From 8ea8fb5c9cfcf82f5f1fcdabbf8751add12a9fa8 Mon Sep 17 00:00:00 2001 From: "adheli.tavares" Date: Tue, 10 Sep 2024 09:17:27 +0100 Subject: Increase code coverage in policy-management Issue-ID: POLICY-5068 Change-Id: Ie7ac44a948fe559306b1aa3a403d888c352be7f2 Signed-off-by: adheli.tavares --- .../controller/IndexedDroolsControllerFactory.java | 27 +- .../controller/internal/MavenDroolsController.java | 5 +- .../features/PolicyControllerFeatureApi.java | 3 +- .../drools/persistence/FileSystemPersistence.java | 3 +- .../drools/protocol/coders/EventProtocolCoder.java | 13 +- .../protocol/coders/GenericEventProtocolCoder.java | 322 ++++------ .../protocol/coders/GsonProtocolCoderToolset.java | 37 +- .../coders/MultiplexorEventProtocolCoder.java | 47 +- .../protocol/coders/ProtocolCoderToolset.java | 10 +- .../coders/TopicCoderFilterConfiguration.java | 34 +- .../IndexedDroolsControllerFactoryTest.java | 154 +++++ .../MavenDroolsControllerUpgradesTest.java | 56 +- .../features/DroolsControllerFeatureApiTest.java | 83 +++ .../features/PolicyControllerFeatureApiTest.java | 171 ++++++ .../features/PolicyEngineFeatureApiTest.java | 174 ++++++ .../persistence/FileSystemPersistenceTest.java | 78 +++ .../protocol/coders/EventProtocolCoderTest.java | 27 + .../protocol/coders/GenericProtocolCoderTest.java | 651 +++++++++++++++++++++ .../coders/GsonProtocolCoderToolsetTest.java | 197 +++++++ .../coders/MultiplexorEventProtocolCoderTest.java | 308 ++++++++++ .../protocol/coders/ProtocolCoderToolsetTest.java | 95 ++- .../coders/TopicCoderFilterConfigurationTest.java | 75 +++ .../server/restful/test/RestManagerTest.java | 252 ++++---- .../drools/stats/PolicyStatsManagerTest.java | 14 + .../onap/policy/drools/stats/PolicyStatsTest.java | 9 + .../drools/system/PolicyControllerFactoryTest.java | 7 +- .../drools/system/PolicyEngineManagerTest.java | 25 +- .../system/internal/FeatureLockImplTest.java | 16 - 28 files changed, 2392 insertions(+), 501 deletions(-) create mode 100644 policy-management/src/test/java/org/onap/policy/drools/controller/IndexedDroolsControllerFactoryTest.java create mode 100644 policy-management/src/test/java/org/onap/policy/drools/features/DroolsControllerFeatureApiTest.java create mode 100644 policy-management/src/test/java/org/onap/policy/drools/features/PolicyControllerFeatureApiTest.java create mode 100644 policy-management/src/test/java/org/onap/policy/drools/features/PolicyEngineFeatureApiTest.java create mode 100644 policy-management/src/test/java/org/onap/policy/drools/persistence/FileSystemPersistenceTest.java create mode 100644 policy-management/src/test/java/org/onap/policy/drools/protocol/coders/GenericProtocolCoderTest.java create mode 100644 policy-management/src/test/java/org/onap/policy/drools/protocol/coders/GsonProtocolCoderToolsetTest.java create mode 100644 policy-management/src/test/java/org/onap/policy/drools/protocol/coders/MultiplexorEventProtocolCoderTest.java create mode 100644 policy-management/src/test/java/org/onap/policy/drools/protocol/coders/TopicCoderFilterConfigurationTest.java (limited to 'policy-management/src') diff --git a/policy-management/src/main/java/org/onap/policy/drools/controller/IndexedDroolsControllerFactory.java b/policy-management/src/main/java/org/onap/policy/drools/controller/IndexedDroolsControllerFactory.java index 7f28f9bb..a6459d67 100644 --- a/policy-management/src/main/java/org/onap/policy/drools/controller/IndexedDroolsControllerFactory.java +++ b/policy-management/src/main/java/org/onap/policy/drools/controller/IndexedDroolsControllerFactory.java @@ -28,6 +28,7 @@ import java.util.List; import java.util.Map; import java.util.Properties; import lombok.NonNull; +import org.apache.commons.lang3.StringUtils; import org.onap.policy.common.endpoints.event.comm.Topic; import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure; import org.onap.policy.common.endpoints.event.comm.TopicSink; @@ -62,7 +63,7 @@ class IndexedDroolsControllerFactory implements DroolsControllerFactory { /** * Null Drools Controller. */ - protected NullDroolsController nullDroolsController = new NullDroolsController(); + protected NullDroolsController nullDroolsController; /** * Constructs the object. @@ -71,11 +72,11 @@ class IndexedDroolsControllerFactory implements DroolsControllerFactory { /* Add a NULL controller which will always be present in the hash */ - DroolsController controller = new NullDroolsController(); - String controllerId = controller.getGroupId() + ":" + controller.getArtifactId(); + nullDroolsController = new NullDroolsController(); + String controllerId = nullDroolsController.getGroupId() + ":" + nullDroolsController.getArtifactId(); synchronized (this) { - droolsControllers.put(controllerId, controller); + droolsControllers.put(controllerId, nullDroolsController); } } @@ -84,17 +85,17 @@ class IndexedDroolsControllerFactory implements DroolsControllerFactory { List eventSinks) throws LinkageError { String groupId = properties.getProperty(DroolsPropertyConstants.RULES_GROUPID); - if (groupId == null || groupId.isEmpty()) { + if (StringUtils.isBlank(groupId)) { groupId = DroolsControllerConstants.NO_GROUP_ID; } String artifactId = properties.getProperty(DroolsPropertyConstants.RULES_ARTIFACTID); - if (artifactId == null || artifactId.isEmpty()) { + if (StringUtils.isBlank(artifactId)) { artifactId = DroolsControllerConstants.NO_ARTIFACT_ID; } String version = properties.getProperty(DroolsPropertyConstants.RULES_VERSION); - if (version == null || version.isEmpty()) { + if (StringUtils.isBlank(version)) { version = DroolsControllerConstants.NO_VERSION; } @@ -110,15 +111,15 @@ class IndexedDroolsControllerFactory implements DroolsControllerFactory { List decoderConfigurations, List encoderConfigurations) throws LinkageError { - if (newGroupId == null || newGroupId.isEmpty()) { + if (StringUtils.isBlank(newGroupId)) { throw new IllegalArgumentException("Missing maven group-id coordinate"); } - if (newArtifactId == null || newArtifactId.isEmpty()) { + if (StringUtils.isBlank(newArtifactId)) { throw new IllegalArgumentException("Missing maven artifact-id coordinate"); } - if (newVersion == null || newVersion.isEmpty()) { + if (StringUtils.isBlank(newVersion)) { throw new IllegalArgumentException("Missing maven version coordinate"); } @@ -240,7 +241,7 @@ class IndexedDroolsControllerFactory implements DroolsControllerFactory { String eventClasses = properties .getProperty(propertyTopicEntityPrefix + PolicyEndPointProperties.PROPERTY_TOPIC_EVENTS_SUFFIX); - if (eventClasses == null || eventClasses.isEmpty()) { + if (StringUtils.isBlank(eventClasses)) { logger.warn("There are no event classes for topic {}", firstTopic); continue; } @@ -280,7 +281,7 @@ class IndexedDroolsControllerFactory implements DroolsControllerFactory { + PolicyEndPointProperties.PROPERTY_TOPIC_EVENTS_CUSTOM_MODEL_CODER_GSON_SUFFIX); CustomGsonCoder customGsonCoder = null; - if (customGson != null && !customGson.isEmpty()) { + if (StringUtils.isNotBlank(customGson)) { try { customGsonCoder = new CustomGsonCoder(customGson); } catch (IllegalArgumentException e) { @@ -375,7 +376,7 @@ class IndexedDroolsControllerFactory implements DroolsControllerFactory { @Override public DroolsController get(String groupId, String artifactId, String version) { - if (groupId == null || artifactId == null || groupId.isEmpty() || artifactId.isEmpty()) { + if (StringUtils.isBlank(groupId) || StringUtils.isBlank(artifactId)) { throw new IllegalArgumentException("Missing maven coordinates: " + groupId + ":" + artifactId); } diff --git a/policy-management/src/main/java/org/onap/policy/drools/controller/internal/MavenDroolsController.java b/policy-management/src/main/java/org/onap/policy/drools/controller/internal/MavenDroolsController.java index 68a69159..aa701dfd 100644 --- a/policy-management/src/main/java/org/onap/policy/drools/controller/internal/MavenDroolsController.java +++ b/policy-management/src/main/java/org/onap/policy/drools/controller/internal/MavenDroolsController.java @@ -3,7 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2017-2021 AT&T Intellectual Property. All rights reserved. - * Modifications Copyright (C) 2023 Nordix Foundation. + * Modifications Copyright (C) 2023-2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,6 +31,7 @@ import java.util.stream.Collectors; import lombok.Getter; import lombok.NonNull; import org.apache.commons.collections4.queue.CircularFifoQueue; +import org.apache.commons.lang3.StringUtils; import org.drools.core.ClassObjectFilter; import org.kie.api.definition.KiePackage; import org.kie.api.definition.rule.Query; @@ -219,7 +220,7 @@ public class MavenDroolsController implements DroolsController { } private void validateText(String text, String errorMessage) { - if (text == null || text.isEmpty()) { + if (StringUtils.isBlank(text)) { throw new IllegalArgumentException(errorMessage); } } diff --git a/policy-management/src/main/java/org/onap/policy/drools/features/PolicyControllerFeatureApi.java b/policy-management/src/main/java/org/onap/policy/drools/features/PolicyControllerFeatureApi.java index f022bf1d..15b48a5c 100644 --- a/policy-management/src/main/java/org/onap/policy/drools/features/PolicyControllerFeatureApi.java +++ b/policy-management/src/main/java/org/onap/policy/drools/features/PolicyControllerFeatureApi.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2017-2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,7 +33,7 @@ public interface PolicyControllerFeatureApi extends OrderedService { * called before creating a controller with name 'name' and * properties 'properties'. * - * @param name name of the the controller + * @param name name of the controller * @param properties configuration properties * * @return a policy controller. A take over of the creation operation diff --git a/policy-management/src/main/java/org/onap/policy/drools/persistence/FileSystemPersistence.java b/policy-management/src/main/java/org/onap/policy/drools/persistence/FileSystemPersistence.java index 9fb76d87..717a6f58 100644 --- a/policy-management/src/main/java/org/onap/policy/drools/persistence/FileSystemPersistence.java +++ b/policy-management/src/main/java/org/onap/policy/drools/persistence/FileSystemPersistence.java @@ -35,6 +35,7 @@ import java.util.List; import java.util.Properties; import java.util.function.BiPredicate; import lombok.Getter; +import lombok.NonNull; import lombok.ToString; import org.onap.policy.drools.properties.DroolsPropertyConstants; import org.onap.policy.drools.utils.PropertyUtil; @@ -151,7 +152,7 @@ public class FileSystemPersistence implements SystemPersistence { } } - protected Properties getProperties(Path propertiesPath) { + protected Properties getProperties(@NonNull Path propertiesPath) { if (!Files.exists(propertiesPath)) { throw new IllegalArgumentException("properties for " + propertiesPath + " are not persisted."); } diff --git a/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/EventProtocolCoder.java b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/EventProtocolCoder.java index 88b25255..7cfa5a3a 100644 --- a/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/EventProtocolCoder.java +++ b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/EventProtocolCoder.java @@ -4,6 +4,7 @@ * ================================================================================ * Copyright (C) 2017-2019,2022 AT&T Intellectual Property. All rights reserved. * Modifications Copyright(C) 2018 Samsung Electronics Co., Ltd. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,7 +36,7 @@ public interface EventProtocolCoder { @Getter @Setter @AllArgsConstructor - public static class CoderFilters { + class CoderFilters { /** * coder class. @@ -54,13 +55,9 @@ public interface EventProtocolCoder { @Override public String toString() { - return "CoderFilters [factClass=" - + factClass - + ", filter=" - + filter - + ", modelClassLoaderHash=" - + modelClassLoaderHash - + "]"; + return "CoderFilters [factClass=" + factClass + + ", filter=" + filter + + ", modelClassLoaderHash=" + modelClassLoaderHash + "]"; } } diff --git a/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/GenericEventProtocolCoder.java b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/GenericEventProtocolCoder.java index 0729c706..6fe1648a 100644 --- a/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/GenericEventProtocolCoder.java +++ b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/GenericEventProtocolCoder.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2019-2020, 2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,15 +22,19 @@ package org.onap.policy.drools.protocol.coders; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Objects; import lombok.AccessLevel; import lombok.NoArgsConstructor; +import org.apache.commons.lang3.StringUtils; import org.onap.policy.drools.controller.DroolsController; import org.onap.policy.drools.controller.DroolsControllerConstants; import org.onap.policy.drools.protocol.coders.EventProtocolCoder.CoderFilters; +import org.onap.policy.drools.system.PolicyDroolsPdpRuntimeException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -43,7 +48,7 @@ abstract class GenericEventProtocolCoder { private static final String INVALID_GROUP_ID_MSG = "Invalid group id"; private static final String INVALID_TOPIC_MSG = "Invalid Topic"; private static final String UNSUPPORTED_MSG = "Unsupported"; - private static final String UNSUPPORTED_EX_MSG = "Unsupported:"; + private static final String UNSUPPORTED_EX_MSG = "Unsupported: "; private static final String MISSING_CLASS = "class must be provided"; private static final Logger logger = LoggerFactory.getLogger(GenericEventProtocolCoder.class); @@ -52,37 +57,26 @@ abstract class GenericEventProtocolCoder { * Mapping topic:controller-id -> / where protocol-coder-toolset contains * a gson-protocol-coder-toolset. */ - protected final HashMap coders = - new HashMap<>(); + protected final HashMap coders = new HashMap<>(); /** * Mapping topic + classname -> Protocol Set. */ - protected final HashMap> - reverseCoders = new HashMap<>(); + protected final HashMap> reverseCoders = new HashMap<>(); /** * Index a new coder. */ public void add(EventProtocolParams eventProtocolParams) { - if (eventProtocolParams.getGroupId() == null || eventProtocolParams.getGroupId().isEmpty()) { - throw new IllegalArgumentException(INVALID_GROUP_ID_MSG); - } - if (eventProtocolParams.getArtifactId() == null || eventProtocolParams.getArtifactId().isEmpty()) { - throw new IllegalArgumentException(INVALID_ARTIFACT_ID_MSG); - } + validateKeyParameters(eventProtocolParams.getGroupId(), + eventProtocolParams.getArtifactId(), + eventProtocolParams.getTopic()); - if (eventProtocolParams.getTopic() == null || eventProtocolParams.getTopic().isEmpty()) { - throw new IllegalArgumentException(INVALID_TOPIC_MSG); - } - - if (eventProtocolParams.getEventClass() == null) { - throw new IllegalArgumentException("Invalid Event Class"); - } + validateStringParameter(eventProtocolParams.getEventClass(), "Invalid Event Class"); String key = this.codersKey(eventProtocolParams.getGroupId(), eventProtocolParams.getArtifactId(), - eventProtocolParams.getTopic()); + eventProtocolParams.getTopic()); String reverseKey = this.reverseCodersKey(eventProtocolParams.getTopic(), eventProtocolParams.getEventClass()); synchronized (this) { @@ -91,22 +85,16 @@ abstract class GenericEventProtocolCoder { logger.info("{}: adding coders for existing {}: {}", this, key, toolset); - toolset - .addCoder( - eventProtocolParams.getEventClass(), - eventProtocolParams.getProtocolFilter(), - eventProtocolParams.getModelClassLoaderHash()); + toolset.addCoder( + eventProtocolParams.getEventClass(), + eventProtocolParams.getProtocolFilter(), + eventProtocolParams.getModelClassLoaderHash()); if (!reverseCoders.containsKey(reverseKey)) { - logger.info( - "{}: adding new reverse coders (multiple classes case) for {}:{}: {}", - this, - reverseKey, - key, - toolset); - - List reverseMappings = - new ArrayList<>(); + logger.info("{}: adding new reverse coders (multiple classes case) for {}:{}: {}", + this, reverseKey, key, toolset); + + List reverseMappings = new ArrayList<>(); reverseMappings.add(toolset); reverseCoders.put(reverseKey, reverseMappings); } @@ -128,20 +116,15 @@ abstract class GenericEventProtocolCoder { // There is another controller (different group id/artifact id/topic) // that shares the class and the topic. - List toolsets = - reverseCoders.get(reverseKey); + List toolsets = reverseCoders.get(reverseKey); var present = false; for (ProtocolCoderToolset parserSet : toolsets) { - // just doublecheck + // just double check present = parserSet.getControllerId().equals(key); if (present) { /* anomaly */ - logger.error( - "{}: unexpected toolset reverse mapping found for {}:{}: {}", - this, - reverseKey, - key, - parserSet); + logger.error("{}: unexpected toolset reverse mapping found for {}:{}: {}", + this, reverseKey, key, parserSet); } } @@ -191,17 +174,7 @@ abstract class GenericEventProtocolCoder { */ public void remove(String groupId, String artifactId, String topic) { - if (groupId == null || groupId.isEmpty()) { - throw new IllegalArgumentException(INVALID_GROUP_ID_MSG); - } - - if (artifactId == null || artifactId.isEmpty()) { - throw new IllegalArgumentException(INVALID_ARTIFACT_ID_MSG); - } - - if (topic == null || topic.isEmpty()) { - throw new IllegalArgumentException(INVALID_TOPIC_MSG); - } + validateKeyParameters(groupId, artifactId, topic); String key = this.codersKey(groupId, artifactId, topic); @@ -225,23 +198,23 @@ abstract class GenericEventProtocolCoder { return; } - List toolsets = - this.reverseCoders.get(reverseKey); - Iterator toolsetsIter = - toolsets.iterator(); + List toolsets = this.reverseCoders.getOrDefault(reverseKey, Collections.emptyList()); + + if (toolsets.isEmpty()) { + logger.info("{}: removing reverse mapping for {}: ", this, reverseKey); + this.reverseCoders.remove(reverseKey); + return; + } + + Iterator toolsetsIter = toolsets.iterator(); + while (toolsetsIter.hasNext()) { ProtocolCoderToolset toolset = toolsetsIter.next(); if (toolset.getControllerId().equals(key)) { - logger.info( - "{}: removed coder from toolset for {} from reverse mapping", this, reverseKey); + logger.info("{}: removed coder from toolset for {} from reverse mapping", this, reverseKey); toolsetsIter.remove(); } } - - if (this.reverseCoders.get(reverseKey).isEmpty()) { - logger.info("{}: removing reverse mapping for {}: ", this, reverseKey); - this.reverseCoders.remove(reverseKey); - } } /** @@ -250,23 +223,14 @@ abstract class GenericEventProtocolCoder { * @param groupId group id * @param artifactId artifact id * @param topic topic - * @return true if its is codable + * @return true if it's supported to be coded */ public boolean isCodingSupported(String groupId, String artifactId, String topic) { - if (groupId == null || groupId.isEmpty()) { - throw new IllegalArgumentException(INVALID_GROUP_ID_MSG); - } - - if (artifactId == null || artifactId.isEmpty()) { - throw new IllegalArgumentException(INVALID_ARTIFACT_ID_MSG); - } - - if (topic == null || topic.isEmpty()) { - throw new IllegalArgumentException(INVALID_TOPIC_MSG); - } + validateKeyParameters(groupId, artifactId, topic); String key = this.codersKey(groupId, artifactId, topic); + synchronized (this) { return coders.containsKey(key); } @@ -280,14 +244,14 @@ abstract class GenericEventProtocolCoder { * @param topic topic * @param json json string to convert to object * @return the decoded object - * @throws IllegalArgumentException if invalid argument is provided - * @throws UnsupportedOperationException if the operation cannot be performed + * @throws IllegalArgumentException if invalid argument is provided + * @throws PolicyDroolsPdpRuntimeException if the operation cannot be performed */ public Object decode(String groupId, String artifactId, String topic, String json) { if (!isCodingSupported(groupId, artifactId, topic)) { throw new IllegalArgumentException( - UNSUPPORTED_EX_MSG + codersKey(groupId, artifactId, topic) + " for encoding"); + UNSUPPORTED_EX_MSG + codersKey(groupId, artifactId, topic) + " for encoding"); } String key = this.codersKey(groupId, artifactId, topic); @@ -321,9 +285,7 @@ abstract class GenericEventProtocolCoder { throw new IllegalArgumentException(UNSUPPORTED_EX_MSG + codersKey(groupId, artifactId, topic)); } - if (event == null) { - throw new IllegalArgumentException("Unsupported topic:" + topic); - } + validateObjectParameter(event, "Event cannot be null or empty"); // reuse the decoder set, since there must be affinity in the model String key = this.codersKey(groupId, artifactId, topic); @@ -341,25 +303,18 @@ abstract class GenericEventProtocolCoder { */ public String encode(String topic, Object event) { - if (event == null) { - throw new IllegalArgumentException("Invalid encoded class"); - } + validateObjectParameter(event, "Event cannot be null or empty"); - if (topic == null || topic.isEmpty()) { - throw new IllegalArgumentException("Invalid topic"); - } + validateStringParameter(topic, INVALID_TOPIC_MSG); String reverseKey = this.reverseCodersKey(topic, event.getClass().getName()); if (!this.reverseCoders.containsKey(reverseKey)) { throw new IllegalArgumentException("no reverse coder has been found"); } - List toolsets = - this.reverseCoders.get(reverseKey); + List toolsets = this.reverseCoders.get(reverseKey); - String key = - codersKey( - toolsets.get(0).getGroupId(), toolsets.get(0).getArtifactId(), topic); + String key = codersKey(toolsets.get(0).getGroupId(), toolsets.get(0).getArtifactId(), topic); return this.encodeInternal(key, event); } @@ -374,13 +329,9 @@ abstract class GenericEventProtocolCoder { */ public String encode(String topic, Object encodedClass, DroolsController droolsController) { - if (encodedClass == null) { - throw new IllegalArgumentException("Invalid encoded class"); - } + validateObjectParameter(encodedClass, "Invalid encoded class"); - if (topic == null || topic.isEmpty()) { - throw new IllegalArgumentException("Invalid topic"); - } + validateStringParameter(topic, INVALID_TOPIC_MSG); String key = codersKey(droolsController.getGroupId(), droolsController.getArtifactId(), topic); return this.encodeInternal(key, encodedClass); @@ -397,31 +348,19 @@ abstract class GenericEventProtocolCoder { */ protected String encodeInternal(String key, Object event) { - logger.debug("{}: encode for {}: {}", this, key, event); // NOSONAR - - /* - * It seems that sonar declares the previous logging line as a security vulnerability - * when logging the topic variable. The static code analysis indicates that - * the path starts in org.onap.policy.drools.server.restful.RestManager::decode(), - * but the request is rejected if the topic contains invalid characters (the sonar description - * mentions "/r/n/t" characters) all of which are validated against in the checkValidNameInput(topic). - * Furthermore production instances are assumed not to have debug enabled, nor the REST telemetry API - * should be published externally. An additional note is that Path URLs containing spaces and newlines - * will be rejected earlier in the HTTP protocol libraries (jetty) so an URL of the form - * "https://../to\npic" won't even make it here. - */ + logger.debug("{}: encode for {}: {}", this, key, event); ProtocolCoderToolset coderTools = coders.get(key); try { String json = coderTools.encode(event); - if (json != null && !json.isEmpty()) { + if (!StringUtils.isBlank(json)) { return json; } } catch (Exception e) { logger.warn("{}: cannot encode (first) for {}: {}", this, key, event, e); } - throw new UnsupportedOperationException("Cannot decode with gson"); + throw new UnsupportedOperationException("Cannot encode with gson"); } /** @@ -443,50 +382,37 @@ abstract class GenericEventProtocolCoder { return droolsControllers; } - List toolsets = - this.reverseCoders.get(reverseKey); + List toolsets = this.reverseCoders.getOrDefault(reverseKey, Collections.emptyList()); // There must be multiple toolsets associated with reverseKey // case 2 different controllers use the same models and register the same encoder for // the same topic. This is assumed not to occur often but for the purpose of encoding - // but there should be no side-effects. Ownership is crosscheck against classname and + // but there should be no side effects. Ownership is crosscheck against classname and // classloader reference. - if (toolsets == null || toolsets.isEmpty()) { - throw new IllegalStateException( - "No Encoders toolsets available for topic " - + topic - + " encoder " - + encodedClass.getClass().getName()); - } - for (ProtocolCoderToolset encoderSet : toolsets) { addToolsetControllers(droolsControllers, encodedClass, encoderSet); } if (droolsControllers.isEmpty()) { - throw new IllegalStateException( - "No Encoders toolsets available for " - + topic - + ":" - + encodedClass.getClass().getName()); + throw new IllegalStateException("No Encoders toolsets available for " + topic + ":" + + encodedClass.getClass().getName()); } return droolsControllers; } private void addToolsetControllers(List droolsControllers, Object encodedClass, - ProtocolCoderToolset encoderSet) { + ProtocolCoderToolset encoderSet) { // figure out the right toolset String groupId = encoderSet.getGroupId(); String artifactId = encoderSet.getArtifactId(); List coderFilters = encoderSet.getCoders(); for (CoderFilters coder : coderFilters) { if (coder.getFactClass().equals(encodedClass.getClass().getName())) { - var droolsController = - DroolsControllerConstants.getFactory().get(groupId, artifactId, ""); + var droolsController = DroolsControllerConstants.getFactory().get(groupId, artifactId, ""); if (droolsController.ownsCoder( - encodedClass.getClass(), coder.getModelClassLoaderHash())) { + encodedClass.getClass(), coder.getModelClassLoaderHash())) { droolsControllers.add(droolsController); } } @@ -523,19 +449,13 @@ abstract class GenericEventProtocolCoder { */ public List getFilters(String groupId, String artifactId) { - if (groupId == null || groupId.isEmpty()) { - throw new IllegalArgumentException(INVALID_GROUP_ID_MSG); - } - - if (artifactId == null || artifactId.isEmpty()) { - throw new IllegalArgumentException(INVALID_ARTIFACT_ID_MSG); - } + validateStringParameter(groupId, INVALID_GROUP_ID_MSG); + validateStringParameter(artifactId, INVALID_ARTIFACT_ID_MSG); String key = this.codersKey(groupId, artifactId, ""); List codersFilters = new ArrayList<>(); - for (Map.Entry entry : - coders.entrySet()) { + for (Map.Entry entry : coders.entrySet()) { if (entry.getKey().startsWith(key)) { codersFilters.addAll(entry.getValue().getCoders()); } @@ -555,15 +475,13 @@ abstract class GenericEventProtocolCoder { * @throws IllegalArgumentException if invalid input */ public CoderFilters getFilters( - String groupId, String artifactId, String topic, String classname) { + String groupId, String artifactId, String topic, String classname) { if (!isCodingSupported(groupId, artifactId, topic)) { throw new IllegalArgumentException(UNSUPPORTED_EX_MSG + codersKey(groupId, artifactId, topic)); } - if (classname == null || classname.isEmpty()) { - throw new IllegalArgumentException("classname must be provided"); - } + validateStringParameter(classname, "classname must be provided"); String key = this.codersKey(groupId, artifactId, topic); ProtocolCoderToolset coderTools = coders.get(key); @@ -580,7 +498,7 @@ abstract class GenericEventProtocolCoder { * @throws IllegalArgumentException if invalid input */ public ProtocolCoderToolset getCoders( - String groupId, String artifactId, String topic) { + String groupId, String artifactId, String topic) { if (!isCodingSupported(groupId, artifactId, topic)) { throw new IllegalArgumentException(UNSUPPORTED_EX_MSG + codersKey(groupId, artifactId, topic)); @@ -598,22 +516,16 @@ abstract class GenericEventProtocolCoder { * @return list of coders * @throws IllegalArgumentException if invalid input */ - public List getCoders( - String groupId, String artifactId) { + public List getCoders(String groupId, String artifactId) { - if (groupId == null || groupId.isEmpty()) { - throw new IllegalArgumentException(INVALID_GROUP_ID_MSG); - } + validateStringParameter(groupId, INVALID_GROUP_ID_MSG); - if (artifactId == null || artifactId.isEmpty()) { - throw new IllegalArgumentException(INVALID_ARTIFACT_ID_MSG); - } + validateStringParameter(artifactId, INVALID_ARTIFACT_ID_MSG); String key = this.codersKey(groupId, artifactId, ""); List coderToolset = new ArrayList<>(); - for (Map.Entry entry : - coders.entrySet()) { + for (Map.Entry entry : coders.entrySet()) { if (entry.getKey().startsWith(key)) { coderToolset.add(entry.getValue()); } @@ -631,19 +543,12 @@ abstract class GenericEventProtocolCoder { */ public List getReverseFilters(String topic, String codedClass) { - if (topic == null || topic.isEmpty()) { - throw new IllegalArgumentException(UNSUPPORTED_MSG); - } + validateStringParameter(topic, INVALID_TOPIC_MSG); - if (codedClass == null) { - throw new IllegalArgumentException(MISSING_CLASS); - } + validateStringParameter(codedClass, MISSING_CLASS); String key = this.reverseCodersKey(topic, codedClass); - List toolsets = this.reverseCoders.get(key); - if (toolsets == null) { - throw new IllegalArgumentException("No Coder found for " + key); - } + List toolsets = this.reverseCoders.getOrDefault(key, Collections.emptyList()); List coderFilters = new ArrayList<>(); for (ProtocolCoderToolset toolset : toolsets) { @@ -656,79 +561,70 @@ abstract class GenericEventProtocolCoder { /** * returns group and artifact id of the creator of the encoder. * - * @param topic topic - * @param fact fact + * @param topic topic + * @param encodedClass class encoder * @return the drools controller */ - DroolsController getDroolsController(String topic, Object fact) { - - if (topic == null || topic.isEmpty()) { - throw new IllegalArgumentException(UNSUPPORTED_MSG); - } - - if (fact == null) { - throw new IllegalArgumentException(MISSING_CLASS); - } - - List droolsControllers = droolsCreators(topic, fact); + DroolsController getDroolsController(String topic, Object encodedClass) { + List droolsControllers = getDroolsControllers(topic, encodedClass); if (droolsControllers.isEmpty()) { - throw new IllegalArgumentException("Invalid Topic: " + topic); + throw new IllegalArgumentException(UNSUPPORTED_MSG + " topic " + topic + + " and encodedClass " + encodedClass.getClass()); } - if (droolsControllers.size() > 1) { - logger.warn( - "{}: multiple drools-controller {} for {}:{} ", - this, - droolsControllers, - topic, - fact.getClass().getName()); - // continue - } return droolsControllers.get(0); } /** * returns group and artifact id of the creator of the encoder. * - * @param topic topic - * @param fact fact + * @param topic topic + * @param encodedClass class encoder * @return list of drools controllers */ - List getDroolsControllers(String topic, Object fact) { + List getDroolsControllers(String topic, Object encodedClass) { - if (topic == null || topic.isEmpty()) { - throw new IllegalArgumentException(UNSUPPORTED_MSG); - } + validateStringParameter(topic, INVALID_TOPIC_MSG); - if (fact == null) { - throw new IllegalArgumentException(MISSING_CLASS); - } + validateObjectParameter(encodedClass, MISSING_CLASS); - List droolsControllers = droolsCreators(topic, fact); + List droolsControllers = droolsCreators(topic, encodedClass); if (droolsControllers.size() > 1) { // unexpected - logger.warn( - "{}: multiple drools-controller {} for {}:{} ", - this, - droolsControllers, - topic, - fact.getClass().getName()); + logger.warn("{}: multiple drools-controller {} for {}:{} ", + this, droolsControllers, topic, encodedClass.getClass().getName()); // continue } return droolsControllers; } + private void validateKeyParameters(String groupId, String artifactId, String topic) { + validateStringParameter(groupId, INVALID_GROUP_ID_MSG); + validateStringParameter(artifactId, INVALID_ARTIFACT_ID_MSG); + validateStringParameter(topic, INVALID_TOPIC_MSG); + } + + private static void validateStringParameter(String value, String errorMessage) { + if (StringUtils.isBlank(value)) { + throw new IllegalArgumentException(errorMessage); + } + } + + private static void validateObjectParameter(Object object, String errorMessage) { + if (Objects.isNull(object)) { + throw new IllegalArgumentException(errorMessage); + } + } + /* - * Note: this only logs the KEYSETS, thus lombok ToString annotation is not used. + * Note: this only logs the KEY SETS, thus lombok ToString annotation is not used. * Otherwise, it results in too much verbosity. */ @Override public String toString() { - return "GenericEventProtocolCoder [coders=" - + coders.keySet() - + ", reverseCoders=" - + reverseCoders.keySet() - + "]"; + return "GenericEventProtocolCoder " + + "[coders=" + coders.keySet() + ", " + + "reverseCoders=" + reverseCoders.keySet() + "]"; } } diff --git a/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/GsonProtocolCoderToolset.java b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/GsonProtocolCoderToolset.java index 80844612..18fcb1a3 100644 --- a/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/GsonProtocolCoderToolset.java +++ b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/GsonProtocolCoderToolset.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2019-2022 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -62,7 +63,7 @@ class GsonProtocolCoderToolset extends ProtocolCoderToolset { public static class GsonUtcAdapter implements JsonSerializer, JsonDeserializer { @Override public ZonedDateTime deserialize(JsonElement element, Type type, - JsonDeserializationContext context) { + JsonDeserializationContext context) { try { return ZonedDateTime.parse(element.getAsString(), format); } catch (final Exception e) { @@ -73,7 +74,7 @@ class GsonProtocolCoderToolset extends ProtocolCoderToolset { @Override public JsonElement serialize(ZonedDateTime datetime, Type type, - JsonSerializationContext context) { + JsonSerializationContext context) { return new JsonPrimitive(datetime.format(format)); } } @@ -112,7 +113,7 @@ class GsonProtocolCoderToolset extends ProtocolCoderToolset { * Toolset to encode/decode tools associated with a topic. * * @param eventProtocolParams parameter object for event encoder - * @param controllerId controller id + * @param controllerId controller id */ public GsonProtocolCoderToolset(EventProtocolParams eventProtocolParams, String controllerId) { super(eventProtocolParams, controllerId); @@ -145,7 +146,7 @@ class GsonProtocolCoderToolset extends ProtocolCoderToolset { public Object decode(String json) { final var droolsController = - DroolsControllerConstants.getFactory().get(this.groupId, this.artifactId, ""); + DroolsControllerConstants.getFactory().get(this.groupId, this.artifactId, ""); if (droolsController == null) { logger.warn("{}: no drools-controller to process {}", this, json); throw new IllegalStateException("no drools-controller to process event"); @@ -163,35 +164,36 @@ class GsonProtocolCoderToolset extends ProtocolCoderToolset { if (decoderClass == null) { logger.warn(CANNOT_FETCH_CLASS, this, decoderFilter.getFactClass()); throw new IllegalStateException( - FETCH_CLASS_EX_MSG + decoderFilter.getFactClass()); + FETCH_CLASS_EX_MSG + decoderFilter.getFactClass()); } } catch (final Exception e) { logger.warn(CANNOT_FETCH_CLASS, this, decoderFilter.getFactClass()); throw new UnsupportedOperationException( - FETCH_CLASS_EX_MSG + decoderFilter.getFactClass(), e); + FETCH_CLASS_EX_MSG + decoderFilter.getFactClass(), e); } if (this.customCoder != null) { try { final var gsonClassContainer = - droolsController.fetchModelClass(this.customCoder.getClassContainer()); + droolsController.fetchModelClass(this.customCoder.getClassContainer()); final var gsonField = gsonClassContainer.getField(this.customCoder.staticCoderField); final var gsonObject = gsonField.get(null); final var fromJsonMethod = gsonObject.getClass().getDeclaredMethod("fromJson", - String.class, Class.class); + String.class, Class.class); return fromJsonMethod.invoke(gsonObject, json, decoderClass); } catch (final Exception e) { logger.warn(CANNOT_FETCH_CLASS, this, decoderFilter.getFactClass()); - throw new UnsupportedOperationException( - FETCH_CLASS_EX_MSG + decoderFilter.getFactClass(), e); + throw new UnsupportedOperationException("cannot decode with customCoder: " + + customCoder.getClassContainer() + + " using application class " + decoderFilter.getFactClass(), e); } } else { try { - return this.decoder.fromJson(json, decoderClass); + return this.getDecoder().fromJson(json, decoderClass); } catch (final Exception e) { logger.warn("{} cannot decode {} into {}", this, json, decoderClass.getName()); throw new UnsupportedOperationException( - "cannot decode into " + decoderFilter.getFactClass(), e); + "cannot decode into " + decoderFilter.getFactClass(), e); } } } @@ -205,21 +207,20 @@ class GsonProtocolCoderToolset extends ProtocolCoderToolset { if (this.customCoder != null) { try { final var droolsController = - DroolsControllerConstants.getFactory().get(this.groupId, this.artifactId, null); + DroolsControllerConstants.getFactory().get(this.groupId, this.artifactId, null); final Class gsonClassContainer = - droolsController.fetchModelClass(this.customCoder.getClassContainer()); + droolsController.fetchModelClass(this.customCoder.getClassContainer()); final var gsonField = gsonClassContainer.getField(this.customCoder.staticCoderField); final var gsonObject = gsonField.get(null); - final var toJsonMethod = - gsonObject.getClass().getDeclaredMethod("toJson", Object.class); + final var toJsonMethod = gsonObject.getClass().getDeclaredMethod("toJson", Object.class); return (String) toJsonMethod.invoke(gsonObject, event); } catch (final Exception e) { logger.warn("{} cannot custom-encode {}", this, event); - throw new UnsupportedOperationException("event cannot be encoded", e); + throw new UnsupportedOperationException("event cannot be custom encoded", e); } } else { try { - return this.encoder.toJson(event); + return this.getEncoder().toJson(event); } catch (final Exception e) { logger.warn("{} cannot encode {}", this, event); throw new UnsupportedOperationException("event cannot be encoded", e); diff --git a/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/MultiplexorEventProtocolCoder.java b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/MultiplexorEventProtocolCoder.java index 3fea6821..cfbf2e4f 100644 --- a/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/MultiplexorEventProtocolCoder.java +++ b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/MultiplexorEventProtocolCoder.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,7 +21,6 @@ package org.onap.policy.drools.protocol.coders; -import java.util.ArrayList; import java.util.List; import lombok.ToString; import org.onap.policy.drools.controller.DroolsController; @@ -126,19 +126,7 @@ class MultiplexorEventProtocolCoder implements EventProtocolCoder { */ @Override public Object decode(String groupId, String artifactId, String topic, String json) { - logger.debug("{}: decode {}:{}:{}:{}", this, groupId, artifactId, topic, json); // NOSONAR - - /* - * It seems that sonar declares the previous logging line as a security vulnerability - * when logging the topic variable. The static code analysis indicates that - * the path starts in org.onap.policy.drools.server.restful.RestManager::decode(), - * but the request is rejected if the topic contains invalid characters (the sonar description - * mentions "/r/n/t" characters) which are validated against in the checkValidNameInput(topic). - * Furthermore production instances are assumed not to have debug enabled, nor the REST telemetry API - * should be published externally. An additional note is that Path URLs containing spaces and newlines - * will be failed earlier at the HTTP protocol libraries (jetty, etc ..) so an URL of the form - * "https://../to\npic" won't even make it here. - */ + logger.debug("{}: decode {}:{}:{}:{}", this, groupId, artifactId, topic, json); return this.decoders.decode(groupId, artifactId, topic, json); } @@ -156,13 +144,7 @@ class MultiplexorEventProtocolCoder implements EventProtocolCoder { */ @Override public String encode(String topic, Object event) { - logger.debug("{}: encode {}:{}", this, topic, event); // NOSONAR - - /* - * See explanation for decode(String groupId, String artifactId, String topic, String json). - * The same applies here as it is called from - * org.onap.policy.drools.server.restful.RestManager::encode(), - */ + logger.debug("{}: encode {}:{}", this, topic, event); return this.encoders.encode(topic, event); } @@ -187,8 +169,7 @@ class MultiplexorEventProtocolCoder implements EventProtocolCoder { * {@inheritDoc}. */ @Override - public CoderFilters getDecoderFilters( - String groupId, String artifactId, String topic, String classname) { + public CoderFilters getDecoderFilters(String groupId, String artifactId, String topic, String classname) { return this.decoders.getFilters(groupId, artifactId, topic, classname); } @@ -205,18 +186,11 @@ class MultiplexorEventProtocolCoder implements EventProtocolCoder { */ @Override public ProtocolCoderToolset getDecoders(String groupId, String artifactId, String topic) { - ProtocolCoderToolset decoderToolsets = - this.decoders.getCoders(groupId, artifactId, topic); - if (decoderToolsets == null) { - throw new IllegalArgumentException( - "Decoders not found for " + groupId + ":" + artifactId + ":" + topic); - } - - return decoderToolsets; + return this.decoders.getCoders(groupId, artifactId, topic); } /** - * get all deocders by maven coordinates and topic. + * get all decoders by maven coordinates and topic. * * @param groupId group id * @param artifactId artifact id @@ -225,14 +199,7 @@ class MultiplexorEventProtocolCoder implements EventProtocolCoder { */ @Override public List getDecoders(String groupId, String artifactId) { - - List decoderToolsets = - this.decoders.getCoders(groupId, artifactId); - if (decoderToolsets == null) { - throw new IllegalArgumentException("Decoders not found for " + groupId + ":" + artifactId); - } - - return new ArrayList<>(decoderToolsets); + return this.decoders.getCoders(groupId, artifactId); } /** diff --git a/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/ProtocolCoderToolset.java b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/ProtocolCoderToolset.java index 277c4ed3..5cd68709 100644 --- a/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/ProtocolCoderToolset.java +++ b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/ProtocolCoderToolset.java @@ -4,6 +4,7 @@ * ================================================================================ * Copyright (C) 2017-2022 AT&T Intellectual Property. All rights reserved. * Modifications Copyright (C) 2018 Samsung Electronics Co., Ltd. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,6 +27,7 @@ import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import lombok.Getter; import lombok.Setter; +import org.apache.commons.lang3.StringUtils; import org.onap.policy.drools.protocol.coders.EventProtocolCoder.CoderFilters; import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomCoder; import org.slf4j.Logger; @@ -82,7 +84,7 @@ public abstract class ProtocolCoderToolset { */ protected ProtocolCoderToolset(EventProtocolParams eventProtocolParams, String controllerId) { - if (eventProtocolParams == null || controllerId == null) { + if (eventProtocolParams == null || StringUtils.isBlank(controllerId)) { throw new IllegalArgumentException("Invalid input"); } @@ -104,7 +106,7 @@ public abstract class ProtocolCoderToolset { * @return the decoder filters or null if not found */ public CoderFilters getCoder(String classname) { - if (classname == null || classname.isEmpty()) { + if (StringUtils.isBlank(classname)) { throw new IllegalArgumentException("no classname provided"); } @@ -132,7 +134,7 @@ public abstract class ProtocolCoderToolset { * @param filter filter */ public void addCoder(String eventClass, JsonProtocolFilter filter, int modelClassLoaderHash) { - if (eventClass == null || eventClass.isEmpty()) { + if (StringUtils.isBlank(eventClass)) { throw new IllegalArgumentException("no event class provided"); } @@ -152,7 +154,7 @@ public abstract class ProtocolCoderToolset { * @param eventClass event class */ public void removeCoders(String eventClass) { - if (eventClass == null || eventClass.isEmpty()) { + if (StringUtils.isBlank(eventClass)) { throw new IllegalArgumentException("no event class provided"); } diff --git a/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/TopicCoderFilterConfiguration.java b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/TopicCoderFilterConfiguration.java index 4dd132b9..69bc0527 100644 --- a/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/TopicCoderFilterConfiguration.java +++ b/policy-management/src/main/java/org/onap/policy/drools/protocol/coders/TopicCoderFilterConfiguration.java @@ -3,6 +3,7 @@ * policy-management * ================================================================================ * Copyright (C) 2017-2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +26,7 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.Setter; import lombok.ToString; +import org.apache.commons.lang3.StringUtils; @Getter @ToString @@ -51,19 +53,21 @@ public class TopicCoderFilterConfiguration { * @param rawCustomCoder with format: <class-containing-custom-coder>,<static-coder-field>. */ protected CustomCoder(String rawCustomCoder) { - if (rawCustomCoder != null && !rawCustomCoder.isEmpty()) { - - this.classContainer = rawCustomCoder.substring(0, rawCustomCoder.indexOf(',')); - if (this.classContainer == null || this.classContainer.isEmpty()) { - throw new IllegalArgumentException( - "No classname to create CustomCoder cannot be created"); - } - - this.staticCoderField = rawCustomCoder.substring(rawCustomCoder.indexOf(',') + 1); - if (this.staticCoderField == null || this.staticCoderField.isEmpty()) { - throw new IllegalArgumentException( - "No staticCoderField to create CustomCoder cannot be created for class " + classContainer); - } + if (StringUtils.isBlank(rawCustomCoder)) { + throw new IllegalArgumentException("Constructor argument cannot be empty. " + + "Use format \"customCoderClass,staticCoderField\""); + } + + this.classContainer = rawCustomCoder.substring(0, rawCustomCoder.indexOf(',')); + if (StringUtils.isBlank(this.classContainer)) { + throw new IllegalArgumentException( + "No classname to create CustomCoder cannot be created"); + } + + this.staticCoderField = rawCustomCoder.substring(rawCustomCoder.indexOf(',') + 1); + if (StringUtils.isBlank(this.staticCoderField)) { + throw new IllegalArgumentException( + "No staticCoderField to create CustomCoder cannot be created for class " + classContainer); } } @@ -74,11 +78,11 @@ public class TopicCoderFilterConfiguration { * @param staticCoderField static coder field */ protected CustomCoder(String className, String staticCoderField) { - if (className == null || className.isEmpty()) { + if (StringUtils.isBlank(className)) { throw new IllegalArgumentException("No classname to create CustomCoder cannot be created"); } - if (staticCoderField == null || staticCoderField.isEmpty()) { + if (StringUtils.isBlank(staticCoderField)) { throw new IllegalArgumentException( "No staticCoderField to create CustomCoder cannot be created for class " + className); } diff --git a/policy-management/src/test/java/org/onap/policy/drools/controller/IndexedDroolsControllerFactoryTest.java b/policy-management/src/test/java/org/onap/policy/drools/controller/IndexedDroolsControllerFactoryTest.java new file mode 100644 index 00000000..39a03db3 --- /dev/null +++ b/policy-management/src/test/java/org/onap/policy/drools/controller/IndexedDroolsControllerFactoryTest.java @@ -0,0 +1,154 @@ +/*- + * ============LICENSE_START=============================================== + * ONAP + * ======================================================================== + * Copyright (C) 2024 Nordix Foundation. + * ======================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END================================================= + */ + +package org.onap.policy.drools.controller; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.doCallRealMethod; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration; +import org.springframework.test.util.ReflectionTestUtils; + +class IndexedDroolsControllerFactoryTest { + + IndexedDroolsControllerFactory factory; + static final String GROUP_ID = "groupId"; + static final String ARTIFACT_ID = "artifactId"; + static final String VERSION = "version"; + static final String OTHER_VERSION = "otherVersion"; + + @BeforeEach + void setUp() { + this.factory = new IndexedDroolsControllerFactory(); + } + + @Test + void build_EmptyArguments() { + var props = new Properties(); + List decoderConfigs = List.of(); + List encoderConfigs = List.of(); + + assertThatThrownBy(() -> factory.build(props, "", ARTIFACT_ID, VERSION, decoderConfigs, encoderConfigs)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Missing maven group-id coordinate"); + + assertThatThrownBy(() -> factory.build(props, GROUP_ID, "", VERSION, decoderConfigs, encoderConfigs)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Missing maven artifact-id coordinate"); + + assertThatThrownBy(() -> factory.build(props, GROUP_ID, ARTIFACT_ID, "", decoderConfigs, encoderConfigs)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Missing maven version coordinate"); + } + + @Test + void testBuild_CheckControllerCopy() { + var props = new Properties(); + List decoderConfigs = List.of(); + List encoderConfigs = List.of(); + + var mockFactory = mock(IndexedDroolsControllerFactory.class); + when(mockFactory.build(props, GROUP_ID, ARTIFACT_ID, VERSION, decoderConfigs, encoderConfigs)) + .thenCallRealMethod(); + + var controller = mock(DroolsController.class); + doNothing().when(controller).updateToVersion(GROUP_ID, ARTIFACT_ID, VERSION, decoderConfigs, encoderConfigs); + when(controller.getVersion()).thenReturn(OTHER_VERSION); + Map controllers = new HashMap<>(); + controllers.put(GROUP_ID + ":" + ARTIFACT_ID, controller); + ReflectionTestUtils.setField(mockFactory, "droolsControllers", controllers); + + assertNotNull(mockFactory.build(props, GROUP_ID, ARTIFACT_ID, VERSION, decoderConfigs, encoderConfigs)); + } + + @Test + void unmanage() { + assertThatThrownBy(() -> factory.unmanage(null)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("No controller provided"); + + var mockController = mock(DroolsController.class); + when(mockController.isBrained()).thenReturn(false) + .thenReturn(true).thenReturn(true); + when(mockController.getGroupId()).thenReturn(GROUP_ID); + when(mockController.getArtifactId()).thenReturn(ARTIFACT_ID); + + var mockFactory = mock(IndexedDroolsControllerFactory.class); + doCallRealMethod().when(mockFactory).unmanage(mockController); + when(mockFactory.toString()).thenCallRealMethod(); + + Map controllers = new HashMap<>(); + controllers.put(GROUP_ID + ":" + ARTIFACT_ID, mockController); + ReflectionTestUtils.setField(mockFactory, "droolsControllers", controllers); + + // should return after isBrained returns false + assertDoesNotThrow(() -> mockFactory.unmanage(mockController)); + assertFalse(mockFactory.droolsControllers.isEmpty()); + assertEquals("IndexedDroolsControllerFactory [#droolsControllers=1]", mockFactory.toString()); + + // should go ahead and remove controller from hash map + assertDoesNotThrow(() -> mockFactory.unmanage(mockController)); + assertTrue(mockFactory.droolsControllers.isEmpty()); + assertEquals("IndexedDroolsControllerFactory [#droolsControllers=0]", mockFactory.toString()); + + controllers.put("anotherKey", mockController); + ReflectionTestUtils.setField(mockFactory, "droolsControllers", controllers); + + // should return after comparing the key in the hash map (does not match) + assertDoesNotThrow(() -> mockFactory.unmanage(mockController)); + assertFalse(mockFactory.droolsControllers.isEmpty()); + assertEquals("IndexedDroolsControllerFactory [#droolsControllers=1]", mockFactory.toString()); + } + + @Test + void shutdown() { + var mockController = mock(DroolsController.class); + doNothing().when(mockController).shutdown(); + + var mockFactory = mock(IndexedDroolsControllerFactory.class); + doNothing().when(mockFactory).unmanage(mockController); + + assertDoesNotThrow(() -> mockFactory.shutdown(mockController)); + } + + @Test + void get_EmptyParameters() { + assertThatThrownBy(() -> factory.get("", ARTIFACT_ID, VERSION)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Missing maven coordinates"); + assertThatThrownBy(() -> factory.get(GROUP_ID, "", VERSION)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Missing maven coordinates"); + } +} \ No newline at end of file diff --git a/policy-management/src/test/java/org/onap/policy/drools/controller/internal/MavenDroolsControllerUpgradesTest.java b/policy-management/src/test/java/org/onap/policy/drools/controller/internal/MavenDroolsControllerUpgradesTest.java index 38b38a8c..753296a8 100644 --- a/policy-management/src/test/java/org/onap/policy/drools/controller/internal/MavenDroolsControllerUpgradesTest.java +++ b/policy-management/src/test/java/org/onap/policy/drools/controller/internal/MavenDroolsControllerUpgradesTest.java @@ -88,7 +88,7 @@ public class MavenDroolsControllerUpgradesTest { KieUtils.installArtifact( Paths.get(DROOLS_RESOURCES_DIR + RULES_BASE + KMODULE_EXT).toFile(), Paths.get(DROOLS_RESOURCES_DIR + name + POM_EXT).toFile(), - DROOLS_KJAR_RESOURCES_DIR + KBNAME_RULES + "/" + KBPACKAGE_RULES + "/", + DROOLS_KJAR_RESOURCES_DIR + KBNAME_RULES + "/" + KBPACKAGE_RULES + "/", drls); } @@ -105,8 +105,8 @@ public class MavenDroolsControllerUpgradesTest { rulesDescriptor2 = install("rules2", Stream.of(path.toFile(), - Paths.get(DROOLS_RESOURCES_DIR + "rules2" + DRL_EXT).toFile()) - .collect(Collectors.toList())); + Paths.get(DROOLS_RESOURCES_DIR + "rules2" + DRL_EXT).toFile()) + .collect(Collectors.toList())); LoggerUtils.setLevel("ROOT", "WARN"); LoggerUtils.setLevel("org.onap.policy.drools.controller.internal", "INFO"); @@ -169,13 +169,13 @@ public class MavenDroolsControllerUpgradesTest { private void summary() { logger.info("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); - logger.info("Controller: " + controller.getGroupId() + ":" + controller.getArtifactId() - + ":" + controller.getVersion()); + logger.info("Controller: {}:{}:{}", controller.getGroupId(), controller.getArtifactId(), + controller.getVersion()); logger.info("....................................................................."); - logger.info("KIE-BASES: " + KieUtils.getBases(controller.getContainer().getKieContainer())); - logger.info("KIE-PACKAGE-NAMES: " + KieUtils.getPackageNames(controller.getContainer().getKieContainer())); - logger.info("KIE-RULE-NAMES: " + KieUtils.getRuleNames(controller.getContainer().getKieContainer())); - logger.info("FACTS: " + controller.facts(KBSESSION_RULES, Object.class)); + logger.info("KIE-BASES: {}", KieUtils.getBases(controller.getContainer().getKieContainer())); + logger.info("KIE-PACKAGE-NAMES: {}", KieUtils.getPackageNames(controller.getContainer().getKieContainer())); + logger.info("KIE-RULE-NAMES: {}", KieUtils.getRuleNames(controller.getContainer().getKieContainer())); + logger.info("FACTS: {}", controller.facts(KBSESSION_RULES, Object.class)); logger.info("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); } @@ -190,25 +190,25 @@ public class MavenDroolsControllerUpgradesTest { controller.getContainer() .getPolicySession(KBSESSION_RULES) .getKieSession() - .addEventListener(new RuleRuntimeEventListener() { - @Override - public void objectInserted(ObjectInsertedEvent objectInsertedEvent) { - logger.info("RULE {}: inserting {}", - objectInsertedEvent.getRule().getName(), objectInsertedEvent.getObject()); - } - - @Override - public void objectUpdated(ObjectUpdatedEvent objectUpdatedEvent) { - logger.info("RULE {}: updating {}", - objectUpdatedEvent.getRule().getName(), objectUpdatedEvent.getObject()); - } - - @Override - public void objectDeleted(ObjectDeletedEvent objectDeletedEvent) { - logger.info("RULE {}: deleting {}", - objectDeletedEvent.getRule().getName(), objectDeletedEvent.getOldObject()); - } - }); + .addEventListener(new RuleRuntimeEventListener() { + @Override + public void objectInserted(ObjectInsertedEvent objectInsertedEvent) { + logger.info("RULE {}: inserting {}", + objectInsertedEvent.getRule().getName(), objectInsertedEvent.getObject()); + } + + @Override + public void objectUpdated(ObjectUpdatedEvent objectUpdatedEvent) { + logger.info("RULE {}: updating {}", + objectUpdatedEvent.getRule().getName(), objectUpdatedEvent.getObject()); + } + + @Override + public void objectDeleted(ObjectDeletedEvent objectDeletedEvent) { + logger.info("RULE {}: deleting {}", + objectDeletedEvent.getRule().getName(), objectDeletedEvent.getOldObject()); + } + }); controller.getContainer() .getPolicySession(KBSESSION_RULES) diff --git a/policy-management/src/test/java/org/onap/policy/drools/features/DroolsControllerFeatureApiTest.java b/policy-management/src/test/java/org/onap/policy/drools/features/DroolsControllerFeatureApiTest.java new file mode 100644 index 00000000..83171dae --- /dev/null +++ b/policy-management/src/test/java/org/onap/policy/drools/features/DroolsControllerFeatureApiTest.java @@ -0,0 +1,83 @@ +/*- + * ============LICENSE_START=============================================== + * ONAP + * ======================================================================== + * Copyright (C) 2024 Nordix Foundation. + * ======================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END================================================= + */ + +package org.onap.policy.drools.features; + + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; + +import java.util.Collections; +import java.util.Properties; +import org.junit.jupiter.api.Test; +import org.onap.policy.common.endpoints.event.comm.TopicSink; +import org.onap.policy.drools.controller.DroolsController; + +/** + * DroolsControllerFeatureApi is implemented in other modules, therefore, coverage is not coming up in this module. + * This class has no intention of unit testing features, sole goal is raise coverage. + */ +class DroolsControllerFeatureApiTest { + + DroolsControllerFeatureApi testClass = new TestDroolsControllerFeatureApi(); + Properties props = new Properties(); + DroolsController controller; + TopicSink sink; + Object fact; + + @Test + void beforeInstance() { + assertNull(testClass.beforeInstance(props, "group", "artifact", "version", + Collections.emptyList(), Collections.emptyList())); + } + + @Test + void afterInstance() { + assertFalse(testClass.afterInstance(controller, props)); + } + + @Test + void beforeInsert() { + assertFalse(testClass.beforeInsert(controller, props)); + } + + @Test + void afterInsert() { + assertFalse(testClass.afterInsert(controller, fact, false)); + } + + @Test + void beforeDeliver() { + assertFalse(testClass.beforeDeliver(controller, sink, fact)); + } + + @Test + void afterDeliver() { + assertFalse(testClass.afterDeliver(controller, sink, fact, "json", false)); + } + + static class TestDroolsControllerFeatureApi implements DroolsControllerFeatureApi { + + @Override + public int getSequenceNumber() { + return 30; + } + } +} \ No newline at end of file diff --git a/policy-management/src/test/java/org/onap/policy/drools/features/PolicyControllerFeatureApiTest.java b/policy-management/src/test/java/org/onap/policy/drools/features/PolicyControllerFeatureApiTest.java new file mode 100644 index 00000000..f48bf937 --- /dev/null +++ b/policy-management/src/test/java/org/onap/policy/drools/features/PolicyControllerFeatureApiTest.java @@ -0,0 +1,171 @@ +/*- + * ============LICENSE_START=============================================== + * ONAP + * ======================================================================== + * Copyright (C) 2024 Nordix Foundation. + * ======================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END================================================= + */ + +package org.onap.policy.drools.features; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure.NOOP; + +import java.util.Properties; +import org.junit.jupiter.api.Test; +import org.onap.policy.drools.protocol.configuration.DroolsConfiguration; +import org.onap.policy.drools.system.PolicyController; + +/** + * PolicyControllerFeatureApi is implemented in other modules, therefore, coverage is not coming up in this module. + * This class has no intention of unit testing features, sole goal is raise coverage. + */ +class PolicyControllerFeatureApiTest { + + PolicyControllerFeatureApi testClass = new TestPolicyControllerFeatureApi(); + Properties props = new Properties(); + PolicyController controller; + DroolsConfiguration configuration; + + + @Test + void beforeCreate() { + assertNull(testClass.beforeCreate("name", props)); + } + + @Test + void afterCreate() { + assertFalse(testClass.afterCreate(controller)); + } + + @Test + void beforeInstance() { + assertNull(testClass.beforeInstance("name", props)); + } + + @Test + void afterInstance() { + assertFalse(testClass.afterInstance(controller, props)); + } + + @Test + void beforeStart() { + assertFalse(testClass.beforeStart(controller)); + } + + @Test + void afterStart() { + assertFalse(testClass.afterStart(controller)); + } + + @Test + void beforeStop() { + assertFalse(testClass.beforeStop(controller)); + } + + @Test + void afterStop() { + assertFalse(testClass.afterStop(controller)); + } + + @Test + void beforePatch() { + assertFalse(testClass.beforePatch(controller, configuration, configuration)); + } + + @Test + void afterPatch() { + assertFalse(testClass.afterPatch(controller, configuration, configuration, true)); + } + + @Test + void beforeLock() { + assertFalse(testClass.beforeLock(controller)); + } + + @Test + void afterLock() { + assertFalse(testClass.afterLock(controller)); + } + + @Test + void beforeUnlock() { + assertFalse(testClass.beforeUnlock(controller)); + } + + @Test + void afterUnlock() { + assertFalse(testClass.afterUnlock(controller)); + } + + @Test + void beforeShutdown() { + assertFalse(testClass.beforeShutdown(controller)); + } + + @Test + void afterShutdown() { + assertFalse(testClass.afterShutdown(controller)); + } + + @Test + void beforeHalt() { + assertFalse(testClass.beforeHalt(controller)); + } + + @Test + void afterHalt() { + assertFalse(testClass.afterHalt(controller)); + } + + @Test + void beforeOffer() { + assertFalse(testClass.beforeOffer(controller, new Object())); + } + + @Test + void testBeforeOffer() { + assertFalse(testClass.beforeOffer(controller, NOOP, "topic", "event")); + } + + @Test + void afterOffer() { + assertFalse(testClass.afterOffer(controller, new Object(), true)); + } + + @Test + void testAfterOffer() { + assertFalse(testClass.afterOffer(controller, NOOP, "topic", "event", true)); + } + + @Test + void beforeDeliver() { + assertFalse(testClass.beforeDeliver(controller, NOOP, "topic", "event")); + } + + @Test + void afterDeliver() { + assertFalse(testClass.afterDeliver(controller, NOOP, "topic", "event", true)); + } + + static class TestPolicyControllerFeatureApi implements PolicyControllerFeatureApi { + + @Override + public int getSequenceNumber() { + return 20; + } + } +} \ No newline at end of file diff --git a/policy-management/src/test/java/org/onap/policy/drools/features/PolicyEngineFeatureApiTest.java b/policy-management/src/test/java/org/onap/policy/drools/features/PolicyEngineFeatureApiTest.java new file mode 100644 index 00000000..90feeb20 --- /dev/null +++ b/policy-management/src/test/java/org/onap/policy/drools/features/PolicyEngineFeatureApiTest.java @@ -0,0 +1,174 @@ +/*- + * ============LICENSE_START=============================================== + * ONAP + * ======================================================================== + * Copyright (C) 2024 Nordix Foundation. + * ======================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END================================================= + */ + +package org.onap.policy.drools.features; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.mockito.Mockito.mock; + +import java.util.Properties; +import org.junit.jupiter.api.Test; +import org.onap.policy.common.endpoints.event.comm.Topic; +import org.onap.policy.drools.core.lock.PolicyResourceLockManager; +import org.onap.policy.drools.protocol.configuration.PdpdConfiguration; +import org.onap.policy.drools.system.PolicyEngine; + +/** + * PolicyEngineFeatureApi is implemented in other modules, therefore, coverage is not coming up in this module. + * This class has no intention of unit testing features, sole goal is raise coverage. + */ +class PolicyEngineFeatureApiTest { + + PolicyEngineFeatureApi testClass = new TestPolicyEngineFeatureApi(); + + PolicyEngine policyEngine = mock(PolicyEngine.class); + Properties props = new Properties(); + + @Test + void beforeBoot() { + assertFalse(testClass.beforeBoot(policyEngine, new String[] {"a", "b"})); + } + + @Test + void afterBoot() { + assertFalse(testClass.afterBoot(policyEngine)); + } + + @Test + void beforeConfigure() { + assertFalse(testClass.beforeConfigure(policyEngine, props)); + } + + @Test + void afterConfigure() { + assertFalse(testClass.afterConfigure(policyEngine)); + } + + @Test + void beforeActivate() { + assertFalse(testClass.beforeActivate(policyEngine)); + } + + @Test + void afterActivate() { + assertFalse(testClass.afterActivate(policyEngine)); + } + + @Test + void beforeDeactivate() { + assertFalse(testClass.beforeDeactivate(policyEngine)); + } + + @Test + void afterDeactivate() { + assertFalse(testClass.afterDeactivate(policyEngine)); + } + + @Test + void beforeStart() { + assertFalse(testClass.beforeStart(policyEngine)); + } + + @Test + void afterStart() { + assertFalse(testClass.afterStart(policyEngine)); + } + + @Test + void beforeStop() { + assertFalse(testClass.beforeStop(policyEngine)); + } + + @Test + void afterStop() { + assertFalse(testClass.afterStop(policyEngine)); + } + + @Test + void beforeLock() { + assertFalse(testClass.beforeLock(policyEngine)); + } + + @Test + void afterLock() { + assertFalse(testClass.afterLock(policyEngine)); + } + + @Test + void beforeUnlock() { + assertFalse(testClass.beforeUnlock(policyEngine)); + } + + @Test + void afterUnlock() { + assertFalse(testClass.afterUnlock(policyEngine)); + } + + @Test + void beforeShutdown() { + assertFalse(testClass.beforeShutdown(policyEngine)); + } + + @Test + void afterShutdown() { + assertFalse(testClass.afterShutdown(policyEngine)); + } + + @Test + void beforeOnTopicEvent() { + assertFalse(testClass.beforeOnTopicEvent(policyEngine, Topic.CommInfrastructure.NOOP, "topic", "event")); + } + + @Test + void afterOnTopicEvent() { + assertFalse(testClass.afterOnTopicEvent(policyEngine, mock(PdpdConfiguration.class), + Topic.CommInfrastructure.NOOP, "topic", "event")); + } + + @Test + void beforeOpen() { + assertFalse(testClass.beforeOpen(policyEngine)); + } + + @Test + void afterOpen() { + assertFalse(testClass.afterOpen(policyEngine)); + } + + @Test + void beforeCreateLockManager() { + assertNull(testClass.beforeCreateLockManager()); + } + + @Test + void afterCreateLockManager() { + assertFalse(testClass.afterCreateLockManager(policyEngine, props, mock(PolicyResourceLockManager.class))); + } + + static class TestPolicyEngineFeatureApi implements PolicyEngineFeatureApi { + + @Override + public int getSequenceNumber() { + return 10; + } + + } +} \ No newline at end of file diff --git a/policy-management/src/test/java/org/onap/policy/drools/persistence/FileSystemPersistenceTest.java b/policy-management/src/test/java/org/onap/policy/drools/persistence/FileSystemPersistenceTest.java new file mode 100644 index 00000000..80a8dc6b --- /dev/null +++ b/policy-management/src/test/java/org/onap/policy/drools/persistence/FileSystemPersistenceTest.java @@ -0,0 +1,78 @@ +/*- + * ============LICENSE_START=============================================== + * ONAP + * ======================================================================== + * Copyright (C) 2024 Nordix Foundation. + * ======================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END================================================= + */ + +package org.onap.policy.drools.persistence; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.nio.file.Path; +import org.junit.jupiter.api.Test; + +class FileSystemPersistenceTest { + + FileSystemPersistence persistence = new FileSystemPersistence(); + + @Test + void testSetConfiguration_FileIsNotDirectory() { + persistence.configurationPath = Path.of("src/test/resources/echo.drl"); + assertThrows(IllegalStateException.class, () -> persistence.setConfigurationDir()); + assertThatThrownBy(() -> persistence.setConfigurationDir()) + .hasMessageContaining("config directory: src/test/resources/echo.drl is not a directory"); + } + + @Test + void testSetConfiguration_InvalidDir() { + persistence.configurationPath = Path.of("/opt/path"); // opt path needs sudo + assertThrows(IllegalStateException.class, () -> persistence.setConfigurationDir()); + assertThatThrownBy(() -> persistence.setConfigurationDir()) + .hasMessageContaining("cannot create /opt/path"); + } + + @Test + void testGetProperties_Exception() { + assertThatThrownBy(() -> persistence.getProperties("")) + .hasMessageContaining("properties name must be provided"); + + String propName = null; + assertThatThrownBy(() -> persistence.getProperties(propName)) // for code coverage + .hasMessageContaining("properties name must be provided"); + } + + @Test + void testGetEnvironmentProperties_Exception() { + assertThatThrownBy(() -> persistence.getEnvironmentProperties("")) + .hasMessageContaining("environment name must be provided"); + + String propName = null; + assertThatThrownBy(() -> persistence.getEnvironmentProperties(propName)) // for code coverage + .hasMessageContaining("environment name must be provided"); + } + + @Test + void testGetProperties_ByPathException() { + assertThatThrownBy(() -> persistence.getProperties(Path.of("/path/does/not/exist.properties"))) + .hasMessageContaining("properties for /path/does/not/exist.properties are not persisted."); + + Path pathProps = null; + assertThatThrownBy(() -> persistence.getProperties(pathProps)) // for code coverage + .hasMessageContaining("propertiesPath is marked non-null but is null"); + } +} diff --git a/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/EventProtocolCoderTest.java b/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/EventProtocolCoderTest.java index 6d461eef..c98467ea 100644 --- a/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/EventProtocolCoderTest.java +++ b/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/EventProtocolCoderTest.java @@ -22,6 +22,7 @@ package org.onap.policy.drools.protocol.coders; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Properties; @@ -88,4 +89,30 @@ class EventProtocolCoderTest { EventProtocolCoderConstants.getManager().removeEncoders(ENCODER_GROUP, ENCODER_ARTIFACT, NOOP_TOPIC); } + + @Test + void test_extra() { + final Properties noopSinkProperties = new Properties(); + noopSinkProperties.put(PolicyEndPointProperties.PROPERTY_NOOP_SINK_TOPICS, NOOP_TOPIC); + + TopicEndpointManager.getManager().addTopicSinks(noopSinkProperties); + + var encoder = EventProtocolParams.builder().groupId(ENCODER_GROUP).artifactId(ENCODER_ARTIFACT) + .topic(NOOP_TOPIC).eventClass(DroolsConfiguration.class.getName()) + .protocolFilter(new JsonProtocolFilter()).customGsonCoder(null) + .modelClassLoaderHash(DroolsConfiguration.class.getName().hashCode()).build(); + + EventProtocolCoderConstants.getManager().addEncoder(encoder); + + final String json = EventProtocolCoderConstants.getManager().encode(NOOP_TOPIC, + new DroolsConfiguration(ENCODER_ARTIFACT, ENCODER_GROUP, ENCODER_VERSION)); + + assertTrue(json.contains(ENCODER_GROUP)); + assertTrue(json.contains(ENCODER_ARTIFACT)); + + // check if adding same encoder doesn't throw any exceptions as expected + assertDoesNotThrow(() -> EventProtocolCoderConstants.getManager().addEncoder(encoder)); + EventProtocolCoderConstants.getManager().removeEncoders(ENCODER_GROUP, ENCODER_ARTIFACT, NOOP_TOPIC); + EventProtocolCoderConstants.getManager().removeEncoders("NotExistentGroup", ENCODER_ARTIFACT, NOOP_TOPIC); + } } diff --git a/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/GenericProtocolCoderTest.java b/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/GenericProtocolCoderTest.java new file mode 100644 index 00000000..7a8be59e --- /dev/null +++ b/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/GenericProtocolCoderTest.java @@ -0,0 +1,651 @@ +/*- + * ============LICENSE_START=============================================== + * ONAP + * ======================================================================== + * Copyright (C) 2024 Nordix Foundation. + * ======================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END================================================= + */ + +package org.onap.policy.drools.protocol.coders; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doCallRealMethod; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.onap.policy.drools.controller.DroolsController; +import org.onap.policy.drools.controller.DroolsControllerConstants; +import org.onap.policy.drools.controller.DroolsControllerFactory; +import org.onap.policy.drools.controller.internal.NullDroolsController; +import org.springframework.test.util.ReflectionTestUtils; + +class GenericProtocolCoderTest { + + EventProtocolEncoder encoder = new EventProtocolEncoder(); + EventProtocolDecoder decoder = new EventProtocolDecoder(); + + private static final String GROUP_ID = "groupId"; + private static final String ARTIFACT_ID = "artifactId"; + private static final String TOPIC = "topic"; + private static final String VALID_KEY = GROUP_ID + ":" + ARTIFACT_ID + ":" + TOPIC; + private static final String INVALID_KEY = "anotherKey"; + + @Test + void testAdd_ReverseCoder() { + var params = new EventProtocolParams(GROUP_ID, ARTIFACT_ID, TOPIC, "java.lang.Object", + mock(JsonProtocolFilter.class), mock(TopicCoderFilterConfiguration.CustomGsonCoder.class), 1); + + var myKey = "group:artifact:topic"; + + var mockEncoder = mock(EventProtocolEncoder.class); + // set the key to be returned when checking the hash maps + when(mockEncoder.codersKey(GROUP_ID, ARTIFACT_ID, TOPIC)).thenReturn(myKey); + when(mockEncoder.reverseCodersKey(GROUP_ID, "java.lang.Object")).thenReturn(myKey); + doCallRealMethod().when(mockEncoder).add(params); + + + // create the hash maps for coders/reverseCoders + var toolset = mock(ProtocolCoderToolset.class); + HashMap coders = new HashMap<>(); + coders.put(myKey, toolset); + ReflectionTestUtils.setField(mockEncoder, "coders", coders); + HashMap> reverseCoders = new HashMap<>(); + reverseCoders.put("group:javaClass", new ArrayList<>(List.of(toolset))); + ReflectionTestUtils.setField(mockEncoder, "reverseCoders", reverseCoders); + + assertDoesNotThrow(() -> mockEncoder.add(params)); + assertEquals(2, mockEncoder.reverseCoders.size()); + assertEquals(1, mockEncoder.coders.size()); + } + + @Test + void testAdd_InvalidParams_GroupId() { + var mockEventProtocolsParams = mock(EventProtocolParams.class); + when(mockEventProtocolsParams.getGroupId()).thenReturn(null); + + assertThatThrownBy(() -> encoder.add(mockEventProtocolsParams)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid group id"); + + when(mockEventProtocolsParams.getGroupId()).thenReturn(""); + + assertThatThrownBy(() -> encoder.add(mockEventProtocolsParams)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid group id"); + } + + @Test + void testAdd_InvalidParams_ArtifactId() { + var mockEventProtocolsParams = mock(EventProtocolParams.class); + when(mockEventProtocolsParams.getGroupId()).thenReturn(GROUP_ID); + when(mockEventProtocolsParams.getArtifactId()).thenReturn(null); + + assertThatThrownBy(() -> encoder.add(mockEventProtocolsParams)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid artifact id"); + + when(mockEventProtocolsParams.getArtifactId()).thenReturn(""); + + assertThatThrownBy(() -> encoder.add(mockEventProtocolsParams)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid artifact id"); + } + + @Test + void testAdd_InvalidParams_Topic() { + var mockEventProtocolsParams = mock(EventProtocolParams.class); + when(mockEventProtocolsParams.getGroupId()).thenReturn(GROUP_ID); + when(mockEventProtocolsParams.getArtifactId()).thenReturn(ARTIFACT_ID); + when(mockEventProtocolsParams.getTopic()).thenReturn(null); + + assertThatThrownBy(() -> encoder.add(mockEventProtocolsParams)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid Topic"); + + when(mockEventProtocolsParams.getGroupId()).thenReturn(GROUP_ID); + when(mockEventProtocolsParams.getArtifactId()).thenReturn(ARTIFACT_ID); + when(mockEventProtocolsParams.getTopic()).thenReturn(""); + + assertThatThrownBy(() -> encoder.add(mockEventProtocolsParams)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid Topic"); + } + + @Test + void testAdd_InvalidParams_EventClass() { + var mockEventProtocolsParams = mock(EventProtocolParams.class); + when(mockEventProtocolsParams.getGroupId()).thenReturn(GROUP_ID); + when(mockEventProtocolsParams.getArtifactId()).thenReturn(ARTIFACT_ID); + when(mockEventProtocolsParams.getTopic()).thenReturn(TOPIC); + when(mockEventProtocolsParams.getEventClass()).thenReturn(null); + + assertThatThrownBy(() -> encoder.add(mockEventProtocolsParams)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid Event Class"); + } + + @Test + void testDecode_Exceptions() { + var mockDecoder = mock(EventProtocolDecoder.class); + when(mockDecoder.isCodingSupported(GROUP_ID, ARTIFACT_ID, TOPIC)) + .thenReturn(false); + when(mockDecoder.decode(GROUP_ID, ARTIFACT_ID, TOPIC, null)) + .thenCallRealMethod(); + when(mockDecoder.codersKey(GROUP_ID, ARTIFACT_ID, TOPIC)) + .thenCallRealMethod(); + + assertThatThrownBy(() -> mockDecoder.decode(GROUP_ID, ARTIFACT_ID, TOPIC, null)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Unsupported: groupId:artifactId:topic for encoding"); + } + + @Test + void testDecode_ExceptionCantDecode() { + var mockDecoder = mock(EventProtocolDecoder.class); + + HashMap coders = new HashMap<>(); + var params = mock(EventProtocolParams.class); + coders.put("groupId:artifactId:topic", new GsonProtocolCoderToolset(params, "controllerId")); + ReflectionTestUtils.setField(mockDecoder, "coders", coders); + + when(mockDecoder.isCodingSupported(GROUP_ID, ARTIFACT_ID, TOPIC)) + .thenReturn(true); + when(mockDecoder.decode(GROUP_ID, ARTIFACT_ID, TOPIC, null)) + .thenCallRealMethod(); + when(mockDecoder.codersKey(GROUP_ID, ARTIFACT_ID, TOPIC)) + .thenCallRealMethod(); + + assertThatThrownBy(() -> mockDecoder.decode(GROUP_ID, ARTIFACT_ID, TOPIC, null)) + .isInstanceOf(UnsupportedOperationException.class) + .hasMessageContaining("Cannot decode with gson"); + } + + @Test + void testDecode_Decode() { + var mockDecoder = mock(EventProtocolDecoder.class); + var myKey = "groupId:artifactId:topic"; + var json = "{\"json\":\"true\"}"; + + HashMap coders = new HashMap<>(); + var mockToolset = mock(ProtocolCoderToolset.class); + when(mockToolset.decode(json)) + .thenReturn(new Object()) // success case + .thenReturn(null); // failure case + + coders.put(myKey, mockToolset); + ReflectionTestUtils.setField(mockDecoder, "coders", coders); + + when(mockDecoder.isCodingSupported(GROUP_ID, ARTIFACT_ID, TOPIC)).thenReturn(true); + when(mockDecoder.codersKey(GROUP_ID, ARTIFACT_ID, TOPIC)).thenReturn(myKey); + when(mockDecoder.decode(GROUP_ID, ARTIFACT_ID, TOPIC, json)) + .thenCallRealMethod(); + + assertNotNull(mockDecoder.decode(GROUP_ID, ARTIFACT_ID, TOPIC, json)); + + assertThatThrownBy(() -> mockDecoder.decode(GROUP_ID, ARTIFACT_ID, TOPIC, json)) + .isInstanceOf(UnsupportedOperationException.class) + .hasMessageContaining("Cannot decode with gson"); + } + + @Test + void testEncode_WithGroupArtifactTopicAndEvent() { + var mockEncoder = mock(EventProtocolEncoder.class); + var event = new Object(); + when(mockEncoder.isCodingSupported(GROUP_ID, ARTIFACT_ID, TOPIC)) + .thenReturn(false); + when(mockEncoder.encode(GROUP_ID, ARTIFACT_ID, TOPIC, event)) + .thenCallRealMethod(); + when(mockEncoder.codersKey(GROUP_ID, ARTIFACT_ID, TOPIC)) + .thenCallRealMethod(); + + assertThatThrownBy(() -> mockEncoder.encode(GROUP_ID, ARTIFACT_ID, TOPIC, event)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Unsupported: groupId:artifactId:topic"); + + // test with event null + when(mockEncoder.isCodingSupported(GROUP_ID, ARTIFACT_ID, TOPIC)) + .thenReturn(true); + when(mockEncoder.codersKey(GROUP_ID, ARTIFACT_ID, TOPIC)) + .thenCallRealMethod(); + when(mockEncoder.encode(GROUP_ID, ARTIFACT_ID, TOPIC, null)) + .thenCallRealMethod(); + + assertThatThrownBy(() -> mockEncoder.encode(GROUP_ID, ARTIFACT_ID, TOPIC, null)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Event cannot be null or empty"); + } + + @Test + void testEncode_WithGroupArtifactTopicAndEvent_ReturnJson() { + var mockEncoder = mock(EventProtocolEncoder.class); + var event = new Object(); + var myKey = "group:artifact:topic"; + + // test with event null + when(mockEncoder.isCodingSupported(GROUP_ID, ARTIFACT_ID, TOPIC)).thenReturn(true); + when(mockEncoder.codersKey(GROUP_ID, ARTIFACT_ID, TOPIC)).thenReturn(myKey); + when(mockEncoder.encode(GROUP_ID, ARTIFACT_ID, TOPIC, event)).thenCallRealMethod(); + when(mockEncoder.encodeInternal(myKey, event)).thenCallRealMethod(); + + var mockToolset = mock(ProtocolCoderToolset.class); + when(mockToolset.encode(event)).thenReturn("{\"json\":\"true\"}"); + + HashMap coders = new HashMap<>(); + coders.put(myKey, mockToolset); + ReflectionTestUtils.setField(mockEncoder, "coders", coders); + + var result = mockEncoder.encode(GROUP_ID, ARTIFACT_ID, TOPIC, event); + assertNotNull(result); + assertEquals("{\"json\":\"true\"}", result); + } + + @Test + void testEncode_WithTopicAndEvent() { + var event = new Object(); + + assertThatThrownBy(() -> encoder.encode(null, event)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid Topic"); + + assertThatThrownBy(() -> encoder.encode("", event)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid Topic"); + + assertThatThrownBy(() -> encoder.encode(TOPIC, null)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Event cannot be null or empty"); + + assertThatThrownBy(() -> encoder.encode(TOPIC, event)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("no reverse coder has been found"); + } + + @Test + void testEncode_WithTopicEncodedClassAndDroolsController() { + var encodedClass = new Object(); + var droolsController = new NullDroolsController(); + + assertThatThrownBy(() -> encoder.encode(null, encodedClass, droolsController)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid Topic"); + + assertThatThrownBy(() -> encoder.encode("", encodedClass, droolsController)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid Topic"); + + assertThatThrownBy(() -> encoder.encode(TOPIC, null, droolsController)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid encoded class"); + + assertThatThrownBy(() -> encoder.encode(TOPIC, encodedClass, droolsController)) + .isInstanceOf(UnsupportedOperationException.class) + .hasMessageContaining("Cannot encode with gson"); + } + + @Test + void testEncode_WithTopicEncodedClassAndDroolsController_ReturnNullJson() { + var encodedClass = new Object(); + var droolsController = new NullDroolsController(); + var mockCoderTools = mock(ProtocolCoderToolset.class); + when(mockCoderTools.encode(encodedClass)).thenReturn(null); + + var mockEncoder = mock(EventProtocolEncoder.class); + when(mockEncoder.codersKey(anyString(), anyString(), anyString())).thenReturn("myKey"); + when(mockEncoder.encodeInternal("myKey", encodedClass)).thenCallRealMethod(); + when(mockEncoder.encode(TOPIC, encodedClass, droolsController)).thenCallRealMethod(); + + HashMap coders = new HashMap<>(); + coders.put("myKey", mockCoderTools); + ReflectionTestUtils.setField(mockEncoder, "coders", coders); + + assertThatThrownBy(() -> mockEncoder.encode(TOPIC, encodedClass, droolsController)) + .isInstanceOf(UnsupportedOperationException.class) + .hasMessageContaining("Cannot encode with gson"); + } + + @Test + void droolsCreators() { + var encodedClass = new Object(); + assertTrue(encoder.droolsCreators(TOPIC, encodedClass).isEmpty()); + } + + @Test + void droolsCreators_ContainsReverseKey() { + var encodedClass = new Object(); + var mockDecoder = mock(EventProtocolDecoder.class); + when(mockDecoder.droolsCreators(TOPIC, encodedClass)).thenCallRealMethod(); + when(mockDecoder.reverseCodersKey(TOPIC, encodedClass.getClass().getName())) + .thenReturn("topic:java.lang.Object"); + + HashMap> reverseCoders = new HashMap<>(); + reverseCoders.put("topic:java.lang.Object", List.of()); + ReflectionTestUtils.setField(mockDecoder, "reverseCoders", reverseCoders); + + assertThatThrownBy(() -> mockDecoder.droolsCreators(TOPIC, encodedClass)) + .isInstanceOf(IllegalStateException.class) + .hasMessageContaining("No Encoders toolsets available for topic:java.lang.Object"); + } + + @Test + void droolsCreators_ContainsReverseKey_ReturnControllers() { + var encodedClass = new Object(); + var mockDecoder = mock(EventProtocolDecoder.class); + when(mockDecoder.droolsCreators(TOPIC, encodedClass)).thenCallRealMethod(); + when(mockDecoder.reverseCodersKey(TOPIC, encodedClass.getClass().getName())) + .thenReturn("group:artifact:topic"); + + var toolset = mock(ProtocolCoderToolset.class); + when(toolset.getGroupId()).thenReturn(GROUP_ID); + when(toolset.getArtifactId()).thenReturn(ARTIFACT_ID); + + var mockCoders = mock(EventProtocolCoder.CoderFilters.class); + when(mockCoders.getFactClass()).thenReturn("java.lang.Object"); + when(mockCoders.getModelClassLoaderHash()).thenReturn(1); + when(toolset.getCoders()).thenReturn(List.of(mockCoders)); + + HashMap> reverseCoders = new HashMap<>(); + var toolsetList = new ArrayList(); + toolsetList.add(toolset); + reverseCoders.put("group:artifact:topic", toolsetList); + ReflectionTestUtils.setField(mockDecoder, "reverseCoders", reverseCoders); + + var mockDroolsController = mock(DroolsController.class); + when(mockDroolsController.ownsCoder(encodedClass.getClass(), 1)).thenReturn(true); + + var mockFactory = mock(DroolsControllerFactory.class); + when(mockFactory.get(GROUP_ID, ARTIFACT_ID, "")).thenReturn(mockDroolsController); + + try (MockedStatic factory = Mockito.mockStatic(DroolsControllerConstants.class)) { + factory.when(DroolsControllerConstants::getFactory).thenReturn(mockFactory); + assertEquals(mockFactory, DroolsControllerConstants.getFactory()); + assertFalse(mockDecoder.droolsCreators(TOPIC, encodedClass).isEmpty()); + } + } + + @Test + void testGetFilters_WithGroupArtifactAndTopic() { + assertThatThrownBy(() -> encoder.getFilters(GROUP_ID, ARTIFACT_ID, TOPIC)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Unsupported: groupId:artifactId:topic"); + + var mockEncoder = mock(EventProtocolEncoder.class); + when(mockEncoder.isCodingSupported(GROUP_ID, ARTIFACT_ID, TOPIC)).thenReturn(true); + when((mockEncoder.codersKey(GROUP_ID, ARTIFACT_ID, TOPIC))).thenCallRealMethod(); + when(mockEncoder.getFilters(GROUP_ID, ARTIFACT_ID, TOPIC)).thenCallRealMethod(); + + HashMap coders = new HashMap<>(); + var mockCoderTools = mock(ProtocolCoderToolset.class); + when(mockCoderTools.getCoders()).thenReturn(List.of()); + coders.put(VALID_KEY, mockCoderTools); + ReflectionTestUtils.setField(mockEncoder, "coders", coders); + + assertTrue(mockEncoder.getFilters(GROUP_ID, ARTIFACT_ID, TOPIC).isEmpty()); + } + + @Test + void testGetFilters_WithGroupAndArtifact() { + assertTrue(encoder.getFilters(GROUP_ID, ARTIFACT_ID).isEmpty()); + + assertThatThrownBy(() -> encoder.getFilters("", ARTIFACT_ID)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid group"); + + assertThatThrownBy(() -> encoder.getFilters(GROUP_ID, "")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid artifact"); + } + + @Test + void testGetFilters_WithGroupArtifactTopicAndClassName() { + assertThatThrownBy(() -> encoder.getFilters(GROUP_ID, ARTIFACT_ID, TOPIC, "className")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Unsupported: groupId:artifactId:topic"); + } + + @Test + void testGetFilters_WithGroupArtifactTopicAndClassNameNull() { + var mockEncoder = mock(EventProtocolEncoder.class); + when(mockEncoder.isCodingSupported(GROUP_ID, ARTIFACT_ID, TOPIC)).thenReturn(true); + when(mockEncoder.getFilters(GROUP_ID, ARTIFACT_ID, TOPIC, "")) + .thenCallRealMethod(); + + assertThatThrownBy(() -> mockEncoder.getFilters(GROUP_ID, ARTIFACT_ID, TOPIC, "")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("classname must be provided"); + } + + @Test + void testGetFilters_WithGroupArtifactTopicAndClassName_ReturnValue() { + var mockEncoder = mock(EventProtocolEncoder.class); + when(mockEncoder.isCodingSupported(GROUP_ID, ARTIFACT_ID, TOPIC)).thenReturn(true); + when(mockEncoder.getFilters(GROUP_ID, ARTIFACT_ID, TOPIC, "className")) + .thenCallRealMethod(); + when((mockEncoder.codersKey(GROUP_ID, ARTIFACT_ID, TOPIC))).thenCallRealMethod(); + + HashMap coders = new HashMap<>(); + var mockCoderTools = mock(ProtocolCoderToolset.class); + when(mockCoderTools.getCoder("className")).thenReturn(null); + coders.put(VALID_KEY, mockCoderTools); + ReflectionTestUtils.setField(mockEncoder, "coders", coders); + + assertNull(mockEncoder.getFilters(GROUP_ID, ARTIFACT_ID, TOPIC, "className")); + } + + @Test + void testGetCoders_ReturnObject() { + var mockEncoder = mock(EventProtocolEncoder.class); + when(mockEncoder.isCodingSupported(GROUP_ID, ARTIFACT_ID, TOPIC)).thenReturn(true); + when(mockEncoder.getCoders(GROUP_ID, ARTIFACT_ID, TOPIC)) + .thenCallRealMethod(); + HashMap coders = new HashMap<>(); + ReflectionTestUtils.setField(mockEncoder, "coders", coders); + + assertNull(mockEncoder.getCoders(GROUP_ID, ARTIFACT_ID, TOPIC)); + } + + @Test + void testGetCoders_ReturnList() { + assertThatThrownBy(() -> encoder.getCoders("", ARTIFACT_ID)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid group"); + + assertThatThrownBy(() -> encoder.getCoders(GROUP_ID, "")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid artifact"); + + assertTrue(encoder.getCoders(GROUP_ID, ARTIFACT_ID).isEmpty()); + + // mock a successful return + var mockEncoder = mock(EventProtocolEncoder.class); + HashMap coders = new HashMap<>(); + var params = mock(EventProtocolParams.class); + coders.put(VALID_KEY, new GsonProtocolCoderToolset(params, "controllerId")); + ReflectionTestUtils.setField(mockEncoder, "coders", coders); + when(mockEncoder.codersKey(GROUP_ID, ARTIFACT_ID, "")).thenCallRealMethod(); + when(mockEncoder.getCoders(GROUP_ID, ARTIFACT_ID)).thenCallRealMethod(); + + var resultList = mockEncoder.getCoders(GROUP_ID, ARTIFACT_ID); + assertFalse(resultList.isEmpty()); + assertEquals(1, resultList.size()); + + var emptyResult = mockEncoder.getCoders("group2", "artifact2"); + assertTrue(emptyResult.isEmpty()); + } + + @Test + void testGetReverseFilters() { + assertThatThrownBy(() -> decoder.getReverseFilters("", "codedClass")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid Topic"); + + assertThatThrownBy(() -> decoder.getReverseFilters(TOPIC, "")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("class must be provided"); + + assertTrue(decoder.getReverseFilters(TOPIC, "codedClass").isEmpty()); + } + + @Test + void testGetReverseFilters_ReturnToolset() { + var mockDecoder = mock(EventProtocolDecoder.class); + + // mock a successful return + HashMap> reverseCoders = new HashMap<>(); + var params = mock(EventProtocolParams.class); + var toolset = new GsonProtocolCoderToolset(params, "controllerId"); + reverseCoders.put("topic:codedClass", List.of(toolset)); + ReflectionTestUtils.setField(mockDecoder, "reverseCoders", reverseCoders); + + when(mockDecoder.reverseCodersKey(TOPIC, "codedClass")).thenReturn("topic:codedClass"); + when(mockDecoder.getReverseFilters(TOPIC, "codedClass")).thenCallRealMethod(); + + var resultList = mockDecoder.getReverseFilters(TOPIC, "codedClass"); + assertFalse(resultList.isEmpty()); + assertEquals(1, resultList.size()); + } + + @Test + void testGetDroolsController_Exception() { + var fact = new Object(); + assertThatThrownBy(() -> decoder.getDroolsController("", fact)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid Topic"); + + assertThatThrownBy(() -> decoder.getDroolsController(TOPIC, null)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("class must be provided"); + + assertThatThrownBy(() -> decoder.getDroolsController(TOPIC, fact)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Unsupported topic topic and encodedClass class java.lang.Object"); + } + + @Test + void testGetDroolsController_ReturnObject() { + var mockDecoder = mock(EventProtocolDecoder.class); + var droolsController = new NullDroolsController(); + var droolsController2 = new NullDroolsController(); + var fact = new Object(); + + // mock first call to return only one controller, then second call should return 2 controllers + when(mockDecoder.getDroolsControllers(TOPIC, fact)) + .thenReturn(List.of(droolsController)) + .thenReturn(List.of(droolsController, droolsController2)); + when(mockDecoder.getDroolsController(TOPIC, fact)).thenCallRealMethod(); + + var result = mockDecoder.getDroolsController(TOPIC, fact); + assertNotNull(result); + + // second call supposed to return 2 controllers internally, but still return 1 item + var result2 = mockDecoder.getDroolsController(TOPIC, fact); + assertNotNull(result2); + } + + @Test + void testGetDroolsControllers_Exception() { + var fact = new Object(); + assertThatThrownBy(() -> decoder.getDroolsControllers("", fact)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid Topic"); + + assertThatThrownBy(() -> decoder.getDroolsControllers(TOPIC, null)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("class must be provided"); + + assertTrue(decoder.getDroolsControllers(TOPIC, fact).isEmpty()); + } + + @Test + void testGetDroolsControllers_ReturnValues() { + var mockDecoder = mock(EventProtocolDecoder.class); + var droolsController = new NullDroolsController(); + var droolsController2 = new NullDroolsController(); + var fact = new Object(); + + // mock first call to return only one controller, then second call should return 2 controllers + when(mockDecoder.droolsCreators(TOPIC, fact)) + .thenReturn(List.of(droolsController)) + .thenReturn(List.of(droolsController, droolsController2)); + when(mockDecoder.getDroolsControllers(TOPIC, fact)).thenCallRealMethod(); + + var result = mockDecoder.getDroolsControllers(TOPIC, fact); + assertEquals(1, result.size()); + + // second call supposed to return 2 controllers + var result2 = mockDecoder.getDroolsControllers(TOPIC, fact); + assertEquals(2, result2.size()); + } + + @Test + void testRemove() { + var mockDecoder = mock(EventProtocolDecoder.class); + doCallRealMethod().when(mockDecoder).remove(GROUP_ID, ARTIFACT_ID, TOPIC); + when(mockDecoder.codersKey(GROUP_ID, ARTIFACT_ID, TOPIC)).thenCallRealMethod(); + when(mockDecoder.reverseCodersKey(TOPIC, "className")).thenReturn(INVALID_KEY); + + var toolset = mock(ProtocolCoderToolset.class); + var mockCoders = new EventProtocolCoder.CoderFilters("className", mock(JsonProtocolFilter.class), 1); + when(toolset.getCoders()).thenReturn(List.of(mockCoders)); + + HashMap coders = new HashMap<>(); + coders.put(VALID_KEY, toolset); + ReflectionTestUtils.setField(mockDecoder, "coders", coders); + HashMap> reverseCoders = new HashMap<>(); + reverseCoders.put(VALID_KEY, new ArrayList<>(List.of(toolset))); + ReflectionTestUtils.setField(mockDecoder, "reverseCoders", reverseCoders); + + assertDoesNotThrow(() -> mockDecoder.remove(GROUP_ID, ARTIFACT_ID, TOPIC)); + assertEquals(1, mockDecoder.reverseCoders.size()); + assertTrue(mockDecoder.coders.isEmpty()); + } + + @Test + void testRemove2() { + var myKey = "group:artifact:topic"; + var mockDecoder = mock(EventProtocolDecoder.class); + doCallRealMethod().when(mockDecoder).remove(GROUP_ID, ARTIFACT_ID, TOPIC); + when(mockDecoder.codersKey(GROUP_ID, ARTIFACT_ID, TOPIC)).thenReturn(myKey); + when(mockDecoder.reverseCodersKey(TOPIC, "className")).thenReturn(myKey); + + var toolset = mock(ProtocolCoderToolset.class); + var mockCoders = new EventProtocolCoder.CoderFilters("className", mock(JsonProtocolFilter.class), 1); + when(toolset.getCoders()).thenReturn(List.of(mockCoders)); + + HashMap coders = new HashMap<>(); + coders.put(myKey, toolset); + ReflectionTestUtils.setField(mockDecoder, "coders", coders); + HashMap> reverseCoders = new HashMap<>(); + reverseCoders.put(myKey, new ArrayList<>()); + ReflectionTestUtils.setField(mockDecoder, "reverseCoders", reverseCoders); + + assertDoesNotThrow(() -> mockDecoder.remove(GROUP_ID, ARTIFACT_ID, TOPIC)); + assertTrue(mockDecoder.reverseCoders.isEmpty()); + assertTrue(mockDecoder.coders.isEmpty()); + } + +} \ No newline at end of file diff --git a/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/GsonProtocolCoderToolsetTest.java b/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/GsonProtocolCoderToolsetTest.java new file mode 100644 index 00000000..4bd2aab2 --- /dev/null +++ b/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/GsonProtocolCoderToolsetTest.java @@ -0,0 +1,197 @@ +/*- + * ============LICENSE_START=============================================== + * ONAP + * ======================================================================== + * Copyright (C) 2024 Nordix Foundation. + * ======================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END================================================= + */ + +package org.onap.policy.drools.protocol.coders; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.mockito.Mockito.doCallRealMethod; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.google.gson.Gson; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonElement; +import com.google.gson.JsonIOException; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSyntaxException; +import java.lang.reflect.Type; +import java.time.Instant; +import java.time.ZonedDateTime; +import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.stubbing.Answer; +import org.onap.policy.drools.controller.DroolsControllerConstants; +import org.onap.policy.drools.controller.DroolsControllerFactory; +import org.onap.policy.drools.controller.internal.NullDroolsController; +import org.springframework.test.util.ReflectionTestUtils; + +class GsonProtocolCoderToolsetTest { + + @Test + void decode() { + var mockGsonToolset = mock(GsonProtocolCoderToolset.class); + ReflectionTestUtils.setField(mockGsonToolset, "groupId", "group"); + ReflectionTestUtils.setField(mockGsonToolset, "artifactId", "artifact"); + doCallRealMethod().when(mockGsonToolset).decode("json"); + + var decoderClass = ProtocolCoderToolsetTest.ThreeStrings.class; + var mockGson = mock(Gson.class); + when(mockGson.fromJson("json", decoderClass)).thenThrow(new JsonSyntaxException("error")); + when(mockGsonToolset.getDecoder()).thenReturn(mockGson); + + var mockCustomCoder = mock(TopicCoderFilterConfiguration.CustomCoder.class); + when(mockCustomCoder.getClassContainer()).thenReturn("classContainer"); + ReflectionTestUtils.setField(mockGsonToolset, "customCoder", mockCustomCoder); + + var mockFilter = mock(EventProtocolCoder.CoderFilters.class); + when(mockFilter.getFactClass()).thenReturn("someClassName"); + when(mockGsonToolset.filter("json")).thenReturn(mockFilter); + + var droolsController = mock(NullDroolsController.class); + when(droolsController.fetchModelClass("someClassName")) + .thenReturn(null) + .thenAnswer((Answer>) invocation -> decoderClass) + .thenAnswer((Answer>) invocation -> decoderClass); + when(droolsController.fetchModelClass("classContainer")).thenReturn(null); + + var mockFactory = mock(DroolsControllerFactory.class); + when(mockFactory.get("group", "artifact", "")) + .thenReturn(null) + .thenReturn(droolsController); + + try (MockedStatic factory = Mockito.mockStatic(DroolsControllerConstants.class)) { + factory.when(DroolsControllerConstants::getFactory).thenReturn(mockFactory); + assertEquals(mockFactory, DroolsControllerConstants.getFactory()); + + // first call to fail when droolsController returns null + assertThatThrownBy(() -> mockGsonToolset.decode("json")) + .isInstanceOf(IllegalStateException.class) + .hasMessageContaining("no drools-controller to process event"); + + // second call to fail when droolsController.fetchModelClass returns null + assertThatThrownBy(() -> mockGsonToolset.decode("json")) + .isInstanceOf(UnsupportedOperationException.class) + .hasMessageContaining("cannot fetch application class someClassName"); + + // third call to fail when droolsController.fetchModelClass returns null when using customCoder + assertThatThrownBy(() -> mockGsonToolset.decode("json")) + .isInstanceOf(UnsupportedOperationException.class) + .hasMessageContaining("cannot decode with customCoder: classContainer") + .hasMessageContaining("using application class someClassName"); + + // set customCoder to null to test default decoder + ReflectionTestUtils.setField(mockGsonToolset, "customCoder", null); + + // fourth call to fail when decoder can't parse json + assertThatThrownBy(() -> mockGsonToolset.decode("json")) + .isInstanceOf(UnsupportedOperationException.class) + .hasMessageContaining("cannot decode into"); + } + } + + @Test + void encode() { + var event = new Object(); + + var mockGsonToolset = mock(GsonProtocolCoderToolset.class); + ReflectionTestUtils.setField(mockGsonToolset, "groupId", "group"); + ReflectionTestUtils.setField(mockGsonToolset, "artifactId", "artifact"); + doCallRealMethod().when(mockGsonToolset).encode(event); + + var mockGson = mock(Gson.class); + when(mockGson.toJson(event)).thenThrow(new JsonIOException("error")); + when(mockGsonToolset.getEncoder()).thenReturn(mockGson); + + var mockCustomCoder = mock(TopicCoderFilterConfiguration.CustomCoder.class); + ReflectionTestUtils.setField(mockGsonToolset, "customCoder", mockCustomCoder); + + var mockFactory = mock(DroolsControllerFactory.class); + when(mockFactory.get("group", "artifact", "")).thenReturn(null); + + try (MockedStatic factory = Mockito.mockStatic(DroolsControllerConstants.class)) { + factory.when(DroolsControllerConstants::getFactory).thenReturn(mockFactory); + assertEquals(mockFactory, DroolsControllerConstants.getFactory()); + + // first call to encode fails with droolsController returning null, therefore, can't process event + assertThatThrownBy(() -> mockGsonToolset.encode(event)) + .isInstanceOf(UnsupportedOperationException.class) + .hasMessageContaining("event cannot be custom encoded"); + + // set customCoder to null to test default encoder + ReflectionTestUtils.setField(mockGsonToolset, "customCoder", null); + + // second call to encode fails when gson.toJson raises an exception + assertThatThrownBy(() -> mockGsonToolset.encode(event)) + .isInstanceOf(UnsupportedOperationException.class) + .hasMessageContaining("event cannot be encoded"); + } + } + + @Test + void test_GsonInstantAdapter() { + var instantAdapter = new GsonProtocolCoderToolset.GsonInstantAdapter(); + + var currentTime = System.currentTimeMillis(); + var json = mock(JsonElement.class); + when(json.getAsLong()).thenReturn(currentTime); + + var result = instantAdapter.deserialize(json, mock(Type.class), mock(JsonDeserializationContext.class)); + assertInstanceOf(Instant.class, result); + assertEquals(currentTime, result.toEpochMilli()); + + var jsonResult = instantAdapter.serialize(result, mock(Type.class), mock(JsonSerializationContext.class)); + assertInstanceOf(JsonElement.class, jsonResult); + assertEquals(currentTime, jsonResult.getAsLong()); + } + + @Test + void test_GsonUtcAdapter() { + var utcAdapter = new GsonProtocolCoderToolset.GsonUtcAdapter(); + + var currentZone = ZonedDateTime.now(); + var formattedCurrentZone = ZonedDateTime.now().format(GsonProtocolCoderToolset.format); + var json = mock(JsonElement.class); + when(json.getAsString()).thenReturn(formattedCurrentZone).thenReturn("invalid json"); + + var result = utcAdapter.deserialize(json, mock(Type.class), mock(JsonDeserializationContext.class)); + assertNotNull(result); + assertAll(() -> { + assertEquals(currentZone.getYear(), result.getYear()); + assertEquals(currentZone.getMonth(), result.getMonth()); + assertEquals(currentZone.getDayOfMonth(), result.getDayOfMonth()); + assertEquals(currentZone.getHour(), result.getHour()); + assertEquals(currentZone.getMinute(), result.getMinute()); + assertEquals(currentZone.getSecond(), result.getSecond()); + }); + + // when json.getAsString returns invalid json, should fail and return null + assertNull(utcAdapter.deserialize(json, mock(Type.class), mock(JsonDeserializationContext.class))); + + var result2 = utcAdapter.serialize(result, mock(Type.class), mock(JsonSerializationContext.class)); + assertNotNull(result2); + assertEquals(formattedCurrentZone, result2.getAsString()); + } +} \ No newline at end of file diff --git a/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/MultiplexorEventProtocolCoderTest.java b/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/MultiplexorEventProtocolCoderTest.java new file mode 100644 index 00000000..c64e9bce --- /dev/null +++ b/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/MultiplexorEventProtocolCoderTest.java @@ -0,0 +1,308 @@ +/*- + * ============LICENSE_START=============================================== + * ONAP + * ======================================================================== + * Copyright (C) 2024 Nordix Foundation. + * ======================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END================================================= + */ + +package org.onap.policy.drools.protocol.coders; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.HashMap; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.policy.drools.controller.DroolsController; +import org.springframework.test.util.ReflectionTestUtils; + +class MultiplexorEventProtocolCoderTest { + + @Mock + EventProtocolEncoder encoder; + + @Mock + EventProtocolDecoder decoder; + + MultiplexorEventProtocolCoder coder = new MultiplexorEventProtocolCoder(); + + AutoCloseable closeable; + + private static final String GROUP_ID = "group"; + private static final String ARTIFACT_ID = "artifact"; + private static final String TOPIC = "topic"; + + @BeforeEach + void setUp() { + closeable = MockitoAnnotations.openMocks(this); + ReflectionTestUtils.setField(coder, "encoders", encoder); + ReflectionTestUtils.setField(coder, "decoders", decoder); + } + + @AfterEach + void tearDown() throws Exception { + closeable.close(); + } + + @Test + void addDecoder() { + var mockParams = mock(EventProtocolParams.class); + doNothing().when(decoder).add(mockParams); + + assertDoesNotThrow(() -> coder.addDecoder(mockParams)); + } + + @Test + void addEncoder() { + var mockParams = mock(EventProtocolParams.class); + doNothing().when(encoder).add(mockParams); + + assertDoesNotThrow(() -> coder.addEncoder(mockParams)); + } + + @Test + void removeDecoders() { + doNothing().when(decoder).remove(GROUP_ID, ARTIFACT_ID, TOPIC); + assertDoesNotThrow(() -> coder.removeDecoders(GROUP_ID, ARTIFACT_ID, TOPIC)); + } + + @Test + void removeEncoders() { + doNothing().when(encoder).remove(GROUP_ID, ARTIFACT_ID, TOPIC); + assertDoesNotThrow(() -> coder.removeEncoders(GROUP_ID, ARTIFACT_ID, TOPIC)); + } + + @Test + void isDecodingSupported() { + HashMap coders = new HashMap<>(); + coders.put("otherGroup:artifact:topic", mock(ProtocolCoderToolset.class)); + ReflectionTestUtils.setField(decoder, "coders", coders); + when(decoder.codersKey(GROUP_ID, ARTIFACT_ID, TOPIC)).thenCallRealMethod(); + when(decoder.isCodingSupported(GROUP_ID, ARTIFACT_ID, TOPIC)) + .thenReturn(true) + .thenCallRealMethod(); + assertTrue(coder.isDecodingSupported(GROUP_ID, ARTIFACT_ID, TOPIC)); + assertFalse(coder.isDecodingSupported(GROUP_ID, ARTIFACT_ID, TOPIC)); + } + + @Test + void isEncodingSupported() { + HashMap coders = new HashMap<>(); + coders.put("otherGroup:artifact:topic", mock(ProtocolCoderToolset.class)); + ReflectionTestUtils.setField(encoder, "coders", coders); + when(encoder.codersKey(GROUP_ID, ARTIFACT_ID, TOPIC)).thenCallRealMethod(); + when(encoder.isCodingSupported(GROUP_ID, ARTIFACT_ID, TOPIC)) + .thenReturn(true) + .thenCallRealMethod(); + assertTrue(coder.isEncodingSupported(GROUP_ID, ARTIFACT_ID, TOPIC)); + assertFalse(coder.isEncodingSupported(GROUP_ID, ARTIFACT_ID, TOPIC)); + } + + @Test + void decode() { + when(decoder.decode(GROUP_ID, ARTIFACT_ID, TOPIC, "{}")) + .thenReturn(new Object()) + .thenCallRealMethod(); + when(decoder.isCodingSupported(GROUP_ID, ARTIFACT_ID, TOPIC)).thenReturn(false); + + // first mock call to return directly new Object() + assertNotNull(coder.decode(GROUP_ID, ARTIFACT_ID, TOPIC, "{}")); + + // second mock call to check isCodingSupport return false, then throws exception + assertThrows(IllegalArgumentException.class, + () -> coder.decode(GROUP_ID, ARTIFACT_ID, TOPIC, "{}")); + } + + @Test + void encode() { + var event = new Object(); + when(encoder.encode(GROUP_ID, ARTIFACT_ID, TOPIC, event)) + .thenReturn("{}") + .thenCallRealMethod(); + when(encoder.isCodingSupported(GROUP_ID, ARTIFACT_ID, TOPIC)).thenReturn(false); + + // first mock call to return directly new Object() + assertNotNull(coder.encode(GROUP_ID, ARTIFACT_ID, TOPIC, event)); + + // second mock call to check isCodingSupport return false, then throws exception + assertThrows(IllegalArgumentException.class, + () -> coder.encode(GROUP_ID, ARTIFACT_ID, TOPIC, event)); + } + + @Test + void encode_WithTopicAndEvent() { + var event = new Object(); + when(encoder.encode(TOPIC, event)).thenReturn("{}"); + + var result = coder.encode(TOPIC, event); + assertNotNull(result); + assertInstanceOf(String.class, result); + } + + @Test + void encode_WithTopicEncodedClassAndController() { + var event = new Object(); + var controller = mock(DroolsController.class); + when(encoder.encode(TOPIC, event, controller)).thenReturn("{}"); + + var result = coder.encode(TOPIC, event, controller); + assertNotNull(result); + assertInstanceOf(String.class, result); + } + + @Test + void getDecoderFilters() { + when(decoder.getFilters(GROUP_ID, ARTIFACT_ID, TOPIC)) + .thenReturn(new ArrayList<>()) + .thenCallRealMethod(); + when(decoder.isCodingSupported(GROUP_ID, ARTIFACT_ID, TOPIC)).thenReturn(false); + + // first mock call return a list + var result = coder.getDecoderFilters(GROUP_ID, ARTIFACT_ID, TOPIC); + assertTrue(result.isEmpty()); + + // second call goes for real method, with isCodingSupported mocked to false, exception is thrown + assertThrows(IllegalArgumentException.class, + () -> coder.getDecoderFilters(GROUP_ID, ARTIFACT_ID, TOPIC)); + } + + @Test + void testGetDecoderFilters_WithGroupArtifactTopicAndClassName() { + when(decoder.getFilters(GROUP_ID, ARTIFACT_ID, TOPIC, "className")) + .thenReturn(mock(EventProtocolCoder.CoderFilters.class)) + .thenCallRealMethod(); + when(decoder.isCodingSupported(GROUP_ID, ARTIFACT_ID, TOPIC)).thenReturn(false); + + // first mock call return a mock object + assertNotNull(coder.getDecoderFilters(GROUP_ID, ARTIFACT_ID, TOPIC, "className")); + + // second call goes for real method, with isCodingSupported mocked to false, exception is thrown + assertThrows(IllegalArgumentException.class, + () -> coder.getDecoderFilters(GROUP_ID, ARTIFACT_ID, TOPIC, "className")); + } + + @Test + void testGetDecoderFilters_WithGroupAndArtifact() { + when(decoder.getFilters(GROUP_ID, ARTIFACT_ID)).thenReturn(new ArrayList<>()); + + assertThat(coder.getDecoderFilters(GROUP_ID, ARTIFACT_ID, TOPIC)).isEmpty(); + } + + @Test + void getDecoders() { + when(decoder.getCoders(GROUP_ID, ARTIFACT_ID, TOPIC)) + .thenReturn(mock(ProtocolCoderToolset.class)) + .thenCallRealMethod(); + when(decoder.isCodingSupported(GROUP_ID, ARTIFACT_ID, TOPIC)).thenReturn(false); + + assertNotNull(coder.getDecoders(GROUP_ID, ARTIFACT_ID, TOPIC)); + assertThrows(IllegalArgumentException.class, + () -> coder.getDecoders(GROUP_ID, ARTIFACT_ID, TOPIC)); + } + + @Test + void testGetDecoders_WithGroupAndArtifact() { + when(decoder.getCoders(GROUP_ID, ARTIFACT_ID)).thenReturn(new ArrayList<>()); + + assertThat(coder.getDecoders(GROUP_ID, ARTIFACT_ID)).isEmpty(); + } + + @Test + void getEncoderFilters() { + when(encoder.getFilters(GROUP_ID, ARTIFACT_ID, TOPIC)) + .thenReturn(new ArrayList<>()) + .thenCallRealMethod(); + when(encoder.isCodingSupported(GROUP_ID, ARTIFACT_ID, TOPIC)).thenReturn(false); + + // first mock call return a list + var result = coder.getEncoderFilters(GROUP_ID, ARTIFACT_ID, TOPIC); + assertTrue(result.isEmpty()); + + // second call goes for real method, with isCodingSupported mocked to false, exception is thrown + assertThrows(IllegalArgumentException.class, + () -> coder.getEncoderFilters(GROUP_ID, ARTIFACT_ID, TOPIC)); + } + + @Test + void testGetEncoderFilters_WithGroupArtifactTopicAndClassName() { + when(encoder.getFilters(GROUP_ID, ARTIFACT_ID, TOPIC, "className")) + .thenReturn(mock(EventProtocolCoder.CoderFilters.class)) + .thenCallRealMethod(); + when(encoder.isCodingSupported(GROUP_ID, ARTIFACT_ID, TOPIC)).thenReturn(false); + + // first mock call return a mock object + assertNotNull(coder.getEncoderFilters(GROUP_ID, ARTIFACT_ID, TOPIC, "className")); + + // second call goes for real method, with isCodingSupported mocked to false, exception is thrown + assertThrows(IllegalArgumentException.class, + () -> coder.getEncoderFilters(GROUP_ID, ARTIFACT_ID, TOPIC, "className")); + } + + @Test + void testGetEncoderFilters_WithGroupAndArtifact() { + when(encoder.getFilters(GROUP_ID, ARTIFACT_ID)).thenReturn(new ArrayList<>()); + + assertThat(coder.getEncoderFilters(GROUP_ID, ARTIFACT_ID, TOPIC)).isEmpty(); + } + + @Test + void getReverseEncoderFilters() { + when(encoder.getReverseFilters(TOPIC, "codedClass")).thenReturn(new ArrayList<>()); + assertThat(coder.getReverseEncoderFilters(TOPIC, "codedClass")).isEmpty(); + } + + @Test + void getDroolsController() { + var fact = new Object(); + // mock success + when(encoder.getDroolsController(TOPIC, fact)) + .thenReturn(mock(DroolsController.class)) + .thenCallRealMethod(); + // mock failure + when(encoder.getDroolsControllers(TOPIC, fact)).thenReturn(new ArrayList<>()); + + // first call gets mock DroolsController - pass + assertNotNull(coder.getDroolsController(TOPIC, fact)); + // second call goes through the method, then call inside method that returns empty list, throws an exception + assertThrows(IllegalArgumentException.class, () -> coder.getDroolsController(TOPIC, fact)); + } + + @Test + void getDroolsControllers() { + var fact = new Object(); + when(encoder.getDroolsControllers(TOPIC, fact)).thenReturn(new ArrayList<>()); + + assertThat(coder.getDroolsControllers(TOPIC, fact)).isEmpty(); + } + + @Test + void testToString() { + assertThat(coder.toString()) + .contains("MultiplexorEventProtocolCoder"); + } +} \ No newline at end of file diff --git a/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/ProtocolCoderToolsetTest.java b/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/ProtocolCoderToolsetTest.java index 659965f8..cb4397c8 100644 --- a/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/ProtocolCoderToolsetTest.java +++ b/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/ProtocolCoderToolsetTest.java @@ -22,11 +22,19 @@ package org.onap.policy.drools.protocol.coders; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doCallRealMethod; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -53,6 +61,7 @@ import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration.Cust import org.onap.policy.drools.util.KieUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.test.util.ReflectionTestUtils; /** * ProtocolCoder Toolset Junits. @@ -62,12 +71,12 @@ public class ProtocolCoderToolsetTest { private static final String JUNIT_PROTOCOL_CODER_TOPIC = JUNIT_PROTOCOL_CODER_ARTIFACT_ID; private static final String CONTROLLER_ID = "blah"; - private static final Logger logger = LoggerFactory.getLogger(ProtocolCoderToolset.class); + private static final Logger logger = LoggerFactory.getLogger(ProtocolCoderToolsetTest.class); private static volatile ReleaseId releaseId; // customCoder has to be public to be accessed in tests below - public static final Gson customCoder = new GsonBuilder().create(); + public static final Gson customCoder = new GsonBuilder().create(); // NOSONAR actually being used in the test private DroolsController controller; @@ -77,9 +86,9 @@ public class ProtocolCoderToolsetTest { @BeforeAll public static void setUpClass() throws IOException { releaseId = KieUtils.installArtifact(Paths.get(MavenDroolsControllerTest.JUNIT_ECHO_KMODULE_PATH).toFile(), - Paths.get(MavenDroolsControllerTest.JUNIT_ECHO_KMODULE_POM_PATH).toFile(), - MavenDroolsControllerTest.JUNIT_ECHO_KJAR_DRL_PATH, - Paths.get(MavenDroolsControllerTest.JUNIT_ECHO_KMODULE_DRL_PATH).toFile()); + Paths.get(MavenDroolsControllerTest.JUNIT_ECHO_KMODULE_POM_PATH).toFile(), + MavenDroolsControllerTest.JUNIT_ECHO_KJAR_DRL_PATH, + Paths.get(MavenDroolsControllerTest.JUNIT_ECHO_KMODULE_DRL_PATH).toFile()); } /** @@ -105,6 +114,55 @@ public class ProtocolCoderToolsetTest { testGsonToolset(createFilterSet()); } + @Test + void testExceptions() { + // should fail without params + assertThrows(IllegalArgumentException.class, + () -> new GsonProtocolCoderToolset(null, "controller")); + + // should fail without controller ID + assertThrows(IllegalArgumentException.class, + () -> new GsonProtocolCoderToolset(mock(EventProtocolParams.class), "")); + + // set mock under test - always call real method under test + var toolset = mock(GsonProtocolCoderToolset.class); + when(toolset.getCoder("")).thenCallRealMethod(); + + // should fail calling with empty classname + assertThatThrownBy(() -> toolset.getCoder("")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("no classname provided"); + + // should fail when trying to add coder with empty event class + doCallRealMethod().when(toolset).addCoder(anyString(), any(JsonProtocolFilter.class), anyInt()); + assertThatThrownBy(() -> toolset.addCoder("", mock(JsonProtocolFilter.class), 1)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("no event class provided"); + + // should fail when trying to remove coder with empty event + doCallRealMethod().when(toolset).removeCoders(anyString()); + assertThatThrownBy(() -> toolset.removeCoders("")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("no event class provided"); + + // set coders to empty list + when(toolset.filter(anyString())).thenCallRealMethod(); + ReflectionTestUtils.setField(toolset, "coders", List.of()); + + // should fail when trying to find a filter from an empty list + assertThatThrownBy(() -> toolset.filter("")) + .isInstanceOf(IllegalStateException.class) + .hasMessageContaining("No coders available"); + + // there is a coder in the list, but can't check if accepts json when coder doesn't have filter + var mockCoderFilter = mock(CoderFilters.class); + when(mockCoderFilter.getFilter()).thenReturn(null); + ReflectionTestUtils.setField(toolset, "coders", List.of(mockCoderFilter)); + + assertNull(toolset.filter("json")); + + } + /** * Test the Gson toolset. * @@ -112,10 +170,10 @@ public class ProtocolCoderToolsetTest { */ private void testGsonToolset(JsonProtocolFilter protocolFilter) { GsonProtocolCoderToolset gsonToolset = - new GsonProtocolCoderToolset(EventProtocolParams.builder().topic(JUNIT_PROTOCOL_CODER_TOPIC) - .groupId(releaseId.getGroupId()).artifactId(releaseId.getArtifactId()) - .eventClass(ThreeStrings.class.getName()).protocolFilter(protocolFilter) - .customGsonCoder(null).modelClassLoaderHash(12345678).build(), CONTROLLER_ID); + new GsonProtocolCoderToolset(EventProtocolParams.builder().topic(JUNIT_PROTOCOL_CODER_TOPIC) + .groupId(releaseId.getGroupId()).artifactId(releaseId.getArtifactId()) + .eventClass(ThreeStrings.class.getName()).protocolFilter(protocolFilter) + .customGsonCoder(null).modelClassLoaderHash(12345678).build(), CONTROLLER_ID); assertNotNull(gsonToolset.getEncoder()); assertNotNull(gsonToolset.getDecoder()); @@ -154,7 +212,7 @@ public class ProtocolCoderToolsetTest { } private void decode(JsonProtocolFilter protocolFilter, ProtocolCoderToolset coderToolset, - ThreeStrings triple, String tripleEncoded) { + ThreeStrings triple, String tripleEncoded) { try { coderToolset.decode(tripleEncoded); @@ -212,7 +270,7 @@ public class ProtocolCoderToolsetTest { assertNotNull(coderToolset.getCoder(ThreeStrings.class.getName()).getFilter().getRule()); assertEquals("[?($.third =~ /.*/)]", - coderToolset.getCoder(ThreeStrings.class.getName()).getFilter().getRule()); + coderToolset.getCoder(ThreeStrings.class.getName()).getFilter().getRule()); } private void validateInitialization(JsonProtocolFilter protocolFilter, ProtocolCoderToolset coderToolset) { @@ -241,16 +299,21 @@ public class ProtocolCoderToolsetTest { sinkConfig.put(PolicyEndPointProperties.PROPERTY_NOOP_SINK_TOPICS, JUNIT_PROTOCOL_CODER_TOPIC); final List noopTopics = TopicEndpointManager.getManager().addTopicSinks(sinkConfig); + Properties droolsControllerConfig = getDroolsControllerConfig(); + + return DroolsControllerConstants.getFactory().build(droolsControllerConfig, null, noopTopics); + } + + private static Properties getDroolsControllerConfig() { Properties droolsControllerConfig = new Properties(); droolsControllerConfig.put(DroolsPropertyConstants.RULES_GROUPID, releaseId.getGroupId()); droolsControllerConfig.put(DroolsPropertyConstants.RULES_ARTIFACTID, releaseId.getArtifactId()); droolsControllerConfig.put(DroolsPropertyConstants.RULES_VERSION, releaseId.getVersion()); droolsControllerConfig.put( - PolicyEndPointProperties.PROPERTY_NOOP_SINK_TOPICS + "." + JUNIT_PROTOCOL_CODER_TOPIC - + PolicyEndPointProperties.PROPERTY_TOPIC_EVENTS_SUFFIX, - ThreeStrings.class.getName()); - - return DroolsControllerConstants.getFactory().build(droolsControllerConfig, null, noopTopics); + PolicyEndPointProperties.PROPERTY_NOOP_SINK_TOPICS + "." + JUNIT_PROTOCOL_CODER_TOPIC + + PolicyEndPointProperties.PROPERTY_TOPIC_EVENTS_SUFFIX, + ThreeStrings.class.getName()); + return droolsControllerConfig; } private JsonProtocolFilter createFilterSet() { diff --git a/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/TopicCoderFilterConfigurationTest.java b/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/TopicCoderFilterConfigurationTest.java new file mode 100644 index 00000000..5429a94e --- /dev/null +++ b/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/TopicCoderFilterConfigurationTest.java @@ -0,0 +1,75 @@ +/*- + * ============LICENSE_START=============================================== + * ONAP + * ======================================================================== + * Copyright (C) 2024 Nordix Foundation. + * ======================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END================================================= + */ + +package org.onap.policy.drools.protocol.coders; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import java.util.List; +import org.junit.jupiter.api.Test; + +class TopicCoderFilterConfigurationTest { + + @Test + void setCustomGsonCoder() { + var topic = "topic"; + var decodeFilter = new TopicCoderFilterConfiguration + .PotentialCoderFilter("codedClass", new JsonProtocolFilter("rule")); + var customCoder = new TopicCoderFilterConfiguration + .CustomGsonCoder("className", "staticCoderField"); + var topicConfig = new TopicCoderFilterConfiguration(topic, List.of(decodeFilter), customCoder); + + assertNotNull(topicConfig); + assertNotNull(topicConfig.getCoderFilters()); + assertEquals("topic", topicConfig.getTopic()); + + assertEquals("className", topicConfig.getCustomGsonCoder().getClassContainer()); + + var customCoder2 = new TopicCoderFilterConfiguration.CustomGsonCoder("className2,staticCoderField2"); + topicConfig.setCustomGsonCoder(customCoder2); + + assertEquals("className2", topicConfig.getCustomGsonCoder().getClassContainer()); + } + + @Test + void setCustomCoder_Exceptions() { + assertThatThrownBy(() -> new TopicCoderFilterConfiguration.CustomGsonCoder("", "staticCoderField")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("No classname to create CustomCoder cannot be created"); + + assertThatThrownBy(() -> new TopicCoderFilterConfiguration.CustomGsonCoder("className", "")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("No staticCoderField to create CustomCoder cannot be created for class className"); + + assertThatThrownBy(() -> new TopicCoderFilterConfiguration.CustomGsonCoder(",staticCoderField")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("No classname to create CustomCoder cannot be created"); + + assertThatThrownBy(() -> new TopicCoderFilterConfiguration.CustomGsonCoder("className,")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("No staticCoderField to create CustomCoder cannot be created for class className"); + + assertThatThrownBy(() -> new TopicCoderFilterConfiguration.CustomGsonCoder("")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Constructor argument cannot be empty."); + } +} \ No newline at end of file diff --git a/policy-management/src/test/java/org/onap/policy/drools/server/restful/test/RestManagerTest.java b/policy-management/src/test/java/org/onap/policy/drools/server/restful/test/RestManagerTest.java index 6a17f269..1ceff3d0 100644 --- a/policy-management/src/test/java/org/onap/policy/drools/server/restful/test/RestManagerTest.java +++ b/policy-management/src/test/java/org/onap/policy/drools/server/restful/test/RestManagerTest.java @@ -127,7 +127,6 @@ public class RestManagerTest { Properties controllerProps = new Properties(); PolicyEngineConstants.getManager().createPolicyController(FOO_CONTROLLER, controllerProps); - // client = HttpClients.createDefault(); CredentialsProvider provider = new BasicCredentialsProvider(); UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(TELEMETRY_USER, TELEMETRY_PASSWORD); provider.setCredentials(AuthScope.ANY, credentials); @@ -249,7 +248,7 @@ public class RestManagerTest { private void requestTest(HttpRequestBase request, int statusCode) throws IOException { CloseableHttpResponse resp = client.execute(request); - logger.info(request.getRequestLine() + "response code: {}", resp.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", request.getRequestLine(), resp.getStatusLine().getStatusCode()); assertEquals(statusCode, resp.getStatusLine().getStatusCode()); request.releaseConnection(); } @@ -291,13 +290,13 @@ public class RestManagerTest { CloseableHttpResponse response; httpGet = new HttpGet(HOST_URL + "/engine/swagger"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); } @Test - void testGet() throws IOException { + void testGetEngine() throws IOException { HttpGet httpGet; CloseableHttpResponse response; @@ -306,45 +305,46 @@ public class RestManagerTest { * /engine/inputs /engine/properties /engine/environment /engine/switches * /engine/controllers */ + httpGet = new HttpGet(HOST_URL + "/engine"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); httpGet = new HttpGet(HOST_URL + "/engine/features"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); httpGet = new HttpGet(HOST_URL + "/engine/features/inventory"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); httpGet = new HttpGet(HOST_URL + "/engine/features/foobar"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(404, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); httpGet = new HttpGet(HOST_URL + "/engine/inputs"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); httpGet = new HttpGet(HOST_URL + "/engine/properties"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); httpGet = new HttpGet(HOST_URL + "/engine/environment"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); @@ -352,26 +352,32 @@ public class RestManagerTest { httpGet = new HttpGet(HOST_URL + "/engine/environment/foo"); response = client.execute(httpGet); String responseBody = this.getResponseBody(response); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); - logger.info(httpGet.getRequestLine() + " response body: {}", responseBody); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); + logger.info("{} response body: {}", httpGet.getRequestLine(), responseBody); assertEquals(200, response.getStatusLine().getStatusCode()); assertEquals("bar", responseBody); httpGet.releaseConnection(); httpGet = new HttpGet(HOST_URL + "/engine/switches"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); httpGet = new HttpGet(HOST_URL + "/engine/controllers"); response = client.execute(httpGet); responseBody = this.getResponseBody(response); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); - logger.info(httpGet.getRequestLine() + " response body: {}", responseBody); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); + logger.info("{} response body: {}", httpGet.getRequestLine(), responseBody); assertEquals(200, response.getStatusLine().getStatusCode()); assertEquals("[\"" + FOO_CONTROLLER + "\"]", responseBody); httpGet.releaseConnection(); + } + + @Test + void testGet_EngineControllers() throws IOException { + HttpGet httpGet; + CloseableHttpResponse response; /* * GET: /engine/controllers/inventory /engine/controllers/features @@ -381,39 +387,46 @@ public class RestManagerTest { */ httpGet = new HttpGet(HOST_URL + "/engine/controllers/inventory"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); httpGet = new HttpGet(HOST_URL + "/engine/controllers/features"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); httpGet = new HttpGet(HOST_URL + "/engine/controllers/features/inventory"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); httpGet = new HttpGet(HOST_URL + "/engine/controllers/features/dummy"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(404, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); httpGet = new HttpGet(HOST_URL + "/engine/controllers/" + FOO_CONTROLLER); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); httpGet = new HttpGet(HOST_URL + "/engine/controllers/nonexistantcontroller"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(404, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); + } + + @Test + void testGet() throws IOException { + HttpGet httpGet; + CloseableHttpResponse response; + String responseBody; /* * GET: /engine/controllers/controllerName/properties @@ -423,52 +436,45 @@ public class RestManagerTest { httpGet = new HttpGet(HOST_URL + "/engine/controllers/" + FOO_CONTROLLER + "/properties"); response = client.execute(httpGet); responseBody = this.getResponseBody(response); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); - logger.info(httpGet.getRequestLine() + " response code: {}", responseBody); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), responseBody); assertEquals(200, response.getStatusLine().getStatusCode()); assertEquals("{}", responseBody); httpGet.releaseConnection(); httpGet = new HttpGet(HOST_URL + "/engine/controllers/nonexistantcontroller/properties"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(404, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); httpGet = new HttpGet(HOST_URL + "/engine/controllers/" + FOO_CONTROLLER + "/inputs"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); httpGet = new HttpGet(HOST_URL + "/engine/controllers/" + FOO_CONTROLLER + "/switches"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); httpGet = new HttpGet(HOST_URL + "/engine/controllers/" + FOO_CONTROLLER + "/drools"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); httpGet = new HttpGet(HOST_URL + "/engine/controllers/nonexistantcontroller/drools"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(404, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); - - testGetDroolsControllers(); - - testGetControllersDecoders(); - - testGetTopics(); - - testGetEngineTools(); } - private static void testGetDroolsControllers() throws IOException { + @Test + void testGetDroolsControllers() throws IOException { CloseableHttpResponse response; HttpGet httpGet; /* @@ -480,43 +486,44 @@ public class RestManagerTest { */ httpGet = new HttpGet(HOST_URL + "/engine/controllers/" + FOO_CONTROLLER + "/drools/facts"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); httpGet = new HttpGet(HOST_URL + "/engine/controllers/nonexistantcontroller/drools/facts"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(404, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); httpGet = new HttpGet(HOST_URL + "/engine/controllers/" + FOO_CONTROLLER + "/drools/facts/session"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); httpGet = new HttpGet(HOST_URL + "/engine/controllers/" + FOO_CONTROLLER + "/drools/facts/session/factType"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); httpGet = new HttpGet( HOST_URL + "/engine/controllers/" + FOO_CONTROLLER + "/drools/facts/session/query/queriedEntity"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); httpGet = new HttpGet(HOST_URL + "/engine/controllers/dummy" + "/drools/facts/session/query/queriedEntity"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(404, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); } - private static void testGetEngineTools() throws IOException { + @Test + void testGetEngineTools() throws IOException { CloseableHttpResponse response; HttpGet httpGet; /* @@ -524,24 +531,25 @@ public class RestManagerTest { */ httpGet = new HttpGet(HOST_URL + "/engine/tools/uuid"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); httpGet = new HttpGet(HOST_URL + "/engine/tools/loggers"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); httpGet = new HttpGet(HOST_URL + "/engine/tools/loggers/ROOT"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); } - private static void testGetControllersDecoders() throws IOException { + @Test + void testGetControllersDecoders() throws IOException { HttpGet httpGet; CloseableHttpResponse response; /* @@ -556,68 +564,69 @@ public class RestManagerTest { */ httpGet = new HttpGet(HOST_URL + "/engine/controllers/" + FOO_CONTROLLER + "/decoders"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); httpGet = new HttpGet(HOST_URL + "/engine/controllers/nonexistantcontroller/decoders"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(404, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); httpGet = new HttpGet(HOST_URL + "/engine/controllers/" + FOO_CONTROLLER + "/decoders/filters"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); httpGet = new HttpGet(HOST_URL + "/engine/controllers/nonexistantcontroller/decoders/filters"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(404, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); httpGet = new HttpGet(HOST_URL + "/engine/controllers/" + FOO_CONTROLLER + "/decoders/topic"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(404, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); httpGet = new HttpGet(HOST_URL + "/engine/controllers/" + FOO_CONTROLLER + "/decoders/topic/filters"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(404, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); httpGet = new HttpGet(HOST_URL + "/engine/controllers/" + FOO_CONTROLLER + "/decoders/topic/filters/factType"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(404, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); httpGet = new HttpGet( HOST_URL + "/engine/controllers/" + FOO_CONTROLLER + "/decoders/topic/filters/factType/rules"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(404, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); httpGet = new HttpGet( HOST_URL + "/engine/controllers/" + FOO_CONTROLLER + "/decoders/topic/filters/factType/rules/ruleName"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(404, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); httpGet = new HttpGet(HOST_URL + "/engine/controllers/" + FOO_CONTROLLER + "/encoders"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); } - private static void testGetTopics() throws IOException { + @Test + void testGetKafkaTopics() throws IOException { CloseableHttpResponse response; HttpGet httpGet; /* @@ -635,169 +644,186 @@ public class RestManagerTest { */ httpGet = new HttpGet(HOST_URL + "/engine/topics"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); httpGet = new HttpGet(HOST_URL + "/engine/topics/switches"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); httpGet = new HttpGet(HOST_URL + "/engine/topics/sources"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); httpGet = new HttpGet(HOST_URL + "/engine/topics/sinks"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); httpGet = new HttpGet(HOST_URL + "/engine/topics/sources/kafka"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); httpGet = new HttpGet(HOST_URL + "/engine/topics/sinks/kafka"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); - httpGet = new HttpGet(HOST_URL + "/engine/topics/sources/noop"); + httpGet = new HttpGet(HOST_URL + "/engine/topics/sources/kafka/" + KAFKA_TOPIC); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); - httpGet = new HttpGet(HOST_URL + "/engine/topics/sinks/noop"); + httpGet = new HttpGet(HOST_URL + "/engine/topics/sources/kafka/foobar"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); - assertEquals(200, response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); + assertEquals(500, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); - httpGet = new HttpGet(HOST_URL + "/engine/topics/sources/kafka/" + KAFKA_TOPIC); + httpGet = new HttpGet(HOST_URL + "/engine/topics/sinks/kafka/" + KAFKA_TOPIC); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); - httpGet = new HttpGet(HOST_URL + "/engine/topics/sources/kafka/foobar"); + httpGet = new HttpGet(HOST_URL + "/engine/topics/sinks/kafka/foobar"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(500, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); - httpGet = new HttpGet(HOST_URL + "/engine/topics/sinks/kafka/" + KAFKA_TOPIC); + httpGet = new HttpGet(HOST_URL + "/engine/topics/sources/kafka/" + KAFKA_TOPIC + "/events"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); - httpGet = new HttpGet(HOST_URL + "/engine/topics/sinks/kafka/foobar"); + httpGet = new HttpGet(HOST_URL + "/engine/topics/sources/kafka/foobar/events"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(500, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); - httpGet = new HttpGet(HOST_URL + "/engine/topics/sources/noop/" + NOOP_TOPIC); + httpGet = new HttpGet(HOST_URL + "/engine/topics/sinks/kafka/" + KAFKA_TOPIC + "/events"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); - httpGet = new HttpGet(HOST_URL + "/engine/topics/sources/noop/foobar"); + httpGet = new HttpGet(HOST_URL + "/engine/topics/sinks/kafka/foobar/events"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(500, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); - httpGet = new HttpGet(HOST_URL + "/engine/topics/sinks/noop/" + NOOP_TOPIC); + httpGet = new HttpGet(HOST_URL + "/engine/topics/sources/kafka/" + KAFKA_TOPIC + "/switches"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); - httpGet = new HttpGet(HOST_URL + "/engine/topics/sinks/noop/foobar"); + httpGet = new HttpGet(HOST_URL + "/engine/topics/sinks/kafka/" + KAFKA_TOPIC + "/switches"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); - assertEquals(500, response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); + assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); + } - httpGet = new HttpGet(HOST_URL + "/engine/topics/sources/kafka/" + KAFKA_TOPIC + "/events"); + @Test + void testGetNoopTopics() throws IOException { + CloseableHttpResponse response; + HttpGet httpGet; + /* + * GET: /engine/topics + * /engine/topics/sources/noop + * /engine/topics/sinks/noop + * /engine/topics/sources/noop/topic + * /engine/topics/sinks/noop/topic + * /engine/topics/sources/noop/topic/events + * /engine/topics/sinks/noop/topic/events + * /engine/topics/sources/noop/topic/switches + * /engine/topics/sinks/noop/topic/switches + */ + + httpGet = new HttpGet(HOST_URL + "/engine/topics/sources/noop"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); - httpGet = new HttpGet(HOST_URL + "/engine/topics/sources/kafka/foobar/events"); + httpGet = new HttpGet(HOST_URL + "/engine/topics/sinks/noop"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); - assertEquals(500, response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); + assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); - httpGet = new HttpGet(HOST_URL + "/engine/topics/sinks/kafka/" + KAFKA_TOPIC + "/events"); + httpGet = new HttpGet(HOST_URL + "/engine/topics/sources/noop/" + NOOP_TOPIC); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); - httpGet = new HttpGet(HOST_URL + "/engine/topics/sinks/kafka/foobar/events"); + httpGet = new HttpGet(HOST_URL + "/engine/topics/sources/noop/foobar"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(500, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); - httpGet = new HttpGet(HOST_URL + "/engine/topics/sources/noop/" + NOOP_TOPIC + "/events"); + httpGet = new HttpGet(HOST_URL + "/engine/topics/sinks/noop/" + NOOP_TOPIC); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); - httpGet = new HttpGet(HOST_URL + "/engine/topics/sources/noop/foobar/events"); + httpGet = new HttpGet(HOST_URL + "/engine/topics/sinks/noop/foobar"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(500, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); - httpGet = new HttpGet(HOST_URL + "/engine/topics/sinks/noop/" + NOOP_TOPIC + "/events"); + httpGet = new HttpGet(HOST_URL + "/engine/topics/sources/noop/" + NOOP_TOPIC + "/events"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); - httpGet = new HttpGet(HOST_URL + "/engine/topics/sinks/noop/foobar/events"); + httpGet = new HttpGet(HOST_URL + "/engine/topics/sources/noop/foobar/events"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(500, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); - httpGet = new HttpGet(HOST_URL + "/engine/topics/sources/kafka/" + KAFKA_TOPIC + "/switches"); + httpGet = new HttpGet(HOST_URL + "/engine/topics/sinks/noop/" + NOOP_TOPIC + "/events"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); - httpGet = new HttpGet(HOST_URL + "/engine/topics/sources/noop/" + NOOP_TOPIC + "/switches"); + httpGet = new HttpGet(HOST_URL + "/engine/topics/sinks/noop/foobar/events"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); - assertEquals(200, response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); + assertEquals(500, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); - httpGet = new HttpGet(HOST_URL + "/engine/topics/sinks/kafka/" + KAFKA_TOPIC + "/switches"); + httpGet = new HttpGet(HOST_URL + "/engine/topics/sources/noop/" + NOOP_TOPIC + "/switches"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); httpGet = new HttpGet(HOST_URL + "/engine/topics/sinks/noop/" + NOOP_TOPIC + "/switches"); response = client.execute(httpGet); - logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); + logger.info("{} response code: {}", httpGet.getRequestLine(), response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); } diff --git a/policy-management/src/test/java/org/onap/policy/drools/stats/PolicyStatsManagerTest.java b/policy-management/src/test/java/org/onap/policy/drools/stats/PolicyStatsManagerTest.java index 118c4d7e..c13a4664 100644 --- a/policy-management/src/test/java/org/onap/policy/drools/stats/PolicyStatsManagerTest.java +++ b/policy-management/src/test/java/org/onap/policy/drools/stats/PolicyStatsManagerTest.java @@ -21,6 +21,7 @@ package org.onap.policy.drools.stats; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; @@ -42,4 +43,17 @@ class PolicyStatsManagerTest { assertEquals(1, stats.getSubgroupStats().get("foo").getPolicyExecutedFailCount()); assertEquals(2, stats.getSubgroupStats().get("blah").getPolicyExecutedFailCount()); } + + @Test + void test_Exceptions() { + PolicyStatsManager stats = new PolicyStatsManager(); + assertThatThrownBy(() -> stats.stat("foo", null)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("transaction is marked non-null but is nul"); + + Metric trans = new Metric(); + assertThatThrownBy(() -> stats.stat(null, trans)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("subGroupName is marked non-null but is null"); + } } \ No newline at end of file diff --git a/policy-management/src/test/java/org/onap/policy/drools/stats/PolicyStatsTest.java b/policy-management/src/test/java/org/onap/policy/drools/stats/PolicyStatsTest.java index 3f26e82e..6b76837d 100644 --- a/policy-management/src/test/java/org/onap/policy/drools/stats/PolicyStatsTest.java +++ b/policy-management/src/test/java/org/onap/policy/drools/stats/PolicyStatsTest.java @@ -22,6 +22,7 @@ package org.onap.policy.drools.stats; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; @@ -74,6 +75,14 @@ class PolicyStatsTest { assertThat(stats.getBirthTime()).isLessThanOrEqualTo(trans2.getStartTime().toEpochMilli()); } + @Test + void test_Exception() { + PolicyStats stats = new PolicyStats(); + assertThatThrownBy(() -> stats.stat(null)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("trans is marked non-null but is null"); + } + private Metric createTrans() { Metric trans = new Metric(); trans.setStartTime(null); diff --git a/policy-management/src/test/java/org/onap/policy/drools/system/PolicyControllerFactoryTest.java b/policy-management/src/test/java/org/onap/policy/drools/system/PolicyControllerFactoryTest.java index 615ffe2b..8a388dfc 100644 --- a/policy-management/src/test/java/org/onap/policy/drools/system/PolicyControllerFactoryTest.java +++ b/policy-management/src/test/java/org/onap/policy/drools/system/PolicyControllerFactoryTest.java @@ -35,7 +35,6 @@ import static org.mockito.Mockito.when; import static org.onap.policy.drools.properties.DroolsPropertyConstants.PROPERTY_CONTROLLER_TYPE; import java.util.Arrays; -import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Properties; @@ -504,9 +503,9 @@ class PolicyControllerFactoryTest { @Override public DroolsController beforeInstance(Properties properties, - String groupId, String artifactId, String version, - List decoderConfigurations, - List encoderConfigurations) { + String groupId, String artifactId, String version, + List decoderConfigurations, + List encoderConfigurations) { if (POLICY_CONTROLLER_BUILDER_TAG.equals(properties.getProperty(PROPERTY_CONTROLLER_TYPE))) { return new NullDroolsController(); diff --git a/policy-management/src/test/java/org/onap/policy/drools/system/PolicyEngineManagerTest.java b/policy-management/src/test/java/org/onap/policy/drools/system/PolicyEngineManagerTest.java index 8dae42e2..0b88b3f1 100644 --- a/policy-management/src/test/java/org/onap/policy/drools/system/PolicyEngineManagerTest.java +++ b/policy-management/src/test/java/org/onap/policy/drools/system/PolicyEngineManagerTest.java @@ -731,7 +731,7 @@ class PolicyEngineManagerTest { } @Test - void testUpdatePolicyController() throws Exception { + void testUpdatePolicyController_Exceptions() throws Exception { assertEquals(controller3, mgr.updatePolicyController(config3)); verify(engine).createPolicyController(CONTROLLER3, properties); @@ -775,7 +775,10 @@ class PolicyEngineManagerTest { setUp(); when(persist.getControllerProperties(CONTROLLER3)).thenThrow(new LinkageError(EXPECTED)); assertThatIllegalStateException().isThrownBy(() -> mgr.updatePolicyController(config3)); + } + @Test + void testUpdatePolicyController() throws Exception { /* * For remaining tests, the factory will return the controller instead of creating * one. @@ -954,14 +957,7 @@ class PolicyEngineManagerTest { assertTrue(mgr.stop()); verify(prov1).beforeStop(mgr); verify(prov2).beforeStop(mgr); - verify(controller, never()).stop(); - verify(source1, never()).stop(); - verify(sink1, never()).stop(); - verify(endpoint, never()).stop(); - verify(server1, never()).stop(); - verify(client1, never()).stop(); - verify(prov1, never()).afterStop(mgr); - verify(prov2, never()).afterStop(mgr); + verifyNeverCalled(); // controller fails to stop - still does everything testStop(false, () -> when(controller.stop()).thenReturn(false)); @@ -1999,6 +1995,17 @@ class PolicyEngineManagerTest { assertThatThrownBy(() -> verifyAfter.accept(prov2)).isInstanceOf(AssertionError.class); } + private void verifyNeverCalled() { + verify(controller, never()).stop(); + verify(source1, never()).stop(); + verify(sink1, never()).stop(); + verify(endpoint, never()).stop(); + verify(server1, never()).stop(); + verify(client1, never()).stop(); + verify(prov1, never()).afterStop(mgr); + verify(prov2, never()).afterStop(mgr); + } + /** * Manager with overrides. */ diff --git a/policy-management/src/test/java/org/onap/policy/drools/system/internal/FeatureLockImplTest.java b/policy-management/src/test/java/org/onap/policy/drools/system/internal/FeatureLockImplTest.java index 8a10c516..6d2380f0 100644 --- a/policy-management/src/test/java/org/onap/policy/drools/system/internal/FeatureLockImplTest.java +++ b/policy-management/src/test/java/org/onap/policy/drools/system/internal/FeatureLockImplTest.java @@ -213,22 +213,6 @@ class FeatureLockImplTest { verify(callback, never()).lockUnavailable(any()); } - /** - * Tests doNotify() when there is no session. - */ - @Test - void testDoNotifyNoSession() { - MyLock lock = new MyLock(LockState.WAITING, RESOURCE, OWNER_KEY, HOLD_SEC, callback); - lock.grant(); - - assertTrue(lock.isActive()); - assertEquals(1, lock.nupdates); - - invokeCallback(); - verify(callback).lockAvailable(any()); - verify(callback, never()).lockUnavailable(any()); - } - @Test void testFreeAllowed() { MyLock lock = new MyLock(LockState.WAITING, RESOURCE, OWNER_KEY, HOLD_SEC, callback); -- cgit 1.2.3-korg