aboutsummaryrefslogtreecommitdiffstats
path: root/policy-core
diff options
context:
space:
mode:
authoradheli.tavares <adheli.tavares@est.tech>2024-09-17 14:19:51 +0100
committerAdheli Tavares <adheli.tavares@est.tech>2024-09-20 09:06:21 +0000
commitc274fd4a91bdbd86d8fc719f12834133adc6584d (patch)
tree29a4ab0b7304666c7b36f1371c28e9c6807120db /policy-core
parentc13387e348160c181584141f6a5861c9d7b7ddb3 (diff)
Increase code coverage in policy-core and policy-utils
Issue-ID: POLICY-5068 Change-Id: I598b674fd623ff56c2e7b0316c114e7c270c2b3f Signed-off-by: adheli.tavares <adheli.tavares@est.tech>
Diffstat (limited to 'policy-core')
-rw-r--r--policy-core/pom.xml4
-rw-r--r--policy-core/src/main/java/org/onap/policy/drools/core/PolicyContainer.java149
-rw-r--r--policy-core/src/test/java/org/onap/policy/drools/core/DroolsContainerTest.java106
-rw-r--r--policy-core/src/test/java/org/onap/policy/drools/core/PolicyContainerTest.java230
-rw-r--r--policy-core/src/test/java/org/onap/policy/drools/core/PolicySessionFeatureApiMock.java6
-rw-r--r--policy-core/src/test/java/org/onap/policy/drools/core/jmx/PdpJmxListenerTest.java66
-rw-r--r--policy-core/src/test/java/org/onap/policy/drools/core/lock/AlwaysFailLockTest.java6
-rw-r--r--policy-core/src/test/java/org/onap/policy/drools/core/lock/AlwaysSuccessLockTest.java25
8 files changed, 479 insertions, 113 deletions
diff --git a/policy-core/pom.xml b/policy-core/pom.xml
index 57fd613c..9eb0af1a 100644
--- a/policy-core/pom.xml
+++ b/policy-core/pom.xml
@@ -133,6 +133,10 @@
<groupId>org.glassfish.hk2.external</groupId>
<artifactId>jakarta.inject</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ </dependency>
</dependencies>
</project>
diff --git a/policy-core/src/main/java/org/onap/policy/drools/core/PolicyContainer.java b/policy-core/src/main/java/org/onap/policy/drools/core/PolicyContainer.java
index ec5ceb21..533ac223 100644
--- a/policy-core/src/main/java/org/onap/policy/drools/core/PolicyContainer.java
+++ b/policy-core/src/main/java/org/onap/policy/drools/core/PolicyContainer.java
@@ -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");
+ }
+ }
}
diff --git a/policy-core/src/test/java/org/onap/policy/drools/core/DroolsContainerTest.java b/policy-core/src/test/java/org/onap/policy/drools/core/DroolsContainerTest.java
index abed9727..d6804b60 100644
--- a/policy-core/src/test/java/org/onap/policy/drools/core/DroolsContainerTest.java
+++ b/policy-core/src/test/java/org/onap/policy/drools/core/DroolsContainerTest.java
@@ -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
index 00000000..72c8d2d3
--- /dev/null
+++ b/policy-core/src/test/java/org/onap/policy/drools/core/PolicyContainerTest.java
@@ -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
diff --git a/policy-core/src/test/java/org/onap/policy/drools/core/PolicySessionFeatureApiMock.java b/policy-core/src/test/java/org/onap/policy/drools/core/PolicySessionFeatureApiMock.java
index d8257067..f0e5b516 100644
--- a/policy-core/src/test/java/org/onap/policy/drools/core/PolicySessionFeatureApiMock.java
+++ b/policy-core/src/test/java/org/onap/policy/drools/core/PolicySessionFeatureApiMock.java
@@ -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
index 00000000..d81dc3e9
--- /dev/null
+++ b/policy-core/src/test/java/org/onap/policy/drools/core/jmx/PdpJmxListenerTest.java
@@ -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
diff --git a/policy-core/src/test/java/org/onap/policy/drools/core/lock/AlwaysFailLockTest.java b/policy-core/src/test/java/org/onap/policy/drools/core/lock/AlwaysFailLockTest.java
index 51273d7d..02c3fead 100644
--- a/policy-core/src/test/java/org/onap/policy/drools/core/lock/AlwaysFailLockTest.java
+++ b/policy-core/src/test/java/org/onap/policy/drools/core/lock/AlwaysFailLockTest.java
@@ -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));
+ }
}
diff --git a/policy-core/src/test/java/org/onap/policy/drools/core/lock/AlwaysSuccessLockTest.java b/policy-core/src/test/java/org/onap/policy/drools/core/lock/AlwaysSuccessLockTest.java
index 80f81f92..0104d0a8 100644
--- a/policy-core/src/test/java/org/onap/policy/drools/core/lock/AlwaysSuccessLockTest.java
+++ b/policy-core/src/test/java/org/onap/policy/drools/core/lock/AlwaysSuccessLockTest.java
@@ -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));
+ }
}