2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2020-2021, 2023 AT&T Intellectual Property. All rights reserved.
6 * Modifications Copyright (C) 2023-2024 Nordix Foundation.
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END=========================================================
22 package org.onap.policy.drools.apps.controller.usecases;
24 import static org.assertj.core.api.Assertions.assertThat;
25 import static org.assertj.core.api.Assertions.assertThatCode;
26 import static org.assertj.core.api.Assertions.assertThatThrownBy;
27 import static org.junit.jupiter.api.Assertions.assertEquals;
28 import static org.junit.jupiter.api.Assertions.assertFalse;
29 import static org.junit.jupiter.api.Assertions.assertNotNull;
30 import static org.junit.jupiter.api.Assertions.assertSame;
31 import static org.junit.jupiter.api.Assertions.assertTrue;
32 import static org.mockito.ArgumentMatchers.any;
33 import static org.mockito.Mockito.mock;
34 import static org.mockito.Mockito.verify;
35 import static org.mockito.Mockito.when;
37 import java.time.Instant;
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.ExecutorService;
45 import org.drools.core.WorkingMemory;
46 import org.drools.core.common.InternalFactHandle;
47 import org.junit.jupiter.api.BeforeEach;
48 import org.junit.jupiter.api.Test;
49 import org.onap.policy.common.utils.coder.Coder;
50 import org.onap.policy.common.utils.coder.CoderException;
51 import org.onap.policy.common.utils.coder.StandardYamlCoder;
52 import org.onap.policy.common.utils.resources.ResourceUtils;
53 import org.onap.policy.controlloop.ControlLoopEventStatus;
54 import org.onap.policy.controlloop.ControlLoopException;
55 import org.onap.policy.controlloop.ControlLoopTargetType;
56 import org.onap.policy.controlloop.VirtualControlLoopEvent;
57 import org.onap.policy.controlloop.actorserviceprovider.Operation;
58 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
59 import org.onap.policy.controlloop.actorserviceprovider.OperationProperties;
60 import org.onap.policy.controlloop.actorserviceprovider.OperationResult;
61 import org.onap.policy.controlloop.actorserviceprovider.Operator;
62 import org.onap.policy.controlloop.actorserviceprovider.TargetType;
63 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
64 import org.onap.policy.controlloop.actorserviceprovider.spi.Actor;
65 import org.onap.policy.controlloop.drl.legacy.ControlLoopParams;
66 import org.onap.policy.controlloop.eventmanager.ActorConstants;
67 import org.onap.policy.controlloop.eventmanager.EventManagerServices;
68 import org.onap.policy.controlloop.ophistory.OperationHistoryDataManager;
69 import org.onap.policy.drools.apps.controller.usecases.step.AaiCqStep2;
70 import org.onap.policy.drools.apps.controller.usecases.step.AaiGetPnfStep2;
71 import org.onap.policy.drools.apps.controller.usecases.step.AaiGetTenantStep2;
72 import org.onap.policy.drools.apps.controller.usecases.step.GetTargetEntityStep2;
73 import org.onap.policy.drools.apps.controller.usecases.step.GuardStep2;
74 import org.onap.policy.drools.apps.controller.usecases.step.Step2;
75 import org.onap.policy.drools.core.lock.LockCallback;
76 import org.onap.policy.drools.core.lock.LockImpl;
77 import org.onap.policy.drools.core.lock.LockState;
78 import org.onap.policy.drools.system.PolicyEngine;
79 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
80 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
81 import org.onap.policy.sdnr.PciBody;
82 import org.onap.policy.sdnr.PciMessage;
83 import org.onap.policy.sdnr.PciResponse;
85 class UsecasesEventManagerTest {
86 private static final UUID REQ_ID = UUID.randomUUID();
87 private static final String CL_NAME = "my-closed-loop-name";
88 private static final String POLICY_NAME = "my-policy-name";
89 private static final String POLICY_SCOPE = "my-scope";
90 private static final String POLICY_VERSION = "1.2.3";
91 private static final String SIMPLE_ACTOR = "First";
92 private static final String SIMPLE_OPERATION = "OperationA";
93 private static final String MY_TARGET = "my-target";
94 private static final String EVENT_MGR_SIMPLE_YAML =
95 "../eventmanager/src/test/resources/eventManager/event-mgr-simple.yaml";
96 private static final Coder yamlCoder = new StandardYamlCoder();
97 private static final String OUTCOME_MSG = "my outcome message";
99 private final PolicyEngine engineMgr = mock(PolicyEngine.class);
100 private final WorkingMemory workMem = mock(WorkingMemory.class);
101 private final InternalFactHandle factHandle = mock(InternalFactHandle.class);
102 private final Operator policyOperator = mock(Operator.class);
103 private final Operation policyOperation = mock(Operation.class);
104 private final Actor policyActor = mock(Actor.class);
105 private final EventManagerServices services = mock(EventManagerServices.class);
106 private final OperationHistoryDataManager dataMgr = mock(OperationHistoryDataManager.class);
107 private final ExecutorService executor = mock(ExecutorService.class);
108 private Step2 stepa = mock(Step2.class);
109 private final Step2 stepb = mock(Step2.class);
111 private List<LockImpl> locks;
112 private ToscaPolicy tosca;
113 private ControlLoopParams params;
114 private VirtualControlLoopEvent event;
115 private UsecasesEventManager mgr;
121 public void setUp() throws ControlLoopException, CoderException {
122 when(services.getDataManager()).thenReturn(dataMgr);
124 when(workMem.getFactHandle(any())).thenReturn(factHandle);
126 event = new VirtualControlLoopEvent();
127 event.setRequestId(REQ_ID);
128 event.setTarget(UsecasesConstants.VSERVER_VSERVER_NAME);
129 event.setAai(new TreeMap<>(Map.of(UsecasesConstants.VSERVER_VSERVER_NAME, MY_TARGET)));
130 event.setClosedLoopEventStatus(ControlLoopEventStatus.ONSET);
131 event.setClosedLoopControlName(CL_NAME);
132 event.setTargetType(ControlLoopTargetType.VNF);
134 params = new ControlLoopParams();
135 params.setClosedLoopControlName(CL_NAME);
136 params.setPolicyName(POLICY_NAME);
137 params.setPolicyScope(POLICY_SCOPE);
138 params.setPolicyVersion(POLICY_VERSION);
140 loadPolicy(EVENT_MGR_SIMPLE_YAML);
142 locks = new ArrayList<>();
144 mgr = new MyManager(services, params, event, workMem);
148 void testConstructor() {
149 assertEquals(POLICY_NAME, mgr.getPolicyName());
150 assertSame(event, mgr.getEvent());
152 var orig = event.getAai();
154 event.setAai(addAai(orig, UsecasesConstants.VSERVER_IS_CLOSED_LOOP_DISABLED, "true"));
155 assertThatThrownBy(() -> new UsecasesEventManager(services, params, event, workMem))
156 .hasMessage("is-closed-loop-disabled is set to true on VServer or VNF");
159 event.setAai(addAai(orig, UsecasesConstants.VSERVER_PROV_STATUS,
160 UsecasesConstants.PROV_STATUS_ACTIVE.toUpperCase()));
161 assertThatCode(() -> new UsecasesEventManager(services, params, event, workMem)).doesNotThrowAnyException();
164 event.setAai(addAai(orig, UsecasesConstants.VSERVER_PROV_STATUS,
165 UsecasesConstants.PROV_STATUS_ACTIVE.toLowerCase()));
166 assertThatCode(() -> new UsecasesEventManager(services, params, event, workMem)).doesNotThrowAnyException();
169 event.setAai(addAai(orig, UsecasesConstants.VSERVER_PROV_STATUS, "inactive"));
170 assertThatThrownBy(() -> new UsecasesEventManager(services, params, event, workMem))
171 .hasMessage("prov-status is not ACTIVE on VServer or VNF");
174 event.setAai(addAai(orig, UsecasesConstants.GENERIC_VNF_PROV_STATUS,
175 UsecasesConstants.PROV_STATUS_ACTIVE.toUpperCase()));
176 assertThatCode(() -> new UsecasesEventManager(services, params, event, workMem)).doesNotThrowAnyException();
179 event.setAai(addAai(orig, UsecasesConstants.GENERIC_VNF_PROV_STATUS,
180 UsecasesConstants.PROV_STATUS_ACTIVE.toLowerCase()));
181 assertThatCode(() -> new UsecasesEventManager(services, params, event, workMem)).doesNotThrowAnyException();
184 event.setAai(addAai(orig, UsecasesConstants.GENERIC_VNF_PROV_STATUS, "inactive"));
185 assertThatThrownBy(() -> new UsecasesEventManager(services, params, event, workMem))
186 .hasMessage("prov-status is not ACTIVE on VServer or VNF");
190 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
193 event.setTarget("unknown-target");
194 assertThatThrownBy(() -> new UsecasesEventManager(services, params, event, workMem))
195 .isInstanceOf(ControlLoopException.class);
199 void testLoadPreprocessorSteps() {
200 stepa = new Step2(mgr, ControlLoopOperationParams.builder().build(), event) {
202 public List<String> getPropertyNames() {
203 return List.of(OperationProperties.AAI_DEFAULT_CLOUD_REGION);
207 protected Operation buildOperation() {
208 return policyOperation;
212 mgr.getSteps().add(stepa);
213 mgr.getSteps().add(stepb);
215 mgr.loadPreprocessorSteps();
217 var steps = mgr.getSteps();
219 Step2 lockStep = steps.poll();
220 assertNotNull(lockStep);
221 assertEquals(ActorConstants.LOCK_ACTOR, lockStep.getActorName());
222 assertThat(steps.poll()).isInstanceOf(AaiCqStep2.class);
223 assertThat(steps.poll()).isInstanceOf(GuardStep2.class);
224 assertSame(stepa, steps.poll());
225 assertSame(stepb, steps.poll());
226 assertThat(steps).isEmpty();
230 * Tests loadPreprocessorSteps() when no additional steps are needed.
233 void testLoadPreprocessorStepsNothingToLoad() {
234 when(stepa.isPolicyStep()).thenReturn(false);
235 when(stepa.getPropertyNames()).thenReturn(List.of("unknown-property"));
237 var steps = mgr.getSteps();
242 mgr.loadPreprocessorSteps();
244 assertSame(stepa, steps.poll());
245 assertSame(stepb, steps.poll());
246 assertThat(steps).isEmpty();
250 * Tests loadPreprocessorSteps() when an A&AI custom query is needed.
253 void testLoadPreprocessorStepsCq() {
254 loadStepsWithProperties(OperationProperties.AAI_DEFAULT_CLOUD_REGION, OperationProperties.AAI_DEFAULT_TENANT);
257 mgr.loadPreprocessorSteps();
259 var steps = mgr.getSteps();
261 assertThat(steps.poll()).isInstanceOf(AaiCqStep2.class);
262 assertSame(stepa, steps.poll());
263 assertSame(stepb, steps.poll());
264 assertThat(steps).isEmpty();
268 * Tests loadPreprocessorSteps() when an A&AI PNF query is needed.
271 void testLoadPreprocessorStepsPnf() {
272 // doubling up the property to check both branches
273 loadStepsWithProperties(OperationProperties.AAI_PNF, OperationProperties.AAI_PNF);
276 mgr.loadPreprocessorSteps();
278 var steps = mgr.getSteps();
280 assertThat(steps.poll()).isInstanceOf(AaiGetPnfStep2.class);
281 assertSame(stepa, steps.poll());
282 assertSame(stepb, steps.poll());
283 assertThat(steps).isEmpty();
287 * Tests loadPreprocessorSteps() when an A&AI Tenant query is needed.
290 void testLoadPreprocessorStepsTenant() {
291 // doubling up the property to check both branches
292 event.getAai().put(Step2.VSERVER_VSERVER_NAME, "my-vserver");
293 loadStepsWithProperties(OperationProperties.AAI_VSERVER_LINK, OperationProperties.AAI_VSERVER_LINK);
296 mgr.loadPreprocessorSteps();
298 var steps = mgr.getSteps();
300 assertThat(steps.poll()).isInstanceOf(AaiGetTenantStep2.class);
301 assertSame(stepa, steps.poll());
302 assertSame(stepb, steps.poll());
303 assertThat(steps).isEmpty();
307 * Tests loadPreprocessorSteps() when the target entity is unset.
310 void testLoadPreprocessorStepsNeedTargetEntity() {
311 stepa = new Step2(mgr, ControlLoopOperationParams.builder()
312 .targetType(TargetType.toTargetType(event.getTargetType())).targetEntityIds(Map.of()).build(),
315 public List<String> getPropertyNames() {
316 return List.of(OperationProperties.AAI_TARGET_ENTITY);
320 protected Operation buildOperation() {
321 return policyOperation;
325 public boolean isPolicyStep() {
330 var steps = mgr.getSteps();
334 mgr.loadPreprocessorSteps();
336 Step2 entityStep = steps.poll();
338 assertThat(entityStep).isInstanceOf(GetTargetEntityStep2.class);
339 assertSame(stepa, steps.poll());
340 assertSame(stepb, steps.poll());
341 assertThat(steps).isEmpty();
343 // put get-target-entity back onto the queue and ensure nothing else is added
344 steps.add(entityStep);
345 mgr.loadPreprocessorSteps();
346 assertSame(entityStep, steps.poll());
347 assertThat(steps).isEmpty();
352 var outcome = makeCompletedOutcome();
353 outcome.setResult(OperationResult.FAILURE);
355 // closed loop timeout
356 outcome.setActor(ActorConstants.CL_TIMEOUT_ACTOR);
357 assertTrue(mgr.isAbort(outcome));
360 outcome.setActor(ActorConstants.LOCK_ACTOR);
361 assertTrue(mgr.isAbort(outcome));
363 // no effect for success
364 outcome.setResult(OperationResult.SUCCESS);
365 assertFalse(mgr.isAbort(outcome));
369 void testStoreInDataBase() throws ControlLoopException {
370 when(services.getDataManager()).thenReturn(dataMgr);
371 when(workMem.getFactHandle(any())).thenReturn(factHandle);
373 var outcome = makeOutcome();
374 mgr.addToHistory(outcome);
376 mgr.storeInDataBase(mgr.getPartialHistory().peekLast());
378 verify(dataMgr).store(REQ_ID.toString(), event.getClosedLoopControlName(), event, null,
379 mgr.getPartialHistory().peekLast().getClOperation());
383 void testMakeControlLoopResponse() {
384 final var outcome = new OperationOutcome();
386 // no message - should return null
387 checkResp(outcome, null);
389 // not a PciMessage - should return null
390 outcome.setResponse("not-a-pci-message");
391 checkResp(outcome, null);
394 * now work with a PciMessage
396 var msg = new PciMessage();
397 outcome.setResponse(msg);
399 var body = new PciBody();
402 var output = new PciResponse();
403 body.setOutput(output);
405 output.setPayload("my-payload");
407 // should generate a response, with a payload
408 checkResp(outcome, "my-payload");
411 * these should generate a response, with null payload
413 output.setPayload(null);
414 checkResp(outcome, null);
416 body.setOutput(null);
417 checkResp(outcome, null);
420 checkResp(outcome, null);
422 outcome.setResponse(null);
423 checkResp(outcome, null);
427 void testCheckEventSyntax() {
429 * only need to check one success and one failure from the super class method
432 // initially, it's valid
433 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
435 event.setTarget("unknown-target");
436 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class)
437 .hasMessage("target field invalid");
439 event.setTarget(null);
440 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class)
441 .hasMessage("No target field");
443 event.setRequestId(null);
444 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class)
445 .hasMessage("No request ID");
449 void testValidateStatus() {
451 * only need to check one success and one failure from the super class method
453 event.setClosedLoopEventStatus(ControlLoopEventStatus.ONSET);
454 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
456 event.setClosedLoopEventStatus(null);
457 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class)
458 .hasMessage("Invalid value in closedLoopEventStatus");
462 void testValidateAaiData() {
463 event.setTargetType("unknown-target-type");
464 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class)
465 .hasMessage("The target type is not supported");
467 event.setTargetType(null);
468 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class)
469 .hasMessage("The Target type is null");
472 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class)
473 .hasMessage("AAI is null");
476 event.setTargetType(ControlLoopTargetType.VM);
477 event.setAai(Map.of(UsecasesConstants.GENERIC_VNF_VNF_ID, MY_TARGET));
478 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
480 event.setAai(Map.of());
481 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class);
484 event.setTargetType(ControlLoopTargetType.VNF);
485 event.setAai(Map.of(UsecasesConstants.GENERIC_VNF_VNF_ID, MY_TARGET));
486 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
488 event.setAai(Map.of());
489 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class);
492 event.setTargetType(ControlLoopTargetType.PNF);
493 event.setAai(Map.of(UsecasesConstants.PNF_NAME, MY_TARGET));
494 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
496 event.setAai(Map.of());
497 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class);
501 void testValidateAaiVmVnfData() {
502 event.setTargetType(ControlLoopTargetType.VM);
503 event.setAai(Map.of(UsecasesConstants.GENERIC_VNF_VNF_ID, MY_TARGET));
504 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
506 event.setAai(Map.of(UsecasesConstants.VSERVER_VSERVER_NAME, MY_TARGET));
507 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
509 event.setAai(Map.of(UsecasesConstants.GENERIC_VNF_VNF_NAME, MY_TARGET));
510 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
512 event.setAai(Map.of());
513 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class).hasMessage(
514 "generic-vnf.vnf-id or generic-vnf.vnf-name or vserver.vserver-name information missing");
518 void testValidateAaiPnfData() {
519 event.setTargetType(ControlLoopTargetType.PNF);
520 event.setAai(Map.of(UsecasesConstants.PNF_NAME, MY_TARGET));
521 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
523 event.setAai(Map.of());
524 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class)
525 .hasMessage("AAI PNF object key pnf-name is missing");
529 void testIsClosedLoopDisabled() {
530 var orig = event.getAai();
532 event.setAai(addAai(orig, UsecasesConstants.VSERVER_IS_CLOSED_LOOP_DISABLED, "true"));
533 assertThatThrownBy(() -> new UsecasesEventManager(services, params, event, workMem))
534 .isInstanceOf(IllegalStateException.class);
536 event.setAai(addAai(orig, UsecasesConstants.GENERIC_VNF_IS_CLOSED_LOOP_DISABLED, "true"));
537 assertThatThrownBy(() -> new UsecasesEventManager(services, params, event, workMem))
538 .isInstanceOf(IllegalStateException.class);
540 event.setAai(addAai(orig, UsecasesConstants.PNF_IS_IN_MAINT, "true"));
541 assertThatThrownBy(() -> new UsecasesEventManager(services, params, event, workMem))
542 .isInstanceOf(IllegalStateException.class);
546 void testIsProvStatusInactive() {
547 var orig = event.getAai();
549 event.setAai(addAai(orig, UsecasesConstants.VSERVER_PROV_STATUS, "ACTIVE"));
550 assertThatCode(() -> new UsecasesEventManager(services, params, event, workMem)).doesNotThrowAnyException();
552 event.setAai(addAai(orig, UsecasesConstants.VSERVER_PROV_STATUS, "inactive"));
553 assertThatThrownBy(() -> new UsecasesEventManager(services, params, event, workMem))
554 .isInstanceOf(IllegalStateException.class);
556 event.setAai(addAai(orig, UsecasesConstants.GENERIC_VNF_PROV_STATUS, "ACTIVE"));
557 assertThatCode(() -> new UsecasesEventManager(services, params, event, workMem)).doesNotThrowAnyException();
559 event.setAai(addAai(orig, UsecasesConstants.GENERIC_VNF_PROV_STATUS, "inactive"));
560 assertThatThrownBy(() -> new UsecasesEventManager(services, params, event, workMem))
561 .isInstanceOf(IllegalStateException.class);
565 void testIsAaiTrue() {
566 var orig = event.getAai();
568 for (var value : Arrays.asList("yes", "y", "true", "t", "yEs", "trUe")) {
569 event.setAai(addAai(orig, UsecasesConstants.VSERVER_IS_CLOSED_LOOP_DISABLED, value));
570 assertThatThrownBy(() -> new UsecasesEventManager(services, params, event, workMem))
571 .isInstanceOf(IllegalStateException.class);
574 event.setAai(addAai(orig, UsecasesConstants.VSERVER_IS_CLOSED_LOOP_DISABLED, "false"));
575 assertThatCode(() -> new UsecasesEventManager(services, params, event, workMem)).doesNotThrowAnyException();
577 event.setAai(addAai(orig, UsecasesConstants.VSERVER_IS_CLOSED_LOOP_DISABLED, "no"));
578 assertThatCode(() -> new UsecasesEventManager(services, params, event, workMem)).doesNotThrowAnyException();
583 private Map<String, String> addAai(Map<String, String> original, String key, String value) {
584 Map<String, String> map = new TreeMap<>(original);
589 private void loadPolicy(String fileName) throws CoderException {
590 var template = yamlCoder.decode(ResourceUtils.getResourceAsString(fileName), ToscaServiceTemplate.class);
591 tosca = template.getToscaTopologyTemplate().getPolicies().get(0).values().iterator().next();
593 params.setToscaPolicy(tosca);
596 private void loadStepsWithProperties(String... properties) {
597 stepa = new Step2(mgr, ControlLoopOperationParams.builder().build(), event) {
600 public boolean isPolicyStep() {
605 public List<String> getPropertyNames() {
606 return List.of(properties);
610 protected Operation buildOperation() {
611 return policyOperation;
615 mgr.getSteps().add(stepa);
616 mgr.getSteps().add(stepb);
619 private OperationOutcome makeCompletedOutcome() {
620 var outcome = makeOutcome();
621 outcome.setEnd(outcome.getStart());
626 private OperationOutcome makeOutcome() {
627 var outcome = new OperationOutcome();
628 outcome.setActor(SIMPLE_ACTOR);
629 outcome.setOperation(SIMPLE_OPERATION);
630 outcome.setMessage(OUTCOME_MSG);
631 outcome.setResult(OperationResult.SUCCESS);
632 outcome.setStart(Instant.now());
633 outcome.setTarget(MY_TARGET);
638 private void checkResp(OperationOutcome outcome, String expectedPayload) {
639 var resp = mgr.makeControlLoopResponse(outcome);
641 assertEquals(REQ_ID, resp.getRequestId());
642 assertEquals(expectedPayload, resp.getPayload());
646 * Sets the target entity so a step doesn't have to be added to set it.
648 private void setTargetEntity() {
649 mgr.setProperty(OperationProperties.AAI_TARGET_ENTITY, MY_TARGET);
653 private class MyManager extends UsecasesEventManager {
654 private static final long serialVersionUID = 1L;
656 public MyManager(EventManagerServices services, ControlLoopParams params, VirtualControlLoopEvent event,
657 WorkingMemory workMem) throws ControlLoopException {
659 super(services, params, event, workMem);
663 protected ExecutorService getBlockingExecutor() {
668 protected void makeLock(String targetEntity, String requestId, int holdSec, LockCallback callback) {
669 var lock = new LockImpl(LockState.ACTIVE, targetEntity, requestId, holdSec, callback);
671 callback.lockAvailable(lock);
675 protected PolicyEngine getPolicyEngineManager() {