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();
}
}