Increase code coverage in policy-core and policy-utils 65/138965/2
authoradheli.tavares <adheli.tavares@est.tech>
Tue, 17 Sep 2024 13:19:51 +0000 (14:19 +0100)
committerAdheli Tavares <adheli.tavares@est.tech>
Fri, 20 Sep 2024 09:06:21 +0000 (09:06 +0000)
Issue-ID: POLICY-5068
Change-Id: I598b674fd623ff56c2e7b0316c114e7c270c2b3f
Signed-off-by: adheli.tavares <adheli.tavares@est.tech>
18 files changed:
policy-core/pom.xml
policy-core/src/main/java/org/onap/policy/drools/core/PolicyContainer.java
policy-core/src/test/java/org/onap/policy/drools/core/DroolsContainerTest.java
policy-core/src/test/java/org/onap/policy/drools/core/PolicyContainerTest.java [new file with mode: 0644]
policy-core/src/test/java/org/onap/policy/drools/core/PolicySessionFeatureApiMock.java
policy-core/src/test/java/org/onap/policy/drools/core/jmx/PdpJmxListenerTest.java [new file with mode: 0644]
policy-core/src/test/java/org/onap/policy/drools/core/lock/AlwaysFailLockTest.java
policy-core/src/test/java/org/onap/policy/drools/core/lock/AlwaysSuccessLockTest.java
policy-management/src/main/java/org/onap/policy/drools/system/internal/LockManager.java
policy-management/src/test/java/org/onap/policy/drools/controller/internal/NullDroolsControllerTest.java
policy-management/src/test/java/org/onap/policy/drools/system/PolicyEngineManagerTest.java
policy-utils/pom.xml
policy-utils/src/main/java/org/onap/policy/drools/metrics/Metric.java
policy-utils/src/main/java/org/onap/policy/drools/policies/DomainMaker.java
policy-utils/src/test/java/org/onap/policy/drools/metrics/MetricTest.java
policy-utils/src/test/java/org/onap/policy/drools/policies/DomainMakerTest.java
policy-utils/src/test/java/org/onap/policy/drools/utils/LookupTest.java [new file with mode: 0644]
policy-utils/src/test/java/org/onap/policy/drools/utils/PropertyUtilTest.java

index 57fd613..9eb0af1 100644 (file)
             <groupId>org.glassfish.hk2.external</groupId>
             <artifactId>jakarta.inject</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-test</artifactId>
+        </dependency>
     </dependencies>
 
 </project>
index ec5ceb2..533ac22 100644 (file)
@@ -28,6 +28,8 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.concurrent.ConcurrentHashMap;
 import lombok.Getter;
+import lombok.NonNull;
+import org.apache.commons.lang3.StringUtils;
 import org.kie.api.KieServices;
 import org.kie.api.builder.KieScanner;
 import org.kie.api.builder.Message;
@@ -49,13 +51,13 @@ public class PolicyContainer implements Startable {
     // get an instance of logger
     private static final Logger logger = LoggerFactory.getLogger(PolicyContainer.class);
     // 'KieServices' singleton
-    private static KieServices kieServices = KieServices.Factory.get();
+    private static final KieServices kieServices = KieServices.Factory.get();
 
     // set of all 'PolicyContainer' instances
     private static final HashSet<PolicyContainer> containers = new HashSet<>();
 
     // maps feature objects to per-PolicyContainer data
-    private ConcurrentHashMap<Object, Object> adjuncts = new ConcurrentHashMap<>();
+    private final ConcurrentHashMap<Object, Object> adjuncts = new ConcurrentHashMap<>();
 
     // 'KieContainer' associated with this 'PolicyContainer'
     @Getter
@@ -90,9 +92,9 @@ public class PolicyContainer implements Startable {
      *
      * <p>An exception occurs if the creation of the 'KieContainer' fails.
      *
-     * @param groupId the 'groupId' associated with the artifact
+     * @param groupId    the 'groupId' associated with the artifact
      * @param artifactId the artifact name
-     * @param version a comma-separated list of possible versions
+     * @param version    a comma-separated list of possible versions
      */
     public PolicyContainer(String groupId, String artifactId, String version) {
         this(kieServices.newReleaseId(groupId, artifactId, version));
@@ -112,7 +114,7 @@ public class PolicyContainer implements Startable {
         if (newReleaseId.getVersion().contains(",")) {
             // this is actually a comma-separated list of release ids
             newReleaseId =
-                    loadArtifact(newReleaseId.getGroupId(), newReleaseId.getArtifactId(), newReleaseId.getVersion());
+                loadArtifact(newReleaseId.getGroupId(), newReleaseId.getArtifactId(), newReleaseId.getVersion());
         } else {
             kieContainer = kieServices.newKieContainer(newReleaseId);
         }
@@ -138,9 +140,9 @@ public class PolicyContainer implements Startable {
      * Load an artifact into a new KieContainer. This method handles the case where the 'version' is
      * actually a comma-separated list of versions.
      *
-     * @param groupId the 'groupId' associated with the artifact
+     * @param groupId    the 'groupId' associated with the artifact
      * @param artifactId the artifact name
-     * @param version a comma-separated list of possible versions
+     * @param version    a comma-separated list of possible versions
      */
     private ReleaseId loadArtifact(String groupId, String artifactId, String version) {
         String[] versions = version.split(",");
@@ -180,15 +182,11 @@ public class PolicyContainer implements Startable {
     }
 
     /**
-     * Get name.
+     * Get name in the form of (groupId + ":" + artifactId + ":" + version)
+     * Note that the name changes after a successful call to 'updateToVersion', although
+     * typically only the 'version' part changes.
      *
-     * @return the name of the container, which is the String equivalent of the 'ReleaseId'. It has
-     *         the form:
-     *
-     *         (groupId + ":" + artifactId + ":" + version)
-     *
-     *         Note that the name changes after a successful call to 'updateToVersion', although
-     *         typically only the 'version' part changes.
+     * @return the name of the container, which is the String equivalent of the 'ReleaseId'.
      */
     public String getName() {
         return kieContainer.getReleaseId().toString();
@@ -204,7 +202,7 @@ public class PolicyContainer implements Startable {
     }
 
     /**
-     * Get group Id.
+     * Get group id.
      *
      * @return the Maven GroupId of the top-level artifact wrapped by the container.
      */
@@ -235,7 +233,7 @@ public class PolicyContainer implements Startable {
      * Fetch the named 'PolicySession'.
      *
      * @param name the name of the KieSession (which is also the name of the associated
-     *        PolicySession)
+     *             PolicySession)
      * @return a PolicySession if found, 'null' if not
      */
     public PolicySession getPolicySession(String name) {
@@ -245,7 +243,7 @@ public class PolicyContainer implements Startable {
     /**
      * Internal method to create a PolicySession, possibly restoring it from persistent storage.
      *
-     * @param name of the KieSession and PolicySession
+     * @param name        of the KieSession and PolicySession
      * @param kieBaseName name of the associated 'KieBase' instance
      * @return a new or existing PolicySession, or 'null' if not found
      */
@@ -255,7 +253,7 @@ public class PolicyContainer implements Startable {
             PolicySession session = sessions.computeIfAbsent(name, key -> makeSession(name, kieBaseName));
 
             logger.info("activatePolicySession:session - {} is returned.",
-                            session == null ? "null" : session.getFullName());
+                session == null ? "null" : session.getFullName());
             return session;
         }
     }
@@ -307,30 +305,32 @@ public class PolicyContainer implements Startable {
      * provides a way for 'KieSession' instances that are created programmatically to fit into this
      * framework.
      *
-     * @param name the name for the new 'PolicySession'
+     * @param name       the name for the new 'PolicySession'
      * @param kieSession a 'KieSession' instance, that will be included in this infrastructure
      * @return the new 'PolicySession'
      * @throws IllegalArgumentException if 'kieSession' does not reside within this container
-     * @throws IllegalStateException if a 'PolicySession' already exists with this name
+     * @throws IllegalStateException    if a 'PolicySession' already exists with this name
      */
     public PolicySession adoptKieSession(String name, KieSession kieSession) {
 
-        if (name == null) {
+        if (StringUtils.isBlank(name)) {
             logger.warn("adoptKieSession:input name is null");
             throw new IllegalArgumentException("KieSession input name is null " + getName());
-        } else if (kieSession == null) {
+        }
+
+        if (kieSession == null) {
             logger.warn("adoptKieSession:input kieSession is null");
             throw new IllegalArgumentException("KieSession '" + name + "' is null " + getName());
-        } else {
-            logger.info("adoptKieSession:name: {} kieSession: {}", name, kieSession);
         }
+
+        logger.info("adoptKieSession:name: {} kieSession: {}", name, kieSession);
         // fetch KieBase, and verify it belongs to this KieContainer
         var match = false;
         var kieBase = kieSession.getKieBase();
         logger.info("adoptKieSession:kieBase: {}", kieBase);
         for (String kieBaseName : kieContainer.getKieBaseNames()) {
             logger.info("adoptKieSession:kieBaseName: {}", kieBaseName);
-            if (kieBase == kieContainer.getKieBase(kieBaseName)) {
+            if (kieBase.equals(kieContainer.getKieBase(kieBaseName))) {
                 match = true;
                 break;
             }
@@ -338,9 +338,9 @@ public class PolicyContainer implements Startable {
         logger.info("adoptKieSession:match {}", match);
         // if we don't have a match yet, the last chance is to look at the
         // default KieBase, if it exists
-        if (!match && kieBase != kieContainer.getKieBase()) {
+        if (!match && !kieBase.equals(kieContainer.getKieBase())) {
             throw new IllegalArgumentException(
-                    "KieSession '" + name + "' does not reside within container " + getName());
+                "KieSession '" + name + "' does not reside within container " + getName());
         }
 
         synchronized (sessions) {
@@ -370,15 +370,13 @@ public class PolicyContainer implements Startable {
      * This call 'KieContainer.updateToVersion()', and returns the associated response as a String.
      * If successful, the name of this 'PolicyContainer' changes to match the new version.
      *
-     * @param newVersion this is the version to update to (the 'groupId' and 'artifactId' remain the
-     *        same)
-     * @return the list of messages associated with the update (not sure if this can be 'null', or
-     *         how to determine success/failure)
+     * @param newVersion this is the version to update to ('groupId' and 'artifactId' remain the same)
+     * @return the list of messages associated with the update
      */
     public String updateToVersion(String newVersion) {
         var releaseId = kieContainer.getReleaseId();
-        var results = this.updateToVersion(
-                kieServices.newReleaseId(releaseId.getGroupId(), releaseId.getArtifactId(), newVersion));
+        var results = this.updateToVersion(kieServices.newReleaseId(releaseId.getGroupId(),
+            releaseId.getArtifactId(), newVersion));
 
         List<Message> messages = results == null ? null : results.getMessages();
         return messages == null ? null : messages.toString();
@@ -455,46 +453,46 @@ public class PolicyContainer implements Startable {
      *
      * @param releaseId the release id used to create the container
      */
-    public synchronized void startScanner(ReleaseId releaseId) {
+    public synchronized void startScanner(@NonNull ReleaseId releaseId) {
         String version = releaseId.getVersion();
 
-        if (scannerStarted || scanner != null || version == null) {
+        if (!isValidVersion(version)) {
+            logger.warn("version is invalid - check if empty or if it's not LATEST, RELEASE or SNAPSHOT");
             return;
         }
 
-        if (!("LATEST".equals(version) || "RELEASE".equals(version) || version.endsWith("-SNAPSHOT"))) {
+        if (isScannerStarted()) {
+            logger.warn("scanner already started");
             return;
         }
 
         // create the scanner, and poll at 60 second intervals
-        try {
-            scannerStarted = true;
 
-            // start this in a separate thread -- it can block for a long time
-            new Thread("Scanner Starter " + getName()) {
-                @Override
-                public void run() {
+        scannerStarted = true;
+
+        // start this in a separate thread -- it can block for a long time
+        new Thread("Scanner Starter " + getName()) {
+            @Override
+            public void run() {
+                try {
                     scanner = kieServices.newKieScanner(kieContainer);
                     scanner.start(60000L);
+                } catch (Exception e) {
+                    // sometimes the scanner initialization fails for some reason
+                    logger.error("startScanner error", e);
                 }
-            }.start();
-        } catch (Exception e) {
-            // sometimes the scanner initialization fails for some reason
-            logger.error("startScanner error", e);
-        }
+            }
+        }.start();
     }
 
     /**
      * Insert a fact into a specific named session.
      *
-     * @param name this is the session name
+     * @param name   this is the session name
      * @param object this is the fact to be inserted into the session
      * @return 'true' if the named session was found, 'false' if not
      */
     public boolean insert(String name, Object object) {
-        // TODO: Should the definition of 'name' be expanded to include an
-        // alternate entry point as well? For example, 'name.entryPoint' (or
-        // something other than '.' if that is a problem).
         synchronized (sessions) {
             PolicySession session = sessions.get(name);
             if (session != null) {
@@ -568,7 +566,7 @@ public class PolicyContainer implements Startable {
         Collection<PolicySession> localSessions;
 
         synchronized (sessions) {
-            // local set containing all of the sessions
+            // local set containing all the sessions
             localSessions = new HashSet<>(sessions.values());
 
             // clear the 'name->session' map in 'PolicyContainer'
@@ -631,7 +629,7 @@ public class PolicyContainer implements Startable {
         Collection<PolicySession> localSessions;
 
         synchronized (sessions) {
-            // local set containing all of the sessions
+            // local set containing all the sessions
             localSessions = new HashSet<>(sessions.values());
 
             // clear the 'name->session' map in 'PolicyContainer'
@@ -667,7 +665,7 @@ public class PolicyContainer implements Startable {
      * This method is called when the host goes from the 'standby->active' state.
      */
     public static void activate() {
-        // start all of the 'PolicyContainer' instances
+        // start all the 'PolicyContainer' instances
         for (PolicyContainer container : containers) {
             try {
                 container.start();
@@ -681,7 +679,7 @@ public class PolicyContainer implements Startable {
      * This method is called when the host goes from the 'active->standby' state.
      */
     public static void deactivate() {
-        // deactivate all of the 'PolicyContainer' instances
+        // deactivate all the 'PolicyContainer' instances
         for (PolicyContainer container : containers) {
             try {
                 container.stop();
@@ -694,7 +692,7 @@ public class PolicyContainer implements Startable {
     /**
      * This method does the following:
      *
-     * <p>1) Initializes logging 2) Starts the DroolsPDP Integrity Monitor 3) Initilaizes persistence
+     * <p>1) Initializes logging 2) Starts the DroolsPDP Integrity Monitor 3) Initializes persistence
      *
      * <p>It no longer reads in properties files, o creates 'PolicyContainer' instances.
      *
@@ -718,7 +716,7 @@ public class PolicyContainer implements Startable {
      * Fetch the adjunct object associated with a given feature.
      *
      * @param object this is typically the singleton feature object that is used as a key, but it
-     *        might also be useful to use nested objects within the feature as keys.
+     *               might also be useful to use nested objects within the feature as keys.
      * @return a feature-specific object associated with the key, or 'null' if it is not found.
      */
     public Object getAdjunct(Object object) {
@@ -729,9 +727,9 @@ public class PolicyContainer implements Startable {
      * Store the adjunct object associated with a given feature.
      *
      * @param object this is typically the singleton feature object that is used as a key, but it
-     *        might also be useful to use nested objects within the feature as keys.
-     * @param value a feature-specific object associated with the key, or 'null' if the
-     *        feature-specific object should be removed
+     *               might also be useful to use nested objects within the feature as keys.
+     * @param value  a feature-specific object associated with the key, or 'null' if the
+     *               feature-specific object should be removed
      */
     public void setAdjunct(Object object, Object value) {
         if (value == null) {
@@ -768,4 +766,33 @@ public class PolicyContainer implements Startable {
             KieUtils.addKiePackages(kieContainer.getKieBase(name), kiePackages);
         }
     }
+
+    /**
+     * Checks if boolean scannerStarted is true and if scanner itself is not null.
+     *
+     * @return true if the above is all true, false otherwise.
+     */
+    public boolean isScannerStarted() {
+        return scannerStarted || scanner != null;
+    }
+
+    /**
+     * Validation of a release version for starting a scanner.
+     * Can be valid if LATEST, RELEASE or SNAPSHOT version.
+     *
+     * @param version release version
+     * @return true if valid based on values above, false otherwise.
+     */
+    protected boolean isValidVersion(String version) {
+        if (StringUtils.isBlank(version)) {
+            logger.warn("version is empty");
+            return false;
+        }
+
+        if (version.toUpperCase().contains("LATEST") || version.toUpperCase().contains("RELEASE")) {
+            return true;
+        } else {
+            return version.toUpperCase().endsWith("-SNAPSHOT");
+        }
+    }
 }
index abed972..d6804b6 100644 (file)
@@ -79,44 +79,7 @@ public class DroolsContainerTest {
      */
     @Test
     void createAndUpdate() throws Exception {
-        // make sure feature log starts out clean
-        PolicySessionFeatureApiMock.getLog();
-
-        // run 'globalInit', and verify expected feature hook fired
-        PolicyContainer.globalInit(new String[0]);
-        assertEquals(List.of("globalInit"),
-                PolicySessionFeatureApiMock.getLog());
-
-        // initial conditions -- there should be no containers
-        assertEquals(0, PolicyContainer.getPolicyContainers().size());
-
-        // create the container, and start it
-        PolicyContainer container =
-                new PolicyContainer("org.onap.policy.drools-pdp",
-                        "drools-artifact1", "17.1.0-SNAPSHOT");
-        container.start();
-        assertTrue(container.isAlive());
-
-        // verify expected feature hooks fired
-        assertEquals(Arrays.asList("activatePolicySession",
-                "newPolicySession",
-                "selectThreadModel"),
-                PolicySessionFeatureApiMock.getLog());
-
-        // this container should be on the list
-        {
-            Collection<PolicyContainer> containers =
-                    PolicyContainer.getPolicyContainers();
-            assertEquals(1, containers.size());
-            assertTrue(containers.contains(container));
-        }
-
-        // verify initial container attributes
-        assertEquals("org.onap.policy.drools-pdp:drools-artifact1:17.1.0-SNAPSHOT",
-                container.getName());
-        assertEquals("org.onap.policy.drools-pdp", container.getGroupId());
-        assertEquals("drools-artifact1", container.getArtifactId());
-        assertEquals("17.1.0-SNAPSHOT", container.getVersion());
+        PolicyContainer container = validateCreatedContainer();
 
         try {
             // fetch the session, and verify that it exists
@@ -225,20 +188,17 @@ public class DroolsContainerTest {
 
         // run 'globalInit', and verify expected feature hook fired
         PolicyContainer.globalInit(new String[0]);
-        assertEquals(List.of("globalInit-exception"),
-                PolicySessionFeatureApiMock.getLog());
+        assertEquals(List.of("globalInit-exception"), PolicySessionFeatureApiMock.getLog());
 
         // initial conditions -- there should be no containers
         assertEquals(0, PolicyContainer.getPolicyContainers().size());
 
-        String versionList =
-                "17.3.0-SNAPSHOT,17.1.0-SNAPSHOT,17.2.0-SNAPSHOT";
+        String versionList = "17.3.0-SNAPSHOT,17.1.0-SNAPSHOT,17.2.0-SNAPSHOT";
 
         // versions should be tried in order -- the 17.1.0-SNAPSHOT should "win",
         // given the fact that '17.3.0-SNAPSHOT' doesn't exist
         PolicyContainer container =
-                new PolicyContainer("org.onap.policy.drools-pdp",
-                        "drools-artifact1", versionList);
+                new PolicyContainer("org.onap.policy.drools-pdp", "drools-artifact1", versionList);
         // the following should be equivalent to 'container.start()'
         PolicyContainer.activate();
         assertTrue(container.isAlive());
@@ -251,15 +211,12 @@ public class DroolsContainerTest {
 
         // this container should be on the list
         {
-            Collection<PolicyContainer> containers =
-                    PolicyContainer.getPolicyContainers();
-            assertEquals(1, containers.size());
-            assertTrue(containers.contains(container));
+            Collection<PolicyContainer> containers = PolicyContainer.getPolicyContainers();
+            assertTrue(containers.contains(container) && (containers.size() == 1));
         }
 
         // verify initial container attributes
-        assertEquals("org.onap.policy.drools-pdp:drools-artifact1:17.1.0-SNAPSHOT",
-                container.getName());
+        assertEquals("org.onap.policy.drools-pdp:drools-artifact1:17.1.0-SNAPSHOT", container.getName());
         assertEquals("org.onap.policy.drools-pdp", container.getGroupId());
         assertEquals("drools-artifact1", container.getArtifactId());
         assertEquals("17.1.0-SNAPSHOT", container.getVersion());
@@ -288,8 +245,7 @@ public class DroolsContainerTest {
             // get all sessions, and verify that this one is the only one
             {
                 Collection<PolicySession> sessions = container.getPolicySessions();
-                assertEquals(1, sessions.size());
-                assertTrue(sessions.contains(session));
+                assertTrue(sessions.contains(session) && (1 == sessions.size()));
             }
 
             // verify session attributes
@@ -341,4 +297,50 @@ public class DroolsContainerTest {
         // final conditions -- there should be no containers
         assertEquals(0, PolicyContainer.getPolicyContainers().size());
     }
+
+    /**
+     * Creates a policy container.
+     * @return a container used on create and update test
+     */
+    private static PolicyContainer validateCreatedContainer() {
+        // make sure feature log starts out clean
+        PolicySessionFeatureApiMock.getLog();
+
+        // run 'globalInit', and verify expected feature hook fired
+        PolicyContainer.globalInit(new String[0]);
+        assertEquals(List.of("globalInit"),
+            PolicySessionFeatureApiMock.getLog());
+
+        // initial conditions -- there should be no containers
+        assertEquals(0, PolicyContainer.getPolicyContainers().size());
+
+        // create the container, and start it
+        PolicyContainer container =
+            new PolicyContainer("org.onap.policy.drools-pdp",
+                "drools-artifact1", "17.1.0-SNAPSHOT");
+        container.start();
+        assertTrue(container.isAlive());
+
+        // verify expected feature hooks fired
+        assertEquals(Arrays.asList("activatePolicySession",
+                "newPolicySession",
+                "selectThreadModel"),
+            PolicySessionFeatureApiMock.getLog());
+
+        // this container should be on the list
+        {
+            Collection<PolicyContainer> containers =
+                PolicyContainer.getPolicyContainers();
+            assertEquals(1, containers.size());
+            assertTrue(containers.contains(container));
+        }
+
+        // verify initial container attributes
+        assertEquals("org.onap.policy.drools-pdp:drools-artifact1:17.1.0-SNAPSHOT",
+            container.getName());
+        assertEquals("org.onap.policy.drools-pdp", container.getGroupId());
+        assertEquals("drools-artifact1", container.getArtifactId());
+        assertEquals("17.1.0-SNAPSHOT", container.getVersion());
+        return container;
+    }
 }
diff --git a/policy-core/src/test/java/org/onap/policy/drools/core/PolicyContainerTest.java b/policy-core/src/test/java/org/onap/policy/drools/core/PolicyContainerTest.java
new file mode 100644 (file)
index 0000000..72c8d2d
--- /dev/null
@@ -0,0 +1,230 @@
+/*-
+ * ============LICENSE_START================================================
+ * policy-core
+ * =========================================================================
+ * 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.core;
+
+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.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
+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 org.junit.jupiter.api.Test;
+import org.kie.api.KieBase;
+import org.kie.api.KieServices;
+import org.kie.api.builder.KieScanner;
+import org.kie.api.builder.ReleaseId;
+import org.kie.api.event.rule.AgendaEventListener;
+import org.kie.api.event.rule.RuleRuntimeEventListener;
+import org.kie.api.runtime.KieContainer;
+import org.kie.api.runtime.KieSession;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+import org.springframework.test.util.ReflectionTestUtils;
+
+class PolicyContainerTest {
+
+    private static final String VERSION = "1.0.0";
+
+    @Test
+    void adoptKieSession_Exceptions() {
+        var mockKieSession = mock(KieSession.class);
+        var policyContainer = mock(PolicyContainer.class);
+
+        when(policyContainer.getName()).thenReturn("kieReleaseName");
+        when(policyContainer.adoptKieSession(any(), eq(mockKieSession))).thenCallRealMethod();
+        when(policyContainer.adoptKieSession("name", null)).thenCallRealMethod();
+
+        assertThatThrownBy(() -> policyContainer.adoptKieSession("", mockKieSession))
+            .isInstanceOf(IllegalArgumentException.class)
+            .hasMessageContaining("KieSession input name is null kieReleaseName");
+
+        assertThatThrownBy(() -> policyContainer.adoptKieSession(null, mockKieSession))
+            .isInstanceOf(IllegalArgumentException.class)
+            .hasMessageContaining("KieSession input name is null kieReleaseName");
+
+        assertThatThrownBy(() -> policyContainer.adoptKieSession("name", null))
+            .isInstanceOf(IllegalArgumentException.class)
+            .hasMessageContaining("KieSession 'name' is null kieReleaseName");
+    }
+
+    @Test
+    void testAdoptKieSession() {
+        var mockKieSession = mock(KieSession.class);
+        doNothing().when(mockKieSession).addEventListener(any(AgendaEventListener.class));
+        doNothing().when(mockKieSession).addEventListener(any(RuleRuntimeEventListener.class));
+
+        var policyContainer = mock(PolicyContainer.class);
+        when(policyContainer.adoptKieSession("name", mockKieSession)).thenCallRealMethod();
+        when(policyContainer.getName()).thenReturn("kieReleaseName");
+
+        var mockKieBase = mock(KieBase.class);
+        when(mockKieSession.getKieBase()).thenReturn(mockKieBase);
+
+        var mockKieContainer = mock(KieContainer.class);
+        when(policyContainer.getKieContainer()).thenReturn(mockKieContainer);
+        when(mockKieContainer.getKieBase("baseName")).thenReturn(mockKieBase);
+        when(mockKieContainer.getKieBaseNames()).thenReturn(List.of("baseName"));
+        when(mockKieContainer.getKieBase()).thenReturn(mockKieBase);
+
+        HashMap<String, PolicySession> sessions = new HashMap<>();
+        ReflectionTestUtils.setField(policyContainer, "sessions", sessions);
+        ReflectionTestUtils.setField(policyContainer, "kieContainer", mockKieContainer);
+
+        assertNotNull(policyContainer.adoptKieSession("name", mockKieSession));
+        assertThatThrownBy(() -> policyContainer.adoptKieSession("name", mockKieSession))
+            .isInstanceOf(IllegalStateException.class)
+            .hasMessageContaining("PolicySession 'name' already exists");
+    }
+
+    @Test
+    void testAdoptKieSession_KieBaseDoesntMatch() {
+        var mockKieSession = mock(KieSession.class);
+
+        var policyContainer = mock(PolicyContainer.class);
+        when(policyContainer.adoptKieSession("name", mockKieSession)).thenCallRealMethod();
+        when(policyContainer.getName()).thenReturn("kieReleaseName");
+
+        var mockKieBase = mock(KieBase.class);
+        when(mockKieSession.getKieBase()).thenReturn(mockKieBase);
+        var mockKieBase2 = mock(KieBase.class);
+
+        var mockKieContainer = mock(KieContainer.class);
+        when(policyContainer.getKieContainer()).thenReturn(mockKieContainer);
+        when(mockKieContainer.getKieBase("baseName")).thenReturn(mockKieBase2);
+        when(mockKieContainer.getKieBaseNames()).thenReturn(List.of("baseName"));
+        when(mockKieContainer.getKieBase()).thenReturn(mockKieBase2);
+
+        ReflectionTestUtils.setField(policyContainer, "kieContainer", mockKieContainer);
+
+        assertThatThrownBy(() -> policyContainer.adoptKieSession("name", mockKieSession))
+            .isInstanceOf(IllegalArgumentException.class)
+            .hasMessageContaining("KieSession 'name' does not reside within container kieReleaseName");
+    }
+
+    @Test
+    void startScanner_Exceptions() {
+        var policyContainer = mock(PolicyContainer.class);
+        doCallRealMethod().when(policyContainer).startScanner(any(ReleaseId.class));
+        doCallRealMethod().when(policyContainer).startScanner(isNull());
+        when(policyContainer.isScannerStarted()).thenCallRealMethod();
+
+        assertThatThrownBy(() -> policyContainer.startScanner(null))
+            .hasMessageContaining("releaseId is marked non-null but is null");
+        assertFalse(policyContainer.isScannerStarted());
+
+        // shouldn't throw exception, but won't start scanner as version is null
+        var mockVersionNull = mock(ReleaseId.class);
+        when(mockVersionNull.getVersion()).thenReturn(null);
+        when(policyContainer.isValidVersion(isNull())).thenCallRealMethod();
+        assertDoesNotThrow(() -> policyContainer.startScanner(mockVersionNull));
+        assertFalse(policyContainer.isScannerStarted());
+
+        var mockVersionSnapshot = mock(ReleaseId.class);
+        when(mockVersionSnapshot.getVersion()).thenReturn(VERSION);
+        when(policyContainer.isValidVersion(VERSION)).thenCallRealMethod();
+        assertDoesNotThrow(() -> policyContainer.startScanner(mockVersionSnapshot));
+        assertFalse(policyContainer.isScannerStarted());
+    }
+
+    @Test
+    void startScanner_SnapshotVersion() {
+        var policyContainer = mock(PolicyContainer.class);
+        when(policyContainer.isScannerStarted()).thenCallRealMethod();
+        when(policyContainer.isValidVersion(VERSION + "-SNAPSHOT")).thenCallRealMethod();
+
+        var mockVersionSnapshot = mock(ReleaseId.class);
+        when(mockVersionSnapshot.getVersion()).thenReturn(VERSION + "-SNAPSHOT");
+
+        doCallRealMethod().when(policyContainer).startScanner(mockVersionSnapshot);
+
+        assertDoesNotThrow(() -> policyContainer.startScanner(mockVersionSnapshot));
+        assertTrue(policyContainer.isScannerStarted());
+    }
+
+    @Test
+    void startScanner_LatestVersion() {
+        var policyContainer = mock(PolicyContainer.class);
+        when(policyContainer.isScannerStarted()).thenCallRealMethod();
+        when(policyContainer.isValidVersion(anyString())).thenCallRealMethod();
+
+        var mockLatestVersion = mock(ReleaseId.class);
+        when(mockLatestVersion.getVersion()).thenReturn(VERSION + "LATEST");
+
+        doCallRealMethod().when(policyContainer).startScanner(mockLatestVersion);
+
+        assertDoesNotThrow(() -> policyContainer.startScanner(mockLatestVersion));
+        assertTrue(policyContainer.isScannerStarted());
+    }
+
+    @Test
+    void startScanner_ReleaseVersion() {
+        var mockKieServices = mock(KieServices.class);
+        when(mockKieServices.newKieScanner(any(KieContainer.class))).thenReturn(mock(KieScanner.class));
+
+        try (MockedStatic<KieServices.Factory> factory = Mockito.mockStatic(KieServices.Factory.class)) {
+            factory.when(KieServices.Factory::get).thenReturn(mockKieServices);
+            assertEquals(mockKieServices, KieServices.Factory.get());
+
+            var policyContainer = mock(PolicyContainer.class);
+            when(policyContainer.isScannerStarted()).thenCallRealMethod();
+            when(policyContainer.isValidVersion(VERSION + "RELEASE")).thenCallRealMethod();
+
+            var mockLatestVersion = mock(ReleaseId.class);
+            when(mockLatestVersion.getVersion()).thenReturn(VERSION + "RELEASE");
+
+            doCallRealMethod().when(policyContainer).startScanner(mockLatestVersion);
+
+            assertDoesNotThrow(() -> policyContainer.startScanner(mockLatestVersion));
+            assertTrue(policyContainer.isScannerStarted());
+
+            // try again, but should come out at checking if scanner is already started.
+            assertDoesNotThrow(() -> policyContainer.startScanner(mockLatestVersion));
+        }
+    }
+
+    @Test
+    void insert() {
+        var policyContainer = mock(PolicyContainer.class);
+        var object = new Object();
+        when(policyContainer.insert("name", object)).thenCallRealMethod();
+
+        HashMap<String, PolicySession> sessions = new HashMap<>();
+        ReflectionTestUtils.setField(policyContainer, "sessions", sessions);
+
+        assertFalse(policyContainer.insert("name", object));
+    }
+
+    @Test
+    void deactivate() {
+        assertDoesNotThrow(PolicyContainer::deactivate);
+    }
+}
\ No newline at end of file
index d825706..f0e5b51 100644 (file)
@@ -86,6 +86,7 @@ public class PolicySessionFeatureApiMock implements PolicySessionFeatureApi {
     /**
      * {@inheritDoc}.
      */
+    @Override
     public void globalInit(String[] args, String configDir) {
         addLog("globalInit");
     }
@@ -93,6 +94,7 @@ public class PolicySessionFeatureApiMock implements PolicySessionFeatureApi {
     /**
      * {@inheritDoc}.
      */
+    @Override
     public KieSession activatePolicySession(PolicyContainer policyContainer, String name, String kieBaseName) {
         addLog("activatePolicySession");
         return null;
@@ -101,6 +103,7 @@ public class PolicySessionFeatureApiMock implements PolicySessionFeatureApi {
     /**
      * {@inheritDoc}.
      */
+    @Override
     public void newPolicySession(PolicySession policySession) {
         addLog("newPolicySession");
     }
@@ -108,6 +111,7 @@ public class PolicySessionFeatureApiMock implements PolicySessionFeatureApi {
     /**
      * {@inheritDoc}.
      */
+    @Override
     public PolicySession.ThreadModel selectThreadModel(PolicySession session) {
         addLog("selectThreadModel");
         return null;
@@ -116,6 +120,7 @@ public class PolicySessionFeatureApiMock implements PolicySessionFeatureApi {
     /**
      * {@inheritDoc}.
      */
+    @Override
     public void disposeKieSession(PolicySession policySession) {
         addLog("disposeKieSession");
     }
@@ -123,6 +128,7 @@ public class PolicySessionFeatureApiMock implements PolicySessionFeatureApi {
     /**
      * {@inheritDoc}.
      */
+    @Override
     public void destroyKieSession(PolicySession policySession) {
         addLog("destroyKieSession");
     }
diff --git a/policy-core/src/test/java/org/onap/policy/drools/core/jmx/PdpJmxListenerTest.java b/policy-core/src/test/java/org/onap/policy/drools/core/jmx/PdpJmxListenerTest.java
new file mode 100644 (file)
index 0000000..d81dc3e
--- /dev/null
@@ -0,0 +1,66 @@
+/*-
+ * ============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.core.jmx;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.lang.management.ManagementFactory;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanRegistrationException;
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.NotCompliantMBeanException;
+import javax.management.ObjectName;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+
+class PdpJmxListenerTest {
+
+    @Test
+    void test() {
+        Assertions.assertDoesNotThrow(PdpJmxListener::start);
+        Assertions.assertDoesNotThrow(PdpJmxListener::stop);
+    }
+
+    @Test
+    void testExceptions()
+        throws MalformedObjectNameException, NotCompliantMBeanException, InstanceAlreadyExistsException,
+        MBeanRegistrationException, InstanceNotFoundException {
+
+        var mockMBean = Mockito.mock(MBeanServer.class);
+        Mockito.doThrow(MBeanRegistrationException.class).when(mockMBean)
+            .registerMBean(PdpJmx.getInstance(), new ObjectName("PolicyEngine:type=PdpJmx"));
+        Mockito.doThrow(MBeanRegistrationException.class).when(mockMBean)
+            .unregisterMBean(new ObjectName("PolicyEngine:type=PdpJmx"));
+
+        // trying to reach exception catch clause, but can't validate if exception was thrown
+        try (MockedStatic<ManagementFactory> factory = Mockito.mockStatic(ManagementFactory.class)) {
+            factory.when(ManagementFactory::getPlatformMBeanServer).thenReturn(mockMBean);
+            assertEquals(mockMBean, ManagementFactory.getPlatformMBeanServer());
+
+            Assertions.assertDoesNotThrow(PdpJmxListener::start);
+            Assertions.assertDoesNotThrow(PdpJmxListener::stop);
+        }
+    }
+}
\ No newline at end of file
index 51273d7..02c3fea 100644 (file)
@@ -22,6 +22,7 @@
 package org.onap.policy.drools.core.lock;
 
 import static org.assertj.core.api.Assertions.assertThatCode;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.Mockito.mock;
@@ -52,4 +53,9 @@ class AlwaysFailLockTest extends AlwaysLockBaseTest<AlwaysFailLock> {
         assertFalse(lock.free());
         assertTrue(lock.isUnavailable());
     }
+
+    @Test
+    void testExtend() {
+        assertDoesNotThrow(() -> lock.extend(10, callback));
+    }
 }
index 80f81f9..0104d0a 100644 (file)
@@ -25,6 +25,7 @@ import static org.assertj.core.api.Assertions.assertThatCode;
 import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.Mockito.mock;
 
@@ -67,4 +68,28 @@ class AlwaysSuccessLockTest extends AlwaysLockBaseTest<AlwaysSuccessLock> {
         assertEquals(HOLD_SEC2, lock.getHoldSec());
         assertSame(callback2, lock.getCallback());
     }
+
+    @Test
+    void testNullArgs() {
+        assertThrows(NullPointerException.class,
+            () -> new AlwaysSuccessLock(null, RESOURCE, OWNER_KEY, HOLD_SEC, callback));
+
+        assertThrows(NullPointerException.class,
+            () -> new AlwaysSuccessLock(LockState.WAITING, null, OWNER_KEY, HOLD_SEC, callback));
+
+        assertThrows(NullPointerException.class,
+            () -> new AlwaysSuccessLock(LockState.WAITING, RESOURCE, null, HOLD_SEC, callback));
+
+        assertThrows(NullPointerException.class,
+            () -> new AlwaysSuccessLock(LockState.WAITING, RESOURCE, OWNER_KEY, HOLD_SEC, null));
+
+        assertThrows(NullPointerException.class,
+            () -> new AlwaysSuccessLock(null, OWNER_KEY, HOLD_SEC, callback));
+
+        assertThrows(NullPointerException.class,
+            () -> new AlwaysSuccessLock(RESOURCE, null, HOLD_SEC, callback));
+
+        assertThrows(NullPointerException.class,
+            () -> new AlwaysSuccessLock(RESOURCE, OWNER_KEY, HOLD_SEC, null));
+    }
 }
index 1683b0f..fa26442 100644 (file)
@@ -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.
@@ -122,7 +123,7 @@ public abstract class LockManager<T extends FeatureLockImpl> implements PolicyRe
     /**
      * After performing checks, this invokes
      * {@link #makeLock(LockState, String, String, int, LockCallback)} to create a lock
-     * object, inserts it into the map, and then invokes {@link #finishLock(MgrLock)}.
+     * object, inserts it into the map, and then invokes {@link #finishLock(FeatureLockImpl)}.
      */
     @Override
     public Lock createLock(String resourceId, String ownerKey, int holdSec, LockCallback callback,
index f61412d..ccefcc6 100644 (file)
@@ -22,6 +22,7 @@
 package org.onap.policy.drools.controller.internal;
 
 import static org.assertj.core.api.Assertions.assertThatCode;
+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;
@@ -36,32 +37,35 @@ import org.onap.policy.drools.controller.DroolsControllerConstants;
 
 class NullDroolsControllerTest {
 
+    private final NullDroolsController controller = new NullDroolsController();
+    private static final String NULL_EXCEPTION = "marked non-null but is null";
+
     @Test
     void testStart() {
-        DroolsController controller = new NullDroolsController();
-        controller.start();
-        assertFalse(controller.isAlive());
-        controller.stop();
-        assertFalse(controller.isAlive());
-        controller.shutdown();
-        assertFalse(controller.isAlive());
-        controller.halt();
-        assertFalse(controller.isAlive());
+        DroolsController controller1 = new NullDroolsController();
+        controller1.start();
+        assertFalse(controller1.isAlive());
+        controller1.stop();
+        assertFalse(controller1.isAlive());
+        controller1.shutdown();
+        assertFalse(controller1.isAlive());
+        controller1.halt();
+        assertFalse(controller1.isAlive());
     }
 
     @Test
     void testSerialize() {
         assertThatCode(() -> new GsonTestUtils().compareGson(new NullDroolsController(),
-                        NullDroolsControllerTest.class)).doesNotThrowAnyException();
+            NullDroolsControllerTest.class)).doesNotThrowAnyException();
     }
 
     @Test
     void testLock() {
-        DroolsController controller = new NullDroolsController();
-        controller.lock();
-        assertFalse(controller.isLocked());
-        controller.unlock();
-        assertFalse(controller.isLocked());
+        DroolsController controller1 = new NullDroolsController();
+        controller1.lock();
+        assertFalse(controller1.isLocked());
+        controller1.unlock();
+        assertFalse(controller1.isLocked());
     }
 
     @Test
@@ -81,78 +85,75 @@ class NullDroolsControllerTest {
 
     @Test
     void getSessionNames() {
-        assertTrue(new NullDroolsController().getSessionNames().isEmpty());
+        assertTrue(controller.getSessionNames().isEmpty());
     }
 
     @Test
     void getCanonicalSessionNames() {
-        assertTrue(new NullDroolsController().getCanonicalSessionNames().isEmpty());
+        assertTrue(controller.getCanonicalSessionNames().isEmpty());
     }
 
     @Test
     void offer() {
-        assertFalse(new NullDroolsController().offer(null, null));
+        assertFalse(controller.offer(null, null));
+        assertFalse(controller.offer(null));
     }
 
     @Test
     void deliver() {
-        var controller = new NullDroolsController();
         assertThrows(IllegalStateException.class, () -> controller.deliver(null, null));
     }
 
     @Test
     void getRecentSourceEvents() {
-        assertEquals(0, new NullDroolsController().getRecentSourceEvents().length);
+        assertEquals(0, controller.getRecentSourceEvents().length);
     }
 
     @Test
     void getRecentSinkEvents() {
-        assertEquals(0, new NullDroolsController().getRecentSinkEvents().length);
+        assertEquals(0, controller.getRecentSinkEvents().length);
     }
 
     @Test
     void getContainer() {
-        assertNull(new NullDroolsController().getContainer());
+        assertNull(controller.getContainer());
     }
 
     @Test
     void getDomains() {
-        assertTrue(new NullDroolsController().getBaseDomainNames().isEmpty());
+        assertTrue(controller.getBaseDomainNames().isEmpty());
     }
 
     @Test
     void ownsCoder() {
-        var controller = new NullDroolsController();
         assertThrows(IllegalStateException.class, () -> controller.ownsCoder(null, 0));
     }
 
     @Test
     void fetchModelClass() {
-        var controller = new NullDroolsController();
         var className = this.getClass().getName();
         assertThrows(IllegalArgumentException.class, () -> controller.fetchModelClass(className));
     }
 
     @Test
     void isBrained() {
-        assertFalse(new NullDroolsController().isBrained());
+        assertFalse(controller.isBrained());
     }
 
     @Test
     void stringify() {
-        assertNotNull(new NullDroolsController().toString());
+        assertNotNull(controller.toString());
     }
 
     @Test
     void updateToVersion() {
-        var controller = new NullDroolsController();
         assertThrows(IllegalArgumentException.class, () ->
             controller.updateToVersion(null, null, null, null, null));
     }
 
     @Test
     void factClassNames() {
-        assertTrue(new NullDroolsController().factClassNames(null).isEmpty());
+        assertTrue(controller.factClassNames(null).isEmpty());
     }
 
     @Test
@@ -162,18 +163,40 @@ class NullDroolsControllerTest {
 
     @Test
     void facts() {
-        assertTrue(new NullDroolsController().facts(null, null, true).isEmpty());
+        assertTrue(controller.facts(null, null, true).isEmpty());
+        assertTrue(controller.facts("sessionName", Object.class).isEmpty());
+
+        assertThatThrownBy(() -> controller.facts(null, Object.class)).hasMessageContaining(NULL_EXCEPTION);
+        assertThatThrownBy(() -> controller.facts("sessionName", null)).hasMessageContaining(NULL_EXCEPTION);
     }
 
     @Test
     void factQuery() {
-        assertTrue(new NullDroolsController().factQuery(null, null, null, false).isEmpty());
+        assertTrue(controller.factQuery(null, null, null, false).isEmpty());
     }
 
     @Test
     void exists() {
         Object o1 = new Object();
-        assertFalse(new NullDroolsController().exists("blah", o1));
-        assertFalse(new NullDroolsController().exists(o1));
+        assertFalse(controller.exists("blah", o1));
+        assertFalse(controller.exists(o1));
+
+        assertThatThrownBy(() -> controller.exists("blah", null)).hasMessageContaining(NULL_EXCEPTION);
+        assertThatThrownBy(() -> controller.exists(null, o1)).hasMessageContaining(NULL_EXCEPTION);
+        assertThatThrownBy(() -> controller.exists(null)).hasMessageContaining(NULL_EXCEPTION);
+    }
+
+    @Test
+    void testDelete() {
+        assertThatThrownBy(() -> controller.delete("sessionName", null)).hasMessageContaining(NULL_EXCEPTION);
+        assertThatThrownBy(() -> controller.delete(null, Object.class)).hasMessageContaining(NULL_EXCEPTION);
+        assertThatThrownBy(() -> controller.delete(null)).hasMessageContaining(NULL_EXCEPTION);
+        Object o1 = null;
+        assertThatThrownBy(() -> controller.delete(o1)).hasMessageContaining(NULL_EXCEPTION);
+
+        assertFalse(controller.delete("sessionName", new Object()));
+        assertFalse(controller.delete("sessionName", Object.class));
+        assertFalse(controller.delete(new Object()));
+        assertFalse(controller.delete(Object.class));
     }
 }
index 0b88b3f..138ad9f 100644 (file)
@@ -102,7 +102,7 @@ class PolicyEngineManagerTest {
     private static final Object MY_EVENT = new Object();
 
     private static final GsonTestUtils gson = new GsonMgmtTestBuilder().addTopicSourceMock().addTopicSinkMock()
-                    .addHttpServletServerMock().build();
+        .addHttpServletServerMock().build();
 
     private Properties properties;
     private PolicyEngineFeatureApi prov1;
@@ -579,30 +579,34 @@ class PolicyEngineManagerTest {
         verify(prov1).afterConfigure(mgr);
         verify(prov2).afterConfigure(mgr);
 
+        // other tests
+        checkBeforeAfter(
+            (prov, flag) -> when(prov.beforeConfigure(mgr, properties)).thenReturn(flag),
+            (prov, flag) -> when(prov.afterConfigure(mgr)).thenReturn(flag),
+            () -> mgr.configure(properties),
+            prov -> verify(prov).beforeConfigure(mgr, properties),
+            () -> assertSame(properties, mgr.getProperties()),
+            prov -> verify(prov).afterConfigure(mgr));
+    }
+
+    @Test
+    void testConfigureProperties_InvalidProperties() throws Exception {
         // middle stuff throws exception - still calls afterXxx
-        setUp();
         when(endpoint.addTopicSources(properties)).thenThrow(new IllegalArgumentException(EXPECTED));
         when(endpoint.addTopicSinks(properties)).thenThrow(new IllegalArgumentException(EXPECTED));
         when(serverFactory.build(properties)).thenThrow(new IllegalArgumentException(EXPECTED));
         when(clientFactory.build(properties)).thenThrow(new IllegalArgumentException(EXPECTED));
         mgr.configure(properties);
         verify(prov2).afterConfigure(mgr);
+    }
 
+    @Test
+    void testConfigureProperties_NullProperties() {
         // null properties - nothing should be invoked
-        setUp();
         Properties nullProps = null;
         assertThatIllegalArgumentException().isThrownBy(() -> mgr.configure(nullProps));
         verify(prov1, never()).beforeConfigure(mgr, properties);
         verify(prov1, never()).afterConfigure(mgr);
-
-        // other tests
-        checkBeforeAfter(
-            (prov, flag) -> when(prov.beforeConfigure(mgr, properties)).thenReturn(flag),
-            (prov, flag) -> when(prov.afterConfigure(mgr)).thenReturn(flag),
-            () -> mgr.configure(properties),
-            prov -> verify(prov).beforeConfigure(mgr, properties),
-            () -> assertSame(properties, mgr.getProperties()),
-            prov -> verify(prov).afterConfigure(mgr));
     }
 
     @Test
@@ -631,17 +635,8 @@ class PolicyEngineManagerTest {
     }
 
     @Test
-    void testCreatePolicyController() throws Exception {
-        assertEquals(controller, mgr.createPolicyController(MY_NAME, properties));
-
-        verify(contProv1).beforeCreate(MY_NAME, properties);
-        verify(contProv2).beforeCreate(MY_NAME, properties);
-        verify(controller, never()).lock();
-        verify(contProv1).afterCreate(controller);
-        verify(contProv2).afterCreate(controller);
-
+    void testCreatePolicy_FirstProviderThrowsException() {
         // first provider throws exceptions - same result
-        setUp();
         when(contProv1.beforeCreate(MY_NAME, properties)).thenThrow(new RuntimeException(EXPECTED));
         when(contProv1.afterCreate(controller)).thenThrow(new RuntimeException(EXPECTED));
         assertEquals(controller, mgr.createPolicyController(MY_NAME, properties));
@@ -651,17 +646,11 @@ class PolicyEngineManagerTest {
         verify(controller, never()).lock();
         verify(contProv1).afterCreate(controller);
         verify(contProv2).afterCreate(controller);
+    }
 
-        // locked - same result, but engine locked
-        setUp();
-        mgr.lock();
-        assertEquals(controller, mgr.createPolicyController(MY_NAME, properties));
-        verify(contProv1).beforeCreate(MY_NAME, properties);
-        verify(controller, times(2)).lock();
-        verify(contProv2).afterCreate(controller);
-
+    @Test
+    void testCreatePolicyController_InvalidProperties() throws Exception {
         // empty name in properties - same result
-        setUp();
         properties.setProperty(DroolsPropertyConstants.PROPERTY_CONTROLLER_NAME, "");
         assertEquals(controller, mgr.createPolicyController(MY_NAME, properties));
         verify(contProv1).beforeCreate(MY_NAME, properties);
@@ -677,6 +666,25 @@ class PolicyEngineManagerTest {
         properties.setProperty(DroolsPropertyConstants.PROPERTY_CONTROLLER_NAME, "mistmatched-name");
         assertThatIllegalStateException().isThrownBy(() -> mgr.createPolicyController(MY_NAME, properties));
         verify(contProv1, never()).beforeCreate(MY_NAME, properties);
+    }
+
+    @Test
+    void testCreatePolicyController() throws Exception {
+        assertEquals(controller, mgr.createPolicyController(MY_NAME, properties));
+
+        verify(contProv1).beforeCreate(MY_NAME, properties);
+        verify(contProv2).beforeCreate(MY_NAME, properties);
+        verify(controller, never()).lock();
+        verify(contProv1).afterCreate(controller);
+        verify(contProv2).afterCreate(controller);
+
+        // locked - same result, but engine locked
+        setUp();
+        mgr.lock();
+        assertEquals(controller, mgr.createPolicyController(MY_NAME, properties));
+        verify(contProv1).beforeCreate(MY_NAME, properties);
+        verify(controller, times(2)).lock();
+        verify(contProv2).afterCreate(controller);
 
         // first provider generates controller - stops after first provider
         setUp();
@@ -902,7 +910,7 @@ class PolicyEngineManagerTest {
      * Tests the start() method, after setting some option.
      *
      * @param expectedResult what start() is expected to return
-     * @param setOption function that sets an option
+     * @param setOption      function that sets an option
      * @throws Throwable if an error occurs during setup
      */
     private void testStart(boolean expectedResult, RunnableWithEx setOption) throws Throwable {
@@ -1004,7 +1012,7 @@ class PolicyEngineManagerTest {
      * Tests the stop() method, after setting some option.
      *
      * @param expectedResult what stop() is expected to return
-     * @param setOption function that sets an option
+     * @param setOption      function that sets an option
      * @throws Throwable if an error occurs during setup
      */
     private void testStop(boolean expectedResult, RunnableWithEx setOption) throws Throwable {
@@ -1211,7 +1219,7 @@ class PolicyEngineManagerTest {
      * Tests the lock() method, after setting some option.
      *
      * @param expectedResult what lock() is expected to return
-     * @param setOption function that sets an option
+     * @param setOption      function that sets an option
      * @throws Throwable if an error occurs during setup
      */
     private void testLock(boolean expectedResult, RunnableWithEx setOption) throws Throwable {
@@ -1287,7 +1295,7 @@ class PolicyEngineManagerTest {
      * Tests the unlock() method, after setting some option.
      *
      * @param expectedResult what unlock() is expected to return
-     * @param setOption function that sets an option
+     * @param setOption      function that sets an option
      * @throws Throwable if an error occurs during setup
      */
     private void testUnlock(boolean expectedResult, RunnableWithEx setOption) throws Throwable {
@@ -1411,8 +1419,8 @@ class PolicyEngineManagerTest {
         assertEquals(1, mgr.getStats().getSubgroupStats().get(CONTROLLOOP).getPolicyExecutedFailCount());
 
         Summary.Child.Value summary =
-                PolicyEngineManagerImpl.transLatencySecsSummary
-                        .labels(CONTROLLER1, CONTROLLOOP, POLICY, PdpResponseStatus.FAIL.name()).get();
+            PolicyEngineManagerImpl.transLatencySecsSummary
+                .labels(CONTROLLER1, CONTROLLOOP, POLICY, PdpResponseStatus.FAIL.name()).get();
 
         assertEquals(0, summary.count, 0.0);
         assertEquals(0, summary.sum, 0.0);
@@ -1423,8 +1431,8 @@ class PolicyEngineManagerTest {
         mgr.transaction(CONTROLLER1, CONTROLLOOP, metric);
 
         summary =
-                PolicyEngineManagerImpl.transLatencySecsSummary
-                        .labels(CONTROLLER1, CONTROLLOOP, POLICY, PdpResponseStatus.FAIL.name()).get();
+            PolicyEngineManagerImpl.transLatencySecsSummary
+                .labels(CONTROLLER1, CONTROLLOOP, POLICY, PdpResponseStatus.FAIL.name()).get();
 
         assertEquals(1, summary.count, 0.0);
         assertEquals(5, summary.sum, 0.0);
@@ -1553,7 +1561,7 @@ class PolicyEngineManagerTest {
         mgr.start();
         when(sink1.send(any())).thenThrow(new ArithmeticException(EXPECTED));
         assertThatThrownBy(() -> mgr.deliver(CommInfrastructure.NOOP, MY_TOPIC, MY_EVENT))
-                        .isInstanceOf(ArithmeticException.class);
+            .isInstanceOf(ArithmeticException.class);
 
         /*
          * For remaining tests, have the controller handle delivery.
@@ -1610,7 +1618,7 @@ class PolicyEngineManagerTest {
 
         // unknown topic
         assertThatIllegalStateException()
-                        .isThrownBy(() -> mgr.deliver(CommInfrastructure.NOOP, "unknown-topic", MESSAGE));
+            .isThrownBy(() -> mgr.deliver(CommInfrastructure.NOOP, "unknown-topic", MESSAGE));
 
         // locked
         mgr.lock();
@@ -1737,7 +1745,7 @@ class PolicyEngineManagerTest {
 
         // not configured yet, thus no lock manager
         assertThatIllegalStateException()
-                        .isThrownBy(() -> mgr.createLock(MY_RESOURCE, MY_OWNER, 10, callback, false));
+            .isThrownBy(() -> mgr.createLock(MY_RESOURCE, MY_OWNER, 10, callback, false));
 
         // now configure it and try again
         mgr.configure(properties);
@@ -1745,14 +1753,14 @@ class PolicyEngineManagerTest {
 
         // test illegal args
         assertThatThrownBy(() -> mgr.createLock(null, MY_OWNER, 10, callback, false))
-                        .hasMessageContaining("resourceId");
+            .hasMessageContaining("resourceId");
         assertThatThrownBy(() -> mgr.createLock(MY_RESOURCE, null, 10, callback, false))
-                        .hasMessageContaining("ownerKey");
+            .hasMessageContaining("ownerKey");
         assertThatIllegalArgumentException()
-                        .isThrownBy(() -> mgr.createLock(MY_RESOURCE, MY_OWNER, -1, callback, false))
-                        .withMessageContaining("holdSec");
+            .isThrownBy(() -> mgr.createLock(MY_RESOURCE, MY_OWNER, -1, callback, false))
+            .withMessageContaining("holdSec");
         assertThatThrownBy(() -> mgr.createLock(MY_RESOURCE, MY_OWNER, 10, null, false))
-                        .hasMessageContaining("callback");
+            .hasMessageContaining("callback");
     }
 
     @Test
@@ -1850,19 +1858,19 @@ class PolicyEngineManagerTest {
      * Performs an operation that has a beforeXxx method and an afterXxx method. Tries
      * combinations where beforeXxx and afterXxx return {@code true} and {@code false}.
      *
-     * @param setBefore function to set the return value of a provider's beforeXxx method
-     * @param setAfter function to set the return value of a provider's afterXxx method
-     * @param action invokes the operation
+     * @param setBefore    function to set the return value of a provider's beforeXxx method
+     * @param setAfter     function to set the return value of a provider's afterXxx method
+     * @param action       invokes the operation
      * @param verifyBefore verifies that a provider's beforeXxx method was invoked
      * @param verifyMiddle verifies that the action occurring between the beforeXxx loop
-     *        and the afterXxx loop was invoked
-     * @param verifyAfter verifies that a provider's afterXxx method was invoked
+     *                     and the afterXxx loop was invoked
+     * @param verifyAfter  verifies that a provider's afterXxx method was invoked
      * @throws Exception if an error occurs while calling {@link #setUp()}
      */
     private void checkBeforeAfter(BiConsumer<PolicyEngineFeatureApi, Boolean> setBefore,
-                    BiConsumer<PolicyEngineFeatureApi, Boolean> setAfter, Runnable action,
-                    Consumer<PolicyEngineFeatureApi> verifyBefore, Runnable verifyMiddle,
-                    Consumer<PolicyEngineFeatureApi> verifyAfter) throws Exception {
+                                  BiConsumer<PolicyEngineFeatureApi, Boolean> setAfter, Runnable action,
+                                  Consumer<PolicyEngineFeatureApi> verifyBefore, Runnable verifyMiddle,
+                                  Consumer<PolicyEngineFeatureApi> verifyAfter) throws Exception {
 
         checkBeforeAfter_FalseFalse(setBefore, setAfter, action, verifyBefore, verifyMiddle, verifyAfter);
         checkBeforeAfter_FalseTrue(setBefore, setAfter, action, verifyBefore, verifyMiddle, verifyAfter);
@@ -1875,19 +1883,19 @@ class PolicyEngineManagerTest {
      * Performs an operation that has a beforeXxx method and an afterXxx method. Tries the
      * case where both the beforeXxx and afterXxx methods return {@code false}.
      *
-     * @param setBefore function to set the return value of a provider's beforeXxx method
-     * @param setAfter function to set the return value of a provider's afterXxx method
-     * @param action invokes the operation
+     * @param setBefore    function to set the return value of a provider's beforeXxx method
+     * @param setAfter     function to set the return value of a provider's afterXxx method
+     * @param action       invokes the operation
      * @param verifyBefore verifies that a provider's beforeXxx method was invoked
      * @param verifyMiddle verifies that the action occurring between the beforeXxx loop
-     *        and the afterXxx loop was invoked
-     * @param verifyAfter verifies that a provider's afterXxx method was invoked
+     *                     and the afterXxx loop was invoked
+     * @param verifyAfter  verifies that a provider's afterXxx method was invoked
      * @throws Exception if an error occurs while calling {@link #setUp()}
      */
     private void checkBeforeAfter_FalseFalse(BiConsumer<PolicyEngineFeatureApi, Boolean> setBefore,
-                    BiConsumer<PolicyEngineFeatureApi, Boolean> setAfter, Runnable action,
-                    Consumer<PolicyEngineFeatureApi> verifyBefore, Runnable verifyMiddle,
-                    Consumer<PolicyEngineFeatureApi> verifyAfter) throws Exception {
+                                             BiConsumer<PolicyEngineFeatureApi, Boolean> setAfter, Runnable action,
+                                             Consumer<PolicyEngineFeatureApi> verifyBefore, Runnable verifyMiddle,
+                                             Consumer<PolicyEngineFeatureApi> verifyAfter) throws Exception {
 
         setUp();
 
@@ -1916,19 +1924,19 @@ class PolicyEngineManagerTest {
      * case where the first provider's afterXxx returns {@code true}, while the others
      * return {@code false}.
      *
-     * @param setBefore function to set the return value of a provider's beforeXxx method
-     * @param setAfter function to set the return value of a provider's afterXxx method
-     * @param action invokes the operation
+     * @param setBefore    function to set the return value of a provider's beforeXxx method
+     * @param setAfter     function to set the return value of a provider's afterXxx method
+     * @param action       invokes the operation
      * @param verifyBefore verifies that a provider's beforeXxx method was invoked
      * @param verifyMiddle verifies that the action occurring between the beforeXxx loop
-     *        and the afterXxx loop was invoked
-     * @param verifyAfter verifies that a provider's afterXxx method was invoked
+     *                     and the afterXxx loop was invoked
+     * @param verifyAfter  verifies that a provider's afterXxx method was invoked
      * @throws Exception if an error occurs while calling {@link #setUp()}
      */
     private void checkBeforeAfter_FalseTrue(BiConsumer<PolicyEngineFeatureApi, Boolean> setBefore,
-                    BiConsumer<PolicyEngineFeatureApi, Boolean> setAfter, Runnable action,
-                    Consumer<PolicyEngineFeatureApi> verifyBefore, Runnable verifyMiddle,
-                    Consumer<PolicyEngineFeatureApi> verifyAfter) throws Exception {
+                                            BiConsumer<PolicyEngineFeatureApi, Boolean> setAfter, Runnable action,
+                                            Consumer<PolicyEngineFeatureApi> verifyBefore, Runnable verifyMiddle,
+                                            Consumer<PolicyEngineFeatureApi> verifyAfter) throws Exception {
 
         setUp();
 
@@ -1957,19 +1965,19 @@ class PolicyEngineManagerTest {
      * case where the first provider's beforeXxx returns {@code true}, while the others
      * return {@code false}.
      *
-     * @param setBefore function to set the return value of a provider's beforeXxx method
-     * @param setAfter function to set the return value of a provider's afterXxx method
-     * @param action invokes the operation
+     * @param setBefore    function to set the return value of a provider's beforeXxx method
+     * @param setAfter     function to set the return value of a provider's afterXxx method
+     * @param action       invokes the operation
      * @param verifyBefore verifies that a provider's beforeXxx method was invoked
      * @param verifyMiddle verifies that the action occurring between the beforeXxx loop
-     *        and the afterXxx loop was invoked
-     * @param verifyAfter verifies that a provider's afterXxx method was invoked
+     *                     and the afterXxx loop was invoked
+     * @param verifyAfter  verifies that a provider's afterXxx method was invoked
      * @throws Exception if an error occurs while calling {@link #setUp()}
      */
     private void checkBeforeAfter_TrueFalse(BiConsumer<PolicyEngineFeatureApi, Boolean> setBefore,
-                    BiConsumer<PolicyEngineFeatureApi, Boolean> setAfter, Runnable action,
-                    Consumer<PolicyEngineFeatureApi> verifyBefore, Runnable verifyMiddle,
-                    Consumer<PolicyEngineFeatureApi> verifyAfter) throws Exception {
+                                            BiConsumer<PolicyEngineFeatureApi, Boolean> setAfter, Runnable action,
+                                            Consumer<PolicyEngineFeatureApi> verifyBefore, Runnable verifyMiddle,
+                                            Consumer<PolicyEngineFeatureApi> verifyAfter) throws Exception {
 
         setUp();
 
index 319711a..09c4e14 100644 (file)
@@ -70,5 +70,9 @@
             <groupId>net.jimblackler.jsonschemafriend</groupId>
             <artifactId>core</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-test</artifactId>
+        </dependency>
     </dependencies>
 </project>
index 01ff58f..c275521 100644 (file)
@@ -3,6 +3,7 @@
  * ONAP
  * ================================================================================
  * Copyright (C) 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.
@@ -134,8 +135,7 @@ public class Metric {
         }
 
         if (endTime != null && startTime != null) {
-            this.elapsedTime =
-                    Duration.between(startTime, endTime).toMillis();
+            this.elapsedTime = Duration.between(startTime, endTime).toMillis();
             return;
         }
 
index 84c81cf..27dfee4 100644 (file)
@@ -31,7 +31,6 @@ import org.onap.policy.common.utils.coder.StandardCoder;
 import org.onap.policy.common.utils.resources.ResourceUtils;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
-import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyType;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -70,7 +69,7 @@ public class DomainMaker {
             return false;
         }
 
-        return validators.get(policyType).isConformant(json);
+        return getValidator(policyType).isConformant(json);
     }
 
     /**
@@ -94,7 +93,7 @@ public class DomainMaker {
         }
 
         try {
-            return validators.get(policyType).encode(domainPolicy) != null;
+            return getValidator(policyType).encode(domainPolicy) != null;
         } catch (CoderException e) {
             logger.info("policy {}:{} is not conformant", policyType, domainPolicy.getClass().getName(), e);
             return false;
@@ -116,7 +115,7 @@ public class DomainMaker {
         }
 
         try {
-            validators.get(policy.getTypeIdentifier()).conformance(rawPolicy);
+            getValidator(policy.getTypeIdentifier()).conformance(rawPolicy);
         } catch (CoderException e) {
             logger.error("policy {}:{}:{} is not conformant",
                 policy.getTypeIdentifier(), policy.getName(), policy.getVersion(), e);
@@ -137,7 +136,7 @@ public class DomainMaker {
         }
 
         try {
-            validators.get(policyType).encode(domainPolicy);
+            getValidator(policyType).encode(domainPolicy);
         } catch (CoderException e) {
             logger.error("policy {}:{} is not conformant", policyType, domainPolicy.getClass().getName(), e);
             return false;
@@ -190,29 +189,21 @@ public class DomainMaker {
     public <T> T convertTo(@NonNull ToscaConceptIdentifier policyType, @NonNull String json, @NonNull Class<T> clazz)
         throws CoderException {
         if (isRegistered(policyType)) {
-            return validators.get(policyType).decode(json, clazz);
+            return getValidator(policyType).decode(json, clazz);
         } else {
             return nonValCoder.decode(json, clazz);
         }
     }
 
-    /**
-     * Converts a Tosca Policy Type specification to a domain-specific json specification.
-     */
-    public String convertToSchema(@NonNull ToscaPolicyType policyType) {
-        //
-        // TODO:   // NOSONAR
-        // 1. Convert Tosca Policy Type definition schema to suitable json schema.
-        // 2. Call registerValidator to register
-        throw new UnsupportedOperationException("schema generation from policy type is not supported");
-    }
-
     public boolean isRegistered(@NonNull ToscaConceptIdentifier policyType) {
         return validators.containsKey(policyType) || registerValidator(policyType);
     }
 
+    private StandardValCoder getValidator(ToscaConceptIdentifier policyType) {
+        return validators.get(policyType);
+    }
 
-    private String serialize(@NonNull ToscaPolicy policy) {
+    private String serialize(ToscaPolicy policy) {
         String rawPolicy = null;
         try {
             rawPolicy = nonValCoder.encode(policy);
index 924d1c9..f1999cc 100644 (file)
@@ -48,12 +48,12 @@ class MetricTest {
     void testPojo() {
         PojoClass metric = PojoClassFactory.getPojoClass(Metric.class);
         Validator val = ValidatorBuilder
-                .create()
-                .with(new SetterMustExistRule())
-                .with(new GetterMustExistRule())
-                .with(new SetterTester())
-                .with(new GetterTester())
-                .build();
+            .create()
+            .with(new SetterMustExistRule())
+            .with(new GetterMustExistRule())
+            .with(new SetterTester())
+            .with(new GetterTester())
+            .build();
         val.validate(metric);
     }
 
@@ -190,4 +190,24 @@ class MetricTest {
         Instant now = Instant.now();
         assertEquals(new SimpleDateFormat(Metric.DATE_FORMAT).format(Date.from(now)), Metric.toTimestamp(now));
     }
+
+    @Test
+    void testElapsedTime_EndTimeStartTimeNullValues() {
+        // test seems unnecessary, but when setElapsedTime receives null,
+        // the method tries to calculate elapsed time between start and end time,
+        // which only having the values was covered.
+        Metric metric = new Metric();
+
+        metric.setElapsedTime(null);
+        assertNull(metric.getElapsedTime());
+
+        metric.setEndTime(Instant.now());
+        metric.setElapsedTime(null);
+        assertNull(metric.getElapsedTime());
+
+        metric = new Metric();
+        metric.setStartTime(Instant.now());
+        metric.setElapsedTime(null);
+        assertNull(metric.getElapsedTime());
+    }
 }
\ No newline at end of file
index f8ffa50..8fbf237 100644 (file)
@@ -26,6 +26,8 @@ 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.mock;
+import static org.mockito.Mockito.when;
 
 import java.io.IOException;
 import java.nio.file.Files;
@@ -40,7 +42,7 @@ import org.onap.policy.drools.models.domains.a.Nested;
 import org.onap.policy.drools.models.domains.a.Properties;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
-import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyType;
+import org.springframework.test.util.ReflectionTestUtils;
 
 class DomainMakerTest {
 
@@ -62,6 +64,13 @@ class DomainMakerTest {
 
         policyTypeId.setVersion("2.0.0");
         assertFalse(domainMaker.isConformant(policyTypeId, rawJsonPolicyType));
+
+        // for code coverage
+        assertThatThrownBy(() -> domainMaker.isConformant(null, "{\"json\":\"valid\"}"))
+            .hasMessageContaining("policyType is marked non-null but is null");
+
+        assertThatThrownBy(() -> domainMaker.isConformant(policyTypeId, null))
+            .hasMessageContaining("json is marked non-null but is null");
     }
 
     @Test
@@ -93,6 +102,12 @@ class DomainMakerTest {
         // not registered schema for policy type
         policyTypeId.setVersion("2.0.0");
         assertFalse(domainMaker.isDomainConformant(policyTypeId, domainAPolicy));
+
+        assertThatThrownBy(() -> domainMaker.isDomainConformant(null, domainAPolicy))
+            .hasMessageContaining("policyType is marked non-null but is null");
+
+        assertThatThrownBy(() -> domainMaker.isDomainConformant(policyTypeId, null))
+            .hasMessageContaining("domainPolicy is marked non-null but is null");
     }
 
 
@@ -117,6 +132,12 @@ class DomainMakerTest {
         policy2.setTypeVersion("4.2.5");
         assertFalse(domainMaker.conformance(policy2));
         assertFalse(domainMaker.conformance(policy2.getTypeIdentifier(), domainAPolicy));
+
+        assertThatThrownBy(() -> domainMaker.conformance(null, domainAPolicy))
+            .hasMessageContaining("policyType is marked non-null but is null");
+
+        assertThatThrownBy(() -> domainMaker.conformance(null))
+            .hasMessageContaining("policy is marked non-null but is null");
     }
 
     @Test
@@ -136,6 +157,15 @@ class DomainMakerTest {
         assertFalse(domainMaker.isConformant(policy));
 
         assertFalse(domainMaker.registerValidator(policy.getTypeIdentifier(), "$schema"));
+
+        assertThatThrownBy(() -> domainMaker.registerValidator(null))
+            .hasMessageContaining("policyType is marked non-null but is null");
+
+        assertThatThrownBy(() -> domainMaker.registerValidator(null, "$schema"))
+            .hasMessageContaining("policyType is marked non-null but is null");
+
+        assertThatThrownBy(() -> domainMaker.registerValidator(policy.getTypeIdentifier(), null))
+            .hasMessageContaining("schema is marked non-null but is null");
     }
 
     @Test
@@ -146,14 +176,21 @@ class DomainMakerTest {
 
         assertNotNull(domainMaker.convertTo(getToscaPolicy("src/test/resources/policyA-no-policy-type.json"),
             DomainAPolicy.class));
-    }
 
-    @Test
-    void testConvertToSchema() {
-        ToscaPolicyType type = new ToscaPolicyType();
-        assertThatThrownBy(() -> domainMaker
-            .convertToSchema(type))
-            .isInstanceOf(UnsupportedOperationException.class);
+        assertThatThrownBy(() -> domainMaker.convertTo(null, DomainAPolicy.class))
+            .hasMessageContaining("toscaPolicy is marked non-null but is null");
+
+        assertThatThrownBy(() -> domainMaker.convertTo(mock(ToscaPolicy.class), null))
+            .hasMessageContaining("clazz is marked non-null but is null");
+
+        assertThatThrownBy(() -> domainMaker.convertTo(null, "json", DomainAPolicy.class))
+            .hasMessageContaining("policyType is marked non-null but is null");
+
+        assertThatThrownBy(() -> domainMaker.convertTo(mock(ToscaConceptIdentifier.class), null, DomainAPolicy.class))
+            .hasMessageContaining("json is marked non-null but is null");
+
+        assertThatThrownBy(() -> domainMaker.convertTo(mock(ToscaConceptIdentifier.class), "json", null))
+            .hasMessageContaining("clazz is marked non-null but is null");
     }
 
     @Test
@@ -166,6 +203,25 @@ class DomainMakerTest {
             new ToscaConceptIdentifier("policy.type.external", "7.7.9");
         assertFalse(domainMaker.isRegistered(policyTypeId2));
 
+        assertThatThrownBy(() -> domainMaker.isRegistered(null))
+            .hasMessageContaining("policyType is marked non-null but is null");
+    }
+
+    @Test
+    void testIsConformant_SerializeReturnsNull() throws CoderException {
+        var mockDomainMaker = mock(DomainMaker.class);
+        var mockToscaPolicy = mock(ToscaPolicy.class);
+        when(mockDomainMaker.isConformant(mockToscaPolicy)).thenCallRealMethod();
+
+        var mockCoder = mock(StandardCoder.class);
+        when(mockCoder.encode(mockToscaPolicy)).thenThrow(new CoderException("error"));
+        ReflectionTestUtils.setField(mockDomainMaker, "nonValCoder", mockCoder);
+
+        assertFalse(mockDomainMaker.isConformant(mockToscaPolicy));
+
+        when(mockDomainMaker.conformance(mockToscaPolicy)).thenCallRealMethod();
+        when(mockDomainMaker.isRegistered(mockToscaPolicy.getTypeIdentifier())).thenReturn(true);
+        assertFalse(mockDomainMaker.conformance(mockToscaPolicy));
     }
 
     private String getJsonFromFile(String filePath) throws IOException {
diff --git a/policy-utils/src/test/java/org/onap/policy/drools/utils/LookupTest.java b/policy-utils/src/test/java/org/onap/policy/drools/utils/LookupTest.java
new file mode 100644 (file)
index 0000000..dd043b4
--- /dev/null
@@ -0,0 +1,57 @@
+/*-
+ * ============LICENSE_START================================================
+ * 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.utils;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
+import org.onap.policy.common.utils.security.CryptoCoder;
+
+class LookupTest {
+
+    @Test
+    void testCryptoLookup() {
+        var cryptoCoder = new CryptoCoderValueLookup(new CryptoCoder() {
+            @Override
+            public String encrypt(String s) {
+                return String.valueOf(s.hashCode());
+            }
+
+            @Override
+            public String decrypt(String s) {
+                return s;
+            }
+        });
+
+        assertTrue(cryptoCoder.lookup("hello").startsWith("enc"));
+        assertNull(cryptoCoder.lookup(null));
+        assertNull(cryptoCoder.lookup(""));
+    }
+
+    @Test
+    void testEnvDefaultLookup() {
+        var envLookup = new EnvironmentVariableWithDefaultLookup();
+
+        assertNull(envLookup.lookup(null));
+        assertNull(envLookup.lookup(""));
+        assertEquals("", envLookup.lookup(":"));
+    }
+}
\ No newline at end of file
index f2676e5..bec2223 100644 (file)
@@ -22,6 +22,8 @@
 package org.onap.policy.drools.utils;
 
 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.assertTrue;
 
 import java.io.File;
@@ -93,7 +95,8 @@ public class PropertyUtilTest {
 
         // create a directory for temporary files
         directory = new File(UUID.randomUUID().toString());
-        directory.mkdir();
+        var isDirCreated = directory.mkdir();
+        logger.info("directory created: {}", isDirCreated);
     }
 
     /**
@@ -141,8 +144,7 @@ public class PropertyUtilTest {
             public void propertiesChanged(Properties properties, Set<String> changedKeys) {
                 // When a notification is received, store the values in the
                 // 'returns' array, and signal using the same array.
-                logger.info("Listener invoked: properties=" + properties
-                        + ", changedKeys=" + changedKeys);
+                logger.info("Listener invoked: properties={}, changedKeys={}", properties, changedKeys);
                 returns[0] = properties;
                 returns[1] = changedKeys;
                 synchronized (returns) {
@@ -181,6 +183,73 @@ public class PropertyUtilTest {
 
     }
 
+    /**
+     * This tests the 'PropertyUtil.Listener' interface.
+     */
+    @Test
+    void testListenerInterface() throws Exception {
+        logger.info("testListenerInterface: test receipt of dynamic updates");
+
+        // create initial property file
+        Properties prop1 = new Properties();
+        prop1.setProperty("p1", "p1 value");
+        prop1.setProperty("p2", "p2 value");
+        prop1.setProperty("p3", "p3 value");
+        logger.info("Create initial properties file: {}", prop1);
+        File file1 = createFile("createAndReadPropertyFile-2", prop1);
+
+        // create a listener for the notification interface
+        Object[] returns = new Object[2];
+        PropertyUtil.Listener listener = createListenerThread(returns);
+
+        // read it in, and do a comparison
+        Properties prop2 = PropertyUtil.getProperties(file1, listener);
+        logger.info("Read in properties: {}", prop2);
+        assertEquals(prop1, prop2);
+        assertEquals("p1 value", prop2.getProperty("p1"));
+        assertEquals("p2 value", prop2.getProperty("p2"));
+        assertEquals("p3 value", prop2.getProperty("p3"));
+
+        // make some changes, and update the file (p3 is left unchanged)
+        prop2.remove("p1"); // remove one property
+        prop2.setProperty("p2", "new p2 value");    // change one property
+        prop2.setProperty("p4", "p4 value");        // add a new property
+        logger.info("Modified properties: {}", prop2);
+
+        // now, update the file, and wait for notification
+        synchronized (returns) {
+            createFile("createAndReadPropertyFile-2", prop2);
+
+            // wait up to 60 seconds, although we should receive notification
+            // in 10 seconds or less (if things are working)
+            returns.wait(60000L);
+        }
+
+        // verify we have the updates
+        assertEquals(prop2, returns[0]);
+
+        // verify that we have the expected set of keys
+        assertEquals(new TreeSet<>(Arrays.asList("p1", "p2", "p4")), returns[1]);
+
+        String filePath = file1.getAbsolutePath();
+        PropertyUtil.stopListening(filePath, listener);
+    }
+
+    @Test
+    void testGetProperties_ListenerNull() throws IOException {
+        String filepath = "src/test/resources/interpolation.properties";
+        File propertiesFile = new File(filepath);
+        assertNotNull(propertiesFile);
+        PropertyUtil.Listener listener = null;
+        var result = PropertyUtil.getProperties(propertiesFile, listener);
+        assertNotNull(result);
+        assertInstanceOf(Properties.class, result);
+
+        var anotherResult = PropertyUtil.getProperties(filepath, listener);
+        assertNotNull(anotherResult);
+        assertInstanceOf(Properties.class, anotherResult);
+    }
+
     private void testGetDefaultCryptoSystemProps() throws IOException {
         // system properties + default crypto coder
         PropertyUtil.setDefaultCryptoCoder(new CryptoUtils(INTERPOLATION_CRYPTO_KEY));
@@ -251,54 +320,4 @@ public class PropertyUtilTest {
         assertEquals(System.getProperty("user.home"), props.getProperty(INTERPOLATION_SYS));
         assertEquals(INTERPOLATION_ENVD_DEFAULT_VALUE, props.getProperty(INTERPOLATION_ENVD_DEFAULT));
     }
-
-    /**
-     * This tests the 'PropertyUtil.Listener' interface.
-     */
-    @Test
-    void testListenerInterface() throws Exception {
-        logger.info("testListenerInterface: test receipt of dynamic updates");
-
-        // create initial property file
-        Properties prop1 = new Properties();
-        prop1.setProperty("p1", "p1 value");
-        prop1.setProperty("p2", "p2 value");
-        prop1.setProperty("p3", "p3 value");
-        logger.info("Create initial properties file: " + prop1);
-        File file1 = createFile("createAndReadPropertyFile-2", prop1);
-
-        // create a listener for the notification interface
-        Object[] returns = new Object[2];
-        PropertyUtil.Listener listener = createListenerThread(returns);
-
-        // read it in, and do a comparison
-        Properties prop2 = PropertyUtil.getProperties(file1, listener);
-        logger.info("Read in properties: " + prop2);
-        assertEquals(prop1, prop2);
-        assertEquals("p1 value", prop2.getProperty("p1"));
-        assertEquals("p2 value", prop2.getProperty("p2"));
-        assertEquals("p3 value", prop2.getProperty("p3"));
-
-        // make some changes, and update the file (p3 is left unchanged)
-        prop2.remove("p1"); // remove one property
-        prop2.setProperty("p2", "new p2 value");    // change one property
-        prop2.setProperty("p4", "p4 value");        // add a new property
-        logger.info("Modified properties: " + prop2);
-
-        // now, update the file, and wait for notification
-        synchronized (returns) {
-            createFile("createAndReadPropertyFile-2", prop2);
-
-            // wait up to 60 seconds, although we should receive notification
-            // in 10 seconds or less (if things are working)
-            returns.wait(60000L);
-        }
-
-        // verify we have the updates
-        assertEquals(prop2, returns[0]);
-
-        // verify that we have the expected set of keys
-        assertEquals(new TreeSet<String>(Arrays.asList(new String[]{"p1", "p2", "p4"})),
-                returns[1]);
-    }
 }