Join state should not be entered

- Fix join pseudostate to be transient.
- Fix tests which uses wrong concepts.
- Fixes #222
This commit is contained in:
Janne Valkealahti
2016-05-06 17:24:54 +01:00
parent 2836902635
commit 12137222a8
9 changed files with 79 additions and 39 deletions

View File

@@ -49,6 +49,29 @@ public class ForkJoinEntryExitTests extends AbstractBuildTests {
plan.test();
}
@Test
@SuppressWarnings("unchecked")
public void testJoinExits() throws Exception {
context.register(Config1.class);
context.refresh();
StateMachine<String, String> stateMachine = context.getBean(StateMachine.class);
StateMachineTestPlan<String, String> plan =
StateMachineTestPlanBuilder.<String, String>builder()
.stateMachine(stateMachine)
.step().expectState("S1").and()
.step()
.sendEvent("E1")
.expectStates("S2", "S210", "S220").and()
.step()
.sendEvent("E2")
.sendEvent("E3")
.expectStateEntered(3)
.expectStates("S3").and()
.build();
plan.test();
}
@Configuration
@EnableStateMachine
public static class Config1 extends StateMachineConfigurerAdapter<String, String> {

View File

@@ -631,7 +631,19 @@ public abstract class AbstractStateMachineFactory<S, E> extends LifecycleObjectS
joins.add(stateMap.get(fs));
}
}
JoinPseudoState<S, E> pseudoState = new JoinPseudoState<S, E>(joins);
S ss = null;
Collection<TransitionData<S, E>> transitions = stateMachineTransitions.getTransitions();
for (TransitionData<S, E> tt : transitions) {
if (tt.getSource() == s) {
ss = tt.getTarget();
break;
}
}
StateHolder<S, E> holder = new StateHolder<S, E>(stateMap.get(ss));
if (holder.getState() == null) {
holderMap.put(ss, holder);
}
JoinPseudoState<S, E> pseudoState = new JoinPseudoState<S, E>(joins, holder);
state = buildStateInternal(stateData.getState(), stateData.getDeferred(), stateData.getEntryActions(),
stateData.getExitActions(), pseudoState);
states.add(state);

View File

@@ -21,6 +21,7 @@ import java.util.List;
import org.springframework.statemachine.StateContext;
import org.springframework.statemachine.listener.StateMachineListenerAdapter;
import org.springframework.statemachine.state.PseudoStateContext.PseudoAction;
import org.springframework.util.Assert;
/**
* Join implementation of a {@link PseudoState}.
@@ -34,22 +35,26 @@ public class JoinPseudoState<S, E> extends AbstractPseudoState<S, E> {
private final List<State<S, E>> joins;
private volatile JoinTracker tracker;
private final StateHolder<S, E> state;
/**
* Instantiates a new join pseudo state.
*
* @param joins the joins
* @param state the holder for target state
*/
public JoinPseudoState(List<State<S, E>> joins) {
public JoinPseudoState(List<State<S, E>> joins, StateHolder<S, E> state) {
super(PseudoStateKind.JOIN);
Assert.notNull(state, "Holder must be set");
this.joins = joins;
this.state = state;
}
@Override
public State<S, E> entry(StateContext<S, E> context) {
tracker = new JoinTracker(this, new ArrayList<State<S,E>>(joins));
context.getStateMachine().addStateListener(tracker);
return null;
return state.getState();
}
@Override

View File

@@ -146,7 +146,6 @@ public class RegionState<S, E> extends AbstractState<S, E> {
@Override
public void entry(StateContext<S, E> context) {
System.out.println("XXXXXX " + context);
if (join != null) {
join.entry(context);
}

View File

@@ -751,7 +751,7 @@ public abstract class AbstractStateMachine<S, E> extends StateMachineObjectSuppo
private State<S,E> followLinkedPseudoStates(State<S,E> state, StateContext<S, E> stateContext) {
PseudoStateKind kind = state.getPseudoState() != null ? state.getPseudoState().getKind() : null;
if (kind == PseudoStateKind.INITIAL || kind == PseudoStateKind.JOIN || kind == PseudoStateKind.FORK) {
if (kind == PseudoStateKind.INITIAL || kind == PseudoStateKind.FORK) {
return state;
} else if (kind != null) {
State<S,E> toState = state.getPseudoState().entry(stateContext);
@@ -776,6 +776,7 @@ public abstract class AbstractStateMachine<S, E> extends StateMachineObjectSuppo
State<S, E> toState = findStateWithPseudoState(pseudoState);
StateContext<S, E> stateContext = buildStateContext(Stage.STATE_EXIT, null, null, getRelayStateMachine());
pseudoState.exit(stateContext);
toState = followLinkedPseudoStates(toState, stateContext);
switchToState(toState, null, null, getRelayStateMachine());
}
});

View File

@@ -146,10 +146,10 @@ public class StateMachineTests extends AbstractStateMachineTests {
assertThat(listener.stateChangedCount, is(1));
assertThat(machine.getState().getIds(), containsInAnyOrder(TestStates.S2, TestStates.S21, TestStates.S30));
listener.reset(3);
listener.reset(2);
machine.sendEvent(TestEvents.E3);
assertThat(listener.stateChangedLatch.await(2, TimeUnit.SECONDS), is(true));
assertThat(listener.stateChangedCount, is(3));
assertThat(listener.stateChangedCount, is(2));
assertThat(machine.getState().getIds(), containsInAnyOrder(TestStates.S4));
}

View File

@@ -70,10 +70,10 @@ public class JoinStateTests extends AbstractStateMachineTests {
assertThat(listener.stateChangedLatch.await(2, TimeUnit.SECONDS), is(true));
assertThat(listener.stateChangedCount, is(1));
listener.reset(3);
listener.reset(2);
machine.sendEvent(TestEvents.E3);
assertThat(listener.stateChangedLatch.await(2, TimeUnit.SECONDS), is(true));
assertThat(listener.stateChangedCount, is(3));
assertThat(listener.stateChangedCount, is(2));
assertThat(machine.getState().getIds(), contains(TestStates.S4));
}
@@ -144,10 +144,10 @@ public class JoinStateTests extends AbstractStateMachineTests {
assertThat(listener.stateChangedLatch.await(2, TimeUnit.SECONDS), is(true));
assertThat(listener.stateChangedCount, is(1));
listener.reset(3);
listener.reset(2);
machine.sendEvent(TestEvents.E3);
assertThat(listener.stateChangedLatch.await(2, TimeUnit.SECONDS), is(true));
assertThat(listener.stateChangedCount, is(3));
assertThat(listener.stateChangedCount, is(2));
assertThat(machine.getState().getIds(), contains(TestStates.S4));
}

View File

@@ -47,7 +47,7 @@ public class TasksHandlerTests {
.build();
TestListener listener = new TestListener();
listener.reset(10, 0, 0);
listener.reset(9, 0, 0);
StateMachine<String, String> machine = handler.getStateMachine();
machine.addStateListener(listener);
machine.start();
@@ -56,7 +56,7 @@ public class TasksHandlerTests {
handler.runTasks();
assertThat(listener.stateChangedLatch.await(8, TimeUnit.SECONDS), is(true));
assertThat(listener.stateChangedCount, is(10));
assertThat(listener.stateChangedCount, is(9));
assertThat(machine.getState().getIds(), contains(TasksHandler.STATE_READY));
Map<Object, Object> variables = machine.getExtendedState().getVariables();
assertThat(variables.size(), is(3));
@@ -71,7 +71,7 @@ public class TasksHandlerTests {
.build();
TestListener listener = new TestListener();
listener.reset(12, 0, 0);
listener.reset(11, 0, 0);
StateMachine<String, String> machine = handler.getStateMachine();
machine.addStateListener(listener);
machine.start();
@@ -80,7 +80,7 @@ public class TasksHandlerTests {
handler.runTasks();
assertThat(listener.stateChangedLatch.await(8, TimeUnit.SECONDS), is(true));
assertThat(listener.stateChangedCount, is(12));
assertThat(listener.stateChangedCount, is(11));
assertThat(machine.getState().getIds(), contains(TasksHandler.STATE_ERROR, TasksHandler.STATE_MANUAL));
Map<Object, Object> variables = machine.getExtendedState().getVariables();
assertThat(variables.size(), is(3));
@@ -95,7 +95,7 @@ public class TasksHandlerTests {
.build();
TestListener listener = new TestListener();
listener.reset(12, 0, 0);
listener.reset(11, 0, 0);
StateMachine<String, String> machine = handler.getStateMachine();
machine.addStateListener(listener);
machine.start();
@@ -104,7 +104,7 @@ public class TasksHandlerTests {
handler.runTasks();
assertThat(listener.stateChangedLatch.await(8, TimeUnit.SECONDS), is(true));
assertThat(listener.stateChangedCount, is(12));
assertThat(listener.stateChangedCount, is(11));
assertThat(machine.getState().getIds(), contains(TasksHandler.STATE_ERROR, TasksHandler.STATE_MANUAL));
listener.reset(0, 0, 0, 0, 1);
@@ -139,11 +139,11 @@ public class TasksHandlerTests {
assertThat(listener.stateChangedLatch.await(2, TimeUnit.SECONDS), is(true));
assertThat(listener.stateChangedCount, is(1));
listener.reset(11, 0, 0);
listener.reset(10, 0, 0);
handler.runTasks();
assertThat(listener.stateChangedLatch.await(4, TimeUnit.SECONDS), is(true));
assertThat(listener.stateChangedCount, is(11));
assertThat(listener.stateChangedCount, is(10));
assertThat(machine.getState().getIds(), contains(TasksHandler.STATE_READY));
}
@@ -156,7 +156,7 @@ public class TasksHandlerTests {
.build();
TestListener listener = new TestListener();
listener.reset(10, 0, 0);
listener.reset(9, 0, 0);
StateMachine<String, String> machine = handler.getStateMachine();
machine.addStateListener(listener);
machine.start();
@@ -165,7 +165,7 @@ public class TasksHandlerTests {
handler.runTasks();
assertThat(listener.stateChangedLatch.await(12, TimeUnit.SECONDS), is(true));
assertThat(listener.stateChangedCount, is(10));
assertThat(listener.stateChangedCount, is(9));
assertThat(machine.getState().getIds(), contains(TasksHandler.STATE_READY));
Map<Object, Object> variables = machine.getExtendedState().getVariables();
assertThat(variables.size(), is(3));
@@ -195,11 +195,11 @@ public class TasksHandlerTests {
assertThat(listener.stateChangedLatch.await(2, TimeUnit.SECONDS), is(true));
assertThat(listener.stateChangedCount, is(1));
listener.reset(21, 0, 0);
listener.reset(20, 0, 0);
handler.runTasks();
assertThat(listener.stateChangedLatch.await(10, TimeUnit.SECONDS), is(true));
assertThat(listener.stateChangedCount, is(21));
assertThat(listener.stateChangedCount, is(20));
assertThat(machine.getState().getIds(), contains(TasksHandler.STATE_READY));
Map<Object, Object> variables = machine.getExtendedState().getVariables();
assertThat(variables.size(), is(9));
@@ -216,7 +216,7 @@ public class TasksHandlerTests {
.build();
TestListener listener = new TestListener();
listener.reset(10, 0, 0);
listener.reset(9, 0, 0);
StateMachine<String, String> machine = handler.getStateMachine();
machine.addStateListener(listener);
machine.start();
@@ -226,7 +226,7 @@ public class TasksHandlerTests {
handler.runTasks();
assertThat(listener.stateChangedLatch.await(8, TimeUnit.SECONDS), is(true));
assertThat(listener.stateChangedCount, is(10));
assertThat(listener.stateChangedCount, is(9));
assertThat(machine.getState().getIds(), contains(TasksHandler.STATE_READY));
assertThat(tasksListener.onTasksStartedLatch.await(1, TimeUnit.SECONDS), is(true));
@@ -253,7 +253,7 @@ public class TasksHandlerTests {
.build();
TestListener listener = new TestListener();
listener.reset(12, 0, 0);
listener.reset(11, 0, 0);
StateMachine<String, String> machine = handler.getStateMachine();
machine.addStateListener(listener);
machine.start();
@@ -263,7 +263,7 @@ public class TasksHandlerTests {
handler.runTasks();
assertThat(listener.stateChangedLatch.await(8, TimeUnit.SECONDS), is(true));
assertThat(listener.stateChangedCount, is(12));
assertThat(listener.stateChangedCount, is(11));
assertThat(tasksListener.onTasksStartedLatch.await(1, TimeUnit.SECONDS), is(true));
assertThat(tasksListener.onTasksStarted, is(1));
@@ -287,7 +287,7 @@ public class TasksHandlerTests {
.build();
TestListener listener = new TestListener();
listener.reset(12, 0, 0);
listener.reset(11, 0, 0);
StateMachine<String, String> machine = handler.getStateMachine();
machine.addStateListener(listener);
machine.start();
@@ -297,7 +297,7 @@ public class TasksHandlerTests {
handler.runTasks();
assertThat(listener.stateChangedLatch.await(8, TimeUnit.SECONDS), is(true));
assertThat(listener.stateChangedCount, is(12));
assertThat(listener.stateChangedCount, is(11));
assertThat(machine.getState().getIds(), contains(TasksHandler.STATE_ERROR, TasksHandler.STATE_MANUAL));
listener.reset(1, 0, 0);
@@ -322,7 +322,7 @@ public class TasksHandlerTests {
.build();
TestListener listener = new TestListener();
listener.reset(10, 0, 0);
listener.reset(9, 0, 0);
StateMachine<String, String> machine = handler.getStateMachine();
machine.addStateListener(listener);
machine.start();
@@ -333,7 +333,7 @@ public class TasksHandlerTests {
handler.runTasks();
assertThat(listener.stateChangedLatch.await(8, TimeUnit.SECONDS), is(true));
assertThat(listener.stateChangedCount, is(10));
assertThat(listener.stateChangedCount, is(9));
assertThat(machine.getState().getIds(), contains(TasksHandler.STATE_READY));
Map<Object, Object> variables = machine.getExtendedState().getVariables();
assertThat(variables.size(), is(3));
@@ -361,7 +361,7 @@ public class TasksHandlerTests {
.build();
TestListener listener = new TestListener();
listener.reset(12, 0, 0);
listener.reset(11, 0, 0);
StateMachine<String, String> machine = handler.getStateMachine();
machine.addStateListener(listener);
machine.start();
@@ -372,7 +372,7 @@ public class TasksHandlerTests {
handler.runTasks();
assertThat(listener.stateChangedLatch.await(8, TimeUnit.SECONDS), is(true));
assertThat(listener.stateChangedCount, is(12));
assertThat(listener.stateChangedCount, is(11));
assertThat(machine.getState().getIds(), contains(TasksHandler.STATE_ERROR, TasksHandler.STATE_MANUAL));
Map<Object, Object> variables = machine.getExtendedState().getVariables();
assertThat(variables.size(), is(3));

View File

@@ -61,7 +61,7 @@ public class TasksTests {
@Test
public void testRunOnce() throws InterruptedException {
listener.reset(9, 0, 0);
listener.reset(8, 0, 0);
tasks.run();
assertThat(listener.stateChangedLatch.await(8, TimeUnit.SECONDS), is(true));
assertThat(machine.getState().getIds(), contains(States.READY));
@@ -71,7 +71,7 @@ public class TasksTests {
@Test
public void testRunTwice() throws InterruptedException {
listener.reset(9, 0, 0);
listener.reset(8, 0, 0);
tasks.run();
assertThat(listener.stateChangedLatch.await(8, TimeUnit.SECONDS), is(true));
assertThat(machine.getState().getIds(), contains(States.READY));
@@ -79,7 +79,7 @@ public class TasksTests {
Map<Object, Object> variables = machine.getExtendedState().getVariables();
assertThat(variables.size(), is(3));
listener.reset(9, 0, 0);
listener.reset(8, 0, 0);
tasks.run();
assertThat(listener.stateChangedLatch.await(8, TimeUnit.SECONDS), is(true));
assertThat(machine.getState().getIds(), contains(States.READY));
@@ -90,17 +90,17 @@ public class TasksTests {
@Test
public void testFailAutomaticFix() throws InterruptedException {
listener.reset(11, 0, 0);
listener.reset(10, 0, 0);
tasks.fail("T1");
tasks.run();
assertThat(listener.stateChangedLatch.await(6, TimeUnit.SECONDS), is(true));
assertThat(listener.stateChangedCount, is(11));
assertThat(listener.stateChangedCount, is(10));
assertThat(machine.getState().getIds(), contains(States.READY));
}
@Test
public void testFailManualFix() throws InterruptedException {
listener.reset(11, 0, 0);
listener.reset(10, 0, 0);
tasks.fail("T2");
tasks.run();
assertThat(listener.stateChangedLatch.await(6, TimeUnit.SECONDS), is(true));