package ee.telekom.workflow.graph;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import org.junit.Assert;
import ee.telekom.workflow.graph.core.EnvironmentImpl;
import ee.telekom.workflow.graph.core.GraphEngineImpl;
import ee.telekom.workflow.graph.node.event.CatchSignal;
import ee.telekom.workflow.graph.node.event.CatchTimer;
public abstract class AbstractGraphTest{
protected static List<String> EVENTS_0WI = Collections.unmodifiableList( Arrays.asList(
RecordEventsListener.INSTANCE_CREATED,
RecordEventsListener.INSTANCE_STARTED,
RecordEventsListener.INSTANCE_COMPLETED ) );
protected static List<String> EVENTS_1WI = Collections.unmodifiableList( Arrays.asList(
RecordEventsListener.INSTANCE_CREATED,
RecordEventsListener.WORK_ITEM_CREATED + " 1",
RecordEventsListener.INSTANCE_STARTED,
RecordEventsListener.WORK_ITEM_COMPLETED + " 1",
RecordEventsListener.INSTANCE_COMPLETED ) );
protected static List<String> EVENTS_2WI_SERIAL = Collections.unmodifiableList( Arrays.asList(
RecordEventsListener.INSTANCE_CREATED,
RecordEventsListener.WORK_ITEM_CREATED + " 1",
RecordEventsListener.INSTANCE_STARTED,
RecordEventsListener.WORK_ITEM_COMPLETED + " 1",
RecordEventsListener.WORK_ITEM_CREATED + " 1",
RecordEventsListener.WORK_ITEM_COMPLETED + " 1",
RecordEventsListener.INSTANCE_COMPLETED ) );
protected static List<String> EVENTS_2WI_PARALLEL = Collections.unmodifiableList( Arrays.asList(
RecordEventsListener.INSTANCE_CREATED,
RecordEventsListener.WORK_ITEM_CREATED + " 2",
RecordEventsListener.WORK_ITEM_CREATED + " 3",
RecordEventsListener.INSTANCE_STARTED,
RecordEventsListener.WORK_ITEM_COMPLETED + " 2",
RecordEventsListener.WORK_ITEM_COMPLETED + " 3",
RecordEventsListener.INSTANCE_COMPLETED ) );
protected void assertConditionalExecution( Graph graph, String testValue, String expectedPath ){
EnvironmentImpl env = createSingletonEnvironment( GraphFactory.CONDITION_TEST_ATTRIBUTE, testValue );
EnvironmentImpl expectedEnv = createSingletonEnvironment( GraphFactory.CONDITION_TEST_ATTRIBUTE, testValue );
expectedEnv.setAttribute( RecordPathScript.ATTRIBUTE, expectedPath );
assertExecution( graph, env, expectedEnv );
}
protected void assertLoopExecution( Graph graph, long loopCount, String expectedPath ){
EnvironmentImpl expectedEnv = createSingletonEnvironment( "executionCount", loopCount );
expectedEnv.setAttribute( RecordPathScript.ATTRIBUTE, expectedPath );
assertExecution( graph, null, expectedEnv );
}
protected void assertExecution( Graph graph, String expectedPath ){
EnvironmentImpl expectedEnv = createSingletonEnvironment( RecordPathScript.ATTRIBUTE, expectedPath );
assertExecution( graph, null, expectedEnv );
}
protected void assertExecution( Graph graph, Environment initialEnv, EnvironmentImpl expectedEnv ){
RecordEventsListener listener = new RecordEventsListener();
GraphEngine engine = createEngine( listener );
GraphInstance instance = engine.start( graph, initialEnv );
assertActiveTokens( instance, 0 );
assertActiveWorkItems( instance, 0 );
Assert.assertTrue( instance.isCompleted() );
assertEnvironmnent( instance, expectedEnv );
Assert.assertEquals( EVENTS_0WI, listener.getEvents() );
}
protected void assertPath( GraphInstance instance, String expectedPath ){
String actualPath = (String)instance.getEnvironment().getAttribute( RecordPathScript.ATTRIBUTE );
Assert.assertEquals( expectedPath, actualPath );
}
protected void assertActiveTokens( GraphInstance instance, int count ){
Assert.assertEquals( count, instance.getActiveTokens().size() );
}
protected void assertActiveWorkItems( GraphInstance instance, int count ){
Assert.assertEquals( count, getActiveWorkItems( instance ).size() );
}
protected void assertEnvironmnent( GraphInstance instance, Environment expectedEnv ){
// Iterating both ways to ensure that both environments contain the same attributes!
for( String name : expectedEnv.getAttributeNames() ){
Object expected = expectedEnv.getAttribute( name );
Object actual = instance.getEnvironment().getAttribute( name );
Assert.assertTrue( "Attribute with name " + name + " not equal. Expected: " + expected + ", Actual: " + actual, equals( expected, actual ) );
}
for( String name : instance.getEnvironment().getAttributeNames() ){
Object expected = expectedEnv.getAttribute( name );
Object actual = instance.getEnvironment().getAttribute( name );
Assert.assertTrue( "Attribute with name " + name + " not equal. Expected: " + expected + ", Actual: " + actual, equals( expected, actual ) );
}
}
protected void assertAwaitingSignal( Token token, String signal ){
Assert.assertTrue( token.isActive() );
Assert.assertTrue( token.getNode() instanceof CatchSignal );
GraphWorkItem wi = token.getInstance().getActiveWorkItem( token );
Assert.assertEquals( signal, wi.getSignal() );
Assert.assertEquals( WorkItemStatus.NEW, wi.getStatus() );
}
protected void assertAwaitingTimer( Token token, long delayInMs ){
Assert.assertTrue( token.isActive() );
Assert.assertTrue( token.getNode() instanceof CatchTimer );
GraphWorkItem wi = token.getInstance().getActiveWorkItem( token );
// Asserting that the timer is due after expected delay +/- 10 seconds.
Date min = new Date( System.currentTimeMillis() + delayInMs - 10000 );
Date max = new Date( System.currentTimeMillis() + delayInMs + 10000 );
Assert.assertTrue( min.before( wi.getDueDate() ) );
Assert.assertTrue( max.after( wi.getDueDate() ) );
Assert.assertEquals( WorkItemStatus.NEW, wi.getStatus() );
}
protected void completeWorkItemOnToken( GraphEngineFacade engine, Token token ){
GraphWorkItem wi = token.getInstance().getActiveWorkItem( token );
engine.complete( wi );
}
private boolean equals( Object a, Object b ){
if( a == null && b == null ){
return true;
}
if( (a != null && b == null) || (a == null && b != null) ){
return false;
}
if( !a.getClass().equals( b.getClass() ) ){
return false;
}
if( a instanceof int[] ){
return Arrays.equals( (int[])a, (int[])b );
}
else{ // Yes, there are other array types but those are not tested
return a.equals( b );
}
}
protected List<GraphWorkItem> getActiveWorkItems( GraphInstance instance ){
List<GraphWorkItem> result = new LinkedList<>();
for( GraphWorkItem wi : instance.getWorkItems() ){
if( !WorkItemStatus.COMPLETED.equals( wi.getStatus() )
&& !WorkItemStatus.CANCELLED.equals( wi.getStatus() ) ){
result.add( wi );
}
}
return result;
}
protected GraphEngineImpl createEngine( RecordEventsListener listener ){
GraphEngineImpl engine = new GraphEngineImpl();
engine.registerInstanceEventListener( listener );
engine.registerWorkItemEventListener( listener );
return engine;
}
protected EnvironmentImpl createSingletonEnvironment( String name, Object value ){
EnvironmentImpl environment = new EnvironmentImpl();
environment.setAttribute( name, value );
return environment;
}
protected Token getTokenById( Collection<Token> tokens, long id ){
for( Token token : tokens ){
if( token.getId() == id ){
return token;
}
}
return null;
}
}