/** Checks that condition c has exactly the given waiter threads. */
 void assertHasWaitersLocked(Mutex sync, ConditionObject c, Thread... threads) {
   assertEquals(threads.length > 0, sync.hasWaiters(c));
   assertEquals(threads.length, sync.getWaitQueueLength(c));
   assertEquals(threads.length == 0, sync.getWaitingThreads(c).isEmpty());
   assertEquals(threads.length, sync.getWaitingThreads(c).size());
   assertEquals(
       new HashSet<Thread>(sync.getWaitingThreads(c)),
       new HashSet<Thread>(Arrays.asList(threads)));
 }
 /** getWaitingThreads throws NPE if null */
 public void testGetWaitingThreadsNPE() {
   final Mutex sync = new Mutex();
   try {
     sync.getWaitingThreads(null);
     shouldThrow();
   } catch (NullPointerException success) {
   }
 }
    public void thread2() throws InterruptedException {
      waitForTick(2);
      sync.acquire(1);
      assertFalse(sync.getWaitingThreads(c).isEmpty());
      c.await();

      assertTick(3);
      sync.release(1);
    }
    public void thread3() {
      sync.acquire(1);
      assertTrue(sync.getWaitingThreads(c).isEmpty());
      sync.release(1);

      waitForTick(3);
      sync.acquire(1);
      assertTrue(sync.hasWaiters(c));
      assertTrue(sync.getWaitingThreads(c).contains(getThread(1)));
      assertTrue(sync.getWaitingThreads(c).contains(getThread(2)));
      c.signalAll();
      sync.release(1);

      waitForTick(4);
      sync.acquire(1);
      assertFalse(sync.hasWaiters(c));
      assertTrue(sync.getWaitingThreads(c).isEmpty());
      sync.release(1);
    }
 /** getWaitingThreads throws IllegalMonitorStateException if not synced */
 public void testGetWaitingThreadsIMSE() {
   final Mutex sync = new Mutex();
   final ConditionObject c = sync.newCondition();
   try {
     sync.getWaitingThreads(c);
     shouldThrow();
   } catch (IllegalMonitorStateException success) {
   }
   assertHasWaitersUnlocked(sync, c, NO_THREADS);
 }
  /** getWaitingThreads returns only and all waiting threads */
  public void testGetWaitingThreads() {
    final Mutex sync = new Mutex();
    final ConditionObject c = sync.newCondition();
    final BooleanLatch acquired1 = new BooleanLatch();
    final BooleanLatch acquired2 = new BooleanLatch();
    final Thread t1 =
        new Thread(
            new CheckedRunnable() {
              public void realRun() throws InterruptedException {
                sync.acquire();
                assertHasWaitersLocked(sync, c, NO_THREADS);
                assertTrue(sync.getWaitingThreads(c).isEmpty());
                assertTrue(acquired1.releaseShared(0));
                c.await();
                sync.release();
              }
            });

    final Thread t2 =
        new Thread(
            new CheckedRunnable() {
              public void realRun() throws InterruptedException {
                sync.acquire();
                assertHasWaitersLocked(sync, c, t1);
                assertTrue(sync.getWaitingThreads(c).contains(t1));
                assertFalse(sync.getWaitingThreads(c).isEmpty());
                assertEquals(1, sync.getWaitingThreads(c).size());
                assertTrue(acquired2.releaseShared(0));
                c.await();
                sync.release();
              }
            });

    sync.acquire();
    assertHasWaitersLocked(sync, c, NO_THREADS);
    assertFalse(sync.getWaitingThreads(c).contains(t1));
    assertFalse(sync.getWaitingThreads(c).contains(t2));
    assertTrue(sync.getWaitingThreads(c).isEmpty());
    assertEquals(0, sync.getWaitingThreads(c).size());
    sync.release();

    t1.start();
    acquired1.acquireShared(0);
    sync.acquire();
    assertHasWaitersLocked(sync, c, t1);
    assertTrue(sync.getWaitingThreads(c).contains(t1));
    assertFalse(sync.getWaitingThreads(c).contains(t2));
    assertFalse(sync.getWaitingThreads(c).isEmpty());
    assertEquals(1, sync.getWaitingThreads(c).size());
    sync.release();

    t2.start();
    acquired2.acquireShared(0);
    sync.acquire();
    assertHasWaitersLocked(sync, c, t1, t2);
    assertHasExclusiveQueuedThreads(sync, NO_THREADS);
    assertTrue(sync.getWaitingThreads(c).contains(t1));
    assertTrue(sync.getWaitingThreads(c).contains(t2));
    assertFalse(sync.getWaitingThreads(c).isEmpty());
    assertEquals(2, sync.getWaitingThreads(c).size());
    c.signalAll();
    assertHasWaitersLocked(sync, c, NO_THREADS);
    assertHasExclusiveQueuedThreads(sync, t1, t2);
    assertFalse(sync.getWaitingThreads(c).contains(t1));
    assertFalse(sync.getWaitingThreads(c).contains(t2));
    assertTrue(sync.getWaitingThreads(c).isEmpty());
    assertEquals(0, sync.getWaitingThreads(c).size());
    sync.release();

    awaitTermination(t1);
    awaitTermination(t2);
    assertHasWaitersUnlocked(sync, c, NO_THREADS);
  }