package pt.ul.jarmus;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import java.util.Collection;
import java.util.concurrent.Phaser;
import org.junit.Test;
import org.mockito.InOrder;
import org.mockito.Mockito;
import pt.ul.armus.DeadlockInfo;
import pt.ul.armus.Resource;
import pt.ul.armus.conf.ConfigurationLoader;
import pt.ul.armus.conf.DetectionConfiguration;
import pt.ul.armus.conf.MainConfiguration;
import pt.ul.armus.conf.in.ParserException;
import pt.ul.armus.deadlockresolver.DeadlockResolver;
import pt.ul.jarmus.checkers.PhaserChecker;
import pt.ul.jarmus.checkers.PhaserListener;
import pt.ul.jarmus.inst.PhaserObserver;
/**
* A collection of regression tests.
* @author Tiago Cogumbreiro
*
*/
public class RegressionTests {
private static final String JARMUS = "jarmus";
public static class NilResolver implements DeadlockResolver {
@Override
public void onDeadlockDetected(DeadlockInfo deadlock) {
// do nothing
}
}
public static void restart(MainConfiguration conf) {
JArmusController ctl = JArmusSetup.createControllerFrom(conf);
JArmus.getSetup().setController(ctl);
}
private static void initAvoidance() {
MainConfiguration conf;
try {
conf = ConfigurationLoader.parseFromSystem();
conf.detection = new DetectionConfiguration(false, 0, 0);
restart(conf);
} catch (ParserException e) {
throw new AssertionError(e);
}
}
/**
* Found in the deadlocked program {@link pt.ul.jarmus.deadlocks.SplitPhase}
* @throws ParserException
*/
@Test
public void illegalStateClearBlocked1() throws ParserException {
initAvoidance();
// we do not use the Byteman integration
final Phaser a = new pt.ul.jarmus.ext.Phaser(1);
final Phaser b = new pt.ul.jarmus.ext.Phaser(1);
JArmus.register(a);
JArmus.register(b);
b.arriveAndAwaitAdvance();
a.arriveAndAwaitAdvance();
}
/**
* Found in the deadlocked program {@link pt.ul.jarmus.deadlocks.SplitPhase}
* With automatic code instrumentation.
* @throws ParserException
*/
@Test
public void illegalStateClearBlocked2() throws ParserException {
initAvoidance();
final Phaser a = new Phaser(1);
final Phaser b = new Phaser(1);
JArmus.register(a);
JArmus.register(b);
b.arriveAndAwaitAdvance();
a.arriveAndAwaitAdvance();
}
/**
* Found while debugging {@link RegressionTests#illegalStateClearBlocked()}
* Same example, but without automatic code instrumentation.
*/
@Test
public void falseDeadlock1a() {
initAvoidance();
final Phaser a = new pt.ul.jarmus.ext.Phaser(1);
final Phaser b = new pt.ul.jarmus.ext.Phaser(1);
JArmus.register(a);
JArmus.register(b);
b.arrive();
a.arriveAndAwaitAdvance();
b.awaitAdvance(0);
}
/**
* Found while debugging {@link RegressionTests#illegalStateClearBlocked()}
* Same example, but with avoidance, instead of detection.
*/
@Test
public void falseDeadlock1b() throws InterruptedException, InstantiationException, IllegalAccessException {
initAvoidance();
final Phaser a = new Phaser(1);
final Phaser b = new Phaser(1);
JArmus.register(a);
JArmus.register(b);
b.arrive();
a.arriveAndAwaitAdvance();
b.awaitAdvance(0);
}
/**
* Found while debugging {@link RegressionTests#illegalStateClearBlocked()}
* Only triggered with automatic instrumentation, so instead of using
* automatic instrumentation, we make the direct calls instead.
*/
@Test
public void falseDeadlock1c() throws InterruptedException, InstantiationException, IllegalAccessException {
initAvoidance();
final Phaser a = new Phaser(1);
final Phaser b = new Phaser(1);
JArmus.register(a);
JArmus.register(b);
PhaserChecker ph = new PhaserChecker();
ph.onArrive(b);
//b.arrive();
ph.beforeArriveAndAwaitAdvance(a);
//a.arriveAndAwaitAdvance();
ph.afterArriveAndAwaitAdvance();
ph.beforeAwaitAdvance(b, 0);
//b.awaitAdvance(0);
ph.afterAwaitAdvance();
}
/**
* Found while debugging {@link RegressionTests#illegalStateClearBlocked()}
* Checking if automatic instrumentation is working.
*/
@Test
public void falseDeadlock1d() throws InterruptedException, InstantiationException, IllegalAccessException {
PhaserListener facade = Mockito.mock(PhaserListener.class);
PhaserObserver.aspectOf().setListener(facade);
initAvoidance();
final Phaser a = new Phaser(1);
final Phaser b = new Phaser(1);
JArmus.register(a);
JArmus.register(b);
b.arrive();
a.arriveAndAwaitAdvance();
b.awaitAdvance(0);
// Verify phase
InOrder inOrder = inOrder(facade);
inOrder.verify(facade).onArrive(b);
//b.arrive();
inOrder.verify(facade).beforeArriveAndAwaitAdvance(a);
//a.arriveAndAwaitAdvance();
inOrder.verify(facade).afterArriveAndAwaitAdvance();
inOrder.verify(facade).beforeAwaitAdvance(b, 0);
//b.awaitAdvance(0);
inOrder.verify(facade).afterAwaitAdvance();
verifyNoMoreInteractions(facade);
}
/**
* Register not working.
* @throws IllegalAccessException
* @throws InstantiationException
*/
@Test
public void forgotToSetBlocked() throws InstantiationException, IllegalAccessException {
initAvoidance();
final Phaser barrier1 = new Phaser(1);
JArmus.register(barrier1);
assertTrue(JArmus.getSetup().getController().isRegistered(barrier1));
try {
barrier1.awaitAdvance(0);
} catch (DeadlockIdentifiedException e) {
// ok
}
}
}