// Path: src/main/java/com/google/code/tempusfugit/temporal/Condition.java
// public interface Condition {
//     boolean isSatisfied();
// }
// 
// Path: src/test/java/com/google/code/tempusfugit/concurrency/DeadlockMatcher.java
// public static Matcher<Deadlocks> detected() {
//     return new DeadlockMatcher();
// }
// 
// Path: src/main/java/com/google/code/tempusfugit/temporal/Duration.java
// public static Duration millis(long millis) {
//     validate(millis, TimeUnit.MILLISECONDS);
//     return new Duration(millis, TimeUnit.MILLISECONDS);
// }
// 
// Path: src/main/java/com/google/code/tempusfugit/temporal/Timeout.java
// public static Timeout timeout(Duration duration) {
//     return new Timeout(duration);
// }
// 
// Path: src/main/java/com/google/code/tempusfugit/temporal/WaitFor.java
// public static void waitOrTimeout(Condition condition, Timeout timeout) throws InterruptedException, TimeoutException {
//     waitOrTimeout(condition, timeout, new ThreadSleep(SLEEP_PERIOD));
// }


import static org.hamcrest.Matchers.not;
import com.google.code.tempusfugit.concurrency.kidnapping.*;
import com.google.code.tempusfugit.temporal.Condition;
import org.junit.Test;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.ReentrantLock;
import static com.google.code.tempusfugit.concurrency.DeadlockMatcher.detected;
import static com.google.code.tempusfugit.temporal.Duration.millis;
import static com.google.code.tempusfugit.temporal.Timeout.timeout;
import static com.google.code.tempusfugit.temporal.WaitFor.waitOrTimeout;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
        negotiator.interruptAndWaitToFinish();
    }

    @Test
    public void detectsIntrinsicMonitorBasedDeadlock() throws InterruptedException, TimeoutException {
        Cash cash = new SynchronizedLock(latch);
        Cat nibbles = new SynchronizedLock(latch);

        new Kidnapper(cash, nibbles).start();
        new Negotiator(cash, nibbles).start();

        waitOrTimeout(forDeadlockDetected(), timeout(millis(250)));
        verify(deadlocks, Object.class);
    }

    private Condition forDeadlockDetected() {
        return forDeadlockDetected(0);
    }

    private Condition forDeadlockDetected(final int stackDepth) {
        return () -> {
            DeadlockDetector.printDeadlocks(deadlocks, stackDepth);
            return deadlocks.detected();
        };
    }

    private void verify(Deadlocks deadlocks, Class<?> lockClass) {
        assertThat(deadlocks.toString(), containsString("Deadlock detected"));
        assertThat(deadlocks.toString(), containsString("Negotiator-Thread"));
        assertThat(deadlocks.toString(), containsString("waiting to lock Monitor of " + lockClass.getName()));
// Path: src/main/java/com/google/code/tempusfugit/temporal/Condition.java
// public interface Condition {
//     boolean isSatisfied();
// }
// 
// Path: src/test/java/com/google/code/tempusfugit/concurrency/DeadlockMatcher.java
// public static Matcher<Deadlocks> detected() {
//     return new DeadlockMatcher();
// }
// 
// Path: src/main/java/com/google/code/tempusfugit/temporal/Duration.java
// public static Duration millis(long millis) {
//     validate(millis, TimeUnit.MILLISECONDS);
//     return new Duration(millis, TimeUnit.MILLISECONDS);
// }
// 
// Path: src/main/java/com/google/code/tempusfugit/temporal/Timeout.java
// public static Timeout timeout(Duration duration) {
//     return new Timeout(duration);
// }
// 
// Path: src/main/java/com/google/code/tempusfugit/temporal/WaitFor.java
// public static void waitOrTimeout(Condition condition, Timeout timeout) throws InterruptedException, TimeoutException {
//     waitOrTimeout(condition, timeout, new ThreadSleep(SLEEP_PERIOD));
// }


// Path: src/test/java/com/google/code/tempusfugit/concurrency/DeadlockDetectorTest.java
import static org.hamcrest.Matchers.not;
import com.google.code.tempusfugit.concurrency.kidnapping.*;
import com.google.code.tempusfugit.temporal.Condition;
import org.junit.Test;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.ReentrantLock;
import static com.google.code.tempusfugit.concurrency.DeadlockMatcher.detected;
import static com.google.code.tempusfugit.temporal.Duration.millis;
import static com.google.code.tempusfugit.temporal.Timeout.timeout;
import static com.google.code.tempusfugit.temporal.WaitFor.waitOrTimeout;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;

        negotiator.interruptAndWaitToFinish();
    }

    @Test
    public void detectsIntrinsicMonitorBasedDeadlock() throws InterruptedException, TimeoutException {
        Cash cash = new SynchronizedLock(latch);
        Cat nibbles = new SynchronizedLock(latch);

        new Kidnapper(cash, nibbles).start();
        new Negotiator(cash, nibbles).start();

        waitOrTimeout(forDeadlockDetected(), timeout(millis(250)));
        verify(deadlocks, Object.class);
    }

    private Condition forDeadlockDetected() {
        return forDeadlockDetected(0);
    }

    private Condition forDeadlockDetected(final int stackDepth) {
        return () -> {
            DeadlockDetector.printDeadlocks(deadlocks, stackDepth);
            return deadlocks.detected();
        };
    }

    private void verify(Deadlocks deadlocks, Class<?> lockClass) {
        assertThat(deadlocks.toString(), containsString("Deadlock detected"));
        assertThat(deadlocks.toString(), containsString("Negotiator-Thread"));
        assertThat(deadlocks.toString(), containsString("waiting to lock Monitor of " + lockClass.getName()));
        assertThat(deadlocks.toString(), containsString("which is held by \"Kidnapper-Thread"));