StateMachineTestPlan with multiple event

- Backport #134 fixes #136
- Add support for defining multiple events
  within a single step.
This commit is contained in:
Janne Valkealahti
2015-12-06 15:27:22 +00:00
parent a9d24c038c
commit 8068cb9dd2
3 changed files with 88 additions and 21 deletions

View File

@@ -34,6 +34,7 @@ import java.util.concurrent.TimeUnit;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hamcrest.Matcher;
import org.springframework.messaging.Message;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.test.StateMachineTestPlanBuilder.StateMachineTestPlanStep;
import org.springframework.statemachine.test.support.LatchStateMachineListener;
@@ -119,7 +120,7 @@ public class StateMachineTestPlan<S, E> {
}
}
if (step.sendEvent != null) {
if (!step.sendEvent.isEmpty()) {
ArrayList<StateMachine<S, E>> sendVia = new ArrayList<StateMachine<S, E>>();
if (step.sendEventMachineId != null) {
sendVia.add(stateMachines.get(step.sendEventMachineId));
@@ -131,13 +132,17 @@ public class StateMachineTestPlan<S, E> {
assertThat("Error finding machine to send via", sendVia, not(empty()));
if (!step.sendEventParallel) {
for (StateMachine<S, E> machine : sendVia) {
log.info("Sending test event " + step.sendEvent + " via machine " + machine);
machine.sendEvent(step.sendEvent);
for (E event : step.sendEvent) {
log.info("Sending test event " + event + " via machine " + machine);
machine.sendEvent(event);
}
}
} else {
sendEventParallel(sendVia, step.sendEvent);
for (E event : step.sendEvent) {
sendEventParallel(sendVia, event);
}
}
} else if (step.sendMessage != null) {
} else if (!step.sendMessage.isEmpty()) {
ArrayList<StateMachine<S, E>> sendVia = new ArrayList<StateMachine<S, E>>();
if (step.sendEventMachineId != null) {
sendVia.add(stateMachines.get(step.sendEventMachineId));
@@ -148,8 +153,10 @@ public class StateMachineTestPlan<S, E> {
}
assertThat("Error finding machine to send via", sendVia, not(empty()));
for (StateMachine<S, E> machine : sendVia) {
log.info("Sending test event " + step.sendEvent + " via machine " + machine);
machine.sendEvent(step.sendMessage);
for (Message<E> event : step.sendMessage) {
log.info("Sending test event " + event + " via machine " + machine);
machine.sendEvent(event);
}
}
}

View File

@@ -110,8 +110,8 @@ public class StateMachineTestPlanBuilder<S, E> {
*/
public class StateMachineTestPlanStepBuilder {
E sendEvent;
Message<E> sendMessage;
final List<E> sendEvent = new ArrayList<E>();
final List<Message<E>> sendMessage = new ArrayList<Message<E>>();
Object sendEventMachineId;
boolean sendEventToAll = false;
boolean sendEventParallel = false;
@@ -156,6 +156,8 @@ public class StateMachineTestPlanBuilder<S, E> {
/**
* Send an event {@code E}. In case multiple state machines
* exists, a random one will be chosen to send this event.
* Multiple events can be defined which are then send in
* defined order.
*
* @param event the event
* @return the state machine test plan step builder
@@ -166,7 +168,8 @@ public class StateMachineTestPlanBuilder<S, E> {
/**
* Send an event {@code E}. If {@code sendToAll} is set to {@code TRUE} event
* will be send to all existing machines.
* will be send to all existing machines. Multiple events can be defined
* which are then send in defined order.
*
* @param event the event
* @param sendToAll send to all machines
@@ -181,6 +184,7 @@ public class StateMachineTestPlanBuilder<S, E> {
* Send an event {@code E}. If {@code sendToAll} is set to {@code TRUE} event
* will be send to all existing machines. If {@code sendPalallel} is set to
* {@code TRUE} event to all machines will be send by parallel threads.
* Multiple events can be defined which are then send in defined order.
*
* @param event the event
* @param sendToAll send to all machines
@@ -188,7 +192,7 @@ public class StateMachineTestPlanBuilder<S, E> {
* @return the state machine test plan step builder
*/
public StateMachineTestPlanStepBuilder sendEvent(E event, boolean sendToAll, boolean sendParallel) {
this.sendEvent = event;
this.sendEvent.add(event);
this.sendEventMachineId = null;
this.sendEventToAll = sendToAll;
this.sendEventParallel = sendParallel;
@@ -197,21 +201,23 @@ public class StateMachineTestPlanBuilder<S, E> {
/**
* Send an event {@code E} into a state machine identified
* by {@code machineId}.
* by {@code machineId}. Multiple events can be defined
* which are then send in defined order.
*
* @param event the event
* @param machineId the machine identifier for sending event
* @return the state machine test plan step builder
*/
public StateMachineTestPlanStepBuilder sendEvent(E event, Object machineId) {
this.sendEvent = event;
this.sendEvent.add(event);
this.sendEventMachineId = machineId;
return this;
}
/**
* Send a message {@code Message<E>}. In case multiple state machines
* exists, a random one will be chosen to send this event.
* exists, a random one will be chosen to send this event. Multiple
* events can be defined which are then send in defined order.
*
* @param event the event
* @return the state machine test plan step builder
@@ -222,14 +228,15 @@ public class StateMachineTestPlanBuilder<S, E> {
/**
* Send a message {@code Message<E>}. If {@code sendToAll} is set to {@code TRUE} event
* will be send to all existing machines.
* will be send to all existing machines.Multiple events can be defined which are
* then send in defined order.
*
* @param event the event
* @param sendToAll send to all machines
* @return the state machine test plan step builder
*/
public StateMachineTestPlanStepBuilder sendEvent(Message<E> event, boolean sendToAll) {
this.sendMessage = event;
this.sendMessage.add(event);
this.sendEventMachineId = null;
this.sendEventToAll = sendToAll;
return this;
@@ -237,14 +244,15 @@ public class StateMachineTestPlanBuilder<S, E> {
/**
* Send a message {@code Message<E>} into a state machine identified
* by {@code machineId}.
* by {@code machineId}. Multiple events can be defined which are then
* send in defined order.
*
* @param event the event
* @param machineId the machine identifier for sending event
* @return the state machine test plan step builder
*/
public StateMachineTestPlanStepBuilder sendEvent(Message<E> event, Object machineId) {
this.sendMessage = event;
this.sendMessage.add(event);
this.sendEventMachineId = machineId;
return this;
}
@@ -432,8 +440,8 @@ public class StateMachineTestPlanBuilder<S, E> {
}
static class StateMachineTestPlanStep<S, E> {
E sendEvent;
Message<E> sendMessage;
final List<E> sendEvent;
final List<Message<E>> sendMessage;
Object sendEventMachineId;
boolean sendEventToAll = false;
boolean sendEventParallel = false;
@@ -451,7 +459,7 @@ public class StateMachineTestPlanBuilder<S, E> {
final Collection<Object> expectVariableKeys;
final Map<Object, Object> expectVariables;
public StateMachineTestPlanStep(E sendEvent, Message<E> sendMessage, Object sendEventMachineId,
public StateMachineTestPlanStep(List<E> sendEvent, List<Message<E>> sendMessage, Object sendEventMachineId,
boolean sendEventToAll, boolean sendEventParallel, Collection<S> expectStates,
Integer expectStateChanged, Integer expectStateEntered, Integer expectStateExited,
Integer expectEventNotAccepted, Integer expectTransition, Integer expectTransitionStarted,

View File

@@ -65,6 +65,28 @@ public class StateMachineTestingTests extends AbstractStateMachineTests {
plan.test();
}
@SuppressWarnings("unchecked")
@Test
public void testMultipleEvents() throws Exception {
registerAndRefresh(Config3.class);
StateMachine<String, String> machine = context.getBean(StateMachine.class);
StateMachineTestPlan<String, String> plan =
StateMachineTestPlanBuilder.<String, String>builder()
.stateMachine(machine)
.step().expectStateMachineStarted(1).and()
.step().expectState("READY").and()
.step()
.sendEvent("DEPLOY")
.sendEvent("DEPLOY")
.expectStateChanged(6)
.expectState("READY")
.and()
.build();
plan.test();
}
@Override
protected AnnotationConfigApplicationContext buildContext() {
return new AnnotationConfigApplicationContext();
@@ -142,4 +164,34 @@ public class StateMachineTestingTests extends AbstractStateMachineTests {
}
@Configuration
@EnableStateMachine
static class Config3 extends StateMachineConfigurerAdapter<String, String> {
@Override
public void configure(StateMachineStateConfigurer<String, String> states)
throws Exception {
states
.withStates()
.initial("READY")
.state("DEPLOYPREPARE", "DEPLOY")
.state("DEPLOYEXECUTE", "DEPLOY");
}
@Override
public void configure(StateMachineTransitionConfigurer<String, String> transitions)
throws Exception {
transitions
.withExternal()
.source("READY").target("DEPLOYPREPARE")
.event("DEPLOY")
.and()
.withExternal()
.source("DEPLOYPREPARE").target("DEPLOYEXECUTE")
.and()
.withExternal()
.source("DEPLOYEXECUTE").target("READY");
}
}
}