2  * ============LICENSE_START=======================================================
 
   4  * ================================================================================
 
   5  * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
 
   6  * ================================================================================
 
   7  * Licensed under the Apache License, Version 2.0 (the "License");
 
   8  * you may not use this file except in compliance with the License.
 
   9  * You may obtain a copy of the License at
 
  11  *      http://www.apache.org/licenses/LICENSE-2.0
 
  13  * Unless required by applicable law or agreed to in writing, software
 
  14  * distributed under the License is distributed on an "AS IS" BASIS,
 
  15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
  16  * See the License for the specific language governing permissions and
 
  17  * limitations under the License.
 
  18  * ============LICENSE_END=========================================================
 
  21 package org.onap.policy.controlloop.common.rules.test;
 
  23 import static org.junit.Assert.assertEquals;
 
  25 import java.util.List;
 
  26 import java.util.UUID;
 
  27 import java.util.function.Function;
 
  28 import java.util.function.Supplier;
 
  29 import java.util.stream.Collectors;
 
  30 import lombok.AccessLevel;
 
  33 import org.junit.Ignore;
 
  34 import org.junit.Test;
 
  35 import org.onap.policy.appc.Request;
 
  36 import org.onap.policy.appclcm.AppcLcmDmaapWrapper;
 
  37 import org.onap.policy.common.utils.coder.Coder;
 
  38 import org.onap.policy.common.utils.coder.StandardCoder;
 
  39 import org.onap.policy.common.utils.coder.StandardCoderInstantAsMillis;
 
  40 import org.onap.policy.controlloop.ControlLoopNotificationType;
 
  41 import org.onap.policy.controlloop.VirtualControlLoopNotification;
 
  42 import org.onap.policy.drools.system.PolicyController;
 
  43 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
 
  46  * Superclass used for rule tests.
 
  48 public abstract class BaseRuleTest {
 
  49     private static final String APPC_RESTART_OP = "restart";
 
  50     private static final String APPC_MODIFY_CONFIG_OP = "ModifyConfig";
 
  53      * Canonical Topic Names.
 
  55     protected static final String DCAE_TOPIC = "DCAE_TOPIC";
 
  56     protected static final String APPC_LCM_WRITE_TOPIC = "APPC-LCM-WRITE";
 
  57     protected static final String POLICY_CL_MGT_TOPIC = "POLICY-CL-MGT";
 
  58     protected static final String APPC_LCM_READ_TOPIC = "APPC-LCM-READ";
 
  59     protected static final String APPC_CL_TOPIC = "APPC-CL";
 
  62      * Constants for each test case.
 
  65     // service123 (i.e., multi-operation policy)
 
  66     private static final String SERVICE123_TOSCA_COMPLIANT_POLICY = "service123/tosca-compliant-service123.json";
 
  67     private static final String SERVICE123_ONSET = "service123/service123.onset.json";
 
  68     private static final String SERVICE123_APPC_RESTART_FAILURE = "service123/service123.appc.restart.failure.json";
 
  69     private static final String SERVICE123_APPC_REBUILD_FAILURE = "service123/service123.appc.rebuild.failure.json";
 
  70     private static final String SERVICE123_APPC_MIGRATE_SUCCESS = "service123/service123.appc.migrate.success.json";
 
  72     // duplicates (i.e., mutliple events in the engine at the same time)
 
  73     private static final String DUPLICATES_TOSCA_COMPLIANT_POLICY = "duplicates/tosca-compliant-duplicates.json";
 
  74     private static final String DUPLICATES_ONSET_1 = "duplicates/duplicates.onset.1.json";
 
  75     private static final String DUPLICATES_ONSET_2 = "duplicates/duplicates.onset.2.json";
 
  76     private static final String DUPLICATES_APPC_SUCCESS = "duplicates/duplicates.appc.success.json";
 
  79     private static final String VCPE_TOSCA_LEGACY_POLICY = "vcpe/tosca-legacy-vcpe.json";
 
  80     private static final String VCPE_TOSCA_COMPLIANT_POLICY = "vcpe/tosca-compliant-vcpe.json";
 
  81     private static final String VCPE_ONSET_1 = "vcpe/vcpe.onset.1.json";
 
  82     private static final String VCPE_ONSET_2 = "vcpe/vcpe.onset.2.json";
 
  83     private static final String VCPE_ONSET_3 = "vcpe/vcpe.onset.3.json";
 
  84     private static final String VCPE_APPC_SUCCESS = "vcpe/vcpe.appc.success.json";
 
  87     private static final String VDNS_TOSCA_LEGACY_POLICY = "vdns/tosca-legacy-vdns.json";
 
  88     private static final String VDNS_TOSCA_COMPLIANT_POLICY = "vdns/tosca-compliant-vdns.json";
 
  89     private static final String VDNS_ONSET = "vdns/vdns.onset.json";
 
  92     private static final String VFW_TOSCA_LEGACY_POLICY = "vfw/tosca-vfw.json";
 
  93     private static final String VFW_TOSCA_COMPLIANT_POLICY = "vfw/tosca-compliant-vfw.json";
 
  94     private static final String VFW_TOSCA_COMPLIANT_TIME_OUT_POLICY = "vfw/tosca-compliant-timeout-vfw.json";
 
  95     private static final String VFW_ONSET = "vfw/vfw.onset.json";
 
  96     private static final String VFW_APPC_SUCCESS = "vfw/vfw.appc.success.json";
 
  97     private static final String VFW_APPC_FAILURE = "vfw/vfw.appc.failure.json";
 
 100      * Coders used to decode requests and responses.
 
 102     private static final Coder APPC_LEGACY_CODER = new StandardCoderInstantAsMillis();
 
 103     private static final Coder APPC_LCM_CODER = new StandardCoder();
 
 105     // these may be overridden by junit tests
 
 106     private static Function<String, Rules> ruleMaker = Rules::new;
 
 107     private static Supplier<HttpClients> httpClientMaker = HttpClients::new;
 
 108     private static Supplier<Simulators> simMaker = Simulators::new;
 
 109     private static Supplier<Topics> topicMaker = Topics::new;
 
 111     protected static Rules rules;
 
 112     protected static HttpClients httpClients;
 
 113     protected static Simulators simulators;
 
 115     // used to inject and wait for messages
 
 116     @Getter(AccessLevel.PROTECTED)
 
 117     private Topics topics;
 
 119     // used to wait for messages on SINK topics
 
 120     protected Listener<VirtualControlLoopNotification> policyClMgt;
 
 121     protected Listener<Request> appcClSink;
 
 122     protected Listener<AppcLcmDmaapWrapper> appcLcmRead;
 
 124     protected PolicyController controller;
 
 127      * Tosca Policy that was loaded.
 
 129     protected ToscaPolicy policy;
 
 133      * Initializes {@link #rules}, {@link #httpClients}, and {@link #simulators}.
 
 135      * @param controllerName the rule controller name
 
 137     public static void initStatics(String controllerName) {
 
 138         rules = ruleMaker.apply(controllerName);
 
 139         httpClients = httpClientMaker.get();
 
 140         simulators = simMaker.get();
 
 144      * Destroys {@link #httpClients}, {@link #simulators}, and {@link #rules}.
 
 146     public static void finishStatics() {
 
 147         httpClients.destroy();
 
 148         simulators.destroy();
 
 153      * Initializes {@link #topics} and {@link #controller}.
 
 156         topics = topicMaker.get();
 
 157         controller = rules.getController();
 
 161      * Destroys {@link #topics} and resets the rule facts.
 
 163     public void finish() {
 
 168     // Service123 (i.e., Policy with multiple operations)
 
 171      * Service123 with Tosca Compliant Policy.
 
 174     public void testService123Compliant() {
 
 175         policyClMgt = topics.createListener(POLICY_CL_MGT_TOPIC, VirtualControlLoopNotification.class, controller);
 
 176         appcLcmRead = topics.createListener(APPC_LCM_READ_TOPIC, AppcLcmDmaapWrapper.class, APPC_LCM_CODER);
 
 178         assertEquals(0, controller.getDrools().factCount(rules.getControllerName()));
 
 179         policy = rules.setupPolicyFromFile(SERVICE123_TOSCA_COMPLIANT_POLICY);
 
 180         assertEquals(2, controller.getDrools().factCount(rules.getControllerName()));
 
 182         // inject an ONSET event over the DCAE topic
 
 183         topics.inject(DCAE_TOPIC, SERVICE123_ONSET);
 
 185         /* Wait to acquire a LOCK and a PDP-X PERMIT */
 
 186         waitForLockAndPermit(policy, policyClMgt);
 
 188         // restart request should be sent and fail four times (i.e., because retry=3)
 
 189         for (int count = 0; count < 4; ++count) {
 
 190             AppcLcmDmaapWrapper appcreq = appcLcmRead.await(req -> APPC_RESTART_OP.equals(req.getRpcName()));
 
 192             topics.inject(APPC_LCM_WRITE_TOPIC, SERVICE123_APPC_RESTART_FAILURE,
 
 193                             appcreq.getBody().getInput().getCommonHeader().getSubRequestId());
 
 196         // rebuild request should be sent and fail once
 
 197         AppcLcmDmaapWrapper appcreq = appcLcmRead.await(req -> "rebuild".equals(req.getRpcName()));
 
 199         topics.inject(APPC_LCM_WRITE_TOPIC, SERVICE123_APPC_REBUILD_FAILURE,
 
 200                         appcreq.getBody().getInput().getCommonHeader().getSubRequestId());
 
 202         // migrate request should be sent and succeed
 
 203         appcreq = appcLcmRead.await(req -> "migrate".equals(req.getRpcName()));
 
 205         topics.inject(APPC_LCM_WRITE_TOPIC, SERVICE123_APPC_MIGRATE_SUCCESS,
 
 206                         appcreq.getBody().getInput().getCommonHeader().getSubRequestId());
 
 208         /* --- Operation Completed --- */
 
 210         waitForOperationSuccess();
 
 212         /* --- Transaction Completed --- */
 
 213         waitForFinalSuccess(policy, policyClMgt);
 
 219      * This test case tests the scenario where 3 events occur and 2 of the requests refer
 
 220      * to the same target entity while the 3rd is for another entity. The expected result
 
 221      * is that the event with the duplicate target entity will have a final success result
 
 222      * for one of the events, and a rejected message for the one that was unable to obtain
 
 223      * the lock. The event that is referring to a different target entity should be able
 
 224      * to obtain a lock since it is a different target. After processing of all events
 
 225      * there should only be the policy and params objects left in memory.
 
 227     // Ignoring test due to TimeoutException (for some reason this test fails only on docker build)
 
 228     // https://jenkins.onap.org/job/policy-drools-applications-maven-docker-stage-master/294/
 
 231     public void testDuplicatesEvents() {
 
 232         policyClMgt = topics.createListener(POLICY_CL_MGT_TOPIC, VirtualControlLoopNotification.class, controller);
 
 233         appcLcmRead = topics.createListener(APPC_LCM_READ_TOPIC, AppcLcmDmaapWrapper.class, APPC_LCM_CODER);
 
 235         assertEquals(0, controller.getDrools().factCount(rules.getControllerName()));
 
 236         policy = rules.setupPolicyFromFile(DUPLICATES_TOSCA_COMPLIANT_POLICY);
 
 237         assertEquals(2, controller.getDrools().factCount(rules.getControllerName()));
 
 240          * Inject ONSET events over the DCAE topic. First and last have the same target
 
 241          * entity, but different request IDs - only one should succeed. The middle one is
 
 242          * for a different target entity, so it should succeed.
 
 244         topics.inject(DCAE_TOPIC, DUPLICATES_ONSET_1, UUID.randomUUID().toString());
 
 245         topics.inject(DCAE_TOPIC, DUPLICATES_ONSET_2);
 
 246         topics.inject(DCAE_TOPIC, DUPLICATES_ONSET_1, UUID.randomUUID().toString());
 
 248         // one should immediately generate a FINAL failure
 
 249         waitForFinal(policy, policyClMgt, ControlLoopNotificationType.FINAL_FAILURE);
 
 251         // should see two restarts
 
 252         for (int count = 0; count < 2; ++count) {
 
 253             AppcLcmDmaapWrapper appcreq = appcLcmRead.await(req -> APPC_RESTART_OP.equals(req.getRpcName()));
 
 256             topics.inject(APPC_LCM_WRITE_TOPIC, DUPLICATES_APPC_SUCCESS,
 
 257                             appcreq.getBody().getInput().getCommonHeader().getSubRequestId());
 
 260         // should see two FINAL successes
 
 261         VirtualControlLoopNotification notif1 = waitForFinalSuccess(policy, policyClMgt);
 
 262         VirtualControlLoopNotification notif2 = waitForFinalSuccess(policy, policyClMgt);
 
 264         // get the list of target names so we can ensure there's one of each
 
 265         List<String> actual = List.of(notif1, notif2).stream().map(notif -> notif.getAai().get("generic-vnf.vnf-id"))
 
 266                         .sorted().collect(Collectors.toList());
 
 268         assertEquals(List.of("duplicate-VNF", "vCPE_Infrastructure_vGMUX_demo_app").toString(), actual.toString());
 
 274      * Sunny Day with Legacy Tosca Policy.
 
 277     public void testVcpeSunnyDayLegacy() {
 
 278         appcLcmSunnyDay(VCPE_TOSCA_LEGACY_POLICY, VCPE_ONSET_1, APPC_RESTART_OP);
 
 282      * Sunny Day with Tosca Compliant Policy.
 
 285     public void testVcpeSunnyDayCompliant() {
 
 286         appcLcmSunnyDay(VCPE_TOSCA_COMPLIANT_POLICY, VCPE_ONSET_1, APPC_RESTART_OP);
 
 290      * An ONSET flood prevention test that injects a few ONSETs at once. It attempts to
 
 291      * simulate the flooding behavior of the DCAE TCA microservice. TCA could blast tens
 
 292      * or hundreds of ONSETs within sub-second intervals.
 
 295     public void testVcpeOnsetFloodPrevention() {
 
 296         appcLcmSunnyDay(VCPE_TOSCA_COMPLIANT_POLICY, List.of(VCPE_ONSET_1, VCPE_ONSET_2, VCPE_ONSET_3),
 
 303      * Sunny Day with Legacy Tosca Policy.
 
 306     public void testVdnsSunnyDayLegacy() {
 
 307         httpSunnyDay(VDNS_TOSCA_LEGACY_POLICY, VDNS_ONSET);
 
 311      * Sunny Day with Tosca Compliant Policy.
 
 314     public void testVdnsSunnyDayCompliant() {
 
 315         httpSunnyDay(VDNS_TOSCA_COMPLIANT_POLICY, VDNS_ONSET);
 
 321      * VFW Sunny Day with Legacy Tosca Policy.
 
 324     public void testVfwSunnyDayLegacy() {
 
 325         appcLegacySunnyDay(VFW_TOSCA_LEGACY_POLICY, VFW_ONSET, APPC_MODIFY_CONFIG_OP);
 
 329      * VFW Sunny Day with Tosca Compliant Policy.
 
 332     public void testVfwSunnyDayCompliant() {
 
 333         appcLegacySunnyDay(VFW_TOSCA_COMPLIANT_POLICY, VFW_ONSET, APPC_MODIFY_CONFIG_OP);
 
 337      * VFW Rainy Day using legacy tosca policy (operation and final failure).
 
 340     public void testVfwRainyDayLegacyFailure() {
 
 341         appcLegacyRainyDay(VFW_TOSCA_LEGACY_POLICY, VFW_ONSET, APPC_MODIFY_CONFIG_OP);
 
 345      * VFW Rainy Day using compliant tosca policy (final failure).
 
 348     public void testVfwRainyDayOverallTimeout() {
 
 349         appcLegacyRainyDayNoResponse(VFW_TOSCA_COMPLIANT_TIME_OUT_POLICY, VFW_ONSET, APPC_MODIFY_CONFIG_OP);
 
 353      * VFW Rainy day using compliant tosca policy (final failure due to timeout).
 
 356     public void testVfwRainyDayCompliantTimeout() {
 
 357         appcLegacyRainyDayNoResponse(VFW_TOSCA_COMPLIANT_POLICY, VFW_ONSET, APPC_MODIFY_CONFIG_OP);
 
 361      * Sunny day scenario for use cases that use APPC-LCM.
 
 363      * @param policyFile file containing the ToscaPolicy to be loaded
 
 364      * @param onsetFile file containing the ONSET to be injected
 
 365      * @param operation expected APPC operation request
 
 367     protected void appcLcmSunnyDay(String policyFile, String onsetFile, String operation) {
 
 368         appcLcmSunnyDay(policyFile, List.of(onsetFile), operation);
 
 372      * Sunny day scenario for use cases that use APPC-LCM.
 
 374      * @param policyFile file containing the ToscaPolicy to be loaded
 
 375      * @param onsetFiles list of files containing the ONSET to be injected
 
 376      * @param operation expected APPC operation request
 
 378     protected void appcLcmSunnyDay(String policyFile, List<String> onsetFiles, String operation) {
 
 379         policyClMgt = topics.createListener(POLICY_CL_MGT_TOPIC, VirtualControlLoopNotification.class, controller);
 
 380         appcLcmRead = topics.createListener(APPC_LCM_READ_TOPIC, AppcLcmDmaapWrapper.class, APPC_LCM_CODER);
 
 382         assertEquals(0, controller.getDrools().factCount(rules.getControllerName()));
 
 383         policy = rules.setupPolicyFromFile(policyFile);
 
 384         assertEquals(2, controller.getDrools().factCount(rules.getControllerName()));
 
 386         // inject several ONSET events over the DCAE topic
 
 387         for (String onsetFile : onsetFiles) {
 
 388             topics.inject(DCAE_TOPIC, onsetFile);
 
 391         /* Wait to acquire a LOCK and a PDP-X PERMIT */
 
 392         waitForLockAndPermit(policy, policyClMgt);
 
 395          * Ensure that an APPC RESTART request was sent in response to the matching ONSET
 
 397         AppcLcmDmaapWrapper appcreq = appcLcmRead.await(req -> operation.equals(req.getRpcName()));
 
 400          * Inject a 400 APPC Response Return over the APPC topic, with appropriate
 
 403         topics.inject(APPC_LCM_WRITE_TOPIC, VCPE_APPC_SUCCESS,
 
 404                         appcreq.getBody().getInput().getCommonHeader().getSubRequestId());
 
 406         /* --- Operation Completed --- */
 
 408         waitForOperationSuccess();
 
 410         /* --- Transaction Completed --- */
 
 411         waitForFinalSuccess(policy, policyClMgt);
 
 415      * Sunny day scenario for use cases that use Legacy APPC.
 
 417      * @param policyFile file containing the ToscaPolicy to be loaded
 
 418      * @param onsetFile file containing the ONSET to be injected
 
 419      * @param operation expected APPC operation request
 
 421     protected void appcLegacySunnyDay(String policyFile, String onsetFile, String operation) {
 
 422         policyClMgt = topics.createListener(POLICY_CL_MGT_TOPIC, VirtualControlLoopNotification.class, controller);
 
 423         appcClSink = topics.createListener(APPC_CL_TOPIC, Request.class, APPC_LEGACY_CODER);
 
 425         assertEquals(0, controller.getDrools().factCount(rules.getControllerName()));
 
 426         policy = rules.setupPolicyFromFile(policyFile);
 
 427         assertEquals(2, controller.getDrools().factCount(rules.getControllerName()));
 
 429         /* Inject an ONSET event over the DCAE topic */
 
 430         topics.inject(DCAE_TOPIC, onsetFile);
 
 432         /* Wait to acquire a LOCK and a PDP-X PERMIT */
 
 433         waitForLockAndPermit(policy, policyClMgt);
 
 436          * Ensure that an APPC RESTART request was sent in response to the matching ONSET
 
 438         Request appcreq = appcClSink.await(req -> operation.equals(req.getAction()));
 
 441          * Inject a 400 APPC Response Return over the APPC topic, with appropriate
 
 444         topics.inject(APPC_CL_TOPIC, VFW_APPC_SUCCESS, appcreq.getCommonHeader().getSubRequestId());
 
 446         /* --- Operation Completed --- */
 
 448         waitForOperationSuccess();
 
 450         /* --- Transaction Completed --- */
 
 451         waitForFinalSuccess(policy, policyClMgt);
 
 455      * Rainy day scenario for use cases that use Legacy APPC.
 
 457      * @param policyFile file containing the ToscaPolicy to be loaded
 
 458      * @param onsetFile file containing the ONSET to be injected
 
 459      * @param operation expected APPC operation request
 
 460      * @param checkOperation flag to determine whether or not to wait for operation timeout
 
 462     protected void appcLegacyRainyDay(String policyFile, String onsetFile, String operation) {
 
 463         policyClMgt = topics.createListener(POLICY_CL_MGT_TOPIC, VirtualControlLoopNotification.class, controller);
 
 464         appcClSink = topics.createListener(APPC_CL_TOPIC, Request.class, APPC_LEGACY_CODER);
 
 466         assertEquals(0, controller.getDrools().factCount(rules.getControllerName()));
 
 467         policy = rules.setupPolicyFromFile(policyFile);
 
 468         assertEquals(2, controller.getDrools().factCount(rules.getControllerName()));
 
 470         /* Inject an ONSET event over the DCAE topic */
 
 471         topics.inject(DCAE_TOPIC, onsetFile);
 
 473         /* Wait to acquire a LOCK and a PDP-X PERMIT */
 
 474         waitForLockAndPermit(policy, policyClMgt);
 
 477          * Ensure that an APPC RESTART request was sent in response to the matching ONSET
 
 479         Request appcreq = appcClSink.await(req -> operation.equals(req.getAction()));
 
 482          * Inject a 401 APPC Response Return over the APPC topic, with appropriate
 
 485         topics.inject(APPC_CL_TOPIC, VFW_APPC_FAILURE, appcreq.getCommonHeader().getSubRequestId());
 
 487         /* --- Operation Completed --- */
 
 488         waitForOperationFailure();
 
 490         /* --- Transaction Completed --- */
 
 491         waitForFinalFailure(policy, policyClMgt);
 
 495      * Rainy day scenario for use cases that use Legacy APPC.
 
 496      * Expected to fail due to timeout.
 
 498      * @param policyFile file containing the ToscaPolicy to be loaded
 
 499      * @param onsetFile file containing the ONSET to be injected
 
 500      * @param operation expected APPC operation request
 
 502     protected void appcLegacyRainyDayNoResponse(String policyFile, String onsetFile, String operation) {
 
 503         policyClMgt = topics.createListener(POLICY_CL_MGT_TOPIC, VirtualControlLoopNotification.class, controller);
 
 504         appcClSink = topics.createListener(APPC_CL_TOPIC, Request.class, APPC_LEGACY_CODER);
 
 506         assertEquals(0, controller.getDrools().factCount(rules.getControllerName()));
 
 507         policy = rules.setupPolicyFromFile(policyFile);
 
 508         assertEquals(2, controller.getDrools().factCount(rules.getControllerName()));
 
 510         /* Inject an ONSET event over the DCAE topic */
 
 511         topics.inject(DCAE_TOPIC, onsetFile);
 
 513         /* Wait to acquire a LOCK and a PDP-X PERMIT */
 
 514         waitForLockAndPermit(policy, policyClMgt);
 
 517          * Ensure that an APPC RESTART request was sent in response to the matching ONSET
 
 519         appcClSink.await(req -> operation.equals(req.getAction()));
 
 522          * Do not inject an APPC Response.
 
 525         /* --- Transaction Completed --- */
 
 526         waitForFinalFailure(policy, policyClMgt);
 
 530      * Sunny day scenario for use cases that use an HTTP simulator.
 
 532      * @param policyFile file containing the ToscaPolicy to be loaded
 
 533      * @param onsetFile file containing the ONSET to be injected
 
 534      * @param operation expected APPC operation request
 
 536     protected void httpSunnyDay(String policyFile, String onsetFile) {
 
 537         policyClMgt = topics.createListener(POLICY_CL_MGT_TOPIC, VirtualControlLoopNotification.class, controller);
 
 539         assertEquals(0, controller.getDrools().factCount(rules.getControllerName()));
 
 540         policy = rules.setupPolicyFromFile(policyFile);
 
 541         assertEquals(2, controller.getDrools().factCount(rules.getControllerName()));
 
 543         /* Inject an ONSET event over the DCAE topic */
 
 544         topics.inject(DCAE_TOPIC, onsetFile);
 
 546         /* Wait to acquire a LOCK and a PDP-X PERMIT */
 
 547         waitForLockAndPermit(policy, policyClMgt);
 
 549         /* --- Operation Completed --- */
 
 551         waitForOperationSuccess();
 
 553         /* --- Transaction Completed --- */
 
 554         waitForFinalSuccess(policy, policyClMgt);
 
 558      * Waits for a OPERATION SUCCESS transaction notification.
 
 560     protected void waitForOperationSuccess() {
 
 561         policyClMgt.await(notif -> notif.getNotification() == ControlLoopNotificationType.OPERATION_SUCCESS);
 
 565      * Waits for a FINAL SUCCESS transaction notification.
 
 567      * @return the FINAL SUCCESS notification
 
 569     protected VirtualControlLoopNotification waitForFinalSuccess(ToscaPolicy policy,
 
 570                     Listener<VirtualControlLoopNotification> policyClMgt) {
 
 572         return this.waitForFinal(policy, policyClMgt, ControlLoopNotificationType.FINAL_SUCCESS);
 
 576      * Waits for a OPERATION FAILURE transaction notification.
 
 578     protected void waitForOperationFailure() {
 
 579         policyClMgt.await(notif -> notif.getNotification() == ControlLoopNotificationType.OPERATION_FAILURE);
 
 583      * Waits for a FINAL FAILURE transaction notification.
 
 585      * @return the FINAL FAILURE notification
 
 587     protected VirtualControlLoopNotification waitForFinalFailure(ToscaPolicy policy,
 
 588                     Listener<VirtualControlLoopNotification> policyClMgt) {
 
 590         return this.waitForFinal(policy, policyClMgt, ControlLoopNotificationType.FINAL_FAILURE);
 
 594      * Waits for notifications for LOCK acquisition and GUARD Permit so that event
 
 595      * processing may proceed.
 
 597     protected abstract void waitForLockAndPermit(ToscaPolicy policy,
 
 598                     Listener<VirtualControlLoopNotification> policyClMgt);
 
 601      * Waits for a FINAL transaction notification.
 
 603      * @param finalType FINAL_xxx type for which to wait
 
 605      * @return the FINAL notification
 
 607     protected abstract VirtualControlLoopNotification waitForFinal(ToscaPolicy policy,
 
 608                     Listener<VirtualControlLoopNotification> policyClMgt, ControlLoopNotificationType finalType);