From 8d0516fd693ae0224100b74a81d09e62cea8ba62 Mon Sep 17 00:00:00 2001 From: Taka Cho Date: Mon, 3 Aug 2020 19:49:45 -0400 Subject: Refactor BaseRuleTest for Drools apps 1, rename BaseRuleTest to BaseTest. 2, remove drools related code in BaseTest that would use for tdjam controller. 3, DroolsRuleTest extends BaseTest that would use for frankfurt controller for drools base. Issue-ID: POLICY-2750 Change-Id: Ica9637a850de6e929f09532f077ae3e997aa2045 Signed-off-by: Taka Cho --- .../common/rules/test/BaseRuleTest.java | 743 --------------------- .../controlloop/common/rules/test/BaseTest.java | 741 ++++++++++++++++++++ .../common/rules/test/DroolsRuleTest.java | 97 +++ .../controlloop/common/rules/test/Rules.java | 5 +- .../common/rules/test/BaseRuleTestTest.java | 607 ----------------- .../common/rules/test/BaseTestTest.java | 575 ++++++++++++++++ .../common/rules/test/DroolsRuleTestTest.java | 294 ++++++++ 7 files changed, 1711 insertions(+), 1351 deletions(-) delete mode 100644 controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/BaseRuleTest.java create mode 100644 controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/BaseTest.java create mode 100644 controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/DroolsRuleTest.java delete mode 100644 controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/BaseRuleTestTest.java create mode 100644 controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/BaseTestTest.java create mode 100644 controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/DroolsRuleTestTest.java (limited to 'controlloop/common/rules-test') 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 deleted file mode 100644 index 7c34fc875..000000000 --- a/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/BaseRuleTest.java +++ /dev/null @@ -1,743 +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.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.controlloop.eventmanager.ControlLoopEventManager2; -import org.onap.policy.drools.system.PolicyController; -import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; -import org.onap.policy.sdnr.PciMessage; - -/** - * Superclass used for rule tests. - */ -public abstract class BaseRuleTest { - private static final String APPC_RESTART_OP = "restart"; - private static final String APPC_MODIFY_CONFIG_OP = "ModifyConfig"; - - /* - * 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 final String SDNR_CL_TOPIC = "SDNR-CL"; - protected static final String SDNR_CL_RSP_TOPIC = "SDNR-CL-RSP"; - - /* - * 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_LEGACY_POLICY = "vdns/tosca-legacy-vdns.json"; - private static final String VDNS_TOSCA_COMPLIANT_POLICY = "vdns/tosca-compliant-vdns.json"; - private static final String VDNS_TOSCA_COMPLIANT_RAINY_POLICY = "vdns/tosca-compliant-vdns-rainy.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_TOSCA_COMPLIANT_TIME_OUT_POLICY = "vfw/tosca-compliant-timeout-vfw.json"; - private static final String VFW_ONSET = "vfw/vfw.onset.json"; - private static final String VFW_APPC_SUCCESS = "vfw/vfw.appc.success.json"; - private static final String VFW_APPC_FAILURE = "vfw/vfw.appc.failure.json"; - - // VPCI - private static final String VPCI_TOSCA_POLICY = "vpci/tosca-vpci.json"; - private static final String VPCI_TOSCA_COMPLIANT_POLICY = "vpci/tosca-compliant-vpci.json"; - private static final String VPCI_ONSET = "vpci/vpci.onset.json"; - private static final String VPCI_SDNR_SUCCESS = "vpci/vpci.sdnr.success.json"; - - // VSONH - private static final String VSONH_TOSCA_POLICY = "vsonh/tosca-vsonh.json"; - private static final String VSONH_TOSCA_COMPLIANT_POLICY = "vsonh/tosca-compliant-vsonh.json"; - private static final String VSONH_ONSET = "vsonh/vsonh.onset.json"; - private static final String VSONH_SDNR_SUCCESS = "vsonh/vsonh.sdnr.success.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(); - - /* - * Coders used to decode requests and responses. - */ - private static final Coder SDNR_CODER = new StandardCoder(); - - // these may be overridden by junit tests - private static Function ruleMaker = Rules::new; - private static Supplier httpClientMaker = HttpClients::new; - private static Supplier simMaker = Simulators::new; - private static Supplier 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 policyClMgt; - protected Listener appcClSink; - protected Listener appcLcmRead; - protected Listener sdnrClSink; - - 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 -> APPC_RESTART_OP.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())); - - final long initCount = getCreateCount(); - - /* - * 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()); - - // should see two restarts - for (int count = 0; count < 2; ++count) { - AppcLcmDmaapWrapper appcreq = appcLcmRead.await(req -> APPC_RESTART_OP.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 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()); - - long added = getCreateCount() - initCount; - assertEquals(2, added); - } - - // VCPE - - /** - * Sunny Day with Legacy Tosca Policy. - */ - @Test - public void testVcpeSunnyDayLegacy() { - appcLcmSunnyDay(VCPE_TOSCA_LEGACY_POLICY, VCPE_ONSET_1, APPC_RESTART_OP); - } - - /** - * Sunny Day with Tosca Compliant Policy. - */ - @Test - public void testVcpeSunnyDayCompliant() { - appcLcmSunnyDay(VCPE_TOSCA_COMPLIANT_POLICY, VCPE_ONSET_1, APPC_RESTART_OP); - } - - /** - * 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), - APPC_RESTART_OP); - } - - // VDNS - - /** - * Sunny Day with Legacy Tosca Policy. - */ - @Test - public void testVdnsSunnyDayLegacy() { - httpSunnyDay(VDNS_TOSCA_LEGACY_POLICY, VDNS_ONSET); - } - - /** - * Sunny Day with Tosca Compliant Policy. - */ - @Test - public void testVdnsSunnyDayCompliant() { - httpSunnyDay(VDNS_TOSCA_COMPLIANT_POLICY, VDNS_ONSET); - } - - /** - * Vdns Rainy Day with Compliant Tosca Policy. - */ - @Test - public void testVdnsRainyDayCompliant() { - httpRainyDay(VDNS_TOSCA_COMPLIANT_RAINY_POLICY, VDNS_ONSET); - } - - - // VFW - - /** - * VFW Sunny Day with Legacy Tosca Policy. - */ - @Test - public void testVfwSunnyDayLegacy() { - appcLegacySunnyDay(VFW_TOSCA_LEGACY_POLICY, VFW_ONSET, APPC_MODIFY_CONFIG_OP); - } - - /** - * VFW Sunny Day with Tosca Compliant Policy. - */ - @Test - public void testVfwSunnyDayCompliant() { - appcLegacySunnyDay(VFW_TOSCA_COMPLIANT_POLICY, VFW_ONSET, APPC_MODIFY_CONFIG_OP); - } - - /** - * VFW Rainy Day using legacy tosca policy (operation and final failure). - */ - @Test - public void testVfwRainyDayLegacyFailure() { - appcLegacyRainyDay(VFW_TOSCA_LEGACY_POLICY, VFW_ONSET, APPC_MODIFY_CONFIG_OP); - } - - /** - * VFW Rainy Day using compliant tosca policy (final failure). - */ - @Test - public void testVfwRainyDayOverallTimeout() { - appcLegacyRainyDayNoResponse(VFW_TOSCA_COMPLIANT_TIME_OUT_POLICY, VFW_ONSET, APPC_MODIFY_CONFIG_OP); - } - - /** - * VFW Rainy day using compliant tosca policy (final failure due to timeout). - */ - @Test - public void testVfwRainyDayCompliantTimeout() { - appcLegacyRainyDayNoResponse(VFW_TOSCA_COMPLIANT_POLICY, VFW_ONSET, APPC_MODIFY_CONFIG_OP); - } - - /** - * VPCI Sunny Day with Legacy Tosca Policy. - */ - @Test - public void testVpciSunnyDayLegacy() { - sdnrSunnyDay(VPCI_TOSCA_POLICY, VPCI_ONSET, VPCI_SDNR_SUCCESS, "ModifyConfig"); - } - - /** - * VPCI Sunny Day Tosca Policy. - */ - @Test - public void testVpciSunnyDayCompliant() { - sdnrSunnyDay(VPCI_TOSCA_COMPLIANT_POLICY, VPCI_ONSET, VPCI_SDNR_SUCCESS, "ModifyConfig"); - } - - // VSONH - - /** - * VSONH Sunny Day with Legacy Tosca Policy. - */ - @Test - public void testVsonhSunnyDayLegacy() { - sdnrSunnyDay(VSONH_TOSCA_POLICY, VSONH_ONSET, VSONH_SDNR_SUCCESS, "ModifyConfigANR"); - } - - /** - * VSONH Sunny Day with Tosca Policy. - */ - @Test - public void testVsonhSunnyDayCompliant() { - sdnrSunnyDay(VSONH_TOSCA_COMPLIANT_POLICY, VSONH_ONSET, VSONH_SDNR_SUCCESS, "ModifyConfigANR"); - } - - /** - * 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 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); - } - - /** - * Rainy 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 - * @param checkOperation flag to determine whether or not to wait for operation timeout - */ - protected void appcLegacyRainyDay(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 401 APPC Response Return over the APPC topic, with appropriate - * subRequestId - */ - topics.inject(APPC_CL_TOPIC, VFW_APPC_FAILURE, appcreq.getCommonHeader().getSubRequestId()); - - /* --- Operation Completed --- */ - waitForOperationFailure(); - - /* --- Transaction Completed --- */ - waitForFinalFailure(policy, policyClMgt); - } - - /** - * Rainy day scenario for use cases that use Legacy APPC. - * Expected to fail due to timeout. - * - * @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 appcLegacyRainyDayNoResponse(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 - */ - appcClSink.await(req -> operation.equals(req.getAction())); - - /* - * Do not inject an APPC Response. - */ - - /* --- Transaction Completed --- */ - waitForFinalFailure(policy, policyClMgt); - } - - /** - * Sunny day scenario for use cases that use SDNR. - * - * @param policyFile file containing the ToscaPolicy to be loaded - * @param onsetFile file containing the ONSET to be injected - * @param operation expected SDNR operation request - */ - protected void sdnrSunnyDay(String policyFile, String onsetFile, String successFile, String operation) { - policyClMgt = topics.createListener(POLICY_CL_MGT_TOPIC, - VirtualControlLoopNotification.class, controller); - sdnrClSink = topics.createListener(SDNR_CL_TOPIC, PciMessage.class, SDNR_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 SDNR RESTART request was sent in response to the matching ONSET - */ - PciMessage pcireq = sdnrClSink.await(req -> operation.equals(req.getBody().getInput().getAction())); - - /* - * Inject response. - */ - topics.inject(SDNR_CL_RSP_TOPIC, successFile, pcireq.getBody().getInput().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); - } - - /** - * Rainy 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 httpRainyDay(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 --- */ - waitForOperationFailure(); - - /* --- Transaction Completed --- */ - waitForFinalFailure(policy, policyClMgt); - } - - protected long getCreateCount() { - return ControlLoopEventManager2.getCreateCount(); - } - - /** - * 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 policyClMgt) { - - return this.waitForFinal(policy, policyClMgt, ControlLoopNotificationType.FINAL_SUCCESS); - } - - /** - * Waits for a OPERATION FAILURE transaction notification. - */ - protected void waitForOperationFailure() { - policyClMgt.await(notif -> notif.getNotification() == ControlLoopNotificationType.OPERATION_FAILURE); - } - - /** - * Waits for a FINAL FAILURE transaction notification. - * - * @return the FINAL FAILURE notification - */ - protected VirtualControlLoopNotification waitForFinalFailure(ToscaPolicy policy, - Listener policyClMgt) { - - return this.waitForFinal(policy, policyClMgt, ControlLoopNotificationType.FINAL_FAILURE); - } - - /** - * Waits for notifications for LOCK acquisition and GUARD Permit so that event - * processing may proceed. - */ - protected abstract void waitForLockAndPermit(ToscaPolicy policy, - Listener 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 policyClMgt, ControlLoopNotificationType finalType); -} diff --git a/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/BaseTest.java b/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/BaseTest.java new file mode 100644 index 000000000..725057661 --- /dev/null +++ b/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/BaseTest.java @@ -0,0 +1,741 @@ +/*- + * ============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.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.CoderException; +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.controlloop.eventmanager.ControlLoopEventManager2; +import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; +import org.onap.policy.sdnr.PciMessage; + +/** + * Superclass used for rule tests. + */ +public abstract class BaseTest { + private static final String APPC_RESTART_OP = "restart"; + private static final String APPC_MODIFY_CONFIG_OP = "ModifyConfig"; + + /* + * 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 final String SDNR_CL_TOPIC = "SDNR-CL"; + protected static final String SDNR_CL_RSP_TOPIC = "SDNR-CL-RSP"; + + /* + * 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_LEGACY_POLICY = "vdns/tosca-legacy-vdns.json"; + private static final String VDNS_TOSCA_COMPLIANT_POLICY = "vdns/tosca-compliant-vdns.json"; + private static final String VDNS_TOSCA_COMPLIANT_RAINY_POLICY = "vdns/tosca-compliant-vdns-rainy.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_TOSCA_COMPLIANT_TIME_OUT_POLICY = "vfw/tosca-compliant-timeout-vfw.json"; + private static final String VFW_ONSET = "vfw/vfw.onset.json"; + private static final String VFW_APPC_SUCCESS = "vfw/vfw.appc.success.json"; + private static final String VFW_APPC_FAILURE = "vfw/vfw.appc.failure.json"; + + // VPCI + private static final String VPCI_TOSCA_POLICY = "vpci/tosca-vpci.json"; + private static final String VPCI_TOSCA_COMPLIANT_POLICY = "vpci/tosca-compliant-vpci.json"; + private static final String VPCI_ONSET = "vpci/vpci.onset.json"; + private static final String VPCI_SDNR_SUCCESS = "vpci/vpci.sdnr.success.json"; + + // VSONH + private static final String VSONH_TOSCA_POLICY = "vsonh/tosca-vsonh.json"; + private static final String VSONH_TOSCA_COMPLIANT_POLICY = "vsonh/tosca-compliant-vsonh.json"; + private static final String VSONH_ONSET = "vsonh/vsonh.onset.json"; + private static final String VSONH_SDNR_SUCCESS = "vsonh/vsonh.sdnr.success.json"; + + /* + * Coders used to decode requests and responses. + */ + protected static final Coder APPC_LEGACY_CODER = new StandardCoderInstantAsMillis(); + protected static final Coder APPC_LCM_CODER = new StandardCoder(); + protected static final Coder POLICY_CL_MGT_CODER = new PolicyClMgtCoder(); + + /* + * Coders used to decode requests and responses. + */ + private static final Coder SDNR_CODER = new StandardCoder(); + + // these may be overridden by junit tests + protected static Supplier httpClientMaker = HttpClients::new; + protected static Supplier simMaker = Simulators::new; + protected static Supplier 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) + protected static Topics topics; + + // used to wait for messages on SINK topics + protected Listener policyClMgt; + protected Listener appcClSink; + protected Listener appcLcmRead; + protected Listener sdnrClSink; + + /* + * Tosca Policy that was loaded. + */ + protected ToscaPolicy policy; + + /** + * Initializes {@link #rules}, {@link #httpClients}, and {@link #simulators}. + */ + public static void initStatics() { + httpClients = httpClientMaker.get(); + simulators = simMaker.get(); + } + + /** + * Destroys {@link #httpClients}, {@link #simulators}, and {@link #rules}. + */ + public static void finishStatics() { + httpClients.destroy(); + simulators.destroy(); + } + + /** + * Initializes {@link #topics} and {@link #controller}. + */ + public void init() { + topics = topicMaker.get(); + } + + /** + * Destroys {@link #topics} and resets the rule facts. + */ + public void finish() { + topics.destroy(); + } + + // Service123 (i.e., Policy with multiple operations) + + /** + * Service123 with Tosca Compliant Policy. + */ + @Test + public void testService123Compliant() { + policyClMgt = createNoficationTopicListener(); + appcLcmRead = topics.createListener(APPC_LCM_READ_TOPIC, AppcLcmDmaapWrapper.class, APPC_LCM_CODER); + policy = checkPolicy(SERVICE123_TOSCA_COMPLIANT_POLICY); + + // 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 -> APPC_RESTART_OP.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 = createNoficationTopicListener(); + appcLcmRead = topics.createListener(APPC_LCM_READ_TOPIC, AppcLcmDmaapWrapper.class, APPC_LCM_CODER); + + policy = checkPolicy(DUPLICATES_TOSCA_COMPLIANT_POLICY); + + final long initCount = getCreateCount(); + + /* + * 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()); + + // should see two restarts + for (int count = 0; count < 2; ++count) { + AppcLcmDmaapWrapper appcreq = appcLcmRead.await(req -> APPC_RESTART_OP.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 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()); + + long added = getCreateCount() - initCount; + assertEquals(2, added); + } + + // VCPE + + /** + * Sunny Day with Legacy Tosca Policy. + */ + @Test + public void testVcpeSunnyDayLegacy() { + appcLcmSunnyDay(VCPE_TOSCA_LEGACY_POLICY, VCPE_ONSET_1, APPC_RESTART_OP); + } + + /** + * Sunny Day with Tosca Compliant Policy. + */ + @Test + public void testVcpeSunnyDayCompliant() { + appcLcmSunnyDay(VCPE_TOSCA_COMPLIANT_POLICY, VCPE_ONSET_1, APPC_RESTART_OP); + } + + /** + * 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), + APPC_RESTART_OP); + } + + // VDNS + + /** + * Sunny Day with Legacy Tosca Policy. + */ + @Test + public void testVdnsSunnyDayLegacy() { + httpSunnyDay(VDNS_TOSCA_LEGACY_POLICY, VDNS_ONSET); + } + + /** + * Sunny Day with Tosca Compliant Policy. + */ + @Test + public void testVdnsSunnyDayCompliant() { + httpSunnyDay(VDNS_TOSCA_COMPLIANT_POLICY, VDNS_ONSET); + } + + /** + * Vdns Rainy Day with Compliant Tosca Policy. + */ + @Test + public void testVdnsRainyDayCompliant() { + httpRainyDay(VDNS_TOSCA_COMPLIANT_RAINY_POLICY, VDNS_ONSET); + } + + + // VFW + + /** + * VFW Sunny Day with Legacy Tosca Policy. + */ + @Test + public void testVfwSunnyDayLegacy() { + appcLegacySunnyDay(VFW_TOSCA_LEGACY_POLICY, VFW_ONSET, APPC_MODIFY_CONFIG_OP); + } + + /** + * VFW Sunny Day with Tosca Compliant Policy. + */ + @Test + public void testVfwSunnyDayCompliant() { + appcLegacySunnyDay(VFW_TOSCA_COMPLIANT_POLICY, VFW_ONSET, APPC_MODIFY_CONFIG_OP); + } + + /** + * VFW Rainy Day using legacy tosca policy (operation and final failure). + */ + @Test + public void testVfwRainyDayLegacyFailure() { + appcLegacyRainyDay(VFW_TOSCA_LEGACY_POLICY, VFW_ONSET, APPC_MODIFY_CONFIG_OP); + } + + /** + * VFW Rainy Day using compliant tosca policy (final failure). + */ + @Test + public void testVfwRainyDayOverallTimeout() { + appcLegacyRainyDayNoResponse(VFW_TOSCA_COMPLIANT_TIME_OUT_POLICY, VFW_ONSET, APPC_MODIFY_CONFIG_OP); + } + + /** + * VFW Rainy day using compliant tosca policy (final failure due to timeout). + */ + @Test + public void testVfwRainyDayCompliantTimeout() { + appcLegacyRainyDayNoResponse(VFW_TOSCA_COMPLIANT_POLICY, VFW_ONSET, APPC_MODIFY_CONFIG_OP); + } + + /** + * VPCI Sunny Day with Legacy Tosca Policy. + */ + @Test + public void testVpciSunnyDayLegacy() { + sdnrSunnyDay(VPCI_TOSCA_POLICY, VPCI_ONSET, VPCI_SDNR_SUCCESS, "ModifyConfig"); + } + + /** + * VPCI Sunny Day Tosca Policy. + */ + @Test + public void testVpciSunnyDayCompliant() { + sdnrSunnyDay(VPCI_TOSCA_COMPLIANT_POLICY, VPCI_ONSET, VPCI_SDNR_SUCCESS, "ModifyConfig"); + } + + // VSONH + + /** + * VSONH Sunny Day with Legacy Tosca Policy. + */ + @Test + public void testVsonhSunnyDayLegacy() { + sdnrSunnyDay(VSONH_TOSCA_POLICY, VSONH_ONSET, VSONH_SDNR_SUCCESS, "ModifyConfigANR"); + } + + /** + * VSONH Sunny Day with Tosca Policy. + */ + @Test + public void testVsonhSunnyDayCompliant() { + sdnrSunnyDay(VSONH_TOSCA_COMPLIANT_POLICY, VSONH_ONSET, VSONH_SDNR_SUCCESS, "ModifyConfigANR"); + } + + /** + * 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 onsetFiles, String operation) { + policyClMgt = createNoficationTopicListener(); + appcLcmRead = topics.createListener(APPC_LCM_READ_TOPIC, AppcLcmDmaapWrapper.class, APPC_LCM_CODER); + + policy = checkPolicy(policyFile); + + + // 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 = createNoficationTopicListener(); + appcClSink = topics.createListener(APPC_CL_TOPIC, Request.class, APPC_LEGACY_CODER); + + policy = checkPolicy(policyFile); + + /* 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); + } + + /** + * Rainy 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 + * @param checkOperation flag to determine whether or not to wait for operation timeout + */ + protected void appcLegacyRainyDay(String policyFile, String onsetFile, String operation) { + policyClMgt = createNoficationTopicListener(); + appcClSink = topics.createListener(APPC_CL_TOPIC, Request.class, APPC_LEGACY_CODER); + + policy = checkPolicy(policyFile); + + /* 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 401 APPC Response Return over the APPC topic, with appropriate + * subRequestId + */ + topics.inject(APPC_CL_TOPIC, VFW_APPC_FAILURE, appcreq.getCommonHeader().getSubRequestId()); + + /* --- Operation Completed --- */ + waitForOperationFailure(); + + /* --- Transaction Completed --- */ + waitForFinalFailure(policy, policyClMgt); + } + + /** + * Rainy day scenario for use cases that use Legacy APPC. + * Expected to fail due to timeout. + * + * @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 appcLegacyRainyDayNoResponse(String policyFile, String onsetFile, String operation) { + policyClMgt = createNoficationTopicListener(); + appcClSink = topics.createListener(APPC_CL_TOPIC, Request.class, APPC_LEGACY_CODER); + + policy = checkPolicy(policyFile); + + /* 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 + */ + appcClSink.await(req -> operation.equals(req.getAction())); + + /* + * Do not inject an APPC Response. + */ + + /* --- Transaction Completed --- */ + waitForFinalFailure(policy, policyClMgt); + } + + /** + * Sunny day scenario for use cases that use SDNR. + * + * @param policyFile file containing the ToscaPolicy to be loaded + * @param onsetFile file containing the ONSET to be injected + * @param operation expected SDNR operation request + */ + protected void sdnrSunnyDay(String policyFile, String onsetFile, String successFile, String operation) { + policyClMgt = createNoficationTopicListener(); + sdnrClSink = topics.createListener(SDNR_CL_TOPIC, PciMessage.class, SDNR_CODER); + + policy = checkPolicy(policyFile); + + /* 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 SDNR RESTART request was sent in response to the matching ONSET + */ + PciMessage pcireq = sdnrClSink.await(req -> operation.equals(req.getBody().getInput().getAction())); + + /* + * Inject response. + */ + topics.inject(SDNR_CL_RSP_TOPIC, successFile, pcireq.getBody().getInput().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 = createNoficationTopicListener(); + + policy = checkPolicy(policyFile); + + /* 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); + } + + /** + * Rainy 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 httpRainyDay(String policyFile, String onsetFile) { + policyClMgt = createNoficationTopicListener(); + + policy = checkPolicy(policyFile); + + /* 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 --- */ + waitForOperationFailure(); + + /* --- Transaction Completed --- */ + waitForFinalFailure(policy, policyClMgt); + } + + protected long getCreateCount() { + return ControlLoopEventManager2.getCreateCount(); + } + + /** + * 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 policyClMgt) { + + return this.waitForFinal(policy, policyClMgt, ControlLoopNotificationType.FINAL_SUCCESS); + } + + /** + * Waits for a OPERATION FAILURE transaction notification. + */ + protected void waitForOperationFailure() { + policyClMgt.await(notif -> notif.getNotification() == ControlLoopNotificationType.OPERATION_FAILURE); + } + + /** + * Waits for a FINAL FAILURE transaction notification. + * + * @return the FINAL FAILURE notification + */ + protected VirtualControlLoopNotification waitForFinalFailure(ToscaPolicy policy, + Listener policyClMgt) { + + return this.waitForFinal(policy, policyClMgt, ControlLoopNotificationType.FINAL_FAILURE); + } + + /** + * Waits for notifications for LOCK acquisition and GUARD Permit so that event + * processing may proceed. + */ + protected abstract void waitForLockAndPermit(ToscaPolicy policy, + Listener 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 policyClMgt, ControlLoopNotificationType finalType); + + /** + * Returns ToscaPolicy from File. + * + * @param fileName a path name + * @return ToscaPolicy + */ + protected ToscaPolicy checkPolicy(String fileName) { + try { + return Rules.getPolicyFromFile(fileName); + } catch (CoderException e) { + throw new IllegalArgumentException(fileName, e); + } + } + + /** + * Creates a Coder for PolicyClMgt from StandardCoder. + * + */ + public static class PolicyClMgtCoder extends StandardCoder { + public PolicyClMgtCoder() { + super(org.onap.policy.controlloop.util.Serialization.gson, + org.onap.policy.controlloop.util.Serialization.gsonPretty); + } + } + + /** + * Returns Listener from createListner based on Coder. + * @return the Listener + */ + protected Listener createNoficationTopicListener() { + return topics.createListener(POLICY_CL_MGT_TOPIC, + VirtualControlLoopNotification.class, POLICY_CL_MGT_CODER); + } +} diff --git a/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/DroolsRuleTest.java b/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/DroolsRuleTest.java new file mode 100644 index 000000000..a57395cb6 --- /dev/null +++ b/controlloop/common/rules-test/src/main/java/org/onap/policy/controlloop/common/rules/test/DroolsRuleTest.java @@ -0,0 +1,97 @@ +/*- + * ============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.function.Function; +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 DroolsRuleTest extends BaseTest { + + // these may be overridden by junit tests + private static Function ruleMaker = Rules::new; + + protected static Rules rules; + + protected PolicyController controller; + + /** + * Initializes {@link #rules}, {@link #httpClients}, and {@link #simulators}. + * + * @param controllerName the rule controller name + */ + public static void initStatics(String controllerName) { + rules = ruleMaker.apply(controllerName); + BaseTest.initStatics(); + } + + /** + * Destroys {@link #httpClients}, {@link #simulators}, and {@link #rules}. + */ + public static void finishStatics() { + BaseTest.finishStatics(); + rules.destroy(); + } + + /** + * Initializes {@link #topics} and {@link #controller}. + */ + @Override + public void init() { + super.init(); + controller = rules.getController(); + } + + /** + * Destroys {@link #topics} and resets the rule facts. + */ + @Override + public void finish() { + super.finish(); + rules.resetFacts(); + } + + /** + * Returns ToscaPolicy from File. + * + * @param fileName a path name + * @return ToscaPolicy + */ + @Override + protected ToscaPolicy checkPolicy(String fileName) { + return rules.setupPolicyFromFile(fileName); + } + + /** + * Returns Listener from createListener based on Coder. + * @return the Listener + */ + @Override + protected Listener createNoficationTopicListener() { + return topics.createListener(POLICY_CL_MGT_TOPIC, + VirtualControlLoopNotification.class, controller); + } +} 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 index 62632e9d2..64f088070 100644 --- 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 @@ -223,7 +223,10 @@ public class Rules { } } - private ToscaPolicy getPolicyFromFile(String policyPath) throws CoderException { + /** + * Get policy from file. + */ + public static ToscaPolicy getPolicyFromFile(String policyPath) throws CoderException { String policyJson = ResourceUtils.getResourceAsString(policyPath); if (policyJson == null) { throw new CoderException(new FileNotFoundException(policyPath)); 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 deleted file mode 100644 index 9f313ca39..000000000 --- a/controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/BaseRuleTestTest.java +++ /dev/null @@ -1,607 +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.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.spy; -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.concurrent.atomic.AtomicLong; -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.onap.policy.sdnr.PciBody; -import org.onap.policy.sdnr.PciCommonHeader; -import org.onap.policy.sdnr.PciMessage; -import org.onap.policy.sdnr.PciRequest; -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 ruleMaker; - private static Supplier httpClientMaker; - private static Supplier simMaker; - private static Supplier topicMaker; - - private BaseRuleTest base; - private LinkedList clMgtQueue; - private Queue appcLcmQueue; - private Queue appcLegacyQueue; - private Queue sdnrQueue; - 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 policyClMgt; - @Mock - private Listener appcClSink; - @Mock - private Listener appcLcmRead; - @Mock - private Listener sdnrClSink; - @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); - when(topics.createListener(eq(BaseRuleTest.SDNR_CL_TOPIC), eq(PciMessage.class), - any(StandardCoder.class))).thenReturn(sdnrClSink); - - Function ruleMaker = this::makeRules; - Supplier httpClientMaker = this::makeHttpClients; - Supplier simMaker = this::makeSim; - Supplier 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<>(); - sdnrQueue = new LinkedList<>(); - - when(policyClMgt.await(any())).thenAnswer(args -> { - VirtualControlLoopNotification notif = clMgtQueue.remove(); - Predicate pred = args.getArgument(0); - assertTrue(pred.test(notif)); - return notif; - }); - - when(appcLcmRead.await(any())).thenAnswer(args -> { - AppcLcmDmaapWrapper req = appcLcmQueue.remove(); - Predicate pred = args.getArgument(0); - assertTrue(pred.test(req)); - return req; - }); - - when(appcClSink.await(any())).thenAnswer(args -> { - Request req = appcLegacyQueue.remove(); - Predicate pred = args.getArgument(0); - assertTrue(pred.test(req)); - return req; - }); - - when(sdnrClSink.await(any())).thenAnswer(args -> { - PciMessage pcireq = sdnrQueue.remove(); - Predicate pred = args.getArgument(0); - assertTrue(pred.test(pcireq)); - return pcireq; - }); - - 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() { - // the test expects the count to be incremented by 2 between calls - AtomicLong count = new AtomicLong(5); - base = spy(base); - when(base.getCreateCount()).thenAnswer(args -> count.getAndAdd(2)); - - enqueueAppcLcm("restart", "restart"); - enqueueClMgt(ControlLoopNotificationType.FINAL_SUCCESS); - enqueueClMgt(ControlLoopNotificationType.FINAL_SUCCESS); - - clMgtQueue.get(0).setAai(Map.of("generic-vnf.vnf-id", "duplicate-VNF")); - clMgtQueue.get(1).setAai(Map.of("generic-vnf.vnf-id", "vCPE_Infrastructure_vGMUX_demo_app")); - - base.testDuplicatesEvents(); - - assertEquals(0, permitCount); - assertEquals(2, 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 testTestVdnsSunnyDayLegacy() { - checkHttpPolicy(base::testVdnsSunnyDayLegacy); - } - - @Test - public void testTestVdnsSunnyDayCompliant() { - checkHttpPolicy(base::testVdnsSunnyDayCompliant); - } - - @Test - public void testTestVdnsRainyDayCompliant() { - checkHttpPolicyCompliantFailure(base::testVdnsRainyDayCompliant); - } - - @Test - public void testTestVfwSunnyDayLegacy() { - checkAppcLegacyPolicy("ModifyConfig", base::testVfwSunnyDayLegacy); - } - - @Test - public void testTestVfwSunnyDayCompliant() { - checkAppcLegacyPolicy("ModifyConfig", base::testVfwSunnyDayCompliant); - } - - @Test - public void testTestVfwRainyDayLegacyFailure() { - checkAppcLegacyPolicyOperationFailure("ModifyConfig", base::testVfwRainyDayLegacyFailure); - } - - @Test - public void testTestVfwRainyDayOverallTimeout() { - checkAppcLegacyPolicyFinalFailure("ModifyConfig", base::testVfwRainyDayOverallTimeout); - } - - @Test - public void testTestVfwRainyDayCompliantTimeout() { - checkAppcLegacyPolicyFinalFailure("ModifyConfig", base::testVfwRainyDayCompliantTimeout); - } - - @Test - public void testTestVpciSunnyDayLegacy() { - checkSdnrPolicy("ModifyConfig", base::testVpciSunnyDayLegacy); - } - - @Test - public void testTestVpciSunnyDayCompliant() { - checkSdnrPolicy("ModifyConfig", base::testVpciSunnyDayCompliant); - } - - @Test - public void testTestVsonhSunnyDayLegacy() { - checkSdnrPolicy("ModifyConfigANR", base::testVsonhSunnyDayLegacy); - } - - @Test - public void testTestVsonhSunnyDayCompliant() { - checkSdnrPolicy("ModifyConfigANR", base::testVsonhSunnyDayCompliant); - } - - 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 checkAppcLegacyPolicyOperationFailure(String operation, Runnable test) { - enqueueAppcLegacy(operation); - enqueueClMgt(ControlLoopNotificationType.OPERATION_FAILURE); - enqueueClMgt(ControlLoopNotificationType.FINAL_FAILURE); - - 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 checkAppcLegacyPolicyFinalFailure(String operation, Runnable test) { - enqueueAppcLegacy(operation); - enqueueClMgt(ControlLoopNotificationType.FINAL_FAILURE); - - test.run(); - - assertEquals(1, permitCount); - assertEquals(1, finalCount); - - assertTrue(appcLcmQueue.isEmpty()); - assertTrue(clMgtQueue.isEmpty()); - - // initial event - verify(topics).inject(eq(BaseRuleTest.DCAE_TOPIC), any()); - - // There were no requests sent - } - - protected void checkSdnrPolicy(String operation, Runnable test) { - enqueueSdnr(operation); - enqueueClMgt(ControlLoopNotificationType.OPERATION_SUCCESS); - enqueueClMgt(ControlLoopNotificationType.FINAL_SUCCESS); - - test.run(); - - assertEquals(1, permitCount); - assertEquals(1, finalCount); - - assertTrue(sdnrQueue.isEmpty()); - assertTrue(clMgtQueue.isEmpty()); - - // initial event - verify(topics).inject(eq(BaseRuleTest.DCAE_TOPIC), any()); - - // reply to each SDNR request - verify(topics).inject(eq(BaseRuleTest.SDNR_CL_RSP_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()); - } - - protected void checkHttpPolicyCompliantFailure(Runnable test) { - enqueueClMgt(ControlLoopNotificationType.OPERATION_FAILURE); - enqueueClMgt(ControlLoopNotificationType.FINAL_FAILURE); - - 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 void enqueueSdnr(String... operationNames) { - for (String oper : operationNames) { - PciMessage pcimessage = new PciMessage(); - PciRequest req = new PciRequest(); - PciBody body = new PciBody(); - body.setInput(req); - pcimessage.setBody(body); - pcimessage.getBody().getInput().setAction(oper); - PciCommonHeader header = new PciCommonHeader(); - pcimessage.getBody().getInput().setCommonHeader(header); - - header.setSubRequestId("my-subrequest-id"); - - sdnrQueue.add(pcimessage); - } - } - - 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 policyClMgt) { - permitCount++; - } - - @Override - protected VirtualControlLoopNotification waitForFinal(ToscaPolicy policy, - Listener 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/BaseTestTest.java b/controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/BaseTestTest.java new file mode 100644 index 000000000..ecff7e0bb --- /dev/null +++ b/controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/BaseTestTest.java @@ -0,0 +1,575 @@ +/*- + * ============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.spy; +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.concurrent.atomic.AtomicLong; +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.models.tosca.authorative.concepts.ToscaPolicy; +import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifier; +import org.onap.policy.sdnr.PciBody; +import org.onap.policy.sdnr.PciCommonHeader; +import org.onap.policy.sdnr.PciMessage; +import org.onap.policy.sdnr.PciRequest; +import org.powermock.reflect.Whitebox; + +public class BaseTestTest { + private static final String POLICY_NAME = "my-policy-name"; + + // saved values + private static Supplier httpClientMaker; + private static Supplier simMaker; + private static Supplier topicMaker; + + private BaseTest base; + private LinkedList clMgtQueue; + private Queue appcLcmQueue; + private Queue appcLegacyQueue; + private Queue sdnrQueue; + private int permitCount; + private int finalCount; + + @Mock + private HttpClients httpClients; + @Mock + private Simulators simulators; + @Mock + private Topics topics; + @Mock + private Listener policyClMgt; + @Mock + private Listener appcClSink; + @Mock + private Listener appcLcmRead; + @Mock + private Listener sdnrClSink; + @Mock + private DroolsController drools; + @Mock + private ToscaPolicy policy; + @Mock + private ToscaPolicyIdentifier policyIdent; + + + /** + * Saves static values from the class. + */ + @BeforeClass + public static void setUpBeforeClass() { + httpClientMaker = Whitebox.getInternalState(BaseTest.class, "httpClientMaker"); + simMaker = Whitebox.getInternalState(BaseTest.class, "simMaker"); + topicMaker = Whitebox.getInternalState(BaseTest.class, "topicMaker"); + } + + /** + * Restores static values. + */ + @AfterClass + public static void tearDownAfterClass() { + Whitebox.setInternalState(BaseTest.class, "httpClientMaker", httpClientMaker); + Whitebox.setInternalState(BaseTest.class, "simMaker", simMaker); + Whitebox.setInternalState(BaseTest.class, "topicMaker", topicMaker); + } + + /** + * Sets up. + */ + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + when(policy.getIdentifier()).thenReturn(policyIdent); + when(policyIdent.getName()).thenReturn(POLICY_NAME); + + when(topics.createListener(eq(BaseTest.POLICY_CL_MGT_TOPIC), eq(VirtualControlLoopNotification.class), + any(StandardCoder.class))).thenReturn(policyClMgt); + when(topics.createListener(eq(BaseTest.APPC_LCM_READ_TOPIC), eq(AppcLcmDmaapWrapper.class), + any(StandardCoder.class))).thenReturn(appcLcmRead); + when(topics.createListener(eq(BaseTest.APPC_CL_TOPIC), eq(Request.class), + any(StandardCoderInstantAsMillis.class))).thenReturn(appcClSink); + when(topics.createListener(eq(BaseTest.SDNR_CL_TOPIC), eq(PciMessage.class), + any(StandardCoder.class))).thenReturn(sdnrClSink); + + Supplier httpClientMaker = this::makeHttpClients; + Supplier simMaker = this::makeSim; + Supplier topicMaker = this::makeTopics; + + Whitebox.setInternalState(BaseTest.class, "httpClientMaker", httpClientMaker); + Whitebox.setInternalState(BaseTest.class, "simMaker", simMaker); + Whitebox.setInternalState(BaseTest.class, "topicMaker", topicMaker); + + clMgtQueue = new LinkedList<>(); + appcLcmQueue = new LinkedList<>(); + appcLegacyQueue = new LinkedList<>(); + sdnrQueue = new LinkedList<>(); + + when(policyClMgt.await(any())).thenAnswer(args -> { + VirtualControlLoopNotification notif = clMgtQueue.remove(); + Predicate pred = args.getArgument(0); + assertTrue(pred.test(notif)); + return notif; + }); + + when(appcLcmRead.await(any())).thenAnswer(args -> { + AppcLcmDmaapWrapper req = appcLcmQueue.remove(); + Predicate pred = args.getArgument(0); + assertTrue(pred.test(req)); + return req; + }); + + when(appcClSink.await(any())).thenAnswer(args -> { + Request req = appcLegacyQueue.remove(); + Predicate pred = args.getArgument(0); + assertTrue(pred.test(req)); + return req; + }); + + when(sdnrClSink.await(any())).thenAnswer(args -> { + PciMessage pcireq = sdnrQueue.remove(); + Predicate pred = args.getArgument(0); + assertTrue(pred.test(pcireq)); + return pcireq; + }); + + permitCount = 0; + finalCount = 0; + + base = new MyTest(); + + BaseTest.initStatics(); + base.init(); + } + + @Test + public void testInitStatics() { + assertSame(httpClients, BaseTest.httpClients); + assertSame(simulators, BaseTest.simulators); + } + + @Test + public void testFinishStatics() { + BaseTest.finishStatics(); + verify(httpClients).destroy(); + verify(simulators).destroy(); + } + + @Test + public void testInit() { + assertSame(topics, base.getTopics()); + } + + @Test + public void testFinish() { + base.finish(); + verify(topics).destroy(); + } + + @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(BaseTest.DCAE_TOPIC), any()); + + // replies to each APPC request + verify(topics, times(6)).inject(eq(BaseTest.APPC_LCM_WRITE_TOPIC), any(), any()); + } + + @Test + public void testTestDuplicatesEvents() { + // the test expects the count to be incremented by 2 between calls + AtomicLong count = new AtomicLong(5); + base = spy(base); + when(base.getCreateCount()).thenAnswer(args -> count.getAndAdd(2)); + + enqueueAppcLcm("restart", "restart"); + enqueueClMgt(ControlLoopNotificationType.FINAL_SUCCESS); + enqueueClMgt(ControlLoopNotificationType.FINAL_SUCCESS); + + clMgtQueue.get(0).setAai(Map.of("generic-vnf.vnf-id", "duplicate-VNF")); + clMgtQueue.get(1).setAai(Map.of("generic-vnf.vnf-id", "vCPE_Infrastructure_vGMUX_demo_app")); + + base.testDuplicatesEvents(); + + assertEquals(0, permitCount); + assertEquals(2, finalCount); + + assertTrue(appcLcmQueue.isEmpty()); + assertTrue(clMgtQueue.isEmpty()); + + // initial events + verify(topics).inject(eq(BaseTest.DCAE_TOPIC), any()); + verify(topics, times(2)).inject(eq(BaseTest.DCAE_TOPIC), any(), any()); + + // two restarts + verify(topics, times(2)).inject(eq(BaseTest.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(BaseTest.DCAE_TOPIC), any()); + + // one restart + verify(topics).inject(eq(BaseTest.APPC_LCM_WRITE_TOPIC), any(), any()); + } + + @Test + public void testTestVdnsSunnyDayLegacy() { + checkHttpPolicy(base::testVdnsSunnyDayLegacy); + } + + @Test + public void testTestVdnsSunnyDayCompliant() { + checkHttpPolicy(base::testVdnsSunnyDayCompliant); + } + + @Test + public void testTestVdnsRainyDayCompliant() { + checkHttpPolicyCompliantFailure(base::testVdnsRainyDayCompliant); + } + + @Test + public void testTestVfwSunnyDayLegacy() { + checkAppcLegacyPolicy("ModifyConfig", base::testVfwSunnyDayLegacy); + } + + @Test + public void testTestVfwSunnyDayCompliant() { + checkAppcLegacyPolicy("ModifyConfig", base::testVfwSunnyDayCompliant); + } + + @Test + public void testTestVfwRainyDayLegacyFailure() { + checkAppcLegacyPolicyOperationFailure("ModifyConfig", base::testVfwRainyDayLegacyFailure); + } + + @Test + public void testTestVfwRainyDayOverallTimeout() { + checkAppcLegacyPolicyFinalFailure("ModifyConfig", base::testVfwRainyDayOverallTimeout); + } + + @Test + public void testTestVfwRainyDayCompliantTimeout() { + checkAppcLegacyPolicyFinalFailure("ModifyConfig", base::testVfwRainyDayCompliantTimeout); + } + + @Test + public void testTestVpciSunnyDayLegacy() { + checkSdnrPolicy("ModifyConfig", base::testVpciSunnyDayLegacy); + } + + @Test + public void testTestVpciSunnyDayCompliant() { + checkSdnrPolicy("ModifyConfig", base::testVpciSunnyDayCompliant); + } + + @Test + public void testTestVsonhSunnyDayLegacy() { + checkSdnrPolicy("ModifyConfigANR", base::testVsonhSunnyDayLegacy); + } + + @Test + public void testTestVsonhSunnyDayCompliant() { + checkSdnrPolicy("ModifyConfigANR", base::testVsonhSunnyDayCompliant); + } + + 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(BaseTest.DCAE_TOPIC), any()); + + // reply to each APPC request + verify(topics).inject(eq(BaseTest.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(BaseTest.DCAE_TOPIC), any()); + + // reply to each APPC request + verify(topics).inject(eq(BaseTest.APPC_CL_TOPIC), any(), any()); + } + + protected void checkAppcLegacyPolicyOperationFailure(String operation, Runnable test) { + enqueueAppcLegacy(operation); + enqueueClMgt(ControlLoopNotificationType.OPERATION_FAILURE); + enqueueClMgt(ControlLoopNotificationType.FINAL_FAILURE); + + test.run(); + + assertEquals(1, permitCount); + assertEquals(1, finalCount); + + assertTrue(appcLcmQueue.isEmpty()); + assertTrue(clMgtQueue.isEmpty()); + + // initial event + verify(topics).inject(eq(BaseTest.DCAE_TOPIC), any()); + + // reply to each APPC request + verify(topics).inject(eq(BaseTest.APPC_CL_TOPIC), any(), any()); + } + + protected void checkAppcLegacyPolicyFinalFailure(String operation, Runnable test) { + enqueueAppcLegacy(operation); + enqueueClMgt(ControlLoopNotificationType.FINAL_FAILURE); + + test.run(); + + assertEquals(1, permitCount); + assertEquals(1, finalCount); + + assertTrue(appcLcmQueue.isEmpty()); + assertTrue(clMgtQueue.isEmpty()); + + // initial event + verify(topics).inject(eq(BaseTest.DCAE_TOPIC), any()); + + // There were no requests sent + } + + protected void checkSdnrPolicy(String operation, Runnable test) { + enqueueSdnr(operation); + enqueueClMgt(ControlLoopNotificationType.OPERATION_SUCCESS); + enqueueClMgt(ControlLoopNotificationType.FINAL_SUCCESS); + + test.run(); + + assertEquals(1, permitCount); + assertEquals(1, finalCount); + + assertTrue(sdnrQueue.isEmpty()); + assertTrue(clMgtQueue.isEmpty()); + + // initial event + verify(topics).inject(eq(BaseTest.DCAE_TOPIC), any()); + + // reply to each SDNR request + verify(topics).inject(eq(BaseTest.SDNR_CL_RSP_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(BaseTest.DCAE_TOPIC), any()); + } + + protected void checkHttpPolicyCompliantFailure(Runnable test) { + enqueueClMgt(ControlLoopNotificationType.OPERATION_FAILURE); + enqueueClMgt(ControlLoopNotificationType.FINAL_FAILURE); + + test.run(); + + assertEquals(1, permitCount); + assertEquals(1, finalCount); + + assertTrue(clMgtQueue.isEmpty()); + + // initial event + verify(topics).inject(eq(BaseTest.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 void enqueueSdnr(String... operationNames) { + for (String oper : operationNames) { + PciMessage pcimessage = new PciMessage(); + PciRequest req = new PciRequest(); + PciBody body = new PciBody(); + body.setInput(req); + pcimessage.setBody(body); + pcimessage.getBody().getInput().setAction(oper); + PciCommonHeader header = new PciCommonHeader(); + pcimessage.getBody().getInput().setCommonHeader(header); + + header.setSubRequestId("my-subrequest-id"); + + sdnrQueue.add(pcimessage); + } + } + + 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 BaseTest { + + @Override + protected void waitForLockAndPermit(ToscaPolicy policy, Listener policyClMgt) { + permitCount++; + } + + @Override + protected VirtualControlLoopNotification waitForFinal(ToscaPolicy policy, + Listener 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/DroolsRuleTestTest.java b/controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/DroolsRuleTestTest.java new file mode 100644 index 000000000..a21fa0a93 --- /dev/null +++ b/controlloop/common/rules-test/src/test/java/org/onap/policy/controlloop/common/rules/test/DroolsRuleTestTest.java @@ -0,0 +1,294 @@ +/*- + * ============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.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.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.onap.policy.sdnr.PciMessage; +import org.powermock.reflect.Whitebox; + +public class DroolsRuleTestTest { + + private static final String CONTROLLER_NAME = "my-controller-name"; + private static final String POLICY_NAME = "my-policy-name"; + + // saved values + private static Function ruleMaker; + private static Supplier httpClientMaker; + private static Supplier simMaker; + private static Supplier topicMaker; + + private DroolsRuleTest base; + private LinkedList clMgtQueue; + private Queue appcLcmQueue; + 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 policyClMgt; + @Mock + private Listener appcClSink; + @Mock + private Listener appcLcmRead; + @Mock + private Listener sdnrClSink; + @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(DroolsRuleTest.class, "ruleMaker"); + httpClientMaker = Whitebox.getInternalState(DroolsRuleTest.class, "httpClientMaker"); + simMaker = Whitebox.getInternalState(DroolsRuleTest.class, "simMaker"); + topicMaker = Whitebox.getInternalState(DroolsRuleTest.class, "topicMaker"); + } + + /** + * Restores static values. + */ + @AfterClass + public static void tearDownAfterClass() { + Whitebox.setInternalState(DroolsRuleTest.class, "ruleMaker", ruleMaker); + Whitebox.setInternalState(DroolsRuleTest.class, "httpClientMaker", httpClientMaker); + Whitebox.setInternalState(DroolsRuleTest.class, "simMaker", simMaker); + Whitebox.setInternalState(DroolsRuleTest.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(DroolsRuleTest.POLICY_CL_MGT_TOPIC, + VirtualControlLoopNotification.class, controller)).thenReturn(policyClMgt); + when(topics.createListener(eq(DroolsRuleTest.APPC_LCM_READ_TOPIC), eq(AppcLcmDmaapWrapper.class), + any(StandardCoder.class))).thenReturn(appcLcmRead); + when(topics.createListener(eq(DroolsRuleTest.APPC_CL_TOPIC), eq(Request.class), + any(StandardCoderInstantAsMillis.class))).thenReturn(appcClSink); + when(topics.createListener(eq(DroolsRuleTest.SDNR_CL_TOPIC), eq(PciMessage.class), + any(StandardCoder.class))).thenReturn(sdnrClSink); + + Function ruleMaker = this::makeRules; + Supplier httpClientMaker = this::makeHttpClients; + Supplier simMaker = this::makeSim; + Supplier topicMaker = this::makeTopics; + + Whitebox.setInternalState(DroolsRuleTest.class, "ruleMaker", ruleMaker); + Whitebox.setInternalState(DroolsRuleTest.class, "httpClientMaker", httpClientMaker); + Whitebox.setInternalState(DroolsRuleTest.class, "simMaker", simMaker); + Whitebox.setInternalState(DroolsRuleTest.class, "topicMaker", topicMaker); + + clMgtQueue = new LinkedList<>(); + appcLcmQueue = new LinkedList<>(); + + when(policyClMgt.await(any())).thenAnswer(args -> { + VirtualControlLoopNotification notif = clMgtQueue.remove(); + Predicate pred = args.getArgument(0); + assertTrue(pred.test(notif)); + return notif; + }); + + when(appcLcmRead.await(any())).thenAnswer(args -> { + AppcLcmDmaapWrapper req = appcLcmQueue.remove(); + Predicate pred = args.getArgument(0); + assertTrue(pred.test(req)); + return req; + }); + + permitCount = 0; + finalCount = 0; + + base = new MyDroolsTest(); + DroolsRuleTest.initStatics(CONTROLLER_NAME); + base.init(); + } + + @Test + public void testInitStatics() { + assertSame(rules, DroolsRuleTest.rules); + assertSame(httpClients, DroolsRuleTest.httpClients); + assertSame(simulators, DroolsRuleTest.simulators); + } + + @Test + public void testFinishStatics() { + DroolsRuleTest.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 testDroolsTestService123Compliant() { + enqueueAppcLcm("restart", "restart", "restart", "restart", "rebuild", "migrate"); + enqueueClMgt(ControlLoopNotificationType.OPERATION_SUCCESS); + enqueueClMgt(ControlLoopNotificationType.FINAL_SUCCESS); + System.out.println("Drools TestTest Here"); + base.testService123Compliant(); + + assertEquals(1, permitCount); + assertEquals(1, finalCount); + + assertTrue(appcLcmQueue.isEmpty()); + assertTrue(clMgtQueue.isEmpty()); + + // initial event + verify(topics).inject(eq(DroolsRuleTest.DCAE_TOPIC), any()); + + // replies to each APPC request + verify(topics, times(6)).inject(eq(DroolsRuleTest.APPC_LCM_WRITE_TOPIC), any(), 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 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 MyDroolsTest extends DroolsRuleTest { + + @Override + protected void waitForLockAndPermit(ToscaPolicy policy, Listener policyClMgt) { + permitCount++; + } + + @Override + protected VirtualControlLoopNotification waitForFinal(ToscaPolicy policy, + Listener policyClMgt, ControlLoopNotificationType finalType) { + finalCount++; + return policyClMgt.await(notif -> notif.getNotification() == finalType); + } + } +} \ No newline at end of file -- cgit 1.2.3-korg