add4c41aa9a3c4a9ab48857990003b55e0a04319
[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.eventmanager;
22
23 import static org.assertj.core.api.Assertions.assertThat;
24 import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
25 import static org.junit.Assert.assertEquals;
26 import static org.junit.Assert.assertFalse;
27 import static org.junit.Assert.assertNotNull;
28 import static org.junit.Assert.assertNull;
29 import static org.junit.Assert.assertSame;
30 import static org.junit.Assert.assertTrue;
31 import static org.mockito.ArgumentMatchers.any;
32 import static org.mockito.ArgumentMatchers.eq;
33 import static org.mockito.Mockito.doAnswer;
34 import static org.mockito.Mockito.never;
35 import static org.mockito.Mockito.times;
36 import static org.mockito.Mockito.verify;
37 import static org.mockito.Mockito.when;
38
39 import java.time.Instant;
40 import java.util.Map;
41 import java.util.TreeMap;
42 import java.util.UUID;
43 import java.util.concurrent.CompletableFuture;
44 import java.util.concurrent.CountDownLatch;
45 import java.util.concurrent.TimeUnit;
46 import java.util.function.Consumer;
47 import org.junit.Before;
48 import org.junit.Test;
49 import org.mockito.ArgumentCaptor;
50 import org.mockito.Captor;
51 import org.mockito.Mock;
52 import org.mockito.MockitoAnnotations;
53 import org.onap.aai.domain.yang.GenericVnf;
54 import org.onap.policy.aai.AaiCqResponse;
55 import org.onap.policy.common.utils.time.PseudoExecutor;
56 import org.onap.policy.controlloop.ControlLoopOperation;
57 import org.onap.policy.controlloop.ControlLoopResponse;
58 import org.onap.policy.controlloop.VirtualControlLoopEvent;
59 import org.onap.policy.controlloop.actor.guard.DecisionOperation;
60 import org.onap.policy.controlloop.actor.guard.GuardActor;
61 import org.onap.policy.controlloop.actorserviceprovider.ActorService;
62 import org.onap.policy.controlloop.actorserviceprovider.Operation;
63 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
64 import org.onap.policy.controlloop.actorserviceprovider.Operator;
65 import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext;
66 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
67 import org.onap.policy.controlloop.actorserviceprovider.spi.Actor;
68 import org.onap.policy.controlloop.ophistory.OperationHistoryDataManager;
69 import org.onap.policy.controlloop.policy.Policy;
70 import org.onap.policy.controlloop.policy.PolicyResult;
71 import org.onap.policy.controlloop.policy.Target;
72 import org.onap.policy.controlloop.policy.TargetType;
73 import org.onap.policy.sdnr.PciBody;
74 import org.onap.policy.sdnr.PciMessage;
75 import org.onap.policy.sdnr.PciResponse;
76
77 public class ControlLoopOperationManager2Test {
78     private static final UUID REQ_ID = UUID.randomUUID();
79     private static final String MISMATCH = "mismatch";
80     private static final String POLICY_ID = "my-policy";
81     private static final String POLICY_ACTOR = "my-actor";
82     private static final String POLICY_OPERATION = "my-operation";
83     private static final String OTHER_ACTOR = "another-actor";
84     private static final String MY_TARGET = "my-target";
85     private static final String MY_VNF_ID = "my-vnf-id";
86     private static final String PAYLOAD_KEY = "payload-key";
87     private static final String PAYLOAD_VALUE = "payload-value";
88     private static final long REMAINING_MS = 5000;
89     private static final int MAX_RUN = 100;
90     private static final Integer POLICY_RETRY = 3;
91     private static final Integer POLICY_TIMEOUT = 20;
92     private static final IllegalArgumentException EXPECTED_EXCEPTION =
93                     new IllegalArgumentException("expected exception");
94
95     @Captor
96     private ArgumentCaptor<Consumer<OperationOutcome>> lockCallback;
97
98     @Mock
99     private OperationHistoryDataManager dataMgr;
100     @Mock
101     private ManagerContext mgrctx;
102     @Mock
103     private Operator policyOperator;
104     @Mock
105     private Operation policyOperation;
106     @Mock
107     private Actor policyActor;
108     @Mock
109     private ActorService actors;
110     @Mock
111     private AaiCqResponse cqdata;
112     @Mock
113     private GenericVnf vnf;
114
115     private CompletableFuture<OperationOutcome> lockFuture;
116     private CompletableFuture<OperationOutcome> policyFuture;
117     private Target target;
118     private Map<String, String> payload;
119     private Policy policy;
120     private VirtualControlLoopEvent event;
121     private ControlLoopEventContext context;
122     private PseudoExecutor executor;
123     private ControlLoopOperationManager2 mgr;
124
125     /**
126      * Sets up.
127      */
128     @Before
129     public void setUp() {
130         MockitoAnnotations.initMocks(this);
131
132         lockFuture = new CompletableFuture<>();
133         policyFuture = new CompletableFuture<>();
134
135         when(mgrctx.getActorService()).thenReturn(actors);
136         when(mgrctx.getDataManager()).thenReturn(dataMgr);
137         when(mgrctx.requestLock(any(), any())).thenReturn(lockFuture);
138
139         // configure policy operation
140         when(actors.getActor(POLICY_ACTOR)).thenReturn(policyActor);
141         when(policyActor.getOperator(POLICY_OPERATION)).thenReturn(policyOperator);
142         when(policyOperator.buildOperation(any())).thenReturn(policyOperation);
143         when(policyOperation.start()).thenReturn(policyFuture);
144
145         when(vnf.getVnfId()).thenReturn(MY_VNF_ID);
146         when(cqdata.getDefaultGenericVnf()).thenReturn(vnf);
147
148         target = new Target();
149         target.setType(TargetType.VM);
150
151         payload = Map.of(PAYLOAD_KEY, PAYLOAD_VALUE);
152
153         policy = new Policy();
154         policy.setId(POLICY_ID);
155         policy.setActor(POLICY_ACTOR);
156         policy.setRecipe(POLICY_OPERATION);
157         policy.setTarget(target);
158         policy.setPayload(payload);
159         policy.setRetry(POLICY_RETRY);
160         policy.setTimeout(POLICY_TIMEOUT);
161
162         event = new VirtualControlLoopEvent();
163         event.setRequestId(REQ_ID);
164         event.setTarget(ControlLoopOperationManager2.VSERVER_VSERVER_NAME);
165         event.setAai(new TreeMap<>(Map.of(ControlLoopOperationManager2.VSERVER_VSERVER_NAME, MY_TARGET)));
166
167         context = new ControlLoopEventContext(event);
168         context.setProperty(AaiCqResponse.CONTEXT_KEY, cqdata);
169
170         executor = new PseudoExecutor();
171
172         mgr = new ControlLoopOperationManager2(mgrctx, context, policy, executor);
173     }
174
175     @Test
176     public void testStart() {
177         mgr.start(REMAINING_MS);
178
179         // should have determined the target entity by now
180         assertEquals(MY_TARGET, mgr.getTargetEntity());
181
182         verify(mgrctx).requestLock(eq(MY_TARGET), any());
183
184         lockFuture.complete(new OperationOutcome());
185         genGuardOutcome();
186         policyFuture.complete(genOpOutcome());
187         runToCompletion();
188
189         assertEquals(ControlLoopOperationManager2.State.GUARD_STARTED, mgr.getState());
190
191         assertTrue(mgr.nextStep());
192         assertEquals(ControlLoopOperationManager2.State.GUARD_PERMITTED, mgr.getState());
193
194         assertTrue(mgr.nextStep());
195         assertEquals(ControlLoopOperationManager2.State.OPERATION_STARTED, mgr.getState());
196
197         assertTrue(mgr.nextStep());
198         assertEquals(ControlLoopOperationManager2.State.OPERATION_SUCCESS, mgr.getState());
199
200         assertFalse(mgr.nextStep());
201
202         OperationOutcome outcome = mgr.getOutcomes().peek();
203         assertEquals(PolicyResult.SUCCESS, outcome.getResult());
204         assertTrue(outcome.isFinalOutcome());
205
206         verify(mgrctx, times(4)).updated(mgr);
207     }
208
209     /**
210      * Tests start() when detmTarget() (i.e., the first task) throws an exception.
211      */
212     @Test
213     public void testStartDetmTargetException() {
214         policy.setTarget(new Target());
215         mgr.start(REMAINING_MS);
216
217         runToCompletion();
218
219         assertFalse(mgr.nextStep());
220         assertEquals(ControlLoopOperationManager2.State.OPERATION_FAILURE, mgr.getState());
221
222         // should have called update() for operation-start, but not for any nextStep()
223         verify(mgrctx).updated(mgr);
224     }
225
226     /**
227      * Tests start() when a subsequent task throws an exception.
228      */
229     @Test
230     public void testStartException() {
231         when(policyOperation.start()).thenThrow(EXPECTED_EXCEPTION);
232
233         mgr.start(REMAINING_MS);
234
235         lockFuture.complete(new OperationOutcome());
236         runToCompletion();
237
238         assertFalse(mgr.nextStep());
239         assertEquals(ControlLoopOperationManager2.State.OPERATION_FAILURE, mgr.getState());
240
241         // should have called update() for operation-start, but not for any nextStep()
242         verify(mgrctx).updated(mgr);
243     }
244
245     /**
246      * Tests start() when the control loop times out before the operation starts.
247      */
248     @Test
249     public void testStartClTimeout_testHandleTimeout() throws InterruptedException {
250         // catch the callback when it times out
251         CountDownLatch updatedLatch = new CountDownLatch(1);
252         doAnswer(args -> {
253             updatedLatch.countDown();
254             return null;
255         }).when(mgrctx).updated(any());
256
257         long tstart = System.currentTimeMillis();
258
259         // give it a short timeout
260         mgr.start(100);
261
262         assertTrue(updatedLatch.await(5, TimeUnit.SECONDS));
263         assertTrue(System.currentTimeMillis() - tstart >= 100);
264
265         // don't generate any responses
266         runToCompletion();
267
268         // wait for the future to be canceled, via a background thread
269         CountDownLatch futureLatch = new CountDownLatch(1);
270         mgr.getFuture().whenComplete((unused, thrown) -> futureLatch.countDown());
271         assertTrue(futureLatch.await(5, TimeUnit.SECONDS));
272
273         // lock should have been canceled
274         assertTrue(mgr.getFuture().isCancelled());
275
276         assertFalse(mgr.nextStep());
277         assertEquals(ControlLoopOperationManager2.State.CONTROL_LOOP_TIMEOUT, mgr.getState());
278
279         // should have called update() for operation-start, but not for any nextStep()
280         verify(mgrctx).updated(mgr);
281
282         // should have added a record to the DB
283         verify(dataMgr).store(any(), any(), any(), any());
284     }
285
286     @Test
287     public void testStartOperation() {
288         mgr.start(REMAINING_MS);
289
290         lockFuture.complete(new OperationOutcome());
291         genGuardOutcome();
292         runToCompletion();
293
294         verify(policyOperation).start();
295
296         ArgumentCaptor<ControlLoopOperationParams> captor = ArgumentCaptor.forClass(ControlLoopOperationParams.class);
297         verify(policyOperator).buildOperation(captor.capture());
298
299         ControlLoopOperationParams params = captor.getValue();
300
301         assertNotNull(params);
302         assertEquals(POLICY_ACTOR, params.getActor());
303         assertSame(actors, params.getActorService());
304         assertNotNull(params.getCompleteCallback());
305         assertSame(context, params.getContext());
306         assertSame(executor, params.getExecutor());
307         assertEquals(POLICY_OPERATION, params.getOperation());
308         assertEquals(payload, params.getPayload());
309         assertSame(REQ_ID, params.getRequestId());
310         assertSame(POLICY_RETRY, params.getRetry());
311         assertNotNull(params.getStartCallback());
312         assertSame(target, params.getTarget());
313         assertEquals(MY_TARGET, params.getTargetEntity());
314         assertSame(POLICY_TIMEOUT, params.getTimeoutSec());
315     }
316
317     @Test
318     public void testStartOperationNullPayload() {
319         policy.setPayload(null);
320         mgr.start(REMAINING_MS);
321
322         lockFuture.complete(new OperationOutcome());
323         genGuardOutcome();
324         runToCompletion();
325
326         verify(policyOperation).start();
327
328         ArgumentCaptor<ControlLoopOperationParams> captor = ArgumentCaptor.forClass(ControlLoopOperationParams.class);
329         verify(policyOperator).buildOperation(captor.capture());
330
331         ControlLoopOperationParams params = captor.getValue();
332
333         assertNotNull(params);
334         assertEquals(POLICY_ACTOR, params.getActor());
335         assertSame(actors, params.getActorService());
336         assertNotNull(params.getCompleteCallback());
337         assertSame(context, params.getContext());
338         assertSame(executor, params.getExecutor());
339         assertEquals(POLICY_OPERATION, params.getOperation());
340         assertTrue(params.getPayload().isEmpty());
341         assertSame(REQ_ID, params.getRequestId());
342         assertSame(POLICY_RETRY, params.getRetry());
343         assertNotNull(params.getStartCallback());
344         assertSame(target, params.getTarget());
345         assertEquals(MY_TARGET, params.getTargetEntity());
346         assertSame(POLICY_TIMEOUT, params.getTimeoutSec());
347     }
348
349     @Test
350     public void testMakeControlLoopResponse() {
351         final OperationOutcome outcome = new OperationOutcome();
352         PciMessage msg = new PciMessage();
353         outcome.setResponse(msg);
354
355         PciBody body = new PciBody();
356         msg.setBody(body);
357
358         PciResponse output = new PciResponse();
359         body.setOutput(output);
360
361         output.setPayload("my-payload");
362
363
364         // not an SDNR action - should return null
365         assertNull(mgr.makeControlLoopResponse(outcome));
366
367         /*
368          * now work with SDNR actor
369          */
370         policy.setActor("SDNR");
371         mgr = new ControlLoopOperationManager2(mgrctx, context, policy, executor);
372
373         // should return null for a null input
374         assertNull(mgr.makeControlLoopResponse(null));
375
376         // should generate a response, with a payload
377         checkResp(outcome, "my-payload");
378
379         /*
380          * these should generate a response, with null payload
381          */
382         output.setPayload(null);
383         checkResp(outcome, null);
384
385         body.setOutput(null);
386         checkResp(outcome, null);
387
388         msg.setBody(null);
389         checkResp(outcome, null);
390
391         outcome.setResponse(null);
392         checkResp(outcome, null);
393     }
394
395     @Test
396     public void testGetOperationMessage() {
397         // no history yet
398         assertNull(mgr.getOperationMessage());
399
400         runCyle();
401         assertThat(mgr.getOperationMessage()).contains("actor=my-actor").contains("operation=my-operation");
402     }
403
404     @Test
405     public void testGetOperationResult() {
406         // no history yet
407         assertNotNull(mgr.getOperationResult());
408
409         runCyle();
410         assertEquals(PolicyResult.SUCCESS, mgr.getOperationResult());
411     }
412
413     /**
414      * Tests getOperationResult() when it ends in a failure.
415      */
416     @Test
417     public void testGetOperationResultFailure() {
418         mgr.start(REMAINING_MS);
419
420         genLockFailure();
421         runToCompletion();
422
423         assertEquals(PolicyResult.FAILURE_GUARD, mgr.getOperationResult());
424     }
425
426     /**
427      * Tests handleException() when the exception is a "cancel".
428      */
429     @Test
430     public void testHandleExceptionCanceled() {
431         lockFuture.cancel(false);
432
433         mgr.start(REMAINING_MS);
434
435         runToCompletion();
436
437         assertTrue(mgr.nextStep());
438         assertEquals(ControlLoopOperationManager2.State.ACTIVE, mgr.getState());
439     }
440
441     @Test
442     public void testCancel() {
443         mgr.start(REMAINING_MS);
444
445         mgr.cancel();
446         assertTrue(mgr.getFuture().isCancelled());
447     }
448
449     /**
450      * Tests cancel() when the operation hasn't been started.
451      */
452     @Test
453     public void testCancelNotStarted() {
454         assertNull(mgr.getFuture());
455
456         mgr.cancel();
457         assertNull(mgr.getFuture());
458     }
459
460     @Test
461     public void testLockUnavailable() {
462         mgr.start(REMAINING_MS);
463
464         runToCompletion();
465
466         // lock failure outcome
467         final OperationOutcome outcome = genLockFailure();
468
469         runToCompletion();
470
471         assertFalse(mgr.nextStep());
472         assertEquals(ControlLoopOperationManager2.State.LOCK_DENIED, mgr.getState());
473
474         assertEquals(outcome, mgr.getOutcomes().peek());
475
476         // should have called update() for operation-start, but not for any nextStep()
477         verify(mgrctx).updated(mgr);
478     }
479
480     /**
481      * Tests onStart() and onComplete() with other actors.
482      */
483     @Test
484     public void testOnStart_testOnComplete() {
485         mgr.start(REMAINING_MS);
486
487         lockFuture.complete(new OperationOutcome());
488         genGuardOutcome();
489
490         // generate failure outcome for ANOTHER actor - should be ignored
491         OperationOutcome outcome = mgr.getParams().makeOutcome();
492         outcome.setActor(OTHER_ACTOR);
493         outcome.setResult(PolicyResult.FAILURE);
494         outcome.setStart(Instant.now());
495         mgr.getParams().callbackStarted(new OperationOutcome(outcome));
496
497         outcome.setEnd(Instant.now());
498         mgr.getParams().callbackCompleted(outcome);
499
500         policyFuture.complete(genOpOutcome());
501         runToCompletion();
502
503         // should not include the other actor's outcome
504         assertEquals(ControlLoopOperationManager2.State.GUARD_STARTED, mgr.getState());
505
506         assertTrue(mgr.nextStep());
507         assertEquals(ControlLoopOperationManager2.State.GUARD_PERMITTED, mgr.getState());
508
509         assertTrue(mgr.nextStep());
510         assertEquals(ControlLoopOperationManager2.State.OPERATION_STARTED, mgr.getState());
511
512         assertTrue(mgr.nextStep());
513         assertEquals(ControlLoopOperationManager2.State.OPERATION_SUCCESS, mgr.getState());
514
515         assertFalse(mgr.nextStep());
516
517         assertEquals(PolicyResult.SUCCESS, mgr.getOutcomes().peek().getResult());
518
519         verify(mgrctx, times(4)).updated(mgr);
520     }
521
522     @Test
523     public void testNextStep() {
524         mgr.start(REMAINING_MS);
525
526         // only do the lock and the guard
527         lockFuture.complete(new OperationOutcome());
528         genGuardOutcome();
529         runToCompletion();
530
531         assertEquals(ControlLoopOperationManager2.State.GUARD_STARTED, mgr.getState());
532
533         assertTrue(mgr.nextStep());
534         assertEquals(ControlLoopOperationManager2.State.GUARD_PERMITTED, mgr.getState());
535
536         assertTrue(mgr.nextStep());
537         assertTrue(mgr.nextStep());
538
539         verify(mgrctx, times(2)).updated(mgr);
540     }
541
542     /**
543      * Tests processOutcome() when the lock is denied.
544      */
545     @Test
546     public void testProcessOutcomeLockDenied() {
547         mgr.start(REMAINING_MS);
548
549         // unavailable from the start => "denied"
550         genLockFailure();
551
552         runToCompletion();
553
554         assertEquals(ControlLoopOperationManager2.State.LOCK_DENIED, mgr.getState());
555
556         assertFalse(mgr.nextStep());
557         verify(mgrctx).updated(mgr);
558
559         verifyDb(1, PolicyResult.FAILURE_GUARD, "Operation denied by Lock");
560     }
561
562     /**
563      * Tests processOutcome() when the lock is lost.
564      */
565     @Test
566     public void testProcessOutcomeLockLost() {
567         mgr.start(REMAINING_MS);
568
569         // indicate lock success initially
570         lockFuture.complete(new OperationOutcome());
571
572         // do the guard
573         genGuardOutcome();
574
575         // now generate a lock failure => "lost"
576         genLockFailure();
577
578         runToCompletion();
579
580         assertEquals(ControlLoopOperationManager2.State.GUARD_STARTED, mgr.getState());
581
582         assertTrue(mgr.nextStep());
583         assertEquals(ControlLoopOperationManager2.State.GUARD_PERMITTED, mgr.getState());
584
585         assertTrue(mgr.nextStep());
586         assertEquals(ControlLoopOperationManager2.State.LOCK_LOST, mgr.getState());
587
588         assertFalse(mgr.nextStep());
589         verify(mgrctx, times(3)).updated(mgr);
590
591         verifyDb(1, PolicyResult.FAILURE, "Operation aborted by Lock");
592     }
593
594     /**
595      * Tests processOutcome() when the guard is permitted.
596      */
597     @Test
598     public void testProcessOutcomeGuardPermit() {
599         mgr.start(REMAINING_MS);
600
601         lockFuture.complete(new OperationOutcome());
602         genGuardOutcome();
603
604         runToCompletion();
605
606         assertEquals(ControlLoopOperationManager2.State.GUARD_STARTED, mgr.getState());
607
608         assertTrue(mgr.nextStep());
609         assertEquals(ControlLoopOperationManager2.State.GUARD_PERMITTED, mgr.getState());
610
611         assertTrue(mgr.nextStep());
612         verify(mgrctx, times(2)).updated(mgr);
613
614         verify(dataMgr, never()).store(any(), any(), any(), any());
615     }
616
617     /**
618      * Tests processOutcome() when the guard is permitted.
619      */
620     @Test
621     public void testProcessOutcomeGuardDenied() {
622         mgr.start(REMAINING_MS);
623
624         lockFuture.complete(new OperationOutcome());
625         genGuardOutcome(false);
626
627         runToCompletion();
628
629         assertEquals(ControlLoopOperationManager2.State.GUARD_STARTED, mgr.getState());
630
631         assertTrue(mgr.nextStep());
632         assertEquals(ControlLoopOperationManager2.State.GUARD_DENIED, mgr.getState());
633
634         assertFalse(mgr.nextStep());
635         verify(mgrctx, times(2)).updated(mgr);
636
637         verifyDb(1, PolicyResult.FAILURE_GUARD, "Operation denied by Guard");
638     }
639
640     /**
641      * Tests processOutcome() when the operation is a success.
642      */
643     @Test
644     public void testProcessOutcomeOperSuccess() {
645         mgr.start(REMAINING_MS);
646
647         lockFuture.complete(new OperationOutcome());
648         genGuardOutcome();
649         genOpOutcome();
650
651         runToCompletion();
652
653         assertEquals(ControlLoopOperationManager2.State.GUARD_STARTED, mgr.getState());
654
655         assertTrue(mgr.nextStep());
656         assertEquals(ControlLoopOperationManager2.State.GUARD_PERMITTED, mgr.getState());
657
658         assertTrue(mgr.nextStep());
659         assertEquals(ControlLoopOperationManager2.State.OPERATION_STARTED, mgr.getState());
660
661         assertTrue(mgr.nextStep());
662         assertEquals(ControlLoopOperationManager2.State.OPERATION_SUCCESS, mgr.getState());
663
664         assertFalse(mgr.nextStep());
665         verify(mgrctx, times(4)).updated(mgr);
666
667         verifyDb(2, PolicyResult.SUCCESS, null);
668     }
669
670     /**
671      * Tests processOutcome() when the operation is a failure.
672      */
673     @Test
674     public void testProcessOutcomeOperFailure() {
675         mgr.start(REMAINING_MS);
676
677         lockFuture.complete(new OperationOutcome());
678         genGuardOutcome();
679         genOpOutcome(false);
680
681         runToCompletion();
682
683         assertEquals(ControlLoopOperationManager2.State.GUARD_STARTED, mgr.getState());
684
685         assertTrue(mgr.nextStep());
686         assertEquals(ControlLoopOperationManager2.State.GUARD_PERMITTED, mgr.getState());
687
688         assertTrue(mgr.nextStep());
689         assertEquals(ControlLoopOperationManager2.State.OPERATION_STARTED, mgr.getState());
690
691         assertTrue(mgr.nextStep());
692         assertEquals(ControlLoopOperationManager2.State.OPERATION_FAILURE, mgr.getState());
693         verifyDb(2, PolicyResult.FAILURE, null);
694
695         assertThat(mgr.toString()).contains("attempts=1");
696
697         // next failure
698         genOpOutcome(false);
699         runToCompletion();
700
701         assertTrue(mgr.nextStep());
702         assertEquals(ControlLoopOperationManager2.State.OPERATION_STARTED, mgr.getState());
703
704         assertTrue(mgr.nextStep());
705         assertEquals(ControlLoopOperationManager2.State.OPERATION_FAILURE, mgr.getState());
706         verifyDb(4, PolicyResult.FAILURE, null);
707
708         assertThat(mgr.toString()).contains("attempts=2");
709
710         // and finally a success
711         genOpOutcome();
712
713         assertTrue(mgr.nextStep());
714         assertEquals(ControlLoopOperationManager2.State.OPERATION_STARTED, mgr.getState());
715
716         assertTrue(mgr.nextStep());
717         assertEquals(ControlLoopOperationManager2.State.OPERATION_SUCCESS, mgr.getState());
718         verifyDb(6, PolicyResult.SUCCESS, null);
719
720         assertThat(mgr.toString()).contains("attempts=3");
721
722         assertFalse(mgr.nextStep());
723         verify(mgrctx, times(8)).updated(mgr);
724     }
725
726     @Test
727     public void testGetOperationHistory() {
728         // no history yet
729         assertNull(mgr.getOperationHistory());
730
731         runCyle();
732         assertThat(mgr.getOperationHistory()).contains("actor=my-actor").contains("operation=my-operation")
733                         .contains("outcome=Success");
734     }
735
736     @Test
737     public void testGetHistory() {
738         // no history yet
739         assertEquals(0, mgr.getHistory().size());
740
741         runCyle();
742         assertEquals(1, mgr.getHistory().size());
743     }
744
745     @Test
746     public void testDetmTargetVm() {
747         target.setType(TargetType.VM);
748         assertNull(mgr.detmTarget());
749         assertEquals(MY_TARGET, mgr.getTargetEntity());
750
751         target.setType(TargetType.VNF);
752         assertNull(mgr.detmTarget());
753         assertEquals(MY_TARGET, mgr.getTargetEntity());
754
755         target.setType(TargetType.VFMODULE);
756         assertNull(mgr.detmTarget());
757         assertEquals(MY_TARGET, mgr.getTargetEntity());
758
759         // unsupported type
760         target.setType(TargetType.VFC);
761         assertThatIllegalArgumentException().isThrownBy(() -> mgr.detmTarget())
762                         .withMessage("The target type is not supported");
763
764         // null type
765         target.setType(null);
766         assertThatIllegalArgumentException().isThrownBy(() -> mgr.detmTarget()).withMessage("The target type is null");
767
768         // null target
769         policy.setTarget(null);
770         assertThatIllegalArgumentException().isThrownBy(() -> mgr.detmTarget()).withMessage("The target is null");
771     }
772
773     @Test
774     public void testDetmPnfTarget() {
775         setTargetPnf();
776         assertNull(mgr.detmTarget());
777         assertEquals(MY_TARGET, mgr.getTargetEntity());
778
779         // missing enrichment data
780         event.getAai().clear();
781         assertThatIllegalArgumentException().isThrownBy(() -> mgr.detmTarget())
782                         .withMessage("AAI section is missing " + ControlLoopOperationManager2.PNF_NAME);
783
784         // wrong target
785         event.setTarget(MISMATCH);
786         assertThatIllegalArgumentException().isThrownBy(() -> mgr.detmTarget())
787                         .withMessage("Target does not match target type");
788     }
789
790     @Test
791     public void testDetmVfModuleTarget() {
792         // vserver
793         event.setTarget(ControlLoopOperationManager2.VSERVER_VSERVER_NAME);
794         event.getAai().clear();
795         event.getAai().putAll(Map.of(ControlLoopOperationManager2.VSERVER_VSERVER_NAME, MY_TARGET));
796         assertNull(mgr.detmTarget());
797         assertEquals(MY_TARGET, mgr.getTargetEntity());
798
799         // vnf-id
800         event.setTarget(ControlLoopOperationManager2.GENERIC_VNF_VNF_ID);
801         event.getAai().clear();
802         event.getAai().putAll(Map.of(ControlLoopOperationManager2.GENERIC_VNF_VNF_ID, MY_TARGET));
803         assertNull(mgr.detmTarget());
804         assertEquals(MY_TARGET, mgr.getTargetEntity());
805
806         // wrong type
807         event.setTarget(MISMATCH);
808         assertThatIllegalArgumentException().isThrownBy(() -> mgr.detmTarget())
809                         .withMessage("Target does not match target type");
810
811         // missing enrichment data
812         event.setTarget(ControlLoopOperationManager2.VSERVER_VSERVER_NAME);
813         event.getAai().clear();
814         assertThatIllegalArgumentException().isThrownBy(() -> mgr.detmTarget())
815                         .withMessage("Enrichment data is missing " + ControlLoopOperationManager2.VSERVER_VSERVER_NAME);
816
817         // null target
818         event.setTarget(null);
819         assertThatIllegalArgumentException().isThrownBy(() -> mgr.detmTarget()).withMessage("Target is null");
820     }
821
822     @Test
823     public void testDetmVnfName() {
824         setTargetVnfName();
825         assertNull(mgr.detmTarget());
826         assertEquals(MY_TARGET, mgr.getTargetEntity());
827
828         // force it to be gotten from the CQ data
829         event.getAai().clear();
830         assertNull(mgr.detmTarget());
831         assertEquals(MY_VNF_ID, mgr.getTargetEntity());
832     }
833
834     @Test
835     public void testExtractVnfFromCq() {
836         // force it to be gotten from the CQ data
837         setTargetVnfName();
838         event.getAai().clear();
839
840         // missing vnf id in CQ data
841         when(vnf.getVnfId()).thenReturn(null);
842         assertThatIllegalArgumentException().isThrownBy(() -> mgr.detmTarget()).withMessage("No vnf-id found");
843
844         // missing default vnf in CQ data
845         when(cqdata.getDefaultGenericVnf()).thenReturn(null);
846         assertThatIllegalArgumentException().isThrownBy(() -> mgr.detmTarget()).withMessage("No vnf-id found");
847     }
848
849     @Test
850     public void testGetState_testGetActor_testGetOperation() {
851         assertEquals(ControlLoopOperationManager2.State.ACTIVE, mgr.getState());
852         assertEquals(POLICY_ACTOR, mgr.getActor());
853         assertEquals(POLICY_OPERATION, mgr.getOperation());
854     }
855
856     @Test
857     public void testToString() {
858         assertThat(mgr.toString()).contains("state").contains("requestId").contains("policyId").contains("attempts");
859     }
860
861     /**
862      * Runs a cycle, from start to completion.
863      */
864     private void runCyle() {
865         mgr.start(REMAINING_MS);
866
867         lockFuture.complete(new OperationOutcome());
868         genGuardOutcome();
869         genOpOutcome();
870
871         runToCompletion();
872
873         // guard start
874         assertTrue(mgr.nextStep());
875
876         // guard permit
877         assertTrue(mgr.nextStep());
878
879         // operation start
880         assertTrue(mgr.nextStep());
881
882         // operation success
883         assertFalse(mgr.nextStep());
884     }
885
886     /**
887      * Runs everything until the executor queue is empty.
888      */
889     private void runToCompletion() {
890         assertTrue(executor.runAll(MAX_RUN));
891     }
892
893     /**
894      * Generates a failure outcome for the lock, and invokes the callbacks.
895      *
896      * @return the generated outcome
897      */
898     private OperationOutcome genLockFailure() {
899         OperationOutcome outcome = new OperationOutcome();
900         outcome.setActor(ControlLoopOperationManager2.LOCK_ACTOR);
901         outcome.setOperation(ControlLoopOperationManager2.LOCK_OPERATION);
902         outcome.setResult(PolicyResult.FAILURE);
903         outcome.setStart(Instant.now());
904         outcome.setEnd(Instant.now());
905         outcome.setFinalOutcome(true);
906
907         verify(mgrctx).requestLock(eq(MY_TARGET), lockCallback.capture());
908         lockCallback.getValue().accept(outcome);
909
910         lockFuture.complete(outcome);
911
912         return outcome;
913     }
914
915     /**
916      * Generates an outcome for the guard, and invokes the callbacks.
917      *
918      * @return the generated outcome
919      */
920     private OperationOutcome genGuardOutcome() {
921         return genGuardOutcome(true);
922     }
923
924     /**
925      * Generates an outcome for the guard, and invokes the callbacks.
926      *
927      * @param permit {@code true} if the guard should be permitted, {@code false} if
928      *        denied
929      * @return the generated outcome
930      */
931     private OperationOutcome genGuardOutcome(boolean permit) {
932         OperationOutcome outcome = mgr.getParams().makeOutcome();
933         outcome.setActor(GuardActor.NAME);
934         outcome.setOperation(DecisionOperation.NAME);
935         outcome.setStart(Instant.now());
936         mgr.getParams().callbackStarted(new OperationOutcome(outcome));
937
938         if (!permit) {
939             outcome.setResult(PolicyResult.FAILURE);
940         }
941
942         outcome.setEnd(Instant.now());
943         mgr.getParams().callbackCompleted(outcome);
944
945         return outcome;
946     }
947
948     /**
949      * Generates an outcome for the operation, itself, and invokes the callbacks.
950      *
951      * @return the generated outcome
952      */
953     private OperationOutcome genOpOutcome() {
954         return genOpOutcome(true);
955     }
956
957     /**
958      * Generates an outcome for the operation, itself, and invokes the callbacks.
959      *
960      * @param success {@code true} if the outcome should be a success, {@code false} if a
961      *        failure
962      * @return the generated outcome
963      */
964     private OperationOutcome genOpOutcome(boolean success) {
965         OperationOutcome outcome = mgr.getParams().makeOutcome();
966         outcome.setStart(Instant.now());
967         mgr.getParams().callbackStarted(new OperationOutcome(outcome));
968
969         if (success) {
970             outcome.setFinalOutcome(true);
971         } else {
972             outcome.setResult(PolicyResult.FAILURE);
973         }
974
975         outcome.setEnd(Instant.now());
976         mgr.getParams().callbackCompleted(outcome);
977
978         return outcome;
979     }
980
981     /**
982      * Configures the data for a PNF target.
983      */
984     private void setTargetPnf() {
985         event.setTarget(ControlLoopOperationManager2.PNF_NAME);
986         event.getAai().clear();
987         event.getAai().putAll(Map.of(ControlLoopOperationManager2.PNF_NAME, MY_TARGET));
988
989         target.setType(TargetType.PNF);
990     }
991
992     /**
993      * Configures the data for a VNF-NAME target.
994      */
995     private void setTargetVnfName() {
996         event.setTarget(ControlLoopOperationManager2.GENERIC_VNF_VNF_NAME);
997         event.getAai().clear();
998         event.getAai().putAll(Map.of(ControlLoopOperationManager2.GENERIC_VNF_VNF_ID, MY_TARGET));
999
1000         target.setType(TargetType.VNF);
1001     }
1002
1003     private void checkResp(OperationOutcome outcome, String expectedPayload) {
1004         ControlLoopResponse resp = mgr.makeControlLoopResponse(outcome);
1005         assertNotNull(resp);
1006         assertEquals(REQ_ID, resp.getRequestId());
1007         assertEquals(expectedPayload, resp.getPayload());
1008     }
1009
1010     private void verifyDb(int nrecords, PolicyResult expectedResult, String expectedMsg) {
1011         ArgumentCaptor<String> entityCaptor = ArgumentCaptor.forClass(String.class);
1012         ArgumentCaptor<ControlLoopOperation> opCaptor = ArgumentCaptor.forClass(ControlLoopOperation.class);
1013         verify(dataMgr, times(nrecords)).store(any(), any(), entityCaptor.capture(), opCaptor.capture());
1014
1015         assertEquals(MY_TARGET, entityCaptor.getValue());
1016
1017         ControlLoopOperation oper = opCaptor.getValue();
1018
1019         assertEquals(expectedResult.toString(), oper.getOutcome());
1020         assertEquals(expectedMsg, oper.getMessage());
1021     }
1022 }