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