c582ecebe1e2aa115daad93f3c27debf37d5055a
[policy/drools-applications.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP
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
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
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=========================================================
19  */
20
21 package org.onap.policy.controlloop.common.rules.test;
22
23 import static org.junit.Assert.assertEquals;
24
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;
31 import lombok.Getter;
32
33 import org.junit.Test;
34 import org.onap.policy.appc.Request;
35 import org.onap.policy.appclcm.AppcLcmDmaapWrapper;
36 import org.onap.policy.common.utils.coder.Coder;
37 import org.onap.policy.common.utils.coder.StandardCoder;
38 import org.onap.policy.common.utils.coder.StandardCoderInstantAsMillis;
39 import org.onap.policy.controlloop.ControlLoopNotificationType;
40 import org.onap.policy.controlloop.VirtualControlLoopNotification;
41 import org.onap.policy.drools.system.PolicyController;
42 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
43
44 /**
45  * Superclass used for rule tests.
46  */
47 public abstract class BaseRuleTest {
48     private static final String APPC_RESTART_OP = "restart";
49     private static final String APPC_MODIFY_CONFIG_OP = "ModifyConfig";
50
51     /*
52      * Canonical Topic Names.
53      */
54     protected static final String DCAE_TOPIC = "DCAE_TOPIC";
55     protected static final String APPC_LCM_WRITE_TOPIC = "APPC-LCM-WRITE";
56     protected static final String POLICY_CL_MGT_TOPIC = "POLICY-CL-MGT";
57     protected static final String APPC_LCM_READ_TOPIC = "APPC-LCM-READ";
58     protected static final String APPC_CL_TOPIC = "APPC-CL";
59
60     /*
61      * Constants for each test case.
62      */
63
64     // service123 (i.e., multi-operation policy)
65     private static final String SERVICE123_TOSCA_COMPLIANT_POLICY = "service123/tosca-compliant-service123.json";
66     private static final String SERVICE123_ONSET = "service123/service123.onset.json";
67     private static final String SERVICE123_APPC_RESTART_FAILURE = "service123/service123.appc.restart.failure.json";
68     private static final String SERVICE123_APPC_REBUILD_FAILURE = "service123/service123.appc.rebuild.failure.json";
69     private static final String SERVICE123_APPC_MIGRATE_SUCCESS = "service123/service123.appc.migrate.success.json";
70
71     // duplicates (i.e., mutliple events in the engine at the same time)
72     private static final String DUPLICATES_TOSCA_COMPLIANT_POLICY = "duplicates/tosca-compliant-duplicates.json";
73     private static final String DUPLICATES_ONSET_1 = "duplicates/duplicates.onset.1.json";
74     private static final String DUPLICATES_ONSET_2 = "duplicates/duplicates.onset.2.json";
75     private static final String DUPLICATES_APPC_SUCCESS = "duplicates/duplicates.appc.success.json";
76
77     // VCPE
78     private static final String VCPE_TOSCA_LEGACY_POLICY = "vcpe/tosca-legacy-vcpe.json";
79     private static final String VCPE_TOSCA_COMPLIANT_POLICY = "vcpe/tosca-compliant-vcpe.json";
80     private static final String VCPE_ONSET_1 = "vcpe/vcpe.onset.1.json";
81     private static final String VCPE_ONSET_2 = "vcpe/vcpe.onset.2.json";
82     private static final String VCPE_ONSET_3 = "vcpe/vcpe.onset.3.json";
83     private static final String VCPE_APPC_SUCCESS = "vcpe/vcpe.appc.success.json";
84
85     // VDNS
86     private static final String VDNS_TOSCA_LEGACY_POLICY = "vdns/tosca-legacy-vdns.json";
87     private static final String VDNS_TOSCA_COMPLIANT_POLICY = "vdns/tosca-compliant-vdns.json";
88     private static final String VDNS_ONSET = "vdns/vdns.onset.json";
89
90     // VFW
91     private static final String VFW_TOSCA_LEGACY_POLICY = "vfw/tosca-vfw.json";
92     private static final String VFW_TOSCA_COMPLIANT_POLICY = "vfw/tosca-compliant-vfw.json";
93     private static final String VFW_TOSCA_COMPLIANT_TIME_OUT_POLICY = "vfw/tosca-compliant-timeout-vfw.json";
94     private static final String VFW_ONSET = "vfw/vfw.onset.json";
95     private static final String VFW_APPC_SUCCESS = "vfw/vfw.appc.success.json";
96     private static final String VFW_APPC_FAILURE = "vfw/vfw.appc.failure.json";
97
98     /*
99      * Coders used to decode requests and responses.
100      */
101     private static final Coder APPC_LEGACY_CODER = new StandardCoderInstantAsMillis();
102     private static final Coder APPC_LCM_CODER = new StandardCoder();
103
104     // these may be overridden by junit tests
105     private static Function<String, Rules> ruleMaker = Rules::new;
106     private static Supplier<HttpClients> httpClientMaker = HttpClients::new;
107     private static Supplier<Simulators> simMaker = Simulators::new;
108     private static Supplier<Topics> topicMaker = Topics::new;
109
110     protected static Rules rules;
111     protected static HttpClients httpClients;
112     protected static Simulators simulators;
113
114     // used to inject and wait for messages
115     @Getter(AccessLevel.PROTECTED)
116     private Topics topics;
117
118     // used to wait for messages on SINK topics
119     protected Listener<VirtualControlLoopNotification> policyClMgt;
120     protected Listener<Request> appcClSink;
121     protected Listener<AppcLcmDmaapWrapper> appcLcmRead;
122
123     protected PolicyController controller;
124
125     /*
126      * Tosca Policy that was loaded.
127      */
128     protected ToscaPolicy policy;
129
130
131     /**
132      * Initializes {@link #rules}, {@link #httpClients}, and {@link #simulators}.
133      *
134      * @param controllerName the rule controller name
135      */
136     public static void initStatics(String controllerName) {
137         rules = ruleMaker.apply(controllerName);
138         httpClients = httpClientMaker.get();
139         simulators = simMaker.get();
140     }
141
142     /**
143      * Destroys {@link #httpClients}, {@link #simulators}, and {@link #rules}.
144      */
145     public static void finishStatics() {
146         httpClients.destroy();
147         simulators.destroy();
148         rules.destroy();
149     }
150
151     /**
152      * Initializes {@link #topics} and {@link #controller}.
153      */
154     public void init() {
155         topics = topicMaker.get();
156         controller = rules.getController();
157     }
158
159     /**
160      * Destroys {@link #topics} and resets the rule facts.
161      */
162     public void finish() {
163         topics.destroy();
164         rules.resetFacts();
165     }
166
167     // Service123 (i.e., Policy with multiple operations)
168
169     /**
170      * Service123 with Tosca Compliant Policy.
171      */
172     @Test
173     public void testService123Compliant() {
174         policyClMgt = topics.createListener(POLICY_CL_MGT_TOPIC, VirtualControlLoopNotification.class, controller);
175         appcLcmRead = topics.createListener(APPC_LCM_READ_TOPIC, AppcLcmDmaapWrapper.class, APPC_LCM_CODER);
176
177         assertEquals(0, controller.getDrools().factCount(rules.getControllerName()));
178         policy = rules.setupPolicyFromFile(SERVICE123_TOSCA_COMPLIANT_POLICY);
179         assertEquals(2, controller.getDrools().factCount(rules.getControllerName()));
180
181         // inject an ONSET event over the DCAE topic
182         topics.inject(DCAE_TOPIC, SERVICE123_ONSET);
183
184         /* Wait to acquire a LOCK and a PDP-X PERMIT */
185         waitForLockAndPermit(policy, policyClMgt);
186
187         // restart request should be sent and fail four times (i.e., because retry=3)
188         for (int count = 0; count < 4; ++count) {
189             AppcLcmDmaapWrapper appcreq = appcLcmRead.await(req -> APPC_RESTART_OP.equals(req.getRpcName()));
190
191             topics.inject(APPC_LCM_WRITE_TOPIC, SERVICE123_APPC_RESTART_FAILURE,
192                             appcreq.getBody().getInput().getCommonHeader().getSubRequestId());
193         }
194
195         // rebuild request should be sent and fail once
196         AppcLcmDmaapWrapper appcreq = appcLcmRead.await(req -> "rebuild".equals(req.getRpcName()));
197
198         topics.inject(APPC_LCM_WRITE_TOPIC, SERVICE123_APPC_REBUILD_FAILURE,
199                         appcreq.getBody().getInput().getCommonHeader().getSubRequestId());
200
201         // migrate request should be sent and succeed
202         appcreq = appcLcmRead.await(req -> "migrate".equals(req.getRpcName()));
203
204         topics.inject(APPC_LCM_WRITE_TOPIC, SERVICE123_APPC_MIGRATE_SUCCESS,
205                         appcreq.getBody().getInput().getCommonHeader().getSubRequestId());
206
207         /* --- Operation Completed --- */
208
209         waitForOperationSuccess();
210
211         /* --- Transaction Completed --- */
212         waitForFinalSuccess(policy, policyClMgt);
213     }
214
215     // Duplicate events
216
217     /**
218      * This test case tests the scenario where 3 events occur and 2 of the requests refer
219      * to the same target entity while the 3rd is for another entity. The expected result
220      * is that the event with the duplicate target entity will have a final success result
221      * for one of the events, and a rejected message for the one that was unable to obtain
222      * the lock. The event that is referring to a different target entity should be able
223      * to obtain a lock since it is a different target. After processing of all events
224      * there should only be the policy and params objects left in memory.
225      */
226     @Test
227     public void testDuplicatesEvents() {
228         policyClMgt = topics.createListener(POLICY_CL_MGT_TOPIC, VirtualControlLoopNotification.class, controller);
229         appcLcmRead = topics.createListener(APPC_LCM_READ_TOPIC, AppcLcmDmaapWrapper.class, APPC_LCM_CODER);
230
231         assertEquals(0, controller.getDrools().factCount(rules.getControllerName()));
232         policy = rules.setupPolicyFromFile(DUPLICATES_TOSCA_COMPLIANT_POLICY);
233         assertEquals(2, controller.getDrools().factCount(rules.getControllerName()));
234
235         /*
236          * Inject ONSET events over the DCAE topic. First and last have the same target
237          * entity, but different request IDs - only one should succeed. The middle one is
238          * for a different target entity, so it should succeed.
239          */
240         topics.inject(DCAE_TOPIC, DUPLICATES_ONSET_1, UUID.randomUUID().toString());
241         topics.inject(DCAE_TOPIC, DUPLICATES_ONSET_2);
242         topics.inject(DCAE_TOPIC, DUPLICATES_ONSET_1, UUID.randomUUID().toString());
243
244         // one should immediately generate a FINAL failure
245         waitForFinal(policy, policyClMgt, ControlLoopNotificationType.FINAL_FAILURE);
246
247         // should see two restarts
248         for (int count = 0; count < 2; ++count) {
249             AppcLcmDmaapWrapper appcreq = appcLcmRead.await(req -> APPC_RESTART_OP.equals(req.getRpcName()));
250
251             // indicate success
252             topics.inject(APPC_LCM_WRITE_TOPIC, DUPLICATES_APPC_SUCCESS,
253                             appcreq.getBody().getInput().getCommonHeader().getSubRequestId());
254         }
255
256         // should see two FINAL successes
257         VirtualControlLoopNotification notif1 = waitForFinalSuccess(policy, policyClMgt);
258         VirtualControlLoopNotification notif2 = waitForFinalSuccess(policy, policyClMgt);
259
260         // get the list of target names so we can ensure there's one of each
261         List<String> actual = List.of(notif1, notif2).stream().map(notif -> notif.getAai().get("generic-vnf.vnf-id"))
262                         .sorted().collect(Collectors.toList());
263
264         assertEquals(List.of("duplicate-VNF", "vCPE_Infrastructure_vGMUX_demo_app").toString(), actual.toString());
265     }
266
267     // VCPE
268
269     /**
270      * Sunny Day with Legacy Tosca Policy.
271      */
272     @Test
273     public void testVcpeSunnyDayLegacy() {
274         appcLcmSunnyDay(VCPE_TOSCA_LEGACY_POLICY, VCPE_ONSET_1, APPC_RESTART_OP);
275     }
276
277     /**
278      * Sunny Day with Tosca Compliant Policy.
279      */
280     @Test
281     public void testVcpeSunnyDayCompliant() {
282         appcLcmSunnyDay(VCPE_TOSCA_COMPLIANT_POLICY, VCPE_ONSET_1, APPC_RESTART_OP);
283     }
284
285     /**
286      * An ONSET flood prevention test that injects a few ONSETs at once. It attempts to
287      * simulate the flooding behavior of the DCAE TCA microservice. TCA could blast tens
288      * or hundreds of ONSETs within sub-second intervals.
289      */
290     @Test
291     public void testVcpeOnsetFloodPrevention() {
292         appcLcmSunnyDay(VCPE_TOSCA_COMPLIANT_POLICY, List.of(VCPE_ONSET_1, VCPE_ONSET_2, VCPE_ONSET_3),
293                         APPC_RESTART_OP);
294     }
295
296     // VDNS
297
298     /**
299      * Sunny Day with Legacy Tosca Policy.
300      */
301     @Test
302     public void testVdnsSunnyDayLegacy() {
303         httpSunnyDay(VDNS_TOSCA_LEGACY_POLICY, VDNS_ONSET);
304     }
305
306     /**
307      * Sunny Day with Tosca Compliant Policy.
308      */
309     @Test
310     public void testVdnsSunnyDayCompliant() {
311         httpSunnyDay(VDNS_TOSCA_COMPLIANT_POLICY, VDNS_ONSET);
312     }
313
314     // VFW
315
316     /**
317      * VFW Sunny Day with Legacy Tosca Policy.
318      */
319     @Test
320     public void testVfwSunnyDayLegacy() {
321         appcLegacySunnyDay(VFW_TOSCA_LEGACY_POLICY, VFW_ONSET, APPC_MODIFY_CONFIG_OP);
322     }
323
324     /**
325      * VFW Sunny Day with Tosca Compliant Policy.
326      */
327     @Test
328     public void testVfwSunnyDayCompliant() {
329         appcLegacySunnyDay(VFW_TOSCA_COMPLIANT_POLICY, VFW_ONSET, APPC_MODIFY_CONFIG_OP);
330     }
331
332     /**
333      * VFW Rainy Day using legacy tosca policy (operation and final failure).
334      */
335     @Test
336     public void testVfwRainyDayLegacyFailure() {
337         appcLegacyRainyDay(VFW_TOSCA_LEGACY_POLICY, VFW_ONSET, APPC_MODIFY_CONFIG_OP);
338     }
339
340     /**
341      * VFW Rainy Day using compliant tosca policy (final failure).
342      */
343     @Test
344     public void testVfwRainyDayOverallTimeout() {
345         appcLegacyRainyDayNoResponse(VFW_TOSCA_COMPLIANT_TIME_OUT_POLICY, VFW_ONSET, APPC_MODIFY_CONFIG_OP);
346     }
347
348     /**
349      * VFW Rainy day using compliant tosca policy (final failure due to timeout).
350      */
351     @Test
352     public void testVfwRainyDayCompliantTimeout() {
353         appcLegacyRainyDayNoResponse(VFW_TOSCA_COMPLIANT_POLICY, VFW_ONSET, APPC_MODIFY_CONFIG_OP);
354     }
355
356     /**
357      * Sunny day scenario for use cases that use APPC-LCM.
358      *
359      * @param policyFile file containing the ToscaPolicy to be loaded
360      * @param onsetFile file containing the ONSET to be injected
361      * @param operation expected APPC operation request
362      */
363     protected void appcLcmSunnyDay(String policyFile, String onsetFile, String operation) {
364         appcLcmSunnyDay(policyFile, List.of(onsetFile), operation);
365     }
366
367     /**
368      * Sunny day scenario for use cases that use APPC-LCM.
369      *
370      * @param policyFile file containing the ToscaPolicy to be loaded
371      * @param onsetFiles list of files containing the ONSET to be injected
372      * @param operation expected APPC operation request
373      */
374     protected void appcLcmSunnyDay(String policyFile, List<String> onsetFiles, String operation) {
375         policyClMgt = topics.createListener(POLICY_CL_MGT_TOPIC, VirtualControlLoopNotification.class, controller);
376         appcLcmRead = topics.createListener(APPC_LCM_READ_TOPIC, AppcLcmDmaapWrapper.class, APPC_LCM_CODER);
377
378         assertEquals(0, controller.getDrools().factCount(rules.getControllerName()));
379         policy = rules.setupPolicyFromFile(policyFile);
380         assertEquals(2, controller.getDrools().factCount(rules.getControllerName()));
381
382         // inject several ONSET events over the DCAE topic
383         for (String onsetFile : onsetFiles) {
384             topics.inject(DCAE_TOPIC, onsetFile);
385         }
386
387         /* Wait to acquire a LOCK and a PDP-X PERMIT */
388         waitForLockAndPermit(policy, policyClMgt);
389
390         /*
391          * Ensure that an APPC RESTART request was sent in response to the matching ONSET
392          */
393         AppcLcmDmaapWrapper appcreq = appcLcmRead.await(req -> operation.equals(req.getRpcName()));
394
395         /*
396          * Inject a 400 APPC Response Return over the APPC topic, with appropriate
397          * subRequestId
398          */
399         topics.inject(APPC_LCM_WRITE_TOPIC, VCPE_APPC_SUCCESS,
400                         appcreq.getBody().getInput().getCommonHeader().getSubRequestId());
401
402         /* --- Operation Completed --- */
403
404         waitForOperationSuccess();
405
406         /* --- Transaction Completed --- */
407         waitForFinalSuccess(policy, policyClMgt);
408     }
409
410     /**
411      * Sunny day scenario for use cases that use Legacy APPC.
412      *
413      * @param policyFile file containing the ToscaPolicy to be loaded
414      * @param onsetFile file containing the ONSET to be injected
415      * @param operation expected APPC operation request
416      */
417     protected void appcLegacySunnyDay(String policyFile, String onsetFile, String operation) {
418         policyClMgt = topics.createListener(POLICY_CL_MGT_TOPIC, VirtualControlLoopNotification.class, controller);
419         appcClSink = topics.createListener(APPC_CL_TOPIC, Request.class, APPC_LEGACY_CODER);
420
421         assertEquals(0, controller.getDrools().factCount(rules.getControllerName()));
422         policy = rules.setupPolicyFromFile(policyFile);
423         assertEquals(2, controller.getDrools().factCount(rules.getControllerName()));
424
425         /* Inject an ONSET event over the DCAE topic */
426         topics.inject(DCAE_TOPIC, onsetFile);
427
428         /* Wait to acquire a LOCK and a PDP-X PERMIT */
429         waitForLockAndPermit(policy, policyClMgt);
430
431         /*
432          * Ensure that an APPC RESTART request was sent in response to the matching ONSET
433          */
434         Request appcreq = appcClSink.await(req -> operation.equals(req.getAction()));
435
436         /*
437          * Inject a 400 APPC Response Return over the APPC topic, with appropriate
438          * subRequestId
439          */
440         topics.inject(APPC_CL_TOPIC, VFW_APPC_SUCCESS, appcreq.getCommonHeader().getSubRequestId());
441
442         /* --- Operation Completed --- */
443
444         waitForOperationSuccess();
445
446         /* --- Transaction Completed --- */
447         waitForFinalSuccess(policy, policyClMgt);
448     }
449
450     /**
451      * Rainy day scenario for use cases that use Legacy APPC.
452      *
453      * @param policyFile file containing the ToscaPolicy to be loaded
454      * @param onsetFile file containing the ONSET to be injected
455      * @param operation expected APPC operation request
456      * @param checkOperation flag to determine whether or not to wait for operation timeout
457      */
458     protected void appcLegacyRainyDay(String policyFile, String onsetFile, String operation) {
459         policyClMgt = topics.createListener(POLICY_CL_MGT_TOPIC, VirtualControlLoopNotification.class, controller);
460         appcClSink = topics.createListener(APPC_CL_TOPIC, Request.class, APPC_LEGACY_CODER);
461
462         assertEquals(0, controller.getDrools().factCount(rules.getControllerName()));
463         policy = rules.setupPolicyFromFile(policyFile);
464         assertEquals(2, controller.getDrools().factCount(rules.getControllerName()));
465
466         /* Inject an ONSET event over the DCAE topic */
467         topics.inject(DCAE_TOPIC, onsetFile);
468
469         /* Wait to acquire a LOCK and a PDP-X PERMIT */
470         waitForLockAndPermit(policy, policyClMgt);
471
472         /*
473          * Ensure that an APPC RESTART request was sent in response to the matching ONSET
474          */
475         Request appcreq = appcClSink.await(req -> operation.equals(req.getAction()));
476
477         /*
478          * Inject a 401 APPC Response Return over the APPC topic, with appropriate
479          * subRequestId
480          */
481         topics.inject(APPC_CL_TOPIC, VFW_APPC_FAILURE, appcreq.getCommonHeader().getSubRequestId());
482
483         /* --- Operation Completed --- */
484         waitForOperationFailure();
485
486         /* --- Transaction Completed --- */
487         waitForFinalFailure(policy, policyClMgt);
488     }
489
490     /**
491      * Rainy day scenario for use cases that use Legacy APPC.
492      * Expected to fail due to timeout.
493      *
494      * @param policyFile file containing the ToscaPolicy to be loaded
495      * @param onsetFile file containing the ONSET to be injected
496      * @param operation expected APPC operation request
497      */
498     protected void appcLegacyRainyDayNoResponse(String policyFile, String onsetFile, String operation) {
499         policyClMgt = topics.createListener(POLICY_CL_MGT_TOPIC, VirtualControlLoopNotification.class, controller);
500         appcClSink = topics.createListener(APPC_CL_TOPIC, Request.class, APPC_LEGACY_CODER);
501
502         assertEquals(0, controller.getDrools().factCount(rules.getControllerName()));
503         policy = rules.setupPolicyFromFile(policyFile);
504         assertEquals(2, controller.getDrools().factCount(rules.getControllerName()));
505
506         /* Inject an ONSET event over the DCAE topic */
507         topics.inject(DCAE_TOPIC, onsetFile);
508
509         /* Wait to acquire a LOCK and a PDP-X PERMIT */
510         waitForLockAndPermit(policy, policyClMgt);
511
512         /*
513          * Ensure that an APPC RESTART request was sent in response to the matching ONSET
514          */
515         appcClSink.await(req -> operation.equals(req.getAction()));
516
517         /*
518          * Do not inject an APPC Response.
519          */
520
521         /* --- Transaction Completed --- */
522         waitForFinalFailure(policy, policyClMgt);
523     }
524
525     /**
526      * Sunny day scenario for use cases that use an HTTP simulator.
527      *
528      * @param policyFile file containing the ToscaPolicy to be loaded
529      * @param onsetFile file containing the ONSET to be injected
530      * @param operation expected APPC operation request
531      */
532     protected void httpSunnyDay(String policyFile, String onsetFile) {
533         policyClMgt = topics.createListener(POLICY_CL_MGT_TOPIC, VirtualControlLoopNotification.class, controller);
534
535         assertEquals(0, controller.getDrools().factCount(rules.getControllerName()));
536         policy = rules.setupPolicyFromFile(policyFile);
537         assertEquals(2, controller.getDrools().factCount(rules.getControllerName()));
538
539         /* Inject an ONSET event over the DCAE topic */
540         topics.inject(DCAE_TOPIC, onsetFile);
541
542         /* Wait to acquire a LOCK and a PDP-X PERMIT */
543         waitForLockAndPermit(policy, policyClMgt);
544
545         /* --- Operation Completed --- */
546
547         waitForOperationSuccess();
548
549         /* --- Transaction Completed --- */
550         waitForFinalSuccess(policy, policyClMgt);
551     }
552
553     /**
554      * Waits for a OPERATION SUCCESS transaction notification.
555      */
556     protected void waitForOperationSuccess() {
557         policyClMgt.await(notif -> notif.getNotification() == ControlLoopNotificationType.OPERATION_SUCCESS);
558     }
559
560     /**
561      * Waits for a FINAL SUCCESS transaction notification.
562      *
563      * @return the FINAL SUCCESS notification
564      */
565     protected VirtualControlLoopNotification waitForFinalSuccess(ToscaPolicy policy,
566                     Listener<VirtualControlLoopNotification> policyClMgt) {
567
568         return this.waitForFinal(policy, policyClMgt, ControlLoopNotificationType.FINAL_SUCCESS);
569     }
570
571     /**
572      * Waits for a OPERATION FAILURE transaction notification.
573      */
574     protected void waitForOperationFailure() {
575         policyClMgt.await(notif -> notif.getNotification() == ControlLoopNotificationType.OPERATION_FAILURE);
576     }
577
578     /**
579      * Waits for a FINAL FAILURE transaction notification.
580      *
581      * @return the FINAL FAILURE notification
582      */
583     protected VirtualControlLoopNotification waitForFinalFailure(ToscaPolicy policy,
584                     Listener<VirtualControlLoopNotification> policyClMgt) {
585
586         return this.waitForFinal(policy, policyClMgt, ControlLoopNotificationType.FINAL_FAILURE);
587     }
588
589     /**
590      * Waits for notifications for LOCK acquisition and GUARD Permit so that event
591      * processing may proceed.
592      */
593     protected abstract void waitForLockAndPermit(ToscaPolicy policy,
594                     Listener<VirtualControlLoopNotification> policyClMgt);
595
596     /**
597      * Waits for a FINAL transaction notification.
598      *
599      * @param finalType FINAL_xxx type for which to wait
600      *
601      * @return the FINAL notification
602      */
603     protected abstract VirtualControlLoopNotification waitForFinal(ToscaPolicy policy,
604                     Listener<VirtualControlLoopNotification> policyClMgt, ControlLoopNotificationType finalType);
605 }