7256b3f317ea7910d690e116dfb46403ab31a809
[policy/apex-pdp.git] / core / core-engine / src / test / java / org / onap / policy / apex / core / engine / executor / StateMachineExecutorTest.java
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2018 Ericsson. All rights reserved.
4  *  Modifications Copyright (C) 2020 Nordix Foundation.
5  * ================================================================================
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * SPDX-License-Identifier: Apache-2.0
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.policy.apex.core.engine.executor;
23
24 import static org.junit.Assert.assertEquals;
25 import static org.junit.Assert.assertNotNull;
26 import static org.junit.Assert.assertTrue;
27 import static org.junit.Assert.fail;
28
29 import java.util.LinkedHashMap;
30 import java.util.Map;
31
32 import org.junit.After;
33 import org.junit.Before;
34 import org.junit.Test;
35 import org.mockito.Mock;
36 import org.mockito.Mockito;
37 import org.mockito.MockitoAnnotations;
38 import org.onap.policy.apex.context.parameters.SchemaParameters;
39 import org.onap.policy.apex.core.engine.ExecutorParameters;
40 import org.onap.policy.apex.core.engine.context.ApexInternalContext;
41 import org.onap.policy.apex.core.engine.event.EnEvent;
42 import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
43 import org.onap.policy.apex.model.basicmodel.concepts.AxReferenceKey;
44 import org.onap.policy.apex.model.basicmodel.service.ModelService;
45 import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchema;
46 import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchemas;
47 import org.onap.policy.apex.model.eventmodel.concepts.AxEvent;
48 import org.onap.policy.apex.model.eventmodel.concepts.AxEvents;
49 import org.onap.policy.apex.model.eventmodel.concepts.AxField;
50 import org.onap.policy.apex.model.policymodel.concepts.AxPolicy;
51 import org.onap.policy.apex.model.policymodel.concepts.AxState;
52 import org.onap.policy.apex.model.policymodel.concepts.AxStateFinalizerLogic;
53 import org.onap.policy.apex.model.policymodel.concepts.AxStateOutput;
54 import org.onap.policy.apex.model.policymodel.concepts.AxStateTaskOutputType;
55 import org.onap.policy.apex.model.policymodel.concepts.AxStateTaskReference;
56 import org.onap.policy.apex.model.policymodel.concepts.AxTask;
57 import org.onap.policy.apex.model.policymodel.concepts.AxTasks;
58 import org.onap.policy.common.parameters.ParameterService;
59
60 /**
61  * Test task executor.
62  */
63 public class StateMachineExecutorTest {
64     @Mock
65     private ApexInternalContext internalContextMock;
66
67     @Mock
68     private Executor<EnEvent, EnEvent, AxPolicy, ApexInternalContext> nextExecutorMock;
69
70     @Mock
71     private ExecutorFactory executorFactoryMock;
72
73     @Mock
74     private EnEvent incomingEventMock;
75
76     private AxPolicy axPolicy = new AxPolicy();
77
78     private DummyTaskSelectExecutor dummyTsle;
79
80     private DummyStateFinalizerExecutor dummySfle;
81
82     /**
83      * Set up mocking.
84      */
85     @Before
86     public void startMocking() {
87         MockitoAnnotations.initMocks(this);
88
89         axPolicy.setKey(new AxArtifactKey("Policy:0.0.1"));
90
91         AxReferenceKey state0Key = new AxReferenceKey(axPolicy.getKey(), "state0");
92         AxState state0 = new AxState(state0Key);
93
94         AxReferenceKey state1Key = new AxReferenceKey(axPolicy.getKey(), "state1");
95         AxState state1 = new AxState(state1Key);
96
97         axPolicy.getStateMap().put("State0", state0);
98         axPolicy.getStateMap().put("State1", state1);
99         axPolicy.setFirstState("state0");
100
101         AxArtifactKey event0Key = new AxArtifactKey("Event0:0.0.1");
102         AxEvent event0 = new AxEvent(event0Key, "a.name.space", "source", "target");
103         AxArtifactKey event1Key = new AxArtifactKey("Event1:0.0.1");
104         AxEvent event1 = new AxEvent(event1Key, "a.name.space", "source", "target");
105         AxArtifactKey event2Key = new AxArtifactKey("Event2:0.0.1");
106         AxEvent event2 = new AxEvent(event2Key, "a.name.space", "source", "target");
107         AxEvents events = new AxEvents();
108         events.getEventMap().put(event0Key, event0);
109         events.getEventMap().put(event1Key, event1);
110         events.getEventMap().put(event2Key, event2);
111         ModelService.registerModel(AxEvents.class, events);
112
113         AxReferenceKey fieldKey = new AxReferenceKey("Event1:0.0.1:event:Field0");
114         AxArtifactKey stringSchemaKey = new AxArtifactKey("StringSchema:0.0.1");
115         AxContextSchema stringSchema = new AxContextSchema(stringSchemaKey, "Java", "java.lang.String");
116         AxContextSchemas schemas = new AxContextSchemas();
117         schemas.getSchemasMap().put(stringSchemaKey, stringSchema);
118         ModelService.registerModel(AxContextSchemas.class, schemas);
119
120         AxField event1Field0Definition = new AxField(fieldKey, stringSchemaKey);
121         event1.getParameterMap().put("Event1Field0", event1Field0Definition);
122
123         event0.getParameterMap().put("Event1Field0", event1Field0Definition);
124         event0.getParameterMap().put("UnusedField", event1Field0Definition);
125
126         Mockito.doReturn(event0Key).when(incomingEventMock).getKey();
127         Mockito.doReturn(event0).when(incomingEventMock).getAxEvent();
128
129         state0.setTrigger(event0Key);
130         state1.setTrigger(event1Key);
131
132         AxArtifactKey task0Key = new AxArtifactKey("task0:0.0.1");
133         AxTask task0 = new AxTask(task0Key);
134
135         AxArtifactKey task1Key = new AxArtifactKey("task1:0.0.1");
136         AxTask task1 = new AxTask(task1Key);
137
138         AxTasks tasks = new AxTasks();
139         tasks.getTaskMap().put(task0Key, task0);
140         tasks.getTaskMap().put(task1Key, task1);
141         ModelService.registerModel(AxTasks.class, tasks);
142
143         ParameterService.register(new SchemaParameters());
144
145         AxReferenceKey stateOutput0Key = new AxReferenceKey("Policy:0.0.1:state0:stateOutput0");
146         AxStateOutput stateOutput0 = new AxStateOutput(stateOutput0Key, event1Key, state1.getKey());
147
148         state0.getStateOutputs().put(stateOutput0Key.getLocalName(), stateOutput0);
149
150         AxReferenceKey stateOutput1Key = new AxReferenceKey("Policy:0.0.1:state0:stateOutput1");
151         AxStateOutput stateOutput1 = new AxStateOutput(stateOutput1Key, event2Key, AxReferenceKey.getNullKey());
152
153         state1.getStateOutputs().put(stateOutput1Key.getLocalName(), stateOutput1);
154
155         AxReferenceKey str0Key = new AxReferenceKey("Policy:0.0.1:state0:str0");
156         AxStateTaskReference str0 = new AxStateTaskReference(str0Key, AxStateTaskOutputType.DIRECT, stateOutput0Key);
157         state0.getTaskReferences().put(task0Key, str0);
158
159         AxReferenceKey sflKey = new AxReferenceKey("Policy:0.0.1:state1:sfl");
160         AxStateFinalizerLogic sfl = new AxStateFinalizerLogic(sflKey, "Java", "State fianlizer logic");
161         state1.getStateFinalizerLogicMap().put("sfl", sfl);
162
163         AxReferenceKey str1Key = new AxReferenceKey("Policy:0.0.1:state1:str1");
164         AxStateTaskReference str1 = new AxStateTaskReference(str1Key, AxStateTaskOutputType.LOGIC, sflKey);
165         state1.getTaskReferences().put(task1Key, str1);
166
167         Mockito.doReturn(new DummyTaskExecutor(true)).when(executorFactoryMock).getTaskExecutor(Mockito.anyObject(),
168             Mockito.anyObject(), Mockito.anyObject());
169
170         dummyTsle = new DummyTaskSelectExecutor(true);
171         Mockito.doReturn(dummyTsle).when(executorFactoryMock).getTaskSelectionExecutor(Mockito.anyObject(),
172             Mockito.anyObject(), Mockito.anyObject());
173
174         dummySfle = new DummyStateFinalizerExecutor(true);
175         Mockito.doReturn(dummySfle).when(executorFactoryMock).getStateFinalizerExecutor(Mockito.anyObject(),
176             Mockito.anyObject(), Mockito.anyObject());
177     }
178
179     @After
180     public void cleardown() {
181         ParameterService.clear();
182         ModelService.clear();
183     }
184
185     @Test
186     public void testStateMachineExecutor() {
187         StateMachineExecutor executor =
188             new StateMachineExecutor(executorFactoryMock, new AxArtifactKey("OwnerKey:0.0.1"));
189
190         try {
191             executor.execute(0, null, incomingEventMock);
192             fail("test should throw an exception");
193         } catch (Exception ex) {
194             assertEquals("no states defined on state machine", ex.getMessage());
195         }
196
197         executor.setContext(null, axPolicy, internalContextMock);
198         assertEquals("Policy:0.0.1", executor.getKey().getId());
199         assertEquals(null, executor.getParent());
200         assertEquals(internalContextMock, executor.getContext());
201         assertEquals(null, executor.getNext());
202         assertEquals(null, executor.getIncoming());
203         assertEquals(null, executor.getOutgoing());
204         assertEquals(axPolicy, executor.getSubject());
205
206         executor.setParameters(new ExecutorParameters());
207         executor.setNext(nextExecutorMock);
208         assertEquals(nextExecutorMock, executor.getNext());
209         executor.setNext(null);
210         assertEquals(null, executor.getNext());
211
212         try {
213             executor.executePre(0, null, null);
214             fail("test should throw an exception");
215         } catch (Exception ex) {
216             assertEquals("execution pre work not implemented on class", ex.getMessage());
217         }
218
219         try {
220             executor.executePost(false);
221             fail("test should throw an exception");
222         } catch (Exception ex) {
223             assertEquals("execution post work not implemented on class", ex.getMessage());
224         }
225
226         try {
227             executor.prepare();
228             fail("test should throw an exception");
229         } catch (Exception e) {
230             assertTrue(e instanceof NullPointerException);
231         }
232
233         axPolicy.setFirstState("BadState");
234         executor.setContext(null, axPolicy, internalContextMock);
235         try {
236             executor.execute(0, null, incomingEventMock);
237             fail("test should throw an exception");
238         } catch (Exception ex) {
239             assertEquals("first state not defined on state machine", ex.getMessage());
240         }
241
242         axPolicy.setFirstState("state0");
243         executor.setContext(null, axPolicy, internalContextMock);
244         try {
245             executor.execute(0, null, incomingEventMock);
246         } catch (Exception ex) {
247             fail("test should not throw an exception");
248         }
249
250         dummyTsle.setTaskNo(0);
251         try {
252             executor.execute(0, null, incomingEventMock);
253         } catch (Exception ex) {
254             fail("test should not throw an exception");
255         }
256
257         AxReferenceKey badStateKey = new AxReferenceKey("Policy:0.0.1:PName:BadState");
258         axPolicy.getStateMap().get("State1").getStateOutputs().get("stateOutput1").setNextState(badStateKey);
259         dummyTsle.setTaskNo(0);
260         try {
261             executor.execute(0, null, incomingEventMock);
262             fail("test should throw an exception");
263         } catch (Exception ex) {
264             assertEquals("state execution failed, next state \"Policy:0.0.1:PName:BadState\" not found",
265                 ex.getMessage());
266         }
267
268         axPolicy.getStateMap().get("State1").getStateOutputs().get("stateOutput1")
269             .setNextState(AxReferenceKey.getNullKey());
270         dummyTsle.setTaskNo(0);
271         try {
272             executor.execute(0, null, incomingEventMock);
273         } catch (Exception ex) {
274             fail("test should not throw an exception");
275         }
276
277         axPolicy.getStateMap().get("State1").setTrigger(new AxArtifactKey("BadTrigger:0.0.1"));
278         dummyTsle.setTaskNo(0);
279         try {
280             executor.execute(0, null, incomingEventMock);
281             fail("test should throw an exception");
282         } catch (Exception ex) {
283             assertEquals("incoming event \"Event1:0.0.1\" does not match trigger \"BadTrigger:0.0.1\" "
284                 + "of state \"Policy:0.0.1:NULL:state1\"", ex.getMessage());
285         }
286
287         axPolicy.getStateMap().get("State1").setTrigger(new AxArtifactKey("Event1:0.0.1"));
288         dummyTsle.setTaskNo(0);
289         try {
290             executor.execute(0, null, incomingEventMock);
291         } catch (Exception ex) {
292             fail("test should not throw an exception");
293         }
294
295         AxStateFinalizerLogic savedSfl = axPolicy.getStateMap().get("State1").getStateFinalizerLogicMap().get("sfl");
296         axPolicy.getStateMap().get("State1").getStateFinalizerLogicMap().put("sfl", null);
297         try {
298             executor.setContext(null, axPolicy, internalContextMock);
299             fail("test should throw an exception");
300         } catch (Exception ex) {
301             assertEquals("state finalizer logic on task reference "
302                 + "\"AxStateTaskReference:(stateKey=AxReferenceKey:(parentKeyName=Policy,"
303                 + "parentKeyVersion=0.0.1,parentLocalName=state1,localName=str1),"
304                 + "outputType=LOGIC,output=AxReferenceKey:(parentKeyName=Policy,parentKeyVersion=0.0.1,"
305                 + "parentLocalName=state1,localName=sfl))\" on state \"Policy:0.0.1:NULL:state1\" " + "does not exist",
306                 ex.getMessage());
307         }
308
309         axPolicy.getStateMap().get("State1").getStateFinalizerLogicMap().put("sfl", savedSfl);
310         executor.setContext(null, axPolicy, internalContextMock);
311
312         dummyTsle.setTaskNo(0);
313         try {
314             executor.execute(0, null, incomingEventMock);
315         } catch (Exception ex) {
316             fail("test should not throw an exception");
317         }
318
319         AxArtifactKey task1Key = new AxArtifactKey("task1:0.0.1");
320         try {
321             axPolicy.getStateMap().get("State1").getTaskReferences().get(task1Key)
322                 .setStateTaskOutputType(AxStateTaskOutputType.UNDEFINED);
323             executor.setContext(null, axPolicy, internalContextMock);
324             fail("test should throw an exception");
325         } catch (Exception ex) {
326             assertEquals("invalid state output type on task reference \"AxStateTaskReference:(stateKey=AxReferenceKey:"
327                 + "(parentKeyName=Policy,parentKeyVersion=0.0.1,parentLocalName=state1,localName=str1),"
328                 + "outputType=UNDEFINED,output=AxReferenceKey:(parentKeyName=Policy,"
329                 + "parentKeyVersion=0.0.1,parentLocalName=state1,localName=sfl))\" "
330                 + "on state \"Policy:0.0.1:NULL:state1\"", ex.getMessage());
331         }
332
333         axPolicy.getStateMap().get("State1").getTaskReferences().get(task1Key)
334             .setStateTaskOutputType(AxStateTaskOutputType.LOGIC);
335         executor.setContext(null, axPolicy, internalContextMock);
336
337         dummyTsle.setTaskNo(0);
338         try {
339             executor.execute(0, null, incomingEventMock);
340         } catch (Exception ex) {
341             fail("test should not throw an exception");
342         }
343
344         dummyTsle.setTaskNo(0);
345         dummySfle.setReturnBad(true);
346         try {
347             executor.execute(0, null, incomingEventMock);
348             fail("test should throw an exception");
349         } catch (Exception ex) {
350             assertEquals("State execution of state \"Policy:0.0.1:NULL:state1\" on task \"task1:0.0.1\" failed: "
351                 + "state output definition for state output \"stateOutputBad\" not found for "
352                 + "state \"Policy:0.0.1:NULL:state1\"", ex.getMessage());
353         }
354
355         dummyTsle.setTaskNo(0);
356         dummySfle.setReturnBad(false);
357         try {
358             executor.execute(0, null, incomingEventMock);
359         } catch (Exception ex) {
360             fail("test should not throw an exception");
361         }
362
363         try {
364             executor.cleanUp();
365             fail("test should throw an exception");
366         } catch (Exception ex) {
367             assertEquals("cleanUp() not implemented on class", ex.getMessage());
368         }
369     }
370
371     @Test
372     public void testStateOutput() {
373         StateOutput output =
374             new StateOutput(axPolicy.getStateMap().get("State0").getStateOutputs().get("stateOutput0"));
375         assertNotNull(output);
376
377         assertEquals("stateOutput0", output.getStateOutputDefinition().getKey().getLocalName());
378
379         try {
380             output.setEventFields(null, null);
381             fail("test should throw an exception");
382         } catch (Exception ex) {
383             assertEquals("incomingFieldDefinitionMap may not be null", ex.getMessage());
384         }
385
386         Map<String, AxField> incomingFieldDefinitionMap = new LinkedHashMap<>();
387         try {
388             output.setEventFields(incomingFieldDefinitionMap, null);
389             fail("test should throw an exception");
390         } catch (Exception ex) {
391             assertEquals("eventFieldMap may not be null", ex.getMessage());
392         }
393
394         Map<String, Object> eventFieldMap = new LinkedHashMap<>();
395         try {
396             output.setEventFields(incomingFieldDefinitionMap, eventFieldMap);
397         } catch (Exception ex) {
398             fail("test should not throw an exception");
399         }
400
401         eventFieldMap.put("key", "Value");
402         try {
403             output.setEventFields(incomingFieldDefinitionMap, eventFieldMap);
404             fail("test should throw an exception");
405         } catch (Exception ex) {
406             assertEquals("field definitions and values do not match for event Event1:0.0.1\n[]\n[key]",
407                 ex.getMessage());
408         }
409
410         AxField axBadFieldDefinition = new AxField();
411         incomingFieldDefinitionMap.put("key", axBadFieldDefinition);
412         try {
413             output.setEventFields(incomingFieldDefinitionMap, eventFieldMap);
414             fail("test should throw an exception");
415         } catch (Exception ex) {
416             assertEquals("field \"key\" does not exist on event \"Event1:0.0.1\"", ex.getMessage());
417         }
418
419         incomingFieldDefinitionMap.clear();
420         eventFieldMap.clear();
421         AxArtifactKey stringSchemaKey = new AxArtifactKey("StringSchema:0.0.1");
422         AxReferenceKey fieldKey = new AxReferenceKey("Event1:0.0.1:event:Field0");
423         AxField event1Field0Definition = new AxField(fieldKey, stringSchemaKey);
424         incomingFieldDefinitionMap.put("Event1Field0", event1Field0Definition);
425         eventFieldMap.put("Event1Field0", "Value");
426         try {
427             output.setEventFields(incomingFieldDefinitionMap, eventFieldMap);
428         } catch (Exception ex) {
429             fail("test should not throw an exception");
430         }
431
432         output = new StateOutput(axPolicy.getStateMap().get("State0").getStateOutputs().get("stateOutput0"));
433
434         EnEvent incomingEvent = new EnEvent(new AxArtifactKey("Event0:0.0.1"));
435         output.copyUnsetFields(incomingEvent);
436
437         incomingEvent.put("Event1Field0", "Hello");
438         output.copyUnsetFields(incomingEvent);
439     }
440 }