Tune tests, modify web sample, add more logging
- In web sample change other event C to K which brings machine back from S2 to S1. - Add more logging. - New test sending parallel events.
This commit is contained in:
@@ -108,7 +108,7 @@ public class StateMachineConfig {
|
||||
.source(States.S1).target(States.S2).event(Events.C)
|
||||
.and()
|
||||
.withExternal()
|
||||
.source(States.S2).target(States.S1).event(Events.C)
|
||||
.source(States.S2).target(States.S1).event(Events.K)
|
||||
.and()
|
||||
.withExternal()
|
||||
.source(States.S1).target(States.S0).event(Events.D)
|
||||
@@ -201,7 +201,7 @@ public class StateMachineConfig {
|
||||
}
|
||||
|
||||
public static enum Events {
|
||||
A, B, C, D, E, F, G, H, I, J
|
||||
A, B, C, D, E, F, G, H, I, J, K
|
||||
}
|
||||
|
||||
private static class FooAction implements Action<States, Events> {
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
<button ng-click="sendEvent('G')">event G</button>
|
||||
<button ng-click="sendEvent('H')">event H</button>
|
||||
<button ng-click="sendEvent('I')">event I</button>
|
||||
<button ng-click="sendEvent('K')">event K</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
|
||||
@@ -28,6 +28,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
@@ -124,9 +125,13 @@ public class StateMachineTestPlan<S, E> {
|
||||
sendVia.add(stateMachines.values().iterator().next());
|
||||
}
|
||||
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.sendEvent);
|
||||
if (!step.sendEventParallel) {
|
||||
for (StateMachine<S, E> machine : sendVia) {
|
||||
log.info("Sending test event " + step.sendEvent + " via machine " + machine);
|
||||
machine.sendEvent(step.sendEvent);
|
||||
}
|
||||
} else {
|
||||
sendEventParallel(sendVia, step.sendEvent);
|
||||
}
|
||||
} else if (step.sendMessage != null) {
|
||||
ArrayList<StateMachine<S, E>> sendVia = new ArrayList<StateMachine<S, E>>();
|
||||
@@ -244,4 +249,40 @@ public class StateMachineTestPlan<S, E> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send event parallel to all machines.
|
||||
*
|
||||
* @param machines the machines
|
||||
* @param event the event
|
||||
*/
|
||||
private void sendEventParallel(final List<StateMachine<S, E>> machines, final E event) {
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
final ArrayList<Thread> joins = new ArrayList<Thread>();
|
||||
int threadCount = machines.size();
|
||||
for (int i = 0; i < threadCount; ++i) {
|
||||
final StateMachine<S,E> machine = machines.get(i);
|
||||
Runnable runner = new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
latch.await();
|
||||
machine.sendEvent(event);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
};
|
||||
Thread t = new Thread(runner, "EventSenderThread" + i);
|
||||
joins.add(t);
|
||||
t.start();
|
||||
}
|
||||
latch.countDown();
|
||||
for (Thread t : joins) {
|
||||
try {
|
||||
t.join();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -114,6 +114,7 @@ public class StateMachineTestPlanBuilder<S, E> {
|
||||
Message<E> sendMessage;
|
||||
Object sendEventMachineId;
|
||||
boolean sendEventToAll = false;
|
||||
boolean sendEventParallel = false;
|
||||
final Collection<S> expectStates = new ArrayList<S>();
|
||||
Integer expectStateChanged;
|
||||
Integer expectStateEntered;
|
||||
@@ -172,9 +173,25 @@ public class StateMachineTestPlanBuilder<S, E> {
|
||||
* @return the state machine test plan step builder
|
||||
*/
|
||||
public StateMachineTestPlanStepBuilder sendEvent(E event, boolean sendToAll) {
|
||||
sendEvent(event, sendToAll, false);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @param event the event
|
||||
* @param sendToAll send to all machines
|
||||
* @param sendParallel send event parallel
|
||||
* @return the state machine test plan step builder
|
||||
*/
|
||||
public StateMachineTestPlanStepBuilder sendEvent(E event, boolean sendToAll, boolean sendParallel) {
|
||||
this.sendEvent = event;
|
||||
this.sendEventMachineId = null;
|
||||
this.sendEventToAll = sendToAll;
|
||||
this.sendEventParallel = sendParallel;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -405,9 +422,10 @@ public class StateMachineTestPlanBuilder<S, E> {
|
||||
*/
|
||||
public StateMachineTestPlanBuilder<S, E> and() {
|
||||
steps.add(new StateMachineTestPlanStep<S, E>(sendEvent, sendMessage, sendEventMachineId, sendEventToAll,
|
||||
expectStates, expectStateChanged, expectStateEntered, expectStateExited, expectEventNotAccepted,
|
||||
expectTransition, expectTransitionStarted, expectTransitionEnded, expectStateMachineStarted,
|
||||
expectStateMachineStopped, expectVariableKeys, expectVariables, expectExtendedStateChanged));
|
||||
sendEventParallel, expectStates, expectStateChanged, expectStateEntered, expectStateExited,
|
||||
expectEventNotAccepted, expectTransition, expectTransitionStarted, expectTransitionEnded,
|
||||
expectStateMachineStarted, expectStateMachineStopped, expectVariableKeys, expectVariables,
|
||||
expectExtendedStateChanged));
|
||||
return StateMachineTestPlanBuilder.this;
|
||||
}
|
||||
|
||||
@@ -418,6 +436,7 @@ public class StateMachineTestPlanBuilder<S, E> {
|
||||
Message<E> sendMessage;
|
||||
Object sendEventMachineId;
|
||||
boolean sendEventToAll = false;
|
||||
boolean sendEventParallel = false;
|
||||
final Collection<S> expectStates;
|
||||
Integer expectStateChanged;
|
||||
Integer expectStateEntered;
|
||||
@@ -433,15 +452,17 @@ public class StateMachineTestPlanBuilder<S, E> {
|
||||
final Map<Object, Object> expectVariables;
|
||||
|
||||
public StateMachineTestPlanStep(E sendEvent, Message<E> sendMessage, Object sendEventMachineId,
|
||||
boolean sendEventToAll, Collection<S> expectStates, Integer expectStateChanged,
|
||||
Integer expectStateEntered, Integer expectStateExited, Integer expectEventNotAccepted,
|
||||
Integer expectTransition, Integer expectTransitionStarted, Integer expectTransitionEnded,
|
||||
Integer expectStateMachineStarted, Integer expectStateMachineStopped,
|
||||
Collection<Object> expectVariableKeys, Map<Object, Object> expectVariables, Integer expectExtendedStateChanged) {
|
||||
boolean sendEventToAll, boolean sendEventParallel, Collection<S> expectStates,
|
||||
Integer expectStateChanged, Integer expectStateEntered, Integer expectStateExited,
|
||||
Integer expectEventNotAccepted, Integer expectTransition, Integer expectTransitionStarted,
|
||||
Integer expectTransitionEnded, Integer expectStateMachineStarted, Integer expectStateMachineStopped,
|
||||
Collection<Object> expectVariableKeys, Map<Object, Object> expectVariables,
|
||||
Integer expectExtendedStateChanged) {
|
||||
this.sendEvent = sendEvent;
|
||||
this.sendMessage = sendMessage;
|
||||
this.sendEventMachineId = sendEventMachineId;
|
||||
this.sendEventToAll = sendEventToAll;
|
||||
this.sendEventParallel = sendEventParallel;
|
||||
this.expectStates = expectStates;
|
||||
this.expectStateChanged = expectStateChanged;
|
||||
this.expectStateEntered = expectStateEntered;
|
||||
|
||||
@@ -223,6 +223,9 @@ public class ZookeeperStateMachineEnsemble<S, E> extends StateMachineEnsembleObj
|
||||
log.debug("Requesting persist write " + context + " with version " + stat.getVersion() + " for ensemble " + uuid);
|
||||
}
|
||||
persist.write(context, stat);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Request persist write ok " + context + " new version " + stat.getVersion() + " for ensemble " + uuid);
|
||||
}
|
||||
stateRef.set(new StateWrapper(context, stat.getVersion()));
|
||||
} catch (Exception e) {
|
||||
throw new StateMachineException("Error persisting data", e);
|
||||
|
||||
@@ -304,6 +304,76 @@ public class ZookeeperStateMachineTests extends AbstractZookeeperTests {
|
||||
plan.test();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParallelEvents() throws Exception {
|
||||
context.register(ZkServerConfig.class, BaseConfig.class);
|
||||
context.refresh();
|
||||
|
||||
CuratorFramework curatorClient =
|
||||
context.getBean("curatorClient", CuratorFramework.class);
|
||||
|
||||
StateMachine<String, String> machine1 =
|
||||
buildTestStateMachine2(curatorClient);
|
||||
StateMachine<String, String> machine2 =
|
||||
buildTestStateMachine2(curatorClient);
|
||||
StateMachine<String, String> machine3 =
|
||||
buildTestStateMachine2(curatorClient);
|
||||
StateMachine<String, String> machine4 =
|
||||
buildTestStateMachine2(curatorClient);
|
||||
StateMachine<String, String> machine5 =
|
||||
buildTestStateMachine2(curatorClient);
|
||||
|
||||
StateMachineTestPlan<String, String> plan =
|
||||
StateMachineTestPlanBuilder.<String, String>builder()
|
||||
.defaultAwaitTime(2)
|
||||
.stateMachine(machine1)
|
||||
.stateMachine(machine2)
|
||||
.stateMachine(machine3)
|
||||
.stateMachine(machine4)
|
||||
.stateMachine(machine5)
|
||||
.step()
|
||||
.expectStates("SI")
|
||||
.and()
|
||||
.step()
|
||||
.sendEvent("E1", true)
|
||||
.expectStateChanged(1)
|
||||
.expectStates("S1")
|
||||
.and()
|
||||
.step()
|
||||
.sendEvent("E2", true, true)
|
||||
.expectStateChanged(1)
|
||||
.expectStates("S2")
|
||||
.and()
|
||||
.step()
|
||||
.sendEvent("E3", true, true)
|
||||
.expectStateChanged(1)
|
||||
.expectStates("S1")
|
||||
.and()
|
||||
.step()
|
||||
.sendEvent("E2", true, true)
|
||||
.expectStateChanged(1)
|
||||
.expectStates("S2")
|
||||
.and()
|
||||
.step()
|
||||
.sendEvent("E3", true, true)
|
||||
.expectStateChanged(1)
|
||||
.expectStates("S1")
|
||||
.and()
|
||||
.step()
|
||||
.sendEvent("E2", true, true)
|
||||
.expectStateChanged(1)
|
||||
.expectStates("S2")
|
||||
.and()
|
||||
.step()
|
||||
.sendEvent("E3", true, true)
|
||||
.expectStateChanged(1)
|
||||
.expectStates("S1")
|
||||
.and()
|
||||
.build();
|
||||
|
||||
plan.test();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtendedStateVariables1() throws Exception {
|
||||
context.register(ZkServerConfig.class, BaseConfig.class);
|
||||
@@ -843,6 +913,9 @@ public class ZookeeperStateMachineTests extends AbstractZookeeperTests {
|
||||
.withExternal()
|
||||
.source("S1").target("S2").event("E2")
|
||||
.and()
|
||||
.withExternal()
|
||||
.source("S2").target("S1").event("E3")
|
||||
.and()
|
||||
.withInternal()
|
||||
.source("SI").event("EV")
|
||||
.action(setVariableAction())
|
||||
|
||||
Reference in New Issue
Block a user