759ec90b1c2d8761ed0391664424f32c086b8013
[policy/drools-applications.git] / controlloop / common / eventmanager / src / test / java / org / onap / policy / controlloop / eventmanager / ClEventManagerWithEventTest.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.assertThatCode;
25 import static org.assertj.core.api.Assertions.assertThatThrownBy;
26 import static org.junit.Assert.assertEquals;
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.mockito.ArgumentMatchers.any;
31 import static org.mockito.Mockito.verify;
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.Map;
38 import java.util.TreeMap;
39 import java.util.UUID;
40 import java.util.concurrent.ExecutorService;
41 import java.util.concurrent.atomic.AtomicReference;
42 import org.drools.core.WorkingMemory;
43 import org.junit.Before;
44 import org.junit.Test;
45 import org.junit.runner.RunWith;
46 import org.kie.api.runtime.rule.FactHandle;
47 import org.mockito.Mock;
48 import org.mockito.junit.MockitoJUnitRunner;
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.ControlLoopResponse;
56 import org.onap.policy.controlloop.ControlLoopTargetType;
57 import org.onap.policy.controlloop.VirtualControlLoopEvent;
58 import org.onap.policy.controlloop.VirtualControlLoopNotification;
59 import org.onap.policy.controlloop.actorserviceprovider.ActorService;
60 import org.onap.policy.controlloop.actorserviceprovider.Operation;
61 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
62 import org.onap.policy.controlloop.actorserviceprovider.OperationResult;
63 import org.onap.policy.controlloop.actorserviceprovider.Operator;
64 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
65 import org.onap.policy.controlloop.actorserviceprovider.spi.Actor;
66 import org.onap.policy.controlloop.drl.legacy.ControlLoopParams;
67 import org.onap.policy.controlloop.eventmanager.ClEventManagerWithEvent.NewEventStatus;
68 import org.onap.policy.controlloop.ophistory.OperationHistoryDataManager;
69 import org.onap.policy.drools.core.lock.LockCallback;
70 import org.onap.policy.drools.core.lock.LockImpl;
71 import org.onap.policy.drools.core.lock.LockState;
72 import org.onap.policy.drools.system.PolicyEngine;
73 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
74 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
75
76 @RunWith(MockitoJUnitRunner.class)
77 public class ClEventManagerWithEventTest {
78     private static final UUID REQ_ID = UUID.randomUUID();
79     private static final String CL_NAME = "my-closed-loop-name";
80     private static final String POLICY_NAME = "my-policy-name";
81     private static final String POLICY_SCOPE = "my-scope";
82     private static final String POLICY_VERSION = "1.2.3";
83     private static final String SIMPLE_ACTOR = "First";
84     private static final String SIMPLE_OPERATION = "OperationA";
85     private static final String TARGET_PROP = "my-target-property";
86     private static final String MY_TARGET = "my-target";
87     private static final String EVENT_MGR_MULTI_YAML =
88                     "../eventmanager/src/test/resources/eventManager/event-mgr-multi.yaml";
89     private static final String EVENT_MGR_SIMPLE_YAML =
90                     "../eventmanager/src/test/resources/eventManager/event-mgr-simple.yaml";
91     private static final Coder yamlCoder = new StandardYamlCoder();
92     private static final String OUTCOME_MSG = "my outcome message";
93
94     @Mock
95     private PolicyEngine engineMgr;
96     @Mock
97     private WorkingMemory workMem;
98     @Mock
99     private FactHandle factHandle;
100     @Mock
101     private Operator policyOperator;
102     @Mock
103     private Operation policyOperation;
104     @Mock
105     private Actor policyActor;
106     @Mock
107     private EventManagerServices services;
108     @Mock
109     private ActorService actors;
110     @Mock
111     private OperationHistoryDataManager dataMgr;
112     @Mock
113     private ExecutorService executor;
114     @Mock
115     private MyStep stepa;
116     @Mock
117     private MyStep stepb;
118
119     private List<LockImpl> locks;
120     private ToscaPolicy tosca;
121     private ControlLoopParams params;
122     private VirtualControlLoopEvent event;
123     private ClEventManagerWithEvent<MyStep> mgr;
124
125     /**
126      * Sets up.
127      */
128     @Before
129     public void setUp() throws ControlLoopException, CoderException {
130         when(services.getActorService()).thenReturn(actors);
131         when(services.getDataManager()).thenReturn(dataMgr);
132
133         when(workMem.getFactHandle(any())).thenReturn(factHandle);
134
135         event = new VirtualControlLoopEvent();
136         event.setRequestId(REQ_ID);
137         event.setTarget(TARGET_PROP);
138         event.setAai(new TreeMap<>(Map.of(TARGET_PROP, MY_TARGET)));
139         event.setClosedLoopEventStatus(ControlLoopEventStatus.ONSET);
140         event.setClosedLoopControlName(CL_NAME);
141         event.setTargetType(ControlLoopTargetType.VNF);
142
143         params = new ControlLoopParams();
144         params.setClosedLoopControlName(CL_NAME);
145         params.setPolicyName(POLICY_NAME);
146         params.setPolicyScope(POLICY_SCOPE);
147         params.setPolicyVersion(POLICY_VERSION);
148
149         loadPolicy(EVENT_MGR_SIMPLE_YAML);
150
151         locks = new ArrayList<>();
152
153         mgr = new MyManager(services, params, event, workMem);
154     }
155
156     @Test
157     public void testConstructor() {
158         assertEquals(POLICY_NAME, mgr.getPolicyName());
159         assertSame(event, mgr.getEvent());
160
161         // valid
162         assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
163
164         // invalid
165         event.setTarget("");
166         assertThatThrownBy(() -> new MyManager(services, params, event, workMem))
167                         .isInstanceOf(ControlLoopException.class);
168     }
169
170     @Test
171     public void testPopulateNotification() throws Exception {
172         loadPolicy(EVENT_MGR_MULTI_YAML);
173         mgr = new MyManager(services, params, event, workMem);
174
175         // before started
176         assertNotNull(mgr.makeNotification());
177
178         mgr.start();
179
180         mgr.addToHistory(makeCompletedOutcome());
181         mgr.addToHistory(makeCompletedOutcome());
182         mgr.addToHistory(makeCompletedOutcome());
183
184         // check notification while running
185         VirtualControlLoopNotification notif = mgr.makeNotification();
186         assertThat(notif.getMessage()).contains(SIMPLE_ACTOR);
187         assertThat(notif.getHistory()).hasSize(3);
188         assertThat(notif.getAai()).isEqualTo(event.getAai());
189         assertThat(notif.getClosedLoopAlarmEnd()).isEqualTo(event.getClosedLoopAlarmEnd());
190         assertThat(notif.getClosedLoopAlarmStart()).isEqualTo(event.getClosedLoopAlarmStart());
191         assertThat(notif.getClosedLoopControlName()).isEqualTo(event.getClosedLoopControlName());
192         assertThat(notif.getClosedLoopEventClient()).isEqualTo(event.getClosedLoopEventClient());
193         assertThat(notif.getFrom()).isEqualTo("policy");
194         assertThat(notif.getTarget()).isEqualTo(event.getTarget());
195         assertThat(notif.getTargetType()).isEqualTo(event.getTargetType());
196
197         // indicate success and load the next policy - should clear the partial history
198         mgr.loadNextPolicy(OperationResult.SUCCESS);
199
200         // check notification
201         notif = mgr.makeNotification();
202         assertNull(notif.getMessage());
203         assertThat(notif.getHistory()).isEmpty();
204
205         // add outcomes and check again
206         mgr.addToHistory(makeCompletedOutcome());
207         mgr.addToHistory(makeCompletedOutcome());
208
209         notif = mgr.makeNotification();
210         assertNotNull(notif.getMessage());
211
212         // should only have history for last two outcomes
213         assertThat(notif.getHistory()).hasSize(2);
214
215         // indicate failure - should go to final state
216         mgr.loadNextPolicy(OperationResult.FAILURE);
217
218         // check notification
219         notif = mgr.makeNotification();
220         assertNull(notif.getMessage());
221
222         // should be no history
223         assertThat(notif.getHistory()).isEmpty();
224
225         // null case
226         assertThatThrownBy(() -> mgr.loadNextPolicy(null)).isInstanceOf(NullPointerException.class)
227                         .hasMessageContaining("lastResult");
228     }
229
230     @Test
231     public void testStoreInDataBase() throws ControlLoopException {
232         mgr.start();
233         OperationOutcome outcome = makeOutcome();
234         mgr.addToHistory(outcome);
235
236         mgr.storeInDataBase(mgr.getPartialHistory().peekLast(), MY_TARGET);
237
238         verify(dataMgr).store(REQ_ID.toString(), event.getClosedLoopControlName(), event, MY_TARGET,
239                         mgr.getPartialHistory().peekLast().getClOperation());
240     }
241
242     @Test
243     public void testMakeControlLoopResponse() {
244         final OperationOutcome outcome = new OperationOutcome();
245
246         ControlLoopResponse resp = mgr.makeControlLoopResponse(outcome);
247         assertNotNull(resp);
248         assertEquals("DCAE", resp.getTarget());
249         assertEquals(event.getClosedLoopControlName(), resp.getClosedLoopControlName());
250         assertEquals(event.getPolicyName(), resp.getPolicyName());
251         assertEquals(event.getPolicyVersion(), resp.getPolicyVersion());
252         assertEquals(REQ_ID, resp.getRequestId());
253         assertEquals(event.getVersion(), resp.getVersion());
254     }
255
256     @Test
257     public void testOnNewEvent() {
258         VirtualControlLoopEvent event2 = new VirtualControlLoopEvent(event);
259         assertEquals(NewEventStatus.FIRST_ONSET, mgr.onNewEvent(event2));
260
261         event2.setPayload("other payload");
262         assertEquals(NewEventStatus.SUBSEQUENT_ONSET, mgr.onNewEvent(event2));
263         assertEquals(NewEventStatus.SUBSEQUENT_ONSET, mgr.onNewEvent(event2));
264         assertEquals(NewEventStatus.FIRST_ONSET, mgr.onNewEvent(event));
265
266         event2.setClosedLoopEventStatus(ControlLoopEventStatus.ABATED);
267         assertEquals(NewEventStatus.FIRST_ABATEMENT, mgr.onNewEvent(event2));
268
269         assertEquals(NewEventStatus.SUBSEQUENT_ABATEMENT, mgr.onNewEvent(event2));
270         assertEquals(NewEventStatus.SUBSEQUENT_ABATEMENT, mgr.onNewEvent(event2));
271
272         event2.setClosedLoopEventStatus(null);
273         assertEquals(NewEventStatus.SYNTAX_ERROR, mgr.onNewEvent(event2));
274     }
275
276     @Test
277     public void testCheckEventSyntax() {
278         // initially, it's valid
279         assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
280
281         event.setTarget(null);
282         assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class)
283                         .hasMessage("No target field");
284
285         // abated supersedes previous errors - so it shouldn't throw an exception
286         event.setClosedLoopEventStatus(ControlLoopEventStatus.ABATED);
287         assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
288
289         event.setRequestId(null);
290         assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class)
291                         .hasMessage("No request ID");
292
293         event.setClosedLoopControlName(null);
294         assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class)
295                         .hasMessage("No control loop name");
296     }
297
298     @Test
299     public void testValidateStatus() {
300         event.setClosedLoopEventStatus(ControlLoopEventStatus.ONSET);
301         assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
302
303         event.setClosedLoopEventStatus(ControlLoopEventStatus.ABATED);
304         assertThatCode(() -> mgr.checkEventSyntax(event)).doesNotThrowAnyException();
305
306         event.setClosedLoopEventStatus(null);
307         assertThatCode(() -> mgr.checkEventSyntax(event)).isInstanceOf(ControlLoopException.class)
308                         .hasMessage("Invalid value in closedLoopEventStatus");
309     }
310
311     private void loadPolicy(String fileName) throws CoderException {
312         ToscaServiceTemplate template =
313                         yamlCoder.decode(ResourceUtils.getResourceAsString(fileName), ToscaServiceTemplate.class);
314         tosca = template.getToscaTopologyTemplate().getPolicies().get(0).values().iterator().next();
315
316         params.setToscaPolicy(tosca);
317     }
318
319     private OperationOutcome makeCompletedOutcome() {
320         OperationOutcome outcome = makeOutcome();
321         outcome.setEnd(outcome.getStart());
322
323         return outcome;
324     }
325
326     private OperationOutcome makeOutcome() {
327         OperationOutcome outcome = new OperationOutcome();
328         outcome.setActor(SIMPLE_ACTOR);
329         outcome.setOperation(SIMPLE_OPERATION);
330         outcome.setMessage(OUTCOME_MSG);
331         outcome.setResult(OperationResult.SUCCESS);
332         outcome.setStart(Instant.now());
333         outcome.setTarget(MY_TARGET);
334
335         return outcome;
336     }
337
338
339     private class MyManager extends ClEventManagerWithEvent<MyStep> {
340         private static final long serialVersionUID = 1L;
341
342         public MyManager(EventManagerServices services, ControlLoopParams params, VirtualControlLoopEvent event,
343                         WorkingMemory workMem) throws ControlLoopException {
344
345             super(services, params, event, workMem);
346         }
347
348         @Override
349         protected ExecutorService getBlockingExecutor() {
350             return executor;
351         }
352
353         @Override
354         protected void makeLock(String targetEntity, String requestId, int holdSec, LockCallback callback) {
355             LockImpl lock = new LockImpl(LockState.ACTIVE, targetEntity, requestId, holdSec, callback);
356             locks.add(lock);
357             callback.lockAvailable(lock);
358         }
359
360         @Override
361         protected PolicyEngine getPolicyEngineManager() {
362             return engineMgr;
363         }
364
365         @Override
366         protected void loadPolicyStep(ControlLoopOperationParams params) {
367             getSteps().add(new MyStep(this, params, getEvent()));
368         }
369     }
370
371     private static class MyStep extends Step {
372         public MyStep(StepContext stepContext, ControlLoopOperationParams params, VirtualControlLoopEvent event) {
373             super(params, new AtomicReference<>());
374         }
375     }
376 }