aboutsummaryrefslogtreecommitdiffstats
path: root/controlloop/common/rules-test/src/test
diff options
context:
space:
mode:
authorJim Hahn <jrh3@att.com>2020-03-09 15:15:05 -0400
committerJim Hahn <jrh3@att.com>2020-03-12 12:12:48 -0400
commitaa8225b5211485b3c1150c21e51fd3e93b7f31d3 (patch)
tree922b78d2c8a4c657d4c32604a0b73df40d2fb330 /controlloop/common/rules-test/src/test
parent0e658768fc0573bf6acf7f849a49c9da98c8e47f (diff)
Retool rules tests
Extracted common code from various XxxBaseTest classes into: - Topics class to manage messages for test topics - HttpClients class to manage HttpClient objects for tests - Simulators class to manage simulators for tests - Rules class to manage start up and shutdown of rules Merged remaining code from XxxBaseTest classes into a single class. Modified the Frankfurt and Usescases tests to subclass from this new class and specify just the relevant tests to be executed. Issue-ID: POLICY-2385 Signed-off-by: Jim Hahn <jrh3@att.com> Change-Id: Iaf83c9d2b205a4c343e0dde23ec86508f5773693
Diffstat (limited to 'controlloop/common/rules-test/src/test')
-rw-r--r--controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/BaseRuleTestTest.java459
-rw-r--r--controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/ExceptionsTest.java38
-rw-r--r--controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/HttpClientsTest.java94
-rw-r--r--controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/ListenerTest.java202
-rw-r--r--controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/NamedRunnerTest.java87
-rw-r--r--controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/NamedRunnerTest2.java58
-rw-r--r--controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/RulesTest.java341
-rw-r--r--controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/SimulatorsTest.java105
-rw-r--r--controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/TopicsTest.java230
-rw-r--r--controlloop/common/rules-test/src/test/resources/META-INF/kmodule.xml27
-rw-r--r--controlloop/common/rules-test/src/test/resources/config/rulesTest-controller.properties25
-rw-r--r--controlloop/common/rules-test/src/test/resources/my-http-client.properties26
-rw-r--r--controlloop/common/rules-test/src/test/resources/rulesTest.drl96
-rw-r--r--controlloop/common/rules-test/src/test/resources/rulesTest.pom30
-rw-r--r--controlloop/common/rules-test/src/test/resources/topics.json5
-rw-r--r--controlloop/common/rules-test/src/test/resources/topicsReplaced.json5
-rw-r--r--controlloop/common/rules-test/src/test/resources/tosca-policy.json37
-rw-r--r--controlloop/common/rules-test/src/test/resources/tosca-template.json45
18 files changed, 1910 insertions, 0 deletions
diff --git a/controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/BaseRuleTestTest.java b/controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/BaseRuleTestTest.java
new file mode 100644
index 000000000..745013b3b
--- /dev/null
+++ b/controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/BaseRuleTestTest.java
@@ -0,0 +1,459 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 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.controlloop.common.rules.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Queue;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.onap.policy.appc.CommonHeader;
+import org.onap.policy.appc.Request;
+import org.onap.policy.appclcm.AppcLcmBody;
+import org.onap.policy.appclcm.AppcLcmCommonHeader;
+import org.onap.policy.appclcm.AppcLcmDmaapWrapper;
+import org.onap.policy.appclcm.AppcLcmInput;
+import org.onap.policy.common.utils.coder.StandardCoder;
+import org.onap.policy.common.utils.coder.StandardCoderInstantAsMillis;
+import org.onap.policy.controlloop.ControlLoopNotificationType;
+import org.onap.policy.controlloop.VirtualControlLoopNotification;
+import org.onap.policy.drools.controller.DroolsController;
+import org.onap.policy.drools.system.PolicyController;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifier;
+import org.powermock.reflect.Whitebox;
+
+public class BaseRuleTestTest {
+ private static final String CONTROLLER_NAME = "my-controller-name";
+ private static final String POLICY_NAME = "my-policy-name";
+
+ // saved values
+ private static Function<String, Rules> ruleMaker;
+ private static Supplier<HttpClients> httpClientMaker;
+ private static Supplier<Simulators> simMaker;
+ private static Supplier<Topics> topicMaker;
+
+ private BaseRuleTest base;
+ private LinkedList<VirtualControlLoopNotification> clMgtQueue;
+ private Queue<AppcLcmDmaapWrapper> appcLcmQueue;
+ private Queue<Request> appcLegacyQueue;
+ private int permitCount;
+ private int finalCount;
+
+ @Mock
+ private PolicyController controller;
+ @Mock
+ private Rules rules;
+ @Mock
+ private HttpClients httpClients;
+ @Mock
+ private Simulators simulators;
+ @Mock
+ private Topics topics;
+ @Mock
+ private Listener<VirtualControlLoopNotification> policyClMgt;
+ @Mock
+ private Listener<Request> appcClSink;
+ @Mock
+ private Listener<AppcLcmDmaapWrapper> appcLcmRead;
+ @Mock
+ private DroolsController drools;
+ @Mock
+ private ToscaPolicy policy;
+ @Mock
+ private ToscaPolicyIdentifier policyIdent;
+
+
+ /**
+ * Saves static values from the class.
+ */
+ @BeforeClass
+ public static void setUpBeforeClass() {
+ ruleMaker = Whitebox.getInternalState(BaseRuleTest.class, "ruleMaker");
+ httpClientMaker = Whitebox.getInternalState(BaseRuleTest.class, "httpClientMaker");
+ simMaker = Whitebox.getInternalState(BaseRuleTest.class, "simMaker");
+ topicMaker = Whitebox.getInternalState(BaseRuleTest.class, "topicMaker");
+ }
+
+ /**
+ * Restores static values.
+ */
+ @AfterClass
+ public static void tearDownAfterClass() {
+ Whitebox.setInternalState(BaseRuleTest.class, "ruleMaker", ruleMaker);
+ Whitebox.setInternalState(BaseRuleTest.class, "httpClientMaker", httpClientMaker);
+ Whitebox.setInternalState(BaseRuleTest.class, "simMaker", simMaker);
+ Whitebox.setInternalState(BaseRuleTest.class, "topicMaker", topicMaker);
+ }
+
+ /**
+ * Sets up.
+ */
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ when(policy.getIdentifier()).thenReturn(policyIdent);
+ when(policyIdent.getName()).thenReturn(POLICY_NAME);
+
+ when(drools.factCount(CONTROLLER_NAME)).thenReturn(0L);
+ when(controller.getDrools()).thenReturn(drools);
+
+ when(rules.getControllerName()).thenReturn(CONTROLLER_NAME);
+ when(rules.getController()).thenReturn(controller);
+ when(rules.setupPolicyFromFile(any())).thenAnswer(args -> {
+ when(drools.factCount(CONTROLLER_NAME)).thenReturn(2L);
+ return policy;
+ });
+
+ when(topics.createListener(BaseRuleTest.POLICY_CL_MGT_TOPIC, VirtualControlLoopNotification.class, controller))
+ .thenReturn(policyClMgt);
+ when(topics.createListener(eq(BaseRuleTest.APPC_LCM_READ_TOPIC), eq(AppcLcmDmaapWrapper.class),
+ any(StandardCoder.class))).thenReturn(appcLcmRead);
+ when(topics.createListener(eq(BaseRuleTest.APPC_CL_TOPIC), eq(Request.class),
+ any(StandardCoderInstantAsMillis.class))).thenReturn(appcClSink);
+
+ Function<String, Rules> ruleMaker = this::makeRules;
+ Supplier<HttpClients> httpClientMaker = this::makeHttpClients;
+ Supplier<Simulators> simMaker = this::makeSim;
+ Supplier<Topics> topicMaker = this::makeTopics;
+
+ Whitebox.setInternalState(BaseRuleTest.class, "ruleMaker", ruleMaker);
+ Whitebox.setInternalState(BaseRuleTest.class, "httpClientMaker", httpClientMaker);
+ Whitebox.setInternalState(BaseRuleTest.class, "simMaker", simMaker);
+ Whitebox.setInternalState(BaseRuleTest.class, "topicMaker", topicMaker);
+
+ clMgtQueue = new LinkedList<>();
+ appcLcmQueue = new LinkedList<>();
+ appcLegacyQueue = new LinkedList<>();
+
+ when(policyClMgt.await(any())).thenAnswer(args -> {
+ VirtualControlLoopNotification notif = clMgtQueue.remove();
+ Predicate<VirtualControlLoopNotification> pred = args.getArgument(0);
+ assertTrue(pred.test(notif));
+ return notif;
+ });
+
+ when(appcLcmRead.await(any())).thenAnswer(args -> {
+ AppcLcmDmaapWrapper req = appcLcmQueue.remove();
+ Predicate<AppcLcmDmaapWrapper> pred = args.getArgument(0);
+ assertTrue(pred.test(req));
+ return req;
+ });
+
+ when(appcClSink.await(any())).thenAnswer(args -> {
+ Request req = appcLegacyQueue.remove();
+ Predicate<Request> pred = args.getArgument(0);
+ assertTrue(pred.test(req));
+ return req;
+ });
+
+ permitCount = 0;
+ finalCount = 0;
+
+ base = new MyTest();
+
+ BaseRuleTest.initStatics(CONTROLLER_NAME);
+ base.init();
+ }
+
+ @Test
+ public void testInitStatics() {
+ assertSame(rules, BaseRuleTest.rules);
+ assertSame(httpClients, BaseRuleTest.httpClients);
+ assertSame(simulators, BaseRuleTest.simulators);
+ }
+
+ @Test
+ public void testFinishStatics() {
+ BaseRuleTest.finishStatics();
+
+ verify(rules).destroy();
+ verify(httpClients).destroy();
+ verify(simulators).destroy();
+ }
+
+ @Test
+ public void testInit() {
+ assertSame(topics, base.getTopics());
+ assertSame(controller, base.controller);
+ }
+
+ @Test
+ public void testFinish() {
+ base.finish();
+
+ verify(topics).destroy();
+ verify(rules).resetFacts();
+ }
+
+ @Test
+ public void testTestService123Compliant() {
+ enqueueAppcLcm("restart", "restart", "restart", "restart", "rebuild", "migrate");
+ enqueueClMgt(ControlLoopNotificationType.OPERATION_SUCCESS);
+ enqueueClMgt(ControlLoopNotificationType.FINAL_SUCCESS);
+
+ base.testService123Compliant();
+
+ assertEquals(1, permitCount);
+ assertEquals(1, finalCount);
+
+ assertTrue(appcLcmQueue.isEmpty());
+ assertTrue(clMgtQueue.isEmpty());
+
+ // initial event
+ verify(topics).inject(eq(BaseRuleTest.DCAE_TOPIC), any());
+
+ // replies to each APPC request
+ verify(topics, times(6)).inject(eq(BaseRuleTest.APPC_LCM_WRITE_TOPIC), any(), any());
+ }
+
+ @Test
+ public void testTestDuplicatesEvents() {
+ enqueueAppcLcm("restart", "restart");
+ enqueueClMgt(ControlLoopNotificationType.FINAL_FAILURE);
+ enqueueClMgt(ControlLoopNotificationType.FINAL_SUCCESS);
+ enqueueClMgt(ControlLoopNotificationType.FINAL_SUCCESS);
+
+ clMgtQueue.get(1).setAai(Map.of("generic-vnf.vnf-id", "duplicate-VNF"));
+ clMgtQueue.get(2).setAai(Map.of("generic-vnf.vnf-id", "vCPE_Infrastructure_vGMUX_demo_app"));
+
+ base.testDuplicatesEvents();
+
+ assertEquals(0, permitCount);
+ assertEquals(3, finalCount);
+
+ assertTrue(appcLcmQueue.isEmpty());
+ assertTrue(clMgtQueue.isEmpty());
+
+ // initial events
+ verify(topics).inject(eq(BaseRuleTest.DCAE_TOPIC), any());
+ verify(topics, times(2)).inject(eq(BaseRuleTest.DCAE_TOPIC), any(), any());
+
+ // two restarts
+ verify(topics, times(2)).inject(eq(BaseRuleTest.APPC_LCM_WRITE_TOPIC), any(), any());
+ }
+
+ @Test
+ public void testTestVcpeSunnyDayLegacy() {
+ checkAppcLcmPolicy("restart", base::testVcpeSunnyDayLegacy);
+ }
+
+ @Test
+ public void testTestVcpeSunnyDayCompliant() {
+ checkAppcLcmPolicy("restart", base::testVcpeSunnyDayCompliant);
+ }
+
+ @Test
+ public void testTestVcpeOnsetFloodPrevention() {
+ enqueueAppcLcm("restart");
+ enqueueClMgt(ControlLoopNotificationType.OPERATION_SUCCESS);
+ enqueueClMgt(ControlLoopNotificationType.FINAL_SUCCESS);
+
+ base.testVcpeOnsetFloodPrevention();
+
+ assertEquals(1, permitCount);
+ assertEquals(1, finalCount);
+
+ assertTrue(appcLcmQueue.isEmpty());
+ assertTrue(clMgtQueue.isEmpty());
+
+ // initial events
+ verify(topics, times(3)).inject(eq(BaseRuleTest.DCAE_TOPIC), any());
+
+ // one restart
+ verify(topics).inject(eq(BaseRuleTest.APPC_LCM_WRITE_TOPIC), any(), any());
+ }
+
+ @Test
+ public void testTestVdnsSunnyDayCompliant() {
+ checkHttpPolicy(base::testVdnsSunnyDayCompliant);
+ }
+
+ @Test
+ public void testTestVfwSunnyDayLegacy() {
+ checkAppcLegacyPolicy("ModifyConfig", base::testVfwSunnyDayLegacy);
+ }
+
+ @Test
+ public void testTestVfwSunnyDayCompliant() {
+ checkAppcLegacyPolicy("ModifyConfig", base::testVfwSunnyDayCompliant);
+ }
+
+ @Test
+ public void testTestVlbSunnyDayLegacy() {
+ checkHttpPolicy(base::testVlbSunnyDayLegacy);
+ }
+
+ @Test
+ public void testTestVlbSunnyDayCompliant() {
+ checkHttpPolicy(base::testVlbSunnyDayCompliant);
+ }
+
+ protected void checkAppcLcmPolicy(String operation, Runnable test) {
+ enqueueAppcLcm(operation);
+ enqueueClMgt(ControlLoopNotificationType.OPERATION_SUCCESS);
+ enqueueClMgt(ControlLoopNotificationType.FINAL_SUCCESS);
+
+ test.run();
+
+ assertEquals(1, permitCount);
+ assertEquals(1, finalCount);
+
+ assertTrue(appcLcmQueue.isEmpty());
+ assertTrue(clMgtQueue.isEmpty());
+
+ // initial event
+ verify(topics).inject(eq(BaseRuleTest.DCAE_TOPIC), any());
+
+ // reply to each APPC request
+ verify(topics).inject(eq(BaseRuleTest.APPC_LCM_WRITE_TOPIC), any(), any());
+ }
+
+ protected void checkAppcLegacyPolicy(String operation, Runnable test) {
+ enqueueAppcLegacy(operation);
+ enqueueClMgt(ControlLoopNotificationType.OPERATION_SUCCESS);
+ enqueueClMgt(ControlLoopNotificationType.FINAL_SUCCESS);
+
+ test.run();
+
+ assertEquals(1, permitCount);
+ assertEquals(1, finalCount);
+
+ assertTrue(appcLcmQueue.isEmpty());
+ assertTrue(clMgtQueue.isEmpty());
+
+ // initial event
+ verify(topics).inject(eq(BaseRuleTest.DCAE_TOPIC), any());
+
+ // reply to each APPC request
+ verify(topics).inject(eq(BaseRuleTest.APPC_CL_TOPIC), any(), any());
+ }
+
+ protected void checkHttpPolicy(Runnable test) {
+ enqueueClMgt(ControlLoopNotificationType.OPERATION_SUCCESS);
+ enqueueClMgt(ControlLoopNotificationType.FINAL_SUCCESS);
+
+ test.run();
+
+ assertEquals(1, permitCount);
+ assertEquals(1, finalCount);
+
+ assertTrue(clMgtQueue.isEmpty());
+
+ // initial event
+ verify(topics).inject(eq(BaseRuleTest.DCAE_TOPIC), any());
+ }
+
+ private void enqueueClMgt(ControlLoopNotificationType type) {
+ VirtualControlLoopNotification notif = new VirtualControlLoopNotification();
+ notif.setNotification(type);
+ notif.setPolicyName(POLICY_NAME + ".EVENT.MANAGER.FINAL");
+
+ clMgtQueue.add(notif);
+ }
+
+ private void enqueueAppcLcm(String... operationNames) {
+ for (String oper : operationNames) {
+ AppcLcmDmaapWrapper req = new AppcLcmDmaapWrapper();
+ req.setRpcName(oper);
+
+ AppcLcmBody body = new AppcLcmBody();
+ req.setBody(body);
+
+ AppcLcmInput input = new AppcLcmInput();
+ body.setInput(input);
+
+ AppcLcmCommonHeader header = new AppcLcmCommonHeader();
+ input.setCommonHeader(header);
+
+ header.setSubRequestId("my-subrequest-id");
+
+ appcLcmQueue.add(req);
+ }
+ }
+
+ private void enqueueAppcLegacy(String... operationNames) {
+ for (String oper : operationNames) {
+ Request req = new Request();
+ req.setAction(oper);
+
+ CommonHeader header = new CommonHeader();
+ req.setCommonHeader(header);
+
+ header.setSubRequestId("my-subrequest-id");
+
+ appcLegacyQueue.add(req);
+ }
+ }
+
+ private Rules makeRules(String controllerName) {
+ return rules;
+ }
+
+ private HttpClients makeHttpClients() {
+ return httpClients;
+ }
+
+ private Simulators makeSim() {
+ return simulators;
+ }
+
+ private Topics makeTopics() {
+ return topics;
+ }
+
+ /*
+ * We don't want junit trying to run this, so it's marked "Ignore".
+ */
+ @Ignore
+ private class MyTest extends BaseRuleTest {
+
+ @Override
+ protected void waitForLockAndPermit(ToscaPolicy policy, Listener<VirtualControlLoopNotification> policyClMgt) {
+ permitCount++;
+ }
+
+ @Override
+ protected VirtualControlLoopNotification waitForFinal(ToscaPolicy policy,
+ Listener<VirtualControlLoopNotification> policyClMgt, ControlLoopNotificationType finalType) {
+ finalCount++;
+ return policyClMgt.await(notif -> notif.getNotification() == finalType);
+ }
+ }
+}
diff --git a/controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/ExceptionsTest.java b/controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/ExceptionsTest.java
new file mode 100644
index 000000000..a42ff6f5e
--- /dev/null
+++ b/controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/ExceptionsTest.java
@@ -0,0 +1,38 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 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.controlloop.common.rules.test;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.onap.policy.common.utils.test.ExceptionsTester;
+import org.onap.policy.controlloop.common.rules.test.SimulatorException;
+import org.onap.policy.controlloop.common.rules.test.TopicException;
+
+public class ExceptionsTest {
+
+ @Test
+ public void test() {
+ assertEquals(4, new ExceptionsTester().testAllException(TopicException.class));
+
+ assertEquals(4, new ExceptionsTester().testAllException(SimulatorException.class));
+ }
+}
diff --git a/controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/HttpClientsTest.java b/controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/HttpClientsTest.java
new file mode 100644
index 000000000..5db835343
--- /dev/null
+++ b/controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/HttpClientsTest.java
@@ -0,0 +1,94 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 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.controlloop.common.rules.test;
+
+import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+
+import java.util.Properties;
+import org.junit.After;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.onap.policy.common.endpoints.http.client.HttpClient;
+import org.onap.policy.common.endpoints.http.client.HttpClientConfigException;
+import org.onap.policy.common.endpoints.http.client.HttpClientFactory;
+import org.onap.policy.common.endpoints.http.client.HttpClientFactoryInstance;
+import org.onap.policy.controlloop.common.rules.test.HttpClients;
+import org.onap.policy.drools.persistence.SystemPersistenceConstants;
+
+public class HttpClientsTest {
+ private static final String CLIENT_NAME = "MY-CLIENT";
+
+ @Mock
+ private HttpClientFactory factory;
+
+
+ @BeforeClass
+ public static void setUpBeforeClass() {
+ SystemPersistenceConstants.getManager().setConfigurationDir("src/test/resources");
+ }
+
+ @After
+ public void tearDown() {
+ HttpClientFactoryInstance.getClientFactory().destroy();
+ }
+
+ @Test
+ public void test() throws HttpClientConfigException {
+ MockitoAnnotations.initMocks(this);
+
+ HttpClientFactoryInstance.getClientFactory().destroy();
+
+ HttpClients clients = new HttpClients();
+
+ clients.addClients("my");
+
+ // should find the client now
+ HttpClient client = HttpClientFactoryInstance.getClientFactory().get(CLIENT_NAME);
+ assertNotNull(client);
+
+ clients.destroy();
+
+ // destroyed - should NOT find the client
+ assertThatIllegalArgumentException()
+ .isThrownBy(() -> HttpClientFactoryInstance.getClientFactory().get(CLIENT_NAME));
+
+ // unknown property file
+ assertThatIllegalArgumentException().isThrownBy(() -> clients.addClients("unknown"));
+
+ // force exception from builder
+ HttpClients clients2 = new HttpClients() {
+ @Override
+ protected HttpClientFactory getClientFactory() {
+ return factory;
+ }
+ };
+
+ when(factory.build(any(Properties.class))).thenThrow(new HttpClientConfigException("expected exception"));
+
+ assertThatIllegalArgumentException().isThrownBy(() -> clients2.addClients("my"))
+ .withMessage("cannot initialize HTTP clients");
+ }
+}
diff --git a/controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/ListenerTest.java b/controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/ListenerTest.java
new file mode 100644
index 000000000..07ccc405b
--- /dev/null
+++ b/controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/ListenerTest.java
@@ -0,0 +1,202 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 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.controlloop.common.rules.test;
+
+import static org.assertj.core.api.Assertions.assertThatCode;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
+import org.onap.policy.common.endpoints.event.comm.TopicEndpoint;
+import org.onap.policy.common.endpoints.event.comm.TopicEndpointManager;
+import org.onap.policy.common.endpoints.event.comm.bus.NoopTopicSink;
+import org.onap.policy.common.endpoints.parameters.TopicParameters;
+import org.onap.policy.controlloop.common.rules.test.Listener;
+import org.onap.policy.controlloop.common.rules.test.TopicException;
+
+public class ListenerTest {
+ private static final String EXPECTED_EXCEPTION = "expected exception";
+ private static final String MY_TOPIC = "my-topic";
+ private static final String MESSAGE = "the-message";
+ private static final String MESSAGE2 = "other-message";
+ private static final String MSG_SUFFIX = "s";
+ private static final String DECODED_MESSAGE = MESSAGE + MSG_SUFFIX;
+
+ @Mock
+ private NoopTopicSink sink;
+ @Mock
+ private TopicEndpoint mgr;
+
+ private Listener<String> listener;
+
+ /**
+ * Creates topics.
+ */
+ @BeforeClass
+ public static void setUpBeforeClass() {
+ TopicEndpointManager.getManager().shutdown();
+
+ TopicParameters params = new TopicParameters();
+ params.setTopic(MY_TOPIC);
+ params.setManaged(true);
+ params.setTopicCommInfrastructure("NOOP");
+
+ TopicEndpointManager.getManager().addTopicSinks(List.of(params));
+ }
+
+ @AfterClass
+ public static void tearDownAfterClass() {
+ TopicEndpointManager.getManager().shutdown();
+ }
+
+ /**
+ * Sets up.
+ */
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ when(mgr.getNoopTopicSink(MY_TOPIC)).thenReturn(sink);
+
+ listener = new Listener<>(MY_TOPIC, msg -> msg + MSG_SUFFIX) {
+ @Override
+ protected TopicEndpoint getTopicManager() {
+ return mgr;
+ }
+ };
+ }
+
+ @Test
+ public void testListener() {
+ verify(sink).register(listener);
+ }
+
+ @Test
+ public void testAwait_testAwaitLongTimeUnit_testIsEmpty() {
+ assertTrue(listener.isEmpty());
+
+ listener.onTopicEvent(CommInfrastructure.NOOP, MY_TOPIC, MESSAGE);
+ assertFalse(listener.isEmpty());
+
+ assertEquals(DECODED_MESSAGE, listener.await());
+
+ assertTrue(listener.isEmpty());
+ }
+
+ @Test
+ public void testAwaitPredicateOfT() {
+ listener.onTopicEvent(CommInfrastructure.NOOP, MY_TOPIC, MESSAGE);
+ listener.onTopicEvent(CommInfrastructure.NOOP, MY_TOPIC, MESSAGE2);
+ assertEquals(MESSAGE2 + MSG_SUFFIX, listener.await(msg -> msg.startsWith("other-")));
+ }
+
+ /**
+ * Tests await() when the remaining time is negative.
+ */
+ @Test
+ public void testAwaitLongTimeUnitPredicateNoTime() {
+ assertThatThrownBy(() -> listener.await(-1, TimeUnit.SECONDS)).isInstanceOf(TopicException.class);
+ }
+
+ /**
+ * Tests await() when the poll() returns {@code null}.
+ */
+ @Test
+ public void testAwaitLongTimeUnitPredicateNoMessage() {
+ assertThatThrownBy(() -> listener.await(1, TimeUnit.MILLISECONDS)).isInstanceOf(TopicException.class);
+ }
+
+ /**
+ * Tests await() when the poll() is interrupted.
+ */
+ @Test
+ public void testAwaitLongTimeUnitPredicateInterrupted() throws InterruptedException {
+ listener = new Listener<String>(MY_TOPIC, msg -> msg) {
+ @Override
+ protected String pollMessage(long remainingMs) throws InterruptedException {
+ throw new InterruptedException(EXPECTED_EXCEPTION);
+ }
+ };
+
+ AtomicReference<TopicException> exref = new AtomicReference<>();
+ CountDownLatch interrupted = new CountDownLatch(1);
+
+ Thread thread = new Thread() {
+ @Override
+ public void run() {
+ try {
+ listener.await();
+ } catch (TopicException e) {
+ exref.set(e);
+ }
+
+ if (Thread.currentThread().isInterrupted()) {
+ interrupted.countDown();
+ }
+ }
+ };
+
+ thread.start();
+ assertTrue(interrupted.await(5, TimeUnit.SECONDS));
+ assertNotNull(exref.get());
+ }
+
+ @Test
+ public void testUnregister() {
+ listener.unregister();
+ verify(sink).unregister(listener);
+ }
+
+ @Test
+ public void testOnTopicEvent() {
+ listener = new Listener<>(MY_TOPIC, msg -> {
+ throw new IllegalArgumentException(EXPECTED_EXCEPTION);
+ });
+
+ // onTopicEvent() should not throw an exception
+ assertThatCode(() -> listener.onTopicEvent(CommInfrastructure.NOOP, MY_TOPIC, MESSAGE))
+ .doesNotThrowAnyException();
+
+ // should not have queued a message
+ assertTrue(listener.isEmpty());
+ }
+
+ @Test
+ public void testGetTopicManager() {
+ // use a listener with a real manager
+ assertNotNull(new Listener<>(MY_TOPIC, msg -> msg).getTopicManager());
+ }
+}
diff --git a/controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/NamedRunnerTest.java b/controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/NamedRunnerTest.java
new file mode 100644
index 000000000..fe9ff8083
--- /dev/null
+++ b/controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/NamedRunnerTest.java
@@ -0,0 +1,87 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 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.controlloop.common.rules.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import org.junit.AfterClass;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+/**
+ * Tests NamedRunner. The tests don't do much, because all we really want to check is
+ * which tests are executed based on the {@link TestNames} annotation.
+ */
+@RunWith(NamedRunner.class)
+@TestNames(names = {"testAbc", "testDef", "testIgnore"}, prefixes = {"testGhi", "testJkl"})
+public class NamedRunnerTest {
+
+ private static int testCount = 0;
+
+ @AfterClass
+ public static void tearDownAfterClass() {
+ assertEquals(5, testCount);
+ }
+
+ @Test
+ public void testAbc() {
+ checkTest();
+ }
+
+ @Test
+ public void testAbc2() {
+ fail("should not run");
+ }
+
+ @Test
+ public void testDef() {
+ checkTest();
+ }
+
+ @Test
+ @Ignore
+ public void testIgnore() {
+ fail("should not run");
+ }
+
+ @Test
+ public void testGhi1() {
+ checkTest();
+ }
+
+ @Test
+ public void testGhi2() {
+ checkTest();
+ }
+
+ @Test
+ public void testJkl() {
+ checkTest();
+ }
+
+
+ private static void checkTest() {
+ ++testCount;
+ }
+}
diff --git a/controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/NamedRunnerTest2.java b/controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/NamedRunnerTest2.java
new file mode 100644
index 000000000..1ed5b20bc
--- /dev/null
+++ b/controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/NamedRunnerTest2.java
@@ -0,0 +1,58 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 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.controlloop.common.rules.test;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.AfterClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+/**
+ * Tests NamedRunner when the TestNames annotation is missing - all tests should be
+ * executed.
+ */
+@RunWith(NamedRunner.class)
+public class NamedRunnerTest2 {
+
+ private static int testCount = 0;
+
+ @AfterClass
+ public static void tearDownAfterClass() {
+ assertEquals(2, testCount);
+ }
+
+ @Test
+ public void testAbc() {
+ checkTest();
+ }
+
+ @Test
+ public void testDef() {
+ checkTest();
+ }
+
+
+ private static void checkTest() {
+ ++testCount;
+ }
+}
diff --git a/controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/RulesTest.java b/controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/RulesTest.java
new file mode 100644
index 000000000..28cb977fc
--- /dev/null
+++ b/controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/RulesTest.java
@@ -0,0 +1,341 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 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.controlloop.common.rules.test;
+
+import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.File;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Properties;
+import java.util.stream.Collectors;
+import org.junit.Before;
+import org.junit.Test;
+import org.kie.api.definition.rule.Rule;
+import org.kie.api.event.rule.AfterMatchFiredEvent;
+import org.kie.api.event.rule.AgendaEventListener;
+import org.kie.api.event.rule.BeforeMatchFiredEvent;
+import org.kie.api.event.rule.MatchCancelledEvent;
+import org.kie.api.event.rule.MatchCreatedEvent;
+import org.kie.api.event.rule.ObjectDeletedEvent;
+import org.kie.api.event.rule.ObjectInsertedEvent;
+import org.kie.api.event.rule.ObjectUpdatedEvent;
+import org.kie.api.event.rule.RuleRuntimeEventListener;
+import org.kie.api.runtime.KieSession;
+import org.kie.api.runtime.rule.Match;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.onap.policy.controlloop.ControlLoopEvent;
+import org.onap.policy.controlloop.drl.legacy.ControlLoopParams;
+import org.onap.policy.controlloop.eventmanager.ControlLoopEventManager2;
+import org.onap.policy.drools.controller.DroolsController;
+import org.onap.policy.drools.persistence.SystemPersistence;
+import org.onap.policy.drools.system.PolicyController;
+import org.onap.policy.drools.system.PolicyControllerFactory;
+import org.onap.policy.drools.system.PolicyEngine;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
+
+public class RulesTest {
+ private static final String CONTROLLER_NAME = "rulesTest";
+ private static final String POLICY_FILE = "src/test/resources/tosca-policy.json";
+ private static final String MY_POLICY = "operational.restart";
+ private static final String RESOURCE_DIR = "src/test/resources";
+ private static final String MY_RULE_NAME = "my-rule-name";
+ private static final String MY_TEXT = "my text";
+
+ @Mock
+ private PolicyEngine engine;
+ @Mock
+ private SystemPersistence repo;
+ @Mock
+ private PolicyController controller;
+ @Mock
+ private KieSession kieSession;
+ @Mock
+ private PolicyControllerFactory controllerFactory;
+ @Mock
+ private DroolsController drools;
+
+ private List<Object> facts;
+ private List<RuleRuntimeEventListener> ruleListeners;
+ private List<AgendaEventListener> agendaListeners;
+ private Properties properties;
+ private boolean installed;
+
+ private Rules rules;
+
+ /**
+ * Sets up.
+ */
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ facts = new LinkedList<>();
+ ruleListeners = new LinkedList<>();
+ agendaListeners = new LinkedList<>();
+ installed = false;
+ properties = new Properties();
+
+ when(engine.createPolicyController(any(), any())).thenReturn(controller);
+ when(repo.getControllerProperties(CONTROLLER_NAME)).thenReturn(properties);
+ when(controller.getDrools()).thenReturn(drools);
+
+ when(drools.facts(eq(CONTROLLER_NAME), any())).thenAnswer(args -> {
+ Class<?> clazz = args.getArgument(1);
+ return facts.stream().filter(obj -> obj.getClass() == clazz).collect(Collectors.toList());
+ });
+
+ // notify listeners when objects are added to drools
+ when(drools.offer(any())).thenAnswer(args -> {
+ Object object = args.getArgument(0);
+ notifyInserted(object);
+
+ if (!(object instanceof ToscaPolicy)) {
+ return true;
+ }
+
+ // "insert" Params objects associated with the policy (i.e., mimic the rules)
+ ToscaPolicy policy = (ToscaPolicy) object;
+ ControlLoopParams params = new ControlLoopParams();
+ params.setToscaPolicy(policy);
+ notifyInserted(params);
+
+ return true;
+ });
+
+ when(drools.delete(any())).thenAnswer(args -> {
+ Class<?> clazz = args.getArgument(0);
+ facts.removeIf(obj -> obj.getClass() == clazz);
+ return null;
+ });
+
+ // handle rule listener registration and deregistration with the kieSession
+ doAnswer(args -> {
+ ruleListeners.add(args.getArgument(0));
+ return null;
+ }).when(kieSession).addEventListener(any(RuleRuntimeEventListener.class));
+
+ doAnswer(args -> {
+ ruleListeners.remove(args.getArgument(0));
+ return null;
+ }).when(kieSession).removeEventListener(any(RuleRuntimeEventListener.class));
+
+ // handle agenda listener registration and deregistration with the kieSession
+ doAnswer(args -> {
+ agendaListeners.add(args.getArgument(0));
+ return null;
+ }).when(kieSession).addEventListener(any(AgendaEventListener.class));
+
+ doAnswer(args -> {
+ agendaListeners.remove(args.getArgument(0));
+ return null;
+ }).when(kieSession).removeEventListener(any(AgendaEventListener.class));
+
+ rules = new MyRules();
+
+ rules.configure(RESOURCE_DIR);
+ rules.start();
+ }
+
+ @Test
+ public void testRules() {
+ assertEquals(CONTROLLER_NAME, rules.getControllerName());
+
+ assertSame(engine, rules.getPdpd());
+ assertSame(repo, rules.getPdpdRepo());
+ assertSame(controller, rules.getController());
+ }
+
+ @Test
+ public void testStart() throws Exception {
+ verify(repo).setConfigurationDir("src/test/resources/config");
+ assertTrue(installed);
+ verify(engine).configure(any(Properties.class));
+ verify(engine).createPolicyController(CONTROLLER_NAME, properties);
+ verify(engine).start();
+
+ verify(kieSession).addEventListener(any(RuleRuntimeEventListener.class));
+ verify(kieSession).addEventListener(any(AgendaEventListener.class));
+ }
+
+ @Test
+ public void testDestroy() {
+ rules.destroy();
+
+ verify(controllerFactory).shutdown(CONTROLLER_NAME);
+ verify(engine).stop();
+ }
+
+ @Test
+ public void testResetFacts() {
+ rules.resetFacts();
+
+ verify(drools).delete(ToscaPolicy.class);
+ verify(drools).delete(ControlLoopParams.class);
+ verify(drools).delete(ControlLoopEventManager2.class);
+ verify(drools).delete(ControlLoopEvent.class);
+ }
+
+ @Test
+ public void testSetupPolicyFromTemplate_testGetPolicyFromTemplate() {
+ rules.setupPolicyFromTemplate("tosca-template.json", MY_POLICY);
+
+ assertThatIllegalArgumentException()
+ .isThrownBy(() -> rules.setupPolicyFromTemplate("missing-file.json", "a-policy"));
+ }
+
+ @Test
+ public void testSetupPolicyFromFile_testGetPolicyFromFile_testSetupPolicy() {
+ assertNotNull(rules.setupPolicyFromFile(POLICY_FILE));
+
+ assertThatIllegalArgumentException().isThrownBy(() -> rules.setupPolicyFromFile("missing-file.json"));
+ }
+
+ @Test
+ public void testRuleListenerLogger() {
+ Rule rule = mock(Rule.class);
+ when(rule.getName()).thenReturn(MY_RULE_NAME);
+
+ // insertions - with and without rule name
+ ObjectInsertedEvent insert = mock(ObjectInsertedEvent.class);
+ when(insert.getObject()).thenReturn(MY_TEXT);
+ ruleListeners.forEach(listener -> listener.objectInserted(insert));
+ when(insert.getRule()).thenReturn(rule);
+ ruleListeners.forEach(listener -> listener.objectInserted(insert));
+
+ // updates - with and without rule name
+ ObjectUpdatedEvent update = mock(ObjectUpdatedEvent.class);
+ when(update.getObject()).thenReturn(MY_TEXT);
+ ruleListeners.forEach(listener -> listener.objectUpdated(update));
+ when(update.getRule()).thenReturn(rule);
+ ruleListeners.forEach(listener -> listener.objectUpdated(update));
+
+ // deletions - with and without rule name
+ ObjectDeletedEvent delete = mock(ObjectDeletedEvent.class);
+ when(delete.getOldObject()).thenReturn(MY_TEXT);
+ ruleListeners.forEach(listener -> listener.objectDeleted(delete));
+ when(delete.getRule()).thenReturn(rule);
+ ruleListeners.forEach(listener -> listener.objectDeleted(delete));
+ }
+
+ @Test
+ public void testAgendaListenerLogger() {
+ Rule rule = mock(Rule.class);
+ when(rule.getName()).thenReturn(MY_RULE_NAME);
+
+ Match match = mock(Match.class);
+ when(match.getRule()).thenReturn(rule);
+
+ // create
+ MatchCreatedEvent create = mock(MatchCreatedEvent.class);
+ when(create.getMatch()).thenReturn(match);
+ agendaListeners.forEach(listener -> listener.matchCreated(create));
+
+ // cancel
+ MatchCancelledEvent cancel = mock(MatchCancelledEvent.class);
+ when(cancel.getMatch()).thenReturn(match);
+ agendaListeners.forEach(listener -> listener.matchCancelled(cancel));
+
+ // before-fire
+ BeforeMatchFiredEvent before = mock(BeforeMatchFiredEvent.class);
+ when(before.getMatch()).thenReturn(match);
+ agendaListeners.forEach(listener -> listener.beforeMatchFired(before));
+
+ // after-fire
+ AfterMatchFiredEvent after = mock(AfterMatchFiredEvent.class);
+ when(after.getMatch()).thenReturn(match);
+ agendaListeners.forEach(listener -> listener.afterMatchFired(after));
+ }
+
+ @Test
+ public void testMakePdpd_testMakePdpdRepo() {
+ // need rules that makes real objects
+ rules = new Rules(CONTROLLER_NAME);
+
+ assertNotNull(rules.getPdpd());
+ assertNotNull(rules.getPdpdRepo());
+ }
+
+ protected void notifyInserted(Object object) {
+ // add it to our list
+ facts.add(object);
+
+ // increase code coverage by adding random objects
+ ObjectInsertedEvent event0 = mock(ObjectInsertedEvent.class);
+ when(event0.getObject()).thenReturn(new Object());
+ ruleListeners.forEach(listener -> listener.objectInserted(event0));
+
+ // increase code coverage by adding a random object
+ ObjectInsertedEvent event = mock(ObjectInsertedEvent.class);
+ when(event.getObject()).thenReturn(object);
+
+ if (object instanceof ToscaPolicy) {
+ // increase code coverage by associating it with a random rule
+ Rule rule = mock(Rule.class);
+ when(rule.getName()).thenReturn(MY_RULE_NAME);
+ when(event.getRule()).thenReturn(rule);
+ }
+
+ ruleListeners.forEach(listener -> listener.objectInserted(event));
+ }
+
+ private class MyRules extends Rules {
+ public MyRules() {
+ super(CONTROLLER_NAME);
+ }
+
+ @Override
+ protected PolicyEngine makeEngine() {
+ return engine;
+ }
+
+ @Override
+ protected SystemPersistence makePdpdRepo() {
+ return repo;
+ }
+
+ @Override
+ protected KieSession getKieSession() {
+ return kieSession;
+ }
+
+ @Override
+ protected PolicyControllerFactory getControllerFactory() {
+ return controllerFactory;
+ }
+
+ @Override
+ protected void installArtifact(File kmoduleFile, File pomFile, String resourceDir, List<File> ruleFiles) {
+ installed = true;
+ }
+ }
+}
diff --git a/controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/SimulatorsTest.java b/controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/SimulatorsTest.java
new file mode 100644
index 000000000..8a87c4f26
--- /dev/null
+++ b/controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/SimulatorsTest.java
@@ -0,0 +1,105 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 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.controlloop.common.rules.test;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+import java.util.List;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.onap.policy.common.endpoints.http.server.HttpServletServer;
+import org.onap.policy.controlloop.common.rules.test.SimulatorException;
+import org.onap.policy.controlloop.common.rules.test.Simulators;
+import org.onap.policy.controlloop.common.rules.test.Simulators.SimulatorBuilder;
+
+public class SimulatorsTest {
+ private static final String EXPECTED_EXCEPTION = "expected exception";
+
+ @Mock
+ private HttpServletServer server1;
+ @Mock
+ private HttpServletServer server2;
+ @Mock
+ private HttpServletServer server3;
+
+ private Simulators simulators;
+
+ /**
+ * Sets up.
+ */
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ simulators = new Simulators();
+ }
+
+ @Test
+ public void testStart() {
+ simulators.start(() -> server1, () -> server2);
+ assertEquals(List.of(server1, server2), simulators.getServers());
+
+ verify(server1, never()).shutdown();
+ verify(server2, never()).shutdown();
+ }
+
+ /**
+ * Tests start() when one of the builders throws an exception.
+ */
+ @Test
+ public void testStartException() {
+ SimulatorBuilder exbuilder = () -> {
+ throw new InterruptedException(EXPECTED_EXCEPTION);
+ };
+
+ assertThatThrownBy(() -> simulators.start(() -> server1, () -> server2, exbuilder, () -> server3))
+ .isInstanceOf(SimulatorException.class);
+
+ assertTrue(simulators.getServers().isEmpty());
+
+ verify(server1).shutdown();
+ verify(server2).shutdown();
+
+ // shouldn't have reached this builder, so nothing to shut down
+ verify(server3, never()).shutdown();
+ }
+
+ @Test
+ public void testDestroy() {
+ simulators.start(() -> server1, () -> server2, () -> server3);
+
+ doThrow(new IllegalStateException(EXPECTED_EXCEPTION)).when(server2).shutdown();
+
+ simulators.destroy();
+
+ verify(server1).shutdown();
+ verify(server3).shutdown();
+
+ assertTrue(simulators.getServers().isEmpty());
+ }
+}
diff --git a/controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/TopicsTest.java b/controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/TopicsTest.java
new file mode 100644
index 000000000..6ed8c3828
--- /dev/null
+++ b/controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/TopicsTest.java
@@ -0,0 +1,230 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 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.controlloop.common.rules.test;
+
+import static org.assertj.core.api.Assertions.assertThatCode;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import lombok.ToString;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
+import org.onap.policy.common.endpoints.event.comm.TopicEndpoint;
+import org.onap.policy.common.endpoints.event.comm.TopicEndpointManager;
+import org.onap.policy.common.endpoints.event.comm.bus.NoopTopicSink;
+import org.onap.policy.common.endpoints.event.comm.bus.NoopTopicSource;
+import org.onap.policy.common.endpoints.parameters.TopicParameters;
+import org.onap.policy.common.utils.coder.CoderException;
+import org.onap.policy.common.utils.coder.StandardCoder;
+import org.onap.policy.drools.controller.DroolsController;
+import org.onap.policy.drools.protocol.coders.EventProtocolCoder;
+import org.onap.policy.drools.system.PolicyController;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
+
+public class TopicsTest {
+ private static final String EXPECTED_EXCEPTION = "expected exception";
+ private static final String MY_SOURCE_TOPIC = "my-source-topic";
+ private static final String MY_SINK_TOPIC = "my-sink-topic";
+ private static final String MY_GROUP = "my-group";
+ private static final String MY_ARTIFACT = "my-artifact";
+ private static final String MESSAGE = "{\"text\": \"hello\"}";
+ private static final String TEXT = "hello";
+ private static final String INJECT_FILE = "src/test/resources/topics.json";
+ private static final String POLICY_NAME = "my-policy";
+
+ @Mock
+ private DroolsController drools;
+ @Mock
+ private PolicyController controller;
+ @Mock
+ private EventProtocolCoder protocolCoder;
+ @Mock
+ private NoopTopicSink sink;
+ @Mock
+ private NoopTopicSource source;
+ @Mock
+ private TopicEndpoint mgr;
+
+ private ToscaPolicy policy;
+
+ private Topics topics;
+
+ /**
+ * Creates topics.
+ */
+ @BeforeClass
+ public static void setUpBeforeClass() {
+ TopicEndpointManager.getManager().shutdown();
+
+ TopicParameters params = new TopicParameters();
+ params.setTopic(MY_SOURCE_TOPIC);
+ params.setManaged(true);
+ params.setTopicCommInfrastructure("NOOP");
+ TopicEndpointManager.getManager().addTopicSources(List.of(params));
+ }
+
+ @AfterClass
+ public static void tearDownAfterClass() {
+ TopicEndpointManager.getManager().shutdown();
+ }
+
+ /**
+ * Sets up.
+ */
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ policy = new ToscaPolicy();
+ policy.setName(POLICY_NAME);
+ policy.setVersion("1.0.0");
+
+ when(drools.getGroupId()).thenReturn(MY_GROUP);
+ when(drools.getArtifactId()).thenReturn(MY_ARTIFACT);
+
+ when(controller.getDrools()).thenReturn(drools);
+
+ when(protocolCoder.decode(MY_GROUP, MY_ARTIFACT, MY_SINK_TOPIC, MESSAGE)).thenReturn(TEXT);
+
+ when(mgr.getNoopTopicSink(MY_SINK_TOPIC)).thenReturn(sink);
+ when(mgr.getNoopTopicSource(MY_SOURCE_TOPIC)).thenReturn(source);
+
+ topics = new Topics() {
+ @Override
+ protected TopicEndpoint getTopicManager() {
+ return mgr;
+ }
+
+ @Override
+ protected EventProtocolCoder getProtocolCoder() {
+ return protocolCoder;
+ }
+ };
+ }
+
+ @Test
+ public void testDestroy() {
+ Listener<String> listener1 = topics.createListener(MY_SINK_TOPIC, msg -> msg);
+ Listener<String> listener2 = topics.createListener(MY_SINK_TOPIC, msg -> msg + "a suffix");
+
+ topics.destroy();
+
+ verify(sink).unregister(listener1);
+ verify(sink).unregister(listener2);
+ }
+
+ @Test
+ public void testInjectStringFile() throws IOException {
+ topics.inject(MY_SOURCE_TOPIC, INJECT_FILE);
+
+ // nothing should have been replaced
+ String expected = new String(Files.readAllBytes(Paths.get(INJECT_FILE)));
+ verify(source).offer(expected);
+ }
+
+ @Test
+ public void testInjectStringFileString() throws IOException {
+ topics.inject(MY_SOURCE_TOPIC, INJECT_FILE, "hello");
+
+ // text should have been replaced with "hello"
+ String expected = new String(Files.readAllBytes(Paths.get("src", "test", "resources", "topicsReplaced.json")));
+ verify(source).offer(expected);
+
+ // exception reading file
+ assertThatThrownBy(() -> topics.inject(MY_SOURCE_TOPIC, "missing-file.json", "some text"))
+ .isInstanceOf(TopicException.class);
+ }
+
+ @Test
+ public void testCreateListenerStringClassOfTPolicyController() {
+ Listener<String> listener = topics.createListener(MY_SINK_TOPIC, String.class, controller);
+ listener.onTopicEvent(CommInfrastructure.NOOP, MY_SINK_TOPIC, MESSAGE);
+
+ assertEquals(TEXT, listener.await());
+ }
+
+ @Test
+ public void testCreateListenerStringClassOfTCoder() {
+ Listener<Data> listener = topics.createListener(MY_SINK_TOPIC, Data.class, new StandardCoder());
+ listener.onTopicEvent(CommInfrastructure.NOOP, MY_SINK_TOPIC, MESSAGE);
+
+ Data expected = new Data();
+ expected.text = TEXT;
+ assertEquals(expected.toString(), listener.await().toString());
+ }
+
+ /**
+ * Tests createListener() when the coder throws an exception.
+ */
+ @Test
+ public void testCreateListenerStringClassOfTCoderException() {
+ StandardCoder coder = new StandardCoder() {
+ @Override
+ public <T> T decode(String arg0, Class<T> arg1) throws CoderException {
+ throw new CoderException(EXPECTED_EXCEPTION);
+ }
+ };
+
+ Listener<Data> listener = topics.createListener(MY_SINK_TOPIC, Data.class, coder);
+
+ // onTopicEvent() should not throw an exception
+ assertThatCode(() -> listener.onTopicEvent(CommInfrastructure.NOOP, MY_SINK_TOPIC, MESSAGE))
+ .doesNotThrowAnyException();
+
+ // should not have queued a message
+ assertThatThrownBy(() -> listener.await(0, TimeUnit.MILLISECONDS)).isInstanceOf(TopicException.class);
+ }
+
+ @Test
+ public void testCreateListenerStringFunctionOfStringT() {
+ Listener<String> listener = topics.createListener(MY_SINK_TOPIC, msg -> msg);
+ listener.onTopicEvent(CommInfrastructure.NOOP, MY_SINK_TOPIC, MESSAGE);
+
+ assertEquals(MESSAGE, listener.await());
+ }
+
+ @Test
+ public void testGetTopicManager_testGetProtocolCoder() {
+ // use a topic with a real manager
+ topics = new Topics();
+
+ assertNotNull(topics.getTopicManager());
+ assertNotNull(topics.getProtocolCoder());
+ }
+
+ @ToString
+ private static class Data {
+ private String text;
+ }
+}
diff --git a/controlloop/common/rules-test/src/test/resources/META-INF/kmodule.xml b/controlloop/common/rules-test/src/test/resources/META-INF/kmodule.xml
new file mode 100644
index 000000000..07041c6b1
--- /dev/null
+++ b/controlloop/common/rules-test/src/test/resources/META-INF/kmodule.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ ONAP
+ ================================================================================
+ Copyright (C) 2020 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=========================================================
+ -->
+<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule">
+ <kbase name="onap.policies.controlloop.operational.common.Drools" default="false" equalsBehavior="equality"/>
+ <kbase name="onap.policies.controlloop.Operational" equalsBehavior="equality"
+ packages="org.onap.policy.controlloop" includes="onap.policies.controlloop.operational.common.Drools">
+ <ksession name="rulesTest"/>
+ </kbase>
+</kmodule>
diff --git a/controlloop/common/rules-test/src/test/resources/config/rulesTest-controller.properties b/controlloop/common/rules-test/src/test/resources/config/rulesTest-controller.properties
new file mode 100644
index 000000000..11df5e99e
--- /dev/null
+++ b/controlloop/common/rules-test/src/test/resources/config/rulesTest-controller.properties
@@ -0,0 +1,25 @@
+#
+# ============LICENSE_START=======================================================
+# ONAP
+# ================================================================================
+# Copyright (C) 2020 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=========================================================
+#
+
+controller.name=rulesTest
+
+rules.groupId=org.onap.policy.controlloop
+rules.artifactId=rulesTest
+rules.version=1.0.0
diff --git a/controlloop/common/rules-test/src/test/resources/my-http-client.properties b/controlloop/common/rules-test/src/test/resources/my-http-client.properties
new file mode 100644
index 000000000..7d4ef90b9
--- /dev/null
+++ b/controlloop/common/rules-test/src/test/resources/my-http-client.properties
@@ -0,0 +1,26 @@
+#
+# ============LICENSE_START=======================================================
+# ONAP
+# ================================================================================
+# Copyright (C) 2020 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=========================================================
+#
+
+http.client.services=MY-CLIENT
+
+http.client.services.MY-CLIENT.managed=true
+http.client.services.MY-CLIENT.host=localhost
+http.client.services.MY-CLIENT.port=6669
+http.client.services.MY-CLIENT.contextUriPath=some/path
diff --git a/controlloop/common/rules-test/src/test/resources/rulesTest.drl b/controlloop/common/rules-test/src/test/resources/rulesTest.drl
new file mode 100644
index 000000000..11e99e960
--- /dev/null
+++ b/controlloop/common/rules-test/src/test/resources/rulesTest.drl
@@ -0,0 +1,96 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 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.controlloop;
+
+import org.onap.policy.controlloop.drl.legacy.ControlLoopParams;
+import org.onap.policy.controlloop.CanonicalOnset;
+import org.onap.policy.controlloop.VirtualControlLoopEvent;
+import org.onap.policy.controlloop.VirtualControlLoopNotification;
+import org.onap.policy.controlloop.ControlLoopNotificationType;
+import org.onap.policy.controlloop.policy.Policy;
+import org.onap.policy.controlloop.eventmanager.ControlLoopEventManager2;
+import org.onap.policy.controlloop.eventmanager.ControlLoopEventManager2.NewEventStatus;
+import org.onap.policy.controlloop.eventmanager.ControlLoopOperationManager2;
+import org.onap.policy.controlloop.utils.ControlLoopUtils;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
+
+import org.slf4j.LoggerFactory;
+import org.slf4j.Logger;
+
+import org.onap.policy.drools.system.PolicyEngineConstants;
+
+rule "STARTED"
+ when
+ then
+ System.out.println(drools.getRule().getName());
+end
+
+/*
+*
+* Called when the ControlLoopParams object has been inserted into working memory from the BRMSGW.
+*
+*/
+rule "INSERT.PARAMS"
+ when
+ $params : ControlLoopParams()
+ then
+
+ Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
+ logger.info("{}: {} : TOSCA-POLICY=[{}]", $params.getClosedLoopControlName(), $params.getPolicyName() + "."
+ + drools.getRule().getName(), $params.getToscaPolicy());
+end
+
+/*
+*
+* Called when a Tosca Policy is present.
+*
+*/
+rule "NEW.TOSCA.POLICY"
+ when
+ $policy : ToscaPolicy()
+ then
+
+ Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
+ logger.info("{}: [{}|{}|{}|{}]: CONTENT: {}", drools.getRule().getName(),
+ $policy.getType(), $policy.getTypeVersion(), $policy.getName(),
+ $policy.getVersion(), $policy);
+
+ ControlLoopParams params = ControlLoopUtils.toControlLoopParams($policy);
+ if (params != null) {
+ insert(params);
+ }
+end
+
+/*
+ * Remove Control Loop Parameters.
+ */
+rule "REMOVE.PARAMS"
+ when
+ $params : ControlLoopParams( $policyName : getPolicyName(), $policyVersion : getPolicyVersion() )
+ not ( ToscaPolicy( getName() == $policyName, getVersion() == $policyVersion ) )
+ then
+
+ Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
+ logger.info("{}: [{}|{}|{}]", drools.getRule().getName(),
+ $params.getPolicyScope(), $params.getPolicyName(), $params.getPolicyVersion());
+
+ retract($params);
+end
diff --git a/controlloop/common/rules-test/src/test/resources/rulesTest.pom b/controlloop/common/rules-test/src/test/resources/rulesTest.pom
new file mode 100644
index 000000000..625e736a4
--- /dev/null
+++ b/controlloop/common/rules-test/src/test/resources/rulesTest.pom
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ ONAP
+ ================================================================================
+ Copyright (C) 2020 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=========================================================
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.onap.policy.controlloop</groupId>
+ <artifactId>rulesTest</artifactId>
+ <version>1.0.0</version>
+</project>
diff --git a/controlloop/common/rules-test/src/test/resources/topics.json b/controlloop/common/rules-test/src/test/resources/topics.json
new file mode 100644
index 000000000..4e08bee83
--- /dev/null
+++ b/controlloop/common/rules-test/src/test/resources/topics.json
@@ -0,0 +1,5 @@
+{
+ "closedLoopControlName": "ControlLoop-vCPE-48f0c2c3-a172-4192-9ae3-052274181b6e",
+ "text": "${replaceMe}",
+ "moreText": "${replaceMe}"
+}
diff --git a/controlloop/common/rules-test/src/test/resources/topicsReplaced.json b/controlloop/common/rules-test/src/test/resources/topicsReplaced.json
new file mode 100644
index 000000000..743ef4c71
--- /dev/null
+++ b/controlloop/common/rules-test/src/test/resources/topicsReplaced.json
@@ -0,0 +1,5 @@
+{
+ "closedLoopControlName": "ControlLoop-vCPE-48f0c2c3-a172-4192-9ae3-052274181b6e",
+ "text": "hello",
+ "moreText": "hello"
+}
diff --git a/controlloop/common/rules-test/src/test/resources/tosca-policy.json b/controlloop/common/rules-test/src/test/resources/tosca-policy.json
new file mode 100644
index 000000000..42f54ab12
--- /dev/null
+++ b/controlloop/common/rules-test/src/test/resources/tosca-policy.json
@@ -0,0 +1,37 @@
+{
+ "type": "onap.policies.controlloop.operational.common.Drools",
+ "type_version": "1.0.0",
+ "version": "1.0.0",
+ "name": "operational.restart",
+ "metadata": {
+ "policy-id": "operational.restart"
+ },
+ "properties": {
+ "controllerName": "rulesTest",
+ "id": "ControlLoop-vCPE-48f0c2c3-a172-4192-9ae3-052274181b6e",
+ "timeout": 3600,
+ "abatement": false,
+ "trigger": "unique-policy-id-1-restart",
+ "operations": [
+ {
+ "id": "unique-policy-id-1-restart",
+ "description": "Restart the VM",
+ "operation": {
+ "actor": "APPC",
+ "operation": "Restart",
+ "target": {
+ "targetType": "VM"
+ }
+ },
+ "timeout": 1200,
+ "retries": 3,
+ "success": "final_success",
+ "failure": "final_failure",
+ "failure_timeout": "final_failure_timeout",
+ "failure_retries": "final_failure_retries",
+ "failure_exception": "final_failure_exception",
+ "failure_guard": "final_failure_guard"
+ }
+ ]
+ }
+}
diff --git a/controlloop/common/rules-test/src/test/resources/tosca-template.json b/controlloop/common/rules-test/src/test/resources/tosca-template.json
new file mode 100644
index 000000000..305756064
--- /dev/null
+++ b/controlloop/common/rules-test/src/test/resources/tosca-template.json
@@ -0,0 +1,45 @@
+{
+ "tosca_definitions_version": "tosca_simple_yaml_1_1_0",
+ "topology_template": {
+ "policies": [
+ {
+ "operational.restart": {
+ "type": "onap.policies.controlloop.operational.common.Drools",
+ "type_version": "1.0.0",
+ "version": "1.0.0",
+ "metadata": {
+ "policy-id": "operational.restart"
+ },
+ "properties": {
+ "id": "ControlLoop-vCPE-48f0c2c3-a172-4192-9ae3-052274181b6e",
+ "timeout": 3600,
+ "abatement": true,
+ "trigger": "unique-policy-id-1-restart",
+ "operations": [
+ {
+ "id": "unique-policy-id-1-restart",
+ "description": "Restart the VM",
+ "operation": {
+ "actor": "APPC",
+ "operation": "Restart",
+ "target": {
+ "targetType": "VNF"
+ }
+ },
+ "timeout": 1200,
+ "retries": 3,
+ "success": "final_success",
+ "failure": "final_failure",
+ "failure_timeout": "final_failure_timeout",
+ "failure_retries": "final_failure_retries",
+ "failure_exception": "final_failure_exception",
+ "failure_guard": "final_failure_guard"
+ }
+ ],
+ "controllerName": "usecases"
+ }
+ }
+ }
+ ]
+ }
+}