2acb576811d8e70047f84261f6f721a8fa77601b
[policy/apex-pdp.git] /
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.assertj.core.api.Assertions.assertThatThrownBy;
25 import static org.junit.Assert.assertEquals;
26 import static org.junit.Assert.assertNotNull;
27
28 import java.util.LinkedHashMap;
29 import java.util.Map;
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.ContextException;
37 import org.onap.policy.apex.context.parameters.SchemaParameters;
38 import org.onap.policy.apex.core.engine.ExecutorParameters;
39 import org.onap.policy.apex.core.engine.context.ApexInternalContext;
40 import org.onap.policy.apex.core.engine.event.EnEvent;
41 import org.onap.policy.apex.core.engine.executor.exception.StateMachineException;
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() throws StateMachineException, ContextException {
187         StateMachineExecutor executor =
188             new StateMachineExecutor(executorFactoryMock, new AxArtifactKey("OwnerKey:0.0.1"));
189
190         assertThatThrownBy(() -> executor.execute(0, null, incomingEventMock))
191             .hasMessage("no states defined on state machine");
192         executor.setContext(null, axPolicy, internalContextMock);
193         assertEquals("Policy:0.0.1", executor.getKey().getId());
194         assertEquals(null, executor.getParent());
195         assertEquals(internalContextMock, executor.getContext());
196         assertEquals(null, executor.getNext());
197         assertEquals(null, executor.getIncoming());
198         assertEquals(null, executor.getOutgoing());
199         assertEquals(axPolicy, executor.getSubject());
200
201         executor.setParameters(new ExecutorParameters());
202         executor.setNext(nextExecutorMock);
203         assertEquals(nextExecutorMock, executor.getNext());
204         executor.setNext(null);
205         assertEquals(null, executor.getNext());
206
207         assertThatThrownBy(() -> executor.executePre(0, null, null))
208             .hasMessage("execution pre work not implemented on class");
209         assertThatThrownBy(() -> executor.executePost(false))
210             .hasMessage("execution post work not implemented on class");
211         assertThatThrownBy(executor::prepare)
212             .isInstanceOf(NullPointerException.class);
213         axPolicy.setFirstState("BadState");
214         executor.setContext(null, axPolicy, internalContextMock);
215         assertThatThrownBy(() -> executor.execute(0, null, incomingEventMock))
216             .hasMessage("first state not defined on state machine");
217         axPolicy.setFirstState("state0");
218         executor.setContext(null, axPolicy, internalContextMock);
219         executor.execute(0, null, incomingEventMock);
220
221         dummyTsle.setTaskNo(0);
222         executor.execute(0, null, incomingEventMock);
223
224         AxReferenceKey badStateKey = new AxReferenceKey("Policy:0.0.1:PName:BadState");
225         axPolicy.getStateMap().get("State1").getStateOutputs().get("stateOutput1").setNextState(badStateKey);
226         dummyTsle.setTaskNo(0);
227         assertThatThrownBy(() -> executor.execute(0, null, incomingEventMock))
228             .hasMessage("state execution failed, next state \"Policy:0.0.1:PName:BadState\" not found");
229         axPolicy.getStateMap().get("State1").getStateOutputs().get("stateOutput1")
230             .setNextState(AxReferenceKey.getNullKey());
231         dummyTsle.setTaskNo(0);
232         executor.execute(0, null, incomingEventMock);
233
234         axPolicy.getStateMap().get("State1").setTrigger(new AxArtifactKey("BadTrigger:0.0.1"));
235         dummyTsle.setTaskNo(0);
236         assertThatThrownBy(() -> executor.execute(0, null, incomingEventMock))
237             .hasMessage("incoming event \"Event1:0.0.1\" does not match trigger \"BadTrigger:0.0.1\" "
238                 + "of state \"Policy:0.0.1:NULL:state1\"");
239         axPolicy.getStateMap().get("State1").setTrigger(new AxArtifactKey("Event1:0.0.1"));
240         dummyTsle.setTaskNo(0);
241         executor.execute(0, null, incomingEventMock);
242
243         AxStateFinalizerLogic savedSfl = axPolicy.getStateMap().get("State1").getStateFinalizerLogicMap().get("sfl");
244         axPolicy.getStateMap().get("State1").getStateFinalizerLogicMap().put("sfl", null);
245         assertThatThrownBy(() -> executor.setContext(null, axPolicy, internalContextMock))
246             .hasMessage("state finalizer logic on task reference "
247                 + "\"AxStateTaskReference:(stateKey=AxReferenceKey:(parentKeyName=Policy,"
248                 + "parentKeyVersion=0.0.1,parentLocalName=state1,localName=str1),"
249                 + "outputType=LOGIC,output=AxReferenceKey:(parentKeyName=Policy,parentKeyVersion=0.0.1,"
250                 + "parentLocalName=state1,localName=sfl))\" on state \"Policy:0.0.1:NULL:state1\" " + "does not exist");
251         axPolicy.getStateMap().get("State1").getStateFinalizerLogicMap().put("sfl", savedSfl);
252         executor.setContext(null, axPolicy, internalContextMock);
253
254         dummyTsle.setTaskNo(0);
255         executor.execute(0, null, incomingEventMock);
256
257         AxArtifactKey task1Key = new AxArtifactKey("task1:0.0.1");
258         axPolicy.getStateMap().get("State1").getTaskReferences().get(task1Key)
259             .setStateTaskOutputType(AxStateTaskOutputType.UNDEFINED);
260         assertThatThrownBy(() -> executor.setContext(null, axPolicy, internalContextMock))
261             .hasMessage("invalid state output type on task reference \"AxStateTaskReference:(stateKey"
262                 + "=AxReferenceKey:(parentKeyName=Policy,parentKeyVersion=0.0.1,parentLocalName=state1,localName=str1),"
263                 + "outputType=UNDEFINED,output=AxReferenceKey:(parentKeyName=Policy,"
264                 + "parentKeyVersion=0.0.1,parentLocalName=state1,localName=sfl))\" "
265                 + "on state \"Policy:0.0.1:NULL:state1\"");
266         axPolicy.getStateMap().get("State1").getTaskReferences().get(task1Key)
267             .setStateTaskOutputType(AxStateTaskOutputType.LOGIC);
268         executor.setContext(null, axPolicy, internalContextMock);
269
270         dummyTsle.setTaskNo(0);
271         executor.execute(0, null, incomingEventMock);
272
273         dummyTsle.setTaskNo(0);
274         dummySfle.setReturnBad(true);
275         assertThatThrownBy(() -> executor.execute(0, null, incomingEventMock))
276             .hasMessage("State execution of state \"Policy:0.0.1:NULL:state1\" on task \"task1:0.0.1\""
277                 + " failed: state output definition for state output \"stateOutputBad\" not found for "
278                 + "state \"Policy:0.0.1:NULL:state1\"");
279         dummyTsle.setTaskNo(0);
280         dummySfle.setReturnBad(false);
281         executor.execute(0, null, incomingEventMock);
282
283         assertThatThrownBy(executor::cleanUp)
284             .hasMessage("cleanUp() not implemented on class");
285     }
286
287     @Test
288     public void testStateOutput() throws StateMachineException {
289         final StateOutput output =
290             new StateOutput(axPolicy.getStateMap().get("State0").getStateOutputs().get("stateOutput0"));
291         assertNotNull(output);
292
293         assertEquals("stateOutput0", output.getStateOutputDefinition().getKey().getLocalName());
294
295         assertThatThrownBy(() -> output.setEventFields(null, null))
296             .hasMessage("incomingFieldDefinitionMap may not be null");
297         Map<String, AxField> incomingFieldDefinitionMap = new LinkedHashMap<>();
298         assertThatThrownBy(() -> output.setEventFields(incomingFieldDefinitionMap, null))
299             .hasMessage("eventFieldMap may not be null");
300         Map<String, Object> eventFieldMap = new LinkedHashMap<>();
301         output.setEventFields(incomingFieldDefinitionMap, eventFieldMap);
302
303         eventFieldMap.put("key", "Value");
304         assertThatThrownBy(() -> output.setEventFields(incomingFieldDefinitionMap, eventFieldMap))
305             .hasMessage("field definitions and values do not match for event Event1:0.0.1\n[]\n[key]");
306         AxField axBadFieldDefinition = new AxField();
307         incomingFieldDefinitionMap.put("key", axBadFieldDefinition);
308         assertThatThrownBy(() -> output.setEventFields(incomingFieldDefinitionMap, eventFieldMap))
309             .hasMessage("field \"key\" does not exist on event \"Event1:0.0.1\"");
310         incomingFieldDefinitionMap.clear();
311         eventFieldMap.clear();
312         AxArtifactKey stringSchemaKey = new AxArtifactKey("StringSchema:0.0.1");
313         AxReferenceKey fieldKey = new AxReferenceKey("Event1:0.0.1:event:Field0");
314         AxField event1Field0Definition = new AxField(fieldKey, stringSchemaKey);
315         incomingFieldDefinitionMap.put("Event1Field0", event1Field0Definition);
316         eventFieldMap.put("Event1Field0", "Value");
317         output.setEventFields(incomingFieldDefinitionMap, eventFieldMap);
318
319         StateOutput outputCopy = new StateOutput(axPolicy.getStateMap().get("State0")
320                 .getStateOutputs().get("stateOutput0"));
321
322         EnEvent incomingEvent = new EnEvent(new AxArtifactKey("Event0:0.0.1"));
323         outputCopy.copyUnsetFields(incomingEvent);
324
325         incomingEvent.put("Event1Field0", "Hello");
326         outputCopy.copyUnsetFields(incomingEvent);
327     }
328 }