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:
@@ -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> {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user