2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2021 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.assertThat;
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.Mockito.when;
34 import java.time.Instant;
35 import java.util.ArrayList;
36 import java.util.List;
37 import java.util.UUID;
38 import java.util.concurrent.ExecutorService;
39 import java.util.concurrent.atomic.AtomicReference;
40 import org.drools.core.WorkingMemory;
41 import org.junit.Before;
42 import org.junit.Test;
43 import org.junit.runner.RunWith;
44 import org.kie.api.runtime.rule.FactHandle;
45 import org.mockito.Mock;
46 import org.mockito.junit.MockitoJUnitRunner;
47 import org.onap.policy.common.utils.coder.Coder;
48 import org.onap.policy.common.utils.coder.CoderException;
49 import org.onap.policy.common.utils.coder.StandardYamlCoder;
50 import org.onap.policy.common.utils.resources.ResourceUtils;
51 import org.onap.policy.controlloop.ControlLoopException;
52 import org.onap.policy.controlloop.ControlLoopResponse;
53 import org.onap.policy.controlloop.VirtualControlLoopNotification;
54 import org.onap.policy.controlloop.actorserviceprovider.ActorService;
55 import org.onap.policy.controlloop.actorserviceprovider.Operation;
56 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
57 import org.onap.policy.controlloop.actorserviceprovider.OperationResult;
58 import org.onap.policy.controlloop.actorserviceprovider.Operator;
59 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
60 import org.onap.policy.controlloop.actorserviceprovider.spi.Actor;
61 import org.onap.policy.controlloop.drl.legacy.ControlLoopParams;
62 import org.onap.policy.controlloop.ophistory.OperationHistoryDataManager;
63 import org.onap.policy.drools.core.lock.LockCallback;
64 import org.onap.policy.drools.core.lock.LockImpl;
65 import org.onap.policy.drools.core.lock.LockState;
66 import org.onap.policy.drools.system.PolicyEngine;
67 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
68 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
70 @RunWith(MockitoJUnitRunner.class)
71 public class ClEventManagerWithOutcomeTest {
72 private static final UUID REQ_ID = UUID.randomUUID();
73 private static final String CL_NAME = "my-closed-loop-name";
74 private static final String POLICY_NAME = "my-policy-name";
75 private static final String POLICY_SCOPE = "my-scope";
76 private static final String POLICY_VERSION = "1.2.3";
77 private static final String SIMPLE_ACTOR = "First";
78 private static final String SIMPLE_OPERATION = "OperationA";
79 private static final String MY_TARGET = "my-target";
80 private static final String EVENT_MGR_MULTI_YAML =
81 "../eventmanager/src/test/resources/eventManager/event-mgr-multi.yaml";
82 private static final String EVENT_MGR_SIMPLE_YAML =
83 "../eventmanager/src/test/resources/eventManager/event-mgr-simple.yaml";
84 private static final Coder yamlCoder = new StandardYamlCoder();
85 private static final String OUTCOME_MSG = "my outcome message";
88 private PolicyEngine engineMgr;
90 private WorkingMemory workMem;
92 private FactHandle factHandle;
94 private Operator policyOperator;
96 private Operation policyOperation;
98 private Actor policyActor;
100 private ActorService actors;
102 private OperationHistoryDataManager dataMgr;
104 private ExecutorService executor;
106 private MyStep stepa;
108 private MyStep stepb;
110 private List<LockImpl> locks;
111 private ToscaPolicy tosca;
112 private ControlLoopParams params;
113 private ClEventManagerWithOutcome<MyStep> mgr;
119 public void setUp() throws ControlLoopException, CoderException {
120 when(workMem.getFactHandle(any())).thenReturn(factHandle);
122 params = new ControlLoopParams();
123 params.setClosedLoopControlName(CL_NAME);
124 params.setPolicyName(POLICY_NAME);
125 params.setPolicyScope(POLICY_SCOPE);
126 params.setPolicyVersion(POLICY_VERSION);
128 loadPolicy(EVENT_MGR_SIMPLE_YAML);
130 locks = new ArrayList<>();
132 mgr = new MyManager(params, REQ_ID, workMem);
136 public void testConstructor() {
137 assertEquals(POLICY_NAME, mgr.getPolicyName());
140 assertThatThrownBy(() -> new MyManager(params, null, workMem)).isInstanceOf(ControlLoopException.class);
144 public void testLoadNextPolicy_testGetFullHistory_testGetPartialHistory() throws Exception {
145 loadPolicy(EVENT_MGR_MULTI_YAML);
146 mgr = new MyManager(params, REQ_ID, workMem);
148 // start and load step for first policy
150 assertEquals("OperationA", mgr.getSteps().poll().getOperationName());
151 assertNull(mgr.getFinalResult());
154 OperationOutcome outcome = makeOutcome();
155 mgr.addToHistory(outcome);
157 // indicate success and load next policy
158 mgr.loadNextPolicy(OperationResult.SUCCESS);
159 assertEquals("OperationB", mgr.getSteps().poll().getOperationName());
160 assertNull(mgr.getFinalResult());
162 // loadPolicy() should clear the partial history, but not the full history
163 assertThat(mgr.getPartialHistory()).isEmpty();
164 assertThat(mgr.getFullHistory()).hasSize(1);
168 public void testExecuteStep() {
171 // no steps to execute
172 assertFalse(mgr.executeStep());
173 assertEquals(0, mgr.getAttempts());
177 public void testBumpAttempts() {
178 assertEquals(0, mgr.getAttempts());
182 assertEquals(2, mgr.getAttempts());
186 public void testIsAbort() {
187 OperationOutcome outcome = makeCompletedOutcome();
189 outcome.setResult(OperationResult.FAILURE);
190 assertTrue(mgr.isAbort(outcome));
192 // no effect for success
193 outcome.setResult(OperationResult.SUCCESS);
194 assertFalse(mgr.isAbort(outcome));
198 public void testAddToHistory() throws ControlLoopException {
201 // add a "start" outcome
202 OperationOutcome outcome = makeOutcome();
203 mgr.addToHistory(outcome);
205 assertThat(mgr.getPartialHistory()).hasSize(1);
206 assertThat(mgr.getFullHistory()).hasSize(1);
208 // add a "completion" outcome - should replace the start
209 outcome = makeCompletedOutcome();
210 mgr.addToHistory(outcome);
212 assertThat(mgr.getPartialHistory()).hasSize(1);
213 assertThat(mgr.getFullHistory()).hasSize(1);
214 assertSame(outcome, mgr.getPartialHistory().peek().getOutcome());
215 assertSame(outcome, mgr.getFullHistory().peek().getOutcome());
218 outcome = makeOutcome();
219 mgr.addToHistory(outcome);
221 assertThat(mgr.getPartialHistory()).hasSize(2);
222 assertThat(mgr.getFullHistory()).hasSize(2);
223 assertSame(outcome, mgr.getPartialHistory().peekLast().getOutcome());
224 assertSame(outcome, mgr.getFullHistory().peekLast().getOutcome());
226 // remove the last item from the full history and then add a "completion"
227 mgr.getFullHistory().removeLast();
228 outcome = makeCompletedOutcome();
229 mgr.addToHistory(outcome);
230 assertThat(mgr.getPartialHistory()).hasSize(2);
231 assertThat(mgr.getFullHistory()).hasSize(2);
233 // add another "start"
234 outcome = makeOutcome();
235 mgr.addToHistory(outcome);
236 assertThat(mgr.getPartialHistory()).hasSize(3);
237 assertThat(mgr.getFullHistory()).hasSize(3);
239 // add a "completion" for a different actor - should NOT replace the start
240 outcome = makeCompletedOutcome();
241 outcome.setActor("different-actor");
242 mgr.addToHistory(outcome);
243 assertThat(mgr.getPartialHistory()).hasSize(4);
244 assertThat(mgr.getFullHistory()).hasSize(4);
245 assertSame(outcome, mgr.getPartialHistory().peekLast().getOutcome());
246 assertSame(outcome, mgr.getFullHistory().peekLast().getOutcome());
250 public void testMakeNotification() throws Exception {
251 loadPolicy(EVENT_MGR_MULTI_YAML);
252 mgr = new MyManager(params, REQ_ID, workMem);
255 assertNotNull(mgr.makeNotification());
259 mgr.addToHistory(makeCompletedOutcome());
260 mgr.addToHistory(makeCompletedOutcome());
261 mgr.addToHistory(makeCompletedOutcome());
263 // check notification while running
264 VirtualControlLoopNotification notif = mgr.makeNotification();
265 assertThat(notif.getMessage()).contains(SIMPLE_ACTOR);
266 assertThat(notif.getHistory()).hasSize(3);
268 // indicate success and load the next policy - should clear the partial history
269 mgr.loadNextPolicy(OperationResult.SUCCESS);
271 // check notification
272 notif = mgr.makeNotification();
273 assertNull(notif.getMessage());
274 assertThat(notif.getHistory()).isEmpty();
276 // add outcomes and check again
277 mgr.addToHistory(makeCompletedOutcome());
278 mgr.addToHistory(makeCompletedOutcome());
280 notif = mgr.makeNotification();
281 assertNotNull(notif.getMessage());
283 // should only have history for last two outcomes
284 assertThat(notif.getHistory()).hasSize(2);
286 // indicate failure - should go to final state
287 mgr.loadNextPolicy(OperationResult.FAILURE);
289 // check notification
290 notif = mgr.makeNotification();
291 assertNull(notif.getMessage());
293 // should be no history
294 assertThat(notif.getHistory()).isEmpty();
297 assertThatThrownBy(() -> mgr.loadNextPolicy(null)).isInstanceOf(NullPointerException.class)
298 .hasMessageContaining("lastResult");
302 public void testGetOperationMessage() throws ControlLoopException {
304 assertNull(mgr.getOperationMessage());
308 OperationOutcome outcome = makeOutcome();
309 mgr.addToHistory(outcome);
311 assertThat(mgr.getOperationMessage()).contains("actor=" + SIMPLE_ACTOR)
312 .contains("operation=" + SIMPLE_OPERATION);
316 public void testMakeControlLoopResponse() {
317 final OperationOutcome outcome = new OperationOutcome();
318 outcome.setActor(SIMPLE_ACTOR);
320 ControlLoopResponse resp = mgr.makeControlLoopResponse(outcome);
322 assertEquals(SIMPLE_ACTOR, resp.getFrom());
325 private void loadPolicy(String fileName) throws CoderException {
326 ToscaServiceTemplate template =
327 yamlCoder.decode(ResourceUtils.getResourceAsString(fileName), ToscaServiceTemplate.class);
328 tosca = template.getToscaTopologyTemplate().getPolicies().get(0).values().iterator().next();
330 params.setToscaPolicy(tosca);
333 private OperationOutcome makeCompletedOutcome() {
334 OperationOutcome outcome = makeOutcome();
335 outcome.setEnd(outcome.getStart());
340 private OperationOutcome makeOutcome() {
341 OperationOutcome outcome = new OperationOutcome();
342 outcome.setActor(SIMPLE_ACTOR);
343 outcome.setOperation(SIMPLE_OPERATION);
344 outcome.setMessage(OUTCOME_MSG);
345 outcome.setResult(OperationResult.SUCCESS);
346 outcome.setStart(Instant.now());
347 outcome.setTarget(MY_TARGET);
353 private class MyManager extends ClEventManagerWithOutcome<MyStep> {
354 private static final long serialVersionUID = 1L;
356 public MyManager(ControlLoopParams params, UUID requestId, WorkingMemory workMem) throws ControlLoopException {
358 super(params, requestId, workMem);
362 protected ExecutorService getBlockingExecutor() {
367 protected void makeLock(String targetEntity, String requestId, int holdSec, LockCallback callback) {
368 LockImpl lock = new LockImpl(LockState.ACTIVE, targetEntity, requestId, holdSec, callback);
370 callback.lockAvailable(lock);
374 public ActorService getActorService() {
379 public OperationHistoryDataManager getDataManager() {
384 protected PolicyEngine getPolicyEngineManager() {
389 protected void loadPolicyStep(ControlLoopOperationParams params) {
390 getSteps().add(new MyStep(this, params));
395 private static class MyStep extends Step {
396 public MyStep(StepContext stepContext, ControlLoopOperationParams params) {
397 super(params, new AtomicReference<>());