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