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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 * SPDX-License-Identifier: Apache-2.0
18 * ============LICENSE_END=========================================================
21 package org.onap.policy.apex.core.engine.executor;
23 import static org.junit.Assert.assertEquals;
24 import static org.junit.Assert.assertNotNull;
25 import static org.junit.Assert.fail;
27 import java.util.LinkedHashMap;
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;
62 public class StateMachineExecutorTest {
64 private ApexInternalContext internalContextMock;
67 private Executor<EnEvent, EnEvent, AxPolicy, ApexInternalContext> nextExecutorMock;
70 private ExecutorFactory executorFactoryMock;
73 private EnEvent incomingEventMock;
75 private AxPolicy axPolicy = new AxPolicy();
77 private DummyTaskSelectExecutor dummyTsle;
79 private DummyStateFinalizerExecutor dummySfle;
85 public void startMocking() {
86 MockitoAnnotations.initMocks(this);
88 axPolicy.setKey(new AxArtifactKey("Policy:0.0.1"));
90 AxReferenceKey state0Key = new AxReferenceKey(axPolicy.getKey(), "state0");
91 AxState state0 = new AxState(state0Key);
93 AxReferenceKey state1Key = new AxReferenceKey(axPolicy.getKey(), "state1");
94 AxState state1 = new AxState(state1Key);
96 axPolicy.getStateMap().put("State0", state0);
97 axPolicy.getStateMap().put("State1", state1);
98 axPolicy.setFirstState("state0");
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);
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);
119 AxField event1Field0Definition = new AxField(fieldKey, stringSchemaKey);
120 event1.getParameterMap().put("Event1Field0", event1Field0Definition);
122 event0.getParameterMap().put("Event1Field0", event1Field0Definition);
123 event0.getParameterMap().put("UnusedField", event1Field0Definition);
125 Mockito.doReturn(event0Key).when(incomingEventMock).getKey();
126 Mockito.doReturn(event0).when(incomingEventMock).getAxEvent();
128 state0.setTrigger(event0Key);
129 state1.setTrigger(event1Key);
131 AxArtifactKey task0Key = new AxArtifactKey("task0:0.0.1");
132 AxTask task0 = new AxTask(task0Key);
134 AxArtifactKey task1Key = new AxArtifactKey("task1:0.0.1");
135 AxTask task1 = new AxTask(task1Key);
137 AxTasks tasks = new AxTasks();
138 tasks.getTaskMap().put(task0Key, task0);
139 tasks.getTaskMap().put(task1Key, task1);
140 ModelService.registerModel(AxTasks.class, tasks);
142 ParameterService.register(new SchemaParameters());
144 AxReferenceKey stateOutput0Key = new AxReferenceKey("Policy:0.0.1:state0:stateOutput0");
145 AxStateOutput stateOutput0 = new AxStateOutput(stateOutput0Key, event1Key, state1.getKey());
147 state0.getStateOutputs().put(stateOutput0Key.getLocalName(), stateOutput0);
149 AxReferenceKey stateOutput1Key = new AxReferenceKey("Policy:0.0.1:state0:stateOutput1");
150 AxStateOutput stateOutput1 = new AxStateOutput(stateOutput1Key, event2Key, AxReferenceKey.getNullKey());
152 state1.getStateOutputs().put(stateOutput1Key.getLocalName(), stateOutput1);
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);
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);
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);
166 Mockito.doReturn(new DummyTaskExecutor(true)).when(executorFactoryMock).getTaskExecutor(Mockito.anyObject(),
167 Mockito.anyObject(), Mockito.anyObject());
169 dummyTsle = new DummyTaskSelectExecutor(true);
170 Mockito.doReturn(dummyTsle).when(executorFactoryMock).getTaskSelectionExecutor(Mockito.anyObject(),
171 Mockito.anyObject(), Mockito.anyObject());
173 dummySfle = new DummyStateFinalizerExecutor(true);
174 Mockito.doReturn(dummySfle).when(executorFactoryMock).getStateFinalizerExecutor(Mockito.anyObject(),
175 Mockito.anyObject(), Mockito.anyObject());
179 public void cleardown() {
180 ParameterService.clear();
181 ModelService.clear();
185 public void testStateMachineExecutor() {
186 StateMachineExecutor executor = new StateMachineExecutor(executorFactoryMock,
187 new AxArtifactKey("OwnerKey:0.0.1"));
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());
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());
205 executor.setParameters(new ExecutorParameters());
206 executor.setNext(nextExecutorMock);
207 assertEquals(nextExecutorMock, executor.getNext());
208 executor.setNext(null);
209 assertEquals(null, executor.getNext());
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());
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());
227 } catch (StateMachineException e) {
228 fail("test should not throw an exception");
231 axPolicy.setFirstState("BadState");
232 executor.setContext(null, axPolicy, internalContextMock);
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());
240 axPolicy.setFirstState("state0");
241 executor.setContext(null, axPolicy, internalContextMock);
243 executor.execute(0, incomingEventMock);
244 } catch (Exception ex) {
245 fail("test should not throw an exception");
248 dummyTsle.setTaskNo(0);
250 executor.execute(0, incomingEventMock);
251 } catch (Exception ex) {
252 fail("test should not throw an exception");
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);
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",
266 axPolicy.getStateMap().get("State1").getStateOutputs().get("stateOutput1")
267 .setNextState(AxReferenceKey.getNullKey());
268 dummyTsle.setTaskNo(0);
270 executor.execute(0, incomingEventMock);
271 } catch (Exception ex) {
272 fail("test should not throw an exception");
275 axPolicy.getStateMap().get("State1").setTrigger(new AxArtifactKey("BadTrigger:0.0.1"));
276 dummyTsle.setTaskNo(0);
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());
285 axPolicy.getStateMap().get("State1").setTrigger(new AxArtifactKey("Event1:0.0.1"));
286 dummyTsle.setTaskNo(0);
288 executor.execute(0, incomingEventMock);
289 } catch (Exception ex) {
290 fail("test should not throw an exception");
293 AxStateFinalizerLogic savedSfl = axPolicy.getStateMap().get("State1").getStateFinalizerLogicMap().get("sfl");
294 axPolicy.getStateMap().get("State1").getStateFinalizerLogicMap().put("sfl", null);
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());
307 axPolicy.getStateMap().get("State1").getStateFinalizerLogicMap().put("sfl", savedSfl);
308 executor.setContext(null, axPolicy, internalContextMock);
310 dummyTsle.setTaskNo(0);
312 executor.execute(0, incomingEventMock);
313 } catch (Exception ex) {
314 fail("test should not throw an exception");
317 AxArtifactKey task1Key = new AxArtifactKey("task1:0.0.1");
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());
331 axPolicy.getStateMap().get("State1").getTaskReferences().get(task1Key)
332 .setStateTaskOutputType(AxStateTaskOutputType.LOGIC);
333 executor.setContext(null, axPolicy, internalContextMock);
335 dummyTsle.setTaskNo(0);
337 executor.execute(0, incomingEventMock);
338 } catch (Exception ex) {
339 fail("test should not throw an exception");
342 dummyTsle.setTaskNo(0);
343 dummySfle.setReturnBad(true);
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());
353 dummyTsle.setTaskNo(0);
354 dummySfle.setReturnBad(false);
356 executor.execute(0, incomingEventMock);
357 } catch (Exception ex) {
358 fail("test should not throw an exception");
363 } catch (Exception ex) {
364 fail("test should not throw an exception");
369 public void testStateOutput() {
370 StateOutput output = new StateOutput(
371 axPolicy.getStateMap().get("State0").getStateOutputs().get("stateOutput0"));
372 assertNotNull(output);
374 assertEquals("stateOutput0", output.getStateOutputDefinition().getKey().getLocalName());
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());
383 Map<String, AxField> incomingFieldDefinitionMap = new LinkedHashMap<>();
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());
391 Map<String, Object> eventFieldMap = new LinkedHashMap<>();
393 output.setEventFields(incomingFieldDefinitionMap, eventFieldMap);
394 } catch (Exception ex) {
395 fail("test should not throw an exception");
398 eventFieldMap.put("key", "Value");
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]",
407 AxField axBadFieldDefinition = new AxField();
408 incomingFieldDefinitionMap.put("key", axBadFieldDefinition);
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());
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");
424 output.setEventFields(incomingFieldDefinitionMap, eventFieldMap);
425 } catch (Exception ex) {
426 fail("test should not throw an exception");
429 output = new StateOutput(axPolicy.getStateMap().get("State0").getStateOutputs().get("stateOutput0"));
431 EnEvent incomingEvent = new EnEvent(new AxArtifactKey("Event0:0.0.1"));
432 output.copyUnsetFields(incomingEvent);
434 incomingEvent.put("Event1Field0", "Hello");
435 output.copyUnsetFields(incomingEvent);