package xapi.process;
import static xapi.log.X_Log.info;
import static xapi.process.X_Process.flush;
import static xapi.process.X_Process.kill;
import static xapi.process.X_Process.newThread;
import static xapi.process.X_Process.now;
import static xapi.process.X_Process.runDeferred;
import static xapi.process.X_Process.runFinally;
import static xapi.process.X_Process.threadStartTime;
import static xapi.process.X_Process.trySleep;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import xapi.util.X_Namespace;
import xapi.util.api.Pointer;
public class ConcurrencyTest {
@BeforeClass public static void prepare() {
System.setProperty(X_Namespace.PROPERTY_RUNTIME_META, "target/test-classes");
System.setProperty(X_Namespace.PROPERTY_DEBUG, "true");
System.setProperty(X_Namespace.PROPERTY_MULTITHREADED, "5");
}
@Test
public void testSimpleDeferment() throws Exception{
final Pointer<Boolean> success = new Pointer<Boolean>();
runDeferred(new Runnable() {
@Override
public void run() {
success.set(true);
}
});
success.set(false);
flush(1000);
Assert.assertTrue(success.get());
}
@Test
public void testMultiDeferment() throws Exception{
final Pointer<Boolean> success = new Pointer<Boolean>();
runFinally(new Runnable() {
@Override
public void run() {
success.set(false);
}
});
runDeferred(new Runnable() {
@Override
public void run() {
success.set(true);
}
});
success.set(false);
flush(1000);
Assert.assertTrue(success.get());
}
@Test
public void testComplexDeferment() throws Exception{
//When launching multiple finalies and defers,
//we expect all finalies to run between all deferred commands.
//We will use a closure object to make sure execution is happening in the expected order.
final Pointer<Long> stage = new Pointer<Long>(0L);
runFinally(new Runnable() {
@Override
public void run() {
//runs first
Assert.assertEquals("1st defer ran before 1st finally",stage.get().longValue(), 0);
stage.set(1L);
runDeferred(new Runnable() {
@Override
public void run() {
//runs last
Assert.assertEquals("2nd defer ran before 2nd finally",stage.get().longValue(), 3);
stage.set(4L);
}
});
}
});
runDeferred(new Runnable() {
@Override
public void run() {
//runs second
Assert.assertEquals("1st defer ran before 1st finally",stage.get().longValue(), 1);
stage.set(2L);
runFinally(new Runnable() {
@Override
public void run() {
//runs third, as a finally inside a defer should.
Assert.assertEquals("2nd finally did not run after 1st defer",stage.get().longValue(), 2);
stage.set(3L);
}
});
}
});
flush(1000);
Assert.assertTrue(stage.get() == 4);
}
@Test
public void testSimpleThread() {
final Pointer<Boolean> success = new Pointer<Boolean>();
Thread t = newThread(new Runnable() {
@Override
public void run() {
info("Thread start time: "+(now()-threadStartTime()));
//make sure our thread flushed when it's done!
runFinally(new Runnable() {
@Override
public void run() {
info("To True: "+(now()-threadStartTime()));
success.set(true);
}
});
info("To False: "+(now()-threadStartTime()));
success.set(false);
}
});
success.set(false);
runFinally(new Runnable() {
@Override
public void run() {
info("To False: "+(now()-threadStartTime()));
success.set(false);
}
});
t.start();
trySleep(500);
flush(t, 250);
Assert.assertTrue(success.get());
}
@Test
public void testThreadTimeout() {
final Pointer<Boolean> timeout = new Pointer<Boolean>(false);
final Pointer<Boolean> ran = new Pointer<Boolean>(false);
Thread first = newThread(new Runnable() {
@Override
public void run() {
ran.set(true);
runFinally(new Runnable() {
@Override
public void run() {
timeout.set(true);
}
});
timeout.set(false);
}
});
first.start();
trySleep(50);
kill(first, 200);
Assert.assertTrue("Did not run",ran.get());
Assert.assertTrue("Timing failed",timeout.get());
}
}