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