2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2020-2021, 2023 AT&T Intellectual Property. All rights reserved.
6 * Modifications Copyright (C) 2023 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 {
371 var outcome = makeOutcome();
372 mgr.addToHistory(outcome);
374 mgr.storeInDataBase(mgr.getPartialHistory().peekLast());
376 verify(dataMgr).store(REQ_ID.toString(), event.getClosedLoopControlName(), event, null,
377 mgr.getPartialHistory().peekLast().getClOperation());
381 void testMakeControlLoopResponse() {
382 final var outcome = new OperationOutcome();
384 // no message - should return null
385 checkResp(outcome, null);
387 // not a PciMessage - should return null
388 outcome.setResponse("not-a-pci-message");
389 checkResp(outcome, null);
392 * now work with a PciMessage
394 var msg = new PciMessage();
395 outcome.setResponse(msg);
397 var body = new PciBody();
400 var output = new PciResponse();
401 body.setOutput(output);
403 output.setPayload("my-payload");
405 // should generate a response, with a payload
406 checkResp(outcome, "my-payload");
409 * these should generate a response, with null payload
411 output.setPayload(null);
412 checkResp(outcome, null);
414 body.setOutput(null);
415 checkResp(outcome, null);
418 checkResp(outcome, null);
420 outcome.setResponse(null);
421 checkResp(outcome, null);
425 void testCheckEventSyntax() {
427 * only need to check one success and one failure from the super class method
430 // initially, it's valid
431 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
433 event.setTarget("unknown-target");
434 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class)
435 .hasMessage("target field invalid");
437 event.setTarget(null);
438 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class)
439 .hasMessage("No target field");
441 event.setRequestId(null);
442 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class)
443 .hasMessage("No request ID");
447 void testValidateStatus() {
449 * only need to check one success and one failure from the super class method
451 event.setClosedLoopEventStatus(ControlLoopEventStatus.ONSET);
452 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
454 event.setClosedLoopEventStatus(null);
455 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class)
456 .hasMessage("Invalid value in closedLoopEventStatus");
460 void testValidateAaiData() {
461 event.setTargetType("unknown-target-type");
462 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class)
463 .hasMessage("The target type is not supported");
465 event.setTargetType(null);
466 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class)
467 .hasMessage("The Target type is null");
470 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class)
471 .hasMessage("AAI is null");
474 event.setTargetType(ControlLoopTargetType.VM);
475 event.setAai(Map.of(UsecasesConstants.GENERIC_VNF_VNF_ID, MY_TARGET));
476 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
478 event.setAai(Map.of());
479 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class);
482 event.setTargetType(ControlLoopTargetType.VNF);
483 event.setAai(Map.of(UsecasesConstants.GENERIC_VNF_VNF_ID, MY_TARGET));
484 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
486 event.setAai(Map.of());
487 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class);
490 event.setTargetType(ControlLoopTargetType.PNF);
491 event.setAai(Map.of(UsecasesConstants.PNF_NAME, MY_TARGET));
492 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
494 event.setAai(Map.of());
495 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class);
499 void testValidateAaiVmVnfData() {
500 event.setTargetType(ControlLoopTargetType.VM);
501 event.setAai(Map.of(UsecasesConstants.GENERIC_VNF_VNF_ID, MY_TARGET));
502 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
504 event.setAai(Map.of(UsecasesConstants.VSERVER_VSERVER_NAME, MY_TARGET));
505 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
507 event.setAai(Map.of(UsecasesConstants.GENERIC_VNF_VNF_NAME, MY_TARGET));
508 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
510 event.setAai(Map.of());
511 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class).hasMessage(
512 "generic-vnf.vnf-id or generic-vnf.vnf-name or vserver.vserver-name information missing");
516 void testValidateAaiPnfData() {
517 event.setTargetType(ControlLoopTargetType.PNF);
518 event.setAai(Map.of(UsecasesConstants.PNF_NAME, MY_TARGET));
519 assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
521 event.setAai(Map.of());
522 assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class)
523 .hasMessage("AAI PNF object key pnf-name is missing");
527 void testIsClosedLoopDisabled() {
528 var orig = event.getAai();
530 event.setAai(addAai(orig, UsecasesConstants.VSERVER_IS_CLOSED_LOOP_DISABLED, "true"));
531 assertThatThrownBy(() -> new UsecasesEventManager(services, params, event, workMem))
532 .isInstanceOf(IllegalStateException.class);
534 event.setAai(addAai(orig, UsecasesConstants.GENERIC_VNF_IS_CLOSED_LOOP_DISABLED, "true"));
535 assertThatThrownBy(() -> new UsecasesEventManager(services, params, event, workMem))
536 .isInstanceOf(IllegalStateException.class);
538 event.setAai(addAai(orig, UsecasesConstants.PNF_IS_IN_MAINT, "true"));
539 assertThatThrownBy(() -> new UsecasesEventManager(services, params, event, workMem))
540 .isInstanceOf(IllegalStateException.class);
544 void testIsProvStatusInactive() {
545 var orig = event.getAai();
547 event.setAai(addAai(orig, UsecasesConstants.VSERVER_PROV_STATUS, "ACTIVE"));
548 assertThatCode(() -> new UsecasesEventManager(services, params, event, workMem)).doesNotThrowAnyException();
550 event.setAai(addAai(orig, UsecasesConstants.VSERVER_PROV_STATUS, "inactive"));
551 assertThatThrownBy(() -> new UsecasesEventManager(services, params, event, workMem))
552 .isInstanceOf(IllegalStateException.class);
554 event.setAai(addAai(orig, UsecasesConstants.GENERIC_VNF_PROV_STATUS, "ACTIVE"));
555 assertThatCode(() -> new UsecasesEventManager(services, params, event, workMem)).doesNotThrowAnyException();
557 event.setAai(addAai(orig, UsecasesConstants.GENERIC_VNF_PROV_STATUS, "inactive"));
558 assertThatThrownBy(() -> new UsecasesEventManager(services, params, event, workMem))
559 .isInstanceOf(IllegalStateException.class);
563 void testIsAaiTrue() {
564 var orig = event.getAai();
566 for (var value : Arrays.asList("yes", "y", "true", "t", "yEs", "trUe")) {
567 event.setAai(addAai(orig, UsecasesConstants.VSERVER_IS_CLOSED_LOOP_DISABLED, value));
568 assertThatThrownBy(() -> new UsecasesEventManager(services, params, event, workMem))
569 .isInstanceOf(IllegalStateException.class);
572 event.setAai(addAai(orig, UsecasesConstants.VSERVER_IS_CLOSED_LOOP_DISABLED, "false"));
573 assertThatCode(() -> new UsecasesEventManager(services, params, event, workMem)).doesNotThrowAnyException();
575 event.setAai(addAai(orig, UsecasesConstants.VSERVER_IS_CLOSED_LOOP_DISABLED, "no"));
576 assertThatCode(() -> new UsecasesEventManager(services, params, event, workMem)).doesNotThrowAnyException();
581 private Map<String, String> addAai(Map<String, String> original, String key, String value) {
582 Map<String, String> map = new TreeMap<>(original);
587 private void loadPolicy(String fileName) throws CoderException {
588 var template = yamlCoder.decode(ResourceUtils.getResourceAsString(fileName), ToscaServiceTemplate.class);
589 tosca = template.getToscaTopologyTemplate().getPolicies().get(0).values().iterator().next();
591 params.setToscaPolicy(tosca);
594 private void loadStepsWithProperties(String... properties) {
595 stepa = new Step2(mgr, ControlLoopOperationParams.builder().build(), event) {
598 public boolean isPolicyStep() {
603 public List<String> getPropertyNames() {
604 return List.of(properties);
608 protected Operation buildOperation() {
609 return policyOperation;
613 mgr.getSteps().add(stepa);
614 mgr.getSteps().add(stepb);
617 private OperationOutcome makeCompletedOutcome() {
618 var outcome = makeOutcome();
619 outcome.setEnd(outcome.getStart());
624 private OperationOutcome makeOutcome() {
625 var outcome = new OperationOutcome();
626 outcome.setActor(SIMPLE_ACTOR);
627 outcome.setOperation(SIMPLE_OPERATION);
628 outcome.setMessage(OUTCOME_MSG);
629 outcome.setResult(OperationResult.SUCCESS);
630 outcome.setStart(Instant.now());
631 outcome.setTarget(MY_TARGET);
636 private void checkResp(OperationOutcome outcome, String expectedPayload) {
637 var resp = mgr.makeControlLoopResponse(outcome);
639 assertEquals(REQ_ID, resp.getRequestId());
640 assertEquals(expectedPayload, resp.getPayload());
644 * Sets the target entity so a step doesn't have to be added to set it.
646 private void setTargetEntity() {
647 mgr.setProperty(OperationProperties.AAI_TARGET_ENTITY, MY_TARGET);
651 private class MyManager extends UsecasesEventManager {
652 private static final long serialVersionUID = 1L;
654 public MyManager(EventManagerServices services, ControlLoopParams params, VirtualControlLoopEvent event,
655 WorkingMemory workMem) throws ControlLoopException {
657 super(services, params, event, workMem);
661 protected ExecutorService getBlockingExecutor() {
666 protected void makeLock(String targetEntity, String requestId, int holdSec, LockCallback callback) {
667 var lock = new LockImpl(LockState.ACTIVE, targetEntity, requestId, holdSec, callback);
669 callback.lockAvailable(lock);
673 protected PolicyEngine getPolicyEngineManager() {