summaryrefslogtreecommitdiffstats
path: root/policy-core/src
diff options
context:
space:
mode:
Diffstat (limited to 'policy-core/src')
-rw-r--r--policy-core/src/main/java/org/onap/policy/drools/core/PolicyContainer.java96
-rw-r--r--policy-core/src/main/java/org/onap/policy/drools/core/PolicySession.java24
-rw-r--r--policy-core/src/main/java/org/onap/policy/drools/core/PolicySessionFeatureAPI.java6
-rw-r--r--policy-core/src/main/java/org/onap/policy/drools/core/jmx/PdpJmx.java7
-rw-r--r--policy-core/src/main/java/org/onap/policy/drools/core/jmx/PdpJmxListener.java5
-rw-r--r--policy-core/src/test/java/org/onap/policy/drools/core/DroolsContainerTest.java334
-rw-r--r--policy-core/src/test/java/org/onap/policy/drools/core/TestPolicySessionFeatureAPI.java157
-rw-r--r--policy-core/src/test/resources/META-INF/services/org.onap.policy.drools.core.PolicySessionFeatureAPI1
8 files changed, 568 insertions, 62 deletions
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 9fc2c837..2da53468 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
@@ -51,11 +51,11 @@ public class PolicyContainer implements Startable
// set of all 'PolicyContainer' instances
static private HashSet<PolicyContainer> containers =
- new HashSet<PolicyContainer>();
+ new HashSet<>();
// maps feature objects to per-PolicyContainer data
private ConcurrentHashMap<Object, Object> adjuncts =
- new ConcurrentHashMap<Object, Object>();
+ new ConcurrentHashMap<>();
// 'KieContainer' associated with this 'PolicyContainer'
private KieContainer kieContainer;
@@ -66,7 +66,7 @@ public class PolicyContainer implements Startable
// maps session name into the associated 'PolicySession' instance
private HashMap<String, PolicySession> sessions =
- new HashMap<String, PolicySession>();
+ new HashMap<>();
// if not null, this is a 'KieScanner' looking for updates
private KieScanner scanner = null;
@@ -104,21 +104,22 @@ public class PolicyContainer implements Startable
*/
public PolicyContainer(ReleaseId releaseId)
{
- if (releaseId.getVersion().contains(","))
+ ReleaseId newReleaseId = releaseId;
+ if (newReleaseId.getVersion().contains(","))
{
// this is actually a comma-separated list of release ids
- releaseId = loadArtifact(releaseId.getGroupId(),
- releaseId.getArtifactId(),
- releaseId.getVersion());
+ newReleaseId = loadArtifact(newReleaseId.getGroupId(),
+ newReleaseId.getArtifactId(),
+ newReleaseId.getVersion());
}
else
{
- kieContainer = kieServices.newKieContainer(releaseId);
+ kieContainer = kieServices.newKieContainer(newReleaseId);
}
synchronized(containers)
{
- if(releaseId != null){
- logger.info("Add a new kieContainer in containers: releaseId: " + releaseId.toString());
+ if(newReleaseId != null){
+ logger.info("Add a new kieContainer in containers: releaseId: " + newReleaseId.toString());
}else{
logger.warn("input releaseId is null");
}
@@ -182,9 +183,9 @@ public class PolicyContainer implements Startable
{
// all of the 'newKieContainer' invocations failed -- throw the
// most recent exception
- throw(exception);
+ throw exception;
}
- return(releaseId);
+ return releaseId;
}
/**
@@ -198,7 +199,7 @@ public class PolicyContainer implements Startable
*/
public String getName()
{
- return(kieContainer.getReleaseId().toString());
+ return kieContainer.getReleaseId().toString();
}
/**
@@ -206,7 +207,7 @@ public class PolicyContainer implements Startable
*/
public KieContainer getKieContainer()
{
- return(kieContainer);
+ return kieContainer;
}
/**
@@ -214,7 +215,7 @@ public class PolicyContainer implements Startable
*/
public ClassLoader getClassLoader()
{
- return(kieContainer.getClassLoader());
+ return kieContainer.getClassLoader();
}
/**
@@ -223,7 +224,7 @@ public class PolicyContainer implements Startable
*/
public String getGroupId()
{
- return(kieContainer.getReleaseId().getGroupId());
+ return kieContainer.getReleaseId().getGroupId();
}
/**
@@ -232,7 +233,7 @@ public class PolicyContainer implements Startable
*/
public String getArtifactId()
{
- return(kieContainer.getReleaseId().getArtifactId());
+ return kieContainer.getReleaseId().getArtifactId();
}
/**
@@ -241,7 +242,7 @@ public class PolicyContainer implements Startable
*/
public String getVersion()
{
- return(kieContainer.getReleaseId().getVersion());
+ return kieContainer.getReleaseId().getVersion();
}
/**
@@ -253,7 +254,7 @@ public class PolicyContainer implements Startable
*/
public PolicySession getPolicySession(String name)
{
- return(sessions.get(name));
+ return sessions.get(name);
}
/**
@@ -325,7 +326,7 @@ public class PolicyContainer implements Startable
logger.info("activatePolicySession:session - "
+ (session == null ? "null" : session.getFullName())
+ " is returned.");
- return(session);
+ return session;
}
}
@@ -352,14 +353,14 @@ public class PolicyContainer implements Startable
if(name == null){
logger.warn("adoptKieSession:input name is null");
- throw(new IllegalArgumentException
+ throw new IllegalArgumentException
("KieSession input name is null "
- + getName()));
+ + getName());
}else if(kieSession == null){
logger.warn("adoptKieSession:input kieSession is null");
- throw(new IllegalArgumentException
+ throw new IllegalArgumentException
("KieSession '" + name + "' is null "
- + getName()));
+ + getName());
}else {
logger.info("adoptKieSession:name: " + name + " kieSession: " + kieSession);
}
@@ -381,17 +382,17 @@ public class PolicyContainer implements Startable
// default KieBase, if it exists
if (!match && kieBase != kieContainer.getKieBase())
{
- throw(new IllegalArgumentException
+ throw new IllegalArgumentException
("KieSession '" + name + "' does not reside within container "
- + getName()));
+ + getName());
}
synchronized (sessions)
{
if (sessions.get(name) != null)
{
- throw(new IllegalStateException
- ("PolicySession '" + name + "' already exists"));
+ throw new IllegalStateException
+ ("PolicySession '" + name + "' already exists");
}
// create the new 'PolicySession', add it to the table,
@@ -415,7 +416,7 @@ public class PolicyContainer implements Startable
+ feature.getClass().getName(), e);
}
}
- return(policySession);
+ return policySession;
}
}
@@ -437,8 +438,8 @@ public class PolicyContainer implements Startable
releaseId.getArtifactId(),
newVersion));
- List<Message> messages = (results == null ? null : results.getMessages());
- return(messages == null ? null : messages.toString());
+ List<Message> messages = results == null ? null : results.getMessages();
+ return messages == null ? null : messages.toString();
}
/**
@@ -473,7 +474,7 @@ public class PolicyContainer implements Startable
session.updated();
}
- return(results);
+ return results;
}
/**
@@ -483,7 +484,7 @@ public class PolicyContainer implements Startable
{
synchronized(containers)
{
- return(new HashSet<PolicyContainer>(containers));
+ return new HashSet<>(containers);
}
}
@@ -495,7 +496,7 @@ public class PolicyContainer implements Startable
// KLUDGE WARNING: this is a temporary workaround -- if there are
// no features, we don't have persistence, and 'activate' is never
// called. In this case, make sure the container is started.
- if (PolicySessionFeatureAPI.impl.getList().size() == 0)
+ if (PolicySessionFeatureAPI.impl.getList().isEmpty())
{
start();
}
@@ -503,7 +504,7 @@ public class PolicyContainer implements Startable
// return current set of PolicySessions
synchronized(sessions)
{
- return(new HashSet<PolicySession>(sessions.values()));
+ return new HashSet<>(sessions.values());
}
}
@@ -518,7 +519,7 @@ public class PolicyContainer implements Startable
{
String version = releaseId.getVersion();
if (scannerStarted == false && scanner == null && version != null
- && (version.equals("LATEST") || version.equals("RELEASE")
+ && ("LATEST".equals(version) || "RELEASE".equals(version)
|| version.endsWith("-SNAPSHOT")))
{
// create the scanner, and poll at 60 second intervals
@@ -529,6 +530,7 @@ public class PolicyContainer implements Startable
// start this in a separate thread -- it can block for a long time
new Thread("Scanner Starter " + getName())
{
+ @Override
public void run()
{
scanner = kieServices.newKieScanner(kieContainer);
@@ -562,10 +564,10 @@ public class PolicyContainer implements Startable
if (session != null)
{
session.getKieSession().insert(object);
- return(true);
+ return true;
}
}
- return(false);
+ return false;
}
/**
@@ -586,7 +588,7 @@ public class PolicyContainer implements Startable
rval = true;
}
}
- return(rval);
+ return rval;
}
/*************************/
@@ -596,6 +598,7 @@ public class PolicyContainer implements Startable
/**
* {@inheritDoc}
*/
+ @Override
public synchronized boolean start()
{
if (!isStarted)
@@ -619,12 +622,13 @@ public class PolicyContainer implements Startable
}
isStarted = true;
}
- return(true);
+ return true;
}
/**
* {@inheritDoc}
*/
+ @Override
public synchronized boolean stop()
{
if (isStarted)
@@ -634,7 +638,7 @@ public class PolicyContainer implements Startable
synchronized (sessions)
{
// local set containing all of the sessions
- localSessions = new HashSet<PolicySession>(sessions.values());
+ localSessions = new HashSet<>(sessions.values());
// clear the 'name->session' map in 'PolicyContainer'
sessions.clear();
@@ -664,12 +668,13 @@ public class PolicyContainer implements Startable
}
isStarted = false;
}
- return(true);
+ return true;
}
/**
* {@inheritDoc}
*/
+ @Override
public synchronized void shutdown()
{
// Note that this method does not call 'destroy' on the 'KieSession'
@@ -689,9 +694,10 @@ public class PolicyContainer implements Startable
/**
* {@inheritDoc}
*/
+ @Override
public boolean isAlive()
{
- return(isStarted);
+ return isStarted;
}
/*************************/
@@ -710,7 +716,7 @@ public class PolicyContainer implements Startable
synchronized (sessions)
{
// local set containing all of the sessions
- localSessions = new HashSet<PolicySession>(sessions.values());
+ localSessions = new HashSet<>(sessions.values());
// clear the 'name->session' map in 'PolicyContainer'
sessions.clear();
@@ -831,7 +837,7 @@ public class PolicyContainer implements Startable
*/
public Object getAdjunct(Object object)
{
- return(adjuncts.get(object));
+ return adjuncts.get(object);
}
/**
diff --git a/policy-core/src/main/java/org/onap/policy/drools/core/PolicySession.java b/policy-core/src/main/java/org/onap/policy/drools/core/PolicySession.java
index c18c1343..2a949c0b 100644
--- a/policy-core/src/main/java/org/onap/policy/drools/core/PolicySession.java
+++ b/policy-core/src/main/java/org/onap/policy/drools/core/PolicySession.java
@@ -62,7 +62,7 @@ public class PolicySession
// maps feature objects to per-PolicyContainer data
private ConcurrentHashMap<Object, Object> adjuncts =
- new ConcurrentHashMap<Object, Object>();
+ new ConcurrentHashMap<>();
// associated 'KieSession' instance
private KieSession kieSession;
@@ -72,7 +72,7 @@ public class PolicySession
// supports 'getCurrentSession()' method
static private ThreadLocal<PolicySession> policySession =
- new ThreadLocal<PolicySession>();
+ new ThreadLocal<>();
/**
* Internal constructor - create a 'PolicySession' instance
@@ -96,7 +96,7 @@ public class PolicySession
*/
public PolicyContainer getPolicyContainer()
{
- return(container);
+ return container;
}
/**
@@ -104,7 +104,7 @@ public class PolicySession
*/
public KieSession getKieSession()
{
- return(kieSession);
+ return kieSession;
}
/**
@@ -114,7 +114,7 @@ public class PolicySession
*/
public String getName()
{
- return(name);
+ return name;
}
/**
@@ -123,7 +123,7 @@ public class PolicySession
*/
public String getFullName()
{
- return(container.getName() + ":" + name);
+ return container.getName() + ":" + name;
}
/**
@@ -204,7 +204,7 @@ public class PolicySession
*/
public static PolicySession getCurrentSession()
{
- return(policySession.get());
+ return policySession.get();
}
/**
@@ -218,7 +218,7 @@ public class PolicySession
*/
public Object getAdjunct(Object object)
{
- return(adjuncts.get(object));
+ return adjuncts.get(object);
}
/**
@@ -555,19 +555,19 @@ public class PolicySession
// We want to continue looping, despite any exceptions that occur
// while rules are fired.
- KieSession kieSession = session.getKieSession();
+ KieSession kieSession1 = session.getKieSession();
while (repeat)
{
try
{
- kieSession.fireUntilHalt();
+ kieSession1.fireUntilHalt();
- // if we fall through, it means 'KieSession.halt()' was called,
+ // if we fall through, it means 'kieSession1.halt()' was called,
// but this may be a result of 'KieScanner' doing an update
}
catch (Exception | LinkageError e)
{
- logger.error("startThread error in kieSession.fireUntilHalt", e);
+ logger.error("startThread error in kieSession1.fireUntilHalt", e);
}
}
logger.info("fireUntilHalt() returned");
diff --git a/policy-core/src/main/java/org/onap/policy/drools/core/PolicySessionFeatureAPI.java b/policy-core/src/main/java/org/onap/policy/drools/core/PolicySessionFeatureAPI.java
index 6777eb59..39377ab7 100644
--- a/policy-core/src/main/java/org/onap/policy/drools/core/PolicySessionFeatureAPI.java
+++ b/policy-core/src/main/java/org/onap/policy/drools/core/PolicySessionFeatureAPI.java
@@ -39,7 +39,7 @@ public interface PolicySessionFeatureAPI extends OrderedService
* implementing the 'FeatureAPI' interface.
*/
static public OrderedServiceImpl<PolicySessionFeatureAPI> impl =
- new OrderedServiceImpl<PolicySessionFeatureAPI>(PolicySessionFeatureAPI.class);
+ new OrderedServiceImpl<>(PolicySessionFeatureAPI.class);
/**
* This method is called during initialization at a point right after
@@ -68,7 +68,7 @@ public interface PolicySessionFeatureAPI extends OrderedService
default public KieSession activatePolicySession
(PolicyContainer policyContainer, String name, String kieBaseName)
{
- return(null);
+ return null;
}
/**
@@ -86,7 +86,7 @@ public interface PolicySessionFeatureAPI extends OrderedService
default public PolicySession.ThreadModel selectThreadModel
(PolicySession session)
{
- return(null);
+ return null;
}
/**
diff --git a/policy-core/src/main/java/org/onap/policy/drools/core/jmx/PdpJmx.java b/policy-core/src/main/java/org/onap/policy/drools/core/jmx/PdpJmx.java
index d3cf2e9d..19f6afb4 100644
--- a/policy-core/src/main/java/org/onap/policy/drools/core/jmx/PdpJmx.java
+++ b/policy-core/src/main/java/org/onap/policy/drools/core/jmx/PdpJmx.java
@@ -31,16 +31,21 @@ public class PdpJmx implements PdpJmxMBean {
public static PdpJmx getInstance() {
return instance;
}
-
+
+ @Override
public long getUpdates(){
return updates.longValue();
}
+
+ @Override
public long getRulesFired(){
return actions.longValue();
}
+
public void updateOccured(){
updates.incrementAndGet();
}
+
public void ruleFired(){
actions.incrementAndGet();
}
diff --git a/policy-core/src/main/java/org/onap/policy/drools/core/jmx/PdpJmxListener.java b/policy-core/src/main/java/org/onap/policy/drools/core/jmx/PdpJmxListener.java
index ceb7049e..9136defb 100644
--- a/policy-core/src/main/java/org/onap/policy/drools/core/jmx/PdpJmxListener.java
+++ b/policy-core/src/main/java/org/onap/policy/drools/core/jmx/PdpJmxListener.java
@@ -36,7 +36,10 @@ import org.slf4j.LoggerFactory;
public class PdpJmxListener {
public static final Logger logger = LoggerFactory.getLogger(PdpJmxListener.class);
-
+
+ private PdpJmxListener() {
+ }
+
public static void stop() {
final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
try {
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
new file mode 100644
index 00000000..e83f026c
--- /dev/null
+++ b/policy-core/src/test/java/org/onap/policy/drools/core/DroolsContainerTest.java
@@ -0,0 +1,334 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * policy-core
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * These tests focus on the following classes:
+ * PolicyContainer
+ * PolicySession
+ * PolicySessionFeatureAPI
+ */
+public class DroolsContainerTest
+{
+ /**
+ * This test is centered around the creation of a 'PolicyContainer'
+ * and 'PolicySession', and the updating of that container to a new
+ * version.
+ */
+ @Test
+ public void createAndUpdate() throws Exception
+ {
+ // make sure feature log starts out clean
+ TestPolicySessionFeatureAPI.getLog();
+
+ // run 'globalInit', and verify expected feature hook fired
+ PolicyContainer.globalInit(new String[0]);
+ assertEquals(buildArrayList("globalInit"),
+ TestPolicySessionFeatureAPI.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(buildArrayList("activatePolicySession",
+ "newPolicySession",
+ "selectThreadModel"),
+ TestPolicySessionFeatureAPI.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());
+
+ try
+ {
+ // fetch the session, and verify that it exists
+ PolicySession session = container.getPolicySession("session1");
+ assertTrue(session != null);
+
+ // 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));
+ }
+
+ // verify session attributes
+ assertEquals(container, session.getPolicyContainer());
+ assertEquals("session1", session.getName());
+ assertEquals("org.onap.policy.drools-pdp:drools-artifact1:17.1.0-SNAPSHOT:session1",
+ session.getFullName());
+
+ // insert a new fact
+ int[] a = new int[]{0, 3, 8, 2};
+ session.getKieSession().insert(a);
+
+ // the Drools rules should add 3 + 8 + 2, and store 13 in a[0]
+ assertTrue(waitForChange(a) == 13);
+
+ // update the container to a new version --
+ // the rules will then multiply values rather than add them
+ assertEquals("[]",
+ container.updateToVersion("17.2.0-SNAPSHOT").toString());
+
+ // verify expected feature hooks fired
+ assertEquals(buildArrayList("selectThreadModel"),
+ TestPolicySessionFeatureAPI.getLog());
+
+ // verify new container attributes
+ assertEquals
+ ("org.onap.policy.drools-pdp:drools-artifact1:17.2.0-SNAPSHOT",
+ container.getName());
+ assertEquals("org.onap.policy.drools-pdp", container.getGroupId());
+ assertEquals("drools-artifact1", container.getArtifactId());
+ assertEquals("17.2.0-SNAPSHOT", container.getVersion());
+
+ // verify new session attributes
+ assertEquals(container, session.getPolicyContainer());
+ assertEquals("session1", session.getName());
+ assertEquals("org.onap.policy.drools-pdp:drools-artifact1:17.2.0-SNAPSHOT:session1",
+ session.getFullName());
+
+ // the updated rules should now multiply 3 * 8 * 2, and return 48
+
+ a[0] = 0;
+ container.insert("session1", a);
+ assertTrue(waitForChange(a) == 48);
+ }
+ finally
+ {
+ container.shutdown();
+ assertFalse(container.isAlive());
+
+ // verify expected feature hooks fired
+ assertEquals(buildArrayList("disposeKieSession"),
+ TestPolicySessionFeatureAPI.getLog());
+ }
+
+ // final conditions -- there should be no containers
+ assertEquals(0, PolicyContainer.getPolicyContainers().size());
+ }
+
+ /**
+ * This test create a 'PolicyContainer' and 'PolicySession', and verifies
+ * their behavior, but uses alternate interfaces to increase code coverage.
+ * In addition, feature hook invocations will trigger exceptions in this
+ * test, also to increase code coverage.
+ */
+ @Test
+ public void versionList() throws Exception
+ {
+ // make sure feature log starts out clean
+ TestPolicySessionFeatureAPI.getLog();
+
+ // trigger exceptions in all feature hooks
+ TestPolicySessionFeatureAPI.setExceptionTrigger(true);
+
+ // run 'globalInit', and verify expected feature hook fired
+ PolicyContainer.globalInit(new String[0]);
+ assertEquals(buildArrayList("globalInit-exception"),
+ TestPolicySessionFeatureAPI.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";
+
+ // 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);
+ // the following should be equivalent to 'container.start()'
+ PolicyContainer.activate();
+ assertTrue(container.isAlive());
+
+ // verify expected feature hooks fired
+ assertEquals(buildArrayList("activatePolicySession-exception",
+ "newPolicySession-exception",
+ "selectThreadModel-exception"),
+ TestPolicySessionFeatureAPI.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());
+
+ // some container adjunct tests
+ {
+ Object bogusAdjunct = new Object();
+
+ // initially, no adjunct
+ assertSame(null, container.getAdjunct(this));
+
+ // set and verify adjunct
+ container.setAdjunct(this, bogusAdjunct);
+ assertSame(bogusAdjunct, container.getAdjunct(this));
+
+ // clear and verify adjunct
+ container.setAdjunct(this, null);
+ assertSame(null, container.getAdjunct(this));
+ }
+
+ try
+ {
+ // fetch the session, and verify that it exists
+ PolicySession session = container.getPolicySession("session1");
+ assertTrue(session != null);
+
+ // 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));
+ }
+
+ // verify session attributes
+ assertEquals(container, session.getPolicyContainer());
+ assertEquals("session1", session.getName());
+ assertEquals("org.onap.policy.drools-pdp:drools-artifact1:17.1.0-SNAPSHOT:session1",
+ session.getFullName());
+
+ // some session adjunct tests
+ {
+ Object bogusAdjunct = new Object();
+
+ // initially, no adjunct
+ assertSame(null, session.getAdjunct(this));
+
+ // set and verify adjunct
+ session.setAdjunct(this, bogusAdjunct);
+ assertSame(bogusAdjunct, session.getAdjunct(this));
+
+ // clear and verify adjunct
+ session.setAdjunct(this, null);
+ assertSame(null, session.getAdjunct(this));
+ }
+
+ // insert a new fact (using 'insertAll')
+ int[] a = new int[]{0, 7, 3, 4};
+ container.insertAll(a);
+
+ // the Drools rules should add 7 + 3 + 4, and store 14 in a[0]
+ assertTrue(waitForChange(a) == 14);
+
+ // exercise some more API methods
+ assertEquals(container.getClassLoader(),
+ container.getKieContainer().getClassLoader());
+ }
+ finally
+ {
+ // should be equivalent to 'shutdown' without persistence
+ container.destroy();
+ assertFalse(container.isAlive());
+
+ // verify expected feature hooks fired
+ assertEquals(buildArrayList("destroyKieSession-exception"),
+ TestPolicySessionFeatureAPI.getLog());
+
+ // clear exception trigger
+ TestPolicySessionFeatureAPI.setExceptionTrigger(false);
+ }
+
+ // final conditions -- there should be no containers
+ assertEquals(0, PolicyContainer.getPolicyContainers().size());
+ }
+
+ /**
+ * This method is tied to the expected behavior of the drools sessions.
+ * Initially, the value of 'array[0]' should be 0. The Drools rules
+ * will either add or multiply 'array[1]' through 'array[n-1]', depending
+ * upon the version. It waits up to 30 seconds for a non-zero value
+ * to appear.
+ */
+ private int waitForChange(int[] array) throws InterruptedException
+ {
+ int rval = -1;
+
+ // the value is tested every 1/100 of a second, and it waits up to
+ // 3000 iterations (= 30 seconds) for a non-zero value
+ for (int i = 0 ; i < 3000 ; i += 1)
+ {
+ // wait for 10 milliseconds = 1/100 of a second
+ Thread.sleep(10);
+ if ((rval = array[0]) != 0)
+ {
+ // a non-zero value has been stored
+ break;
+ }
+ }
+ return(rval);
+ }
+
+ /**
+ * @param args an array of string arguments
+ * @return an ArrayList constructed from the provided arguments
+ */
+ private ArrayList<String> buildArrayList(String... args)
+ {
+ ArrayList<String> rval = new ArrayList<>();
+ for (String arg : args)
+ {
+ rval.add(arg);
+ }
+ return(rval);
+ }
+}
diff --git a/policy-core/src/test/java/org/onap/policy/drools/core/TestPolicySessionFeatureAPI.java b/policy-core/src/test/java/org/onap/policy/drools/core/TestPolicySessionFeatureAPI.java
new file mode 100644
index 00000000..f456d814
--- /dev/null
+++ b/policy-core/src/test/java/org/onap/policy/drools/core/TestPolicySessionFeatureAPI.java
@@ -0,0 +1,157 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * policy-core
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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 java.util.ArrayList;
+import org.kie.api.runtime.KieSession;
+
+/**
+ * This class supports 'DroolsContainerTest' by implementing
+ * 'PolicySessionFeatureAPI', and providing a means to indicate
+ * which hooks have been invoked.
+ */
+public class TestPolicySessionFeatureAPI implements PolicySessionFeatureAPI
+{
+ // contains the log entries since the most recent 'getLog()' call
+ static private ArrayList<String> log = new ArrayList<>();
+
+ // if 'true', trigger an exception right after doing the log,
+ // to verify that exceptions are handled
+ static private boolean exceptionTrigger = false;
+
+ /**
+ * @return the current contents of the log, and clear the log
+ */
+ static public ArrayList<String> getLog()
+ {
+ synchronized(log)
+ {
+ ArrayList<String> rval = new ArrayList<>(log);
+ log.clear();
+ return(rval);
+ }
+ }
+
+ /**
+ * This method controls whether these hooks trigger an exception after
+ * being invoked.
+ *
+ * @param indicator if 'true', subsequent hook method calls will trigger
+ * an exception; if 'false', no exception is triggered
+ */
+ static public void setExceptionTrigger(boolean indicator)
+ {
+ exceptionTrigger = indicator;
+ }
+
+ /**
+ * This method adds an entry to the log, and possibly triggers an exception
+ *
+ * @param arg value to add to the log
+ */
+ static private void addLog(String arg)
+ {
+ if (exceptionTrigger)
+ {
+ // the log entry will include a '-exception' appended to the end
+ synchronized(log)
+ {
+ log.add(arg + "-exception");
+ }
+ System.out.println("*** " + arg + "-exception invoked ***");
+
+ // throw an exception -- it is up to the invoking code to catch it
+ throw(new IllegalStateException("Triggered from " + arg));
+ }
+ else
+ {
+ // create a log entry, and display to standard output
+ synchronized(log)
+ {
+ log.add(arg);
+ }
+ System.out.println("*** " + arg + " invoked ***");
+ }
+ }
+
+ /***************************************/
+ /* 'PolicySessionFeatureAPI' interface */
+ /***************************************/
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getSequenceNumber()
+ {
+ return(1);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void globalInit(String args[], String configDir)
+ {
+ addLog("globalInit");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public KieSession activatePolicySession
+ (PolicyContainer policyContainer, String name, String kieBaseName)
+ {
+ addLog("activatePolicySession");
+ return(null);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void newPolicySession(PolicySession policySession)
+ {
+ addLog("newPolicySession");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public PolicySession.ThreadModel selectThreadModel(PolicySession session)
+ {
+ addLog("selectThreadModel");
+ return(null);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void disposeKieSession(PolicySession policySession)
+ {
+ addLog("disposeKieSession");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void destroyKieSession(PolicySession policySession)
+ {
+ addLog("destroyKieSession");
+ }
+}
diff --git a/policy-core/src/test/resources/META-INF/services/org.onap.policy.drools.core.PolicySessionFeatureAPI b/policy-core/src/test/resources/META-INF/services/org.onap.policy.drools.core.PolicySessionFeatureAPI
new file mode 100644
index 00000000..d6b088c3
--- /dev/null
+++ b/policy-core/src/test/resources/META-INF/services/org.onap.policy.drools.core.PolicySessionFeatureAPI
@@ -0,0 +1 @@
+org.onap.policy.drools.core.TestPolicySessionFeatureAPI