package org.infinispan.test.concurrent; import static java.util.concurrent.TimeUnit.SECONDS; import static org.testng.AssertJUnit.assertFalse; import java.util.concurrent.Callable; import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicBoolean; import org.infinispan.test.AbstractInfinispanTest; import org.testng.annotations.Test; /** * {@link StateSequencer} test. * * @author Dan Berindei * @since 7.0 */ @Test(groups = "unit", testName = "test.concurrent.StateSequencerTest") public class StateSequencerTest extends AbstractInfinispanTest { public void testSingleThread() throws Exception { StateSequencer stateSequencer = new StateSequencer(); stateSequencer.logicalThread("t", "s0", "s1", "s2"); stateSequencer.advance("s0", 0, SECONDS); stateSequencer.advance("s1", 0, SECONDS); stateSequencer.advance("s2", 0, SECONDS); } @Test(expectedExceptions = IllegalArgumentException.class) public void testAdvanceToInvalidState() throws Exception { StateSequencer stateSequencer = new StateSequencer(); stateSequencer.advance("s1", 0, SECONDS); } @Test(expectedExceptions = IllegalArgumentException.class) public void testInvalidDependency() throws Exception { StateSequencer stateSequencer = new StateSequencer(); stateSequencer.logicalThread("t", "s1"); stateSequencer.order("s0", "s1"); } @Test(expectedExceptions = IllegalArgumentException.class) public void testInvalidDependency2() throws Exception { StateSequencer stateSequencer = new StateSequencer(); stateSequencer.logicalThread("t", "s1"); stateSequencer.order("s1", "s2"); } @Test(expectedExceptions = IllegalStateException.class) public void testDependencyCycle() throws Exception { StateSequencer stateSequencer = new StateSequencer(); stateSequencer.logicalThread("t", "s1", "s2", "s3", "s4"); stateSequencer.order("s4", "s2"); } public void testMultipleThreads() throws Exception { final StateSequencer stateSequencer = new StateSequencer(); stateSequencer.logicalThread("start", "start"); stateSequencer.logicalThread("t1", "t1:s1").order("start", "t1:s1"); stateSequencer.logicalThread("t2", "t2:s2").order("start", "t2:s2").order("t1:s1", "t2:s2"); stateSequencer.logicalThread("stop", "stop").order("t1:s1", "stop").order("t2:s2", "stop"); Future<Object> future1 = fork(new Callable<Object>() { @Override public Object call() throws Exception { stateSequencer.advance("t1:s1", 10, SECONDS); return null; } }); final AtomicBoolean t2s2Entered = new AtomicBoolean(false); Future<Object> future2 = fork(new Callable<Object>() { @Override public Object call() throws Exception { stateSequencer.enter("t2:s2", 10, SECONDS); t2s2Entered.set(true); stateSequencer.exit("t2:s2"); return null; } }); stateSequencer.enter("start", 0, SECONDS); Thread.sleep(500); assertFalse(future1.isDone()); assertFalse(future2.isDone()); assertFalse(t2s2Entered.get()); stateSequencer.exit("start"); stateSequencer.advance("stop", 10, SECONDS); future1.get(); future2.get(); } }