ba293c1b58bf9645091e0178dcb25b101642906e
[policy/drools-applications.git] / controlloop / common / eventmanager / src / test / java / org / onap / policy / controlloop / eventmanager / ClEventManagerWithOutcomeTest.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP
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
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
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=========================================================
19  */
20
21 package org.onap.policy.controlloop.eventmanager;
22
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;
33
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.Operation;
55 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
56 import org.onap.policy.controlloop.actorserviceprovider.OperationResult;
57 import org.onap.policy.controlloop.actorserviceprovider.Operator;
58 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
59 import org.onap.policy.controlloop.actorserviceprovider.spi.Actor;
60 import org.onap.policy.controlloop.drl.legacy.ControlLoopParams;
61 import org.onap.policy.drools.core.lock.LockCallback;
62 import org.onap.policy.drools.core.lock.LockImpl;
63 import org.onap.policy.drools.core.lock.LockState;
64 import org.onap.policy.drools.system.PolicyEngine;
65 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
66 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
67
68 @RunWith(MockitoJUnitRunner.class)
69 public class ClEventManagerWithOutcomeTest {
70     private static final UUID REQ_ID = UUID.randomUUID();
71     private static final String CL_NAME = "my-closed-loop-name";
72     private static final String POLICY_NAME = "my-policy-name";
73     private static final String POLICY_SCOPE = "my-scope";
74     private static final String POLICY_VERSION = "1.2.3";
75     private static final String SIMPLE_ACTOR = "First";
76     private static final String SIMPLE_OPERATION = "OperationA";
77     private static final String MY_TARGET = "my-target";
78     private static final String EVENT_MGR_MULTI_YAML =
79                     "../eventmanager/src/test/resources/eventManager/event-mgr-multi.yaml";
80     private static final String EVENT_MGR_SIMPLE_YAML =
81                     "../eventmanager/src/test/resources/eventManager/event-mgr-simple.yaml";
82     private static final Coder yamlCoder = new StandardYamlCoder();
83     private static final String OUTCOME_MSG = "my outcome message";
84
85     @Mock
86     private PolicyEngine engineMgr;
87     @Mock
88     private WorkingMemory workMem;
89     @Mock
90     private FactHandle factHandle;
91     @Mock
92     private Operator policyOperator;
93     @Mock
94     private Operation policyOperation;
95     @Mock
96     private Actor policyActor;
97     @Mock
98     private EventManagerServices services;
99     @Mock
100     private ExecutorService executor;
101     @Mock
102     private MyStep stepa;
103     @Mock
104     private MyStep stepb;
105
106     private List<LockImpl> locks;
107     private ToscaPolicy tosca;
108     private ControlLoopParams params;
109     private ClEventManagerWithOutcome<MyStep> mgr;
110
111     /**
112      * Sets up.
113      */
114     @Before
115     public void setUp() throws ControlLoopException, CoderException {
116         when(workMem.getFactHandle(any())).thenReturn(factHandle);
117
118         params = new ControlLoopParams();
119         params.setClosedLoopControlName(CL_NAME);
120         params.setPolicyName(POLICY_NAME);
121         params.setPolicyScope(POLICY_SCOPE);
122         params.setPolicyVersion(POLICY_VERSION);
123
124         loadPolicy(EVENT_MGR_SIMPLE_YAML);
125
126         locks = new ArrayList<>();
127
128         mgr = new MyManager(services, params, REQ_ID, workMem);
129     }
130
131     @Test
132     public void testConstructor() {
133         assertEquals(POLICY_NAME, mgr.getPolicyName());
134
135         // invalid
136         assertThatThrownBy(() -> new MyManager(services, params, null, workMem))
137                         .isInstanceOf(ControlLoopException.class);
138     }
139
140     @Test
141     public void testLoadNextPolicy_testGetFullHistory_testGetPartialHistory() throws Exception {
142         loadPolicy(EVENT_MGR_MULTI_YAML);
143         mgr = new MyManager(services, params, REQ_ID, workMem);
144
145         // start and load step for first policy
146         mgr.start();
147         assertEquals("OperationA", mgr.getSteps().poll().getOperationName());
148         assertNull(mgr.getFinalResult());
149
150         // add an outcome
151         OperationOutcome outcome = makeOutcome();
152         mgr.addToHistory(outcome);
153
154         // indicate success and load next policy
155         mgr.loadNextPolicy(OperationResult.SUCCESS);
156         assertEquals("OperationB", mgr.getSteps().poll().getOperationName());
157         assertNull(mgr.getFinalResult());
158
159         // loadPolicy() should clear the partial history, but not the full history
160         assertThat(mgr.getPartialHistory()).isEmpty();
161         assertThat(mgr.getFullHistory()).hasSize(1);
162     }
163
164     @Test
165     public void testExecuteStep() {
166         mgr.bumpAttempts();
167
168         // no steps to execute
169         assertFalse(mgr.executeStep());
170         assertEquals(0, mgr.getAttempts());
171     }
172
173     @Test
174     public void testBumpAttempts() {
175         assertEquals(0, mgr.getAttempts());
176
177         mgr.bumpAttempts();
178         mgr.bumpAttempts();
179         assertEquals(2, mgr.getAttempts());
180     }
181
182     @Test
183     public void testIsAbort() {
184         OperationOutcome outcome = makeCompletedOutcome();
185
186         outcome.setResult(OperationResult.FAILURE);
187         assertTrue(mgr.isAbort(outcome));
188
189         // no effect for success
190         outcome.setResult(OperationResult.SUCCESS);
191         assertFalse(mgr.isAbort(outcome));
192     }
193
194     @Test
195     public void testAddToHistory() throws ControlLoopException {
196         mgr.start();
197
198         // add a "start" outcome
199         OperationOutcome outcome = makeOutcome();
200         mgr.addToHistory(outcome);
201
202         assertThat(mgr.getPartialHistory()).hasSize(1);
203         assertThat(mgr.getFullHistory()).hasSize(1);
204
205         // add a "completion" outcome - should replace the start
206         outcome = makeCompletedOutcome();
207         mgr.addToHistory(outcome);
208
209         assertThat(mgr.getPartialHistory()).hasSize(1);
210         assertThat(mgr.getFullHistory()).hasSize(1);
211         assertSame(outcome, mgr.getPartialHistory().peek().getOutcome());
212         assertSame(outcome, mgr.getFullHistory().peek().getOutcome());
213
214         // add another start
215         outcome = makeOutcome();
216         mgr.addToHistory(outcome);
217
218         assertThat(mgr.getPartialHistory()).hasSize(2);
219         assertThat(mgr.getFullHistory()).hasSize(2);
220         assertSame(outcome, mgr.getPartialHistory().peekLast().getOutcome());
221         assertSame(outcome, mgr.getFullHistory().peekLast().getOutcome());
222
223         // remove the last item from the full history and then add a "completion"
224         mgr.getFullHistory().removeLast();
225         outcome = makeCompletedOutcome();
226         mgr.addToHistory(outcome);
227         assertThat(mgr.getPartialHistory()).hasSize(2);
228         assertThat(mgr.getFullHistory()).hasSize(2);
229
230         // add another "start"
231         outcome = makeOutcome();
232         mgr.addToHistory(outcome);
233         assertThat(mgr.getPartialHistory()).hasSize(3);
234         assertThat(mgr.getFullHistory()).hasSize(3);
235
236         // add a "completion" for a different actor - should NOT replace the start
237         outcome = makeCompletedOutcome();
238         outcome.setActor("different-actor");
239         mgr.addToHistory(outcome);
240         assertThat(mgr.getPartialHistory()).hasSize(4);
241         assertThat(mgr.getFullHistory()).hasSize(4);
242         assertSame(outcome, mgr.getPartialHistory().peekLast().getOutcome());
243         assertSame(outcome, mgr.getFullHistory().peekLast().getOutcome());
244     }
245
246     @Test
247     public void testMakeNotification() throws Exception {
248         loadPolicy(EVENT_MGR_MULTI_YAML);
249         mgr = new MyManager(services, params, REQ_ID, workMem);
250
251         // before started
252         assertNotNull(mgr.makeNotification());
253
254         mgr.start();
255
256         mgr.addToHistory(makeCompletedOutcome());
257         mgr.addToHistory(makeCompletedOutcome());
258         mgr.addToHistory(makeCompletedOutcome());
259
260         // check notification while running
261         VirtualControlLoopNotification notif = mgr.makeNotification();
262         assertThat(notif.getMessage()).contains(SIMPLE_ACTOR);
263         assertThat(notif.getHistory()).hasSize(3);
264
265         // indicate success and load the next policy - should clear the partial history
266         mgr.loadNextPolicy(OperationResult.SUCCESS);
267
268         // check notification
269         notif = mgr.makeNotification();
270         assertNull(notif.getMessage());
271         assertThat(notif.getHistory()).isEmpty();
272
273         // add outcomes and check again
274         mgr.addToHistory(makeCompletedOutcome());
275         mgr.addToHistory(makeCompletedOutcome());
276
277         notif = mgr.makeNotification();
278         assertNotNull(notif.getMessage());
279
280         // should only have history for last two outcomes
281         assertThat(notif.getHistory()).hasSize(2);
282
283         // indicate failure - should go to final state
284         mgr.loadNextPolicy(OperationResult.FAILURE);
285
286         // check notification
287         notif = mgr.makeNotification();
288         assertNull(notif.getMessage());
289
290         // should be no history
291         assertThat(notif.getHistory()).isEmpty();
292
293         // null case
294         assertThatThrownBy(() -> mgr.loadNextPolicy(null)).isInstanceOf(NullPointerException.class)
295                         .hasMessageContaining("lastResult");
296     }
297
298     @Test
299     public void testGetOperationMessage() throws ControlLoopException {
300         // no history yet
301         assertNull(mgr.getOperationMessage());
302
303         // add an outcome
304         mgr.start();
305         OperationOutcome outcome = makeOutcome();
306         mgr.addToHistory(outcome);
307
308         assertThat(mgr.getOperationMessage()).contains("actor=" + SIMPLE_ACTOR)
309                         .contains("operation=" + SIMPLE_OPERATION);
310     }
311
312     @Test
313     public void testMakeControlLoopResponse() {
314         final OperationOutcome outcome = new OperationOutcome();
315         outcome.setActor(SIMPLE_ACTOR);
316
317         ControlLoopResponse resp = mgr.makeControlLoopResponse(outcome);
318         assertNotNull(resp);
319         assertEquals(SIMPLE_ACTOR, resp.getFrom());
320     }
321
322     private void loadPolicy(String fileName) throws CoderException {
323         ToscaServiceTemplate template =
324                         yamlCoder.decode(ResourceUtils.getResourceAsString(fileName), ToscaServiceTemplate.class);
325         tosca = template.getToscaTopologyTemplate().getPolicies().get(0).values().iterator().next();
326
327         params.setToscaPolicy(tosca);
328     }
329
330     private OperationOutcome makeCompletedOutcome() {
331         OperationOutcome outcome = makeOutcome();
332         outcome.setEnd(outcome.getStart());
333
334         return outcome;
335     }
336
337     private OperationOutcome makeOutcome() {
338         OperationOutcome outcome = new OperationOutcome();
339         outcome.setActor(SIMPLE_ACTOR);
340         outcome.setOperation(SIMPLE_OPERATION);
341         outcome.setMessage(OUTCOME_MSG);
342         outcome.setResult(OperationResult.SUCCESS);
343         outcome.setStart(Instant.now());
344         outcome.setTarget(MY_TARGET);
345
346         return outcome;
347     }
348
349
350     private class MyManager extends ClEventManagerWithOutcome<MyStep> {
351         private static final long serialVersionUID = 1L;
352
353         public MyManager(EventManagerServices services, ControlLoopParams params, UUID requestId, WorkingMemory workMem)
354                         throws ControlLoopException {
355
356             super(services, params, requestId, workMem);
357         }
358
359         @Override
360         protected ExecutorService getBlockingExecutor() {
361             return executor;
362         }
363
364         @Override
365         protected void makeLock(String targetEntity, String requestId, int holdSec, LockCallback callback) {
366             LockImpl lock = new LockImpl(LockState.ACTIVE, targetEntity, requestId, holdSec, callback);
367             locks.add(lock);
368             callback.lockAvailable(lock);
369         }
370
371         @Override
372         protected PolicyEngine getPolicyEngineManager() {
373             return engineMgr;
374         }
375
376         @Override
377         protected void loadPolicyStep(ControlLoopOperationParams params) {
378             getSteps().add(new MyStep(this, params));
379         }
380     }
381
382
383     private static class MyStep extends Step {
384         public MyStep(StepContext stepContext, ControlLoopOperationParams params) {
385             super(params, new AtomicReference<>());
386         }
387     }
388 }