package com.orbitz.monitoring.lib.timertask;
import java.lang.management.ManagementFactory;
import java.util.Arrays;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import junit.framework.TestCase;
import com.orbitz.monitoring.api.Monitor;
public class DeadlockDetectionTimerTaskTest extends TestCase {
/**
* This test will create deadlocks. Deadlocks would be much less of a
* problem if they could be resolved programmatically. As they cannot the
* order of these tests is very important. This means there is one master
* test method with three sub methods.
*
* @throws Exception
*/
public void testItAll() throws Exception {
while (ManagementFactory.getThreadMXBean().findMonitorDeadlockedThreads() != null) {
fail("Started with thread already in deadlock: " + Arrays.toString(ManagementFactory.getThreadMXBean().findMonitorDeadlockedThreads()));
}
noDeadlock();
createDeadlock();
deadlock();
deadlockMonitoringOff();
}
public void noDeadlock() throws InterruptedException {
DeadlockDetectionTimerTask task = new DeadlockDetectionTimerTask();
Monitor monitor = task.emitMonitors().iterator().next();
assertNull(monitor);
}
public void createDeadlock() throws Exception {
ExecutorService executor = Executors.newFixedThreadPool(2);
Object obj1 = new Object();
Object obj2 = new Object();
Deadlocker deadlock1 = new Deadlocker(obj1, obj2);
Deadlocker deadlock2 = new Deadlocker(obj2, obj1);
executor.execute(deadlock1);
executor.execute(deadlock2);
Thread.sleep(12);
}
public void deadlock() throws Exception {
DeadlockDetectionTimerTask task = new DeadlockDetectionTimerTask();
Monitor monitor = task.emitMonitors().iterator().next();
assertNotNull(monitor);
assertEquals("JvmStats", monitor.get(Monitor.NAME));
assertEquals("Thread.Deadlock", monitor.get("type"));
assertEquals(1, monitor.getAsInt("count"));
}
public void deadlockMonitoringOff() throws Exception {
DeadlockDetectionTimerTask task = new DeadlockDetectionTimerTask();
ManagementFactory.getThreadMXBean().setThreadContentionMonitoringEnabled(false);
Monitor monitor = task.emitMonitors().iterator().next();
assertNull(monitor);
}
class Deadlocker implements Runnable {
private Object a;
private Object b;
public Deadlocker(Object a, Object b) {
super();
this.a = a;
this.b = b;
}
public void run() {
synchronized (a) {
try {
Thread.sleep(1);
} catch (Exception doNothing) {}
synchronized (b) {
try {
Thread.sleep(1);
} catch (Exception doNothing) {}
}
}
}
}
}