aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--controlloop/common/controller-frankfurt/pom.xml6
-rw-r--r--controlloop/common/controller-frankfurt/src/test/java/org/onap/policy/controlloop/FrankfurtBase.java574
-rw-r--r--controlloop/common/controller-frankfurt/src/test/java/org/onap/policy/controlloop/FrankfurtTest.java113
-rw-r--r--controlloop/common/controller-frankfurt/src/test/java/org/onap/policy/controlloop/VcpeTest.java206
-rw-r--r--controlloop/common/controller-frankfurt/src/test/java/org/onap/policy/controlloop/VdnsTest.java139
-rw-r--r--controlloop/common/controller-frankfurt/src/test/java/org/onap/policy/controlloop/VfwTest.java188
-rw-r--r--controlloop/common/controller-frankfurt/src/test/java/org/onap/policy/controlloop/VlbTest.java152
-rw-r--r--controlloop/common/controller-frankfurt/src/test/resources/config/frankfurt-controller.properties8
-rw-r--r--controlloop/common/controller-frankfurt/src/test/resources/vcpe/vcpe.onset.3.json17
-rw-r--r--controlloop/common/controller-frankfurt/src/test/resources/vfw/tosca-vfw.json9
-rw-r--r--controlloop/common/controller-frankfurt/src/test/resources/vlb/tosca-compliant-vlb.json48
-rw-r--r--controlloop/common/controller-usecases/pom.xml6
-rw-r--r--controlloop/common/controller-usecases/src/test/java/org/onap/policy/controlloop/UsecasesBase.java515
-rw-r--r--controlloop/common/controller-usecases/src/test/java/org/onap/policy/controlloop/UsecasesTest.java120
-rw-r--r--controlloop/common/controller-usecases/src/test/java/org/onap/policy/controlloop/VcpeTest.java211
-rw-r--r--controlloop/common/controller-usecases/src/test/java/org/onap/policy/controlloop/VfwTest.java185
-rw-r--r--controlloop/common/controller-usecases/src/test/java/org/onap/policy/controlloop/VlbTest.java157
-rw-r--r--controlloop/common/controller-usecases/src/test/resources/config/usecases-controller.properties9
-rw-r--r--controlloop/common/controller-usecases/src/test/resources/vcpe/tosca-legacy-vcpe.json9
-rw-r--r--controlloop/common/controller-usecases/src/test/resources/vfw/vfw.appc.success.json17
-rw-r--r--controlloop/common/controller-usecases/src/test/resources/vlb/tosca-vlb.json9
-rw-r--r--controlloop/common/controller-usecases/src/test/resources/vlb/vlb.onset.json16
-rw-r--r--controlloop/common/pom.xml1
-rw-r--r--controlloop/common/rules-test/pom.xml165
-rw-r--r--controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/BaseRuleTest.java496
-rw-r--r--controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/HttpClients.java67
-rw-r--r--controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/Listener.java180
-rw-r--r--controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/NamedRunner.java85
-rw-r--r--controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/Rules.java413
-rw-r--r--controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/SimulatorException.java44
-rw-r--r--controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/Simulators.java85
-rw-r--r--controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/TestNames.java44
-rw-r--r--controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/TopicException.java44
-rw-r--r--controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/Topics.java176
-rw-r--r--controlloop/common/rules-test/src/main/resources/duplicates/duplicates.appc.success.json (renamed from controlloop/common/controller-frankfurt/src/test/resources/vcpe/vcpe.appc.success.json)0
-rw-r--r--controlloop/common/rules-test/src/main/resources/duplicates/duplicates.onset.1.json (renamed from controlloop/common/controller-usecases/src/test/resources/vcpe/vcpe.onset.1.json)8
-rw-r--r--controlloop/common/rules-test/src/main/resources/duplicates/duplicates.onset.2.json (renamed from controlloop/common/controller-frankfurt/src/test/resources/vcpe/vcpe.onset.2.json)4
-rw-r--r--controlloop/common/rules-test/src/main/resources/duplicates/tosca-compliant-duplicates.json (renamed from controlloop/common/controller-frankfurt/src/test/resources/vfw/tosca-compliant-vfw.json)29
-rw-r--r--controlloop/common/rules-test/src/main/resources/service123/service123.appc.migrate.success.json22
-rw-r--r--controlloop/common/rules-test/src/main/resources/service123/service123.appc.rebuild.failure.json22
-rw-r--r--controlloop/common/rules-test/src/main/resources/service123/service123.appc.restart.failure.json22
-rw-r--r--controlloop/common/rules-test/src/main/resources/service123/service123.onset.json (renamed from controlloop/common/controller-usecases/src/test/resources/vfw/vfw.onset.json)6
-rw-r--r--controlloop/common/rules-test/src/main/resources/service123/tosca-compliant-service123.json75
-rw-r--r--controlloop/common/rules-test/src/main/resources/vcpe/tosca-compliant-vcpe.json (renamed from controlloop/common/controller-frankfurt/src/test/resources/vcpe/tosca-compliant-vcpe.json)6
-rw-r--r--controlloop/common/rules-test/src/main/resources/vcpe/tosca-legacy-vcpe.json (renamed from controlloop/common/controller-frankfurt/src/test/resources/vcpe/tosca-legacy-vcpe.json)2
-rw-r--r--controlloop/common/rules-test/src/main/resources/vcpe/vcpe.appc.success.json (renamed from controlloop/common/controller-usecases/src/test/resources/vcpe/vcpe.appc.success.json)2
-rw-r--r--controlloop/common/rules-test/src/main/resources/vcpe/vcpe.onset.1.json (renamed from controlloop/common/controller-frankfurt/src/test/resources/vcpe/vcpe.onset.1.json)0
-rw-r--r--controlloop/common/rules-test/src/main/resources/vcpe/vcpe.onset.2.json (renamed from controlloop/common/controller-usecases/src/test/resources/vcpe/vcpe.onset.2.json)0
-rw-r--r--controlloop/common/rules-test/src/main/resources/vcpe/vcpe.onset.3.json (renamed from controlloop/common/controller-usecases/src/test/resources/vcpe/vcpe.onset.3.json)0
-rw-r--r--controlloop/common/rules-test/src/main/resources/vdns/tosca-compliant-vdns.json (renamed from controlloop/common/controller-frankfurt/src/test/resources/vdns/tosca-compliant-vdns.json)4
-rw-r--r--controlloop/common/rules-test/src/main/resources/vdns/vdns.onset.json (renamed from controlloop/common/controller-frankfurt/src/test/resources/vdns/vdns.onset.json)0
-rw-r--r--controlloop/common/rules-test/src/main/resources/vfw/tosca-compliant-vfw.json (renamed from controlloop/common/controller-usecases/src/test/resources/vfw/tosca-compliant-vfw.json)4
-rw-r--r--controlloop/common/rules-test/src/main/resources/vfw/tosca-vfw.json (renamed from controlloop/common/controller-usecases/src/test/resources/vfw/tosca-vfw.json)2
-rw-r--r--controlloop/common/rules-test/src/main/resources/vfw/vfw.appc.success.json (renamed from controlloop/common/controller-frankfurt/src/test/resources/vfw/vfw.appc.success.json)2
-rw-r--r--controlloop/common/rules-test/src/main/resources/vfw/vfw.onset.json (renamed from controlloop/common/controller-frankfurt/src/test/resources/vfw/vfw.onset.json)0
-rw-r--r--controlloop/common/rules-test/src/main/resources/vlb/tosca-compliant-vlb.json (renamed from controlloop/common/controller-usecases/src/test/resources/vlb/tosca-compliant-vlb.json)4
-rw-r--r--controlloop/common/rules-test/src/main/resources/vlb/tosca-vlb.json (renamed from controlloop/common/controller-frankfurt/src/test/resources/vlb/tosca-vlb.json)2
-rw-r--r--controlloop/common/rules-test/src/main/resources/vlb/vlb.onset.json (renamed from controlloop/common/controller-frankfurt/src/test/resources/vlb/vlb.onset.json)2
-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.json (renamed from controlloop/common/controller-usecases/src/test/resources/vcpe/tosca-compliant-vcpe.json)6
-rw-r--r--controlloop/common/rules-test/src/test/resources/tosca-template.json45
76 files changed, 4103 insertions, 2508 deletions
diff --git a/controlloop/common/controller-frankfurt/pom.xml b/controlloop/common/controller-frankfurt/pom.xml
index 9633f1f30..39511705c 100644
--- a/controlloop/common/controller-frankfurt/pom.xml
+++ b/controlloop/common/controller-frankfurt/pom.xml
@@ -190,9 +190,9 @@
<optional>true</optional>
</dependency>
<dependency>
- <groupId>org.onap.policy.models.policy-models-interactions</groupId>
- <artifactId>simulators</artifactId>
- <version>${policy.models.version}</version>
+ <groupId>org.onap.policy.drools-applications.controlloop.common</groupId>
+ <artifactId>rules-test</artifactId>
+ <version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
diff --git a/controlloop/common/controller-frankfurt/src/test/java/org/onap/policy/controlloop/FrankfurtBase.java b/controlloop/common/controller-frankfurt/src/test/java/org/onap/policy/controlloop/FrankfurtBase.java
deleted file mode 100644
index 0ff3de505..000000000
--- a/controlloop/common/controller-frankfurt/src/test/java/org/onap/policy/controlloop/FrankfurtBase.java
+++ /dev/null
@@ -1,574 +0,0 @@
-/*-
- * ============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 static org.assertj.core.api.Assertions.assertThat;
-import static org.awaitility.Awaitility.await;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.Properties;
-import java.util.Queue;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import lombok.Getter;
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.kie.api.event.rule.AfterMatchFiredEvent;
-import org.kie.api.event.rule.BeforeMatchFiredEvent;
-import org.kie.api.event.rule.DefaultAgendaEventListener;
-import org.kie.api.event.rule.DefaultRuleRuntimeEventListener;
-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.onap.policy.common.endpoints.event.comm.Topic;
-import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
-import org.onap.policy.common.endpoints.event.comm.TopicEndpointManager;
-import org.onap.policy.common.endpoints.event.comm.TopicListener;
-import org.onap.policy.common.endpoints.http.client.HttpClientConfigException;
-import org.onap.policy.common.endpoints.http.client.HttpClientFactoryInstance;
-import org.onap.policy.common.endpoints.http.server.HttpServletServerFactoryInstance;
-import org.onap.policy.common.utils.coder.Coder;
-import org.onap.policy.common.utils.coder.CoderException;
-import org.onap.policy.common.utils.coder.StandardCoder;
-import org.onap.policy.common.utils.resources.ResourceUtils;
-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.persistence.SystemPersistenceConstants;
-import org.onap.policy.drools.protocol.coders.EventProtocolCoderConstants;
-import org.onap.policy.drools.system.PolicyController;
-import org.onap.policy.drools.system.PolicyControllerConstants;
-import org.onap.policy.drools.system.PolicyEngine;
-import org.onap.policy.drools.system.PolicyEngineConstants;
-import org.onap.policy.drools.util.KieUtils;
-import org.onap.policy.drools.utils.logging.LoggerUtil;
-import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
-import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
-import org.onap.policy.simulators.Util;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Use Cases Tests Framework.
- */
-public abstract class FrankfurtBase {
-
- private static final Logger logger = LoggerFactory.getLogger(FrankfurtBase.class);
- private static final StandardCoder coder = new StandardCoder();
-
- /**
- * PDP-D Engine.
- */
- protected static final PolicyEngine pdpD = PolicyEngineConstants.getManager();
-
- /**
- * PDP-D Configuration Repository.
- */
- protected static final SystemPersistence repo = SystemPersistenceConstants.getManager();
-
- /**
- * Frankfurt controller and session name.
- */
- protected static final String CONTROLLER_NAME = "frankfurt";
-
- /**
- * Frankfurt controller.
- */
- protected static PolicyController controller;
-
- /*
- * Canonical Topic Names.
- */
- protected static final String DCAE_TOPIC = "DCAE_TOPIC";
- protected static final String APPC_LCM_WRITE_TOPIC = "APPC-LCM-WRITE";
- protected static final String POLICY_CL_MGT_TOPIC = "POLICY-CL-MGT";
- protected static final String APPC_LCM_READ_TOPIC = "APPC-LCM-READ";
- protected static final String APPC_CL_TOPIC = "APPC-CL";
-
- protected static void initConfigDir() {
- SystemPersistenceConstants.getManager().setConfigurationDir("src/test/resources/config");
- }
-
- protected void resetFacts() {
- DroolsController drools = controller.getDrools();
- drools.delete(ToscaPolicy.class);
- drools.delete(ControlLoopParams.class);
- drools.delete(ControlLoopEventManager2.class);
- drools.delete(VirtualControlLoopEvent.class);
- }
-
- /**
- * Sets up overall logging.
- */
- protected static void setupLogging() {
- LoggerUtil.setLevel(LoggerUtil.ROOT_LOGGER, "WARN");
- LoggerUtil.setLevel("org.eclipse.jetty", "WARN");
- LoggerUtil.setLevel("org.onap.policy.controlloop", "INFO");
- LoggerUtil.setLevel("network", "INFO");
- }
-
- /**
- * Sets up Drools Logging for events of interest.
- */
- protected static void setupDroolsLogging() {
- KieSession session = PolicyControllerConstants.getFactory().get(CONTROLLER_NAME).getDrools().getContainer()
- .getPolicySession(CONTROLLER_NAME).getKieSession();
-
- session.addEventListener(new RuleListenerLogger());
- session.addEventListener(new AgendaListenerLogger());
- }
-
- /**
- * Sets up Http Clients specified in the property file.
- */
- protected static void setUpHttpClients() {
- try {
- HttpClientFactoryInstance.getClientFactory().build(
- SystemPersistenceConstants.getManager().getHttpClientProperties("frankfurt"));
- } catch (HttpClientConfigException e) {
- throw new IllegalArgumentException("cannot initialize HTTP clients", e);
- }
- }
-
- /**
- * Sets up Simulators for use case testing.
- */
- protected static void setupSimulators() throws InterruptedException {
- Util.buildAaiSim();
- Util.buildSoSim();
- Util.buildVfcSim();
- Util.buildGuardSim();
- Util.buildSdncSim();
- }
-
- /**
- * Returns the runtime Control Loop Parameters associated with a Tosca Policy.
- */
- protected ControlLoopParams clParameters(ToscaPolicy policy) {
- return controller.getDrools().facts(CONTROLLER_NAME, ControlLoopParams.class).stream()
- .filter((params) -> params.getToscaPolicy() == policy).findFirst().get();
- }
-
- protected ToscaPolicy getPolicyFromResource(String resourcePath, String policyName) throws CoderException {
- String policyJson = ResourceUtils.getResourceAsString(resourcePath);
- ToscaServiceTemplate serviceTemplate = coder.decode(policyJson, ToscaServiceTemplate.class);
- ToscaPolicy policy = serviceTemplate.getToscaTopologyTemplate().getPolicies().get(0).get(policyName);
- assertNotNull(policy);
-
- /*
- * name and version are used within a drl. api component and drools core will
- * ensure that these are populated.
- */
- if (StringUtils.isBlank(policy.getName())) {
- policy.setName(policyName);
- }
-
- if (StringUtils.isBlank(policy.getVersion())) {
- policy.setVersion(policy.getTypeVersion());
- }
-
- return serviceTemplate.getToscaTopologyTemplate().getPolicies().get(0).get(policyName);
- }
-
- protected ToscaPolicy getPolicyFromFile(String policyPath) throws IOException, CoderException {
- String rawPolicy = new String(Files.readAllBytes(Paths.get(policyPath)));
- return coder.decode(rawPolicy, ToscaPolicy.class);
- }
-
- private ToscaPolicy setupPolicy(ToscaPolicy policy) throws InterruptedException {
- final KieObjectExpectedCallback<?> policyTracker = new KieObjectInsertedExpectedCallback<>(policy);
- final KieObjectExpectedCallback<?> paramsTracker =
- new KieClassInsertedExpectedCallback<>(ControlLoopParams.class);
-
- controller.getDrools().offer(policy);
-
- assertTrue(policyTracker.isNotified());
- assertTrue(paramsTracker.isNotified());
-
- assertEquals(1, controller.getDrools().facts(CONTROLLER_NAME, ToscaPolicy.class).stream()
- .filter((anotherPolicy) -> anotherPolicy == policy).count());
-
- assertEquals(1, controller.getDrools().facts(CONTROLLER_NAME, ControlLoopParams.class).stream()
- .filter((params) -> params.getToscaPolicy() == policy).count());
- return policy;
- }
-
- /**
- * Installs a policy from policy/models (examples) repo.
- */
- protected ToscaPolicy setupPolicyFromResource(String resourcePath, String policyName)
- throws CoderException, InterruptedException {
- return setupPolicy(getPolicyFromResource(resourcePath, policyName));
- }
-
-
- /**
- * Installs a given policy.
- */
- protected ToscaPolicy setupPolicyFromFile(String policyPath)
- throws IOException, CoderException, InterruptedException {
- return setupPolicy(getPolicyFromFile(policyPath));
- }
-
- /**
- * Deletes a policy.
- */
- protected void deletePolicy(ToscaPolicy policy) throws InterruptedException {
- ControlLoopParams clParams = clParameters(policy);
- assertNotNull(clParams);
-
- final KieObjectExpectedCallback<?> policyTracker = new KieObjectDeletedExpectedCallback<>(policy);
- final KieObjectExpectedCallback<?> clParamsTracker = new KieObjectDeletedExpectedCallback<>(clParams);
-
- controller.getDrools().delete(CONTROLLER_NAME, policy);
- assertTrue(policyTracker.isNotified());
- assertTrue(clParamsTracker.isNotified());
-
- assertEquals(0, controller.getDrools().facts(CONTROLLER_NAME, ToscaPolicy.class).stream()
- .filter((anotherPolicy) -> anotherPolicy == policy).count());
-
- assertEquals(0, controller.getDrools().facts(CONTROLLER_NAME, ControlLoopParams.class).stream()
- .filter((params) -> params.getPolicyName() == policy.getName()).count());
- }
-
- /**
- * Prepare a PDP-D to test the Use Cases.
- */
- protected static void preparePdpD() throws IOException {
- KieUtils.installArtifact(Paths.get("src/main/resources/META-INF/kmodule.xml").toFile(),
- Paths.get("src/test/resources/frankfurt.pom").toFile(),
- "src/main/resources/org/onap/policy/controlloop/",
- Collections.singletonList(Paths.get("src/main/resources/frankfurt.drl").toFile()));
-
- repo.setConfigurationDir("src/test/resources/config");
- pdpD.configure(new Properties());
-
- controller = pdpD.createPolicyController(CONTROLLER_NAME, repo.getControllerProperties(CONTROLLER_NAME));
- pdpD.start();
-
- setupDroolsLogging();
- }
-
- /**
- * Stop PDP-D.
- */
- protected static void stopPdpD() {
- PolicyControllerConstants.getFactory().shutdown(CONTROLLER_NAME);
- pdpD.stop();
- }
-
- /**
- * Stops the http clients.
- */
- protected static void stopHttpClients() {
- HttpClientFactoryInstance.getClientFactory().destroy();
- }
-
- /**
- * Stop Simulators.
- */
- protected static void stopSimulators() {
- HttpServletServerFactoryInstance.getServerFactory().destroy();
- }
-
- /**
- * Creates a Topic Sink Callback tracker.
- */
- protected <T> TopicCallback<T> createTopicSinkCallback(String topicName, Class<T> clazz) {
- return new TopicCallback<>(TopicEndpointManager.getManager().getNoopTopicSink(topicName), clazz);
- }
-
- /**
- * Creates a Topic Sink Callback tracker.
- */
- protected <T> TopicCallback<T> createTopicSinkCallbackPlain(String topicName, Class<T> clazz, Coder coder) {
- return new TopicCallbackCoder<>(TopicEndpointManager.getManager().getNoopTopicSink(topicName), clazz, coder);
- }
-
- /**
- * Creates a Topic Source Callback tracker.
- */
- protected <T> TopicCallback<T> createTopicSourceCallback(String topicName, Class<T> clazz) {
- return new TopicCallback<>(TopicEndpointManager.getManager().getNoopTopicSource(topicName), clazz);
- }
-
- /**
- * Injects a message on a Topic Source.
- */
- protected void injectOnTopic(String topicName, Path onsetPath) throws IOException {
- TopicEndpointManager.getManager().getNoopTopicSource(topicName)
- .offer(new String(Files.readAllBytes(onsetPath)));
- }
-
- /**
- * Injects a message on a Topic Source, with the given substitution..
- */
- protected void injectOnTopic(String topicName, Path path, String newText) throws IOException {
- String text = IOUtils.toString(path.toUri(), StandardCharsets.UTF_8);
- text = text.replace("${replaceMe}", newText);
- TopicEndpointManager.getManager().getNoopTopicSource(topicName).offer(text);
- }
-
- /**
- * Waits for LOCK acquisition and getting a Permit from PDP-X to proceed.
- */
- protected void waitForLockAndPermit(ToscaPolicy policy, TopicCallback<VirtualControlLoopNotification> policyClMgt) {
- String policyName = policy.getIdentifier().getName();
-
- // TODO register a topic listener instead of using await() ?
-
- await().until(() -> !policyClMgt.getMessages().isEmpty());
- VirtualControlLoopNotification notif = policyClMgt.getMessages().remove();
- assertEquals(ControlLoopNotificationType.ACTIVE, notif.getNotification());
- assertEquals(policyName + ".EVENT", notif.getPolicyName());
-
- await().until(() -> !policyClMgt.getMessages().isEmpty());
- notif = policyClMgt.getMessages().remove();
- assertEquals(ControlLoopNotificationType.OPERATION, notif.getNotification());
- assertEquals(policyName + ".EVENT.MANAGER.PROCESSING", notif.getPolicyName());
- assertThat(notif.getMessage()).startsWith("Sending guard query");
-
- await().until(() -> !policyClMgt.getMessages().isEmpty());
- notif = policyClMgt.getMessages().remove();
- assertEquals(ControlLoopNotificationType.OPERATION, notif.getNotification());
- assertEquals(policyName + ".EVENT.MANAGER.PROCESSING", notif.getPolicyName());
- assertThat(notif.getMessage()).startsWith("Guard result").endsWith("Permit");
-
- await().until(() -> !policyClMgt.getMessages().isEmpty());
- notif = policyClMgt.getMessages().remove();
- assertEquals(ControlLoopNotificationType.OPERATION, notif.getNotification());
- assertEquals(policyName + ".EVENT.MANAGER.PROCESSING", notif.getPolicyName());
- assertThat(notif.getMessage()).startsWith("actor=");
- }
-
- /**
- * Waits for a FINAL SUCCESS transaction notification.
- */
- protected void waitForFinalSuccess(ToscaPolicy policy, TopicCallback<VirtualControlLoopNotification> policyClMgt) {
- await().until(() -> !policyClMgt.getMessages().isEmpty());
- assertEquals(ControlLoopNotificationType.FINAL_SUCCESS, policyClMgt.getMessages().peek().getNotification());
- assertEquals(policy.getIdentifier().getName() + ".EVENT.MANAGER.FINAL",
- policyClMgt.getMessages().remove().getPolicyName());
- }
-
- /**
- * Logs Modifications to Working Memory.
- */
- static class RuleListenerLogger implements RuleRuntimeEventListener {
- @Override
- public void objectInserted(ObjectInsertedEvent event) {
- String ruleName = (event.getRule() != null) ? event.getRule().getName() : "null";
- logger.info("RULE {}: inserted {}", ruleName, event.getObject());
- }
-
- @Override
- public void objectUpdated(ObjectUpdatedEvent event) {
- String ruleName = (event.getRule() != null) ? event.getRule().getName() : "null";
- logger.info("RULE {}: updated {}", ruleName, event.getObject());
-
- }
-
- @Override
- public void objectDeleted(ObjectDeletedEvent event) {
- String ruleName = (event.getRule() != null) ? event.getRule().getName() : "null";
- logger.info("RULE {}: deleted {}", ruleName, event.getOldObject());
- }
- }
-
- /**
- * Logs Rule Matches.
- */
- static class AgendaListenerLogger extends DefaultAgendaEventListener {
- @Override
- public void matchCreated(MatchCreatedEvent event) {
- logger.info("RULE {}: match created", event.getMatch().getRule().getName());
- }
-
- @Override
- public void matchCancelled(MatchCancelledEvent event) {
- logger.info("RULE {}: match cancelled", event.getMatch().getRule().getName());
- }
-
- @Override
- public void beforeMatchFired(BeforeMatchFiredEvent event) {
- logger.info("RULE {}: before match fired", event.getMatch().getRule().getName());
- }
-
- @Override
- public void afterMatchFired(AfterMatchFiredEvent event) {
- logger.info("RULE {}: after match fired", event.getMatch().getRule().getName());
- }
- }
-
- /**
- * Base Class to track Working Memory updates for objects of type T.
- */
- abstract class KieObjectExpectedCallback<T> extends DefaultRuleRuntimeEventListener {
- protected T subject;
-
- protected CountDownLatch countDownLatch = new CountDownLatch(1);
-
- public KieObjectExpectedCallback(T affected) {
- subject = affected;
- register();
- }
-
- public boolean isNotified() throws InterruptedException {
- return countDownLatch.await(9L, TimeUnit.SECONDS);
- }
-
- protected void callbacked() {
- unregister();
- countDownLatch.countDown();
- }
-
- public KieObjectExpectedCallback<T> register() {
- controller.getDrools().getContainer().getPolicySession(CONTROLLER_NAME).getKieSession()
- .addEventListener(this);
- return this;
- }
-
- public KieObjectExpectedCallback<T> unregister() {
- controller.getDrools().getContainer().getPolicySession(CONTROLLER_NAME).getKieSession()
- .removeEventListener(this);
- return this;
- }
- }
-
- /**
- * Tracks inserts in Working Memory for an object of type T.
- */
- class KieObjectInsertedExpectedCallback<T> extends KieObjectExpectedCallback<T> {
- public KieObjectInsertedExpectedCallback(T affected) {
- super(affected);
- }
-
- @Override
- public void objectInserted(ObjectInsertedEvent event) {
- if (subject == event.getObject()) {
- callbacked();
- }
- }
- }
-
- /**
- * Tracks deletes in Working Memory of an object of type T.
- */
- class KieObjectDeletedExpectedCallback<T> extends KieObjectExpectedCallback<T> {
- public KieObjectDeletedExpectedCallback(T affected) {
- super(affected);
- }
-
- @Override
- public void objectDeleted(ObjectDeletedEvent event) {
- if (subject == event.getOldObject()) {
- callbacked();
- }
- }
- }
-
- /**
- * Tracks inserts in Working Memory for any object of class T.
- */
- class KieClassInsertedExpectedCallback<T> extends KieObjectInsertedExpectedCallback<T> {
-
- public KieClassInsertedExpectedCallback(T affected) {
- super(affected);
- }
-
- public void objectInserted(ObjectInsertedEvent event) {
- if (subject == event.getObject().getClass()) {
- callbacked();
- }
- }
- }
-
- /**
- * Tracks callbacks from topics.
- */
- class TopicCallback<T> implements TopicListener {
- protected final Topic topic;
- protected final Class<T> expectedClass;
-
- @Getter
- protected Queue<T> messages = new LinkedList<>();
-
- public TopicCallback(Topic topic, Class<T> expectedClass) {
- this.topic = topic;
- this.expectedClass = expectedClass;
- this.topic.register(this);
- }
-
- public TopicCallback<T> register() {
- this.topic.register(this);
- return this;
- }
-
- public TopicCallback<T> unregister() {
- this.topic.unregister(this);
- return this;
- }
-
- @Override
- @SuppressWarnings("unchecked")
- public void onTopicEvent(CommInfrastructure comm, String topic, String event) {
- try {
- messages.add((T) EventProtocolCoderConstants.getManager().decode(controller.getDrools().getGroupId(),
- controller.getDrools().getArtifactId(), topic, event));
- } catch (Exception e) {
- logger.warn("invalid mapping in topic {} for event {}", topic, event, e);
- }
- }
- }
-
- class TopicCallbackCoder<T> extends TopicCallback<T> {
- private final Coder coder;
-
- public TopicCallbackCoder(Topic topic, Class<T> expectedClass, Coder coder) {
- super(topic, expectedClass);
- this.coder = coder;
- }
-
- @Override
- public void onTopicEvent(CommInfrastructure comm, String topic, String event) {
- try {
- messages.add((T) coder.decode(event, expectedClass));
- } catch (Exception e) {
- logger.warn("invalid mapping in topic {} for event {}", topic, event, e);
- }
- }
-
- }
-}
diff --git a/controlloop/common/controller-frankfurt/src/test/java/org/onap/policy/controlloop/FrankfurtTest.java b/controlloop/common/controller-frankfurt/src/test/java/org/onap/policy/controlloop/FrankfurtTest.java
new file mode 100644
index 000000000..7b8b99a25
--- /dev/null
+++ b/controlloop/common/controller-frankfurt/src/test/java/org/onap/policy/controlloop/FrankfurtTest.java
@@ -0,0 +1,113 @@
+/*-
+ * ============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.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.runner.RunWith;
+import org.onap.policy.controlloop.common.rules.test.BaseRuleTest;
+import org.onap.policy.controlloop.common.rules.test.Listener;
+import org.onap.policy.controlloop.common.rules.test.NamedRunner;
+import org.onap.policy.controlloop.common.rules.test.TestNames;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
+import org.onap.policy.simulators.Util;
+
+/**
+ * Tests use cases using Frankfurt rules.
+ *
+ * <p/>
+ * Note: this runs ALL tests (i.e., any whose names start with "test").
+ */
+@RunWith(NamedRunner.class)
+@TestNames(prefixes = {"test"})
+
+public class FrankfurtTest extends BaseRuleTest {
+ protected static final String CONTROLLER_NAME = "frankfurt";
+
+
+ /**
+ * Sets up statics.
+ */
+ @BeforeClass
+ public static void setUpBeforeClass() {
+ initStatics(CONTROLLER_NAME);
+
+ rules.configure("src/main/resources");
+ rules.start();
+ httpClients.addClients("frankfurt");
+ simulators.start(Util::buildAaiSim, Util::buildSoSim, Util::buildVfcSim, Util::buildGuardSim,
+ Util::buildSdncSim);
+ }
+
+ /**
+ * Cleans up statics.
+ */
+ @AfterClass
+ public static void tearDownAfterClass() {
+ finishStatics();
+ }
+
+ /**
+ * Sets up.
+ */
+ @Before
+ public void setUp() {
+ init();
+ }
+
+ /**
+ * Tears down.
+ */
+ @After
+ public void tearDown() {
+ finish();
+ }
+
+ @Override
+ protected void waitForLockAndPermit(ToscaPolicy policy, Listener<VirtualControlLoopNotification> policyClMgt) {
+ String policyName = policy.getIdentifier().getName();
+
+ policyClMgt.await(notif -> notif.getNotification() == ControlLoopNotificationType.ACTIVE
+ && (policyName + ".EVENT").equals(notif.getPolicyName()));
+
+ policyClMgt.await(notif -> notif.getNotification() == ControlLoopNotificationType.OPERATION
+ && (policyName + ".EVENT.MANAGER.PROCESSING").equals(notif.getPolicyName())
+ && notif.getMessage().startsWith("Sending guard query"));
+
+ policyClMgt.await(notif -> notif.getNotification() == ControlLoopNotificationType.OPERATION
+ && (policyName + ".EVENT.MANAGER.PROCESSING").equals(notif.getPolicyName())
+ && notif.getMessage().startsWith("Guard result") && notif.getMessage().endsWith("Permit"));
+
+ policyClMgt.await(notif -> notif.getNotification() == ControlLoopNotificationType.OPERATION
+ && (policyName + ".EVENT.MANAGER.PROCESSING").equals(notif.getPolicyName())
+ && notif.getMessage().startsWith("actor="));
+ }
+
+ @Override
+ protected VirtualControlLoopNotification waitForFinal(ToscaPolicy policy,
+ Listener<VirtualControlLoopNotification> policyClMgt, ControlLoopNotificationType finalType) {
+
+ return policyClMgt.await(notif -> notif.getNotification() == finalType
+ && (policy.getIdentifier().getName() + ".EVENT.MANAGER.FINAL").equals(notif.getPolicyName()));
+ }
+}
diff --git a/controlloop/common/controller-frankfurt/src/test/java/org/onap/policy/controlloop/VcpeTest.java b/controlloop/common/controller-frankfurt/src/test/java/org/onap/policy/controlloop/VcpeTest.java
deleted file mode 100644
index ff3f7427a..000000000
--- a/controlloop/common/controller-frankfurt/src/test/java/org/onap/policy/controlloop/VcpeTest.java
+++ /dev/null
@@ -1,206 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2019-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 static org.awaitility.Awaitility.await;
-import static org.junit.Assert.assertEquals;
-
-import java.io.IOException;
-import java.nio.file.Paths;
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.onap.policy.appclcm.AppcLcmDmaapWrapper;
-import org.onap.policy.common.utils.coder.CoderException;
-import org.onap.policy.common.utils.coder.StandardCoder;
-import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
-
-/**
- * VCPE Use Case Tests.
- */
-public class VcpeTest extends FrankfurtBase {
-
- /**
- * VCPE Tosca Policy File.
- */
- private static final String TOSCA_LEGACY_POLICY_VCPE = "src/test/resources/vcpe/tosca-legacy-vcpe.json";
- private static final String TOSCA_COMPLIANT_POLICY_VCPE = "src/test/resources/vcpe/tosca-compliant-vcpe.json";
-
- /*
- * VCPE Use case Messages.
- */
- private static final String APPC_SUCCESS = "src/test/resources/vcpe/vcpe.appc.success.json";
- private static final String ONSET_1 = "src/test/resources/vcpe/vcpe.onset.1.json";
- private static final String ONSET_2 = "src/test/resources/vcpe/vcpe.onset.2.json";
- private static final String ONSET_3 = "src/test/resources/vcpe/vcpe.onset.3.json";
-
- /*
- * Topic trackers used by the VCPE use case.
- */
- private TopicCallback<VirtualControlLoopNotification> policyClMgt;
- private TopicCallback<AppcLcmDmaapWrapper> appcLcmRead;
- private TopicCallback<AppcLcmDmaapWrapper> appcLcmWrite;
-
- /*
- * VCPE Tosca Policy.
- */
- private ToscaPolicy policy;
-
- /**
- * Prepare PDP-D Framework for testing.
- */
- @BeforeClass
- public static void prepareResouces() throws InterruptedException, CoderException, IOException {
- initConfigDir();
- setupLogging();
- preparePdpD();
- setUpHttpClients();
- setupSimulators();
- }
-
- /**
- * Take down the resources used by the test framework.
- */
- @AfterClass
- public static void takeDownResources() {
- stopPdpD();
- stopSimulators();
- }
-
- /**
- * Observe Topics.
- */
- @Before
- public void topicsRegistration() {
- resetFacts();
-
- policyClMgt = createTopicSinkCallback(POLICY_CL_MGT_TOPIC, VirtualControlLoopNotification.class);
- appcLcmRead = createTopicSinkCallbackPlain(APPC_LCM_READ_TOPIC, AppcLcmDmaapWrapper.class, new StandardCoder());
- appcLcmWrite = createTopicSourceCallback(APPC_LCM_WRITE_TOPIC, AppcLcmDmaapWrapper.class);
- }
-
- /**
- * Unregister Topic Callbacks.
- */
- @After
- public void topicsUnregistration() throws InterruptedException {
- if (policyClMgt != null) {
- policyClMgt.unregister();
- }
-
- if (appcLcmRead != null) {
- appcLcmRead.unregister();
- }
-
- if (appcLcmWrite != null) {
- appcLcmWrite.unregister();
- }
- }
-
- /**
- * Sunny Day with Legacy Tosca Policy.
- */
- @Test
- public void sunnyDayLegacy() throws InterruptedException, CoderException, IOException {
- assertEquals(0, controller.getDrools().factCount(CONTROLLER_NAME));
- policy = setupPolicyFromFile(TOSCA_LEGACY_POLICY_VCPE);
- assertEquals(2, controller.getDrools().factCount(CONTROLLER_NAME));
-
- sunnyDay();
- }
-
- /**
- * Sunny Day with Tosca Compliant Policy.
- */
- @Test
- public void sunnyDayCompliant() throws InterruptedException, CoderException, IOException {
- assertEquals(0, controller.getDrools().factCount(CONTROLLER_NAME));
- policy = setupPolicyFromFile(TOSCA_COMPLIANT_POLICY_VCPE);
- assertEquals(2, controller.getDrools().factCount(CONTROLLER_NAME));
-
- sunnyDay();
- }
-
- /**
- * An ONSET flood prevention test that injects a few ONSETs at once. It attempts to
- * simulate the flooding behavior of the DCAE TCA microservice. TCA could blast tenths
- * or hundreds of ONSETs within sub-second intervals.
- */
- @Test
- public void onsetFloodPrevention() throws IOException, InterruptedException, CoderException {
- assertEquals(0, controller.getDrools().factCount(CONTROLLER_NAME));
- policy = setupPolicyFromFile(TOSCA_LEGACY_POLICY_VCPE);
- assertEquals(2, controller.getDrools().factCount(CONTROLLER_NAME));
-
- injectOnTopic(DCAE_TOPIC, Paths.get(ONSET_1));
- injectOnTopic(DCAE_TOPIC, Paths.get(ONSET_2));
- injectOnTopic(DCAE_TOPIC, Paths.get(ONSET_3));
-
- assertEquals(1, controller.getDrools().facts(CONTROLLER_NAME, VirtualControlLoopEvent.class).stream().count());
- assertEquals(1, controller.getDrools().facts(CONTROLLER_NAME, CanonicalOnset.class).stream().count());
- assertEquals(controller.getDrools().facts(CONTROLLER_NAME, CanonicalOnset.class).get(0),
- controller.getDrools().facts(CONTROLLER_NAME, VirtualControlLoopEvent.class).get(0));
-
- sunnyDay();
- }
-
- /**
- * Sunny day scenario for the VCPE use case.
- */
- public void sunnyDay() throws IOException {
-
- /* Inject an ONSET event over the DCAE topic */
- injectOnTopic(DCAE_TOPIC, Paths.get(ONSET_1));
-
- /* Wait to acquire a LOCK and a PDP-X PERMIT */
- waitForLockAndPermit(policy, policyClMgt);
-
- /* --- VCPE Operation Execution --- */
-
- /*
- * Ensure that an APPC RESTART request was sent in response to the matching ONSET
- */
- await().until(() -> !appcLcmRead.getMessages().isEmpty());
- AppcLcmDmaapWrapper appcreq = appcLcmRead.getMessages().remove();
- assertEquals("restart", appcreq.getRpcName());
-
- /* Inject a 400 APPC Response Return over the APPC topic */
- injectOnTopic(APPC_LCM_WRITE_TOPIC, Paths.get(APPC_SUCCESS),
- appcreq.getBody().getInput().getCommonHeader().getSubRequestId());
-
- /* Ensure that RESTART response is received */
- await().until(() -> !appcLcmWrite.getMessages().isEmpty());
- assertEquals("restart", appcLcmWrite.getMessages().peek().getRpcName());
- assertEquals(400, appcLcmWrite.getMessages().remove().getBody().getOutput().getStatus().getCode());
-
- /* --- VCPE Operation Completed --- */
-
- /* Ensure that the VCPE RESTART Operation is successfully completed */
- await().until(() -> !policyClMgt.getMessages().isEmpty());
- assertEquals(ControlLoopNotificationType.OPERATION_SUCCESS,
- policyClMgt.getMessages().remove().getNotification());
-
- /* --- VCPE Transaction Completed --- */
- waitForFinalSuccess(policy, policyClMgt);
- }
-}
diff --git a/controlloop/common/controller-frankfurt/src/test/java/org/onap/policy/controlloop/VdnsTest.java b/controlloop/common/controller-frankfurt/src/test/java/org/onap/policy/controlloop/VdnsTest.java
deleted file mode 100644
index c9963a4ec..000000000
--- a/controlloop/common/controller-frankfurt/src/test/java/org/onap/policy/controlloop/VdnsTest.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*-
- * ============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 static org.awaitility.Awaitility.await;
-import static org.junit.Assert.assertEquals;
-
-import java.io.IOException;
-import java.nio.file.Paths;
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.onap.policy.common.utils.coder.CoderException;
-import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
-
-/**
- * VDNS Use Case Tests.
- */
-public class VdnsTest extends FrankfurtBase {
-
- /**
- * VDNS Tosca Policy File.
- */
- private static final String TOSCA_COMPLIANT_POLICY_VDNS = "src/test/resources/vdns/tosca-compliant-vdns.json";
-
- /*
- * VDNS Use case Messages.
- */
- private static final String ONSET = "src/test/resources/vdns/vdns.onset.json";
-
- /*
- * Topic trackers used by the VDNS use case.
- */
- private TopicCallback<VirtualControlLoopNotification> policyClMgt;
-
- /*
- * VDNS Tosca Policy.
- */
- private ToscaPolicy policy;
-
- /**
- * Prepare PDP-D Framework for testing.
- */
- @BeforeClass
- public static void prepareResouces() throws InterruptedException, IOException {
- initConfigDir();
- setupLogging();
- preparePdpD();
- setUpHttpClients();
- setupSimulators();
- }
-
- /**
- * Take down the resources used by the test framework.
- */
- @AfterClass
- public static void takeDownResources() {
- stopPdpD();
- stopSimulators();
- }
-
- /**
- * Observe Topics.
- */
- @Before
- public void topicsRegistration() {
- policyClMgt = createTopicSinkCallback(POLICY_CL_MGT_TOPIC, VirtualControlLoopNotification.class);
- }
-
- /**
- * Unregister Topic Callbacks and uninstall the policy.
- */
- @After
- public void topicsUnregistration() throws InterruptedException {
- if (policyClMgt != null) {
- policyClMgt.unregister();
- }
-
- // uninstall the policy
- assertEquals(2, controller.getDrools().factCount(CONTROLLER_NAME));
- if (policy != null) {
- deletePolicy(policy);
- }
- assertEquals(0, controller.getDrools().factCount(CONTROLLER_NAME));
- }
-
- /**
- * Sunny Day with Tosca Compliant Policy.
- */
- @Test
- public void sunnyDayCompliant() throws InterruptedException, CoderException, IOException {
- assertEquals(0, controller.getDrools().factCount(CONTROLLER_NAME));
- policy = setupPolicyFromFile(TOSCA_COMPLIANT_POLICY_VDNS);
- assertEquals(2, controller.getDrools().factCount(CONTROLLER_NAME));
-
- sunnyDay();
- }
-
- /**
- * Sunny day scenario for the VCPE use case.
- */
- private void sunnyDay() throws IOException {
-
- /* Inject an ONSET event over the DCAE topic */
- injectOnTopic(DCAE_TOPIC, Paths.get(ONSET));
-
- /* Wait to acquire a LOCK and a PDP-X PERMIT */
- waitForLockAndPermit(policy, policyClMgt);
-
- /* Ensure that the VDNS SO Operation was successfully completed */
-
- await().until(() -> !policyClMgt.getMessages().isEmpty());
- assertEquals(ControlLoopNotificationType.OPERATION_SUCCESS,
- policyClMgt.getMessages().remove().getNotification());
-
- /* --- VDNS Transaction Completed --- */
- waitForFinalSuccess(policy, policyClMgt);
- }
-}
diff --git a/controlloop/common/controller-frankfurt/src/test/java/org/onap/policy/controlloop/VfwTest.java b/controlloop/common/controller-frankfurt/src/test/java/org/onap/policy/controlloop/VfwTest.java
deleted file mode 100644
index 2d0cb7630..000000000
--- a/controlloop/common/controller-frankfurt/src/test/java/org/onap/policy/controlloop/VfwTest.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*-
- * ============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 static org.awaitility.Awaitility.await;
-import static org.junit.Assert.assertEquals;
-
-import java.io.IOException;
-import java.nio.file.Paths;
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.onap.policy.appc.Request;
-import org.onap.policy.appc.Response;
-import org.onap.policy.common.utils.coder.CoderException;
-import org.onap.policy.common.utils.coder.StandardCoderInstantAsMillis;
-import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
-
-/**
- * VFW Use Case Tests.
- */
-public class VfwTest extends FrankfurtBase {
-
- /**
- * VFW Tosca Policy File.
- */
- private static final String TOSCA_LEGACY_POLICY_VFW = "src/test/resources/vfw/tosca-vfw.json";
- private static final String TOSCA_COMPLIANT_POLICY_VFW = "src/test/resources/vfw/tosca-compliant-vfw.json";
-
- /*
- * VFW Use case Messages.
- */
- private static final String APPC_SUCCESS = "src/test/resources/vfw/vfw.appc.success.json";
- private static final String ONSET = "src/test/resources/vfw/vfw.onset.json";
-
- /*
- * Topic trackers used by the VFW use case.
- */
- private TopicCallback<VirtualControlLoopNotification> policyClMgt;
- private TopicCallback<Response> appcClSource;
- private TopicCallback<Request> appcClSink;
-
- /*
- * VFW Tosca Policy.
- */
- private ToscaPolicy policy;
-
- /**
- * Prepare PDP-D Framework for testing.
- */
- @BeforeClass
- public static void prepareResouces() throws InterruptedException, IOException {
- initConfigDir();
- setupLogging();
- preparePdpD();
- setUpHttpClients();
- setupSimulators();
- }
-
- /**
- * Take down the resources used by the test framework.
- */
- @AfterClass
- public static void takeDownResources() {
- stopPdpD();
- stopSimulators();
- }
-
- /**
- * Observe Topics.
- */
- @Before
- public void topicsRegistration() {
- policyClMgt = createTopicSinkCallback(POLICY_CL_MGT_TOPIC, VirtualControlLoopNotification.class);
- appcClSink = createTopicSinkCallbackPlain(APPC_CL_TOPIC, Request.class, new StandardCoderInstantAsMillis());
- appcClSource = createTopicSourceCallback(APPC_CL_TOPIC, Response.class);
- }
-
- /**
- * Unregister Topic Callbacks.
- */
- @After
- public void topicsUnregistration() throws InterruptedException {
- if (policyClMgt != null) {
- policyClMgt.unregister();
- }
-
- if (appcClSource != null) {
- appcClSource.unregister();
- }
-
- if (appcClSink != null) {
- appcClSink.unregister();
- }
-
- // uninstall the policy
- assertEquals(2, controller.getDrools().factCount(CONTROLLER_NAME));
- if (policy != null) {
- deletePolicy(policy);
- }
- assertEquals(0, controller.getDrools().factCount(CONTROLLER_NAME));
- }
-
- /**
- * Sunny Day with Legacy Tosca Policy.
- */
- @Test
- public void sunnyDayLegacy() throws InterruptedException, CoderException, IOException {
- assertEquals(0, controller.getDrools().factCount(CONTROLLER_NAME));
- policy = setupPolicyFromFile(TOSCA_LEGACY_POLICY_VFW);
- assertEquals(2, controller.getDrools().factCount(CONTROLLER_NAME));
-
- sunnyDay();
- }
-
- /**
- * Sunny Day with Tosca Compliant Policy.
- */
- @Test
- public void sunnyDayCompliant() throws InterruptedException, CoderException, IOException {
- assertEquals(0, controller.getDrools().factCount(CONTROLLER_NAME));
- policy = setupPolicyFromFile(TOSCA_COMPLIANT_POLICY_VFW);
- assertEquals(2, controller.getDrools().factCount(CONTROLLER_NAME));
-
- sunnyDay();
- }
-
- /**
- * Sunny day scenario for the VFW use case.
- */
- private void sunnyDay() throws IOException {
-
- /* Inject an ONSET event over the DCAE topic */
- injectOnTopic(DCAE_TOPIC, Paths.get(ONSET));
-
- /* Wait to acquire a LOCK and a PDP-X PERMIT */
- waitForLockAndPermit(policy, policyClMgt);
-
- /* --- VFW Operation Execution --- */
-
- /*
- * Ensure that an APPC RESTART request was sent in response to the matching ONSET
- */
- await().until(() -> !appcClSink.getMessages().isEmpty());
- Request appcreq = appcClSink.getMessages().remove();
- assertEquals("ModifyConfig", appcreq.getAction());
-
- /*
- * Inject a 400 APPC Response Return over the APPC topic, with appropriate
- * subRequestId
- */
- injectOnTopic(APPC_CL_TOPIC, Paths.get(APPC_SUCCESS), appcreq.getCommonHeader().getSubRequestId());
-
- /* Ensure that RESTART response is received */
- await().until(() -> !appcClSource.getMessages().isEmpty());
- assertEquals("SUCCESS", appcClSource.getMessages().remove().getStatus().getValue());
-
- /* --- VFW Operation Completed --- */
-
- /* Ensure that the VFW RESTART Operation is successfully completed */
- await().until(() -> !policyClMgt.getMessages().isEmpty());
- assertEquals(ControlLoopNotificationType.OPERATION_SUCCESS,
- policyClMgt.getMessages().remove().getNotification());
-
- /* --- VFW Transaction Completed --- */
- waitForFinalSuccess(policy, policyClMgt);
- }
-}
diff --git a/controlloop/common/controller-frankfurt/src/test/java/org/onap/policy/controlloop/VlbTest.java b/controlloop/common/controller-frankfurt/src/test/java/org/onap/policy/controlloop/VlbTest.java
deleted file mode 100644
index 4e5a6e3c7..000000000
--- a/controlloop/common/controller-frankfurt/src/test/java/org/onap/policy/controlloop/VlbTest.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*-
- * ============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 static org.awaitility.Awaitility.await;
-import static org.junit.Assert.assertEquals;
-
-import java.io.IOException;
-import java.nio.file.Paths;
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.onap.policy.common.utils.coder.CoderException;
-import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
-
-/**
- * VLB Use Case Tests.
- */
-public class VlbTest extends FrankfurtBase {
-
- /**
- * VLB Tosca Policy File.
- */
- private static final String TOSCA_LEGACY_POLICY_VLB = "src/test/resources/vlb/tosca-vlb.json";
- private static final String TOSCA_COMPLIANT_POLICY_VLB = "src/test/resources/vlb/tosca-compliant-vlb.json";
-
- /*
- * VLB Use case Messages.
- */
- private static final String ONSET = "src/test/resources/vlb/vlb.onset.json";
-
- /*
- * Topic trackers used by the VLB use case.
- */
- private TopicCallback<VirtualControlLoopNotification> policyClMgt;
-
- /*
- * VLB Tosca Policy.
- */
- private ToscaPolicy policy;
-
- /**
- * Prepare PDP-D Framework for testing.
- */
- @BeforeClass
- public static void prepareResouces() throws InterruptedException, IOException {
- initConfigDir();
- setupLogging();
- preparePdpD();
- setUpHttpClients();
- setupSimulators();
- }
-
- /**
- * Take down the resources used by the test framework.
- */
- @AfterClass
- public static void takeDownResources() {
- stopPdpD();
- stopSimulators();
- }
-
- /**
- * Observe Topics.
- */
- @Before
- public void topicsRegistration() {
- policyClMgt = createTopicSinkCallback(POLICY_CL_MGT_TOPIC, VirtualControlLoopNotification.class);
- }
-
- /**
- * Unregister Topic Callbacks and uninstall the policy.
- */
- @After
- public void topicsUnregistration() throws InterruptedException {
- if (policyClMgt != null) {
- policyClMgt.unregister();
- }
-
- // uninstall the policy
- assertEquals(2, controller.getDrools().factCount(CONTROLLER_NAME));
- if (policy != null) {
- deletePolicy(policy);
- }
- assertEquals(0, controller.getDrools().factCount(CONTROLLER_NAME));
- }
-
- /**
- * Sunny Day with Legacy Tosca Policy.
- */
- @Test
- public void sunnyDayLegacy() throws InterruptedException, CoderException, IOException {
- assertEquals(0, controller.getDrools().factCount(CONTROLLER_NAME));
- policy = setupPolicyFromFile(TOSCA_LEGACY_POLICY_VLB);
- assertEquals(2, controller.getDrools().factCount(CONTROLLER_NAME));
-
- sunnyDay();
- }
-
- /**
- * Sunny Day with Tosca Compliant Policy.
- */
- @Test
- public void sunnyDayCompliant() throws InterruptedException, CoderException, IOException {
- assertEquals(0, controller.getDrools().factCount(CONTROLLER_NAME));
- policy = setupPolicyFromFile(TOSCA_COMPLIANT_POLICY_VLB);
- assertEquals(2, controller.getDrools().factCount(CONTROLLER_NAME));
-
- sunnyDay();
- }
-
- /**
- * Sunny day scenario for the VCPE use case.
- */
- private void sunnyDay() throws IOException {
-
- /* Inject an ONSET event over the DCAE topic */
- injectOnTopic(DCAE_TOPIC, Paths.get(ONSET));
-
- /* Wait to acquire a LOCK and a PDP-X PERMIT */
- waitForLockAndPermit(policy, policyClMgt);
-
- /* Ensure that the VLB SO Operation was successfully completed */
-
- await().until(() -> !policyClMgt.getMessages().isEmpty());
- assertEquals(ControlLoopNotificationType.OPERATION_SUCCESS,
- policyClMgt.getMessages().remove().getNotification());
-
- /* --- VLB Transaction Completed --- */
- waitForFinalSuccess(policy, policyClMgt);
- }
-}
diff --git a/controlloop/common/controller-frankfurt/src/test/resources/config/frankfurt-controller.properties b/controlloop/common/controller-frankfurt/src/test/resources/config/frankfurt-controller.properties
index 694f66e61..025a60bfa 100644
--- a/controlloop/common/controller-frankfurt/src/test/resources/config/frankfurt-controller.properties
+++ b/controlloop/common/controller-frankfurt/src/test/resources/config/frankfurt-controller.properties
@@ -28,10 +28,10 @@ noop.source.topics=DCAE_TOPIC,APPC-CL,APPC-LCM-WRITE,SDNR-CL-RSP,POLICY-CL-MGT,A
noop.source.topics.DCAE_TOPIC.events=\
org.onap.policy.controlloop.CanonicalOnset,org.onap.policy.controlloop.CanonicalAbated
-noop.source.topics.DCAE_TOPIC.events.org.onap.policy.controlloop.CanonicalOnset.filter=\
- [?($.closedLoopEventStatus == 'ONSET')]
-noop.source.topics.DCAE_TOPIC.events.org.onap.policy.controlloop.CanonicalAbated.filter=\
- [?($.closedLoopEventStatus == 'ABATED')]
+noop.source.topics.DCAE_TOPIC.events.org.onap.policy.controlloop.CanonicalOnset.\
+ filter=[?($.closedLoopEventStatus == 'ONSET')]
+noop.source.topics.DCAE_TOPIC.events.org.onap.policy.controlloop.CanonicalAbated.\
+ filter=[?($.closedLoopEventStatus == 'ABATED')]
noop.source.topics.DCAE_TOPIC.events.custom.gson=org.onap.policy.controlloop.util.Serialization,gson
noop.source.topics.APPC-CL.events=org.onap.policy.appc.Response,org.onap.policy.appc.Request
diff --git a/controlloop/common/controller-frankfurt/src/test/resources/vcpe/vcpe.onset.3.json b/controlloop/common/controller-frankfurt/src/test/resources/vcpe/vcpe.onset.3.json
deleted file mode 100644
index 74a94eb0a..000000000
--- a/controlloop/common/controller-frankfurt/src/test/resources/vcpe/vcpe.onset.3.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "closedLoopControlName": "ControlLoop-vCPE-48f0c2c3-a172-4192-9ae3-052274181b6e",
- "closedLoopAlarmStart": 1570722876324905,
- "closedLoopAlarmEnd": 1570722876324999,
- "closedLoopEventClient": "DCAE_INSTANCE_ID.dcae-tca",
- "closedLoopEventStatus": "ONSET",
- "requestID": "664be3d2-6c12-4f4b-a3e7-c349acced200",
- "target_type": "VNF",
- "target": "generic-vnf.vnf-id",
- "AAI": {
- "vserver.is-closed-loop-disabled": "false",
- "vserver.prov-status": "ACTIVE",
- "generic-vnf.vnf-id": "vCPE_Infrastructure_vGMUX_demo_app"
- },
- "from": "DCAE",
- "version": "1.0.2"
-} \ No newline at end of file
diff --git a/controlloop/common/controller-frankfurt/src/test/resources/vfw/tosca-vfw.json b/controlloop/common/controller-frankfurt/src/test/resources/vfw/tosca-vfw.json
deleted file mode 100644
index 5d1e35277..000000000
--- a/controlloop/common/controller-frankfurt/src/test/resources/vfw/tosca-vfw.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "type": "onap.policies.controlloop.Operational",
- "type_version": "1.0.0",
- "properties": {
- "content": "controlLoop%3A%0A%20%20version%3A%202.0.0%0A%20%20controlLoopName%3A%20ControlLoop-vFirewall-d0a1dfc6-94f5-4fd4-a5b5-4630b438850a%0A%20%20services%3A%0A%20%20%20%20-%20serviceInvariantUUID%3A%20f6937c86-584c-47ae-ad29-8d41d6f0cc7c%0A%20%20%20%20%20%20serviceUUID%3A%207be584e2-0bb2-4126-adaf-ced2c77ca0b3%0A%20%20%20%20%20%20serviceName%3A%20Service_Ete_Name7ba1fbde-6187-464a-a62d-d9dd25bdf4e8%0A%20%20trigger_policy%3A%20unique-policy-id-1-modifyConfig%0A%20%20timeout%3A%2060%0A%20%20abatement%3A%20false%0A%20%0Apolicies%3A%0A%20%20-%20id%3A%20unique-policy-id-1-modifyConfig%0A%20%20%20%20name%3A%20modify%20packet%20gen%20config%0A%20%20%20%20description%3A%0A%20%20%20%20actor%3A%20APPC%0A%20%20%20%20recipe%3A%20ModifyConfig%0A%20%20%20%20target%3A%0A%20%20%20%20%20%20resourceID%3A%20bbb3cefd-01c8-413c-9bdd-2b92f9ca3d38%0A%20%20%20%20%20%20type%3A%20VNF%0A%20%20%20%20retry%3A%200%0A%20%20%20%20timeout%3A%2030%0A%20%20%20%20success%3A%20final_success%0A%20%20%20%20failure%3A%20final_failure%0A%20%20%20%20failure_timeout%3A%20final_failure_timeout%0A%20%20%20%20failure_retries%3A%20final_failure_retries%0A%20%20%20%20failure_exception%3A%20final_failure_exception%0A%20%20%20%20failure_guard%3A%20final_failure_guard"
- },
- "name": "vfw",
- "version": "1.0.0"
-} \ No newline at end of file
diff --git a/controlloop/common/controller-frankfurt/src/test/resources/vlb/tosca-compliant-vlb.json b/controlloop/common/controller-frankfurt/src/test/resources/vlb/tosca-compliant-vlb.json
deleted file mode 100644
index aeb22bb0b..000000000
--- a/controlloop/common/controller-frankfurt/src/test/resources/vlb/tosca-compliant-vlb.json
+++ /dev/null
@@ -1,48 +0,0 @@
-{
- "type": "onap.policies.controlloop.operational.common.Drools",
- "type_version": "1.0.0",
- "name": "operational.scaleout",
- "version": "1.0.0",
- "metadata": {
- "policy-id": "operational.scaleout"
- },
- "properties": {
- "id": "ControlLoop-vDNS-6f37f56d-a87d-4b85-b6a9-cc953cf779b3",
- "timeout": 1200,
- "abatement": false,
- "trigger": "unique-policy-id-1-scale-up",
- "operations": [
- {
- "id": "unique-policy-id-1-scale-up",
- "description": "Create a new VF Module",
- "operation": {
- "actor": "SO",
- "operation": "VF Module Create",
- "target": {
- "targetType": "VFMODULE",
- "entityIds": {
- "modelInvariantId": "e6130d03-56f1-4b0a-9a1d-e1b2ebc30e0e",
- "modelVersionId": "94b18b1d-cc91-4f43-911a-e6348665f292",
- "modelName": "VfwclVfwsnkBbefb8ce2bde..base_vfw..module-0",
- "modelVersion": 1,
- "modelCustomizationId": "47958575-138f-452a-8c8d-d89b595f8164"
- }
- },
- "payload": {
- "requestParameters": "{\"usePreload\":true,\"userParams\":[]}",
- "configurationParameters": "[{\"ip-addr\":\"$.vf-module-topology.vf-module-parameters.param[9]\",\"oam-ip-addr\":\"$.vf-module-topology.vf-module-parameters.param[16]\",\"enabled\":\"$.vf-module-topology.vf-module-parameters.param[23]\"}]"
- }
- },
- "timeout": 1200,
- "retries": 0,
- "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": "frankfurt"
- }
-}
diff --git a/controlloop/common/controller-usecases/pom.xml b/controlloop/common/controller-usecases/pom.xml
index fb29a81c7..6c69e7f89 100644
--- a/controlloop/common/controller-usecases/pom.xml
+++ b/controlloop/common/controller-usecases/pom.xml
@@ -180,9 +180,9 @@
<optional>true</optional>
</dependency>
<dependency>
- <groupId>org.onap.policy.models.policy-models-interactions</groupId>
- <artifactId>simulators</artifactId>
- <version>${policy.models.version}</version>
+ <groupId>org.onap.policy.drools-applications.controlloop.common</groupId>
+ <artifactId>rules-test</artifactId>
+ <version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
diff --git a/controlloop/common/controller-usecases/src/test/java/org/onap/policy/controlloop/UsecasesBase.java b/controlloop/common/controller-usecases/src/test/java/org/onap/policy/controlloop/UsecasesBase.java
deleted file mode 100644
index 66ad32462..000000000
--- a/controlloop/common/controller-usecases/src/test/java/org/onap/policy/controlloop/UsecasesBase.java
+++ /dev/null
@@ -1,515 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2019-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 static org.awaitility.Awaitility.await;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.Properties;
-import java.util.Queue;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import lombok.Getter;
-import org.apache.commons.lang3.StringUtils;
-import org.kie.api.event.rule.AfterMatchFiredEvent;
-import org.kie.api.event.rule.BeforeMatchFiredEvent;
-import org.kie.api.event.rule.DefaultAgendaEventListener;
-import org.kie.api.event.rule.DefaultRuleRuntimeEventListener;
-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.onap.policy.common.endpoints.event.comm.Topic;
-import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
-import org.onap.policy.common.endpoints.event.comm.TopicEndpointManager;
-import org.onap.policy.common.endpoints.event.comm.TopicListener;
-import org.onap.policy.common.endpoints.http.server.HttpServletServerFactoryInstance;
-import org.onap.policy.common.utils.coder.CoderException;
-import org.onap.policy.common.utils.coder.StandardCoder;
-import org.onap.policy.common.utils.resources.ResourceUtils;
-import org.onap.policy.controlloop.drl.legacy.ControlLoopParams;
-import org.onap.policy.drools.persistence.SystemPersistence;
-import org.onap.policy.drools.persistence.SystemPersistenceConstants;
-import org.onap.policy.drools.protocol.coders.EventProtocolCoderConstants;
-import org.onap.policy.drools.system.PolicyController;
-import org.onap.policy.drools.system.PolicyControllerConstants;
-import org.onap.policy.drools.system.PolicyEngine;
-import org.onap.policy.drools.system.PolicyEngineConstants;
-import org.onap.policy.drools.util.KieUtils;
-import org.onap.policy.drools.utils.PropertyUtil;
-import org.onap.policy.drools.utils.logging.LoggerUtil;
-import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
-import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
-import org.onap.policy.simulators.Util;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Use Cases Tests Framework.
- */
-public abstract class UsecasesBase {
-
- private static final Logger logger = LoggerFactory.getLogger(UsecasesBase.class);
- private static final StandardCoder coder = new StandardCoder();
-
- /**
- * PDP-D Engine.
- */
- protected static final PolicyEngine pdpD = PolicyEngineConstants.getManager();
-
- /**
- * PDP-D Configuration Repository.
- */
- protected static final SystemPersistence repo = SystemPersistenceConstants.getManager();
-
- /**
- * Usecases controller and session name.
- */
- protected static final String USECASES = "usecases";
-
- /**
- * Usecases controller.
- */
- protected static PolicyController usecases;
-
- /*
- * Canonical Topic Names.
- */
- protected static final String DCAE_TOPIC = "DCAE_TOPIC";
- protected static final String APPC_LCM_WRITE_TOPIC = "APPC-LCM-WRITE";
- protected static final String POLICY_CL_MGT_TOPIC = "POLICY-CL-MGT";
- protected static final String APPC_LCM_READ_TOPIC = "APPC-LCM-READ";
- protected static final String APPC_CL_TOPIC = "APPC-CL";
-
- /**
- * Sets up overall logging.
- */
- protected static void setupLogging() {
- LoggerUtil.setLevel(LoggerUtil.ROOT_LOGGER, "WARN");
- LoggerUtil.setLevel("org.eclipse.jetty", "WARN");
- LoggerUtil.setLevel("org.onap.policy.controlloop", "INFO");
- LoggerUtil.setLevel("network", "INFO");
- }
-
- /**
- * Sets up Drools Logging for events of interest.
- */
- protected static void setupDroolsLogging() {
- KieSession session =
- PolicyControllerConstants.getFactory().get(USECASES)
- .getDrools().getContainer() .getPolicySession(USECASES).getKieSession();
-
- session.addEventListener(new RuleListenerLogger());
- session.addEventListener(new AgendaListenerLogger());
- }
-
- /**
- * Sets up Simulators for use case testing.
- */
- protected static void setupSimulators() throws InterruptedException {
- Util.buildAaiSim();
- Util.buildSoSim();
- Util.buildVfcSim();
- Util.buildGuardSim();
- Util.buildSdncSim();
- }
-
- /**
- * Returns the runtime Control Loop Parameters associated with a Tosca Policy.
- */
- protected ControlLoopParams clParameters(ToscaPolicy policy) {
- return usecases
- .getDrools()
- .facts(USECASES, ControlLoopParams.class).stream()
- .filter((params) -> params.getToscaPolicy() == policy)
- .findFirst()
- .get();
- }
-
- protected ToscaPolicy getPolicyFromResource(String resourcePath, String policyName) throws CoderException {
- String policyJson = ResourceUtils.getResourceAsString(resourcePath);
- ToscaServiceTemplate serviceTemplate = coder.decode(policyJson, ToscaServiceTemplate.class);
- ToscaPolicy policy = serviceTemplate.getToscaTopologyTemplate().getPolicies().get(0).get(policyName);
- assertNotNull(policy);
-
- /*
- * name and version are used within a drl. api component and drools core will ensure that these
- * are populated.
- */
- if (StringUtils.isBlank(policy.getName())) {
- policy.setName(policyName);
- }
-
- if (StringUtils.isBlank(policy.getVersion())) {
- policy.setVersion(policy.getTypeVersion());
- }
-
- return serviceTemplate.getToscaTopologyTemplate().getPolicies().get(0).get(policyName);
- }
-
- protected ToscaPolicy getPolicyFromFile(String policyPath) throws IOException, CoderException {
- String rawPolicy = new String(Files.readAllBytes(Paths.get(policyPath)));
- return coder.decode(rawPolicy, ToscaPolicy.class);
- }
-
- private ToscaPolicy setupPolicy(ToscaPolicy policy) throws InterruptedException {
- final KieObjectExpectedCallback policyTracker = new KieObjectInsertedExpectedCallback<>(policy);
- final KieObjectExpectedCallback paramsTracker = new KieClassInsertedExpectedCallback<>(ControlLoopParams.class);
-
- usecases.getDrools().offer(policy);
-
- assertTrue(policyTracker.isNotified());
- assertTrue(paramsTracker.isNotified());
-
- assertEquals(1, usecases.getDrools().facts(USECASES, ToscaPolicy.class).stream()
- .filter((anotherPolicy) -> anotherPolicy == policy).count());
-
- assertEquals(1, usecases.getDrools().facts(USECASES, ControlLoopParams.class).stream()
- .filter((params) -> params.getToscaPolicy() == policy).count());
- return policy;
- }
-
- /**
- * Installs a policy from policy/models (examples) repo.
- */
- protected ToscaPolicy setupPolicyFromResource(String resourcePath, String policyName)
- throws CoderException, InterruptedException {
- return setupPolicy(getPolicyFromResource(resourcePath, policyName));
- }
-
-
- /**
- * Installs a given policy.
- */
- protected ToscaPolicy setupPolicyFromFile(String policyPath)
- throws IOException, CoderException, InterruptedException {
- return setupPolicy(getPolicyFromFile(policyPath));
- }
-
- /**
- * Deletes a policy.
- */
- protected void deletePolicy(ToscaPolicy policy) throws InterruptedException {
- ControlLoopParams clParams = clParameters(policy);
- assertNotNull(clParams);
-
- final KieObjectExpectedCallback policyTracker = new KieObjectDeletedExpectedCallback<>(policy);
- final KieObjectExpectedCallback clParamsTracker = new KieObjectDeletedExpectedCallback<>(clParams);
-
- usecases.getDrools().delete(USECASES, policy);
- assertTrue(policyTracker.isNotified());
- assertTrue(clParamsTracker.isNotified());
-
- assertEquals(0,
- usecases
- .getDrools()
- .facts(USECASES, ToscaPolicy.class).stream()
- .filter((anotherPolicy) -> anotherPolicy == policy)
- .count());
-
- assertEquals(0,
- usecases
- .getDrools()
- .facts(USECASES, ControlLoopParams.class).stream()
- .filter((params) -> params.getPolicyName() == policy.getName())
- .count());
- }
-
- /**
- * Prepare a PDP-D to test the Use Cases.
- */
- protected static void preparePdpD() throws IOException {
- KieUtils.installArtifact(
- Paths.get("src/main/resources/META-INF/kmodule.xml").toFile(),
- Paths.get("src/test/resources/usecases.pom").toFile(),
- "src/main/resources/org/onap/policy/controlloop/",
- Collections.singletonList(Paths.get("src/main/resources/usecases.drl").toFile()));
-
- repo.setConfigurationDir("src/test/resources/config");
- PropertyUtil.setSystemProperties(repo.getSystemProperties("controlloop"));
- pdpD.setEnvironment(repo.getEnvironmentProperties("controlloop.properties"));
- pdpD.configure(new Properties());
-
- usecases = pdpD.createPolicyController(USECASES, repo.getControllerProperties(USECASES));
- pdpD.start();
-
- setupDroolsLogging();
- }
-
- /**
- * Stop PDP-D.
- */
- protected static void stopPdpD() {
- PolicyControllerConstants.getFactory().shutdown(USECASES);
- pdpD.stop();
- }
-
- /**
- * Stop Simulators.
- */
- protected static void stopSimulators() {
- HttpServletServerFactoryInstance.getServerFactory().destroy();
- }
-
- /**
- * Creates a Topic Sink Callback tracker.
- */
- protected <T> TopicCallback<T> createTopicSinkCallback(String topicName, Class<T> clazz) {
- return new TopicCallback(TopicEndpointManager.getManager().getNoopTopicSink(topicName), clazz);
- }
-
- /**
- * Creates a Topic Source Callback tracker.
- */
- protected <T> TopicCallback<T> createTopicSourceCallback(String topicName, Class<T> clazz) {
- return new TopicCallback(TopicEndpointManager.getManager().getNoopTopicSource(topicName), clazz);
- }
-
- /**
- * Injects a message on a Topic Source.
- */
- protected void injectOnTopic(String topicName, Path onsetPath) throws IOException {
- TopicEndpointManager
- .getManager()
- .getNoopTopicSource(topicName)
- .offer(new String(Files.readAllBytes(onsetPath)));
- }
-
- /**
- * Waits for LOCK acquisition and getting a Permit from PDP-X to proceed.
- */
- protected void waitForLockAndPermit(ToscaPolicy policy, TopicCallback<VirtualControlLoopNotification> policyClMgt) {
- String policyName = policy.getIdentifier().getName();
-
- await().until(() -> !policyClMgt.getMessages().isEmpty());
- assertEquals(ControlLoopNotificationType.ACTIVE, policyClMgt.getMessages().peek().getNotification());
- assertEquals(policyName + ".EVENT", policyClMgt.getMessages().remove().getPolicyName());
-
- await().until(() -> !policyClMgt.getMessages().isEmpty());
- assertEquals(ControlLoopNotificationType.OPERATION,
- policyClMgt.getMessages().peek().getNotification());
- assertEquals(policyName + ".EVENT.MANAGER.OPERATION.LOCKED.GUARD_NOT_YET_QUERIED",
- policyClMgt.getMessages().remove().getPolicyName());
-
- await().until(() -> !policyClMgt.getMessages().isEmpty());
- assertEquals(ControlLoopNotificationType.OPERATION,
- policyClMgt.getMessages().peek().getNotification());
- assertEquals(policyName + ".GUARD.RESPONSE",
- policyClMgt.getMessages().remove().getPolicyName());
-
- await().until(() -> !policyClMgt.getMessages().isEmpty());
- assertEquals(ControlLoopNotificationType.OPERATION,
- policyClMgt.getMessages().peek().getNotification());
- assertEquals(policyName + ".EVENT.MANAGER.OPERATION.LOCKED.GUARD_PERMITTED",
- policyClMgt.getMessages().remove().getPolicyName());
- }
-
- /**
- * Waits for a FINAL SUCCESS transaction notification.
- */
- protected void waitForFinalSuccess(ToscaPolicy policy, TopicCallback<VirtualControlLoopNotification> policyClMgt) {
- await().until(() -> !policyClMgt.getMessages().isEmpty());
- assertEquals(ControlLoopNotificationType.FINAL_SUCCESS, policyClMgt.getMessages().peek().getNotification());
- assertEquals(policy.getIdentifier().getName() + ".EVENT.MANAGER",
- policyClMgt.getMessages().remove().getPolicyName());
- }
-
- /**
- * Logs Modifications to Working Memory.
- */
- static class RuleListenerLogger implements RuleRuntimeEventListener {
- @Override
- public void objectInserted(ObjectInsertedEvent event) {
- String ruleName = (event.getRule() != null) ? event.getRule().getName() : "null";
- logger.info("RULE {}: inserted {}", ruleName, event.getObject());
- }
-
- @Override
- public void objectUpdated(ObjectUpdatedEvent event) {
- String ruleName = (event.getRule() != null) ? event.getRule().getName() : "null";
- logger.info("RULE {}: updated {}", ruleName, event.getObject());
-
- }
-
- @Override
- public void objectDeleted(ObjectDeletedEvent event) {
- String ruleName = (event.getRule() != null) ? event.getRule().getName() : "null";
- logger.info("RULE {}: deleted {}", ruleName, event.getOldObject());
- }
- }
-
- /**
- * Logs Rule Matches.
- */
- static class AgendaListenerLogger extends DefaultAgendaEventListener {
- @Override
- public void matchCreated(MatchCreatedEvent event) {
- logger.info("RULE {}: match created", event.getMatch().getRule().getName());
- }
-
- @Override
- public void matchCancelled(MatchCancelledEvent event) {
- logger.info("RULE {}: match cancelled", event.getMatch().getRule().getName());
- }
-
- @Override
- public void beforeMatchFired(BeforeMatchFiredEvent event) {
- logger.info("RULE {}: before match fired", event.getMatch().getRule().getName());
- }
-
- @Override
- public void afterMatchFired(AfterMatchFiredEvent event) {
- logger.info("RULE {}: after match fired", event.getMatch().getRule().getName());
- }
- }
-
- /**
- * Base Class to track Working Memory updates for objects of type T.
- */
- abstract class KieObjectExpectedCallback<T> extends DefaultRuleRuntimeEventListener {
- protected T subject;
-
- protected CountDownLatch countDownLatch = new CountDownLatch(1);
-
- public KieObjectExpectedCallback(T affected) {
- subject = affected;
- register();
- }
-
- public boolean isNotified() throws InterruptedException {
- return countDownLatch.await(9L, TimeUnit.SECONDS);
- }
-
- protected void callbacked() {
- unregister();
- countDownLatch.countDown();
- }
-
- public KieObjectExpectedCallback<T> register() {
- usecases.getDrools()
- .getContainer().getPolicySession(USECASES).getKieSession()
- .addEventListener(this);
- return this;
- }
-
- public KieObjectExpectedCallback<T> unregister() {
- usecases.getDrools()
- .getContainer().getPolicySession(USECASES).getKieSession()
- .removeEventListener(this);
- return this;
- }
- }
-
- /**
- * Tracks inserts in Working Memory for an object of type T.
- */
- class KieObjectInsertedExpectedCallback<T> extends KieObjectExpectedCallback {
- public KieObjectInsertedExpectedCallback(T affected) {
- super(affected);
- }
-
- @Override
- public void objectInserted(ObjectInsertedEvent event) {
- if (subject == event.getObject()) {
- callbacked();
- }
- }
- }
-
- /**
- * Tracks deletes in Working Memory of an object of type T.
- */
- class KieObjectDeletedExpectedCallback<T> extends KieObjectExpectedCallback {
- public KieObjectDeletedExpectedCallback(T affected) {
- super(affected);
- }
-
- @Override
- public void objectDeleted(ObjectDeletedEvent event) {
- if (subject == event.getOldObject()) {
- callbacked();
- }
- }
- }
-
- /**
- * Tracks inserts in Working Memory for any object of class T.
- */
- class KieClassInsertedExpectedCallback<T> extends KieObjectInsertedExpectedCallback {
- public KieClassInsertedExpectedCallback(Class<T> affected) {
- super(affected);
- }
-
- public void objectInserted(ObjectInsertedEvent event) {
- if (subject == event.getObject().getClass()) {
- callbacked();
- }
- }
- }
-
- /**
- * Tracks callbacks from topics.
- */
- class TopicCallback<T> implements TopicListener {
- protected final Topic topic;
- protected final Class<T> expectedClass;
-
- @Getter
- protected Queue<T> messages = new LinkedList<>();
-
- public TopicCallback(Topic topic, Class<T> expectedClass) {
- this.topic = topic;
- this.expectedClass = expectedClass;
- this.topic.register(this);
- }
-
- public TopicCallback register() {
- this.topic.register(this);
- return this;
- }
-
- public TopicCallback unregister() {
- this.topic.unregister(this);
- return this;
- }
-
- @Override
- public void onTopicEvent(CommInfrastructure comm, String topic, String event) {
- try {
- messages.add((T) EventProtocolCoderConstants.getManager().decode(
- usecases.getDrools().getGroupId(), usecases.getDrools().getArtifactId(), topic, event));
- } catch (Exception e) {
- logger.warn("invalid mapping in topic {} for event {}", topic, event, e);
- }
- }
- }
-}
diff --git a/controlloop/common/controller-usecases/src/test/java/org/onap/policy/controlloop/UsecasesTest.java b/controlloop/common/controller-usecases/src/test/java/org/onap/policy/controlloop/UsecasesTest.java
new file mode 100644
index 000000000..53c15a312
--- /dev/null
+++ b/controlloop/common/controller-usecases/src/test/java/org/onap/policy/controlloop/UsecasesTest.java
@@ -0,0 +1,120 @@
+/*-
+ * ============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 lombok.Getter;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.runner.RunWith;
+import org.onap.policy.controlloop.common.rules.test.BaseRuleTest;
+import org.onap.policy.controlloop.common.rules.test.Listener;
+import org.onap.policy.controlloop.common.rules.test.NamedRunner;
+import org.onap.policy.controlloop.common.rules.test.TestNames;
+import org.onap.policy.drools.utils.PropertyUtil;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
+import org.onap.policy.simulators.Util;
+
+/**
+ * Tests use case rules. Only a subset of available tests will work with these rules, thus
+ * a "FilterRunner" is used to filter out the other test cases.
+ *
+ * <p/>
+ * Note: this only runs tests whose names start with "testV" (e.g., testVcpe(),
+ * testVdns()).
+ */
+@RunWith(NamedRunner.class)
+@TestNames(prefixes = {"testV"})
+
+public class UsecasesTest extends BaseRuleTest {
+
+ @Getter()
+ protected static final String CONTROLLER_NAME = "usecases";
+
+ /**
+ * Sets up statics.
+ */
+ @BeforeClass
+ public static void setUpBeforeClass() {
+ initStatics(CONTROLLER_NAME);
+
+ rules.configure("src/main/resources");
+ PropertyUtil.setSystemProperties(rules.getPdpdRepo().getSystemProperties("controlloop"));
+ rules.getPdpd().setEnvironment(rules.getPdpdRepo().getEnvironmentProperties("controlloop.properties"));
+
+ rules.start();
+ simulators.start(Util::buildAaiSim, Util::buildSoSim, Util::buildVfcSim, Util::buildGuardSim,
+ Util::buildSdncSim);
+ }
+
+ /**
+ * Cleans up statics.
+ */
+ @AfterClass
+ public static void tearDownAfterClass() {
+ finishStatics();
+ }
+
+ /**
+ * Sets up.
+ */
+ @Before
+ public void setUp() {
+ init();
+ }
+
+ /**
+ * Tears down.
+ */
+ @After
+ public void tearDown() {
+ finish();
+ }
+
+ @Override
+ protected void waitForLockAndPermit(ToscaPolicy policy, Listener<VirtualControlLoopNotification> policyClMgt) {
+ String policyName = policy.getIdentifier().getName();
+
+ policyClMgt.await(notif -> notif.getNotification() == ControlLoopNotificationType.ACTIVE
+ && (policyName + ".EVENT").equals(notif.getPolicyName()));
+
+ policyClMgt.await(notif -> notif.getNotification() == ControlLoopNotificationType.OPERATION
+ && (policyName + ".EVENT.MANAGER.OPERATION.LOCKED.GUARD_NOT_YET_QUERIED")
+ .equals(notif.getPolicyName()));
+
+ policyClMgt.await(notif -> notif.getNotification() == ControlLoopNotificationType.OPERATION
+ && (policyName + ".GUARD.RESPONSE").equals(notif.getPolicyName())
+ && notif.getMessage().startsWith("Guard result") && notif.getMessage().endsWith("Permit"));
+
+ policyClMgt.await(notif -> notif.getNotification() == ControlLoopNotificationType.OPERATION
+ && (policyName + ".EVENT.MANAGER.OPERATION.LOCKED.GUARD_PERMITTED")
+ .equals(notif.getPolicyName()));
+ }
+
+ @Override
+ protected VirtualControlLoopNotification waitForFinal(ToscaPolicy policy,
+ Listener<VirtualControlLoopNotification> policyClMgt, ControlLoopNotificationType finalType) {
+
+ return policyClMgt.await(notif -> notif.getNotification() == finalType
+ && (policy.getIdentifier().getName() + ".EVENT.MANAGER").equals(notif.getPolicyName()));
+ }
+}
diff --git a/controlloop/common/controller-usecases/src/test/java/org/onap/policy/controlloop/VcpeTest.java b/controlloop/common/controller-usecases/src/test/java/org/onap/policy/controlloop/VcpeTest.java
deleted file mode 100644
index ec3b50213..000000000
--- a/controlloop/common/controller-usecases/src/test/java/org/onap/policy/controlloop/VcpeTest.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2019-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 static org.awaitility.Awaitility.await;
-import static org.junit.Assert.assertEquals;
-
-import java.io.IOException;
-import java.nio.file.Paths;
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.onap.policy.appclcm.AppcLcmDmaapWrapper;
-import org.onap.policy.common.utils.coder.CoderException;
-import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
-
-/**
- * VCPE Use Case Tests.
- */
-public class VcpeTest extends UsecasesBase {
-
- /**
- * VCPE Tosca Policy File.
- */
- private static final String TOSCA_LEGACY_POLICY_VCPE = "src/test/resources/vcpe/tosca-legacy-vcpe.json";
- private static final String TOSCA_COMPLIANT_POLICY_VCPE = "src/test/resources/vcpe/tosca-compliant-vcpe.json";
-
- /*
- * VCPE Use case Messages.
- */
- private static final String APPC_SUCCESS = "src/test/resources/vcpe/vcpe.appc.success.json";
- private static final String ONSET_1 = "src/test/resources/vcpe/vcpe.onset.1.json";
- private static final String ONSET_2 = "src/test/resources/vcpe/vcpe.onset.2.json";
- private static final String ONSET_3 = "src/test/resources/vcpe/vcpe.onset.3.json";
-
- /*
- * Topic trackers used by the VCPE use case.
- */
- private TopicCallback<VirtualControlLoopNotification> policyClMgt;
- private TopicCallback<AppcLcmDmaapWrapper> appcLcmRead;
- private TopicCallback<AppcLcmDmaapWrapper> appcLcmWrite;
-
- /*
- * VCPE Tosca Policy.
- */
- private ToscaPolicy policy;
-
- /**
- * Prepare PDP-D Framework for testing.
- */
- @BeforeClass
- public static void prepareResouces() throws InterruptedException, CoderException, IOException {
- setupLogging();
- preparePdpD();
- setupSimulators();
- }
-
- /**
- * Take down the resources used by the test framework.
- */
- @AfterClass
- public static void takeDownResources() {
- stopPdpD();
- stopSimulators();
- }
-
- /**
- * Sunny day scenario for the VCPE use case.
- */
- public void sunnyDay() throws IOException {
-
- /* Inject an ONSET event over the DCAE topic */
- injectOnTopic(DCAE_TOPIC, Paths.get(ONSET_1));
-
- /* Wait to acquire a LOCK and a PDP-X PERMIT */
- waitForLockAndPermit(policy, policyClMgt);
-
- /* --- VCPE Operation Execution --- */
-
- /* Ensure that an APPC RESTART request was sent in response to the matching ONSET */
- await().until(() -> !appcLcmRead.getMessages().isEmpty());
- assertEquals("restart", appcLcmRead.getMessages().remove().getRpcName());
-
- /* Inject a 400 APPC Response Return over the APPC topic */
- injectOnTopic(APPC_LCM_WRITE_TOPIC, Paths.get(APPC_SUCCESS));
-
- /* Ensure that RESTART response is received */
- await().until(() -> !appcLcmWrite.getMessages().isEmpty());
- assertEquals("restart", appcLcmWrite.getMessages().peek().getRpcName());
- assertEquals(400, appcLcmWrite.getMessages().remove().getBody().getOutput().getStatus().getCode());
-
- /* --- VCPE Operation Completed --- */
-
- /* Ensure that the VCPE RESTART Operation is successfully completed */
- await().until(() -> !policyClMgt.getMessages().isEmpty());
- assertEquals(ControlLoopNotificationType.OPERATION_SUCCESS, policyClMgt.getMessages().peek().getNotification());
- assertEquals(policy.getIdentifier().getName() + ".APPC.LCM.RESPONSE",
- policyClMgt.getMessages().remove().getPolicyName());
-
- /* --- VCPE Transaction Completed --- */
- waitForFinalSuccess(policy, policyClMgt);
- }
-
- /**
- * Sunny Day with Legacy Tosca Policy.
- */
- @Test
- public void sunnyDayLegacy() throws InterruptedException, CoderException, IOException {
- assertEquals(0, usecases.getDrools().factCount(USECASES));
- policy = setupPolicyFromFile(TOSCA_LEGACY_POLICY_VCPE);
- assertEquals(2, usecases.getDrools().factCount(USECASES));
-
- sunnyDay();
- }
-
- /**
- * Sunny Day with Tosca Compliant Policy.
- */
- @Test
- public void sunnyDayCompliant() throws InterruptedException, CoderException, IOException {
- assertEquals(0, usecases.getDrools().factCount(USECASES));
- policy = setupPolicyFromFile(TOSCA_COMPLIANT_POLICY_VCPE);
- assertEquals(2, usecases.getDrools().factCount(USECASES));
-
- sunnyDay();
- }
-
- /**
- * An ONSET flood prevention test that injects a few ONSETs at once.
- * It attempts to simulate the flooding behavior of the DCAE TCA microservice.
- * TCA could blast tenths or hundreds of ONSETs within sub-second intervals.
- */
- @Test
- public void onsetFloodPrevention() throws IOException, InterruptedException, CoderException {
- assertEquals(0, usecases.getDrools().factCount(USECASES));
- policy = setupPolicyFromFile(TOSCA_LEGACY_POLICY_VCPE);
- assertEquals(2, usecases.getDrools().factCount(USECASES));
-
- injectOnTopic(DCAE_TOPIC, Paths.get(ONSET_1));
- injectOnTopic(DCAE_TOPIC, Paths.get(ONSET_2));
- injectOnTopic(DCAE_TOPIC, Paths.get(ONSET_3));
-
- assertEquals(1, usecases.getDrools().facts(USECASES, VirtualControlLoopEvent.class).stream().count());
- assertEquals(1, usecases.getDrools().facts(USECASES, CanonicalOnset.class).stream().count());
- assertEquals(usecases.getDrools().facts(USECASES, CanonicalOnset.class).get(0),
- usecases.getDrools().facts(USECASES, VirtualControlLoopEvent.class).get(0));
-
- sunnyDay();
- }
-
- /**
- * Observe Topics.
- */
- @Before
- public void topicsRegistration() {
- policyClMgt = createTopicSinkCallback(POLICY_CL_MGT_TOPIC, VirtualControlLoopNotification.class);
- appcLcmRead = createTopicSinkCallback(APPC_LCM_READ_TOPIC, AppcLcmDmaapWrapper.class);
- appcLcmWrite = createTopicSourceCallback(APPC_LCM_WRITE_TOPIC, AppcLcmDmaapWrapper.class);
- }
-
- /**
- * Unregister Topic Callbacks.
- */
- @After
- public void topicsUnregistration() {
- if (policyClMgt != null) {
- policyClMgt.unregister();
- }
-
- if (appcLcmRead != null) {
- appcLcmRead.unregister();
- }
-
- if (appcLcmWrite != null) {
- appcLcmWrite.unregister();
- }
- }
-
- /**
- * Uninstall Policy.
- */
- @After
- public void uninstallPolicy() throws InterruptedException {
- assertEquals(2, usecases.getDrools().factCount(USECASES));
- if (policy != null) {
- deletePolicy(policy);
- }
- assertEquals(0, usecases.getDrools().factCount(USECASES));
- }
-
-}
diff --git a/controlloop/common/controller-usecases/src/test/java/org/onap/policy/controlloop/VfwTest.java b/controlloop/common/controller-usecases/src/test/java/org/onap/policy/controlloop/VfwTest.java
deleted file mode 100644
index 8386b3028..000000000
--- a/controlloop/common/controller-usecases/src/test/java/org/onap/policy/controlloop/VfwTest.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2019-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 static org.awaitility.Awaitility.await;
-import static org.junit.Assert.assertEquals;
-
-import java.io.IOException;
-import java.nio.file.Paths;
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.onap.policy.appc.Request;
-import org.onap.policy.appc.Response;
-import org.onap.policy.common.utils.coder.CoderException;
-import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
-
-/**
- * VFW Use Case Tests.
- */
-public class VfwTest extends UsecasesBase {
-
- /**
- * VFW Tosca Policy File.
- */
- private static final String TOSCA_LEGACY_POLICY_VFW = "src/test/resources/vfw/tosca-vfw.json";
- private static final String TOSCA_COMPLIANT_POLICY_VFW = "src/test/resources/vfw/tosca-compliant-vfw.json";
-
- /*
- * VFW Use case Messages.
- */
- private static final String APPC_SUCCESS = "src/test/resources/vfw/vfw.appc.success.json";
- private static final String ONSET = "src/test/resources/vfw/vfw.onset.json";
-
- /*
- * Topic trackers used by the VFW use case.
- */
- private TopicCallback<VirtualControlLoopNotification> policyClMgt;
- private TopicCallback<Response> appcClSource;
- private TopicCallback<Request> appcClSink;
-
- /*
- * VFW Tosca Policy.
- */
- private ToscaPolicy policy;
-
- /**
- * Prepare PDP-D Framework for testing.
- */
- @BeforeClass
- public static void prepareResouces() throws InterruptedException, IOException {
- setupLogging();
- preparePdpD();
- setupSimulators();
- }
-
- /**
- * Take down the resources used by the test framework.
- */
- @AfterClass
- public static void takeDownResources() {
- stopPdpD();
- stopSimulators();
- }
-
- /**
- * Sunny day scenario for the VFW use case.
- */
- private void sunnyDay() throws IOException {
-
- /* Inject an ONSET event over the DCAE topic */
- injectOnTopic(DCAE_TOPIC, Paths.get(ONSET));
-
- /* Wait to acquire a LOCK and a PDP-X PERMIT */
- waitForLockAndPermit(policy, policyClMgt);
-
- /* --- VFW Operation Execution --- */
-
- /* Ensure that an APPC RESTART request was sent in response to the matching ONSET */
- await().until(() -> !appcClSink.getMessages().isEmpty());
- assertEquals("ModifyConfig", appcClSink.getMessages().remove().getAction());
-
- /* Inject a 400 APPC Response Return over the APPC topic */
- injectOnTopic(APPC_CL_TOPIC, Paths.get(APPC_SUCCESS));
-
- /* Ensure that RESTART response is received */
- await().until(() -> !appcClSource.getMessages().isEmpty());
- assertEquals("SUCCESS", appcClSource.getMessages().remove().getStatus().getValue());
-
- /* --- VFW Operation Completed --- */
-
- /* Ensure that the VFW RESTART Operation is successfully completed */
- await().until(() -> !policyClMgt.getMessages().isEmpty());
- assertEquals(ControlLoopNotificationType.OPERATION_SUCCESS,
- policyClMgt.getMessages().remove().getNotification());
-
- /* --- VFW Transaction Completed --- */
- waitForFinalSuccess(policy, policyClMgt);
- }
-
- /**
- * Sunny Day with Legacy Tosca Policy.
- */
- @Test
- public void sunnyDayLegacy() throws InterruptedException, CoderException, IOException {
- assertEquals(0, usecases.getDrools().factCount(USECASES));
- policy = setupPolicyFromFile(TOSCA_LEGACY_POLICY_VFW);
- assertEquals(2, usecases.getDrools().factCount(USECASES));
-
- sunnyDay();
- }
-
- /**
- * Sunny Day with Tosca Compliant Policy.
- */
- @Test
- public void sunnyDayCompliant() throws InterruptedException, CoderException, IOException {
- assertEquals(0, usecases.getDrools().factCount(USECASES));
- policy = setupPolicyFromFile(TOSCA_COMPLIANT_POLICY_VFW);
- assertEquals(2, usecases.getDrools().factCount(USECASES));
-
- sunnyDay();
- }
-
- /**
- * Observe Topics.
- */
- @Before
- public void topicsRegistration() {
- policyClMgt = createTopicSinkCallback(POLICY_CL_MGT_TOPIC, VirtualControlLoopNotification.class);
- appcClSink = createTopicSinkCallback(APPC_CL_TOPIC, Request.class);
- appcClSource = createTopicSourceCallback(APPC_CL_TOPIC, Response.class);
- }
-
- /**
- * Unregister Topic Callbacks.
- */
- @After
- public void topicsUnregistration() {
- if (policyClMgt != null) {
- policyClMgt.unregister();
- }
-
- if (appcClSource != null) {
- appcClSource.unregister();
- }
-
- if (appcClSink != null) {
- appcClSink.unregister();
- }
- }
-
- /**
- * Uninstall Policy.
- */
- @After
- public void uninstallPolicy() throws InterruptedException {
- assertEquals(2, usecases.getDrools().factCount(USECASES));
- if (policy != null) {
- deletePolicy(policy);
- }
- assertEquals(0, usecases.getDrools().factCount(USECASES));
- }
-
-}
diff --git a/controlloop/common/controller-usecases/src/test/java/org/onap/policy/controlloop/VlbTest.java b/controlloop/common/controller-usecases/src/test/java/org/onap/policy/controlloop/VlbTest.java
deleted file mode 100644
index 73eeae882..000000000
--- a/controlloop/common/controller-usecases/src/test/java/org/onap/policy/controlloop/VlbTest.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2019-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 static org.awaitility.Awaitility.await;
-import static org.junit.Assert.assertEquals;
-
-import java.io.IOException;
-import java.nio.file.Paths;
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.onap.policy.common.utils.coder.CoderException;
-import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
-
-/**
- * VLB Use Case Tests.
- */
-public class VlbTest extends UsecasesBase {
-
- /**
- * VLB Tosca Policy File.
- */
- private static final String TOSCA_LEGACY_POLICY_VLB = "src/test/resources/vlb/tosca-vlb.json";
- private static final String TOSCA_COMPLIANT_POLICY_VLB = "src/test/resources/vlb/tosca-compliant-vlb.json";
-
- /*
- * VLB Use case Messages.
- */
- private static final String ONSET = "src/test/resources/vlb/vlb.onset.json";
-
- /*
- * Topic trackers used by the VLB use case.
- */
- private TopicCallback<VirtualControlLoopNotification> policyClMgt;
-
- /*
- * VLB Tosca Policy.
- */
- private ToscaPolicy policy;
-
- /**
- * Prepare PDP-D Framework for testing.
- */
- @BeforeClass
- public static void prepareResouces() throws InterruptedException, IOException {
- setupLogging();
- preparePdpD();
- setupSimulators();
- }
-
- /**
- * Take down the resources used by the test framework.
- */
- @AfterClass
- public static void takeDownResources() {
- stopPdpD();
- stopSimulators();
- }
-
- /**
- * Sunny day scenario for the VCPE use case.
- */
- private void sunnyDay() throws IOException {
-
- /* Inject an ONSET event over the DCAE topic */
- injectOnTopic(DCAE_TOPIC, Paths.get(ONSET));
-
- /* Wait to acquire a LOCK and a PDP-X PERMIT */
- waitForLockAndPermit(policy, policyClMgt);
-
- /* Ensure that the VLB SO Operation was successfully completed */
-
- await().until(() -> !policyClMgt.getMessages().isEmpty());
- assertEquals(ControlLoopNotificationType.OPERATION_SUCCESS, policyClMgt.getMessages().peek().getNotification());
- assertEquals(policy.getIdentifier().getName() + ".SO.RESPONSE",
- policyClMgt.getMessages().remove().getPolicyName());
-
- /* --- VLB Transaction Completed --- */
- waitForFinalSuccess(policy, policyClMgt);
- }
-
- /**
- * Sunny Day with Legacy Tosca Policy.
- */
- @Test
- public void sunnyDayLegacy() throws InterruptedException, CoderException, IOException {
- assertEquals(0, usecases.getDrools().factCount(USECASES));
- policy = setupPolicyFromFile(TOSCA_LEGACY_POLICY_VLB);
- assertEquals(2, usecases.getDrools().factCount(USECASES));
-
- sunnyDay();
- }
-
- /**
- * Sunny Day with Tosca Compliant Policy.
- */
- @Test
- public void sunnyDayCompliant() throws InterruptedException, CoderException, IOException {
- assertEquals(0, usecases.getDrools().factCount(USECASES));
- policy = setupPolicyFromFile(TOSCA_COMPLIANT_POLICY_VLB);
- assertEquals(2, usecases.getDrools().factCount(USECASES));
-
- sunnyDay();
- }
-
- /**
- * Observe Topics.
- */
- @Before
- public void topicsRegistration() {
- policyClMgt = createTopicSinkCallback(POLICY_CL_MGT_TOPIC, VirtualControlLoopNotification.class);
- }
-
- /**
- * Unregister Topic Callbacks.
- */
- @After
- public void topicsUnregistration() {
- if (policyClMgt != null) {
- policyClMgt.unregister();
- }
- }
-
- /**
- * Uninstall Policy.
- */
- @After
- public void uninstallPolicy() throws InterruptedException {
- assertEquals(2, usecases.getDrools().factCount(USECASES));
- if (policy != null) {
- deletePolicy(policy);
- }
- assertEquals(0, usecases.getDrools().factCount(USECASES));
- }
-
-}
diff --git a/controlloop/common/controller-usecases/src/test/resources/config/usecases-controller.properties b/controlloop/common/controller-usecases/src/test/resources/config/usecases-controller.properties
index 483b13ad7..a8d202cd5 100644
--- a/controlloop/common/controller-usecases/src/test/resources/config/usecases-controller.properties
+++ b/controlloop/common/controller-usecases/src/test/resources/config/usecases-controller.properties
@@ -26,9 +26,12 @@ rules.version=1.0.0
noop.source.topics=DCAE_TOPIC,APPC-CL,APPC-LCM-WRITE,SDNR-CL-RSP,POLICY-CL-MGT,APPC-LCM-READ,SDNR-CL,DCAE_CL_RSP
-noop.source.topics.DCAE_TOPIC.events=org.onap.policy.controlloop.CanonicalOnset,org.onap.policy.controlloop.CanonicalAbated
-noop.source.topics.DCAE_TOPIC.events.org.onap.policy.controlloop.CanonicalOnset.filter=[?($.closedLoopEventStatus == 'ONSET')]
-noop.source.topics.DCAE_TOPIC.events.org.onap.policy.controlloop.CanonicalAbated.filter=[?($.closedLoopEventStatus == 'ABATED')]
+noop.source.topics.DCAE_TOPIC.events=\
+ org.onap.policy.controlloop.CanonicalOnset,org.onap.policy.controlloop.CanonicalAbated
+noop.source.topics.DCAE_TOPIC.events.org.onap.policy.controlloop.CanonicalOnset.\
+ filter=[?($.closedLoopEventStatus == 'ONSET')]
+noop.source.topics.DCAE_TOPIC.events.org.onap.policy.controlloop.CanonicalAbated.\
+ filter=[?($.closedLoopEventStatus == 'ABATED')]
noop.source.topics.DCAE_TOPIC.events.custom.gson=org.onap.policy.controlloop.util.Serialization,gson
noop.source.topics.APPC-CL.events=org.onap.policy.appc.Response,org.onap.policy.appc.Request
diff --git a/controlloop/common/controller-usecases/src/test/resources/vcpe/tosca-legacy-vcpe.json b/controlloop/common/controller-usecases/src/test/resources/vcpe/tosca-legacy-vcpe.json
deleted file mode 100644
index f42c07da9..000000000
--- a/controlloop/common/controller-usecases/src/test/resources/vcpe/tosca-legacy-vcpe.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "type": "onap.policies.controlloop.Operational",
- "type_version": "1.0.0",
- "properties": {
- "content": "controlLoop%3A%0A%20%20version%3A%202.0.0%0A%20%20controlLoopName%3A%20ControlLoop-vCPE-48f0c2c3-a172-4192-9ae3-052274181b6e%0A%20%20trigger_policy%3A%20unique-policy-id-1-restart%0A%20%20timeout%3A%203600%0A%20%20abatement%3A%20false%0A%20%0Apolicies%3A%0A%20%20-%20id%3A%20unique-policy-id-1-restart%0A%20%20%20%20name%3A%20Restart%20the%20VM%0A%20%20%20%20description%3A%0A%20%20%20%20actor%3A%20APPC%0A%20%20%20%20recipe%3A%20Restart%0A%20%20%20%20target%3A%0A%20%20%20%20%20%20type%3A%20VM%0A%20%20%20%20retry%3A%203%0A%20%20%20%20timeout%3A%201200%0A%20%20%20%20success%3A%20final_success%0A%20%20%20%20failure%3A%20final_failure%0A%20%20%20%20failure_timeout%3A%20final_failure_timeout%0A%20%20%20%20failure_retries%3A%20final_failure_retries%0A%20%20%20%20failure_exception%3A%20final_failure_exception%0A%20%20%20%20failure_guard%3A%20final_failure_guard"
- },
- "name": "vcpe",
- "version": "1.0.0"
-} \ No newline at end of file
diff --git a/controlloop/common/controller-usecases/src/test/resources/vfw/vfw.appc.success.json b/controlloop/common/controller-usecases/src/test/resources/vfw/vfw.appc.success.json
deleted file mode 100644
index 618b70537..000000000
--- a/controlloop/common/controller-usecases/src/test/resources/vfw/vfw.appc.success.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "CommonHeader": {
- "TimeStamp": 1506051879001,
- "APIver": "1.01",
- "RequestID": "c7c6a4aa-bb61-4a15-b831-ba1472dd4a65",
- "SubRequestID": "1",
- "RequestTrack": [],
- "Flags": []
- },
- "Status": {
- "Code": 400,
- "Value": "SUCCESS"
- },
- "Payload": {
- "generic-vnf.vnf-id": "jimmy-test-vnf2"
- }
-} \ No newline at end of file
diff --git a/controlloop/common/controller-usecases/src/test/resources/vlb/tosca-vlb.json b/controlloop/common/controller-usecases/src/test/resources/vlb/tosca-vlb.json
deleted file mode 100644
index 5147d9922..000000000
--- a/controlloop/common/controller-usecases/src/test/resources/vlb/tosca-vlb.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "type": "onap.policies.controlloop.Operational",
- "type_version": "1.0.0",
- "properties": {
- "content": "controlLoop%3A%0A%20%20version%3A%202.0.0%0A%20%20controlLoopName%3A%20ControlLoop-vDNS-6f37f56d-a87d-4b85-b6a9-cc953cf779b3%0A%20%20services%3A%0A%20%20%20%20-%20serviceName%3A%20d4738992-6497-4dca-9db9%0A%20%20%20%20%20%20serviceInvariantUUID%3A%20dc112d6e-7e73-4777-9c6f-1a7fb5fd1b6f%0A%20%20%20%20%20%20serviceUUID%3A%202eea06c6-e1d3-4c3a-b9c4-478c506eeedf%0A%20%20trigger_policy%3A%20unique-policy-id-1-scale-up%0A%20%20timeout%3A%2060%0A%0Apolicies%3A%0A%20%20-%20id%3A%20unique-policy-id-1-scale-up%0A%20%20%20%20name%3A%20Create%20a%20new%20VF%20Module%0A%20%20%20%20description%3A%0A%20%20%20%20actor%3A%20SO%0A%20%20%20%20recipe%3A%20VF%20Module%20Create%0A%20%20%20%20target%3A%0A%20%20%20%20%20%20type%3A%20VFMODULE%0A%20%20%20%20%20%20modelInvariantId%3A%20e6130d03-56f1-4b0a-9a1d-e1b2ebc30e0e%0A%20%20%20%20%20%20modelVersionId%3A%2094b18b1d-cc91-4f43-911a-e6348665f292%0A%20%20%20%20%20%20modelName%3A%20VfwclVfwsnkBbefb8ce2bde..base_vfw..module-0%0A%20%20%20%20%20%20modelVersion%3A%201%0A%20%20%20%20%20%20modelCustomizationId%3A%2047958575-138f-452a-8c8d-d89b595f8164%0A%20%20%20%20payload%3A%0A%20%20%20%20%20%20requestParameters%3A%20%27%7B%22usePreload%22%3Atrue%2C%22userParams%22%3A%5B%5D%7D%27%0A%20%20%20%20%20%20configurationParameters%3A%20%27%5B%7B%22ip-addr%22%3A%22%24.vf-module-topology.vf-module-parameters.param%5B9%5D%22%2C%22oam-ip-addr%22%3A%22%24.vf-module-topology.vf-module-parameters.param%5B16%5D%22%2C%22enabled%22%3A%22%24.vf-module-topology.vf-module-parameters.param%5B23%5D%22%7D%5D%27%0A%20%20%20%20retry%3A%200%0A%20%20%20%20timeout%3A%2030%0A%20%20%20%20success%3A%20final_success%0A%20%20%20%20failure%3A%20final_failure%0A%20%20%20%20failure_timeout%3A%20final_failure_timeout%0A%20%20%20%20failure_retries%3A%20final_failure_retries%0A%20%20%20%20failure_exception%3A%20final_failure_exception%0A%20%20%20%20failure_guard%3A%20final_failure_guard%0A"
- },
- "name": "vlb",
- "version": "1.0.0"
-} \ No newline at end of file
diff --git a/controlloop/common/controller-usecases/src/test/resources/vlb/vlb.onset.json b/controlloop/common/controller-usecases/src/test/resources/vlb/vlb.onset.json
deleted file mode 100644
index 3360c0abb..000000000
--- a/controlloop/common/controller-usecases/src/test/resources/vlb/vlb.onset.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "closedLoopControlName": "ControlLoop-vDNS-6f37f56d-a87d-4b85-b6a9-cc953cf779b3",
- "closedLoopAlarmStart": 1484677482204798,
- "closedLoopEventClient": "DCAE_INSTANCE_ID.dcae-tca",
- "closedLoopEventStatus": "ONSET",
- "requestID": "e4f95e0c-a013-4530-8e59-c5c5f9e539b6",
- "target_type": "VNF",
- "target": "vserver.vserver-name",
- "AAI": {
- "vserver.is-closed-loop-disabled": "false",
- "vserver.prov-status": "ACTIVE",
- "vserver.vserver-name": "OzVServer"
- },
- "from": "DCAE",
- "version": "1.0.2"
-} \ No newline at end of file
diff --git a/controlloop/common/pom.xml b/controlloop/common/pom.xml
index 431ab94e6..29690047d 100644
--- a/controlloop/common/pom.xml
+++ b/controlloop/common/pom.xml
@@ -37,6 +37,7 @@
<module>guard</module>
<module>coordination</module>
<module>eventmanager</module>
+ <module>rules-test</module>
<module>controller-frankfurt</module>
<module>controller-usecases</module>
<module>feature-controlloop-utils</module>
diff --git a/controlloop/common/rules-test/pom.xml b/controlloop/common/rules-test/pom.xml
new file mode 100644
index 000000000..ddd897c35
--- /dev/null
+++ b/controlloop/common/rules-test/pom.xml
@@ -0,0 +1,165 @@
+<!--
+ ============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>
+
+ <parent>
+
+ <groupId>org.onap.policy.drools-applications.controlloop.common</groupId>
+ <artifactId>drools-applications-common</artifactId>
+ <version>1.6.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>rules-test</artifactId>
+ <description>Common Utilities to facilitate testing via JUnit</description>
+ <packaging>jar</packaging>
+
+ <properties>
+ <powermock.version>2.0.4</powermock.version>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.policy.models.policy-models-interactions.model-impl</groupId>
+ <artifactId>events</artifactId>
+ <version>${policy.models.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.policy.models.policy-models-interactions.model-impl</groupId>
+ <artifactId>appc</artifactId>
+ <version>${policy.models.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.policy.models.policy-models-interactions.model-impl</groupId>
+ <artifactId>appclcm</artifactId>
+ <version>${policy.models.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.projectlombok</groupId>
+ <artifactId>lombok</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.awaitility</groupId>
+ <artifactId>awaitility</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.assertj</groupId>
+ <artifactId>assertj-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.policy.common</groupId>
+ <artifactId>utils</artifactId>
+ <version>${version.policy.common}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.policy.common</groupId>
+ <artifactId>policy-endpoints</artifactId>
+ <version>${version.policy.common}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.policy.models.policy-models-interactions</groupId>
+ <artifactId>simulators</artifactId>
+ <version>${policy.models.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.policy.models.policy-models-interactions.model-impl</groupId>
+ <artifactId>events</artifactId>
+ <version>${policy.models.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.policy.drools-applications.controlloop.common</groupId>
+ <artifactId>eventmanager</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.policy.drools-pdp</groupId>
+ <artifactId>policy-management</artifactId>
+ <version>${version.policy.drools-pdp}</version>
+ <scope>provided</scope>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito2</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.policy.common</groupId>
+ <artifactId>utils-test</artifactId>
+ <version>${version.policy.common}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven
+ build itself. -->
+ <plugin>
+ <groupId>org.eclipse.m2e</groupId>
+ <artifactId>lifecycle-mapping</artifactId>
+ <version>1.0.0</version>
+ <configuration>
+ <lifecycleMappingMetadata>
+ <pluginExecutions>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>org.jacoco</groupId>
+ <artifactId>
+ jacoco-maven-plugin
+ </artifactId>
+ <versionRange>
+ [0.7.1.201405082137,)
+ </versionRange>
+ <goals>
+ <goal>prepare-agent</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore />
+ </action>
+ </pluginExecution>
+ </pluginExecutions>
+ </lifecycleMappingMetadata>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+</project>
diff --git a/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/BaseRuleTest.java b/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/BaseRuleTest.java
new file mode 100644
index 000000000..711a61738
--- /dev/null
+++ b/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/BaseRuleTest.java
@@ -0,0 +1,496 @@
+/*-
+ * ============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 java.util.List;
+import java.util.UUID;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+import lombok.AccessLevel;
+import lombok.Getter;
+import org.junit.Test;
+import org.onap.policy.appc.Request;
+import org.onap.policy.appclcm.AppcLcmDmaapWrapper;
+import org.onap.policy.common.utils.coder.Coder;
+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.system.PolicyController;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
+
+/**
+ * Superclass used for rule tests.
+ */
+public abstract class BaseRuleTest {
+ /*
+ * Canonical Topic Names.
+ */
+ protected static final String DCAE_TOPIC = "DCAE_TOPIC";
+ protected static final String APPC_LCM_WRITE_TOPIC = "APPC-LCM-WRITE";
+ protected static final String POLICY_CL_MGT_TOPIC = "POLICY-CL-MGT";
+ protected static final String APPC_LCM_READ_TOPIC = "APPC-LCM-READ";
+ protected static final String APPC_CL_TOPIC = "APPC-CL";
+
+ /*
+ * Constants for each test case.
+ */
+
+ // service123 (i.e., multi-operation policy)
+ private static final String SERVICE123_TOSCA_COMPLIANT_POLICY = "service123/tosca-compliant-service123.json";
+ private static final String SERVICE123_ONSET = "service123/service123.onset.json";
+ private static final String SERVICE123_APPC_RESTART_FAILURE = "service123/service123.appc.restart.failure.json";
+ private static final String SERVICE123_APPC_REBUILD_FAILURE = "service123/service123.appc.rebuild.failure.json";
+ private static final String SERVICE123_APPC_MIGRATE_SUCCESS = "service123/service123.appc.migrate.success.json";
+
+ // duplicates (i.e., mutliple events in the engine at the same time)
+ private static final String DUPLICATES_TOSCA_COMPLIANT_POLICY = "duplicates/tosca-compliant-duplicates.json";
+ private static final String DUPLICATES_ONSET_1 = "duplicates/duplicates.onset.1.json";
+ private static final String DUPLICATES_ONSET_2 = "duplicates/duplicates.onset.2.json";
+ private static final String DUPLICATES_APPC_SUCCESS = "duplicates/duplicates.appc.success.json";
+
+ // VCPE
+ private static final String VCPE_TOSCA_LEGACY_POLICY = "vcpe/tosca-legacy-vcpe.json";
+ private static final String VCPE_TOSCA_COMPLIANT_POLICY = "vcpe/tosca-compliant-vcpe.json";
+ private static final String VCPE_ONSET_1 = "vcpe/vcpe.onset.1.json";
+ private static final String VCPE_ONSET_2 = "vcpe/vcpe.onset.2.json";
+ private static final String VCPE_ONSET_3 = "vcpe/vcpe.onset.3.json";
+ private static final String VCPE_APPC_SUCCESS = "vcpe/vcpe.appc.success.json";
+
+ // VDNS
+ private static final String VDNS_TOSCA_COMPLIANT_POLICY = "vdns/tosca-compliant-vdns.json";
+ private static final String VDNS_ONSET = "vdns/vdns.onset.json";
+
+ // VFW
+ private static final String VFW_TOSCA_LEGACY_POLICY = "vfw/tosca-vfw.json";
+ private static final String VFW_TOSCA_COMPLIANT_POLICY = "vfw/tosca-compliant-vfw.json";
+ private static final String VFW_ONSET = "vfw/vfw.onset.json";
+ private static final String VFW_APPC_SUCCESS = "vfw/vfw.appc.success.json";
+
+ // VLB
+ private static final String VLB_TOSCA_LEGACY_POLICY = "vlb/tosca-vlb.json";
+ private static final String VLB_TOSCA_COMPLIANT_POLICY = "vlb/tosca-compliant-vlb.json";
+ private static final String VLB_ONSET = "vlb/vlb.onset.json";
+
+ /*
+ * Coders used to decode requests and responses.
+ */
+ private static final Coder APPC_LEGACY_CODER = new StandardCoderInstantAsMillis();
+ private static final Coder APPC_LCM_CODER = new StandardCoder();
+
+ // these may be overridden by junit tests
+ private static Function<String, Rules> ruleMaker = Rules::new;
+ private static Supplier<HttpClients> httpClientMaker = HttpClients::new;
+ private static Supplier<Simulators> simMaker = Simulators::new;
+ private static Supplier<Topics> topicMaker = Topics::new;
+
+ protected static Rules rules;
+ protected static HttpClients httpClients;
+ protected static Simulators simulators;
+
+
+ // used to inject and wait for messages
+ @Getter(AccessLevel.PROTECTED)
+ private Topics topics;
+
+ // used to wait for messages on SINK topics
+ protected Listener<VirtualControlLoopNotification> policyClMgt;
+ protected Listener<Request> appcClSink;
+ protected Listener<AppcLcmDmaapWrapper> appcLcmRead;
+
+ protected PolicyController controller;
+
+ /*
+ * Tosca Policy that was loaded.
+ */
+ protected ToscaPolicy policy;
+
+
+ /**
+ * Initializes {@link #rules}, {@link #httpClients}, and {@link #simulators}.
+ *
+ * @param controllerName the rule controller name
+ */
+ public static void initStatics(String controllerName) {
+ rules = ruleMaker.apply(controllerName);
+ httpClients = httpClientMaker.get();
+ simulators = simMaker.get();
+ }
+
+ /**
+ * Destroys {@link #httpClients}, {@link #simulators}, and {@link #rules}.
+ */
+ public static void finishStatics() {
+ httpClients.destroy();
+ simulators.destroy();
+ rules.destroy();
+ }
+
+ /**
+ * Initializes {@link #topics} and {@link #controller}.
+ */
+ public void init() {
+ topics = topicMaker.get();
+ controller = rules.getController();
+ }
+
+ /**
+ * Destroys {@link #topics} and resets the rule facts.
+ */
+ public void finish() {
+ topics.destroy();
+ rules.resetFacts();
+ }
+
+ // Service123 (i.e., Policy with multiple operations)
+
+ /**
+ * Service123 with Tosca Compliant Policy.
+ */
+ @Test
+ public void testService123Compliant() {
+ policyClMgt = topics.createListener(POLICY_CL_MGT_TOPIC, VirtualControlLoopNotification.class, controller);
+ appcLcmRead = topics.createListener(APPC_LCM_READ_TOPIC, AppcLcmDmaapWrapper.class, APPC_LCM_CODER);
+
+ assertEquals(0, controller.getDrools().factCount(rules.getControllerName()));
+ policy = rules.setupPolicyFromFile(SERVICE123_TOSCA_COMPLIANT_POLICY);
+ assertEquals(2, controller.getDrools().factCount(rules.getControllerName()));
+
+ // inject an ONSET event over the DCAE topic
+ topics.inject(DCAE_TOPIC, SERVICE123_ONSET);
+
+ /* Wait to acquire a LOCK and a PDP-X PERMIT */
+ waitForLockAndPermit(policy, policyClMgt);
+
+ // restart request should be sent and fail four times (i.e., because retry=3)
+ for (int count = 0; count < 4; ++count) {
+ AppcLcmDmaapWrapper appcreq = appcLcmRead.await(req -> "restart".equals(req.getRpcName()));
+
+ topics.inject(APPC_LCM_WRITE_TOPIC, SERVICE123_APPC_RESTART_FAILURE,
+ appcreq.getBody().getInput().getCommonHeader().getSubRequestId());
+ }
+
+ // rebuild request should be sent and fail once
+ AppcLcmDmaapWrapper appcreq = appcLcmRead.await(req -> "rebuild".equals(req.getRpcName()));
+
+ topics.inject(APPC_LCM_WRITE_TOPIC, SERVICE123_APPC_REBUILD_FAILURE,
+ appcreq.getBody().getInput().getCommonHeader().getSubRequestId());
+
+ // migrate request should be sent and succeed
+ appcreq = appcLcmRead.await(req -> "migrate".equals(req.getRpcName()));
+
+ topics.inject(APPC_LCM_WRITE_TOPIC, SERVICE123_APPC_MIGRATE_SUCCESS,
+ appcreq.getBody().getInput().getCommonHeader().getSubRequestId());
+
+ /* --- Operation Completed --- */
+
+ waitForOperationSuccess();
+
+ /* --- Transaction Completed --- */
+ waitForFinalSuccess(policy, policyClMgt);
+ }
+
+ // Duplicate events
+
+ /**
+ * This test case tests the scenario where 3 events occur and 2 of the requests refer
+ * to the same target entity while the 3rd is for another entity. The expected result
+ * is that the event with the duplicate target entity will have a final success result
+ * for one of the events, and a rejected message for the one that was unable to obtain
+ * the lock. The event that is referring to a different target entity should be able
+ * to obtain a lock since it is a different target. After processing of all events
+ * there should only be the policy and params objects left in memory.
+ */
+ @Test
+ public void testDuplicatesEvents() {
+ policyClMgt = topics.createListener(POLICY_CL_MGT_TOPIC, VirtualControlLoopNotification.class, controller);
+ appcLcmRead = topics.createListener(APPC_LCM_READ_TOPIC, AppcLcmDmaapWrapper.class, APPC_LCM_CODER);
+
+ assertEquals(0, controller.getDrools().factCount(rules.getControllerName()));
+ policy = rules.setupPolicyFromFile(DUPLICATES_TOSCA_COMPLIANT_POLICY);
+ assertEquals(2, controller.getDrools().factCount(rules.getControllerName()));
+
+ /*
+ * Inject ONSET events over the DCAE topic. First and last have the same target
+ * entity, but different request IDs - only one should succeed. The middle one is
+ * for a different target entity, so it should succeed.
+ */
+ topics.inject(DCAE_TOPIC, DUPLICATES_ONSET_1, UUID.randomUUID().toString());
+ topics.inject(DCAE_TOPIC, DUPLICATES_ONSET_2);
+ topics.inject(DCAE_TOPIC, DUPLICATES_ONSET_1, UUID.randomUUID().toString());
+
+ // one should immediately generate a FINAL failure
+ waitForFinal(policy, policyClMgt, ControlLoopNotificationType.FINAL_FAILURE);
+
+ // should see two restarts
+ for (int count = 0; count < 2; ++count) {
+ AppcLcmDmaapWrapper appcreq = appcLcmRead.await(req -> "restart".equals(req.getRpcName()));
+
+ // indicate success
+ topics.inject(APPC_LCM_WRITE_TOPIC, DUPLICATES_APPC_SUCCESS,
+ appcreq.getBody().getInput().getCommonHeader().getSubRequestId());
+ }
+
+ // should see two FINAL successes
+ VirtualControlLoopNotification notif1 = waitForFinalSuccess(policy, policyClMgt);
+ VirtualControlLoopNotification notif2 = waitForFinalSuccess(policy, policyClMgt);
+
+ // get the list of target names so we can ensure there's one of each
+ List<String> actual = List.of(notif1, notif2).stream().map(notif -> notif.getAai().get("generic-vnf.vnf-id"))
+ .sorted().collect(Collectors.toList());
+
+ assertEquals(List.of("duplicate-VNF", "vCPE_Infrastructure_vGMUX_demo_app").toString(), actual.toString());
+ }
+
+ // VCPE
+
+ /**
+ * Sunny Day with Legacy Tosca Policy.
+ */
+ @Test
+ public void testVcpeSunnyDayLegacy() {
+ appcLcmSunnyDay(VCPE_TOSCA_LEGACY_POLICY, VCPE_ONSET_1, "restart");
+ }
+
+ /**
+ * Sunny Day with Tosca Compliant Policy.
+ */
+ @Test
+ public void testVcpeSunnyDayCompliant() {
+ appcLcmSunnyDay(VCPE_TOSCA_COMPLIANT_POLICY, VCPE_ONSET_1, "restart");
+ }
+
+ /**
+ * An ONSET flood prevention test that injects a few ONSETs at once. It attempts to
+ * simulate the flooding behavior of the DCAE TCA microservice. TCA could blast tens
+ * or hundreds of ONSETs within sub-second intervals.
+ */
+ @Test
+ public void testVcpeOnsetFloodPrevention() {
+ appcLcmSunnyDay(VCPE_TOSCA_COMPLIANT_POLICY, List.of(VCPE_ONSET_1, VCPE_ONSET_2, VCPE_ONSET_3), "restart");
+ }
+
+ // VDNS
+
+ /**
+ * Sunny Day with Tosca Compliant Policy.
+ */
+ @Test
+ public void testVdnsSunnyDayCompliant() {
+ httpSunnyDay(VDNS_TOSCA_COMPLIANT_POLICY, VDNS_ONSET);
+ }
+
+ // VFW
+
+ /**
+ * VFW Sunny Day with Legacy Tosca Policy.
+ */
+ @Test
+ public void testVfwSunnyDayLegacy() {
+ appcLegacySunnyDay(VFW_TOSCA_LEGACY_POLICY, VFW_ONSET, "ModifyConfig");
+ }
+
+ /**
+ * VFW Sunny Day with Tosca Compliant Policy.
+ */
+ @Test
+ public void testVfwSunnyDayCompliant() {
+ appcLegacySunnyDay(VFW_TOSCA_COMPLIANT_POLICY, VFW_ONSET, "ModifyConfig");
+ }
+
+ // VLB
+
+ /**
+ * Sunny Day with Legacy Tosca Policy.
+ */
+ @Test
+ public void testVlbSunnyDayLegacy() {
+ httpSunnyDay(VLB_TOSCA_LEGACY_POLICY, VLB_ONSET);
+ }
+
+ /**
+ * Sunny Day with Tosca Compliant Policy.
+ */
+ @Test
+ public void testVlbSunnyDayCompliant() {
+ httpSunnyDay(VLB_TOSCA_COMPLIANT_POLICY, VLB_ONSET);
+ }
+
+ /**
+ * Sunny day scenario for use cases that use APPC-LCM.
+ *
+ * @param policyFile file containing the ToscaPolicy to be loaded
+ * @param onsetFile file containing the ONSET to be injected
+ * @param operation expected APPC operation request
+ */
+ protected void appcLcmSunnyDay(String policyFile, String onsetFile, String operation) {
+ appcLcmSunnyDay(policyFile, List.of(onsetFile), operation);
+ }
+
+ /**
+ * Sunny day scenario for use cases that use APPC-LCM.
+ *
+ * @param policyFile file containing the ToscaPolicy to be loaded
+ * @param onsetFiles list of files containing the ONSET to be injected
+ * @param operation expected APPC operation request
+ */
+ protected void appcLcmSunnyDay(String policyFile, List<String> onsetFiles, String operation) {
+ policyClMgt = topics.createListener(POLICY_CL_MGT_TOPIC, VirtualControlLoopNotification.class, controller);
+ appcLcmRead = topics.createListener(APPC_LCM_READ_TOPIC, AppcLcmDmaapWrapper.class, APPC_LCM_CODER);
+
+ assertEquals(0, controller.getDrools().factCount(rules.getControllerName()));
+ policy = rules.setupPolicyFromFile(policyFile);
+ assertEquals(2, controller.getDrools().factCount(rules.getControllerName()));
+
+ // inject several ONSET events over the DCAE topic
+ for (String onsetFile : onsetFiles) {
+ topics.inject(DCAE_TOPIC, onsetFile);
+ }
+
+ /* Wait to acquire a LOCK and a PDP-X PERMIT */
+ waitForLockAndPermit(policy, policyClMgt);
+
+ /*
+ * Ensure that an APPC RESTART request was sent in response to the matching ONSET
+ */
+ AppcLcmDmaapWrapper appcreq = appcLcmRead.await(req -> operation.equals(req.getRpcName()));
+
+ /*
+ * Inject a 400 APPC Response Return over the APPC topic, with appropriate
+ * subRequestId
+ */
+ topics.inject(APPC_LCM_WRITE_TOPIC, VCPE_APPC_SUCCESS,
+ appcreq.getBody().getInput().getCommonHeader().getSubRequestId());
+
+ /* --- Operation Completed --- */
+
+ waitForOperationSuccess();
+
+ /* --- Transaction Completed --- */
+ waitForFinalSuccess(policy, policyClMgt);
+ }
+
+ /**
+ * Sunny day scenario for use cases that use Legacy APPC.
+ *
+ * @param policyFile file containing the ToscaPolicy to be loaded
+ * @param onsetFile file containing the ONSET to be injected
+ * @param operation expected APPC operation request
+ */
+ protected void appcLegacySunnyDay(String policyFile, String onsetFile, String operation) {
+ policyClMgt = topics.createListener(POLICY_CL_MGT_TOPIC, VirtualControlLoopNotification.class, controller);
+ appcClSink = topics.createListener(APPC_CL_TOPIC, Request.class, APPC_LEGACY_CODER);
+
+ assertEquals(0, controller.getDrools().factCount(rules.getControllerName()));
+ policy = rules.setupPolicyFromFile(policyFile);
+ assertEquals(2, controller.getDrools().factCount(rules.getControllerName()));
+
+ /* Inject an ONSET event over the DCAE topic */
+ topics.inject(DCAE_TOPIC, onsetFile);
+
+ /* Wait to acquire a LOCK and a PDP-X PERMIT */
+ waitForLockAndPermit(policy, policyClMgt);
+
+ /*
+ * Ensure that an APPC RESTART request was sent in response to the matching ONSET
+ */
+ Request appcreq = appcClSink.await(req -> operation.equals(req.getAction()));
+
+ /*
+ * Inject a 400 APPC Response Return over the APPC topic, with appropriate
+ * subRequestId
+ */
+ topics.inject(APPC_CL_TOPIC, VFW_APPC_SUCCESS, appcreq.getCommonHeader().getSubRequestId());
+
+ /* --- Operation Completed --- */
+
+ waitForOperationSuccess();
+
+ /* --- Transaction Completed --- */
+ waitForFinalSuccess(policy, policyClMgt);
+ }
+
+ /**
+ * Sunny day scenario for use cases that use an HTTP simulator.
+ *
+ * @param policyFile file containing the ToscaPolicy to be loaded
+ * @param onsetFile file containing the ONSET to be injected
+ * @param operation expected APPC operation request
+ */
+ protected void httpSunnyDay(String policyFile, String onsetFile) {
+ policyClMgt = topics.createListener(POLICY_CL_MGT_TOPIC, VirtualControlLoopNotification.class, controller);
+
+ assertEquals(0, controller.getDrools().factCount(rules.getControllerName()));
+ policy = rules.setupPolicyFromFile(policyFile);
+ assertEquals(2, controller.getDrools().factCount(rules.getControllerName()));
+
+ /* Inject an ONSET event over the DCAE topic */
+ topics.inject(DCAE_TOPIC, onsetFile);
+
+ /* Wait to acquire a LOCK and a PDP-X PERMIT */
+ waitForLockAndPermit(policy, policyClMgt);
+
+ /* --- Operation Completed --- */
+
+ waitForOperationSuccess();
+
+ /* --- Transaction Completed --- */
+ waitForFinalSuccess(policy, policyClMgt);
+ }
+
+ /**
+ * Waits for a OPERATION SUCCESS transaction notification.
+ */
+ protected void waitForOperationSuccess() {
+ policyClMgt.await(notif -> notif.getNotification() == ControlLoopNotificationType.OPERATION_SUCCESS);
+ }
+
+ /**
+ * Waits for a FINAL SUCCESS transaction notification.
+ *
+ * @return the FINAL SUCCESS notification
+ */
+ protected VirtualControlLoopNotification waitForFinalSuccess(ToscaPolicy policy,
+ Listener<VirtualControlLoopNotification> policyClMgt) {
+
+ return this.waitForFinal(policy, policyClMgt, ControlLoopNotificationType.FINAL_SUCCESS);
+ }
+
+ /**
+ * Waits for notifications for LOCK acquisition and GUARD Permit so that event
+ * processing may proceed.
+ */
+ protected abstract void waitForLockAndPermit(ToscaPolicy policy,
+ Listener<VirtualControlLoopNotification> policyClMgt);
+
+ /**
+ * Waits for a FINAL transaction notification.
+ *
+ * @param finalType FINAL_xxx type for which to wait
+ *
+ * @return the FINAL notification
+ */
+ protected abstract VirtualControlLoopNotification waitForFinal(ToscaPolicy policy,
+ Listener<VirtualControlLoopNotification> policyClMgt, ControlLoopNotificationType finalType);
+}
diff --git a/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/HttpClients.java b/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/HttpClients.java
new file mode 100644
index 000000000..eb729ad6d
--- /dev/null
+++ b/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/HttpClients.java
@@ -0,0 +1,67 @@
+/*-
+ * ============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 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.drools.persistence.SystemPersistenceConstants;
+
+/**
+ * Mechanism by which junit tests can manage HTTP Clients.
+ */
+public class HttpClients {
+
+ /**
+ * Constructs the object.
+ */
+ public HttpClients() {
+ super();
+ }
+
+
+ /**
+ * Adds Http Clients specified in the property file.
+ *
+ * @param propFilePrefix prefix prepended to "-http-client.properties" to yield the
+ * full name of the property file containing http client properties
+ */
+ public void addClients(String propFilePrefix) {
+ try {
+ getClientFactory().build(SystemPersistenceConstants.getManager().getHttpClientProperties(propFilePrefix));
+ } catch (HttpClientConfigException e) {
+ throw new IllegalArgumentException("cannot initialize HTTP clients", e);
+ }
+ }
+
+ /**
+ * Destroys all Http Clients.
+ */
+ public void destroy() {
+ getClientFactory().destroy();
+ }
+
+ // these methods may be overridden by junit tests
+
+ protected HttpClientFactory getClientFactory() {
+ return HttpClientFactoryInstance.getClientFactory();
+ }
+}
diff --git a/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/Listener.java b/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/Listener.java
new file mode 100644
index 000000000..5042f54c6
--- /dev/null
+++ b/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/Listener.java
@@ -0,0 +1,180 @@
+/*-
+ * ============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 java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.function.Function;
+import java.util.function.Predicate;
+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.TopicListener;
+import org.onap.policy.common.endpoints.event.comm.TopicSink;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Listener for messages published on a topic SINK.
+ *
+ * @param <T> message type
+ */
+public class Listener<T> implements TopicListener {
+ private static final Logger logger = LoggerFactory.getLogger(Listener.class);
+ public static long DEFAULT_WAIT_SEC = 5L;
+
+ private final TopicSink sink;
+ private final Function<String, T> decoder;
+ private final BlockingQueue<T> messages = new LinkedBlockingQueue<>();
+
+ /**
+ * Constructs the object.
+ *
+ * @param topicName name of the NOOP topic SINK on which to listen
+ * @param decoder function that takes a topic name and a message and decodes it into
+ * the desired type
+ */
+ public Listener(String topicName, Function<String, T> decoder) {
+ this.sink = getTopicManager().getNoopTopicSink(topicName);
+ this.decoder = decoder;
+ this.sink.register(this);
+ }
+
+ /**
+ * Determines if there are any messages waiting.
+ *
+ * @return {@code true} if there are no messages waiting, {@code false} otherwise
+ */
+ public boolean isEmpty() {
+ return messages.isEmpty();
+ }
+
+ /**
+ * Waits, for the default amount of time, for a message to be published to the topic.
+ *
+ * @return the message that was published
+ * @throws TopicException if interrupted or no message is received within the
+ * specified time
+ */
+ public T await() {
+ return await(DEFAULT_WAIT_SEC, TimeUnit.SECONDS);
+ }
+
+ /**
+ * Waits, for the specified period of time, for a message to be published to the
+ * topic.
+ *
+ * @param twait maximum time to wait
+ * @param unit time unit
+ * @return the message that was published
+ * @throws TopicException if interrupted or no message is received within the
+ * specified time
+ */
+ public T await(long twait, TimeUnit unit) {
+ return await(twait, unit, msg -> true);
+ }
+
+ /**
+ * Waits, for the default amount of time, for a message to be published to the topic.
+ *
+ * @param filter filter used to select the message of interest; preceding messages
+ * that do not pass the filter are discarded
+ * @return the message that was published
+ * @throws TopicException if interrupted or no message is received within the
+ * specified time
+ */
+ public T await(Predicate<T> filter) {
+ return await(DEFAULT_WAIT_SEC, TimeUnit.SECONDS, filter);
+ }
+
+ /**
+ * Waits, for the specified period of time, for a message to be published to the
+ * topic.
+ *
+ * @param twait maximum time to wait
+ * @param unit time unit
+ * @param filter filter used to select the message of interest; preceding messages
+ * that do not pass the filter are discarded
+ * @return the message that was published
+ * @throws TopicException if interrupted or no message is received within the
+ * specified time
+ */
+ public T await(long twait, TimeUnit unit, Predicate<T> filter) {
+ long endMs = System.currentTimeMillis() + TimeUnit.MILLISECONDS.convert(twait, unit);
+
+ for (;;) {
+ try {
+ long remainingMs = endMs - System.currentTimeMillis();
+ if (remainingMs < 0) {
+ throw new TimeoutException();
+ }
+
+ T msg = pollMessage(remainingMs);
+ if (msg == null) {
+ throw new TimeoutException();
+ }
+
+ if (filter.test(msg)) {
+ return msg;
+ }
+
+ logger.info("message discarded by the filter on topic {}", sink.getTopic());
+
+ } catch (InterruptedException e) {
+ logger.warn("'await' interrupted on topic {}", sink.getTopic());
+ Thread.currentThread().interrupt();
+ throw new TopicException(e);
+
+ } catch (TimeoutException e) {
+ logger.warn("'await' timed out on topic {}", sink.getTopic());
+ throw new TopicException(e);
+ }
+ }
+ }
+
+ /**
+ * Unregisters the listener.
+ */
+ public void unregister() {
+ sink.unregister(this);
+ }
+
+ @Override
+ public void onTopicEvent(CommInfrastructure commType, String topic, String event) {
+ try {
+ messages.add(decoder.apply(event));
+ } catch (RuntimeException e) {
+ logger.warn("cannot decode message on topic {} for event {}", topic, event, e);
+ }
+ }
+
+ // these methods may be overridden by junit tests
+
+ protected TopicEndpoint getTopicManager() {
+ return TopicEndpointManager.getManager();
+ }
+
+ protected T pollMessage(long remainingMs) throws InterruptedException {
+ return messages.poll(remainingMs, TimeUnit.MILLISECONDS);
+ }
+}
diff --git a/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/NamedRunner.java b/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/NamedRunner.java
new file mode 100644
index 000000000..1cbe5a56a
--- /dev/null
+++ b/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/NamedRunner.java
@@ -0,0 +1,85 @@
+/*-
+ * ============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 org.junit.Ignore;
+import org.junit.runner.Description;
+import org.junit.runner.notification.RunNotifier;
+import org.junit.runners.BlockJUnit4ClassRunner;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.InitializationError;
+
+/**
+ * Runs tests listed via the {@link TestNames} annotation.
+ */
+public class NamedRunner extends BlockJUnit4ClassRunner {
+
+ /**
+ * Constructs the object.
+ */
+ public NamedRunner(Class<?> testClass) throws InitializationError {
+ super(testClass);
+ }
+
+ @Override
+ protected void runChild(final FrameworkMethod method, RunNotifier notifier) {
+ Description description = describeChild(method);
+
+ if (method.getAnnotation(Ignore.class) != null) {
+ notifier.fireTestIgnored(description);
+
+ } else if (!isNamed(description.getTestClass(), method.getName())) {
+ notifier.fireTestIgnored(description);
+
+ } else {
+ runLeaf(methodBlock(method), description, notifier);
+ }
+ }
+
+ /**
+ * Determines if the test is in the list of tests to be included.
+ *
+ * @param testClass class under test
+ * @param testName name of the test of interest
+ * @return {@code true} if the test is in the list, {@code false} otherwise
+ */
+ private boolean isNamed(Class<?> testClass, String testName) {
+ TestNames annot = testClass.getAnnotation(TestNames.class);
+ if (annot == null) {
+ // no annotation - everything passes
+ return true;
+ }
+
+ for (String name : annot.names()) {
+ if (testName.equals(name)) {
+ return true;
+ }
+ }
+
+ for (String prefix : annot.prefixes()) {
+ if (testName.startsWith(prefix)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/Rules.java b/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/Rules.java
new file mode 100644
index 000000000..7549c6be6
--- /dev/null
+++ b/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/Rules.java
@@ -0,0 +1,413 @@
+/*-
+ * ============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.awaitility.Awaitility.await;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Properties;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import lombok.Getter;
+import org.apache.commons.lang3.StringUtils;
+import org.kie.api.event.rule.AfterMatchFiredEvent;
+import org.kie.api.event.rule.BeforeMatchFiredEvent;
+import org.kie.api.event.rule.DefaultAgendaEventListener;
+import org.kie.api.event.rule.DefaultRuleRuntimeEventListener;
+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.onap.policy.common.utils.coder.CoderException;
+import org.onap.policy.common.utils.coder.StandardCoder;
+import org.onap.policy.common.utils.resources.ResourceUtils;
+import org.onap.policy.controlloop.ControlLoopEvent;
+import org.onap.policy.controlloop.drl.legacy.ControlLoopParams;
+import org.onap.policy.controlloop.eventmanager.ControlLoopEventManager;
+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.persistence.SystemPersistenceConstants;
+import org.onap.policy.drools.system.PolicyController;
+import org.onap.policy.drools.system.PolicyControllerConstants;
+import org.onap.policy.drools.system.PolicyControllerFactory;
+import org.onap.policy.drools.system.PolicyEngine;
+import org.onap.policy.drools.system.PolicyEngineConstants;
+import org.onap.policy.drools.util.KieUtils;
+import org.onap.policy.drools.utils.logging.LoggerUtil;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Mechanism by which junit tests can manage the rule engine.
+ */
+public class Rules {
+ private static final Logger logger = LoggerFactory.getLogger(Rules.class);
+ private static final StandardCoder coder = new StandardCoder();
+
+ /**
+ * PDP-D Engine.
+ */
+ @Getter
+ private final PolicyEngine pdpd = makeEngine();
+
+ /**
+ * PDP-D Configuration Repository.
+ */
+ @Getter
+ private final SystemPersistence pdpdRepo = makePdpdRepo();
+
+
+ @Getter
+ private final String controllerName;
+
+ @Getter
+ private PolicyController controller;
+
+
+ /**
+ * Constructs the object.
+ *
+ * @param controllerName name of the controller
+ */
+ public Rules(String controllerName) {
+ this.controllerName = controllerName;
+ }
+
+ /**
+ * Configures various items, including the PDP-D Engine.
+ *
+ * @param resourceDir path to resource directory
+ */
+ public void configure(String resourceDir) {
+ pdpdRepo.setConfigurationDir("src/test/resources/config");
+
+ try {
+ File kmoduleFile = new File(resourceDir + "/META-INF/kmodule.xml");
+ File pomFile = new File("src/test/resources/" + controllerName + ".pom");
+ String resourceDir2 = resourceDir + "/org/onap/policy/controlloop/";
+ File ruleFile = new File(resourceDir + "/" + controllerName + ".drl");
+ List<File> ruleFiles = Collections.singletonList(ruleFile);
+
+ installArtifact(kmoduleFile, pomFile, resourceDir2, ruleFiles);
+ } catch (IOException e) {
+ throw new IllegalArgumentException("cannot configure KIE session for " + controllerName, e);
+ }
+
+ setupLogging();
+
+ pdpd.configure(new Properties());
+ }
+
+ /**
+ * Starts various items, including the PDP-D Engine.
+ */
+ public void start() {
+ controller = pdpd.createPolicyController(controllerName, pdpdRepo.getControllerProperties(controllerName));
+ pdpd.start();
+
+ setupDroolsLogging();
+ }
+
+ /**
+ * Stop PDP-D.
+ */
+ public void destroy() {
+ getControllerFactory().shutdown(controllerName);
+ pdpd.stop();
+ }
+
+ /**
+ * Removes various facts from working memory, including the Policy and Params, as well
+ * as any event managers and events.
+ */
+ public void resetFacts() {
+ List<Class<?>> classes = List.of(ToscaPolicy.class, ControlLoopParams.class, ControlLoopEventManager2.class,
+ ControlLoopEvent.class);
+
+ // delete all objects of the listed classes
+ DroolsController drools = controller.getDrools();
+ classes.forEach(drools::delete);
+
+ // wait for them to be deleted
+ for (Class<?> clazz : classes) {
+ await(clazz.getSimpleName()).atMost(5, TimeUnit.SECONDS)
+ .until(() -> drools.facts(controllerName, clazz).isEmpty());
+ }
+
+ /*
+ * We can't delete this class directly; we have to wait for the rules to clean it
+ * up, because the rule also cleans up a number of other associated objects.
+ */
+ Class<?> clazz = ControlLoopEventManager.class;
+ await(clazz.getSimpleName()).atMost(5, TimeUnit.SECONDS)
+ .until(() -> drools.facts(controllerName, clazz).isEmpty());
+ }
+
+ /**
+ * Installs a policy from policy/models (examples) repo.
+ */
+ public ToscaPolicy setupPolicyFromTemplate(String templatePath, String policyName) {
+ try {
+ return setupPolicy(getPolicyFromTemplate(templatePath, policyName));
+
+ } catch (InterruptedException | CoderException e) {
+ throw new IllegalArgumentException("policy " + policyName, e);
+ }
+ }
+
+ private ToscaPolicy getPolicyFromTemplate(String resourcePath, String policyName) throws CoderException {
+ String policyJson = ResourceUtils.getResourceAsString(resourcePath);
+ if (policyJson == null) {
+ throw new CoderException(new FileNotFoundException(resourcePath));
+ }
+
+ ToscaServiceTemplate serviceTemplate = coder.decode(policyJson, ToscaServiceTemplate.class);
+ ToscaPolicy policy = serviceTemplate.getToscaTopologyTemplate().getPolicies().get(0).get(policyName);
+ assertNotNull(policy);
+
+ /*
+ * name and version are used within a drl. api component and drools core will
+ * ensure that these are populated.
+ */
+ if (StringUtils.isBlank(policy.getName())) {
+ policy.setName(policyName);
+ }
+
+ if (StringUtils.isBlank(policy.getVersion())) {
+ policy.setVersion(policy.getTypeVersion());
+ }
+
+ return serviceTemplate.getToscaTopologyTemplate().getPolicies().get(0).get(policyName);
+ }
+
+ /**
+ * Installs a given policy.
+ */
+ public ToscaPolicy setupPolicyFromFile(String policyPath) {
+ try {
+ return setupPolicy(getPolicyFromFile(policyPath));
+
+ } catch (InterruptedException | IOException | CoderException e) {
+ throw new IllegalArgumentException("policy " + policyPath, e);
+ }
+ }
+
+ private ToscaPolicy getPolicyFromFile(String policyPath) throws IOException, CoderException {
+ String policyJson = ResourceUtils.getResourceAsString(policyPath);
+ if (policyJson == null) {
+ throw new CoderException(new FileNotFoundException(policyPath));
+ }
+
+ return coder.decode(policyJson, ToscaPolicy.class);
+ }
+
+ private ToscaPolicy setupPolicy(ToscaPolicy policy) throws InterruptedException {
+ final KieObjectExpectedCallback<?> policyTracker = new KieObjectInsertedExpectedCallback<>(policy);
+ final KieObjectExpectedCallback<?> paramsTracker =
+ new KieClassInsertedExpectedCallback<>(ControlLoopParams.class);
+
+ controller.getDrools().offer(policy);
+
+ assertTrue(policyTracker.isNotified());
+ assertTrue(paramsTracker.isNotified());
+
+ assertEquals(1, controller.getDrools().facts(controllerName, ToscaPolicy.class).stream()
+ .filter((anotherPolicy) -> anotherPolicy == policy).count());
+
+ assertEquals(1, controller.getDrools().facts(controllerName, ControlLoopParams.class).stream()
+ .filter((params) -> params.getToscaPolicy() == policy).count());
+ return policy;
+ }
+
+ /**
+ * Sets up overall logging.
+ */
+ private void setupLogging() {
+ LoggerUtil.setLevel(LoggerUtil.ROOT_LOGGER, "WARN");
+ LoggerUtil.setLevel("org.eclipse.jetty", "WARN");
+ LoggerUtil.setLevel("org.onap.policy.controlloop", "INFO");
+ LoggerUtil.setLevel("network", "INFO");
+ }
+
+ /**
+ * Sets up Drools Logging for events of interest.
+ */
+ private void setupDroolsLogging() {
+ KieSession session = getKieSession();
+
+ session.addEventListener(new RuleListenerLogger());
+ session.addEventListener(new AgendaListenerLogger());
+ }
+
+ /**
+ * Logs Modifications to Working Memory.
+ */
+ private static class RuleListenerLogger implements RuleRuntimeEventListener {
+ @Override
+ public void objectInserted(ObjectInsertedEvent event) {
+ String ruleName = (event.getRule() != null) ? event.getRule().getName() : "null";
+ logger.info("RULE {}: inserted {}", ruleName, event.getObject());
+ }
+
+ @Override
+ public void objectUpdated(ObjectUpdatedEvent event) {
+ String ruleName = (event.getRule() != null) ? event.getRule().getName() : "null";
+ logger.info("RULE {}: updated {}", ruleName, event.getObject());
+
+ }
+
+ @Override
+ public void objectDeleted(ObjectDeletedEvent event) {
+ String ruleName = (event.getRule() != null) ? event.getRule().getName() : "null";
+ logger.info("RULE {}: deleted {}", ruleName, event.getOldObject());
+ }
+ }
+
+ /**
+ * Logs Rule Matches.
+ */
+ private static class AgendaListenerLogger extends DefaultAgendaEventListener {
+ @Override
+ public void matchCreated(MatchCreatedEvent event) {
+ logger.info("RULE {}: match created", event.getMatch().getRule().getName());
+ }
+
+ @Override
+ public void matchCancelled(MatchCancelledEvent event) {
+ logger.info("RULE {}: match cancelled", event.getMatch().getRule().getName());
+ }
+
+ @Override
+ public void beforeMatchFired(BeforeMatchFiredEvent event) {
+ logger.info("RULE {}: before match fired", event.getMatch().getRule().getName());
+ }
+
+ @Override
+ public void afterMatchFired(AfterMatchFiredEvent event) {
+ logger.info("RULE {}: after match fired", event.getMatch().getRule().getName());
+ }
+ }
+
+ /**
+ * Base Class to track Working Memory updates for objects of type T.
+ */
+ private abstract class KieObjectExpectedCallback<T> extends DefaultRuleRuntimeEventListener {
+ protected T subject;
+
+ protected CountDownLatch countDownLatch = new CountDownLatch(1);
+
+ public KieObjectExpectedCallback(T affected) {
+ subject = affected;
+ register();
+ }
+
+ public boolean isNotified() throws InterruptedException {
+ return countDownLatch.await(9L, TimeUnit.SECONDS);
+ }
+
+ protected void callbacked() {
+ unregister();
+ countDownLatch.countDown();
+ }
+
+ public KieObjectExpectedCallback<T> register() {
+ getKieSession().addEventListener(this);
+ return this;
+ }
+
+ public KieObjectExpectedCallback<T> unregister() {
+ getKieSession().removeEventListener(this);
+ return this;
+ }
+ }
+
+ /**
+ * Tracks inserts in Working Memory for an object of type T.
+ */
+ private class KieObjectInsertedExpectedCallback<T> extends KieObjectExpectedCallback<T> {
+ public KieObjectInsertedExpectedCallback(T affected) {
+ super(affected);
+ }
+
+ @Override
+ public void objectInserted(ObjectInsertedEvent event) {
+ if (subject == event.getObject()) {
+ callbacked();
+ }
+ }
+ }
+
+ /**
+ * Tracks inserts in Working Memory for any object of class T.
+ */
+ private class KieClassInsertedExpectedCallback<T> extends KieObjectInsertedExpectedCallback<T> {
+
+ public KieClassInsertedExpectedCallback(T affected) {
+ super(affected);
+ }
+
+ public void objectInserted(ObjectInsertedEvent event) {
+ if (subject == event.getObject().getClass()) {
+ callbacked();
+ }
+ }
+ }
+
+ // these may be overridden by junit tests
+
+
+ protected PolicyEngine makeEngine() {
+ return PolicyEngineConstants.getManager();
+ }
+
+
+ protected SystemPersistence makePdpdRepo() {
+ return SystemPersistenceConstants.getManager();
+ }
+
+ protected KieSession getKieSession() {
+ return getControllerFactory().get(controllerName).getDrools().getContainer().getPolicySession(controllerName)
+ .getKieSession();
+ }
+
+ protected PolicyControllerFactory getControllerFactory() {
+ return PolicyControllerConstants.getFactory();
+ }
+
+ protected void installArtifact(File kmoduleFile, File pomFile, String resourceDir, List<File> ruleFiles)
+ throws IOException {
+
+ KieUtils.installArtifact(kmoduleFile, pomFile, resourceDir, ruleFiles);
+ }
+}
diff --git a/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/SimulatorException.java b/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/SimulatorException.java
new file mode 100644
index 000000000..f9880d07a
--- /dev/null
+++ b/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/SimulatorException.java
@@ -0,0 +1,44 @@
+/*-
+ * ============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;
+
+/**
+ * Exception thrown by <i>Simulators</i>.
+ */
+public class SimulatorException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+
+ public SimulatorException() {
+ super();
+ }
+
+ public SimulatorException(String message) {
+ super(message);
+ }
+
+ public SimulatorException(Throwable cause) {
+ super(cause);
+ }
+
+ public SimulatorException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/Simulators.java b/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/Simulators.java
new file mode 100644
index 000000000..4a325a447
--- /dev/null
+++ b/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/Simulators.java
@@ -0,0 +1,85 @@
+/*-
+ * ============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 java.util.LinkedList;
+import java.util.List;
+import lombok.AccessLevel;
+import lombok.Getter;
+import org.onap.policy.common.endpoints.http.server.HttpServletServer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Simulator container.
+ */
+public class Simulators {
+ private static final Logger logger = LoggerFactory.getLogger(Simulators.class);
+
+ @Getter(AccessLevel.PROTECTED)
+ private final List<HttpServletServer> servers = new LinkedList<>();
+
+ /**
+ * Constructs the object.
+ */
+ public Simulators() {
+ super();
+ }
+
+ /**
+ * Invokes the given functions to start the simulators. Destroys <i>all</i> of the
+ * simulators if any fail to start.
+ *
+ * @param builders functions to invoke to build the simulators
+ */
+ public void start(SimulatorBuilder... builders) {
+ try {
+ for (SimulatorBuilder builder : builders) {
+ servers.add(builder.build());
+ }
+ } catch (InterruptedException e) {
+ logger.warn("interrupted building the simulators");
+ destroy();
+ Thread.currentThread().interrupt();
+ throw new SimulatorException(e);
+ }
+ }
+
+ /**
+ * Stops all of the simulators.
+ */
+ public void destroy() {
+ for (HttpServletServer server : servers) {
+ try {
+ server.shutdown();
+ } catch (RuntimeException e) {
+ logger.warn("error stopping simulator {}", server.getName(), e);
+ }
+ }
+
+ servers.clear();
+ }
+
+ @FunctionalInterface
+ public static interface SimulatorBuilder {
+ public HttpServletServer build() throws InterruptedException;
+ }
+}
diff --git a/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/TestNames.java b/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/TestNames.java
new file mode 100644
index 000000000..5f3d856ef
--- /dev/null
+++ b/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/TestNames.java
@@ -0,0 +1,44 @@
+/*-
+ * ============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 java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation for a test CLASS. Used to identify the names of the test methods to be
+ * included.
+ */
+@Target({ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface TestNames {
+ /**
+ * Test method names to be included.
+ */
+ String[] names() default {};
+
+ /**
+ * Prefixes of test method names to be included.
+ */
+ String[] prefixes() default {};
+}
diff --git a/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/TopicException.java b/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/TopicException.java
new file mode 100644
index 000000000..01a866966
--- /dev/null
+++ b/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/TopicException.java
@@ -0,0 +1,44 @@
+/*-
+ * ============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;
+
+/**
+ * Exception thrown by <i>Topics</i>.
+ */
+public class TopicException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+
+ public TopicException() {
+ super();
+ }
+
+ public TopicException(String message) {
+ super(message);
+ }
+
+ public TopicException(Throwable cause) {
+ super(cause);
+ }
+
+ public TopicException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/Topics.java b/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/Topics.java
new file mode 100644
index 000000000..f71559acb
--- /dev/null
+++ b/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/Topics.java
@@ -0,0 +1,176 @@
+/*-
+ * ============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 java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.function.Function;
+import org.onap.policy.common.endpoints.event.comm.TopicEndpoint;
+import org.onap.policy.common.endpoints.event.comm.TopicEndpointManager;
+import org.onap.policy.common.utils.coder.Coder;
+import org.onap.policy.common.utils.coder.CoderException;
+import org.onap.policy.common.utils.resources.ResourceUtils;
+import org.onap.policy.drools.protocol.coders.EventProtocolCoder;
+import org.onap.policy.drools.protocol.coders.EventProtocolCoderConstants;
+import org.onap.policy.drools.system.PolicyController;
+
+/**
+ * Mechanism by which junit tests can manage topic messages.
+ */
+public class Topics {
+ /**
+ * Wherever this string appears within an input file, it is replaced by a value passed
+ * as a parameter to the {@link #inject(String, String, String)} method.
+ */
+ private static final String REPLACE_ME = "${replaceMe}";
+
+ /**
+ * Listeners that have been created and registered by "this" object.
+ */
+ private final List<Listener<?>> listeners = new LinkedList<>();
+
+
+ /**
+ * Constructs the object.
+ */
+ public Topics() {
+ super();
+ }
+
+ /**
+ * Unregisters all of the listeners.
+ */
+ public void destroy() {
+ listeners.forEach(Listener::unregister);
+ }
+
+ /**
+ * Injects the content of the given file onto a NOOP topic SOURCE.
+ *
+ * @param topicName topic on which to inject
+ * @param file file whose content is to be injected
+ */
+ public void inject(String topicName, String file) {
+ inject(topicName, file, REPLACE_ME);
+ }
+
+ /**
+ * Injects the content of the given file onto a NOOP topic SOURCE, with the given
+ * substitution.
+ *
+ * @param topicName topic on which to inject
+ * @param file file whose content is to be injected
+ * @param newText text to be substituted for occurrences of "${replaceMe}" in the
+ * source file
+ */
+ public void inject(String topicName, String file, String newText) {
+ try {
+ String text = ResourceUtils.getResourceAsString(file);
+ if (text == null) {
+ throw new FileNotFoundException(file);
+ }
+ text = text.replace(REPLACE_ME, newText);
+ getTopicManager().getNoopTopicSource(topicName).offer(text);
+ } catch (IOException e) {
+ throw new TopicException(e);
+ }
+ }
+
+ /**
+ * Creates a listener for messages published on a NOOP topic SINK. Messages are
+ * decoded using the coder associated with the controller.
+ *
+ * @param <T> message type
+ * @param topicName name of the topic on which to listen
+ * @param expectedClass type of message expected
+ * @param controller controller whose decoders are to be used
+ * @return a new listener
+ */
+ public <T> Listener<T> createListener(String topicName, Class<T> expectedClass, PolicyController controller) {
+ EventProtocolCoder mgr = getProtocolCoder();
+ String groupId = controller.getDrools().getGroupId();
+ String artifactId = controller.getDrools().getArtifactId();
+
+ // @formatter:off
+ return createListener(topicName,
+ event -> expectedClass.cast(mgr.decode(groupId, artifactId, topicName, event)));
+ // @formatter:on
+ }
+
+ /**
+ * Creates a listener for messages published on a NOOP topic SINK. Messages are
+ * decoded using the specified coder.
+ *
+ * @param <T> message type
+ * @param topicName name of the topic on which to listen
+ * @param expectedClass type of message expected
+ * @param coder coder to decode the messages
+ * @return a new listener
+ */
+ public <T> Listener<T> createListener(String topicName, Class<T> expectedClass, Coder coder) {
+ Function<String, T> decoder = event -> {
+ try {
+ return coder.decode(event, expectedClass);
+ } catch (CoderException e) {
+ throw new IllegalArgumentException("cannot decode message", e);
+ }
+ };
+
+ return createListener(topicName, decoder);
+ }
+
+ /**
+ * Creates a listener for messages published on a NOOP topic SINK. Messages are
+ * decoded using the specified decoder.
+ *
+ * @param <T> message type
+ * @param topicName name of the topic on which to listen
+ * @param decoder function that takes a message and decodes it into the desired type
+ * @return a new listener
+ */
+ public <T> Listener<T> createListener(String topicName, Function<String, T> decoder) {
+ Listener<T> listener = makeListener(topicName, decoder);
+ listeners.add(listener);
+
+ return listener;
+ }
+
+ // these methods may be overridden by junit tests
+
+ protected TopicEndpoint getTopicManager() {
+ return TopicEndpointManager.getManager();
+ }
+
+ protected EventProtocolCoder getProtocolCoder() {
+ return EventProtocolCoderConstants.getManager();
+ }
+
+ protected <T> Listener<T> makeListener(String topicName, Function<String, T> decoder) {
+ return new Listener<>(topicName, decoder) {
+ @Override
+ protected TopicEndpoint getTopicManager() {
+ return Topics.this.getTopicManager();
+ }
+ };
+ }
+}
diff --git a/controlloop/common/controller-frankfurt/src/test/resources/vcpe/vcpe.appc.success.json b/controlloop/common/rules-test/src/main/resources/duplicates/duplicates.appc.success.json
index 331021798..331021798 100644
--- a/controlloop/common/controller-frankfurt/src/test/resources/vcpe/vcpe.appc.success.json
+++ b/controlloop/common/rules-test/src/main/resources/duplicates/duplicates.appc.success.json
diff --git a/controlloop/common/controller-usecases/src/test/resources/vcpe/vcpe.onset.1.json b/controlloop/common/rules-test/src/main/resources/duplicates/duplicates.onset.1.json
index d08ee47cd..70f48442f 100644
--- a/controlloop/common/controller-usecases/src/test/resources/vcpe/vcpe.onset.1.json
+++ b/controlloop/common/rules-test/src/main/resources/duplicates/duplicates.onset.1.json
@@ -1,16 +1,16 @@
{
- "closedLoopControlName": "ControlLoop-vCPE-48f0c2c3-a172-4192-9ae3-052274181b6e",
+ "closedLoopControlName": "ControlLoop-Duplicates-48f0c2c3-a172-4192-9ae3-052274181b6e",
"closedLoopAlarmStart": 1463679805324,
"closedLoopEventClient": "DCAE_INSTANCE_ID.dcae-tca",
"closedLoopEventStatus": "ONSET",
- "requestID": "664be3d2-6c12-4f4b-a3e7-c349acced200",
+ "requestID": "${replaceMe}",
"target_type": "VNF",
"target": "generic-vnf.vnf-id",
"AAI": {
"vserver.is-closed-loop-disabled": "false",
"vserver.prov-status": "ACTIVE",
- "generic-vnf.vnf-id": "vCPE_Infrastructure_vGMUX_demo_app"
+ "generic-vnf.vnf-id": "duplicate-VNF"
},
"from": "DCAE",
"version": "1.0.2"
-} \ No newline at end of file
+}
diff --git a/controlloop/common/controller-frankfurt/src/test/resources/vcpe/vcpe.onset.2.json b/controlloop/common/rules-test/src/main/resources/duplicates/duplicates.onset.2.json
index d08ee47cd..046243609 100644
--- a/controlloop/common/controller-frankfurt/src/test/resources/vcpe/vcpe.onset.2.json
+++ b/controlloop/common/rules-test/src/main/resources/duplicates/duplicates.onset.2.json
@@ -1,5 +1,5 @@
{
- "closedLoopControlName": "ControlLoop-vCPE-48f0c2c3-a172-4192-9ae3-052274181b6e",
+ "closedLoopControlName": "ControlLoop-Duplicates-48f0c2c3-a172-4192-9ae3-052274181b6e",
"closedLoopAlarmStart": 1463679805324,
"closedLoopEventClient": "DCAE_INSTANCE_ID.dcae-tca",
"closedLoopEventStatus": "ONSET",
@@ -13,4 +13,4 @@
},
"from": "DCAE",
"version": "1.0.2"
-} \ No newline at end of file
+}
diff --git a/controlloop/common/controller-frankfurt/src/test/resources/vfw/tosca-compliant-vfw.json b/controlloop/common/rules-test/src/main/resources/duplicates/tosca-compliant-duplicates.json
index 47cb09d45..d67472743 100644
--- a/controlloop/common/controller-frankfurt/src/test/resources/vfw/tosca-compliant-vfw.json
+++ b/controlloop/common/rules-test/src/main/resources/duplicates/tosca-compliant-duplicates.json
@@ -1,32 +1,30 @@
{
"type": "onap.policies.controlloop.operational.common.Drools",
"type_version": "1.0.0",
- "name": "operational.modifyconfig",
"version": "1.0.0",
+ "name": "operational.restart",
"metadata": {
- "policy-id": "operational.modifyconfig"
+ "policy-id": "operational.restart"
},
"properties": {
- "id": "ControlLoop-vFirewall-d0a1dfc6-94f5-4fd4-a5b5-4630b438850a",
- "timeout": 60,
+ "controllerName": "usecases",
+ "id": "ControlLoop-Duplicates-48f0c2c3-a172-4192-9ae3-052274181b6e",
+ "timeout": 3600,
"abatement": false,
- "trigger": "unique-policy-id-1-modifyConfig",
+ "trigger": "unique-policy-id-1-restart",
"operations": [
{
- "id": "unique-policy-id-1-modifyConfig",
- "description": "Modify the packet generator",
+ "id": "unique-policy-id-1-restart",
+ "description": "Restart the VM",
"operation": {
"actor": "APPC",
- "operation": "ModifyConfig",
+ "operation": "Restart",
"target": {
- "targetType": "VNF",
- "entityIds": {
- "resourceID": "bbb3cefd-01c8-413c-9bdd-2b92f9ca3d38"
- }
+ "targetType": "VM"
}
},
- "timeout": 300,
- "retries": 0,
+ "timeout": 1200,
+ "retries": 3,
"success": "final_success",
"failure": "final_failure",
"failure_timeout": "final_failure_timeout",
@@ -34,7 +32,6 @@
"failure_exception": "final_failure_exception",
"failure_guard": "final_failure_guard"
}
- ],
- "controllerName": "frankfurt"
+ ]
}
}
diff --git a/controlloop/common/rules-test/src/main/resources/service123/service123.appc.migrate.success.json b/controlloop/common/rules-test/src/main/resources/service123/service123.appc.migrate.success.json
new file mode 100644
index 000000000..563e2c762
--- /dev/null
+++ b/controlloop/common/rules-test/src/main/resources/service123/service123.appc.migrate.success.json
@@ -0,0 +1,22 @@
+{
+ "body": {
+ "output": {
+ "common-header": {
+ "timestamp": "2017-08-25T21:06:23.037Z",
+ "api-ver": "5.00",
+ "originator-id": "664be3d2-6c12-4f4b-a3e7-c349acced200",
+ "request-id": "664be3d2-6c12-4f4b-a3e7-c349acced200",
+ "sub-request-id": "${replaceMe}",
+ "flags": {}
+ },
+ "status": {
+ "code": 400,
+ "message": "Migrate Successful"
+ }
+ }
+ },
+ "version": "2.0",
+ "rpc-name": "migrate",
+ "correlation-id": "664be3d2-6c12-4f4b-a3e7-c349acced200-1",
+ "type": "response"
+}
diff --git a/controlloop/common/rules-test/src/main/resources/service123/service123.appc.rebuild.failure.json b/controlloop/common/rules-test/src/main/resources/service123/service123.appc.rebuild.failure.json
new file mode 100644
index 000000000..88e70ef7a
--- /dev/null
+++ b/controlloop/common/rules-test/src/main/resources/service123/service123.appc.rebuild.failure.json
@@ -0,0 +1,22 @@
+{
+ "body": {
+ "output": {
+ "common-header": {
+ "timestamp": "2017-08-25T21:06:23.037Z",
+ "api-ver": "5.00",
+ "originator-id": "664be3d2-6c12-4f4b-a3e7-c349acced200",
+ "request-id": "664be3d2-6c12-4f4b-a3e7-c349acced200",
+ "sub-request-id": "${replaceMe}",
+ "flags": {}
+ },
+ "status": {
+ "code": 401,
+ "message": "Rebuild Failed"
+ }
+ }
+ },
+ "version": "2.0",
+ "rpc-name": "rebuild",
+ "correlation-id": "664be3d2-6c12-4f4b-a3e7-c349acced200-1",
+ "type": "response"
+}
diff --git a/controlloop/common/rules-test/src/main/resources/service123/service123.appc.restart.failure.json b/controlloop/common/rules-test/src/main/resources/service123/service123.appc.restart.failure.json
new file mode 100644
index 000000000..7376c8ad3
--- /dev/null
+++ b/controlloop/common/rules-test/src/main/resources/service123/service123.appc.restart.failure.json
@@ -0,0 +1,22 @@
+{
+ "body": {
+ "output": {
+ "common-header": {
+ "timestamp": "2017-08-25T21:06:23.037Z",
+ "api-ver": "5.00",
+ "originator-id": "664be3d2-6c12-4f4b-a3e7-c349acced200",
+ "request-id": "664be3d2-6c12-4f4b-a3e7-c349acced200",
+ "sub-request-id": "${replaceMe}",
+ "flags": {}
+ },
+ "status": {
+ "code": 401,
+ "message": "Restart Failed"
+ }
+ }
+ },
+ "version": "2.0",
+ "rpc-name": "restart",
+ "correlation-id": "664be3d2-6c12-4f4b-a3e7-c349acced200-1",
+ "type": "response"
+}
diff --git a/controlloop/common/controller-usecases/src/test/resources/vfw/vfw.onset.json b/controlloop/common/rules-test/src/main/resources/service123/service123.onset.json
index 7782867a1..a78cb5337 100644
--- a/controlloop/common/controller-usecases/src/test/resources/vfw/vfw.onset.json
+++ b/controlloop/common/rules-test/src/main/resources/service123/service123.onset.json
@@ -1,9 +1,9 @@
{
- "closedLoopControlName": "ControlLoop-vFirewall-d0a1dfc6-94f5-4fd4-a5b5-4630b438850a",
+ "closedLoopControlName": "ControlLoop-Service123-cbed919f-2212-4ef7-8051-fe6308da1bda",
"closedLoopAlarmStart": 1463679805324,
- "closedLoopEventClient": "microservice.stringmatcher",
+ "closedLoopEventClient": "DCAE_INSTANCE_ID.dcae-tca",
"closedLoopEventStatus": "ONSET",
- "requestID": "c7c6a4aa-bb61-4a15-b831-ba1472dd4a65",
+ "requestID": "664be3d2-6c12-4f4b-a3e7-c349acced200",
"target_type": "VNF",
"target": "generic-vnf.vnf-name",
"AAI": {
diff --git a/controlloop/common/rules-test/src/main/resources/service123/tosca-compliant-service123.json b/controlloop/common/rules-test/src/main/resources/service123/tosca-compliant-service123.json
new file mode 100644
index 000000000..4eaa9e70a
--- /dev/null
+++ b/controlloop/common/rules-test/src/main/resources/service123/tosca-compliant-service123.json
@@ -0,0 +1,75 @@
+{
+ "type": "onap.policies.controlloop.operational.common.Drools",
+ "type_version": "1.0.0",
+ "version": "1.0.0",
+ "name": "operational.service123",
+ "metadata": {
+ "policy-id": "operational.service123"
+ },
+ "properties": {
+ "controllerName": "usecases",
+ "id": "ControlLoop-Service123-cbed919f-2212-4ef7-8051-fe6308da1bda",
+ "timeout": 60,
+ "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": "VM"
+ }
+ },
+ "timeout": 20,
+ "retries": 3,
+ "success": "final_success",
+ "failure": "unique-policy-id-2-rebuild",
+ "failure_timeout": "unique-policy-id-2-rebuild",
+ "failure_retries": "unique-policy-id-2-rebuild",
+ "failure_guard": "unique-policy-id-2-rebuild",
+ "failure_exception": "final_failure_exception"
+ },
+ {
+ "id": "unique-policy-id-2-rebuild",
+ "name": "Rebuild Policy",
+ "operation": {
+ "actor": "APPC",
+ "operation": "Rebuild",
+ "target": {
+ "targetType": "VM"
+ }
+ },
+ "timeout": 10,
+ "retries": 0,
+ "success": "final_success",
+ "failure": "unique-policy-id-3-migrate",
+ "failure_timeout": "unique-policy-id-3-migrate",
+ "failure_retries": "unique-policy-id-3-migrate",
+ "failure_guard": "unique-policy-id-3-migrate",
+ "failure_exception": "final_failure_exception"
+ },
+ {
+ "id": "unique-policy-id-3-migrate",
+ "name": "Migrate Policy",
+ "operation": {
+ "actor": "APPC",
+ "operation": "Migrate",
+ "target": {
+ "targetType": "VM"
+ }
+ },
+ "timeout": 30,
+ "retries": 0,
+ "success": "final_success",
+ "failure": "final_failure",
+ "failure_timeout": "final_failure_timeout",
+ "failure_retries": "final_failure_retries",
+ "failure_guard": "final_failure_guard",
+ "failure_exception": "final_failure_exception"
+ }
+ ]
+ }
+}
diff --git a/controlloop/common/controller-frankfurt/src/test/resources/vcpe/tosca-compliant-vcpe.json b/controlloop/common/rules-test/src/main/resources/vcpe/tosca-compliant-vcpe.json
index b876446dd..b70145b68 100644
--- a/controlloop/common/controller-frankfurt/src/test/resources/vcpe/tosca-compliant-vcpe.json
+++ b/controlloop/common/rules-test/src/main/resources/vcpe/tosca-compliant-vcpe.json
@@ -7,6 +7,7 @@
"policy-id": "operational.restart"
},
"properties": {
+ "controllerName": "usecases",
"id": "ControlLoop-vCPE-48f0c2c3-a172-4192-9ae3-052274181b6e",
"timeout": 3600,
"abatement": false,
@@ -31,7 +32,6 @@
"failure_exception": "final_failure_exception",
"failure_guard": "final_failure_guard"
}
- ],
- "controllerName": "frankfurt"
+ ]
}
-} \ No newline at end of file
+}
diff --git a/controlloop/common/controller-frankfurt/src/test/resources/vcpe/tosca-legacy-vcpe.json b/controlloop/common/rules-test/src/main/resources/vcpe/tosca-legacy-vcpe.json
index f42c07da9..cb0806e16 100644
--- a/controlloop/common/controller-frankfurt/src/test/resources/vcpe/tosca-legacy-vcpe.json
+++ b/controlloop/common/rules-test/src/main/resources/vcpe/tosca-legacy-vcpe.json
@@ -6,4 +6,4 @@
},
"name": "vcpe",
"version": "1.0.0"
-} \ No newline at end of file
+}
diff --git a/controlloop/common/controller-usecases/src/test/resources/vcpe/vcpe.appc.success.json b/controlloop/common/rules-test/src/main/resources/vcpe/vcpe.appc.success.json
index b221b6b24..331021798 100644
--- a/controlloop/common/controller-usecases/src/test/resources/vcpe/vcpe.appc.success.json
+++ b/controlloop/common/rules-test/src/main/resources/vcpe/vcpe.appc.success.json
@@ -6,7 +6,7 @@
"api-ver": "5.00",
"originator-id": "664be3d2-6c12-4f4b-a3e7-c349acced200",
"request-id": "664be3d2-6c12-4f4b-a3e7-c349acced200",
- "sub-request-id": "1",
+ "sub-request-id": "${replaceMe}",
"flags": {}
},
"status": {
diff --git a/controlloop/common/controller-frankfurt/src/test/resources/vcpe/vcpe.onset.1.json b/controlloop/common/rules-test/src/main/resources/vcpe/vcpe.onset.1.json
index d08ee47cd..d08ee47cd 100644
--- a/controlloop/common/controller-frankfurt/src/test/resources/vcpe/vcpe.onset.1.json
+++ b/controlloop/common/rules-test/src/main/resources/vcpe/vcpe.onset.1.json
diff --git a/controlloop/common/controller-usecases/src/test/resources/vcpe/vcpe.onset.2.json b/controlloop/common/rules-test/src/main/resources/vcpe/vcpe.onset.2.json
index b8c76514e..b8c76514e 100644
--- a/controlloop/common/controller-usecases/src/test/resources/vcpe/vcpe.onset.2.json
+++ b/controlloop/common/rules-test/src/main/resources/vcpe/vcpe.onset.2.json
diff --git a/controlloop/common/controller-usecases/src/test/resources/vcpe/vcpe.onset.3.json b/controlloop/common/rules-test/src/main/resources/vcpe/vcpe.onset.3.json
index 40f29b3cf..40f29b3cf 100644
--- a/controlloop/common/controller-usecases/src/test/resources/vcpe/vcpe.onset.3.json
+++ b/controlloop/common/rules-test/src/main/resources/vcpe/vcpe.onset.3.json
diff --git a/controlloop/common/controller-frankfurt/src/test/resources/vdns/tosca-compliant-vdns.json b/controlloop/common/rules-test/src/main/resources/vdns/tosca-compliant-vdns.json
index 1f4cb4125..918e92770 100644
--- a/controlloop/common/controller-frankfurt/src/test/resources/vdns/tosca-compliant-vdns.json
+++ b/controlloop/common/rules-test/src/main/resources/vdns/tosca-compliant-vdns.json
@@ -7,6 +7,7 @@
"policy-id": "operational.scale.up"
},
"properties": {
+ "controllerName": "usecases",
"id": "ControlLoop-vDNS-6f37f56d-a87d-4b85-b6a9-cc953cf779b3",
"timeout": 60,
"abatement": false,
@@ -42,7 +43,6 @@
"failure_exception": "final_failure_exception",
"failure_guard": "final_failure_guard"
}
- ],
- "controllerName": "frankfurt"
+ ]
}
}
diff --git a/controlloop/common/controller-frankfurt/src/test/resources/vdns/vdns.onset.json b/controlloop/common/rules-test/src/main/resources/vdns/vdns.onset.json
index 13f690952..13f690952 100644
--- a/controlloop/common/controller-frankfurt/src/test/resources/vdns/vdns.onset.json
+++ b/controlloop/common/rules-test/src/main/resources/vdns/vdns.onset.json
diff --git a/controlloop/common/controller-usecases/src/test/resources/vfw/tosca-compliant-vfw.json b/controlloop/common/rules-test/src/main/resources/vfw/tosca-compliant-vfw.json
index c96b49c7e..f55145658 100644
--- a/controlloop/common/controller-usecases/src/test/resources/vfw/tosca-compliant-vfw.json
+++ b/controlloop/common/rules-test/src/main/resources/vfw/tosca-compliant-vfw.json
@@ -7,6 +7,7 @@
"policy-id": "operational.modifyconfig"
},
"properties": {
+ "controllerName": "usecases",
"id": "ControlLoop-vFirewall-d0a1dfc6-94f5-4fd4-a5b5-4630b438850a",
"timeout": 60,
"abatement": false,
@@ -34,7 +35,6 @@
"failure_exception": "final_failure_exception",
"failure_guard": "final_failure_guard"
}
- ],
- "controllerName": "usecases"
+ ]
}
}
diff --git a/controlloop/common/controller-usecases/src/test/resources/vfw/tosca-vfw.json b/controlloop/common/rules-test/src/main/resources/vfw/tosca-vfw.json
index 5d1e35277..35a839698 100644
--- a/controlloop/common/controller-usecases/src/test/resources/vfw/tosca-vfw.json
+++ b/controlloop/common/rules-test/src/main/resources/vfw/tosca-vfw.json
@@ -6,4 +6,4 @@
},
"name": "vfw",
"version": "1.0.0"
-} \ No newline at end of file
+}
diff --git a/controlloop/common/controller-frankfurt/src/test/resources/vfw/vfw.appc.success.json b/controlloop/common/rules-test/src/main/resources/vfw/vfw.appc.success.json
index d7e6ec3b9..eb19c6832 100644
--- a/controlloop/common/controller-frankfurt/src/test/resources/vfw/vfw.appc.success.json
+++ b/controlloop/common/rules-test/src/main/resources/vfw/vfw.appc.success.json
@@ -14,4 +14,4 @@
"Payload": {
"generic-vnf.vnf-id": "jimmy-test-vnf2"
}
-} \ No newline at end of file
+}
diff --git a/controlloop/common/controller-frankfurt/src/test/resources/vfw/vfw.onset.json b/controlloop/common/rules-test/src/main/resources/vfw/vfw.onset.json
index 7782867a1..7782867a1 100644
--- a/controlloop/common/controller-frankfurt/src/test/resources/vfw/vfw.onset.json
+++ b/controlloop/common/rules-test/src/main/resources/vfw/vfw.onset.json
diff --git a/controlloop/common/controller-usecases/src/test/resources/vlb/tosca-compliant-vlb.json b/controlloop/common/rules-test/src/main/resources/vlb/tosca-compliant-vlb.json
index 0ddd63006..8a3b64a0a 100644
--- a/controlloop/common/controller-usecases/src/test/resources/vlb/tosca-compliant-vlb.json
+++ b/controlloop/common/rules-test/src/main/resources/vlb/tosca-compliant-vlb.json
@@ -7,6 +7,7 @@
"policy-id": "operational.scaleout"
},
"properties": {
+ "controllerName": "usecases",
"id": "ControlLoop-vDNS-6f37f56d-a87d-4b85-b6a9-cc953cf779b3",
"timeout": 1200,
"abatement": false,
@@ -42,7 +43,6 @@
"failure_exception": "final_failure_exception",
"failure_guard": "final_failure_guard"
}
- ],
- "controllerName": "usecases"
+ ]
}
}
diff --git a/controlloop/common/controller-frankfurt/src/test/resources/vlb/tosca-vlb.json b/controlloop/common/rules-test/src/main/resources/vlb/tosca-vlb.json
index 5147d9922..c4f2b8179 100644
--- a/controlloop/common/controller-frankfurt/src/test/resources/vlb/tosca-vlb.json
+++ b/controlloop/common/rules-test/src/main/resources/vlb/tosca-vlb.json
@@ -6,4 +6,4 @@
},
"name": "vlb",
"version": "1.0.0"
-} \ No newline at end of file
+}
diff --git a/controlloop/common/controller-frankfurt/src/test/resources/vlb/vlb.onset.json b/controlloop/common/rules-test/src/main/resources/vlb/vlb.onset.json
index 3360c0abb..23ad03cbb 100644
--- a/controlloop/common/controller-frankfurt/src/test/resources/vlb/vlb.onset.json
+++ b/controlloop/common/rules-test/src/main/resources/vlb/vlb.onset.json
@@ -13,4 +13,4 @@
},
"from": "DCAE",
"version": "1.0.2"
-} \ No newline at end of file
+}
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/controller-usecases/src/test/resources/vcpe/tosca-compliant-vcpe.json b/controlloop/common/rules-test/src/test/resources/tosca-policy.json
index 61fb8a648..42f54ab12 100644
--- a/controlloop/common/controller-usecases/src/test/resources/vcpe/tosca-compliant-vcpe.json
+++ b/controlloop/common/rules-test/src/test/resources/tosca-policy.json
@@ -7,6 +7,7 @@
"policy-id": "operational.restart"
},
"properties": {
+ "controllerName": "rulesTest",
"id": "ControlLoop-vCPE-48f0c2c3-a172-4192-9ae3-052274181b6e",
"timeout": 3600,
"abatement": false,
@@ -31,7 +32,6 @@
"failure_exception": "final_failure_exception",
"failure_guard": "final_failure_guard"
}
- ],
- "controllerName": "usecases"
+ ]
}
-} \ No newline at end of file
+}
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"
+ }
+ }
+ }
+ ]
+ }
+}