2 * ============LICENSE_START=======================================================
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
21 package org.onap.policy.controlloop.eventmanager;
23 import static org.assertj.core.api.Assertions.assertThatCode;
24 import static org.assertj.core.api.Assertions.assertThatThrownBy;
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.anyLong;
33 import static org.mockito.Mockito.never;
34 import static org.mockito.Mockito.times;
35 import static org.mockito.Mockito.verify;
36 import static org.mockito.Mockito.when;
38 import java.util.ArrayList;
39 import java.util.Arrays;
40 import java.util.List;
42 import java.util.TreeMap;
43 import java.util.UUID;
44 import java.util.concurrent.CompletableFuture;
45 import java.util.concurrent.ExecutorService;
46 import java.util.function.Consumer;
47 import org.drools.core.WorkingMemory;
48 import org.junit.Before;
49 import org.junit.Test;
50 import org.kie.api.runtime.rule.FactHandle;
51 import org.mockito.ArgumentCaptor;
52 import org.mockito.Mock;
53 import org.mockito.MockitoAnnotations;
54 import org.onap.policy.common.utils.coder.Coder;
55 import org.onap.policy.common.utils.coder.CoderException;
56 import org.onap.policy.common.utils.coder.StandardYamlCoder;
57 import org.onap.policy.common.utils.io.Serializer;
58 import org.onap.policy.common.utils.resources.ResourceUtils;
59 import org.onap.policy.controlloop.ControlLoopEventStatus;
60 import org.onap.policy.controlloop.ControlLoopException;
61 import org.onap.policy.controlloop.ControlLoopNotificationType;
62 import org.onap.policy.controlloop.ControlLoopOperation;
63 import org.onap.policy.controlloop.ControlLoopTargetType;
64 import org.onap.policy.controlloop.VirtualControlLoopEvent;
65 import org.onap.policy.controlloop.VirtualControlLoopNotification;
66 import org.onap.policy.controlloop.actorserviceprovider.ActorService;
67 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
68 import org.onap.policy.controlloop.actorserviceprovider.OperationResult;
69 import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext;
70 import org.onap.policy.controlloop.drl.legacy.ControlLoopParams;
71 import org.onap.policy.controlloop.eventmanager.ControlLoopEventManager2.NewEventStatus;
72 import org.onap.policy.controlloop.eventmanager.ControlLoopOperationManager2.State;
73 import org.onap.policy.controlloop.ophistory.OperationHistoryDataManager;
74 import org.onap.policy.drools.core.lock.LockCallback;
75 import org.onap.policy.drools.core.lock.LockImpl;
76 import org.onap.policy.drools.core.lock.LockState;
77 import org.onap.policy.drools.domain.models.operational.Operation;
78 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
79 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
81 public class ControlLoopEventManager2Test {
82 private static final UUID REQ_ID = UUID.randomUUID();
83 private static final String CL_NAME = "my-closed-loop-name";
84 private static final String POLICY_NAME = "my-policy-name";
85 private static final String POLICY_SCOPE = "my-scope";
86 private static final String POLICY_VERSION = "1.2.3";
87 private static final String MY_TARGET = "my-target";
88 private static final String LOCK1 = "my-lock-A";
89 private static final String LOCK2 = "my-lock-B";
90 private static final Coder yamlCoder = new StandardYamlCoder();
93 private WorkingMemory workMem;
95 private Consumer<OperationOutcome> callback1;
97 private Consumer<OperationOutcome> callback2;
99 private Consumer<OperationOutcome> callback3;
101 private FactHandle factHandle;
103 private ActorService actors;
105 private OperationHistoryDataManager dataMgr;
107 private ControlLoopOperationManager2 oper1;
109 private ControlLoopOperationManager2 oper2;
111 private ControlLoopOperationManager2 oper3;
113 private ExecutorService executor;
115 private long preCreateTimeMs;
116 private List<LockImpl> locks;
117 private ToscaPolicy tosca;
118 private ControlLoopParams params;
119 private VirtualControlLoopEvent event;
120 private int updateCount;
121 private ControlLoopEventManager2Drools mgr;
127 public void setUp() throws ControlLoopException, CoderException {
128 MockitoAnnotations.initMocks(this);
130 when(oper1.getHistory()).thenReturn(makeHistory("A"));
131 when(oper2.getHistory()).thenReturn(makeHistory("B"));
132 when(oper3.getHistory()).thenReturn(makeHistory("C"));
134 when(oper1.getActor()).thenReturn("First");
135 when(oper1.getOperation()).thenReturn("OperationA");
136 when(oper1.getOperationMessage()).thenReturn("message-A");
137 when(oper1.getOperationHistory()).thenReturn("history-A");
139 when(oper2.getActor()).thenReturn("Second");
140 when(oper2.getOperation()).thenReturn("OperationB");
141 when(oper2.getOperationMessage()).thenReturn("message-B");
142 when(oper2.getOperationHistory()).thenReturn("history-B");
144 when(oper3.getActor()).thenReturn("Third");
145 when(oper3.getOperation()).thenReturn("OperationC");
146 when(oper3.getOperationMessage()).thenReturn("message-C");
147 when(oper3.getOperationHistory()).thenReturn("history-C");
149 when(workMem.getFactHandle(any())).thenReturn(factHandle);
151 event = new VirtualControlLoopEvent();
152 event.setRequestId(REQ_ID);
153 event.setTarget(ControlLoopOperationManager2.VSERVER_VSERVER_NAME);
154 event.setAai(new TreeMap<>(Map.of(ControlLoopOperationManager2.VSERVER_VSERVER_NAME, MY_TARGET)));
155 event.setClosedLoopEventStatus(ControlLoopEventStatus.ONSET);
156 event.setClosedLoopControlName(CL_NAME);
157 event.setTargetType(ControlLoopTargetType.VNF);
159 params = new ControlLoopParams();
160 params.setClosedLoopControlName(CL_NAME);
161 params.setPolicyName(POLICY_NAME);
162 params.setPolicyScope(POLICY_SCOPE);
163 params.setPolicyVersion(POLICY_VERSION);
165 loadPolicy("eventManager/event-mgr-simple.yaml");
167 locks = new ArrayList<>();
171 preCreateTimeMs = System.currentTimeMillis();
173 mgr = new MyManagerWithOper(params, event, workMem);
177 public void testConstructor() {
178 assertEquals(POLICY_NAME, mgr.getPolicyName());
180 Map<String, String> orig = event.getAai();
182 event.setAai(addAai(orig, ControlLoopEventManager2.VSERVER_IS_CLOSED_LOOP_DISABLED, "true"));
183 assertThatThrownBy(() -> new ControlLoopEventManager2Drools(params, event, workMem))
184 .hasMessage("is-closed-loop-disabled is set to true on VServer or VNF");
187 event.setAai(addAai(orig, ControlLoopEventManager2.VSERVER_PROV_STATUS,
188 ControlLoopEventManager2.PROV_STATUS_ACTIVE.toUpperCase()));
189 assertThatCode(() -> new ControlLoopEventManager2Drools(params, event, workMem)).doesNotThrowAnyException();
192 event.setAai(addAai(orig, ControlLoopEventManager2.VSERVER_PROV_STATUS,
193 ControlLoopEventManager2.PROV_STATUS_ACTIVE.toLowerCase()));
194 assertThatCode(() -> new ControlLoopEventManager2Drools(params, event, workMem)).doesNotThrowAnyException();
197 event.setAai(addAai(orig, ControlLoopEventManager2.VSERVER_PROV_STATUS, "inactive"));
198 assertThatThrownBy(() -> new ControlLoopEventManager2Drools(params, event, workMem))
199 .hasMessage("prov-status is not ACTIVE on VServer or VNF");
202 event.setAai(addAai(orig, ControlLoopEventManager2.GENERIC_VNF_PROV_STATUS,
203 ControlLoopEventManager2.PROV_STATUS_ACTIVE.toUpperCase()));
204 assertThatCode(() -> new ControlLoopEventManager2Drools(params, event, workMem)).doesNotThrowAnyException();
207 event.setAai(addAai(orig, ControlLoopEventManager2.GENERIC_VNF_PROV_STATUS,
208 ControlLoopEventManager2.PROV_STATUS_ACTIVE.toLowerCase()));
209 assertThatCode(() -> new ControlLoopEventManager2Drools(params, event, workMem)).doesNotThrowAnyException();
212 event.setAai(addAai(orig, ControlLoopEventManager2.GENERIC_VNF_PROV_STATUS, "inactive"));
213 assertThatThrownBy(() -> new ControlLoopEventManager2Drools(params, event, workMem))
214 .hasMessage("prov-status is not ACTIVE on VServer or VNF");
218 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
221 event.setTarget("unknown-target");
222 assertThatThrownBy(() -> new ControlLoopEventManager2Drools(params, event, workMem))
223 .isInstanceOf(ControlLoopException.class);
227 * Runs through a policy that has several operations.
230 public void testMultiOperation() throws Exception {
232 loadPolicy("eventManager/event-mgr-multi.yaml");
234 mgr = new MyManagerWithOper(params, event, workMem);
237 for (ControlLoopOperationManager2 oper : Arrays.asList(oper1, oper2, oper3)) {
238 assertTrue(mgr.isActive());
239 nextStep(oper, true, OperationResult.SUCCESS);
242 assertTrue(mgr.isActive());
243 nextStep(oper, false, OperationResult.SUCCESS);
247 assertFalse(mgr.isActive());
251 public void testStart() throws Exception {
256 assertThatCode(() -> mgr.start()).isInstanceOf(IllegalStateException.class)
257 .hasMessage("manager already started");
261 * Tests start() error cases.
264 public void testStartErrors() throws Exception {
266 ControlLoopEventManager2Drools mgr2 = new ControlLoopEventManager2Drools(params, event, workMem);
267 ControlLoopEventManager2Drools mgr3 = Serializer.roundTrip(mgr2);
268 assertThatCode(() -> mgr3.start()).isInstanceOf(IllegalStateException.class)
269 .hasMessage("manager is no longer active");
272 when(workMem.getFactHandle(any())).thenReturn(null);
273 assertThatCode(() -> mgr.start()).isInstanceOf(IllegalStateException.class)
274 .hasMessage("manager is not in working memory");
278 public void testNextStep_testStartOperationSuccess() throws ControlLoopException {
279 runOperation(OperationResult.SUCCESS);
281 VirtualControlLoopNotification notif = mgr.getNotification();
282 assertEquals(ControlLoopNotificationType.FINAL_SUCCESS, notif.getNotification());
283 assertNull(notif.getMessage());
285 assertThatCode(() -> mgr.nextStep()).doesNotThrowAnyException();
289 * Tests nextStep() when the next step is invalid, which should cause an exception to
290 * be thrown by the processor.
293 public void testNextStepMissing() throws Exception {
296 when(oper1.nextStep()).thenThrow(new IllegalArgumentException("expected exception"));
300 assertFalse(mgr.isActive());
302 VirtualControlLoopNotification notif = mgr.getNotification();
303 assertEquals(ControlLoopNotificationType.FINAL_FAILURE, notif.getNotification());
304 assertEquals("Policy processing aborted due to policy error", notif.getMessage());
305 assertTrue(notif.getHistory().isEmpty());
309 * Tests startOperation() with FINAL_FAILURE_EXCEPTION.
312 public void testStartOperationException() throws ControlLoopException {
313 runOperation(OperationResult.FAILURE_EXCEPTION);
315 VirtualControlLoopNotification notif = mgr.getNotification();
316 assertEquals(ControlLoopNotificationType.FINAL_FAILURE, notif.getNotification());
317 assertEquals("Exception in processing closed loop", notif.getMessage());
321 * Tests startOperation() with FINAL_FAILURE.
324 public void testStartOperationFailure() throws ControlLoopException {
325 runOperation(OperationResult.FAILURE);
327 VirtualControlLoopNotification notif = mgr.getNotification();
328 assertEquals(ControlLoopNotificationType.FINAL_FAILURE, notif.getNotification());
329 assertNull(notif.getMessage());
333 * Tests startOperation() with FINAL_OPENLOOP.
336 public void testStartOperationOpenLoop() throws ControlLoopException {
337 runOperation(OperationResult.FAILURE_GUARD);
339 VirtualControlLoopNotification notif = mgr.getNotification();
340 assertEquals(ControlLoopNotificationType.FINAL_OPENLOOP, notif.getNotification());
341 assertNull(notif.getMessage());
345 public void testIsActive() throws Exception {
346 mgr = new ControlLoopEventManager2Drools(params, event, workMem);
347 assertTrue(mgr.isActive());
349 ControlLoopEventManager2Drools mgr2 = Serializer.roundTrip(mgr);
350 assertFalse(mgr2.isActive());
354 public void testUpdated() throws ControlLoopException {
357 // not the active operation - should be ignored
359 verify(workMem, never()).update(any(), any());
361 VirtualControlLoopNotification notif;
363 // check notification data
364 when(oper1.getState()).thenReturn(State.LOCK_DENIED);
366 notif = mgr.getNotification();
367 assertNotNull(notif.getHistory());
370 * try the various cases
372 when(oper1.getState()).thenReturn(State.LOCK_DENIED);
374 verifyNotification(ControlLoopNotificationType.REJECTED, "The target my-target is already locked");
376 when(oper1.getState()).thenReturn(State.LOCK_LOST);
378 verifyNotification(ControlLoopNotificationType.OPERATION_FAILURE, "The target my-target is no longer locked");
380 when(oper1.getState()).thenReturn(State.GUARD_STARTED);
382 verifyNotification(ControlLoopNotificationType.OPERATION, "Sending guard query for First OperationA");
384 when(oper1.getState()).thenReturn(State.GUARD_PERMITTED);
386 verifyNotification(ControlLoopNotificationType.OPERATION, "Guard result for First OperationA is Permit");
388 when(oper1.getState()).thenReturn(State.GUARD_DENIED);
390 verifyNotification(ControlLoopNotificationType.OPERATION, "Guard result for First OperationA is Deny");
392 when(oper1.getState()).thenReturn(State.OPERATION_STARTED);
394 verifyNotification(ControlLoopNotificationType.OPERATION, "message-A");
396 when(oper1.getState()).thenReturn(State.OPERATION_SUCCESS);
398 verifyNotification(ControlLoopNotificationType.OPERATION_SUCCESS, "history-A");
400 when(oper1.getState()).thenReturn(State.OPERATION_FAILURE);
402 verifyNotification(ControlLoopNotificationType.OPERATION_FAILURE, "history-A");
404 // should still be active
405 assertTrue(mgr.isActive());
410 when(oper1.getState()).thenReturn(State.CONTROL_LOOP_TIMEOUT);
412 verifyNotification(ControlLoopNotificationType.FINAL_FAILURE, "Control Loop timed out");
414 // should now be done
415 assertFalse(mgr.isActive());
419 public void testDestroy() {
420 mgr.requestLock(LOCK1, callback1);
421 mgr.requestLock(LOCK2, callback2);
422 mgr.requestLock(LOCK1, callback3);
428 for (LockImpl lock : locks) {
429 assertTrue(lock.isUnavailable());
434 * Tests destroy() once it has been started.
437 public void testDestroyStarted() throws ControlLoopException {
440 mgr.requestLock(LOCK1, callback1);
441 mgr.requestLock(LOCK2, callback2);
442 mgr.requestLock(LOCK1, callback3);
448 // should have canceled the operation
449 verify(oper1).cancel();
451 for (LockImpl lock : locks) {
452 assertTrue(lock.isUnavailable());
457 public void testMakeNotification() throws ControlLoopException {
459 assertNotNull(mgr.makeNotification());
463 nextStep(oper1, true, OperationResult.SUCCESS);
466 // check notification while running
467 VirtualControlLoopNotification notif = mgr.getNotification();
468 assertEquals("history-A", notif.getMessage());
470 List<ControlLoopOperation> history = notif.getHistory();
471 assertNotNull(history);
473 nextStep(oper1, false, OperationResult.SUCCESS);
476 assertFalse(mgr.isActive());
478 // check notification when complete
479 notif = mgr.getNotification();
480 assertNull(notif.getMessage());
481 assertEquals(history, notif.getHistory());
485 public void testOnNewEvent() {
486 VirtualControlLoopEvent event2 = new VirtualControlLoopEvent(event);
487 assertEquals(NewEventStatus.FIRST_ONSET, mgr.onNewEvent(event2));
489 event2.setPayload("other payload");
490 assertEquals(NewEventStatus.SUBSEQUENT_ONSET, mgr.onNewEvent(event2));
491 assertEquals(NewEventStatus.SUBSEQUENT_ONSET, mgr.onNewEvent(event2));
492 assertEquals(NewEventStatus.FIRST_ONSET, mgr.onNewEvent(event));
494 event2.setClosedLoopEventStatus(ControlLoopEventStatus.ABATED);
495 assertEquals(NewEventStatus.FIRST_ABATEMENT, mgr.onNewEvent(event2));
497 assertEquals(NewEventStatus.SUBSEQUENT_ABATEMENT, mgr.onNewEvent(event2));
498 assertEquals(NewEventStatus.SUBSEQUENT_ABATEMENT, mgr.onNewEvent(event2));
500 event2.setClosedLoopEventStatus(null);
501 assertEquals(NewEventStatus.SYNTAX_ERROR, mgr.onNewEvent(event2));
505 public void testDetmControlLoopTimeoutMs() throws Exception {
506 verifyTimeout(1200 * 1000L);
509 private void verifyTimeout(long timeMs) {
510 long end = mgr.getEndTimeMs();
511 assertTrue(end >= preCreateTimeMs + timeMs);
512 assertTrue(end < preCreateTimeMs + timeMs + 5000);
516 public void testCheckEventSyntax() {
517 // initially, it's valid
518 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
520 event.setTarget("unknown-target");
521 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class)
522 .hasMessage("target field invalid");
524 event.setTarget(null);
525 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class)
526 .hasMessage("No target field");
528 // abated supersedes previous errors - so it shouldn't throw an exception
529 event.setClosedLoopEventStatus(ControlLoopEventStatus.ABATED);
530 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
532 event.setRequestId(null);
533 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class)
534 .hasMessage("No request ID");
536 event.setClosedLoopControlName(null);
537 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class)
538 .hasMessage("No control loop name");
542 public void testValidateStatus() {
543 event.setClosedLoopEventStatus(ControlLoopEventStatus.ONSET);
544 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
546 event.setClosedLoopEventStatus(ControlLoopEventStatus.ABATED);
547 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
549 event.setClosedLoopEventStatus(null);
550 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class)
551 .hasMessage("Invalid value in closedLoopEventStatus");
555 public void testValidateAaiData() {
556 event.setTargetType("unknown-target-type");
557 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class)
558 .hasMessage("The target type is not supported");
560 event.setTargetType(null);
561 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class)
562 .hasMessage("The Target type is null");
565 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class)
566 .hasMessage("AAI is null");
569 event.setTargetType(ControlLoopTargetType.VM);
570 event.setAai(Map.of(ControlLoopEventManager2.GENERIC_VNF_VNF_ID, MY_TARGET));
571 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
573 event.setAai(Map.of());
574 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class);
577 event.setTargetType(ControlLoopTargetType.VNF);
578 event.setAai(Map.of(ControlLoopEventManager2.GENERIC_VNF_VNF_ID, MY_TARGET));
579 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
581 event.setAai(Map.of());
582 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class);
585 event.setTargetType(ControlLoopTargetType.PNF);
586 event.setAai(Map.of(ControlLoopEventManager2.PNF_NAME, MY_TARGET));
587 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
589 event.setAai(Map.of());
590 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class);
594 public void testValidateAaiVmVnfData() {
595 event.setTargetType(ControlLoopTargetType.VM);
596 event.setAai(Map.of(ControlLoopEventManager2.GENERIC_VNF_VNF_ID, MY_TARGET));
597 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
599 event.setAai(Map.of(ControlLoopEventManager2.VSERVER_VSERVER_NAME, MY_TARGET));
600 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
602 event.setAai(Map.of(ControlLoopEventManager2.GENERIC_VNF_VNF_NAME, MY_TARGET));
603 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
605 event.setAai(Map.of());
606 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class).hasMessage(
607 "generic-vnf.vnf-id or generic-vnf.vnf-name or vserver.vserver-name information missing");
611 public void testValidateAaiPnfData() {
612 event.setTargetType(ControlLoopTargetType.PNF);
613 event.setAai(Map.of(ControlLoopEventManager2.PNF_NAME, MY_TARGET));
614 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
616 event.setAai(Map.of());
617 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class)
618 .hasMessage("AAI PNF object key pnf-name is missing");
622 public void testIsClosedLoopDisabled() {
623 Map<String, String> orig = event.getAai();
625 event.setAai(addAai(orig, ControlLoopEventManager2.VSERVER_IS_CLOSED_LOOP_DISABLED, "true"));
626 assertThatThrownBy(() -> new ControlLoopEventManager2Drools(params, event, workMem))
627 .isInstanceOf(IllegalStateException.class);
629 event.setAai(addAai(orig, ControlLoopEventManager2.GENERIC_VNF_IS_CLOSED_LOOP_DISABLED, "true"));
630 assertThatThrownBy(() -> new ControlLoopEventManager2Drools(params, event, workMem))
631 .isInstanceOf(IllegalStateException.class);
633 event.setAai(addAai(orig, ControlLoopEventManager2.PNF_IS_IN_MAINT, "true"));
634 assertThatThrownBy(() -> new ControlLoopEventManager2Drools(params, event, workMem))
635 .isInstanceOf(IllegalStateException.class);
638 private Map<String, String> addAai(Map<String, String> original, String key, String value) {
639 Map<String, String> map = new TreeMap<>(original);
645 public void testIsProvStatusInactive() {
646 Map<String, String> orig = event.getAai();
648 event.setAai(addAai(orig, ControlLoopEventManager2.VSERVER_PROV_STATUS, "ACTIVE"));
649 assertThatCode(() -> new ControlLoopEventManager2Drools(params, event, workMem)).doesNotThrowAnyException();
651 event.setAai(addAai(orig, ControlLoopEventManager2.VSERVER_PROV_STATUS, "inactive"));
652 assertThatThrownBy(() -> new ControlLoopEventManager2Drools(params, event, workMem))
653 .isInstanceOf(IllegalStateException.class);
655 event.setAai(addAai(orig, ControlLoopEventManager2.GENERIC_VNF_PROV_STATUS, "ACTIVE"));
656 assertThatCode(() -> new ControlLoopEventManager2Drools(params, event, workMem)).doesNotThrowAnyException();
657 event.setAai(addAai(orig, ControlLoopEventManager2.GENERIC_VNF_PROV_STATUS, "inactive"));
658 assertThatThrownBy(() -> new ControlLoopEventManager2Drools(params, event, workMem))
659 .isInstanceOf(IllegalStateException.class);
663 public void testIsAaiTrue() {
664 Map<String, String> orig = event.getAai();
666 for (String value : Arrays.asList("yes", "y", "true", "t", "yEs", "trUe")) {
667 event.setAai(addAai(orig, ControlLoopEventManager2.VSERVER_IS_CLOSED_LOOP_DISABLED, value));
668 assertThatThrownBy(() -> new ControlLoopEventManager2Drools(params, event, workMem))
669 .isInstanceOf(IllegalStateException.class);
672 event.setAai(addAai(orig, ControlLoopEventManager2.VSERVER_IS_CLOSED_LOOP_DISABLED, "false"));
673 assertThatCode(() -> new ControlLoopEventManager2Drools(params, event, workMem)).doesNotThrowAnyException();
675 event.setAai(addAai(orig, ControlLoopEventManager2.VSERVER_IS_CLOSED_LOOP_DISABLED, "no"));
676 assertThatCode(() -> new ControlLoopEventManager2Drools(params, event, workMem)).doesNotThrowAnyException();
680 public void testRequestLock() {
681 final CompletableFuture<OperationOutcome> future1 = mgr.requestLock(LOCK1, callback1);
682 final CompletableFuture<OperationOutcome> future2 = mgr.requestLock(LOCK2, callback2);
683 assertSame(future1, mgr.requestLock(LOCK1, callback3));
685 assertEquals(2, locks.size());
687 assertTrue(future1.isDone());
688 assertTrue(future2.isDone());
690 verify(callback1, never()).accept(any());
691 verify(callback2, never()).accept(any());
692 verify(callback3, never()).accept(any());
694 // indicate that the first lock failed
695 locks.get(0).notifyUnavailable();
697 verify(callback1).accept(any());
698 verify(callback2, never()).accept(any());
699 verify(callback3).accept(any());
703 public void testMakeOperationManager() throws ControlLoopException {
704 // use a manager that creates real operation managers
705 mgr = new MyManager(params, event, workMem);
707 assertThatCode(() -> mgr.start()).doesNotThrowAnyException();
711 public void testGetBlockingExecutor() throws Exception {
712 mgr = new ControlLoopEventManager2Drools(params, event, workMem);
713 assertThatCode(() -> mgr.getBlockingExecutor()).doesNotThrowAnyException();
717 public void testToString() {
718 assertNotNull(mgr.toString());
722 private void nextStep(ControlLoopOperationManager2 oper, boolean moreSteps, OperationResult result) {
723 when(oper.nextStep()).thenReturn(moreSteps);
724 when(oper.getOperationResult()).thenReturn(result);
726 if (result == OperationResult.SUCCESS) {
727 when(oper.getState()).thenReturn(State.OPERATION_SUCCESS);
729 when(oper.getState()).thenReturn(State.OPERATION_FAILURE);
736 verify(workMem, times(updateCount)).update(factHandle, mgr);
739 private void runRule() {
740 assertTrue(mgr.isActive());
744 private void runOperation(OperationResult finalResult) throws ControlLoopException {
746 verify(oper1).start(anyLong());
748 assertTrue(mgr.isActive());
750 nextStep(oper1, true, OperationResult.SUCCESS);
753 nextStep(oper1, false, finalResult);
756 assertFalse(mgr.isActive());
758 // should have no effect, because it's done
760 verify(workMem, times(updateCount)).update(any(), any());
763 private void verifyNotification(ControlLoopNotificationType expectedType, String expectedMsg) {
764 VirtualControlLoopNotification notif = mgr.getNotification();
765 assertEquals(expectedType, notif.getNotification());
766 assertEquals(expectedMsg, notif.getMessage());
769 private List<ControlLoopOperation> makeHistory(String message) {
770 ControlLoopOperation clo = new ControlLoopOperation();
771 clo.setMessage("history-" + message);
776 private void loadPolicy(String fileName) throws CoderException {
777 ToscaServiceTemplate template =
778 yamlCoder.decode(ResourceUtils.getResourceAsString(fileName), ToscaServiceTemplate.class);
779 tosca = template.getToscaTopologyTemplate().getPolicies().get(0).values().iterator().next();
781 params.setToscaPolicy(tosca);
784 private void freeLocks() {
785 ArgumentCaptor<Runnable> runCaptor = ArgumentCaptor.forClass(Runnable.class);
786 verify(executor).execute(runCaptor.capture());
788 runCaptor.getValue().run();
792 private class MyManager extends ControlLoopEventManager2Drools {
793 private static final long serialVersionUID = 1L;
795 public MyManager(ControlLoopParams params, VirtualControlLoopEvent event, WorkingMemory workMem)
796 throws ControlLoopException {
798 super(params, event, workMem);
802 protected ExecutorService getBlockingExecutor() {
807 protected void makeLock(String targetEntity, String requestId, int holdSec, LockCallback callback) {
808 LockImpl lock = new LockImpl(LockState.ACTIVE, targetEntity, requestId, holdSec, callback);
810 callback.lockAvailable(lock);
814 public ActorService getActorService() {
819 public OperationHistoryDataManager getDataManager() {
825 private class MyManagerWithOper extends MyManager {
826 private static final long serialVersionUID = 1L;
828 public MyManagerWithOper(ControlLoopParams params, VirtualControlLoopEvent event, WorkingMemory workMem)
829 throws ControlLoopException {
831 super(params, event, workMem);
835 protected ControlLoopOperationManager2 makeOperationManager(ControlLoopEventContext ctx, Operation policy) {
836 switch (policy.getActorOperation().getActor()) {
844 throw new IllegalArgumentException("unknown policy actor " + policy.getActorOperation().getActor());