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.junit.rules.ExpectedException;
51 import org.kie.api.runtime.rule.FactHandle;
52 import org.mockito.ArgumentCaptor;
53 import org.mockito.Mock;
54 import org.mockito.MockitoAnnotations;
55 import org.onap.policy.common.utils.coder.Coder;
56 import org.onap.policy.common.utils.coder.CoderException;
57 import org.onap.policy.common.utils.coder.StandardYamlCoder;
58 import org.onap.policy.common.utils.io.Serializer;
59 import org.onap.policy.common.utils.resources.ResourceUtils;
60 import org.onap.policy.controlloop.ControlLoopEventStatus;
61 import org.onap.policy.controlloop.ControlLoopException;
62 import org.onap.policy.controlloop.ControlLoopNotificationType;
63 import org.onap.policy.controlloop.ControlLoopOperation;
64 import org.onap.policy.controlloop.ControlLoopTargetType;
65 import org.onap.policy.controlloop.VirtualControlLoopEvent;
66 import org.onap.policy.controlloop.VirtualControlLoopNotification;
67 import org.onap.policy.controlloop.actorserviceprovider.ActorService;
68 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
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.controlloop.policy.Policy;
75 import org.onap.policy.controlloop.policy.PolicyResult;
76 import org.onap.policy.controlloop.policy.Target;
77 import org.onap.policy.controlloop.policy.TargetType;
78 import org.onap.policy.drools.core.lock.LockCallback;
79 import org.onap.policy.drools.core.lock.LockImpl;
80 import org.onap.policy.drools.core.lock.LockState;
81 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
82 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
84 public class ControlLoopEventManager2Test {
85 private static final UUID REQ_ID = UUID.randomUUID();
86 private static final String CL_NAME = "my-closed-loop-name";
87 private static final String POLICY_NAME = "my-policy-name";
88 private static final String POLICY_SCOPE = "my-scope";
89 private static final String POLICY_VERSION = "1.2.3";
90 private static final String MY_TARGET = "my-target";
91 private static final String LOCK1 = "my-lock-A";
92 private static final String LOCK2 = "my-lock-B";
93 private static final Coder yamlCoder = new StandardYamlCoder();
96 private WorkingMemory workMem;
98 private Consumer<OperationOutcome> callback1;
100 private Consumer<OperationOutcome> callback2;
102 private Consumer<OperationOutcome> callback3;
104 private FactHandle factHandle;
106 private ActorService actors;
108 private OperationHistoryDataManager dataMgr;
110 private ControlLoopOperationManager2 oper1;
112 private ControlLoopOperationManager2 oper2;
114 private ControlLoopOperationManager2 oper3;
116 private ExecutorService executor;
118 private long preCreateTimeMs;
119 private List<LockImpl> locks;
120 private Target target;
121 private ToscaPolicy tosca;
122 private ControlLoopParams params;
123 private VirtualControlLoopEvent event;
124 private int updateCount;
125 private ControlLoopEventManager2 mgr;
131 public void setUp() throws ControlLoopException, CoderException {
132 MockitoAnnotations.initMocks(this);
134 when(oper1.getHistory()).thenReturn(makeHistory("A"));
135 when(oper2.getHistory()).thenReturn(makeHistory("B"));
136 when(oper3.getHistory()).thenReturn(makeHistory("C"));
138 when(oper1.getActor()).thenReturn("First");
139 when(oper1.getOperation()).thenReturn("OperationA");
140 when(oper1.getOperationMessage()).thenReturn("message-A");
141 when(oper1.getOperationHistory()).thenReturn("history-A");
143 when(oper2.getActor()).thenReturn("Second");
144 when(oper2.getOperation()).thenReturn("OperationB");
145 when(oper2.getOperationMessage()).thenReturn("message-B");
146 when(oper2.getOperationHistory()).thenReturn("history-B");
148 when(oper3.getActor()).thenReturn("Third");
149 when(oper3.getOperation()).thenReturn("OperationC");
150 when(oper3.getOperationMessage()).thenReturn("message-C");
151 when(oper3.getOperationHistory()).thenReturn("history-C");
153 when(workMem.getFactHandle(any())).thenReturn(factHandle);
155 event = new VirtualControlLoopEvent();
156 event.setRequestId(REQ_ID);
157 event.setTarget(ControlLoopOperationManager2.VSERVER_VSERVER_NAME);
158 event.setAai(new TreeMap<>(Map.of(ControlLoopOperationManager2.VSERVER_VSERVER_NAME, MY_TARGET)));
159 event.setClosedLoopEventStatus(ControlLoopEventStatus.ONSET);
160 event.setClosedLoopControlName(CL_NAME);
161 event.setTargetType(TargetType.VNF.toString());
163 target = new Target();
164 target.setType(TargetType.VNF);
166 params = new ControlLoopParams();
167 params.setClosedLoopControlName(CL_NAME);
168 params.setPolicyName(POLICY_NAME);
169 params.setPolicyScope(POLICY_SCOPE);
170 params.setPolicyVersion(POLICY_VERSION);
172 loadPolicy("eventManager/event-mgr-simple.yaml");
174 locks = new ArrayList<>();
178 preCreateTimeMs = System.currentTimeMillis();
180 mgr = new MyManagerWithOper(params, event, workMem);
184 public void testConstructor() {
185 assertEquals(POLICY_NAME, mgr.getPolicyName());
187 Map<String, String> orig = event.getAai();
189 event.setAai(addAai(orig, ControlLoopEventManager2.VSERVER_IS_CLOSED_LOOP_DISABLED, "true"));
190 assertThatThrownBy(() -> new ControlLoopEventManager2(params, event, workMem))
191 .hasMessage("is-closed-loop-disabled is set to true on VServer or VNF");
193 event.setAai(addAai(orig, ControlLoopEventManager2.VSERVER_PROV_STATUS, "inactive"));
194 assertThatThrownBy(() -> new ControlLoopEventManager2(params, event, workMem))
195 .hasMessage("prov-status is not ACTIVE on VServer or VNF");
199 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
202 event.setTarget("unknown-target");
203 assertThatThrownBy(() -> new ControlLoopEventManager2(params, event, workMem))
204 .isInstanceOf(ControlLoopException.class);
208 * Runs through a policy that has several operations.
211 public void testMultiOperation() throws Exception {
213 loadPolicy("eventManager/event-mgr-multi.yaml");
215 mgr = new MyManagerWithOper(params, event, workMem);
218 for (ControlLoopOperationManager2 oper : Arrays.asList(oper1, oper2, oper3)) {
219 assertTrue(mgr.isActive());
220 nextStep(oper, true, PolicyResult.SUCCESS);
223 assertTrue(mgr.isActive());
224 nextStep(oper, false, PolicyResult.SUCCESS);
228 assertFalse(mgr.isActive());
232 public void testStart() throws Exception {
237 assertThatCode(() -> mgr.start()).isInstanceOf(IllegalStateException.class)
238 .hasMessage("manager already started");
242 * Tests start() error cases.
245 public void testStartErrors() throws Exception {
247 ControlLoopEventManager2 mgr2 = new ControlLoopEventManager2(params, event, workMem);
248 ControlLoopEventManager2 mgr3 = Serializer.roundTrip(mgr2);
249 assertThatCode(() -> mgr3.start()).isInstanceOf(IllegalStateException.class)
250 .hasMessage("manager is no longer active");
253 when(workMem.getFactHandle(any())).thenReturn(null);
254 assertThatCode(() -> mgr.start()).isInstanceOf(IllegalStateException.class)
255 .hasMessage("manager is not in working memory");
259 public void testNextStep_testStartOperationSuccess() throws ControlLoopException {
260 runOperation(PolicyResult.SUCCESS);
262 VirtualControlLoopNotification notif = mgr.getNotification();
263 assertEquals(ControlLoopNotificationType.FINAL_SUCCESS, notif.getNotification());
264 assertNull(notif.getMessage());
266 assertThatCode(() -> mgr.nextStep()).doesNotThrowAnyException();
270 * Tests nextStep() when the next step is invalid, which should cause an exception to
271 * be thrown by the processor.
274 public void testNextStepMissing() throws Exception {
277 when(oper1.nextStep()).thenThrow(new IllegalArgumentException("expected exception"));
281 assertFalse(mgr.isActive());
283 VirtualControlLoopNotification notif = mgr.getNotification();
284 assertEquals(ControlLoopNotificationType.FINAL_FAILURE, notif.getNotification());
285 assertEquals("Policy processing aborted due to policy error", notif.getMessage());
286 assertTrue(notif.getHistory().isEmpty());
290 * Tests startOperation() with FINAL_FAILURE_EXCEPTION.
293 public void testStartOperationException() throws ControlLoopException {
294 runOperation(PolicyResult.FAILURE_EXCEPTION);
296 VirtualControlLoopNotification notif = mgr.getNotification();
297 assertEquals(ControlLoopNotificationType.FINAL_FAILURE, notif.getNotification());
298 assertEquals("Exception in processing closed loop", notif.getMessage());
302 * Tests startOperation() with FINAL_FAILURE.
305 public void testStartOperationFailure() throws ControlLoopException {
306 runOperation(PolicyResult.FAILURE);
308 VirtualControlLoopNotification notif = mgr.getNotification();
309 assertEquals(ControlLoopNotificationType.FINAL_FAILURE, notif.getNotification());
310 assertNull(notif.getMessage());
314 * Tests startOperation() with FINAL_OPENLOOP.
317 public void testStartOperationOpenLoop() throws ControlLoopException {
318 runOperation(PolicyResult.FAILURE_GUARD);
320 VirtualControlLoopNotification notif = mgr.getNotification();
321 assertEquals(ControlLoopNotificationType.FINAL_OPENLOOP, notif.getNotification());
322 assertNull(notif.getMessage());
326 public void testIsActive() throws Exception {
327 mgr = new ControlLoopEventManager2(params, event, workMem);
328 assertTrue(mgr.isActive());
330 ControlLoopEventManager2 mgr2 = Serializer.roundTrip(mgr);
331 assertFalse(mgr2.isActive());
335 public void testUpdated() throws ControlLoopException {
338 // not the active operation - should be ignored
340 verify(workMem, never()).update(any(), any());
342 VirtualControlLoopNotification notif;
344 // check notification data
345 when(oper1.getState()).thenReturn(State.LOCK_DENIED);
347 notif = mgr.getNotification();
348 assertNotNull(notif.getHistory());
351 * try the various cases
353 when(oper1.getState()).thenReturn(State.LOCK_DENIED);
355 verifyNotification(ControlLoopNotificationType.REJECTED, "The target my-target is already locked");
357 when(oper1.getState()).thenReturn(State.LOCK_LOST);
359 verifyNotification(ControlLoopNotificationType.OPERATION_FAILURE, "The target my-target is no longer locked");
361 when(oper1.getState()).thenReturn(State.GUARD_STARTED);
363 verifyNotification(ControlLoopNotificationType.OPERATION, "Sending guard query for First OperationA");
365 when(oper1.getState()).thenReturn(State.GUARD_PERMITTED);
367 verifyNotification(ControlLoopNotificationType.OPERATION, "Guard result for First OperationA is Permit");
369 when(oper1.getState()).thenReturn(State.GUARD_DENIED);
371 verifyNotification(ControlLoopNotificationType.OPERATION, "Guard result for First OperationA is Deny");
373 when(oper1.getState()).thenReturn(State.OPERATION_STARTED);
375 verifyNotification(ControlLoopNotificationType.OPERATION, "message-A");
377 when(oper1.getState()).thenReturn(State.OPERATION_SUCCESS);
379 verifyNotification(ControlLoopNotificationType.OPERATION_SUCCESS, "history-A");
381 when(oper1.getState()).thenReturn(State.OPERATION_FAILURE);
383 verifyNotification(ControlLoopNotificationType.OPERATION_FAILURE, "history-A");
385 // should still be active
386 assertTrue(mgr.isActive());
391 when(oper1.getState()).thenReturn(State.CONTROL_LOOP_TIMEOUT);
393 verifyNotification(ControlLoopNotificationType.FINAL_FAILURE, "Control Loop timed out");
395 // should now be done
396 assertFalse(mgr.isActive());
400 public void testDestroy() {
401 mgr.requestLock(LOCK1, callback1);
402 mgr.requestLock(LOCK2, callback2);
403 mgr.requestLock(LOCK1, callback3);
409 for (LockImpl lock : locks) {
410 assertTrue(lock.isUnavailable());
415 * Tests destroy() once it has been started.
418 public void testDestroyStarted() throws ControlLoopException {
421 mgr.requestLock(LOCK1, callback1);
422 mgr.requestLock(LOCK2, callback2);
423 mgr.requestLock(LOCK1, callback3);
429 // should have canceled the operation
430 verify(oper1).cancel();
432 for (LockImpl lock : locks) {
433 assertTrue(lock.isUnavailable());
438 public void testMakeNotification() throws ControlLoopException {
440 assertNotNull(mgr.makeNotification());
444 nextStep(oper1, true, PolicyResult.SUCCESS);
447 // check notification while running
448 VirtualControlLoopNotification notif = mgr.getNotification();
449 assertEquals("history-A", notif.getMessage());
451 List<ControlLoopOperation> history = notif.getHistory();
452 assertNotNull(history);
454 nextStep(oper1, false, PolicyResult.SUCCESS);
457 assertFalse(mgr.isActive());
459 // check notification when complete
460 notif = mgr.getNotification();
461 assertNull(notif.getMessage());
462 assertEquals(history, notif.getHistory());
466 public void testOnNewEvent() {
467 VirtualControlLoopEvent event2 = new VirtualControlLoopEvent(event);
468 assertEquals(NewEventStatus.FIRST_ONSET, mgr.onNewEvent(event2));
470 event2.setPayload("other payload");
471 assertEquals(NewEventStatus.SUBSEQUENT_ONSET, mgr.onNewEvent(event2));
472 assertEquals(NewEventStatus.SUBSEQUENT_ONSET, mgr.onNewEvent(event2));
473 assertEquals(NewEventStatus.FIRST_ONSET, mgr.onNewEvent(event));
475 event2.setClosedLoopEventStatus(ControlLoopEventStatus.ABATED);
476 assertEquals(NewEventStatus.FIRST_ABATEMENT, mgr.onNewEvent(event2));
478 assertEquals(NewEventStatus.SUBSEQUENT_ABATEMENT, mgr.onNewEvent(event2));
479 assertEquals(NewEventStatus.SUBSEQUENT_ABATEMENT, mgr.onNewEvent(event2));
481 event2.setClosedLoopEventStatus(null);
482 assertEquals(NewEventStatus.SYNTAX_ERROR, mgr.onNewEvent(event2));
486 public void testDetmControlLoopTimeoutMs() throws Exception {
487 verifyTimeout(1200 * 1000L);
490 private void verifyTimeout(long timeMs) {
491 long end = mgr.getEndTimeMs();
492 assertTrue(end >= preCreateTimeMs + timeMs);
493 assertTrue(end < preCreateTimeMs + timeMs + 5000);
497 public void testCheckEventSyntax() {
498 // initially, it's valid
499 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
501 event.setTarget("unknown-target");
502 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class)
503 .hasMessage("target field invalid");
505 event.setTarget(null);
506 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class)
507 .hasMessage("No target field");
509 // abated supersedes previous errors - so it shouldn't throw an exception
510 event.setClosedLoopEventStatus(ControlLoopEventStatus.ABATED);
511 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
513 event.setRequestId(null);
514 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class)
515 .hasMessage("No request ID");
517 event.setClosedLoopControlName(null);
518 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class)
519 .hasMessage("No control loop name");
523 public void testValidateStatus() {
524 event.setClosedLoopEventStatus(ControlLoopEventStatus.ONSET);
525 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
527 event.setClosedLoopEventStatus(ControlLoopEventStatus.ABATED);
528 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
530 event.setClosedLoopEventStatus(null);
531 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class)
532 .hasMessage("Invalid value in closedLoopEventStatus");
536 public void testValidateAaiData() {
537 event.setTargetType("unknown-target-type");
538 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class)
539 .hasMessage("The target type is not supported");
541 event.setTargetType(null);
542 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class)
543 .hasMessage("The Target type is null");
546 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class)
547 .hasMessage("AAI is null");
550 event.setTargetType(ControlLoopTargetType.VM);
551 event.setAai(Map.of(ControlLoopEventManager2.GENERIC_VNF_VNF_ID, MY_TARGET));
552 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
554 event.setAai(Map.of());
555 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class);
558 event.setTargetType(ControlLoopTargetType.VNF);
559 event.setAai(Map.of(ControlLoopEventManager2.GENERIC_VNF_VNF_ID, MY_TARGET));
560 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
562 event.setAai(Map.of());
563 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class);
566 event.setTargetType(ControlLoopTargetType.PNF);
567 event.setAai(Map.of(ControlLoopEventManager2.PNF_NAME, MY_TARGET));
568 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
570 event.setAai(Map.of());
571 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class);
575 public void testValidateAaiVmVnfData() {
576 event.setTargetType(ControlLoopTargetType.VM);
577 event.setAai(Map.of(ControlLoopEventManager2.GENERIC_VNF_VNF_ID, MY_TARGET));
578 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
580 event.setAai(Map.of(ControlLoopEventManager2.VSERVER_VSERVER_NAME, MY_TARGET));
581 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
583 event.setAai(Map.of(ControlLoopEventManager2.GENERIC_VNF_VNF_NAME, MY_TARGET));
584 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
586 event.setAai(Map.of());
587 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class).hasMessage(
588 "generic-vnf.vnf-id or generic-vnf.vnf-name or vserver.vserver-name information missing");
592 public void testValidateAaiPnfData() {
593 event.setTargetType(ControlLoopTargetType.PNF);
594 event.setAai(Map.of(ControlLoopEventManager2.PNF_NAME, MY_TARGET));
595 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
597 event.setAai(Map.of());
598 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class)
599 .hasMessage("AAI PNF object key pnf-name is missing");
603 public void testIsClosedLoopDisabled() {
604 Map<String, String> orig = event.getAai();
606 event.setAai(addAai(orig, ControlLoopEventManager2.VSERVER_IS_CLOSED_LOOP_DISABLED, "true"));
607 assertThatThrownBy(() -> new ControlLoopEventManager2(params, event, workMem))
608 .isInstanceOf(IllegalStateException.class);
610 event.setAai(addAai(orig, ControlLoopEventManager2.GENERIC_VNF_IS_CLOSED_LOOP_DISABLED, "true"));
611 assertThatThrownBy(() -> new ControlLoopEventManager2(params, event, workMem))
612 .isInstanceOf(IllegalStateException.class);
614 event.setAai(addAai(orig, ControlLoopEventManager2.PNF_IS_IN_MAINT, "true"));
615 assertThatThrownBy(() -> new ControlLoopEventManager2(params, event, workMem))
616 .isInstanceOf(IllegalStateException.class);
619 private Map<String, String> addAai(Map<String, String> original, String key, String value) {
620 Map<String, String> map = new TreeMap<>(original);
626 public void testIsProvStatusInactive() {
627 Map<String, String> orig = event.getAai();
629 event.setAai(addAai(orig, ControlLoopEventManager2.VSERVER_PROV_STATUS, "ACTIVE"));
630 assertThatCode(() -> new ControlLoopEventManager2(params, event, workMem)).doesNotThrowAnyException();
632 event.setAai(addAai(orig, ControlLoopEventManager2.VSERVER_PROV_STATUS, "inactive"));
633 assertThatThrownBy(() -> new ControlLoopEventManager2(params, event, workMem))
634 .isInstanceOf(IllegalStateException.class);
636 event.setAai(addAai(orig, ControlLoopEventManager2.GENERIC_VNF_PROV_STATUS, "ACTIVE"));
637 assertThatCode(() -> new ControlLoopEventManager2(params, event, workMem)).doesNotThrowAnyException();
639 event.setAai(addAai(orig, ControlLoopEventManager2.GENERIC_VNF_PROV_STATUS, "inactive"));
640 assertThatThrownBy(() -> new ControlLoopEventManager2(params, event, workMem))
641 .isInstanceOf(IllegalStateException.class);
645 public void testIsAaiTrue() {
646 Map<String, String> orig = event.getAai();
648 for (String value : Arrays.asList("yes", "y", "true", "t", "yEs", "trUe")) {
649 event.setAai(addAai(orig, ControlLoopEventManager2.VSERVER_IS_CLOSED_LOOP_DISABLED, value));
650 assertThatThrownBy(() -> new ControlLoopEventManager2(params, event, workMem))
651 .isInstanceOf(IllegalStateException.class);
654 event.setAai(addAai(orig, ControlLoopEventManager2.VSERVER_IS_CLOSED_LOOP_DISABLED, "false"));
655 assertThatCode(() -> new ControlLoopEventManager2(params, event, workMem)).doesNotThrowAnyException();
657 event.setAai(addAai(orig, ControlLoopEventManager2.VSERVER_IS_CLOSED_LOOP_DISABLED, "no"));
658 assertThatCode(() -> new ControlLoopEventManager2(params, event, workMem)).doesNotThrowAnyException();
662 public void testRequestLock() {
663 final CompletableFuture<OperationOutcome> future1 = mgr.requestLock(LOCK1, callback1);
664 final CompletableFuture<OperationOutcome> future2 = mgr.requestLock(LOCK2, callback2);
665 assertSame(future1, mgr.requestLock(LOCK1, callback3));
667 assertEquals(2, locks.size());
669 assertTrue(future1.isDone());
670 assertTrue(future2.isDone());
672 verify(callback1, never()).accept(any());
673 verify(callback2, never()).accept(any());
674 verify(callback3, never()).accept(any());
676 // indicate that the first lock failed
677 locks.get(0).notifyUnavailable();
679 verify(callback1).accept(any());
680 verify(callback2, never()).accept(any());
681 verify(callback3).accept(any());
685 public void testMakeOperationManager() throws ControlLoopException {
686 // use a manager that creates real operation managers
687 mgr = new MyManager(params, event, workMem);
689 assertThatCode(() -> mgr.start()).doesNotThrowAnyException();
693 public void testGetBlockingExecutor() throws Exception {
694 mgr = new ControlLoopEventManager2(params, event, workMem);
695 assertThatCode(() -> mgr.getBlockingExecutor()).doesNotThrowAnyException();
699 public void testToString() {
700 assertNotNull(mgr.toString());
704 private void nextStep(ControlLoopOperationManager2 oper, boolean moreSteps, PolicyResult result) {
705 when(oper.nextStep()).thenReturn(moreSteps);
706 when(oper.getOperationResult()).thenReturn(result);
708 if (result == PolicyResult.SUCCESS) {
709 when(oper.getState()).thenReturn(State.OPERATION_SUCCESS);
711 when(oper.getState()).thenReturn(State.OPERATION_FAILURE);
718 verify(workMem, times(updateCount)).update(factHandle, mgr);
721 private void runRule() {
722 assertTrue(mgr.isActive());
726 private void runOperation(PolicyResult finalResult) throws ControlLoopException {
728 verify(oper1).start(anyLong());
730 assertTrue(mgr.isActive());
732 nextStep(oper1, true, PolicyResult.SUCCESS);
735 nextStep(oper1, false, finalResult);
738 assertFalse(mgr.isActive());
740 // should have no effect, because it's done
742 verify(workMem, times(updateCount)).update(any(), any());
745 private void verifyNotification(ControlLoopNotificationType expectedType, String expectedMsg) {
746 VirtualControlLoopNotification notif = mgr.getNotification();
747 assertEquals(expectedType, notif.getNotification());
748 assertEquals(expectedMsg, notif.getMessage());
751 private List<ControlLoopOperation> makeHistory(String message) {
752 ControlLoopOperation clo = new ControlLoopOperation();
753 clo.setMessage("history-" + message);
758 private void loadPolicy(String fileName) throws CoderException {
759 ToscaServiceTemplate template =
760 yamlCoder.decode(ResourceUtils.getResourceAsString(fileName), ToscaServiceTemplate.class);
761 tosca = template.getToscaTopologyTemplate().getPolicies().get(0).values().iterator().next();
763 params.setToscaPolicy(tosca);
766 private void freeLocks() {
767 ArgumentCaptor<Runnable> runCaptor = ArgumentCaptor.forClass(Runnable.class);
768 verify(executor).execute(runCaptor.capture());
770 runCaptor.getValue().run();
774 private class MyManager extends ControlLoopEventManager2 {
775 private static final long serialVersionUID = 1L;
777 public MyManager(ControlLoopParams params, VirtualControlLoopEvent event, WorkingMemory workMem)
778 throws ControlLoopException {
780 super(params, event, workMem);
784 protected ExecutorService getBlockingExecutor() {
789 protected void makeLock(String targetEntity, String requestId, int holdSec, LockCallback callback) {
790 LockImpl lock = new LockImpl(LockState.ACTIVE, targetEntity, requestId, holdSec, callback);
792 callback.lockAvailable(lock);
796 public ActorService getActorService() {
801 public OperationHistoryDataManager getDataManager() {
807 private class MyManagerWithOper extends MyManager {
808 private static final long serialVersionUID = 1L;
810 public MyManagerWithOper(ControlLoopParams params, VirtualControlLoopEvent event, WorkingMemory workMem)
811 throws ControlLoopException {
813 super(params, event, workMem);
817 protected ControlLoopOperationManager2 makeOperationManager(ControlLoopEventContext ctx, Policy policy) {
818 switch (policy.getActor()) {
826 throw new IllegalArgumentException("unknown policy actor " + policy.getActor());