summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/core-engine/pom.xml10
-rw-r--r--core/core-engine/src/main/java/org/onap/policy/apex/core/engine/context/ApexInternalContext.java2
-rw-r--r--core/core-engine/src/main/java/org/onap/policy/apex/core/engine/engine/impl/ApexEngineImpl.java60
-rw-r--r--core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/ExecutorFactory.java2
-rw-r--r--core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/StateFinalizerExecutor.java9
-rw-r--r--core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/StateMachineExecutor.java5
-rw-r--r--core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/TaskExecutor.java73
-rw-r--r--core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/context/AxTaskFacade.java3
-rw-r--r--core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/context/TaskSelectionExecutionContext.java2
-rw-r--r--core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/impl/ExecutorFactoryImpl.java4
-rw-r--r--core/core-engine/src/test/java/org/onap/policy/apex/core/engine/engine/impl/ApexEngineImplTest.java668
-rw-r--r--core/core-engine/src/test/java/org/onap/policy/apex/core/engine/engine/impl/BadListener.java43
-rw-r--r--core/core-engine/src/test/java/org/onap/policy/apex/core/engine/engine/impl/DummyListener.java43
-rw-r--r--core/core-engine/src/test/java/org/onap/policy/apex/core/engine/engine/impl/DummySmExecutor.java87
-rw-r--r--core/core-engine/src/test/java/org/onap/policy/apex/core/engine/engine/impl/SlowListener.java58
-rw-r--r--core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/DummyFailingTaskExecutor.java30
-rw-r--r--core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/DummyStateFinalizerExecutor.java68
-rw-r--r--core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/DummyTaskExecutor.java94
-rw-r--r--core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/DummyTaskSelectExecutor.java82
-rw-r--r--core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/StateExecutorTest.java96
-rw-r--r--core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/StateFinalizerExecutorTest.java199
-rw-r--r--core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/StateMachineExecutorTest.java437
-rw-r--r--core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/TaskExecutorTest.java251
-rw-r--r--core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/TaskSelectExecutorTest.java208
-rw-r--r--core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/context/AxStateFacadeTest.java87
-rw-r--r--core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/context/AxTaskFacadeTest.java155
-rw-r--r--core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/context/DummyContextAlbum.java281
-rw-r--r--core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/context/StateFinalizerExecutionContextTest.java113
-rw-r--r--core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/context/TaskExecutionContextTest.java108
-rw-r--r--core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/context/TaskSelectionExecutionContextTest.java113
-rw-r--r--core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/exception/StateMachineRuntimeExceptionTest.java43
-rw-r--r--core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/impl/ExceutorFactoryImplTest.java310
32 files changed, 3682 insertions, 62 deletions
diff --git a/core/core-engine/pom.xml b/core/core-engine/pom.xml
index f527d46c1..6e21cd444 100644
--- a/core/core-engine/pom.xml
+++ b/core/core-engine/pom.xml
@@ -51,9 +51,19 @@
<version>${project.version}</version>
</dependency>
<dependency>
+ <groupId>org.onap.policy.apex-pdp.core</groupId>
+ <artifactId>core-infrastructure</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<profiles>
diff --git a/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/context/ApexInternalContext.java b/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/context/ApexInternalContext.java
index f73281ada..8eb92a0f8 100644
--- a/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/context/ApexInternalContext.java
+++ b/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/context/ApexInternalContext.java
@@ -51,7 +51,7 @@ import org.onap.policy.apex.model.utilities.comparison.KeyedMapDifference;
*
* @author Liam Fallon
*/
-public final class ApexInternalContext implements AxConceptGetter<ContextAlbum> {
+public class ApexInternalContext implements AxConceptGetter<ContextAlbum> {
// The key of the currently running Apex model
private AxArtifactKey key;
diff --git a/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/engine/impl/ApexEngineImpl.java b/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/engine/impl/ApexEngineImpl.java
index efd6aec5e..b703506ea 100644
--- a/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/engine/impl/ApexEngineImpl.java
+++ b/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/engine/impl/ApexEngineImpl.java
@@ -33,7 +33,9 @@ import org.onap.policy.apex.core.engine.engine.ApexEngine;
import org.onap.policy.apex.core.engine.engine.EnEventListener;
import org.onap.policy.apex.core.engine.event.EnEvent;
import org.onap.policy.apex.core.engine.executor.exception.StateMachineException;
+import org.onap.policy.apex.core.infrastructure.threading.ThreadUtilities;
import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
+import org.onap.policy.apex.model.basicmodel.concepts.ApexRuntimeException;
import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
import org.onap.policy.apex.model.basicmodel.concepts.AxReferenceKey;
import org.onap.policy.apex.model.enginemodel.concepts.AxEngineModel;
@@ -201,30 +203,37 @@ public class ApexEngineImpl implements ApexEngine {
public void stop() throws ApexException {
LOGGER.entry("stop()->" + key);
+ // Check if the engine is already stopped
+ if (state == AxEngineState.STOPPED) {
+ throw new ApexException(
+ STOP + key.getId() + "," + state + ", cannot stop engine, engine is already stopped");
+ }
+
// Stop the engine if it is in state READY, if it is in state EXECUTING, wait for execution to finish
for (int increment = ApexEngineConstants.STOP_EXECUTION_WAIT_TIMEOUT;
- increment > 0;
- increment = ApexEngineConstants.STOP_EXECUTION_WAIT_TIMEOUT) {
+ increment > 0; increment -= ApexEngineConstants.APEX_ENGINE_STOP_EXECUTION_WAIT_INCREMENT) {
+ ThreadUtilities.sleep(ApexEngineConstants.APEX_ENGINE_STOP_EXECUTION_WAIT_INCREMENT);
+
synchronized (state) {
switch (state) {
- // Already stopped
- case STOPPED:
-
- throw new ApexException(STOP + key.getId() + "," + state
- + ", cannot stop engine, engine is already stopped");
- // The normal case, the engine wasn't doing anything or it was executing
+ // Engine is OK to stop or has been stopped on return of an event
case READY:
- case STOPPING:
-
+ case STOPPED:
state = AxEngineState.STOPPED;
stateMachineHandler.stop();
engineStats.engineStop();
LOGGER.exit("stop()" + key);
return;
+
// Engine is executing a policy, wait for it to stop
case EXECUTING:
state = AxEngineState.STOPPING;
break;
+
+ // Wait for the engine to stop
+ case STOPPING:
+ break;
+
default:
throw new ApexException(STOP + key.getId() + "," + state
+ ", cannot stop engine, engine is in an undefined state");
@@ -232,7 +241,12 @@ public class ApexEngineImpl implements ApexEngine {
}
}
- throw new ApexException(STOP + key.getId() + "," + state + ", cannot stop engine, engine stop timed out");
+ // Force the engine to STOPPED state
+ synchronized (state) {
+ state = AxEngineState.STOPPED;
+ }
+
+ throw new ApexException(STOP + key.getId() + "," + state + ", error stopping engine, engine stop timed out");
}
/*
@@ -336,9 +350,11 @@ public class ApexEngineImpl implements ApexEngine {
ret = false;
}
synchronized (state) {
- // Only go to READY if we are still in state EXECUTING, we could be in state STOPPING
+ // Only go to READY if we are still in state EXECUTING, we go to state STOPPED if we were STOPPING
if (state == AxEngineState.EXECUTING) {
state = AxEngineState.READY;
+ } else if (state == AxEngineState.STOPPING) {
+ state = AxEngineState.STOPPED;
}
}
return ret;
@@ -352,6 +368,18 @@ public class ApexEngineImpl implements ApexEngine {
*/
@Override
public void addEventListener(final String listenerName, final EnEventListener listener) {
+ if (listenerName == null) {
+ String message = "addEventListener()<-" + key.getId() + "," + state + ", listenerName is null";
+ LOGGER.warn(message);
+ throw new ApexRuntimeException(message);
+ }
+
+ if (listener == null) {
+ String message = "addEventListener()<-" + key.getId() + "," + state + ", listener is null";
+ LOGGER.warn(message);
+ throw new ApexRuntimeException(message);
+ }
+
eventListeners.put(listenerName, listener);
}
@@ -362,6 +390,12 @@ public class ApexEngineImpl implements ApexEngine {
*/
@Override
public void removeEventListener(final String listenerName) {
+ if (listenerName == null) {
+ String message = "removeEventListener()<-" + key.getId() + "," + state + ", listenerName is null";
+ LOGGER.warn(message);
+ throw new ApexRuntimeException(message);
+ }
+
eventListeners.remove(listenerName);
}
@@ -411,7 +445,7 @@ public class ApexEngineImpl implements ApexEngine {
if (internalContext == null) {
return currentContext;
}
-
+
for (final Entry<AxArtifactKey, ContextAlbum> contextAlbumEntry : internalContext.getContextAlbums()
.entrySet()) {
currentContext.put(contextAlbumEntry.getKey(), contextAlbumEntry.getValue());
diff --git a/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/ExecutorFactory.java b/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/ExecutorFactory.java
index f092ce716..fb6c7b45e 100644
--- a/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/ExecutorFactory.java
+++ b/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/ExecutorFactory.java
@@ -32,7 +32,7 @@ import org.onap.policy.apex.model.policymodel.concepts.AxTask;
* @author Liam Fallon
*/
-public abstract class ExecutorFactory {
+public interface ExecutorFactory {
/**
* Get an executor for task selection logic.
*
diff --git a/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/StateFinalizerExecutor.java b/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/StateFinalizerExecutor.java
index 1c225f7b8..c30bda1b9 100644
--- a/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/StateFinalizerExecutor.java
+++ b/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/StateFinalizerExecutor.java
@@ -101,7 +101,8 @@ public abstract class StateFinalizerExecutor
public void prepare() throws StateMachineException {
LOGGER.debug("prepare:" + finalizerLogic.getId() + "," + finalizerLogic.getLogicFlavour() + ","
+ finalizerLogic.getLogic());
- argumentOfClassNotNull(finalizerLogic.getLogic(), StateMachineException.class, "task logic cannot be null.");
+ argumentOfClassNotNull(finalizerLogic.getLogic(), StateMachineException.class,
+ "state finalizer logic cannot be null.");
}
/*
@@ -237,7 +238,11 @@ public abstract class StateFinalizerExecutor
*/
@Override
public String getOutgoing() {
- return executionContext.getSelectedStateOutputName();
+ if (executionContext != null) {
+ return executionContext.getSelectedStateOutputName();
+ } else {
+ return null;
+ }
}
/*
diff --git a/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/StateMachineExecutor.java b/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/StateMachineExecutor.java
index 97d51bf78..34ba3942c 100644
--- a/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/StateMachineExecutor.java
+++ b/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/StateMachineExecutor.java
@@ -146,11 +146,8 @@ public class StateMachineExecutor implements Executor<EnEvent, EnEvent, AxPolicy
StateOutput stateOutput = new StateOutput(new AxStateOutput(firstExecutor.getSubject().getKey(),
incomingEvent.getKey(), firstExecutor.getSubject().getKey()), incomingEvent);
while (true) {
- // Execute the state
+ // Execute the state, it returns an output or throws an exception
stateOutput = stateExecutor.execute(executionId, stateOutput.getOutputEvent());
- if (stateOutput == null) {
- throw new StateMachineException("state execution failed, invalid state output returned");
- }
// Use the next state of the state output to find if all the states have executed
if (stateOutput.getNextState().equals(AxReferenceKey.getNullKey())) {
diff --git a/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/TaskExecutor.java b/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/TaskExecutor.java
index 2a62f3ae2..c55d4924d 100644
--- a/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/TaskExecutor.java
+++ b/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/TaskExecutor.java
@@ -41,14 +41,14 @@ import org.slf4j.ext.XLogger;
import org.slf4j.ext.XLoggerFactory;
/**
- * This abstract class executes a task in a state of an Apex policy and is specialized by classes
- * that implement execution of task logic.
+ * This abstract class executes a task in a state of an Apex policy and is specialized by classes that implement
+ * execution of task logic.
*
* @author Sven van der Meer (sven.van.der.meer@ericsson.com)
* @author Liam Fallon (liam.fallon@ericsson.com)
*/
public abstract class TaskExecutor
- implements Executor<Map<String, Object>, Map<String, Object>, AxTask, ApexInternalContext> {
+ implements Executor<Map<String, Object>, Map<String, Object>, AxTask, ApexInternalContext> {
// Logger for this class
private static final XLogger LOGGER = XLoggerFactory.getXLogger(TaskExecutor.class);
@@ -86,7 +86,7 @@ public abstract class TaskExecutor
*/
@Override
public void setContext(final Executor<?, ?, ?, ?> newParent, final AxTask newAxTask,
- final ApexInternalContext newInternalContext) {
+ final ApexInternalContext newInternalContext) {
this.parent = newParent;
this.axTask = newAxTask;
this.internalContext = newInternalContext;
@@ -100,7 +100,7 @@ public abstract class TaskExecutor
@Override
public void prepare() throws StateMachineException {
LOGGER.debug("prepare:" + axTask.getKey().getId() + "," + axTask.getTaskLogic().getLogicFlavour() + ","
- + axTask.getTaskLogic().getLogic());
+ + axTask.getTaskLogic().getLogic());
argumentOfClassNotNull(axTask.getTaskLogic().getLogic(), StateMachineException.class,
"task logic cannot be null.");
}
@@ -108,43 +108,43 @@ public abstract class TaskExecutor
/*
* (non-Javadoc)
*
- * @see org.onap.policy.apex.core.engine.executor.Executor#execute(java.lang.long,
- * java.lang.Object)
+ * @see org.onap.policy.apex.core.engine.executor.Executor#execute(java.lang.long, java.lang.Object)
*/
@Override
public Map<String, Object> execute(final long executionId, final Map<String, Object> newIncomingFields)
- throws StateMachineException, ContextException {
+ throws StateMachineException, ContextException {
throw new StateMachineException(
- "execute() not implemented on abstract TaskExecutor class, only on its subclasses");
+ "execute() not implemented on abstract TaskExecutor class, only on its subclasses");
}
/*
* (non-Javadoc)
*
- * @see org.onap.policy.apex.core.engine.executor.Executor#executePre(java.lang.long,
- * java.lang.Object)
+ * @see org.onap.policy.apex.core.engine.executor.Executor#executePre(java.lang.long, java.lang.Object)
*/
@Override
public final void executePre(final long executionId, final Map<String, Object> newIncomingFields)
- throws StateMachineException, ContextException {
+ throws StateMachineException, ContextException {
LOGGER.debug("execute-pre:" + getSubject().getTaskLogic().getLogicFlavour() + ","
- + getSubject().getKey().getId() + "," + getSubject().getTaskLogic().getLogic());
+ + getSubject().getKey().getId() + "," + getSubject().getTaskLogic().getLogic());
// Check that the incoming event has all the input fields for this state
final Set<String> missingTaskInputFields = new TreeSet<>(axTask.getInputFields().keySet());
missingTaskInputFields.removeAll(newIncomingFields.keySet());
// Remove fields from the set that are optional
+ final Set<String> optionalFields = new TreeSet<>();
for (final Iterator<String> missingFieldIterator = missingTaskInputFields.iterator(); missingFieldIterator
- .hasNext();) {
+ .hasNext();) {
final String missingField = missingFieldIterator.next();
if (axTask.getInputFields().get(missingField).getOptional()) {
- missingTaskInputFields.remove(missingField);
+ optionalFields.add(missingField);
}
}
+ missingTaskInputFields.removeAll(optionalFields);
if (!missingTaskInputFields.isEmpty()) {
throw new StateMachineException("task input fields \"" + missingTaskInputFields
- + "\" are missing for task \"" + axTask.getKey().getId() + "\"");
+ + "\" are missing for task \"" + axTask.getKey().getId() + "\"");
}
// Record the incoming fields
@@ -157,8 +157,8 @@ public abstract class TaskExecutor
}
// Get task context object
- executionContext =
- new TaskExecutionContext(this, executionId, getSubject(), getIncoming(), getOutgoing(), getContext());
+ executionContext = new TaskExecutionContext(this, executionId, getSubject(), getIncoming(), getOutgoing(),
+ getContext());
}
/*
@@ -170,7 +170,7 @@ public abstract class TaskExecutor
public final void executePost(final boolean returnValue) throws StateMachineException, ContextException {
if (!returnValue) {
String errorMessage = "execute-post: task logic execution failure on task \"" + axTask.getKey().getName()
- + "\" in model " + internalContext.getKey().getId();
+ + "\" in model " + internalContext.getKey().getId();
if (executionContext.getMessage() != null) {
errorMessage += ", user message: " + executionContext.getMessage();
}
@@ -191,16 +191,19 @@ public abstract class TaskExecutor
missingTaskOutputFields.removeAll(outgoingFields.keySet());
// Remove fields from the set that are optional
+ final Set<String> optionalOrCopiedFields = new TreeSet<>();
for (final Iterator<String> missingFieldIterator = missingTaskOutputFields.iterator(); missingFieldIterator
- .hasNext();) {
+ .hasNext();) {
final String missingField = missingFieldIterator.next();
- if (axTask.getInputFields().get(missingField).getOptional()) {
- missingTaskOutputFields.remove(missingField);
+ if (axTask.getInputFields().containsKey(missingField)
+ || axTask.getOutputFields().get(missingField).getOptional()) {
+ optionalOrCopiedFields.add(missingField);
}
}
+ missingTaskOutputFields.removeAll(optionalOrCopiedFields);
if (!missingTaskOutputFields.isEmpty()) {
throw new StateMachineException("task output fields \"" + missingTaskOutputFields
- + "\" are missing for task \"" + axTask.getKey().getId() + "\"");
+ + "\" are missing for task \"" + axTask.getKey().getId() + "\"");
}
// Finally, check that the outgoing field map don't have any extra fields, if present, raise
@@ -210,7 +213,7 @@ public abstract class TaskExecutor
extraTaskOutputFields.removeAll(axTask.getOutputFields().keySet());
if (!extraTaskOutputFields.isEmpty()) {
throw new StateMachineException("task output fields \"" + extraTaskOutputFields
- + "\" are unwanted for task \"" + axTask.getKey().getId() + "\"");
+ + "\" are unwanted for task \"" + axTask.getKey().getId() + "\"");
}
String message = "execute-post:" + axTask.getKey().getId() + ", returning fields " + outgoingFields.toString();
@@ -218,14 +221,13 @@ public abstract class TaskExecutor
}
/**
- * If the input field exists on the output and it is not set in the task, then it should
- * be copied to the output.
+ * If the input field exists on the output and it is not set in the task, then it should be copied to the output.
*
- * @param field the input field
+ * @param field the input field
*/
private void copyInputField2Output(String field) {
// Check if the field exists and is not set on the output
- if (!getOutgoing().containsKey(field) || getOutgoing().get(field) != null) {
+ if (getOutgoing().containsKey(field) && getOutgoing().get(field) != null) {
return;
}
@@ -316,14 +318,13 @@ public abstract class TaskExecutor
/*
* (non-Javadoc)
*
- * @see
- * org.onap.policy.apex.core.engine.executor.Executor#setNext(org.onap.policy.apex.core.engine.
+ * @see org.onap.policy.apex.core.engine.executor.Executor#setNext(org.onap.policy.apex.core.engine.
* executor.Executor)
*/
@Override
public void setNext(
- final Executor<Map<String, Object>, Map<String, Object>, AxTask, ApexInternalContext> newNextExecutor) {
- this.nextExecutor = newNextExecutor;
+ final Executor<Map<String, Object>, Map<String, Object>, AxTask, ApexInternalContext> nextEx) {
+ this.nextExecutor = nextEx;
}
/*
@@ -339,10 +340,10 @@ public abstract class TaskExecutor
/*
* (non-Javadoc)
*
- * @see
- * org.onap.policy.apex.core.engine.executor.Executor#setParameters(org.onap.policy.apex.core.
- * engine. ExecutorParameters)
+ * @see org.onap.policy.apex.core.engine.executor.Executor#setParameters(org.onap.policy.apex.core. engine.
+ * ExecutorParameters)
*/
@Override
- public void setParameters(final ExecutorParameters parameters) {}
+ public void setParameters(final ExecutorParameters parameters) {
+ }
}
diff --git a/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/context/AxTaskFacade.java b/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/context/AxTaskFacade.java
index f7b53554d..f3906213f 100644
--- a/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/context/AxTaskFacade.java
+++ b/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/context/AxTaskFacade.java
@@ -20,7 +20,6 @@
package org.onap.policy.apex.core.engine.executor.context;
-import org.onap.policy.apex.context.ContextRuntimeException;
import org.onap.policy.apex.context.SchemaHelper;
import org.onap.policy.apex.context.impl.schema.SchemaHelperFactory;
import org.onap.policy.apex.core.engine.event.EnException;
@@ -120,7 +119,7 @@ public class AxTaskFacade {
// Get a schema helper to handle translations of fields to and from the schema
try {
return new SchemaHelperFactory().createSchemaHelper(field.getKey(), field.getSchema());
- } catch (final ContextRuntimeException e) {
+ } catch (final Exception e) {
final String message = "schema helper cannot be created for task field \"" + fieldName + "\" with key \""
+ field.getId() + "\" with schema \"" + field.getSchema() + "\"";
LOGGER.warn(message, e);
diff --git a/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/context/TaskSelectionExecutionContext.java b/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/context/TaskSelectionExecutionContext.java
index 63052348a..312c2a058 100644
--- a/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/context/TaskSelectionExecutionContext.java
+++ b/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/context/TaskSelectionExecutionContext.java
@@ -76,7 +76,7 @@ public class TaskSelectionExecutionContext {
* sets this field in its logic prior to executing and the Apex engine executes this task as the
* task for this state.
*/
- public final AxArtifactKey selectedTask;
+ public AxArtifactKey selectedTask;
/**
* Logger for task selection execution, task selection logic can use this field to access and
diff --git a/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/impl/ExecutorFactoryImpl.java b/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/impl/ExecutorFactoryImpl.java
index d1f07e19a..c0e24dd5a 100644
--- a/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/impl/ExecutorFactoryImpl.java
+++ b/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/impl/ExecutorFactoryImpl.java
@@ -49,7 +49,7 @@ import org.slf4j.ext.XLoggerFactory;
*
* @author Liam Fallon (liam.fallon@ericsson.com)
*/
-public class ExecutorFactoryImpl extends ExecutorFactory {
+public class ExecutorFactoryImpl implements ExecutorFactory {
// Get a reference to the logger
private static final XLogger LOGGER = XLoggerFactory.getXLogger(ExecutorFactoryImpl.class);
@@ -220,7 +220,7 @@ public class ExecutorFactoryImpl extends ExecutorFactory {
throw new StateMachineRuntimeException(errorMessage, e);
}
- // Check the class is a Task Selection Executor
+ // Check the class is the correct type of executor
if (!(executorSuperClass.isAssignableFrom(executorObject.getClass()))) {
final String errorMessage = "Executor on \"" + logicFlavour + "\" of type \"" + executorClass
+ "\" is not an instance of \"" + executorSuperClass.getCanonicalName() + "\"";
diff --git a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/engine/impl/ApexEngineImplTest.java b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/engine/impl/ApexEngineImplTest.java
new file mode 100644
index 000000000..2a80cf06b
--- /dev/null
+++ b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/engine/impl/ApexEngineImplTest.java
@@ -0,0 +1,668 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.core.engine.engine.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.HashMap;
+
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.onap.policy.apex.context.parameters.ContextParameterConstants;
+import org.onap.policy.apex.context.parameters.DistributorParameters;
+import org.onap.policy.apex.context.parameters.LockManagerParameters;
+import org.onap.policy.apex.context.parameters.PersistorParameters;
+import org.onap.policy.apex.context.parameters.SchemaParameters;
+import org.onap.policy.apex.core.engine.EngineParameterConstants;
+import org.onap.policy.apex.core.engine.EngineParameters;
+import org.onap.policy.apex.core.engine.context.ApexInternalContext;
+import org.onap.policy.apex.core.engine.event.EnEvent;
+import org.onap.policy.apex.core.engine.executor.StateMachineExecutor;
+import org.onap.policy.apex.core.engine.executor.exception.StateMachineException;
+import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
+import org.onap.policy.apex.model.basicmodel.concepts.ApexRuntimeException;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.model.basicmodel.concepts.AxReferenceKey;
+import org.onap.policy.apex.model.basicmodel.service.ModelService;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextAlbum;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchema;
+import org.onap.policy.apex.model.enginemodel.concepts.AxEngineState;
+import org.onap.policy.apex.model.eventmodel.concepts.AxEvent;
+import org.onap.policy.apex.model.eventmodel.concepts.AxEvents;
+import org.onap.policy.apex.model.policymodel.concepts.AxPolicy;
+import org.onap.policy.apex.model.policymodel.concepts.AxPolicyModel;
+import org.onap.policy.apex.model.policymodel.concepts.AxState;
+import org.onap.policy.common.parameters.ParameterService;
+
+/**
+ * Test the engine implementation.
+ */
+public class ApexEngineImplTest {
+ private AxPolicyModel policyModel;
+ private AxPolicyModel incompatiblePolicyModel;
+ private AxPolicyModel policyModelWithStates;
+
+ @Mock
+ StateMachineHandler smHandlerMock;
+
+ /**
+ * Set up services.
+ */
+ @BeforeClass
+ public static void setup() {
+ ParameterService.register(new SchemaParameters());
+ ParameterService.register(new DistributorParameters());
+ ParameterService.register(new LockManagerParameters());
+ ParameterService.register(new PersistorParameters());
+ ParameterService.register(new EngineParameters());
+ }
+
+ /**
+ * Set up mocking.
+ */
+ @Before
+ public void initializeMocking() throws ApexException {
+ MockitoAnnotations.initMocks(this);
+
+ Mockito.doThrow(new StateMachineException("mocked state machine exception",
+ new IOException("nexted exception"))).when(smHandlerMock).execute(Mockito.anyObject());
+ }
+
+ /**
+ * Create policy models.
+ */
+ @Before
+ public void createPolicyModels() {
+ AxArtifactKey modelKey = new AxArtifactKey("PolicyModel:0.0.1");
+ policyModel = new AxPolicyModel(modelKey);
+
+ AxArtifactKey schemaKey = new AxArtifactKey("Schema:0.0.1");
+ AxContextSchema schema = new AxContextSchema(schemaKey, "Java", "java.lang.String");
+ policyModel.getSchemas().getSchemasMap().put(schemaKey, schema);
+
+ AxArtifactKey albumKey = new AxArtifactKey("Album:0.0.1");
+ AxContextAlbum album = new AxContextAlbum(albumKey, "Policy", true, schemaKey);
+
+ policyModel.getAlbums().getAlbumsMap().put(albumKey, album);
+
+ AxEvents events = new AxEvents();
+ AxArtifactKey eventKey = new AxArtifactKey("Event:0.0.1");
+ AxEvent event = new AxEvent(eventKey, "event.name.space", "source", "target");
+ events.getEventMap().put(eventKey, event);
+ policyModel.setEvents(events);
+
+ AxArtifactKey incompatibleModelKey = new AxArtifactKey("IncompatiblePolicyModel:0.0.2");
+ incompatiblePolicyModel = new AxPolicyModel(incompatibleModelKey);
+
+ AxArtifactKey incompatibleSchemaKey = new AxArtifactKey("IncompatibleSchema:0.0.1");
+ AxContextSchema incompatibleSchema = new AxContextSchema(incompatibleSchemaKey, "Java", "java.lang.Integer");
+ incompatiblePolicyModel.getSchemas().getSchemasMap().put(incompatibleSchemaKey, incompatibleSchema);
+
+ AxContextAlbum incompatibleAlbum = new AxContextAlbum(albumKey, "Policy", true, incompatibleSchemaKey);
+ incompatiblePolicyModel.getAlbums().getAlbumsMap().put(albumKey, incompatibleAlbum);
+
+ AxArtifactKey modelKeyStates = new AxArtifactKey("PolicyModelStates:0.0.1");
+ policyModelWithStates = new AxPolicyModel(modelKeyStates);
+ policyModelWithStates.getSchemas().getSchemasMap().put(schemaKey, schema);
+ policyModelWithStates.getAlbums().getAlbumsMap().put(albumKey, album);
+ policyModelWithStates.setEvents(events);
+
+ AxPolicy policy0 = new AxPolicy(new AxArtifactKey("Policy0:0.0.1"));
+ AxState state0 = new AxState(new AxReferenceKey(policy0.getKey(), "state0"));
+ state0.setTrigger(eventKey);
+ policy0.getStateMap().put(state0.getKey().getLocalName(), state0);
+ policy0.setFirstState(state0.getKey().getLocalName());
+
+ policyModelWithStates.getPolicies().getPolicyMap().put(policy0.getKey(), policy0);
+
+ AxPolicy policy1 = new AxPolicy(new AxArtifactKey("Policy1:0.0.1"));
+ AxState state1 = new AxState(new AxReferenceKey(policy1.getKey(), "state1"));
+ state1.setTrigger(eventKey);
+ policy1.getStateMap().put(state1.getKey().getLocalName(), state1);
+ policy1.setFirstState(state1.getKey().getLocalName());
+
+ policyModelWithStates.getPolicies().getPolicyMap().put(policy1.getKey(), policy1);
+ }
+
+ /**
+ * Clear registrations.
+ */
+ @AfterClass
+ public static void teardown() {
+ ParameterService.deregister(ContextParameterConstants.SCHEMA_GROUP_NAME);
+ ParameterService.deregister(ContextParameterConstants.DISTRIBUTOR_GROUP_NAME);
+ ParameterService.deregister(ContextParameterConstants.LOCKING_GROUP_NAME);
+ ParameterService.deregister(ContextParameterConstants.PERSISTENCE_GROUP_NAME);
+ ParameterService.deregister(EngineParameterConstants.MAIN_GROUP_NAME);
+ }
+
+ @Test
+ public void testSanity() {
+ AxArtifactKey engineKey = new AxArtifactKey("Engine:0.0.1");
+ ApexEngineImpl engine = (ApexEngineImpl) new ApexEngineFactory().createApexEngine(engineKey);
+ assertNotNull(engine);
+ assertEquals(engineKey, engine.getKey());
+
+ try {
+ engine.start();
+ fail("test should throw an exception");
+ } catch (ApexException ae) {
+ assertEquals("start()<-Engine:0.0.1,STOPPED, cannot start engine, "
+ + "engine has not been initialized, its model is not loaded", ae.getMessage());
+ }
+
+ try {
+ engine.stop();
+ fail("test should throw an exception");
+ } catch (ApexException ae) {
+ assertEquals("stop()<-Engine:0.0.1,STOPPED, cannot stop engine, " + "engine is already stopped",
+ ae.getMessage());
+ }
+
+ assertEquals(AxEngineState.STOPPED, engine.getState());
+ assertEquals(0, engine.getEngineContext().size());
+ assertEquals(engineKey, engine.getEngineStatus().getKey());
+ assertNull(engine.getInternalContext());
+
+ try {
+ engine.clear();
+ } catch (ApexException e) {
+ fail("test should not throw an exception");
+ }
+
+ try {
+ engine.addEventListener(null, null);
+ fail("test should throw an exception");
+ } catch (ApexRuntimeException ae) {
+ assertEquals("addEventListener()<-Engine:0.0.1,STOPPED, listenerName is null", ae.getMessage());
+ }
+
+ try {
+ engine.addEventListener("myListener", null);
+ fail("test should throw an exception");
+ } catch (ApexRuntimeException ae) {
+ assertEquals("addEventListener()<-Engine:0.0.1,STOPPED, listener is null", ae.getMessage());
+ }
+
+ try {
+ engine.removeEventListener(null);
+ fail("test should throw an exception");
+ } catch (ApexRuntimeException ae) {
+ assertEquals("removeEventListener()<-Engine:0.0.1,STOPPED, listenerName is null", ae.getMessage());
+ }
+
+ try {
+ engine.addEventListener("myListener", new DummyListener());
+ engine.removeEventListener("myListener");
+ } catch (Exception e) {
+ fail("test should not throw an exception");
+ }
+
+ assertNull(engine.createEvent(null));
+
+ assertFalse(engine.handleEvent(null));
+
+ try {
+ engine.updateModel(null);
+ fail("test should throw an exception");
+ } catch (ApexException ae) {
+ assertEquals("updateModel()<-Engine:0.0.1, Apex model is not defined, it has a null value",
+ ae.getMessage());
+ }
+
+ try {
+ engine.updateModel(policyModel);
+ } catch (ApexException e) {
+ fail("test should not throw an exception");
+ }
+
+ // Force a context exception
+ ModelService.registerModel(AxPolicyModel.class, new AxPolicyModel());
+ try {
+ engine.updateModel(incompatiblePolicyModel);
+ fail("test should throw an exception");
+ } catch (ApexException ae) {
+ assertEquals("updateModel()<-Engine:0.0.1, error setting the context for engine \"Engine:0.0.1\"",
+ ae.getMessage());
+ }
+
+ try {
+ engine.updateModel(policyModel);
+ } catch (ApexException e) {
+ fail("test should not throw an exception");
+ }
+
+ assertNotNull(engine.getInternalContext());
+ assertEquals(1, engine.getEngineContext().size());
+
+ try {
+ engine.start();
+ assertEquals(AxEngineState.READY, engine.getState());
+ } catch (ApexException e) {
+ fail("test should not throw an exception");
+ }
+
+ try {
+ engine.start();
+ fail("test should throw an exception");
+ } catch (ApexException ae) {
+ assertEquals("start()<-Engine:0.0.1,READY, cannot start engine, engine not in state STOPPED",
+ ae.getMessage());
+ }
+
+ try {
+ engine.clear();
+ fail("test should throw an exception");
+ } catch (ApexException ae) {
+ assertEquals("clear()<-Engine:0.0.1,READY, cannot clear engine, engine is not stopped", ae.getMessage());
+ }
+
+ try {
+ engine.stop();
+ assertEquals(AxEngineState.STOPPED, engine.getState());
+ } catch (ApexException e) {
+ fail("test should not throw an exception");
+ }
+
+ try {
+ engine.clear();
+ assertEquals(AxEngineState.STOPPED, engine.getState());
+ } catch (ApexException e) {
+ fail("test should not throw an exception");
+ }
+
+ try {
+ engine.start();
+ fail("test should throw an exception");
+ } catch (ApexException ae) {
+ assertEquals("start()<-Engine:0.0.1,STOPPED, cannot start engine, "
+ + "engine has not been initialized, its model is not loaded", ae.getMessage());
+ }
+
+ try {
+ engine.updateModel(policyModel);
+ assertEquals(AxEngineState.STOPPED, engine.getState());
+ } catch (ApexException e) {
+ fail("test should not throw an exception");
+ }
+
+ try {
+ engine.start();
+ assertEquals(AxEngineState.READY, engine.getState());
+ } catch (ApexException e) {
+ fail("test should not throw an exception");
+ }
+
+ assertNull(engine.createEvent(null));
+
+ AxArtifactKey eventKey = new AxArtifactKey("Event:0.0.1");
+ EnEvent event = engine.createEvent(eventKey);
+ assertEquals(eventKey, event.getKey());
+
+ assertTrue(engine.handleEvent(event));
+ assertEquals(AxEngineState.READY, engine.getState());
+
+ try {
+ engine.stop();
+ assertEquals(AxEngineState.STOPPED, engine.getState());
+ } catch (ApexException e) {
+ fail("test should not throw an exception");
+ }
+
+ try {
+ engine.addEventListener("myListener", new DummyListener());
+ } catch (Exception e) {
+ fail("test should not throw an exception");
+ }
+
+ try {
+ engine.start();
+ assertEquals(AxEngineState.READY, engine.getState());
+ } catch (ApexException e) {
+ fail("test should not throw an exception");
+ }
+
+ try {
+ engine.updateModel(policyModel);
+ fail("test should throw an exception");
+ } catch (ApexException ae) {
+ assertEquals("updateModel()<-Engine:0.0.1, cannot update model, "
+ + "engine should be stopped but is in state READY", ae.getMessage());
+ }
+
+ assertTrue(engine.handleEvent(event));
+ assertEquals(AxEngineState.READY, engine.getState());
+
+ try {
+ engine.stop();
+ assertEquals(AxEngineState.STOPPED, engine.getState());
+ } catch (ApexException e) {
+ fail("test should not throw an exception");
+ }
+
+ try {
+ engine.addEventListener("badListener", new BadListener());
+ } catch (Exception e) {
+ fail("test should not throw an exception");
+ }
+
+ try {
+ engine.start();
+ assertEquals(AxEngineState.READY, engine.getState());
+ } catch (ApexException e) {
+ fail("test should not throw an exception");
+ }
+
+ assertFalse(engine.handleEvent(event));
+ assertEquals(AxEngineState.READY, engine.getState());
+ try {
+ engine.stop();
+ assertEquals(AxEngineState.STOPPED, engine.getState());
+ } catch (ApexException e) {
+ fail("test should not throw an exception");
+ }
+
+ try {
+ engine.removeEventListener("badListener");
+ engine.addEventListener("slowListener", new SlowListener());
+ } catch (Exception e) {
+ fail("test should not throw an exception");
+ }
+ }
+
+ @Test
+ public void testState() throws InterruptedException {
+ AxArtifactKey engineKey = new AxArtifactKey("Engine:0.0.1");
+ ApexEngineImpl engine = (ApexEngineImpl) new ApexEngineFactory().createApexEngine(engineKey);
+ assertNotNull(engine);
+ assertEquals(engineKey, engine.getKey());
+
+ try {
+ engine.updateModel(policyModel);
+ assertEquals(AxEngineState.STOPPED, engine.getState());
+ } catch (ApexException e) {
+ fail("test should not throw an exception");
+ }
+
+ SlowListener slowListener = new SlowListener();
+ try {
+ engine.addEventListener("slowListener", slowListener);
+ } catch (Exception e) {
+ fail("test should not throw an exception");
+ }
+
+ try {
+ engine.start();
+ assertEquals(AxEngineState.READY, engine.getState());
+ } catch (ApexException e) {
+ fail("test should not throw an exception");
+ }
+
+ assertEquals(AxEngineState.READY, engine.getState());
+
+ AxArtifactKey eventKey = new AxArtifactKey("Event:0.0.1");
+ EnEvent event = engine.createEvent(eventKey);
+ assertEquals(eventKey, event.getKey());
+
+ // 1 second is less than the 3 second wait on engine stopping
+ slowListener.setWaitTime(1000);
+ (new Thread() {
+ public void run() {
+ assertTrue(engine.handleEvent(event));
+ assertEquals(AxEngineState.STOPPED, engine.getState());
+ }
+ }).start();
+
+ Thread.sleep(50);
+ assertEquals(AxEngineState.EXECUTING, engine.getState());
+
+ assertFalse(engine.handleEvent(event));
+ assertNotNull(engine.createEvent(eventKey));
+
+ try {
+ engine.stop();
+ assertEquals(AxEngineState.STOPPED, engine.getState());
+ } catch (ApexException ae) {
+ fail("test should not throw an exception");
+ }
+
+ try {
+ engine.start();
+ assertEquals(AxEngineState.READY, engine.getState());
+ } catch (ApexException ae) {
+ fail("test should not throw an exception");
+ }
+
+ // 4 seconds is more than the 3 second wait on engine stopping
+ slowListener.setWaitTime(4000);
+ (new Thread() {
+ public void run() {
+ assertTrue(engine.handleEvent(event));
+ assertEquals(AxEngineState.STOPPED, engine.getState());
+ }
+ }).start();
+
+ Thread.sleep(50);
+ assertEquals(AxEngineState.EXECUTING, engine.getState());
+ try {
+ engine.stop();
+ assertEquals(AxEngineState.STOPPED, engine.getState());
+ fail("test should throw an exception");
+ } catch (ApexException ae) {
+ assertEquals("stop()<-Engine:0.0.1,STOPPED, error stopping engine, engine stop timed out", ae.getMessage());
+ }
+
+ try {
+ engine.clear();
+ assertEquals(AxEngineState.STOPPED, engine.getState());
+ } catch (ApexException e) {
+ fail("test should not throw an exception");
+ }
+ }
+
+ @Test
+ public void testStateMachineError() throws InterruptedException, IllegalArgumentException, IllegalAccessException,
+ NoSuchFieldException, SecurityException {
+
+ AxArtifactKey engineKey = new AxArtifactKey("Engine:0.0.1");
+ ApexEngineImpl engine = (ApexEngineImpl) new ApexEngineFactory().createApexEngine(engineKey);
+ assertNotNull(engine);
+ assertEquals(engineKey, engine.getKey());
+
+ try {
+ engine.updateModel(policyModel);
+ assertEquals(AxEngineState.STOPPED, engine.getState());
+ } catch (ApexException e) {
+ fail("test should not throw an exception");
+ }
+
+ final Field smHandlerField = engine.getClass().getDeclaredField("stateMachineHandler");
+ smHandlerField.setAccessible(true);
+ smHandlerField.set(engine, smHandlerMock);
+
+ try {
+ engine.start();
+ assertEquals(AxEngineState.READY, engine.getState());
+ } catch (ApexException e) {
+ fail("test should not throw an exception");
+ }
+
+ assertEquals(AxEngineState.READY, engine.getState());
+
+ AxArtifactKey eventKey = new AxArtifactKey("Event:0.0.1");
+ EnEvent event = engine.createEvent(eventKey);
+ assertEquals(eventKey, event.getKey());
+
+ assertFalse(engine.handleEvent(event));
+ assertEquals(AxEngineState.READY, engine.getState());
+
+ try {
+ engine.stop();
+ assertEquals(AxEngineState.STOPPED, engine.getState());
+ } catch (ApexException ae) {
+ fail("test should not throw an exception");
+ }
+
+ try {
+ Mockito.doThrow(new StateMachineException("mocked state machine exception",
+ new IOException("nexted exception"))).when(smHandlerMock).start();
+
+ engine.start();
+ fail("test should throw an exception");
+ } catch (ApexException ae) {
+ assertEquals("updateModel()<-Engine:0.0.1, error starting the engine state machines \"Engine:0.0.1\"",
+ ae.getMessage());
+ }
+
+ assertEquals(AxEngineState.STOPPED, engine.getState());
+
+ try {
+ engine.clear();
+ assertEquals(AxEngineState.STOPPED, engine.getState());
+ } catch (ApexException e) {
+ fail("test should not throw an exception");
+ }
+ }
+
+ @Test
+ public void testStateMachineHandler() throws InterruptedException, IllegalArgumentException, IllegalAccessException,
+ NoSuchFieldException, SecurityException {
+ AxArtifactKey engineKey = new AxArtifactKey("Engine:0.0.1");
+ ApexEngineImpl engine = (ApexEngineImpl) new ApexEngineFactory().createApexEngine(engineKey);
+ assertNotNull(engine);
+ assertEquals(engineKey, engine.getKey());
+
+ try {
+ engine.updateModel(policyModelWithStates);
+ assertEquals(AxEngineState.STOPPED, engine.getState());
+ } catch (ApexException e) {
+ fail("test should not throw an exception");
+ }
+
+ try {
+ engine.start();
+ assertEquals(AxEngineState.READY, engine.getState());
+ } catch (ApexException e) {
+ fail("test should not throw an exception");
+ }
+
+ AxArtifactKey eventKey = new AxArtifactKey("Event:0.0.1");
+ EnEvent event = engine.createEvent(eventKey);
+ assertEquals(eventKey, event.getKey());
+
+ try {
+ engine.stop();
+ assertEquals(AxEngineState.STOPPED, engine.getState());
+ } catch (ApexException ae) {
+ fail("test should not throw an exception");
+ }
+
+ assertEquals(AxEngineState.STOPPED, engine.getState());
+
+ try {
+ engine.start();
+ assertEquals(AxEngineState.READY, engine.getState());
+ } catch (ApexException e) {
+ fail("test should not throw an exception");
+ }
+
+ assertEquals(AxEngineState.READY, engine.getState());
+
+ // Can't work, state is not fully defined
+ assertFalse(engine.handleEvent(event));
+ assertEquals(AxEngineState.READY, engine.getState());
+
+ final Field smHandlerField = engine.getClass().getDeclaredField("stateMachineHandler");
+ smHandlerField.setAccessible(true);
+ StateMachineHandler smHandler = (StateMachineHandler) smHandlerField.get(engine);
+
+ final Field smExecutorMapField = smHandler.getClass().getDeclaredField("stateMachineExecutorMap");
+ smExecutorMapField.setAccessible(true);
+ @SuppressWarnings("unchecked")
+ HashMap<AxEvent, StateMachineExecutor> smExMap = (HashMap<AxEvent, StateMachineExecutor>) smExecutorMapField
+ .get(smHandler);
+
+ assertEquals(1, smExMap.size());
+ DummySmExecutor dummyExecutor = new DummySmExecutor(null, event.getKey());
+ smExMap.put(event.getAxEvent(), dummyExecutor);
+
+ try {
+ ApexInternalContext internalContext = new ApexInternalContext(policyModelWithStates);
+ dummyExecutor.setContext(null, null, internalContext);
+ } catch (Exception e) {
+ // Ignore this exception, we just need to set the internal context
+ }
+
+ try {
+ engine.stop();
+ assertEquals(AxEngineState.STOPPED, engine.getState());
+ } catch (ApexException ae) {
+ fail("test should not throw an exception");
+ }
+
+ try {
+ engine.start();
+ fail("test should throw an exception");
+ } catch (ApexException ae) {
+ assertEquals("updateModel()<-Engine:0.0.1, error starting the engine state machines \"Engine:0.0.1\"",
+ ae.getMessage());
+ }
+
+ assertEquals(AxEngineState.STOPPED, engine.getState());
+
+ try {
+ engine.start();
+ assertEquals(AxEngineState.READY, engine.getState());
+ } catch (ApexException ae) {
+ fail("test should not throw an exception");
+ }
+
+ // Works, Dummy executor fakes event execution
+ assertTrue(engine.handleEvent(event));
+ assertEquals(AxEngineState.READY, engine.getState());
+
+ try {
+ engine.stop();
+ assertEquals(AxEngineState.STOPPED, engine.getState());
+ } catch (ApexException ae) {
+ fail("test should not throw an exception");
+ }
+
+ try {
+ engine.clear();
+ assertEquals(AxEngineState.STOPPED, engine.getState());
+ } catch (ApexException e) {
+ fail("test should not throw an exception");
+ }
+ }
+}
diff --git a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/engine/impl/BadListener.java b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/engine/impl/BadListener.java
new file mode 100644
index 000000000..b829437d6
--- /dev/null
+++ b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/engine/impl/BadListener.java
@@ -0,0 +1,43 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.core.engine.engine.impl;
+
+import org.onap.policy.apex.core.engine.engine.EnEventListener;
+import org.onap.policy.apex.core.engine.event.EnEvent;
+import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
+
+/**
+ * Dummy engine event listener for unit test.
+ *
+ */
+public class BadListener implements EnEventListener {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.onap.policy.apex.core.engine.engine.EnEventListener#onEnEvent(org.onap.policy.apex.core.engine.event.EnEvent)
+ */
+ @Override
+ public void onEnEvent(EnEvent enEvent) throws ApexException {
+ throw new ApexException("not implemented on dummy class");
+ }
+}
diff --git a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/engine/impl/DummyListener.java b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/engine/impl/DummyListener.java
new file mode 100644
index 000000000..33b434af1
--- /dev/null
+++ b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/engine/impl/DummyListener.java
@@ -0,0 +1,43 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.core.engine.engine.impl;
+
+import org.onap.policy.apex.core.engine.engine.EnEventListener;
+import org.onap.policy.apex.core.engine.event.EnEvent;
+import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
+
+/**
+ * Dummy engine event listener for unit test.
+ *
+ */
+public class DummyListener implements EnEventListener {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.onap.policy.apex.core.engine.engine.EnEventListener#onEnEvent(org.onap.policy.apex.core.engine.event.EnEvent)
+ */
+ @Override
+ public void onEnEvent(EnEvent enEvent) throws ApexException {
+ // Do nothing
+ }
+}
diff --git a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/engine/impl/DummySmExecutor.java b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/engine/impl/DummySmExecutor.java
new file mode 100644
index 000000000..db8fc32d9
--- /dev/null
+++ b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/engine/impl/DummySmExecutor.java
@@ -0,0 +1,87 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.core.engine.engine.impl;
+
+import org.onap.policy.apex.core.engine.event.EnEvent;
+import org.onap.policy.apex.core.engine.executor.ExecutorFactory;
+import org.onap.policy.apex.core.engine.executor.StateMachineExecutor;
+import org.onap.policy.apex.core.engine.executor.exception.StateMachineException;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+
+/**
+ * Dummy state machine executor for testing.
+ */
+public class DummySmExecutor extends StateMachineExecutor {
+ private boolean cleanupWorks = false;
+ private boolean prepareWorks;
+
+ /**
+ * Constructor.
+ *
+ * @param executorFactory the factory for executors
+ * @param owner the owner key
+ */
+ public DummySmExecutor(ExecutorFactory executorFactory, AxArtifactKey owner) {
+ super(executorFactory, owner);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.onap.policy.apex.core.engine.executor.Executor#prepare()
+ */
+ @Override
+ public void prepare() throws StateMachineException {
+ if (prepareWorks) {
+ prepareWorks = false;
+ }
+ else {
+ prepareWorks = true;
+ throw new StateMachineException("dummy state machine executor exception");
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.onap.policy.apex.core.engine.executor.Executor#executeDirected(java.lang.long, java.lang.Object)
+ */
+ @Override
+ public EnEvent execute(final long executionId, final EnEvent incomingEvent) {
+ return incomingEvent;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.onap.policy.apex.core.engine.executor.Executor#cleanUp()
+ */
+ @Override
+ public void cleanUp() throws StateMachineException {
+ if (cleanupWorks) {
+ cleanupWorks = false;
+ }
+ else {
+ cleanupWorks = true;
+ throw new StateMachineException("dummy state machine executor exception");
+ }
+ }
+}
diff --git a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/engine/impl/SlowListener.java b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/engine/impl/SlowListener.java
new file mode 100644
index 000000000..f3f885911
--- /dev/null
+++ b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/engine/impl/SlowListener.java
@@ -0,0 +1,58 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.core.engine.engine.impl;
+
+import org.onap.policy.apex.core.engine.engine.EnEventListener;
+import org.onap.policy.apex.core.engine.event.EnEvent;
+import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
+
+/**
+ * Dummy engine event listener for unit test.
+ *
+ */
+public class SlowListener implements EnEventListener {
+
+ private long waitTime;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.onap.policy.apex.core.engine.engine.EnEventListener#onEnEvent(org.onap.policy.apex.core.engine.event.EnEvent)
+ */
+ @Override
+ public void onEnEvent(EnEvent enEvent) throws ApexException {
+ try {
+ Thread.sleep(waitTime);
+ }
+ catch (InterruptedException ie) {
+ // Do nothing
+ }
+ }
+
+ public long getWaitTime() {
+ return waitTime;
+ }
+
+ public void setWaitTime(long waitTime) {
+ this.waitTime = waitTime;
+ }
+}
diff --git a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/DummyFailingTaskExecutor.java b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/DummyFailingTaskExecutor.java
new file mode 100644
index 000000000..4d4fb639f
--- /dev/null
+++ b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/DummyFailingTaskExecutor.java
@@ -0,0 +1,30 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.core.engine.executor;
+
+/**
+ * Dummy task executor for testing.
+ */
+public class DummyFailingTaskExecutor extends TaskExecutor {
+ public DummyFailingTaskExecutor() throws InstantiationException {
+ throw new InstantiationException("I always fail");
+ }
+}
diff --git a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/DummyStateFinalizerExecutor.java b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/DummyStateFinalizerExecutor.java
new file mode 100644
index 000000000..abc11871e
--- /dev/null
+++ b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/DummyStateFinalizerExecutor.java
@@ -0,0 +1,68 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.core.engine.executor;
+
+import java.util.Map;
+
+import org.onap.policy.apex.context.ContextException;
+import org.onap.policy.apex.core.engine.executor.exception.StateMachineException;
+
+/**
+ * Dummy state finalizer executor for testing.
+ */
+public class DummyStateFinalizerExecutor extends StateFinalizerExecutor {
+ private boolean override;
+
+ private boolean returnBad;
+
+ public DummyStateFinalizerExecutor() {
+ this(false);
+ }
+
+ public DummyStateFinalizerExecutor(final boolean override) {
+ this.override = override;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.onap.policy.apex.core.engine.executor.Executor#execute(java.lang.long, java.lang.Object)
+ */
+ @Override
+ public String execute(final long executionId, final Map<String, Object> newIncomingFields)
+ throws StateMachineException, ContextException {
+
+ if (!override) {
+ super.execute(executionId, newIncomingFields);
+ }
+
+ if (returnBad) {
+ return "stateOutputBad";
+ }
+ else {
+ return "stateOutput1";
+ }
+ }
+
+ public void setReturnBad(boolean returnBad) {
+ this.returnBad = returnBad;
+ }
+}
diff --git a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/DummyTaskExecutor.java b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/DummyTaskExecutor.java
new file mode 100644
index 000000000..93fc6190f
--- /dev/null
+++ b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/DummyTaskExecutor.java
@@ -0,0 +1,94 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.core.engine.executor;
+
+import java.util.Map;
+
+import org.onap.policy.apex.context.ContextException;
+import org.onap.policy.apex.core.engine.event.EnEvent;
+import org.onap.policy.apex.core.engine.executor.exception.StateMachineException;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.model.policymodel.concepts.AxTask;
+
+/**
+ * Dummy task executor for testing.
+ */
+public class DummyTaskExecutor extends TaskExecutor {
+ private boolean override;
+
+ public DummyTaskExecutor() {
+ this(false);
+ }
+
+ public DummyTaskExecutor(final boolean override) {
+ this.override = override;
+ }
+
+ @Override
+ public void prepare() throws StateMachineException {
+ if (!override) {
+ super.prepare();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.onap.policy.apex.core.engine.executor.Executor#execute(java.lang.long, java.lang.Object)
+ */
+ @Override
+ public Map<String, Object> execute(final long executionId, final Map<String, Object> newIncomingFields)
+ throws StateMachineException, ContextException {
+ if (!override) {
+ super.execute(executionId, newIncomingFields);
+ }
+
+ AxArtifactKey event0Key = new AxArtifactKey("Event0:0.0.1");
+ return new EnEvent(event0Key);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.onap.policy.apex.core.engine.executor.Executor#getSubject()
+ */
+ @Override
+ public AxTask getSubject() {
+ if (!override) {
+ super.getSubject();
+ }
+
+ AxArtifactKey taskKey = new AxArtifactKey("FirstTask:0.0.1");
+ return new AxTask(taskKey);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.onap.policy.apex.core.engine.executor.Executor#cleanUp()
+ */
+ @Override
+ public void cleanUp() throws StateMachineException {
+ if (!override) {
+ super.cleanUp();
+ }
+ }
+}
diff --git a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/DummyTaskSelectExecutor.java b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/DummyTaskSelectExecutor.java
new file mode 100644
index 000000000..abbb1bd79
--- /dev/null
+++ b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/DummyTaskSelectExecutor.java
@@ -0,0 +1,82 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.core.engine.executor;
+
+import org.onap.policy.apex.context.ContextException;
+import org.onap.policy.apex.core.engine.event.EnEvent;
+import org.onap.policy.apex.core.engine.executor.exception.StateMachineException;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+
+/**
+ * Dummy task selection executor for testing.
+ */
+public class DummyTaskSelectExecutor extends TaskSelectExecutor {
+ private boolean override;
+
+ private static int taskNo;
+
+ public DummyTaskSelectExecutor() {
+ this(false);
+ }
+
+ public DummyTaskSelectExecutor(final boolean override) {
+ this.override = override;
+ }
+
+ @Override
+ public void prepare() throws StateMachineException {
+ if (!override) {
+ super.prepare();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.onap.policy.apex.core.engine.executor.Executor#execute(java.lang.long, java.lang.Object)
+ */
+ @Override
+ public AxArtifactKey execute(final long executionId, final EnEvent newIncomingEvent)
+ throws StateMachineException, ContextException {
+ if (!override) {
+ return super.execute(executionId, newIncomingEvent);
+ }
+
+ return new AxArtifactKey("task" + (taskNo++) + ":0.0.1");
+ }
+
+ public void setTaskNo(int incomingTaskNo) {
+ taskNo = incomingTaskNo;
+ }
+
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.onap.policy.apex.core.engine.executor.Executor#cleanUp()
+ */
+ @Override
+ public void cleanUp() throws StateMachineException {
+ if (!override) {
+ super.cleanUp();
+ }
+ }
+}
diff --git a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/StateExecutorTest.java b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/StateExecutorTest.java
new file mode 100644
index 000000000..08ab03b06
--- /dev/null
+++ b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/StateExecutorTest.java
@@ -0,0 +1,96 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.core.engine.executor;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.onap.policy.apex.core.engine.ExecutorParameters;
+import org.onap.policy.apex.core.engine.context.ApexInternalContext;
+import org.onap.policy.apex.core.engine.event.EnEvent;
+import org.onap.policy.apex.model.basicmodel.concepts.AxReferenceKey;
+import org.onap.policy.apex.model.policymodel.concepts.AxState;
+
+/**
+ * Test task executor.
+ */
+public class StateExecutorTest {
+ @Mock
+ private ApexInternalContext internalContextMock;
+
+ @Mock
+ private AxState axStateMock;
+
+ @Mock
+ private ExecutorFactory executorFactoryMock;
+
+ @Mock
+ private Executor<EnEvent, StateOutput, AxState, ApexInternalContext> nextExecutorMock;
+
+ /**
+ * Set up mocking.
+ */
+ @Before
+ public void startMocking() {
+ MockitoAnnotations.initMocks(this);
+
+ Mockito.doReturn(new AxReferenceKey("Policy:0.0.1:PolName:State0")).when(axStateMock).getKey();
+ }
+
+ @Test
+ public void testStateExecutor() {
+ StateExecutor executor = new StateExecutor(executorFactoryMock);
+
+ executor.setContext(null, axStateMock, internalContextMock);
+ assertEquals("Policy:0.0.1:PolName:State0", executor.getKey().getId());
+ assertEquals(null, executor.getParent());
+ assertEquals(internalContextMock, executor.getContext());
+ assertEquals(null, executor.getNext());
+ assertEquals(null, executor.getIncoming());
+ assertEquals(null, executor.getOutgoing());
+ assertEquals(axStateMock, executor.getSubject());
+
+ executor.setParameters(new ExecutorParameters());
+ executor.setNext(nextExecutorMock);
+ assertEquals(nextExecutorMock, executor.getNext());
+ executor.setNext(null);
+ assertEquals(null, executor.getNext());
+
+ try {
+ executor.executePre(0, null);
+ fail("test should throw an exception");
+ } catch (Exception ex) {
+ assertEquals("execution pre work not implemented on class", ex.getMessage());
+ }
+
+ try {
+ executor.executePost(false);
+ fail("test should throw an exception");
+ } catch (Exception ex) {
+ assertEquals("execution post work not implemented on class", ex.getMessage());
+ }
+ }
+}
diff --git a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/StateFinalizerExecutorTest.java b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/StateFinalizerExecutorTest.java
new file mode 100644
index 000000000..82ac610c9
--- /dev/null
+++ b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/StateFinalizerExecutorTest.java
@@ -0,0 +1,199 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.core.engine.executor;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.onap.policy.apex.core.engine.ExecutorParameters;
+import org.onap.policy.apex.core.engine.context.ApexInternalContext;
+import org.onap.policy.apex.core.engine.event.EnEvent;
+import org.onap.policy.apex.core.engine.executor.exception.StateMachineException;
+import org.onap.policy.apex.model.basicmodel.concepts.AxReferenceKey;
+import org.onap.policy.apex.model.policymodel.concepts.AxState;
+import org.onap.policy.apex.model.policymodel.concepts.AxStateFinalizerLogic;
+
+/**
+ * Test task executor.
+ */
+public class StateFinalizerExecutorTest {
+ @Mock
+ private Executor<?, ?, ?, ?> parentMock;
+
+ @Mock
+ private ApexInternalContext internalContextMock;
+
+ @Mock
+ private AxStateFinalizerLogic stateFinalizerLogicMock;
+
+ @Mock
+ private Executor<Map<String, Object>, String, AxStateFinalizerLogic, ApexInternalContext> nextExecutorMock;
+
+ @Mock
+ private EnEvent incomingEvent;
+
+ /**
+ * Set up mocking.
+ */
+ @Before
+ public void startMocking() {
+ MockitoAnnotations.initMocks(this);
+
+ AxState state = new AxState();
+ state.getStateOutputs().put("ValidOutput", null);
+
+ Mockito.doReturn(state).when(parentMock).getSubject();
+
+ Mockito.doReturn(new AxReferenceKey("State:0.0.1:StateName:StateSFL")).when(stateFinalizerLogicMock).getKey();
+ }
+
+ @Test
+ public void testStateFinalizerExecutor() {
+ DummyStateFinalizerExecutor executor = new DummyStateFinalizerExecutor();
+
+ executor.setContext(parentMock, stateFinalizerLogicMock, internalContextMock);
+ assertEquals("State:0.0.1:StateName:StateSFL", executor.getKey().getId());
+ assertEquals(null, executor.getExecutionContext());
+ assertEquals(parentMock, executor.getParent());
+ assertEquals(internalContextMock, executor.getContext());
+ assertEquals(null, executor.getNext());
+ assertEquals(null, executor.getIncoming());
+ assertEquals(null, executor.getOutgoing());
+ assertEquals(stateFinalizerLogicMock, executor.getSubject());
+
+ executor.setParameters(new ExecutorParameters());
+ executor.setNext(nextExecutorMock);
+ assertEquals(nextExecutorMock, executor.getNext());
+ executor.setNext(null);
+ assertEquals(null, executor.getNext());
+
+ try {
+ executor.cleanUp();
+ fail("test should throw an exception");
+ } catch (Exception ex) {
+ assertEquals("cleanUp() not implemented on class", ex.getMessage());
+ }
+
+ Mockito.doReturn(null).when(stateFinalizerLogicMock).getLogic();
+
+ try {
+ executor.prepare();
+ fail("test should throw an exception");
+ } catch (Exception ex) {
+ assertEquals("state finalizer logic cannot be null.", ex.getMessage());
+ }
+
+ Mockito.doReturn("some task logic").when(stateFinalizerLogicMock).getLogic();
+
+ try {
+ executor.prepare();
+ } catch (StateMachineException e) {
+ fail("test should not throw an exception");
+ }
+
+ try {
+ executor.executePre(0, incomingEvent);
+ } catch (Exception ex) {
+ assertEquals("task input fields \"[InField0]\" are missing for task \"Task0:0.0.1\"", ex.getMessage());
+ }
+
+ try {
+ executor.executePre(0, incomingEvent);
+ } catch (Exception e) {
+ fail("test should not throw an exception");
+ }
+
+ try {
+ executor.execute(0, incomingEvent);
+ fail("test should throw an exception");
+ } catch (Exception ex) {
+ assertEquals("execute() not implemented on abstract StateFinalizerExecutionContext class, "
+ + "only on its subclasses", ex.getMessage());
+ }
+
+ try {
+ executor.executePost(false);
+ fail("test should throw an exception");
+ } catch (Exception ex) {
+ assertEquals("execute-post: state finalizer logic execution failure on state \"NULL:0.0.0:NULL:NULL\" "
+ + "on finalizer logic null", ex.getMessage());
+ }
+
+ executor.getExecutionContext().setMessage("Execution message");
+ try {
+ executor.executePost(false);
+ fail("test should throw an exception");
+ } catch (Exception ex) {
+ assertEquals("execute-post: state finalizer logic execution failure on state \"NULL:0.0.0:NULL:NULL\" "
+ + "on finalizer logic null, user message: Execution message", ex.getMessage());
+ }
+
+ try {
+ executor.executePre(0, incomingEvent);
+ } catch (Exception ex) {
+ fail("test should not throw an exception");
+ }
+
+ try {
+ executor.executePost(true);
+ fail("test should throw an exception");
+ } catch (Exception ex) {
+ assertEquals("execute-post: state finalizer logic \"null\" did not select an output state",
+ ex.getMessage());
+ }
+
+ try {
+ executor.executePre(0, incomingEvent);
+ } catch (Exception ex) {
+ fail("test should not throw an exception");
+ }
+
+ executor.getExecutionContext().setSelectedStateOutputName("ThisOutputDoesNotExist");
+ try {
+ executor.executePost(true);
+ fail("test should throw an exception");
+ } catch (Exception ex) {
+ assertEquals("execute-post: state finalizer logic \"null\" selected output state "
+ + "\"ThisOutputDoesNotExist\" that does not exsist on state \"NULL:0.0.0:NULL:NULL\"",
+ ex.getMessage());
+ }
+
+ try {
+ executor.executePre(0, incomingEvent);
+ } catch (Exception ex) {
+ fail("test should not throw an exception");
+ }
+
+ executor.getExecutionContext().setSelectedStateOutputName("ValidOutput");
+ try {
+ executor.executePost(true);
+ } catch (Exception ex) {
+ fail("test should not throw an exception");
+ }
+ }
+}
diff --git a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/StateMachineExecutorTest.java b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/StateMachineExecutorTest.java
new file mode 100644
index 000000000..f9d3edc6c
--- /dev/null
+++ b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/StateMachineExecutorTest.java
@@ -0,0 +1,437 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.core.engine.executor;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.onap.policy.apex.context.parameters.SchemaParameters;
+import org.onap.policy.apex.core.engine.ExecutorParameters;
+import org.onap.policy.apex.core.engine.context.ApexInternalContext;
+import org.onap.policy.apex.core.engine.event.EnEvent;
+import org.onap.policy.apex.core.engine.executor.exception.StateMachineException;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.model.basicmodel.concepts.AxReferenceKey;
+import org.onap.policy.apex.model.basicmodel.service.ModelService;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchema;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchemas;
+import org.onap.policy.apex.model.eventmodel.concepts.AxEvent;
+import org.onap.policy.apex.model.eventmodel.concepts.AxEvents;
+import org.onap.policy.apex.model.eventmodel.concepts.AxField;
+import org.onap.policy.apex.model.policymodel.concepts.AxPolicy;
+import org.onap.policy.apex.model.policymodel.concepts.AxState;
+import org.onap.policy.apex.model.policymodel.concepts.AxStateFinalizerLogic;
+import org.onap.policy.apex.model.policymodel.concepts.AxStateOutput;
+import org.onap.policy.apex.model.policymodel.concepts.AxStateTaskOutputType;
+import org.onap.policy.apex.model.policymodel.concepts.AxStateTaskReference;
+import org.onap.policy.apex.model.policymodel.concepts.AxTask;
+import org.onap.policy.apex.model.policymodel.concepts.AxTasks;
+import org.onap.policy.common.parameters.ParameterService;
+
+/**
+ * Test task executor.
+ */
+public class StateMachineExecutorTest {
+ @Mock
+ private ApexInternalContext internalContextMock;
+
+ @Mock
+ private Executor<EnEvent, EnEvent, AxPolicy, ApexInternalContext> nextExecutorMock;
+
+ @Mock
+ private ExecutorFactory executorFactoryMock;
+
+ @Mock
+ private EnEvent incomingEventMock;
+
+ private AxPolicy axPolicy = new AxPolicy();
+
+ private DummyTaskSelectExecutor dummyTsle;
+
+ private DummyStateFinalizerExecutor dummySfle;
+
+ /**
+ * Set up mocking.
+ */
+ @Before
+ public void startMocking() {
+ MockitoAnnotations.initMocks(this);
+
+ axPolicy.setKey(new AxArtifactKey("Policy:0.0.1"));
+
+ AxReferenceKey state0Key = new AxReferenceKey(axPolicy.getKey(), "state0");
+ AxState state0 = new AxState(state0Key);
+
+ AxReferenceKey state1Key = new AxReferenceKey(axPolicy.getKey(), "state1");
+ AxState state1 = new AxState(state1Key);
+
+ axPolicy.getStateMap().put("State0", state0);
+ axPolicy.getStateMap().put("State1", state1);
+ axPolicy.setFirstState("state0");
+
+ AxArtifactKey event0Key = new AxArtifactKey("Event0:0.0.1");
+ AxEvent event0 = new AxEvent(event0Key, "a.name.space", "source", "target");
+ AxArtifactKey event1Key = new AxArtifactKey("Event1:0.0.1");
+ AxEvent event1 = new AxEvent(event1Key, "a.name.space", "source", "target");
+ AxArtifactKey event2Key = new AxArtifactKey("Event2:0.0.1");
+ AxEvent event2 = new AxEvent(event2Key, "a.name.space", "source", "target");
+ AxEvents events = new AxEvents();
+ events.getEventMap().put(event0Key, event0);
+ events.getEventMap().put(event1Key, event1);
+ events.getEventMap().put(event2Key, event2);
+ ModelService.registerModel(AxEvents.class, events);
+
+ AxReferenceKey fieldKey = new AxReferenceKey("Event1:0.0.1:event:Field0");
+ AxArtifactKey stringSchemaKey = new AxArtifactKey("StringSchema:0.0.1");
+ AxContextSchema stringSchema = new AxContextSchema(stringSchemaKey, "Java", "java.lang.String");
+ AxContextSchemas schemas = new AxContextSchemas();
+ schemas.getSchemasMap().put(stringSchemaKey, stringSchema);
+ ModelService.registerModel(AxContextSchemas.class, schemas);
+
+ AxField event1Field0Definition = new AxField(fieldKey, stringSchemaKey);
+ event1.getParameterMap().put("Event1Field0", event1Field0Definition);
+
+ event0.getParameterMap().put("Event1Field0", event1Field0Definition);
+ event0.getParameterMap().put("UnusedField", event1Field0Definition);
+
+ Mockito.doReturn(event0Key).when(incomingEventMock).getKey();
+ Mockito.doReturn(event0).when(incomingEventMock).getAxEvent();
+
+ state0.setTrigger(event0Key);
+ state1.setTrigger(event1Key);
+
+ AxArtifactKey task0Key = new AxArtifactKey("task0:0.0.1");
+ AxTask task0 = new AxTask(task0Key);
+
+ AxArtifactKey task1Key = new AxArtifactKey("task1:0.0.1");
+ AxTask task1 = new AxTask(task1Key);
+
+ AxTasks tasks = new AxTasks();
+ tasks.getTaskMap().put(task0Key, task0);
+ tasks.getTaskMap().put(task1Key, task1);
+ ModelService.registerModel(AxTasks.class, tasks);
+
+ ParameterService.register(new SchemaParameters());
+
+ AxReferenceKey stateOutput0Key = new AxReferenceKey("Policy:0.0.1:state0:stateOutput0");
+ AxStateOutput stateOutput0 = new AxStateOutput(stateOutput0Key, event1Key, state1.getKey());
+
+ state0.getStateOutputs().put(stateOutput0Key.getLocalName(), stateOutput0);
+
+ AxReferenceKey stateOutput1Key = new AxReferenceKey("Policy:0.0.1:state0:stateOutput1");
+ AxStateOutput stateOutput1 = new AxStateOutput(stateOutput1Key, event2Key, AxReferenceKey.getNullKey());
+
+ state1.getStateOutputs().put(stateOutput1Key.getLocalName(), stateOutput1);
+
+ AxReferenceKey str0Key = new AxReferenceKey("Policy:0.0.1:state0:str0");
+ AxStateTaskReference str0 = new AxStateTaskReference(str0Key, AxStateTaskOutputType.DIRECT, stateOutput0Key);
+ state0.getTaskReferences().put(task0Key, str0);
+
+ AxReferenceKey sflKey = new AxReferenceKey("Policy:0.0.1:state1:sfl");
+ AxStateFinalizerLogic sfl = new AxStateFinalizerLogic(sflKey, "Java", "State fianlizer logic");
+ state1.getStateFinalizerLogicMap().put("sfl", sfl);
+
+ AxReferenceKey str1Key = new AxReferenceKey("Policy:0.0.1:state1:str1");
+ AxStateTaskReference str1 = new AxStateTaskReference(str1Key, AxStateTaskOutputType.LOGIC, sflKey);
+ state1.getTaskReferences().put(task1Key, str1);
+
+ Mockito.doReturn(new DummyTaskExecutor(true)).when(executorFactoryMock).getTaskExecutor(Mockito.anyObject(),
+ Mockito.anyObject(), Mockito.anyObject());
+
+ dummyTsle = new DummyTaskSelectExecutor(true);
+ Mockito.doReturn(dummyTsle).when(executorFactoryMock).getTaskSelectionExecutor(Mockito.anyObject(),
+ Mockito.anyObject(), Mockito.anyObject());
+
+ dummySfle = new DummyStateFinalizerExecutor(true);
+ Mockito.doReturn(dummySfle).when(executorFactoryMock).getStateFinalizerExecutor(Mockito.anyObject(),
+ Mockito.anyObject(), Mockito.anyObject());
+ }
+
+ @After
+ public void cleardown() {
+ ParameterService.clear();
+ ModelService.clear();
+ }
+
+ @Test
+ public void testStateMachineExecutor() {
+ StateMachineExecutor executor = new StateMachineExecutor(executorFactoryMock,
+ new AxArtifactKey("OwnerKey:0.0.1"));
+
+ try {
+ executor.execute(0, incomingEventMock);
+ fail("test should throw an exception");
+ } catch (Exception ex) {
+ assertEquals("no states defined on state machine", ex.getMessage());
+ }
+
+ executor.setContext(null, axPolicy, internalContextMock);
+ assertEquals("Policy:0.0.1", executor.getKey().getId());
+ assertEquals(null, executor.getParent());
+ assertEquals(internalContextMock, executor.getContext());
+ assertEquals(null, executor.getNext());
+ assertEquals(null, executor.getIncoming());
+ assertEquals(null, executor.getOutgoing());
+ assertEquals(axPolicy, executor.getSubject());
+
+ executor.setParameters(new ExecutorParameters());
+ executor.setNext(nextExecutorMock);
+ assertEquals(nextExecutorMock, executor.getNext());
+ executor.setNext(null);
+ assertEquals(null, executor.getNext());
+
+ try {
+ executor.executePre(0, null);
+ fail("test should throw an exception");
+ } catch (Exception ex) {
+ assertEquals("execution pre work not implemented on class", ex.getMessage());
+ }
+
+ try {
+ executor.executePost(false);
+ fail("test should throw an exception");
+ } catch (Exception ex) {
+ assertEquals("execution post work not implemented on class", ex.getMessage());
+ }
+
+ try {
+ executor.prepare();
+ } catch (StateMachineException e) {
+ fail("test should not throw an exception");
+ }
+
+ axPolicy.setFirstState("BadState");
+ executor.setContext(null, axPolicy, internalContextMock);
+ try {
+ executor.execute(0, incomingEventMock);
+ fail("test should throw an exception");
+ } catch (Exception ex) {
+ assertEquals("first state not defined on state machine", ex.getMessage());
+ }
+
+ axPolicy.setFirstState("state0");
+ executor.setContext(null, axPolicy, internalContextMock);
+ try {
+ executor.execute(0, incomingEventMock);
+ } catch (Exception ex) {
+ fail("test should not throw an exception");
+ }
+
+ dummyTsle.setTaskNo(0);
+ try {
+ executor.execute(0, incomingEventMock);
+ } catch (Exception ex) {
+ fail("test should not throw an exception");
+ }
+
+ AxReferenceKey badStateKey = new AxReferenceKey("Policy:0.0.1:PName:BadState");
+ axPolicy.getStateMap().get("State1").getStateOutputs().get("stateOutput1").setNextState(badStateKey);
+ dummyTsle.setTaskNo(0);
+ try {
+ executor.execute(0, incomingEventMock);
+ fail("test should throw an exception");
+ } catch (Exception ex) {
+ assertEquals("state execution failed, next state \"Policy:0.0.1:PName:BadState\" not found",
+ ex.getMessage());
+ }
+
+ axPolicy.getStateMap().get("State1").getStateOutputs().get("stateOutput1")
+ .setNextState(AxReferenceKey.getNullKey());
+ dummyTsle.setTaskNo(0);
+ try {
+ executor.execute(0, incomingEventMock);
+ } catch (Exception ex) {
+ fail("test should not throw an exception");
+ }
+
+ axPolicy.getStateMap().get("State1").setTrigger(new AxArtifactKey("BadTrigger:0.0.1"));
+ dummyTsle.setTaskNo(0);
+ try {
+ executor.execute(0, incomingEventMock);
+ fail("test should throw an exception");
+ } catch (Exception ex) {
+ assertEquals("incoming event \"Event1:0.0.1\" does not match trigger \"BadTrigger:0.0.1\" "
+ + "of state \"Policy:0.0.1:NULL:state1\"", ex.getMessage());
+ }
+
+ axPolicy.getStateMap().get("State1").setTrigger(new AxArtifactKey("Event1:0.0.1"));
+ dummyTsle.setTaskNo(0);
+ try {
+ executor.execute(0, incomingEventMock);
+ } catch (Exception ex) {
+ fail("test should not throw an exception");
+ }
+
+ AxStateFinalizerLogic savedSfl = axPolicy.getStateMap().get("State1").getStateFinalizerLogicMap().get("sfl");
+ axPolicy.getStateMap().get("State1").getStateFinalizerLogicMap().put("sfl", null);
+ try {
+ executor.setContext(null, axPolicy, internalContextMock);
+ fail("test should throw an exception");
+ } catch (Exception ex) {
+ assertEquals("state finalizer logic on task reference "
+ + "\"AxStateTaskReference:(stateKey=AxReferenceKey:(parentKeyName=Policy,"
+ + "parentKeyVersion=0.0.1,parentLocalName=state1,localName=str1),"
+ + "outputType=LOGIC,output=AxReferenceKey:(parentKeyName=Policy,parentKeyVersion=0.0.1,"
+ + "parentLocalName=state1,localName=sfl))\" on state \"Policy:0.0.1:NULL:state1\" "
+ + "does not exist", ex.getMessage());
+ }
+
+ axPolicy.getStateMap().get("State1").getStateFinalizerLogicMap().put("sfl", savedSfl);
+ executor.setContext(null, axPolicy, internalContextMock);
+
+ dummyTsle.setTaskNo(0);
+ try {
+ executor.execute(0, incomingEventMock);
+ } catch (Exception ex) {
+ fail("test should not throw an exception");
+ }
+
+ AxArtifactKey task1Key = new AxArtifactKey("task1:0.0.1");
+ try {
+ axPolicy.getStateMap().get("State1").getTaskReferences().get(task1Key)
+ .setStateTaskOutputType(AxStateTaskOutputType.UNDEFINED);
+ executor.setContext(null, axPolicy, internalContextMock);
+ fail("test should throw an exception");
+ } catch (Exception ex) {
+ assertEquals("invalid state output type on task reference \"AxStateTaskReference:(stateKey=AxReferenceKey:"
+ + "(parentKeyName=Policy,parentKeyVersion=0.0.1,parentLocalName=state1,localName=str1),"
+ + "outputType=UNDEFINED,output=AxReferenceKey:(parentKeyName=Policy,"
+ + "parentKeyVersion=0.0.1,parentLocalName=state1,localName=sfl))\" "
+ + "on state \"Policy:0.0.1:NULL:state1\"", ex.getMessage());
+ }
+
+ axPolicy.getStateMap().get("State1").getTaskReferences().get(task1Key)
+ .setStateTaskOutputType(AxStateTaskOutputType.LOGIC);
+ executor.setContext(null, axPolicy, internalContextMock);
+
+ dummyTsle.setTaskNo(0);
+ try {
+ executor.execute(0, incomingEventMock);
+ } catch (Exception ex) {
+ fail("test should not throw an exception");
+ }
+
+ dummyTsle.setTaskNo(0);
+ dummySfle.setReturnBad(true);
+ try {
+ executor.execute(0, incomingEventMock);
+ fail("test should throw an exception");
+ } catch (Exception ex) {
+ assertEquals("State execution of state \"Policy:0.0.1:NULL:state1\" on task \"task1:0.0.1\" failed: "
+ + "state output definition for state output \"stateOutputBad\" not found for "
+ + "state \"Policy:0.0.1:NULL:state1\"", ex.getMessage());
+ }
+
+ dummyTsle.setTaskNo(0);
+ dummySfle.setReturnBad(false);
+ try {
+ executor.execute(0, incomingEventMock);
+ } catch (Exception ex) {
+ fail("test should not throw an exception");
+ }
+
+ try {
+ executor.cleanUp();
+ } catch (Exception ex) {
+ fail("test should not throw an exception");
+ }
+ }
+
+ @Test
+ public void testStateOutput() {
+ StateOutput output = new StateOutput(
+ axPolicy.getStateMap().get("State0").getStateOutputs().get("stateOutput0"));
+ assertNotNull(output);
+
+ assertEquals("stateOutput0", output.getStateOutputDefinition().getKey().getLocalName());
+
+ try {
+ output.setEventFields(null, null);
+ fail("test should throw an exception");
+ } catch (Exception ex) {
+ assertEquals("incomingFieldDefinitionMap may not be null", ex.getMessage());
+ }
+
+ Map<String, AxField> incomingFieldDefinitionMap = new LinkedHashMap<>();
+ try {
+ output.setEventFields(incomingFieldDefinitionMap, null);
+ fail("test should throw an exception");
+ } catch (Exception ex) {
+ assertEquals("eventFieldMap may not be null", ex.getMessage());
+ }
+
+ Map<String, Object> eventFieldMap = new LinkedHashMap<>();
+ try {
+ output.setEventFields(incomingFieldDefinitionMap, eventFieldMap);
+ } catch (Exception ex) {
+ fail("test should not throw an exception");
+ }
+
+ eventFieldMap.put("key", "Value");
+ try {
+ output.setEventFields(incomingFieldDefinitionMap, eventFieldMap);
+ fail("test should throw an exception");
+ } catch (Exception ex) {
+ assertEquals("field definitions and values do not match for event Event1:0.0.1\n[]\n[key]",
+ ex.getMessage());
+ }
+
+ AxField axBadFieldDefinition = new AxField();
+ incomingFieldDefinitionMap.put("key", axBadFieldDefinition);
+ try {
+ output.setEventFields(incomingFieldDefinitionMap, eventFieldMap);
+ fail("test should throw an exception");
+ } catch (Exception ex) {
+ assertEquals("field \"key\" does not exist on event \"Event1:0.0.1\"", ex.getMessage());
+ }
+
+ incomingFieldDefinitionMap.clear();
+ eventFieldMap.clear();
+ AxArtifactKey stringSchemaKey = new AxArtifactKey("StringSchema:0.0.1");
+ AxReferenceKey fieldKey = new AxReferenceKey("Event1:0.0.1:event:Field0");
+ AxField event1Field0Definition = new AxField(fieldKey, stringSchemaKey);
+ incomingFieldDefinitionMap.put("Event1Field0", event1Field0Definition);
+ eventFieldMap.put("Event1Field0", "Value");
+ try {
+ output.setEventFields(incomingFieldDefinitionMap, eventFieldMap);
+ } catch (Exception ex) {
+ fail("test should not throw an exception");
+ }
+
+ output = new StateOutput(axPolicy.getStateMap().get("State0").getStateOutputs().get("stateOutput0"));
+
+ EnEvent incomingEvent = new EnEvent(new AxArtifactKey("Event0:0.0.1"));
+ output.copyUnsetFields(incomingEvent);
+
+ incomingEvent.put("Event1Field0", "Hello");
+ output.copyUnsetFields(incomingEvent);
+ }
+}
diff --git a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/TaskExecutorTest.java b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/TaskExecutorTest.java
new file mode 100644
index 000000000..bfc8e2b6d
--- /dev/null
+++ b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/TaskExecutorTest.java
@@ -0,0 +1,251 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.core.engine.executor;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.onap.policy.apex.core.engine.ExecutorParameters;
+import org.onap.policy.apex.core.engine.context.ApexInternalContext;
+import org.onap.policy.apex.core.engine.executor.exception.StateMachineException;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.model.eventmodel.concepts.AxInputField;
+import org.onap.policy.apex.model.eventmodel.concepts.AxOutputField;
+import org.onap.policy.apex.model.policymodel.concepts.AxTask;
+import org.onap.policy.apex.model.policymodel.concepts.AxTaskLogic;
+
+/**
+ * Test task excutor.
+ */
+public class TaskExecutorTest {
+ @Mock
+ private AxTask axTaskMock;
+
+ @Mock
+ private ApexInternalContext internalContextMock;
+
+ @Mock
+ private AxInputField axInputFieldMock;
+
+ @Mock
+ private AxInputField axOptionalInputFieldMock;
+
+ @Mock
+ private AxOutputField axOutputFieldMock;
+
+ @Mock
+ private AxOutputField axOptionalOutputFieldMock;
+
+ @Mock
+ private AxOutputField axMissingOutputFieldMock;
+
+ @Mock
+ private Executor<Map<String, Object>, Map<String, Object>, AxTask, ApexInternalContext> nextExecutorMock;
+
+ @Mock
+ private AxTaskLogic taskLogicMock;
+
+ private LinkedHashMap<String, Object> inFieldMap;
+ private LinkedHashMap<String, Object> outFieldMap;
+
+ /**
+ * Set up mocking.
+ */
+ @Before
+ public void startMocking() {
+ MockitoAnnotations.initMocks(this);
+
+ AxArtifactKey task0Key = new AxArtifactKey("Task0:0.0.1");
+ Mockito.doReturn(task0Key).when(axTaskMock).getKey();
+ Mockito.doReturn(task0Key.getId()).when(axTaskMock).getId();
+
+ inFieldMap = new LinkedHashMap<>();
+ outFieldMap = new LinkedHashMap<>();
+
+ inFieldMap.put("InField0", axInputFieldMock);
+ inFieldMap.put("InField1", axOptionalInputFieldMock);
+ outFieldMap.put("OutField0", axOutputFieldMock);
+ outFieldMap.put("OutField0", axOptionalOutputFieldMock);
+
+ AxArtifactKey schemaKey = new AxArtifactKey("Schema:0.0.1");
+ Mockito.doReturn(schemaKey).when(axInputFieldMock).getSchema();
+ Mockito.doReturn(schemaKey).when(axOptionalInputFieldMock).getSchema();
+ Mockito.doReturn(schemaKey).when(axOutputFieldMock).getSchema();
+ Mockito.doReturn(schemaKey).when(axOptionalOutputFieldMock).getSchema();
+ Mockito.doReturn(schemaKey).when(axMissingOutputFieldMock).getSchema();
+
+ Mockito.doReturn(true).when(axOptionalInputFieldMock).getOptional();
+ Mockito.doReturn(true).when(axOptionalOutputFieldMock).getOptional();
+ Mockito.doReturn(false).when(axMissingOutputFieldMock).getOptional();
+
+ Mockito.doReturn(inFieldMap).when(axTaskMock).getInputFields();
+ Mockito.doReturn(outFieldMap).when(axTaskMock).getOutputFields();
+ Mockito.doReturn(taskLogicMock).when(axTaskMock).getTaskLogic();
+
+ Mockito.doReturn(new AxArtifactKey("Context:0.0.1")).when(internalContextMock).getKey();
+ }
+
+ @Test
+ public void testTaskExecutor() {
+ DummyTaskExecutor executor = new DummyTaskExecutor();
+
+ executor.setContext(null, axTaskMock, internalContextMock);
+ assertEquals("Task0:0.0.1", executor.getKey().getId());
+ assertEquals(null, executor.getExecutionContext());
+ assertEquals(null, executor.getParent());
+ assertEquals(internalContextMock, executor.getContext());
+ assertEquals(null, executor.getNext());
+ assertEquals(null, executor.getIncoming());
+ assertEquals(null, executor.getOutgoing());
+ assertNotNull(executor.getSubject());
+
+ executor.setParameters(new ExecutorParameters());
+ executor.setNext(nextExecutorMock);
+ assertEquals(nextExecutorMock, executor.getNext());
+ executor.setNext(null);
+ assertEquals(null, executor.getNext());
+
+ try {
+ executor.cleanUp();
+ fail("test should throw an exception");
+ } catch (Exception ex) {
+ assertEquals("cleanUp() not implemented on class", ex.getMessage());
+ }
+
+ Mockito.doReturn(null).when(taskLogicMock).getLogic();
+
+ try {
+ executor.prepare();
+ fail("test should throw an exception");
+ } catch (Exception ex) {
+ assertEquals("task logic cannot be null.", ex.getMessage());
+ }
+
+ Mockito.doReturn("some task logic").when(taskLogicMock).getLogic();
+
+ try {
+ executor.prepare();
+ } catch (StateMachineException e) {
+ fail("test should not throw an exception");
+ }
+
+ Map<String, Object> incomingFields = new LinkedHashMap<>();
+ try {
+ executor.executePre(0, incomingFields);
+ } catch (Exception ex) {
+ assertEquals("task input fields \"[InField0]\" are missing for task \"Task0:0.0.1\"", ex.getMessage());
+ }
+
+ incomingFields.put("InField0", "A Value");
+ try {
+ executor.executePre(0, incomingFields);
+ } catch (Exception e) {
+ fail("test should not throw an exception");
+ }
+
+ try {
+ executor.execute(0, incomingFields);
+ fail("test should throw an exception");
+ } catch (Exception ex) {
+ assertEquals("execute() not implemented on abstract TaskExecutor class, only on its subclasses",
+ ex.getMessage());
+ }
+
+ try {
+ executor.executePost(false);
+ fail("test should throw an exception");
+ } catch (Exception ex) {
+ assertEquals("execute-post: task logic execution failure on task \"Task0\" in model Context:0.0.1",
+ ex.getMessage());
+ }
+
+ executor.getExecutionContext().setMessage("Execution message");
+ try {
+ executor.executePost(false);
+ fail("test should throw an exception");
+ } catch (Exception ex) {
+ assertEquals("execute-post: task logic execution failure on task \"Task0\" in model Context:0.0.1, "
+ + "user message: Execution message", ex.getMessage());
+ }
+
+ try {
+ executor.executePost(true);
+ } catch (Exception e) {
+ fail("test should not throw an exception");
+ }
+
+ outFieldMap.put("MissingField", axMissingOutputFieldMock);
+ try {
+ executor.executePost(true);
+ fail("test should throw an exception");
+ } catch (Exception ex) {
+ assertEquals("task output fields \"[MissingField]\" are missing for task \"Task0:0.0.1\"", ex.getMessage());
+ }
+
+ outFieldMap.remove("MissingField");
+ executor.getExecutionContext().outFields.put("BadExtraField", "Howdy!");
+ try {
+ executor.executePost(true);
+ fail("test should throw an exception");
+ } catch (Exception ex) {
+ assertEquals("task output fields \"[BadExtraField]\" are unwanted for task \"Task0:0.0.1\"",
+ ex.getMessage());
+ }
+
+ executor.getExecutionContext().outFields.remove("BadExtraField");
+ outFieldMap.put("InField1", axMissingOutputFieldMock);
+ try {
+ executor.executePost(true);
+ } catch (Exception ex) {
+ fail("test should not throw an exception");
+ }
+
+ outFieldMap.put("InField0", axMissingOutputFieldMock);
+ try {
+ executor.executePost(true);
+ } catch (Exception ex) {
+ fail("test should not throw an exception");
+ }
+
+ executor.getExecutionContext().outFields.put("InField0", "Output Value");
+ try {
+ executor.executePost(true);
+ } catch (Exception ex) {
+ fail("test should not throw an exception");
+ }
+
+ executor.getExecutionContext().outFields.remove("InField0");
+ try {
+ executor.executePost(true);
+ } catch (Exception ex) {
+ fail("test should not throw an exception");
+ }
+ }
+}
diff --git a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/TaskSelectExecutorTest.java b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/TaskSelectExecutorTest.java
new file mode 100644
index 000000000..b303df06a
--- /dev/null
+++ b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/TaskSelectExecutorTest.java
@@ -0,0 +1,208 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.core.engine.executor;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.onap.policy.apex.core.engine.ExecutorParameters;
+import org.onap.policy.apex.core.engine.context.ApexInternalContext;
+import org.onap.policy.apex.core.engine.event.EnEvent;
+import org.onap.policy.apex.core.engine.executor.exception.StateMachineException;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.model.basicmodel.concepts.AxReferenceKey;
+import org.onap.policy.apex.model.policymodel.concepts.AxState;
+import org.onap.policy.apex.model.policymodel.concepts.AxStateTaskReference;
+import org.onap.policy.apex.model.policymodel.concepts.AxTaskSelectionLogic;
+
+/**
+ * Test task executor.
+ */
+public class TaskSelectExecutorTest {
+ @Mock
+ private AxState axStateMock;
+
+ @Mock
+ private ApexInternalContext internalContextMock;
+
+ @Mock
+ private Executor<EnEvent, AxArtifactKey, AxState, ApexInternalContext> nextExecutorMock;
+
+ @Mock
+ private AxTaskSelectionLogic taskSelectionLogicMock;
+
+ @Mock
+ private EnEvent incomingEvent;
+
+ /**
+ * Set up mocking.
+ */
+ @Before
+ public void startMocking() {
+ MockitoAnnotations.initMocks(this);
+
+ AxReferenceKey state0Key = new AxReferenceKey("State0Parent:0.0.1:Parent:State0");
+ Mockito.doReturn(state0Key).when(axStateMock).getKey();
+ Mockito.doReturn(state0Key.getId()).when(axStateMock).getId();
+
+ Map<AxArtifactKey, AxStateTaskReference> taskReferences = new LinkedHashMap<>();
+ taskReferences.put(new AxArtifactKey("Task0:0.0.0"), null);
+ taskReferences.put(new AxArtifactKey("Task1:0.0.0"), null);
+ Mockito.doReturn(taskReferences).when(axStateMock).getTaskReferences();
+ Mockito.doReturn(new AxArtifactKey("Task1:0.0.0")).when(axStateMock).getDefaultTask();
+
+ Mockito.doReturn(taskSelectionLogicMock).when(axStateMock).getTaskSelectionLogic();
+
+ Mockito.doReturn(new AxArtifactKey("Context:0.0.1")).when(internalContextMock).getKey();
+ }
+
+ @Test
+ public void testTaskSelectionExecutor() {
+ DummyTaskSelectExecutor executor = new DummyTaskSelectExecutor();
+
+ executor.setContext(null, axStateMock, internalContextMock);
+ assertEquals("State0Parent:0.0.1:Parent:State0", executor.getKey().getId());
+ assertEquals(null, executor.getExecutionContext());
+ assertEquals(null, executor.getParent());
+ assertEquals(internalContextMock, executor.getContext());
+ assertEquals(null, executor.getNext());
+ assertEquals(null, executor.getIncoming());
+ assertEquals(null, executor.getOutgoing());
+ assertEquals(axStateMock, executor.getSubject());
+
+ executor.setParameters(new ExecutorParameters());
+ executor.setNext(nextExecutorMock);
+ assertEquals(nextExecutorMock, executor.getNext());
+ executor.setNext(null);
+ assertEquals(null, executor.getNext());
+
+ try {
+ executor.cleanUp();
+ fail("test should throw an exception");
+ } catch (Exception ex) {
+ assertEquals("cleanUp() not implemented on class", ex.getMessage());
+ }
+
+ Mockito.doReturn(null).when(taskSelectionLogicMock).getLogic();
+
+ try {
+ executor.prepare();
+ fail("test should throw an exception");
+ } catch (Exception ex) {
+ assertEquals("task selection logic cannot be null.", ex.getMessage());
+ }
+
+ Mockito.doReturn("some task logic").when(taskSelectionLogicMock).getLogic();
+
+ try {
+ executor.prepare();
+ } catch (StateMachineException e) {
+ fail("test should not throw an exception");
+ }
+
+ try {
+ executor.executePre(0, incomingEvent);
+ } catch (Exception ex) {
+ assertEquals("task input fields \"[InField0]\" are missing for task \"Task0:0.0.1\"", ex.getMessage());
+ }
+
+ try {
+ executor.executePre(0, incomingEvent);
+ } catch (Exception e) {
+ fail("test should not throw an exception");
+ }
+
+ try {
+ executor.execute(0, incomingEvent);
+ fail("test should throw an exception");
+ } catch (Exception ex) {
+ assertEquals("execute() not implemented on class", ex.getMessage());
+ }
+
+ try {
+ executor.executePost(false);
+ fail("test should throw an exception");
+ } catch (Exception ex) {
+ assertEquals("execute-post: task selection logic failed on state \"State0Parent:0.0.1:Parent:State0\"",
+ ex.getMessage());
+ }
+
+ executor.getExecutionContext().setMessage("Execution message");
+ try {
+ executor.executePost(false);
+ fail("test should throw an exception");
+ } catch (Exception ex) {
+ assertEquals("execute-post: task selection logic failed on state \"State0Parent:0.0.1:Parent:State0\", "
+ + "user message: Execution message", ex.getMessage());
+ }
+
+ try {
+ executor.executePre(0, incomingEvent);
+ } catch (Exception e) {
+ fail("test should not throw an exception");
+ }
+
+ try {
+ executor.executePost(true);
+ assertEquals("Task1", executor.getOutgoing().getName());
+ } catch (Exception e) {
+ fail("test should not throw an exception");
+ }
+
+ try {
+ executor.executePre(0, incomingEvent);
+ } catch (Exception e) {
+ fail("test should not throw an exception");
+ }
+
+ executor.getOutgoing().setName("IDontExist");
+ try {
+ executor.executePost(true);
+ fail("test should throw an exception");
+ } catch (Exception ex) {
+ assertEquals("task \"IDontExist:0.0.0\" returned by task selection logic not defined "
+ + "on state \"State0Parent:0.0.1:Parent:State0\"", ex.getMessage());
+ }
+
+ try {
+ executor.executePre(0, incomingEvent);
+ } catch (Exception e) {
+ fail("test should not throw an exception");
+ }
+
+ executor.getOutgoing().setName("Task0");
+
+ try {
+ executor.executePost(true);
+ assertEquals("Task0", executor.getOutgoing().getName());
+ } catch (Exception e) {
+ fail("test should not throw an exception");
+ }
+ }
+}
diff --git a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/context/AxStateFacadeTest.java b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/context/AxStateFacadeTest.java
new file mode 100644
index 000000000..a35af534e
--- /dev/null
+++ b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/context/AxStateFacadeTest.java
@@ -0,0 +1,87 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.core.engine.executor.context;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.model.basicmodel.concepts.AxReferenceKey;
+import org.onap.policy.apex.model.basicmodel.service.ModelService;
+import org.onap.policy.apex.model.policymodel.concepts.AxState;
+import org.onap.policy.apex.model.policymodel.concepts.AxTask;
+import org.onap.policy.apex.model.policymodel.concepts.AxTasks;
+
+/**
+ * Test the state facade.
+ */
+public class AxStateFacadeTest {
+ @Mock
+ private AxState axStateMock;
+
+ @Mock
+ private AxTask axTaskMock;
+
+ /**
+ * Set up mocking.
+ */
+ @Before
+ public void startMocking() {
+ MockitoAnnotations.initMocks(this);
+
+ AxReferenceKey stateKey = new AxReferenceKey("StateParent:0.0.1:ParentName:StateName");
+ Mockito.doReturn(stateKey).when(axStateMock).getKey();
+
+ AxArtifactKey task0Key = new AxArtifactKey("Task0:0.0.1");
+ Mockito.doReturn(task0Key).when(axStateMock).getDefaultTask();
+
+ Map<AxArtifactKey, Object> taskReferences = new LinkedHashMap<>();;
+ taskReferences.put(task0Key, null);
+ Mockito.doReturn(taskReferences).when(axStateMock).getTaskReferences();
+
+ AxTasks tasks = new AxTasks();
+ tasks.getTaskMap().put(task0Key, axTaskMock);
+
+ ModelService.registerModel(AxTasks.class, tasks);
+ Mockito.doReturn(task0Key).when(axTaskMock).getKey();
+ }
+
+ @Test
+ public void testAxStateFacade() {
+ AxStateFacade stateFacade = new AxStateFacade(axStateMock);
+
+ assertEquals("StateName", stateFacade.getStateName());
+ assertEquals("StateParent:0.0.1:ParentName:StateName", stateFacade.getId());
+
+ assertEquals("Task0", stateFacade.getDefaultTaskKey().getName());
+ assertNull(stateFacade.getTaskKey(null));
+ assertEquals("Task0", stateFacade.getTaskKey("Task0").getName());
+ stateFacade.getTaskNames();
+ }
+}
diff --git a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/context/AxTaskFacadeTest.java b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/context/AxTaskFacadeTest.java
new file mode 100644
index 000000000..a18718cc5
--- /dev/null
+++ b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/context/AxTaskFacadeTest.java
@@ -0,0 +1,155 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.core.engine.executor.context;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.onap.policy.apex.context.parameters.ContextParameterConstants;
+import org.onap.policy.apex.context.parameters.SchemaParameters;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.model.basicmodel.concepts.AxReferenceKey;
+import org.onap.policy.apex.model.basicmodel.service.ModelService;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchema;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchemas;
+import org.onap.policy.apex.model.eventmodel.concepts.AxInputField;
+import org.onap.policy.apex.model.eventmodel.concepts.AxOutputField;
+import org.onap.policy.apex.model.policymodel.concepts.AxTask;
+import org.onap.policy.common.parameters.ParameterService;
+
+/**
+ * Test the state facade.
+ */
+public class AxTaskFacadeTest {
+ @Mock
+ private AxTask axTaskMock;
+
+ @Mock
+ private AxInputField axInputFieldMock;
+
+ @Mock
+ private AxInputField axInputFieldBadMock;
+
+ @Mock
+ private AxOutputField axOutputFieldMock;
+
+ @Mock
+ private AxOutputField axOutputFieldBadMock;
+
+ /**
+ * Set up mocking.
+ */
+ @Before
+ public void startMocking() {
+ AxContextSchemas schemas = new AxContextSchemas();
+
+ AxArtifactKey stringTypeKey = new AxArtifactKey("StringType:0.0.1");
+ AxContextSchema stringType = new AxContextSchema(stringTypeKey, "Java", "java.lang.String");
+ schemas.getSchemasMap().put(stringTypeKey, stringType);
+
+ ModelService.registerModel(AxContextSchemas.class, schemas);
+
+ MockitoAnnotations.initMocks(this);
+
+ AxArtifactKey task0Key = new AxArtifactKey("Task0:0.0.1");
+ Mockito.doReturn(task0Key).when(axTaskMock).getKey();
+ Mockito.doReturn(task0Key.getId()).when(axTaskMock).getId();
+
+ Map<String, AxInputField> inFieldMap = new LinkedHashMap<>();
+ Map<String, AxOutputField> outFieldMap = new LinkedHashMap<>();
+
+ inFieldMap.put("InField0", axInputFieldMock);
+ inFieldMap.put("InFieldBad", axInputFieldBadMock);
+ outFieldMap.put("OutField0", axOutputFieldMock);
+ outFieldMap.put("OutFieldBad", axOutputFieldBadMock);
+
+ Mockito.doReturn(inFieldMap).when(axTaskMock).getInputFields();
+ Mockito.doReturn(outFieldMap).when(axTaskMock).getOutputFields();
+
+ Mockito.doReturn(new AxReferenceKey(task0Key, "InField0")).when(axInputFieldMock).getKey();
+ Mockito.doReturn(stringTypeKey).when(axInputFieldMock).getSchema();
+
+ Mockito.doReturn(new AxReferenceKey(task0Key, "OutField0")).when(axOutputFieldMock).getKey();
+ Mockito.doReturn(stringTypeKey).when(axOutputFieldMock).getSchema();
+
+ ParameterService.register(new SchemaParameters());
+ }
+
+ @After
+ public void teardown() {
+ ParameterService.deregister(ContextParameterConstants.SCHEMA_GROUP_NAME);
+ ModelService.clear();
+ }
+
+ @Test
+ public void testAxStateFacade() {
+ AxTaskFacade taskFacade = new AxTaskFacade(axTaskMock);
+
+ assertEquals("Task0", taskFacade.getTaskName());
+ assertEquals("Task0:0.0.1", taskFacade.getId());
+
+ try {
+ taskFacade.getInFieldSchemaHelper("InFieldDoesntExist");
+ fail("test should throw an exception");
+ } catch (Exception exc) {
+ assertEquals("no incoming field with name \"InFieldDoesntExist\" " + "defined on task \"Task0:0.0.1\"",
+ exc.getMessage());
+ }
+
+ try {
+ taskFacade.getOutFieldSchemaHelper("OutFieldDoesntExist");
+ fail("test should throw an exception");
+ } catch (Exception exc) {
+ assertEquals("no outgoing field with name \"OutFieldDoesntExist\" " + "defined on task \"Task0:0.0.1\"",
+ exc.getMessage());
+ }
+
+ assertNotNull(taskFacade.getInFieldSchemaHelper("InField0"));
+ assertNotNull(taskFacade.getOutFieldSchemaHelper("OutField0"));
+
+ try {
+ taskFacade.getInFieldSchemaHelper("InFieldBad");
+ fail("test should throw an exception");
+ } catch (Exception exc) {
+ assertEquals("schema helper cannot be created for task field \"InFieldBad\" "
+ + "with key \"null\" with schema \"null\"", exc.getMessage());
+ }
+
+ try {
+ taskFacade.getOutFieldSchemaHelper("OutFieldBad");
+ fail("test should throw an exception");
+ } catch (Exception exc) {
+ assertEquals("schema helper cannot be created for task field \"OutFieldBad\" "
+ + "with key \"null\" with schema \"null\"", exc.getMessage());
+ }
+
+ }
+}
diff --git a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/context/DummyContextAlbum.java b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/context/DummyContextAlbum.java
new file mode 100644
index 000000000..5d5583ff6
--- /dev/null
+++ b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/context/DummyContextAlbum.java
@@ -0,0 +1,281 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.core.engine.executor.context;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.lang3.NotImplementedException;
+import org.onap.policy.apex.context.ContextAlbum;
+import org.onap.policy.apex.context.ContextException;
+import org.onap.policy.apex.context.SchemaHelper;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.model.basicmodel.concepts.AxConcept;
+import org.onap.policy.apex.model.contextmodel.concepts.AxContextAlbum;
+
+/**
+ * Dummy context album for testing.
+ */
+public class DummyContextAlbum implements ContextAlbum {
+ private final AxArtifactKey key;
+
+ /**
+ * Constructor.
+ * @param key the key
+ */
+ public DummyContextAlbum(AxArtifactKey key) {
+ super();
+ this.key = key;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.util.Map#clear()
+ */
+ @Override
+ public void clear() {
+ throw new NotImplementedException("Not implemented on dummy class");
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.util.Map#containsKey(java.lang.Object)
+ */
+ @Override
+ public boolean containsKey(Object key) {
+ throw new NotImplementedException("Not implemented on dummy class");
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.util.Map#containsValue(java.lang.Object)
+ */
+ @Override
+ public boolean containsValue(Object value) {
+ throw new NotImplementedException("Not implemented on dummy class");
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.util.Map#entrySet()
+ */
+ @Override
+ public Set<Entry<String, Object>> entrySet() {
+ throw new NotImplementedException("Not implemented on dummy class");
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.util.Map#get(java.lang.Object)
+ */
+ @Override
+ public Object get(Object key) {
+ throw new NotImplementedException("Not implemented on dummy class");
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.util.Map#isEmpty()
+ */
+ @Override
+ public boolean isEmpty() {
+ throw new NotImplementedException("Not implemented on dummy class");
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.util.Map#keySet()
+ */
+ @Override
+ public Set<String> keySet() {
+ throw new NotImplementedException("Not implemented on dummy class");
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.util.Map#put(java.lang.Object, java.lang.Object)
+ */
+ @Override
+ public Object put(String key, Object value) {
+ throw new NotImplementedException("Not implemented on dummy class");
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.util.Map#putAll(java.util.Map)
+ */
+ @Override
+ public void putAll(Map<? extends String, ? extends Object> map) {
+ throw new NotImplementedException("Not implemented on dummy class");
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.util.Map#remove(java.lang.Object)
+ */
+ @Override
+ public Object remove(Object key) {
+ throw new NotImplementedException("Not implemented on dummy class");
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.util.Map#size()
+ */
+ @Override
+ public int size() {
+ throw new NotImplementedException("Not implemented on dummy class");
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.util.Map#values()
+ */
+ @Override
+ public Collection<Object> values() {
+ throw new NotImplementedException("Not implemented on dummy class");
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.onap.policy.apex.context.ContextAlbum#getKey()
+ */
+ @Override
+ public AxArtifactKey getKey() {
+ return key;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.onap.policy.apex.context.ContextAlbum#getName()
+ */
+ @Override
+ public String getName() {
+ throw new NotImplementedException("Not implemented on dummy class");
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.onap.policy.apex.context.ContextAlbum#getAlbumDefinition()
+ */
+ @Override
+ public AxContextAlbum getAlbumDefinition() {
+ throw new NotImplementedException("Not implemented on dummy class");
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.onap.policy.apex.context.ContextAlbum#getSchemaHelper()
+ */
+ @Override
+ public SchemaHelper getSchemaHelper() {
+ throw new NotImplementedException("Not implemented on dummy class");
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.onap.policy.apex.context.ContextAlbum#lockForReading(java.lang.String)
+ */
+ @Override
+ public void lockForReading(String key) throws ContextException {
+ throw new NotImplementedException("Not implemented on dummy class");
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.onap.policy.apex.context.ContextAlbum#lockForWriting(java.lang.String)
+ */
+ @Override
+ public void lockForWriting(String key) throws ContextException {
+ throw new NotImplementedException("Not implemented on dummy class");
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.onap.policy.apex.context.ContextAlbum#unlockForReading(java.lang.String)
+ */
+ @Override
+ public void unlockForReading(String key) throws ContextException {
+ throw new NotImplementedException("Not implemented on dummy class");
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.onap.policy.apex.context.ContextAlbum#unlockForWriting(java.lang.String)
+ */
+ @Override
+ public void unlockForWriting(String key) throws ContextException {
+ throw new NotImplementedException("Not implemented on dummy class");
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.onap.policy.apex.context.ContextAlbum#getUserArtifactStack()
+ */
+ @Override
+ public AxConcept[] getUserArtifactStack() {
+ throw new NotImplementedException("Not implemented on dummy class");
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.onap.policy.apex.context.ContextAlbum#setUserArtifactStack(org.onap.policy.apex.model.basicmodel.concepts.
+ * AxConcept[])
+ */
+ @Override
+ public void setUserArtifactStack(AxConcept[] userArtifactStack) {
+ // Do nothing
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.onap.policy.apex.context.ContextAlbum#flush()
+ */
+ @Override
+ public void flush() throws ContextException {
+ throw new NotImplementedException("Not implemented on dummy class");
+ }
+}
diff --git a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/context/StateFinalizerExecutionContextTest.java b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/context/StateFinalizerExecutionContextTest.java
new file mode 100644
index 000000000..8b0710ec7
--- /dev/null
+++ b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/context/StateFinalizerExecutionContextTest.java
@@ -0,0 +1,113 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.core.engine.executor.context;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.onap.policy.apex.context.ContextAlbum;
+import org.onap.policy.apex.core.engine.context.ApexInternalContext;
+import org.onap.policy.apex.core.engine.executor.StateFinalizerExecutor;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.model.basicmodel.concepts.AxReferenceKey;
+import org.onap.policy.apex.model.policymodel.concepts.AxState;
+
+/**
+ * Test Task Execution Context.
+ */
+public class StateFinalizerExecutionContextTest {
+ @Mock
+ private StateFinalizerExecutor stateFinalizerExecutorMock;
+
+ @Mock
+ private StateFinalizerExecutor parentExecutorMock;
+
+ @Mock
+ private AxState axStateMock;
+
+ @Mock
+ private ApexInternalContext internalContextMock;
+
+ /**
+ * Set up mocking.
+ */
+ @Before
+ public void startMocking() {
+ MockitoAnnotations.initMocks(this);
+
+ Set<AxArtifactKey> contextAlbumReferences = new LinkedHashSet<>();
+ contextAlbumReferences.add(new AxArtifactKey(("AlbumKey0:0.0.1")));
+ contextAlbumReferences.add(new AxArtifactKey(("AlbumKey1:0.0.1")));
+
+ Mockito.doReturn(contextAlbumReferences).when(axStateMock).getContextAlbumReferences();
+ Mockito.doReturn(new AxReferenceKey("Parent:0.0.1:ParentName:StateName")).when(axStateMock).getKey();
+
+ Map<AxArtifactKey, ContextAlbum> contextAlbumMap = new LinkedHashMap<>();
+ AxArtifactKey album0Key = new AxArtifactKey("AlbumKey0:0.0.1");
+ AxArtifactKey album1Key = new AxArtifactKey("AlbumKey1:0.0.1");
+
+ contextAlbumMap.put(album0Key, new DummyContextAlbum(album0Key));
+ contextAlbumMap.put(album1Key, new DummyContextAlbum(album1Key));
+
+ Mockito.doReturn(contextAlbumMap).when(internalContextMock).getContextAlbums();
+
+ Mockito.doReturn(parentExecutorMock).when(stateFinalizerExecutorMock).getParent();
+ Mockito.doReturn(new AxReferenceKey("Parent:0.0.1:ParentName:LocalName")).when(parentExecutorMock).getKey();
+ }
+
+ @Test
+ public void test() {
+ final Map<String, Object> fields = new LinkedHashMap<>();
+ final Set<String> stateOutputNames = new LinkedHashSet<>();
+
+ StateFinalizerExecutionContext sfec = new StateFinalizerExecutionContext(stateFinalizerExecutorMock, 0,
+ axStateMock, fields, stateOutputNames, internalContextMock);
+
+ assertNotNull(sfec);
+ sfec.setMessage("SFEC Message");
+ assertEquals("SFEC Message", sfec.getMessage());
+
+ sfec.setSelectedStateOutputName("SomeOutput");
+ assertEquals("SomeOutput", sfec.getSelectedStateOutputName());
+
+ ContextAlbum contextAlbum = sfec.getContextAlbum("AlbumKey0");
+ assertEquals("AlbumKey0:0.0.1", contextAlbum.getKey().getId());
+
+ try {
+ sfec.getContextAlbum("AlbumKeyNonExistant");
+ fail("test should throw an exception");
+ } catch (Exception exc) {
+ assertEquals("cannot find definition of context album \"AlbumKeyNonExistant\" "
+ + "on state \"Parent:0.0.1:ParentName:StateName\"", exc.getMessage());
+ }
+ }
+}
diff --git a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/context/TaskExecutionContextTest.java b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/context/TaskExecutionContextTest.java
new file mode 100644
index 000000000..c6c196a01
--- /dev/null
+++ b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/context/TaskExecutionContextTest.java
@@ -0,0 +1,108 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.core.engine.executor.context;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.onap.policy.apex.context.ContextAlbum;
+import org.onap.policy.apex.core.engine.context.ApexInternalContext;
+import org.onap.policy.apex.core.engine.executor.TaskExecutor;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.model.policymodel.concepts.AxTask;
+
+/**
+ * Test Task Execution Context.
+ */
+public class TaskExecutionContextTest {
+ @Mock
+ private TaskExecutor taskExecutorMock;
+
+ @Mock
+ private TaskExecutor parentExecutorMock;
+
+ @Mock
+ private AxTask axTaskMock;
+
+ @Mock
+ private ApexInternalContext internalContextMock;
+
+ /**
+ * Set up mocking.
+ */
+ @Before
+ public void startMocking() {
+ MockitoAnnotations.initMocks(this);
+
+ Set<AxArtifactKey> contextAlbumReferences = new LinkedHashSet<>();
+ contextAlbumReferences.add(new AxArtifactKey(("AlbumKey0:0.0.1")));
+ contextAlbumReferences.add(new AxArtifactKey(("AlbumKey1:0.0.1")));
+
+ Mockito.doReturn(contextAlbumReferences).when(axTaskMock).getContextAlbumReferences();
+
+ Map<AxArtifactKey, ContextAlbum> contextAlbumMap = new LinkedHashMap<>();
+ AxArtifactKey album0Key = new AxArtifactKey("AlbumKey0:0.0.1");
+ AxArtifactKey album1Key = new AxArtifactKey("AlbumKey1:0.0.1");
+
+ contextAlbumMap.put(album0Key, new DummyContextAlbum(album0Key));
+ contextAlbumMap.put(album1Key, new DummyContextAlbum(album1Key));
+
+ Mockito.doReturn(contextAlbumMap).when(internalContextMock).getContextAlbums();
+
+ Mockito.doReturn(parentExecutorMock).when(taskExecutorMock).getParent();
+ Mockito.doReturn(new AxArtifactKey("Parent:0.0.1")).when(parentExecutorMock).getKey();
+ }
+
+ @Test
+ public void test() {
+ final Map<String, Object> inFields = new LinkedHashMap<>();
+ final Map<String, Object> outFields = new LinkedHashMap<>();
+
+ TaskExecutionContext tec = new TaskExecutionContext(taskExecutorMock, 0, axTaskMock, inFields, outFields,
+ internalContextMock);
+
+ assertNotNull(tec);
+ tec.setMessage("TEC Message");
+ assertEquals("TEC Message", tec.getMessage());
+
+ ContextAlbum contextAlbum = tec.getContextAlbum("AlbumKey0");
+ assertEquals("AlbumKey0:0.0.1", contextAlbum.getKey().getId());
+
+ try {
+ tec.getContextAlbum("AlbumKeyNonExistant");
+ fail("test should throw an exception");
+ } catch (Exception exc) {
+ assertEquals("cannot find definition of context album \"AlbumKeyNonExistant\" on task \"null\"",
+ exc.getMessage());
+ }
+ }
+}
diff --git a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/context/TaskSelectionExecutionContextTest.java b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/context/TaskSelectionExecutionContextTest.java
new file mode 100644
index 000000000..02e271717
--- /dev/null
+++ b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/context/TaskSelectionExecutionContextTest.java
@@ -0,0 +1,113 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.core.engine.executor.context;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.onap.policy.apex.context.ContextAlbum;
+import org.onap.policy.apex.core.engine.context.ApexInternalContext;
+import org.onap.policy.apex.core.engine.event.EnEvent;
+import org.onap.policy.apex.core.engine.executor.TaskSelectExecutor;
+import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
+import org.onap.policy.apex.model.basicmodel.concepts.AxReferenceKey;
+import org.onap.policy.apex.model.policymodel.concepts.AxState;
+
+/**
+ * Test Task Execution Context.
+ */
+public class TaskSelectionExecutionContextTest {
+ @Mock
+ private TaskSelectExecutor taskSelectExecutorMock;
+
+ @Mock
+ private TaskSelectExecutor parentExecutorMock;
+
+ @Mock
+ private AxState axStateMock;
+
+ @Mock
+ private ApexInternalContext internalContextMock;
+
+ @Mock
+ private EnEvent incomingEventMock;
+
+ /**
+ * Set up mocking.
+ */
+ @Before
+ public void startMocking() {
+ MockitoAnnotations.initMocks(this);
+
+ Set<AxArtifactKey> contextAlbumReferences = new LinkedHashSet<>();
+ contextAlbumReferences.add(new AxArtifactKey(("AlbumKey0:0.0.1")));
+ contextAlbumReferences.add(new AxArtifactKey(("AlbumKey1:0.0.1")));
+
+ Mockito.doReturn(contextAlbumReferences).when(axStateMock).getContextAlbumReferences();
+ Mockito.doReturn(new AxReferenceKey("Parent:0.0.1:ParentName:StateName")).when(axStateMock).getKey();
+
+ Map<AxArtifactKey, ContextAlbum> contextAlbumMap = new LinkedHashMap<>();
+ AxArtifactKey album0Key = new AxArtifactKey("AlbumKey0:0.0.1");
+ AxArtifactKey album1Key = new AxArtifactKey("AlbumKey1:0.0.1");
+
+ contextAlbumMap.put(album0Key, new DummyContextAlbum(album0Key));
+ contextAlbumMap.put(album1Key, new DummyContextAlbum(album1Key));
+
+ Mockito.doReturn(contextAlbumMap).when(internalContextMock).getContextAlbums();
+
+ Mockito.doReturn(parentExecutorMock).when(taskSelectExecutorMock).getParent();
+ Mockito.doReturn(new AxReferenceKey("Parent:0.0.1:ParentName:LocalName")).when(parentExecutorMock).getKey();
+ }
+
+ @Test
+ public void test() {
+ final AxArtifactKey outgoingEventKey = new AxArtifactKey("OutEvent:0.0.1");
+
+ TaskSelectionExecutionContext tsec = new TaskSelectionExecutionContext(taskSelectExecutorMock, 0, axStateMock,
+ incomingEventMock, outgoingEventKey, internalContextMock);
+
+ assertNotNull(tsec);
+ tsec.setMessage("TSEC Message");
+ assertEquals("TSEC Message", tsec.getMessage());
+
+ ContextAlbum contextAlbum = tsec.getContextAlbum("AlbumKey0");
+ assertEquals("AlbumKey0:0.0.1", contextAlbum.getKey().getId());
+
+ try {
+ tsec.getContextAlbum("AlbumKeyNonExistant");
+ fail("test should throw an exception");
+ } catch (Exception exc) {
+ assertEquals("cannot find definition of context album \"AlbumKeyNonExistant\" "
+ + "on state \"Parent:0.0.1:ParentName:StateName\"", exc.getMessage());
+ }
+ }
+}
diff --git a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/exception/StateMachineRuntimeExceptionTest.java b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/exception/StateMachineRuntimeExceptionTest.java
new file mode 100644
index 000000000..e77002627
--- /dev/null
+++ b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/exception/StateMachineRuntimeExceptionTest.java
@@ -0,0 +1,43 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.core.engine.executor.exception;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.junit.Test;
+
+/**
+ * Test state machine runtime exception.
+ *
+ */
+public class StateMachineRuntimeExceptionTest {
+
+ @Test
+ public void testException() {
+ StateMachineRuntimeException smre = new StateMachineRuntimeException("Exception Message");
+ assertEquals("Exception Message", smre.getMessage());
+
+ smre = new StateMachineRuntimeException("Exception Message", new IOException());
+ assertEquals("Exception Message", smre.getMessage());
+ }
+}
diff --git a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/impl/ExceutorFactoryImplTest.java b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/impl/ExceutorFactoryImplTest.java
new file mode 100644
index 000000000..7fe394758
--- /dev/null
+++ b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/impl/ExceutorFactoryImplTest.java
@@ -0,0 +1,310 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.apex.core.engine.executor.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.onap.policy.apex.core.engine.EngineParameters;
+import org.onap.policy.apex.core.engine.ExecutorParameters;
+import org.onap.policy.apex.core.engine.context.ApexInternalContext;
+import org.onap.policy.apex.core.engine.executor.Executor;
+import org.onap.policy.apex.core.engine.executor.exception.StateMachineException;
+import org.onap.policy.apex.model.policymodel.concepts.AxState;
+import org.onap.policy.apex.model.policymodel.concepts.AxStateFinalizerLogic;
+import org.onap.policy.apex.model.policymodel.concepts.AxTask;
+import org.onap.policy.apex.model.policymodel.concepts.AxTaskLogic;
+import org.onap.policy.apex.model.policymodel.concepts.AxTaskSelectionLogic;
+import org.onap.policy.common.parameters.ParameterService;
+
+/**
+ * Test the executor factory implementation.
+ *
+ */
+public class ExceutorFactoryImplTest {
+ @Mock
+ private ApexInternalContext internalContextMock;
+
+ @Mock
+ private AxState stateMock;
+
+ @Mock
+ private AxTaskSelectionLogic tslMock;
+
+ @Mock
+ private AxTask taskMock;
+
+ @Mock
+ private AxTaskLogic tlMock;
+
+ @Mock
+ private AxStateFinalizerLogic sflMock;
+
+ @Mock
+ private Executor<?, ?, ?, ?> parentMock;
+
+ private ExecutorParameters executorPars;
+
+ /**
+ * Set up mocking.
+ */
+ @Before
+ public void startMocking() {
+ MockitoAnnotations.initMocks(this);
+
+ Mockito.doReturn(tslMock).when(stateMock).getTaskSelectionLogic();
+ Mockito.doReturn("Dummy").when(tslMock).getLogicFlavour();
+
+ Mockito.doReturn(tlMock).when(taskMock).getTaskLogic();
+ Mockito.doReturn("Dummy").when(tlMock).getLogicFlavour();
+
+ Mockito.doReturn("Dummy").when(sflMock).getLogicFlavour();
+ }
+
+ @After
+ public void clearPars() {
+ ParameterService.clear();
+ }
+
+ @Test
+ public void testExecutorFactoryImplGood() {
+ setGoodPars();
+
+ ExecutorFactoryImpl factory = null;
+
+ try {
+ factory = new ExecutorFactoryImpl();
+ } catch (StateMachineException e) {
+ fail("test should not throw an exception");
+ }
+
+ Mockito.doReturn(true).when(stateMock).checkSetTaskSelectionLogic();
+ assertNotNull(factory.getTaskSelectionExecutor(null, stateMock, internalContextMock));
+ Mockito.doReturn(false).when(stateMock).checkSetTaskSelectionLogic();
+ assertNull(factory.getTaskSelectionExecutor(null, stateMock, internalContextMock));
+
+ assertNotNull(factory.getTaskExecutor(null, taskMock, internalContextMock));
+
+ assertNotNull(factory.getStateFinalizerExecutor(parentMock, sflMock, internalContextMock));
+ }
+
+ @Test
+ public void testExecutorFactoryImplNonExistant() {
+ setNonExistantPars();
+
+ try {
+ new ExecutorFactoryImpl();
+ fail("test should throw an exception");
+
+ } catch (StateMachineException ex) {
+ assertEquals("Apex executor class not found for executor plugin "
+ + "\"org.onap.policy.apex.core.engine.executor.BadTaskExecutor\"", ex.getMessage());
+ }
+
+ executorPars.setTaskExecutorPluginClass(null);
+
+ try {
+ new ExecutorFactoryImpl();
+ fail("test should throw an exception");
+ } catch (StateMachineException ex) {
+ assertEquals("Apex executor class not found for executor plugin "
+ + "\"org.onap.policy.apex.core.engine.executor.BadTaskSelectExecutor\"", ex.getMessage());
+ }
+
+ executorPars.setTaskExecutorPluginClass("org.onap.policy.apex.core.engine.executor.DummyTaskExecutor");
+
+ try {
+ new ExecutorFactoryImpl();
+ fail("test should throw an exception");
+ } catch (StateMachineException ex) {
+ assertEquals("Apex executor class not found for executor plugin "
+ + "\"org.onap.policy.apex.core.engine.executor.BadTaskSelectExecutor\"", ex.getMessage());
+ }
+
+ executorPars.setTaskSelectionExecutorPluginClass(
+ "org.onap.policy.apex.core.engine.executor.DummyTaskSelectExecutor");
+
+ try {
+ new ExecutorFactoryImpl();
+ fail("test should throw an exception");
+ } catch (StateMachineException ex) {
+ assertEquals("Apex executor class not found for executor plugin "
+ + "\"org.onap.policy.apex.core.engine.executor.BadStateFinalizerExecutor\"",
+ ex.getMessage());
+ }
+ }
+
+ @Test
+ public void testExecutorFactoryImplBad() {
+ setBadPars();
+
+ try {
+ new ExecutorFactoryImpl();
+ fail("test should throw an exception");
+
+ } catch (StateMachineException ex) {
+ assertEquals("Specified Apex executor plugin class \"java.lang.String\" "
+ + "does not implment the Executor interface", ex.getMessage());
+ }
+
+ executorPars.setTaskExecutorPluginClass("org.onap.policy.apex.core.engine.executor.DummyTaskExecutor");
+
+ try {
+ new ExecutorFactoryImpl();
+ fail("test should throw an exception");
+ } catch (StateMachineException ex) {
+ assertEquals("Specified Apex executor plugin class \"java.lang.String\" "
+ + "does not implment the Executor interface", ex.getMessage());
+ }
+
+ executorPars.setTaskSelectionExecutorPluginClass(
+ "org.onap.policy.apex.core.engine.executor.DummyTaskSelectExecutor");
+
+ try {
+ new ExecutorFactoryImpl();
+ fail("test should throw an exception");
+ } catch (StateMachineException ex) {
+ assertEquals("Specified Apex executor plugin class \"java.lang.String\" "
+ + "does not implment the Executor interface", ex.getMessage());
+ }
+ }
+
+ @Test
+ public void testExecutorFactoryCreateErrors() {
+ setGoodPars();
+
+ executorPars.setTaskExecutorPluginClass(null);
+
+ ExecutorFactoryImpl factory = null;
+
+ try {
+ factory = new ExecutorFactoryImpl();
+ } catch (StateMachineException e) {
+ fail("test should not throw an exception");
+ }
+
+ Mockito.doReturn(true).when(stateMock).checkSetTaskSelectionLogic();
+
+ try {
+ factory.getTaskExecutor(null, taskMock, internalContextMock);
+ fail("test should throw an exception");
+ } catch (Exception ex) {
+ assertEquals("Executor plugin class not defined for \"Dummy\" executor of type "
+ + "\"org.onap.policy.apex.core.engine.executor.TaskExecutor\"", ex.getMessage());
+ }
+
+ executorPars.setTaskExecutorPluginClass("org.onap.policy.apex.core.engine.executor.DummyFailingTaskExecutor");
+
+ try {
+ factory = new ExecutorFactoryImpl();
+ } catch (StateMachineException e) {
+ fail("test should not throw an exception");
+ }
+
+ try {
+ factory.getTaskExecutor(null, taskMock, internalContextMock);
+ fail("test should throw an exception");
+ } catch (Exception ex) {
+ assertEquals("Instantiation error on \"Dummy\" executor of type "
+ + "\"org.onap.policy.apex.core.engine.executor.DummyFailingTaskExecutor\"",
+ ex.getMessage());
+ }
+
+ executorPars.setTaskExecutorPluginClass(
+ "org.onap.policy.apex.core.engine.executor.DummyStateFinalizerExecutor");
+
+ try {
+ factory = new ExecutorFactoryImpl();
+ } catch (StateMachineException e) {
+ fail("test should not throw an exception");
+ }
+
+ try {
+ factory.getTaskExecutor(null, taskMock, internalContextMock);
+ fail("test should throw an exception");
+ } catch (Exception ex) {
+ assertEquals("Executor on \"Dummy\" "
+ + "of type \"class org.onap.policy.apex.core.engine.executor.DummyStateFinalizerExecutor\""
+ + " is not an instance of \"org.onap.policy.apex.core.engine.executor.TaskExecutor\"",
+ ex.getMessage());
+ }
+ }
+
+ /**
+ * Set up good parameters.
+ */
+ private void setGoodPars() {
+ executorPars = new ExecutorParameters();
+ executorPars.setTaskExecutorPluginClass("org.onap.policy.apex.core.engine.executor.DummyTaskExecutor");
+ executorPars.setTaskSelectionExecutorPluginClass(
+ "org.onap.policy.apex.core.engine.executor.DummyTaskSelectExecutor");
+ executorPars.setStateFinalizerExecutorPluginClass(
+ "org.onap.policy.apex.core.engine.executor.DummyStateFinalizerExecutor");
+
+ EngineParameters enginePars = new EngineParameters();
+ enginePars.getExecutorParameterMap().put("Dummy", executorPars);
+
+ ParameterService.register(enginePars);
+ ParameterService.register(executorPars);
+ }
+
+ /**
+ * Set up non existant parameters.
+ */
+ private void setNonExistantPars() {
+ executorPars = new ExecutorParameters();
+ executorPars.setTaskExecutorPluginClass("org.onap.policy.apex.core.engine.executor.BadTaskExecutor");
+ executorPars.setTaskSelectionExecutorPluginClass(
+ "org.onap.policy.apex.core.engine.executor.BadTaskSelectExecutor");
+ executorPars.setStateFinalizerExecutorPluginClass(
+ "org.onap.policy.apex.core.engine.executor.BadStateFinalizerExecutor");
+
+ EngineParameters enginePars = new EngineParameters();
+ enginePars.getExecutorParameterMap().put("Dummy", executorPars);
+
+ ParameterService.register(enginePars, true);
+ ParameterService.register(executorPars, true);
+ }
+
+ /**
+ * Set up bad parameters.
+ */
+ private void setBadPars() {
+ executorPars = new ExecutorParameters();
+ executorPars.setTaskExecutorPluginClass("java.lang.String");
+ executorPars.setTaskSelectionExecutorPluginClass("java.lang.String");
+ executorPars.setStateFinalizerExecutorPluginClass("java.lang.String");
+
+ EngineParameters enginePars = new EngineParameters();
+ enginePars.getExecutorParameterMap().put("Dummy", executorPars);
+
+ ParameterService.register(enginePars, true);
+ ParameterService.register(executorPars, true);
+ }
+}