3bfa971d00301fbf296435603334e9415d002d84
[policy/drools-applications.git] / controlloop / common / rules-test / src / main / java / org / onap / policy / controlloop / common / rules / test / BaseTest.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP
4  * ================================================================================
5  * Copyright (C) 2020-2021 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.Map;
27 import java.util.UUID;
28 import java.util.concurrent.TimeUnit;
29 import java.util.function.Supplier;
30 import java.util.stream.Collectors;
31 import lombok.AccessLevel;
32 import lombok.Getter;
33 import lombok.Setter;
34 import org.awaitility.Awaitility;
35 import org.junit.Test;
36 import org.onap.policy.appc.Request;
37 import org.onap.policy.appclcm.AppcLcmDmaapWrapper;
38 import org.onap.policy.common.utils.coder.Coder;
39 import org.onap.policy.common.utils.coder.CoderException;
40 import org.onap.policy.common.utils.coder.StandardCoder;
41 import org.onap.policy.common.utils.coder.StandardCoderInstantAsMillis;
42 import org.onap.policy.controlloop.ControlLoopNotificationType;
43 import org.onap.policy.controlloop.VirtualControlLoopNotification;
44 import org.onap.policy.controlloop.eventmanager.ControlLoopEventManager;
45 import org.onap.policy.drools.system.PolicyEngineConstants;
46 import org.onap.policy.drools.system.internal.SimpleLockManager;
47 import org.onap.policy.drools.system.internal.SimpleLockManager.SimpleLock;
48 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
49 import org.onap.policy.sdnr.PciMessage;
50 import org.powermock.reflect.Whitebox;
51
52 /**
53  * Superclass used for rule tests.
54  */
55 public abstract class BaseTest {
56     private static final String APPC_RESTART_OP = "restart";
57     private static final String APPC_MODIFY_CONFIG_OP = "ModifyConfig";
58
59     private static final String SDNR_MODIFY_CONFIG_OP = "ModifyConfig";
60     private static final String SNDR_MODIFY_CONFIG_ANR_OP = "ModifyConfigANR";
61
62     /*
63      * Canonical Topic Names.
64      */
65     protected static final String DCAE_TOPIC = "DCAE_TOPIC";
66     protected static final String APPC_LCM_WRITE_TOPIC = "APPC-LCM-WRITE";
67     protected static final String POLICY_CL_MGT_TOPIC = "POLICY-CL-MGT";
68     protected static final String APPC_LCM_READ_TOPIC = "APPC-LCM-READ";
69     protected static final String APPC_CL_TOPIC = "APPC-CL";
70     protected static final String SDNR_CL_TOPIC = "SDNR-CL";
71     protected static final String SDNR_CL_RSP_TOPIC = "SDNR-CL-RSP";
72
73     /*
74      * Constants for each test case.
75      */
76
77     // service123 (i.e., multi-operation policy)
78     private static final String SERVICE123_TOSCA_COMPLIANT_POLICY = "service123/tosca-compliant-service123.json";
79     private static final String SERVICE123_ONSET = "service123/service123.onset.json";
80     private static final String SERVICE123_APPC_RESTART_FAILURE = "service123/service123.appc.restart.failure.json";
81     private static final String SERVICE123_APPC_REBUILD_FAILURE = "service123/service123.appc.rebuild.failure.json";
82     private static final String SERVICE123_APPC_MIGRATE_SUCCESS = "service123/service123.appc.migrate.success.json";
83
84     // duplicates (i.e., mutliple events in the engine at the same time)
85     private static final String DUPLICATES_TOSCA_COMPLIANT_POLICY = "duplicates/tosca-compliant-duplicates.json";
86     private static final String DUPLICATES_ONSET_1 = "duplicates/duplicates.onset.1.json";
87     private static final String DUPLICATES_ONSET_2 = "duplicates/duplicates.onset.2.json";
88     private static final String DUPLICATES_APPC_SUCCESS = "duplicates/duplicates.appc.success.json";
89
90     // VCPE
91     private static final String VCPE_TOSCA_COMPLIANT_POLICY = "vcpe/tosca-compliant-vcpe.json";
92     private static final String VCPE_ONSET_1 = "vcpe/vcpe.onset.1.json";
93     private static final String VCPE_ONSET_2 = "vcpe/vcpe.onset.2.json";
94     private static final String VCPE_ONSET_3 = "vcpe/vcpe.onset.3.json";
95     private static final String VCPE_APPC_SUCCESS = "vcpe/vcpe.appc.success.json";
96
97     // VDNS
98     private static final String VDNS_TOSCA_COMPLIANT_POLICY = "vdns/tosca-compliant-vdns.json";
99     private static final String VDNS_TOSCA_COMPLIANT_RAINY_POLICY = "vdns/tosca-compliant-vdns-rainy.json";
100     private static final String VDNS_ONSET = "vdns/vdns.onset.json";
101
102     // VFW
103     private static final String VFW_TOSCA_COMPLIANT_POLICY = "vfw/tosca-compliant-vfw.json";
104     private static final String VFW_TOSCA_COMPLIANT_TIME_OUT_POLICY = "vfw/tosca-compliant-timeout-vfw.json";
105     private static final String VFW_ONSET = "vfw/vfw.onset.json";
106     private static final String VFW_APPC_SUCCESS = "vfw/vfw.appc.success.json";
107     private static final String VFW_APPC_FAILURE = "vfw/vfw.appc.failure.json";
108
109     // VPCI
110     private static final String VPCI_TOSCA_COMPLIANT_POLICY = "vpci/tosca-compliant-vpci.json";
111     private static final String VPCI_ONSET = "vpci/vpci.onset.json";
112     private static final String VPCI_SDNR_SUCCESS = "vpci/vpci.sdnr.success.json";
113
114     // VSONH
115     private static final String VSONH_TOSCA_COMPLIANT_POLICY = "vsonh/tosca-compliant-vsonh.json";
116     private static final String VSONH_ONSET = "vsonh/vsonh.onset.json";
117     private static final String VSONH_SDNR_SUCCESS = "vsonh/vsonh.sdnr.success.json";
118
119     /*
120      * Coders used to decode requests and responses.
121      */
122     protected static final Coder APPC_LEGACY_CODER = new StandardCoderInstantAsMillis();
123     protected static final Coder APPC_LCM_CODER = new StandardCoder();
124     protected static final Coder POLICY_CL_MGT_CODER = new PolicyClMgtCoder();
125
126     /*
127      * Coders used to decode requests and responses.
128      */
129     private static final Coder SDNR_CODER = new StandardCoder();
130
131     // these may be overridden by junit tests
132     protected static Supplier<HttpClients> httpClientMaker = HttpClients::new;
133     protected static Supplier<Simulators> simMaker = Simulators::new;
134     protected static Supplier<Topics> topicMaker = Topics::new;
135
136     protected static Rules rules;
137     protected static HttpClients httpClients;
138     protected static Simulators simulators;
139
140     // used to inject and wait for messages
141     @Getter(AccessLevel.PROTECTED)
142     @Setter(AccessLevel.PROTECTED)
143     protected static Topics topics;
144
145     // used to wait for messages on SINK topics
146     protected Listener<VirtualControlLoopNotification> policyClMgt;
147     protected Listener<Request> appcClSink;
148     protected Listener<AppcLcmDmaapWrapper> appcLcmRead;
149     protected Listener<PciMessage> sdnrClSink;
150
151     /*
152      * Tosca Policy that was loaded.
153      */
154     protected ToscaPolicy policy;
155
156     /**
157      * Initializes {@link #rules}, {@link #httpClients}, and {@link #simulators}.
158      */
159     public static void initStatics() {
160         httpClients = httpClientMaker.get();
161         simulators = simMaker.get();
162     }
163
164     /**
165      * Destroys {@link #httpClients}, {@link #simulators}, and {@link #rules}.
166      */
167     public static void finishStatics() {
168         httpClients.destroy();
169         simulators.destroy();
170     }
171
172     /**
173      * Initializes {@link #topics} and {@link #controller}.
174      */
175     public void init() {
176         setTopics(topicMaker.get());
177
178         Map<String, SimpleLock> locks = getLockMap();
179         if (locks != null) {
180             locks.clear();
181         }
182     }
183
184     /**
185      * Destroys {@link #topics} and resets the rule facts.
186      */
187     public void finish() {
188         topics.destroy();
189     }
190
191     // Service123 (i.e., Policy with multiple operations)
192
193     /**
194      * Service123 with Tosca Compliant Policy.
195      */
196     @Test
197     public void testService123Compliant() {
198         policyClMgt = createNoficationTopicListener();
199         appcLcmRead = topics.createListener(APPC_LCM_READ_TOPIC, AppcLcmDmaapWrapper.class, APPC_LCM_CODER);
200         policy = checkPolicy(SERVICE123_TOSCA_COMPLIANT_POLICY);
201
202         // inject an ONSET event over the DCAE topic
203         topics.inject(DCAE_TOPIC, SERVICE123_ONSET);
204         /* Wait to acquire a LOCK and a PDP-X PERMIT */
205
206         waitForLockAndPermit(policy, policyClMgt);
207
208         // restart request should be sent and fail four times (i.e., because retry=3)
209         for (var count = 0; count < 4; ++count) {
210             AppcLcmDmaapWrapper appcreq = appcLcmRead.await(req -> APPC_RESTART_OP.equals(req.getRpcName()));
211
212             topics.inject(APPC_LCM_WRITE_TOPIC, SERVICE123_APPC_RESTART_FAILURE,
213                             appcreq.getBody().getInput().getCommonHeader().getSubRequestId());
214         }
215         // rebuild request should be sent and fail once
216         AppcLcmDmaapWrapper appcreq = appcLcmRead.await(req -> "rebuild".equals(req.getRpcName()));
217         topics.inject(APPC_LCM_WRITE_TOPIC, SERVICE123_APPC_REBUILD_FAILURE,
218                         appcreq.getBody().getInput().getCommonHeader().getSubRequestId());
219         // migrate request should be sent and succeed
220         appcreq = appcLcmRead.await(req -> "migrate".equals(req.getRpcName()));
221         topics.inject(APPC_LCM_WRITE_TOPIC, SERVICE123_APPC_MIGRATE_SUCCESS,
222                         appcreq.getBody().getInput().getCommonHeader().getSubRequestId());
223         /* --- Operation Completed --- */
224         waitForOperationSuccess();
225         /* --- Transaction Completed --- */
226         waitForFinalSuccess(policy, policyClMgt);
227
228         verifyUnlocked();
229     }
230
231     // Duplicate events
232
233     /**
234      * This test case tests the scenario where 3 events occur and 2 of the requests refer
235      * to the same target entity while the 3rd is for another entity. The expected result
236      * is that the event with the duplicate target entity will have a final success result
237      * for one of the events, and a rejected message for the one that was unable to obtain
238      * the lock. The event that is referring to a different target entity should be able
239      * to obtain a lock since it is a different target. After processing of all events
240      * there should only be the policy and params objects left in memory.
241      */
242     @Test
243     public void testDuplicatesEvents() {
244         policyClMgt = createNoficationTopicListener();
245         appcLcmRead = topics.createListener(APPC_LCM_READ_TOPIC, AppcLcmDmaapWrapper.class, APPC_LCM_CODER);
246
247         policy = checkPolicy(DUPLICATES_TOSCA_COMPLIANT_POLICY);
248
249         final long initCount = getCreateCount();
250
251         /*
252          * Inject ONSET events over the DCAE topic. First and last have the same target
253          * entity, but different request IDs - only one should succeed. The middle one is
254          * for a different target entity, so it should succeed.
255          */
256         topics.inject(DCAE_TOPIC, DUPLICATES_ONSET_1, UUID.randomUUID().toString());
257         topics.inject(DCAE_TOPIC, DUPLICATES_ONSET_2);
258         topics.inject(DCAE_TOPIC, DUPLICATES_ONSET_1, UUID.randomUUID().toString());
259
260         // should see two restarts
261         for (var count = 0; count < 2; ++count) {
262             AppcLcmDmaapWrapper appcreq = appcLcmRead.await(req -> APPC_RESTART_OP.equals(req.getRpcName()));
263
264             // indicate success
265             topics.inject(APPC_LCM_WRITE_TOPIC, DUPLICATES_APPC_SUCCESS,
266                             appcreq.getBody().getInput().getCommonHeader().getSubRequestId());
267         }
268
269         // should see two FINAL successes
270         VirtualControlLoopNotification notif1 = waitForFinalSuccess(policy, policyClMgt);
271         VirtualControlLoopNotification notif2 = waitForFinalSuccess(policy, policyClMgt);
272
273         // get the list of target names so we can ensure there's one of each
274         List<String> actual = List.of(notif1, notif2).stream().map(notif -> notif.getAai().get("generic-vnf.vnf-id"))
275                         .sorted().collect(Collectors.toList());
276
277         assertEquals(List.of("duplicate-VNF", "vCPE_Infrastructure_vGMUX_demo_app").toString(), actual.toString());
278
279         long added = getCreateCount() - initCount;
280         assertEquals(2, added);
281
282         verifyUnlocked();
283     }
284
285     // VCPE
286
287     /**
288      * Sunny Day with Tosca Compliant Policy.
289      */
290     @Test
291     public void testVcpeSunnyDayCompliant() {
292         appcLcmSunnyDay(VCPE_TOSCA_COMPLIANT_POLICY, VCPE_ONSET_1, APPC_RESTART_OP);
293     }
294
295     /**
296      * An ONSET flood prevention test that injects a few ONSETs at once. It attempts to
297      * simulate the flooding behavior of the DCAE TCA microservice. TCA could blast tens
298      * or hundreds of ONSETs within sub-second intervals.
299      */
300     @Test
301     public void testVcpeOnsetFloodPrevention() {
302         appcLcmSunnyDay(VCPE_TOSCA_COMPLIANT_POLICY, List.of(VCPE_ONSET_1, VCPE_ONSET_2, VCPE_ONSET_3),
303                         APPC_RESTART_OP);
304     }
305
306     // VDNS
307
308     /**
309      * Sunny Day with Tosca Compliant Policy.
310      */
311     @Test
312     public void testVdnsSunnyDayCompliant() {
313         httpSunnyDay(VDNS_TOSCA_COMPLIANT_POLICY, VDNS_ONSET);
314     }
315
316     /**
317      * Vdns Rainy Day with Compliant Tosca Policy.
318      */
319     @Test
320     public void testVdnsRainyDayCompliant() {
321         httpRainyDay(VDNS_TOSCA_COMPLIANT_RAINY_POLICY, VDNS_ONSET);
322     }
323
324
325     // VFW
326
327     /**
328      * VFW Sunny Day with Tosca Compliant Policy.
329      */
330     @Test
331     public void testVfwSunnyDayCompliant() {
332         appcLegacySunnyDay(VFW_TOSCA_COMPLIANT_POLICY, VFW_ONSET, APPC_MODIFY_CONFIG_OP);
333     }
334
335     /**
336      * VFW Rainy Day using compliant tosca policy (final failure).
337      */
338     @Test
339     public void testVfwRainyDayOverallTimeout() {
340         appcLegacyRainyDayNoResponse(VFW_TOSCA_COMPLIANT_TIME_OUT_POLICY, VFW_ONSET, APPC_MODIFY_CONFIG_OP);
341     }
342
343     /**
344      * VFW Rainy day using compliant tosca policy (final failure due to timeout).
345      */
346     @Test
347     public void testVfwRainyDayCompliantTimeout() {
348         appcLegacyRainyDayNoResponse(VFW_TOSCA_COMPLIANT_POLICY, VFW_ONSET, APPC_MODIFY_CONFIG_OP);
349     }
350
351     /**
352      * VPCI Sunny Day Tosca Policy.
353      */
354     @Test
355     public void testVpciSunnyDayCompliant() {
356         sdnrSunnyDay(VPCI_TOSCA_COMPLIANT_POLICY, VPCI_ONSET, VPCI_SDNR_SUCCESS, SDNR_MODIFY_CONFIG_OP);
357     }
358
359     // VSONH
360
361     /**
362      * VSONH Sunny Day with Tosca Policy.
363      */
364     @Test
365     public void testVsonhSunnyDayCompliant() {
366         sdnrSunnyDay(VSONH_TOSCA_COMPLIANT_POLICY, VSONH_ONSET, VSONH_SDNR_SUCCESS, SNDR_MODIFY_CONFIG_ANR_OP);
367     }
368
369     /**
370      * Sunny day scenario for use cases that use APPC-LCM.
371      *
372      * @param policyFile file containing the ToscaPolicy to be loaded
373      * @param onsetFile file containing the ONSET to be injected
374      * @param operation expected APPC operation request
375      */
376     protected void appcLcmSunnyDay(String policyFile, String onsetFile, String operation) {
377         appcLcmSunnyDay(policyFile, List.of(onsetFile), operation);
378     }
379
380     /**
381      * Sunny day scenario for use cases that use APPC-LCM.
382      *
383      * @param policyFile file containing the ToscaPolicy to be loaded
384      * @param onsetFiles list of files containing the ONSET to be injected
385      * @param operation expected APPC operation request
386      */
387     protected void appcLcmSunnyDay(String policyFile, List<String> onsetFiles, String operation) {
388         policyClMgt = createNoficationTopicListener();
389         appcLcmRead = topics.createListener(APPC_LCM_READ_TOPIC, AppcLcmDmaapWrapper.class, APPC_LCM_CODER);
390
391         policy = checkPolicy(policyFile);
392
393
394         // inject several ONSET events over the DCAE topic
395         for (String onsetFile : onsetFiles) {
396             topics.inject(DCAE_TOPIC, onsetFile);
397         }
398
399         /* Wait to acquire a LOCK and a PDP-X PERMIT */
400         waitForLockAndPermit(policy, policyClMgt);
401
402         /*
403          * Ensure that an APPC RESTART request was sent in response to the matching ONSET
404          */
405         AppcLcmDmaapWrapper appcreq = appcLcmRead.await(req -> operation.equals(req.getRpcName()));
406
407         /*
408          * Inject a 400 APPC Response Return over the APPC topic, with appropriate
409          * subRequestId
410          */
411         topics.inject(APPC_LCM_WRITE_TOPIC, VCPE_APPC_SUCCESS,
412                         appcreq.getBody().getInput().getCommonHeader().getSubRequestId());
413
414         /* --- Operation Completed --- */
415
416         waitForOperationSuccess();
417
418         /* --- Transaction Completed --- */
419         waitForFinalSuccess(policy, policyClMgt);
420
421         verifyUnlocked();
422     }
423
424     /**
425      * Sunny day scenario for use cases that use Legacy APPC.
426      *
427      * @param policyFile file containing the ToscaPolicy to be loaded
428      * @param onsetFile file containing the ONSET to be injected
429      * @param operation expected APPC operation request
430      */
431     protected void appcLegacySunnyDay(String policyFile, String onsetFile, String operation) {
432         policyClMgt = createNoficationTopicListener();
433         appcClSink = topics.createListener(APPC_CL_TOPIC, Request.class, APPC_LEGACY_CODER);
434
435         policy = checkPolicy(policyFile);
436
437         /* Inject an ONSET event over the DCAE topic */
438         topics.inject(DCAE_TOPIC, onsetFile);
439
440         /* Wait to acquire a LOCK and a PDP-X PERMIT */
441         waitForLockAndPermit(policy, policyClMgt);
442
443         /*
444          * Ensure that an APPC RESTART request was sent in response to the matching ONSET
445          */
446         Request appcreq = appcClSink.await(req -> operation.equals(req.getAction()));
447
448         /*
449          * Inject a 400 APPC Response Return over the APPC topic, with appropriate
450          * subRequestId
451          */
452         topics.inject(APPC_CL_TOPIC, VFW_APPC_SUCCESS, appcreq.getCommonHeader().getSubRequestId());
453
454         /* --- Operation Completed --- */
455
456         waitForOperationSuccess();
457
458         /* --- Transaction Completed --- */
459         waitForFinalSuccess(policy, policyClMgt);
460
461         verifyUnlocked();
462     }
463
464     /**
465      * Rainy day scenario for use cases that use Legacy APPC.
466      *
467      * @param policyFile file containing the ToscaPolicy to be loaded
468      * @param onsetFile file containing the ONSET to be injected
469      * @param operation expected APPC operation request
470      */
471     protected void appcLegacyRainyDay(String policyFile, String onsetFile, String operation) {
472         policyClMgt = createNoficationTopicListener();
473         appcClSink = topics.createListener(APPC_CL_TOPIC, Request.class, APPC_LEGACY_CODER);
474
475         policy = checkPolicy(policyFile);
476
477         /* Inject an ONSET event over the DCAE topic */
478         topics.inject(DCAE_TOPIC, onsetFile);
479
480         /* Wait to acquire a LOCK and a PDP-X PERMIT */
481         waitForLockAndPermit(policy, policyClMgt);
482
483         /*
484          * Ensure that an APPC RESTART request was sent in response to the matching ONSET
485          */
486         Request appcreq = appcClSink.await(req -> operation.equals(req.getAction()));
487
488         /*
489          * Inject a 401 APPC Response Return over the APPC topic, with appropriate
490          * subRequestId
491          */
492         topics.inject(APPC_CL_TOPIC, VFW_APPC_FAILURE, appcreq.getCommonHeader().getSubRequestId());
493
494         /* --- Operation Completed --- */
495         waitForOperationFailure();
496
497         /* --- Transaction Completed --- */
498         waitForFinalFailure(policy, policyClMgt);
499
500         verifyUnlocked();
501     }
502
503     /**
504      * Rainy day scenario for use cases that use Legacy APPC. Expected to fail due to
505      * timeout.
506      *
507      * @param policyFile file containing the ToscaPolicy to be loaded
508      * @param onsetFile file containing the ONSET to be injected
509      * @param operation expected APPC operation request
510      */
511     protected void appcLegacyRainyDayNoResponse(String policyFile, String onsetFile, String operation) {
512         policyClMgt = createNoficationTopicListener();
513         appcClSink = topics.createListener(APPC_CL_TOPIC, Request.class, APPC_LEGACY_CODER);
514
515         policy = checkPolicy(policyFile);
516
517         /* Inject an ONSET event over the DCAE topic */
518         topics.inject(DCAE_TOPIC, onsetFile);
519
520         /* Wait to acquire a LOCK and a PDP-X PERMIT */
521         waitForLockAndPermit(policy, policyClMgt);
522
523         /*
524          * Ensure that an APPC RESTART request was sent in response to the matching ONSET
525          */
526         appcClSink.await(req -> operation.equals(req.getAction()));
527
528         /*
529          * Do not inject an APPC Response.
530          */
531
532         /* --- Transaction Completed --- */
533         waitForFinalFailure(policy, policyClMgt);
534
535         verifyUnlocked();
536     }
537
538     /**
539      * Sunny day scenario for use cases that use SDNR.
540      *
541      * @param policyFile file containing the ToscaPolicy to be loaded
542      * @param onsetFile file containing the ONSET to be injected
543      * @param operation expected SDNR operation request
544      */
545     protected void sdnrSunnyDay(String policyFile, String onsetFile, String successFile, String operation) {
546         policyClMgt = createNoficationTopicListener();
547         sdnrClSink = topics.createListener(SDNR_CL_TOPIC, PciMessage.class, SDNR_CODER);
548
549         policy = checkPolicy(policyFile);
550
551         /* Inject an ONSET event over the DCAE topic */
552         topics.inject(DCAE_TOPIC, onsetFile);
553
554         /* Wait to acquire a LOCK and a PDP-X PERMIT */
555         waitForLockAndPermit(policy, policyClMgt);
556
557         /*
558          * Ensure that an SDNR RESTART request was sent in response to the matching ONSET
559          */
560         PciMessage pcireq = sdnrClSink.await(req -> operation.equals(req.getBody().getInput().getAction()));
561
562         /*
563          * Inject response.
564          */
565         topics.inject(SDNR_CL_RSP_TOPIC, successFile, pcireq.getBody().getInput().getCommonHeader().getSubRequestId());
566
567         /* --- Operation Completed --- */
568
569         waitForOperationSuccess();
570
571         /* --- Transaction Completed --- */
572         waitForFinalSuccess(policy, policyClMgt);
573
574         verifyUnlocked();
575     }
576
577     /**
578      * Sunny day scenario for use cases that use an HTTP simulator.
579      *
580      * @param policyFile file containing the ToscaPolicy to be loaded
581      * @param onsetFile file containing the ONSET to be injected
582      */
583     protected void httpSunnyDay(String policyFile, String onsetFile) {
584         policyClMgt = createNoficationTopicListener();
585
586         policy = checkPolicy(policyFile);
587
588         /* Inject an ONSET event over the DCAE topic */
589         topics.inject(DCAE_TOPIC, onsetFile);
590
591         /* Wait to acquire a LOCK and a PDP-X PERMIT */
592         waitForLockAndPermit(policy, policyClMgt);
593
594         /* --- Operation Completed --- */
595
596         waitForOperationSuccess();
597
598         /* --- Transaction Completed --- */
599         waitForFinalSuccess(policy, policyClMgt);
600
601         verifyUnlocked();
602     }
603
604     /**
605      * Rainy day scenario for use cases that use an HTTP simulator.
606      *
607      * @param policyFile file containing the ToscaPolicy to be loaded
608      * @param onsetFile file containing the ONSET to be injected
609      */
610     protected void httpRainyDay(String policyFile, String onsetFile) {
611         policyClMgt = createNoficationTopicListener();
612
613         policy = checkPolicy(policyFile);
614
615         /* Inject an ONSET event over the DCAE topic */
616         topics.inject(DCAE_TOPIC, onsetFile);
617
618         /* Wait to acquire a LOCK and a PDP-X PERMIT */
619         waitForLockAndPermit(policy, policyClMgt);
620
621         /* --- Operation Completed --- */
622         waitForOperationFailure();
623
624         /* --- Transaction Completed --- */
625         waitForFinalFailure(policy, policyClMgt);
626
627         verifyUnlocked();
628     }
629
630     protected long getCreateCount() {
631         return ControlLoopEventManager.getCreateCount();
632     }
633
634     /**
635      * Waits for a OPERATION SUCCESS transaction notification.
636      */
637     protected void waitForOperationSuccess() {
638         policyClMgt.await(notif -> notif.getNotification() == ControlLoopNotificationType.OPERATION_SUCCESS);
639     }
640
641     /**
642      * Waits for a FINAL SUCCESS transaction notification.
643      *
644      * @return the FINAL SUCCESS notification
645      */
646     protected VirtualControlLoopNotification waitForFinalSuccess(ToscaPolicy policy,
647                     Listener<VirtualControlLoopNotification> policyClMgt) {
648
649         return this.waitForFinal(policy, policyClMgt, ControlLoopNotificationType.FINAL_SUCCESS);
650     }
651
652     /**
653      * Waits for a OPERATION FAILURE transaction notification.
654      */
655     protected void waitForOperationFailure() {
656         policyClMgt.await(notif -> notif.getNotification() == ControlLoopNotificationType.OPERATION_FAILURE);
657     }
658
659     /**
660      * Waits for a FINAL FAILURE transaction notification.
661      *
662      * @return the FINAL FAILURE notification
663      */
664     protected VirtualControlLoopNotification waitForFinalFailure(ToscaPolicy policy,
665                     Listener<VirtualControlLoopNotification> policyClMgt) {
666
667         return this.waitForFinal(policy, policyClMgt, ControlLoopNotificationType.FINAL_FAILURE);
668     }
669
670     /**
671      * Waits for notifications for LOCK acquisition and GUARD Permit so that event
672      * processing may proceed.
673      */
674     protected abstract void waitForLockAndPermit(ToscaPolicy policy,
675                     Listener<VirtualControlLoopNotification> policyClMgt);
676
677     /**
678      * Waits for a FINAL transaction notification.
679      *
680      * @param finalType FINAL_xxx type for which to wait
681      *
682      * @return the FINAL notification
683      */
684     protected abstract VirtualControlLoopNotification waitForFinal(ToscaPolicy policy,
685                     Listener<VirtualControlLoopNotification> policyClMgt, ControlLoopNotificationType finalType);
686
687     /**
688      * Returns ToscaPolicy from File.
689      *
690      * @param fileName a path name
691      * @return ToscaPolicy
692      */
693     protected ToscaPolicy checkPolicy(String fileName) {
694         try {
695             return Rules.getPolicyFromFile(fileName);
696         } catch (CoderException e) {
697             throw new IllegalArgumentException(fileName, e);
698         }
699     }
700
701     /**
702      * Creates a Coder for PolicyClMgt from StandardCoder.
703      *
704      */
705     public static class PolicyClMgtCoder extends StandardCoder {
706         public PolicyClMgtCoder() {
707             super(org.onap.policy.controlloop.util.Serialization.gson,
708                             org.onap.policy.controlloop.util.Serialization.gsonPretty);
709         }
710     }
711
712     /**
713      * Returns Listener from createListner based on Coder.
714      *
715      * @return the Listener
716      */
717     protected Listener<VirtualControlLoopNotification> createNoficationTopicListener() {
718         return topics.createListener(POLICY_CL_MGT_TOPIC, VirtualControlLoopNotification.class, POLICY_CL_MGT_CODER);
719     }
720
721     /**
722      * Verifies that all locks have been released, waiting a bit, if necessary.
723      */
724     private void verifyUnlocked() {
725         Map<String, SimpleLock> locks = getLockMap();
726         if (locks != null) {
727             Awaitility.await().atMost(5, TimeUnit.SECONDS).until(locks::isEmpty);
728         }
729     }
730
731     private Map<String, SimpleLock> getLockMap() {
732         Object lockMgr = Whitebox.getInternalState(PolicyEngineConstants.getManager(), "lockManager");
733         if (lockMgr instanceof SimpleLockManager) {
734             return Whitebox.getInternalState(lockMgr, "resource2lock");
735         }
736
737         return null;
738     }
739 }