/*
 * Written by Doug Lea with assistance from members of JCP JSR-166
 * Expert Group and released to the public domain, as explained at
 * http://creativecommons.org/publicdomain/zero/1.0/
 * Other contributors include Andrew Wright, Jeffrey Hayes,
 * Pat Fisher, Mike Judd.
 */

package jsr166;

import static java.util.concurrent.TimeUnit.MILLISECONDS;

import java.util.Collection;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Semaphore;

import junit.framework.AssertionFailedError;
import junit.framework.Test;
import junit.framework.TestSuite;

public class SemaphoreTest extends JSR166TestCase {
    // android-note: Removed because the CTS runner does a bad job of
    // retrying tests that have suite() declarations.
    //
    // public static void main(String[] args) {
    //     main(suite(), args);
    // }
    // public static Test suite() {
    //     return new TestSuite(SemaphoreTest.class);
    // }

    /**
     * Subclass to expose protected methods
     */
    static class PublicSemaphore extends Semaphore {
        PublicSemaphore(int permits) { super(permits); }
        PublicSemaphore(int permits, boolean fair) { super(permits, fair); }
        public Collection<Thread> getQueuedThreads() {
            return super.getQueuedThreads();
        }
        public boolean hasQueuedThread(Thread t) {
            return super.getQueuedThreads().contains(t);
        }
        public void reducePermits(int reduction) {
            super.reducePermits(reduction);
        }
    }

    /**
     * A runnable calling acquire
     */
    class InterruptibleLockRunnable extends CheckedRunnable {
        final Semaphore lock;
        InterruptibleLockRunnable(Semaphore s) { lock = s; }
        public void realRun() {
            try {
                lock.acquire();
            }
            catch (InterruptedException ignored) {}
        }
    }

    /**
     * A runnable calling acquire that expects to be interrupted
     */
    class InterruptedLockRunnable extends CheckedInterruptedRunnable {
        final Semaphore lock;
        InterruptedLockRunnable(Semaphore s) { lock = s; }
        public void realRun() throws InterruptedException {
            lock.acquire();
        }
    }

    /**
     * Spin-waits until s.hasQueuedThread(t) becomes true.
     */
    void waitForQueuedThread(PublicSemaphore s, Thread t) {
        long startTime = System.nanoTime();
        while (!s.hasQueuedThread(t)) {
            if (millisElapsedSince(startTime) > LONG_DELAY_MS)
                throw new AssertionFailedError("timed out");
            Thread.yield();
        }
        assertTrue(s.hasQueuedThreads());
        assertTrue(t.isAlive());
    }

    /**
     * Spin-waits until s.hasQueuedThreads() becomes true.
     */
    void waitForQueuedThreads(Semaphore s) {
        long startTime = System.nanoTime();
        while (!s.hasQueuedThreads()) {
            if (millisElapsedSince(startTime) > LONG_DELAY_MS)
                throw new AssertionFailedError("timed out");
            Thread.yield();
        }
    }

    enum AcquireMethod {
        acquire() {
            void acquire(Semaphore s) throws InterruptedException {
                s.acquire();
            }
        },
        acquireN() {
            void acquire(Semaphore s, int permits) throws InterruptedException {
                s.acquire(permits);
            }
        },
        acquireUninterruptibly() {
            void acquire(Semaphore s) {
                s.acquireUninterruptibly();
            }
        },
        acquireUninterruptiblyN() {
            void acquire(Semaphore s, int permits) {
                s.acquireUninterruptibly(permits);
            }
        },
        tryAcquire() {
            void acquire(Semaphore s) {
                assertTrue(s.tryAcquire());
            }
        },
        tryAcquireN() {
            void acquire(Semaphore s, int permits) {
                assertTrue(s.tryAcquire(permits));
            }
        },
        tryAcquireTimed() {
            void acquire(Semaphore s) throws InterruptedException {
                assertTrue(s.tryAcquire(2 * LONG_DELAY_MS, MILLISECONDS));
            }
        },
        tryAcquireTimedN {
            void acquire(Semaphore s, int permits) throws InterruptedException {
                assertTrue(s.tryAcquire(permits, 2 * LONG_DELAY_MS, MILLISECONDS));
            }
        };

        // Intentionally meta-circular

        /** Acquires 1 permit. */
        void acquire(Semaphore s) throws InterruptedException {
            acquire(s, 1);
        }
        /** Acquires the given number of permits. */
        void acquire(Semaphore s, int permits) throws InterruptedException {
            for (int i = 0; i < permits; i++)
                acquire(s);
        }
    }

    /**
     * Zero, negative, and positive initial values are allowed in constructor
     */
    public void testConstructor()      { testConstructor(false); }
    public void testConstructor_fair() { testConstructor(true); }
    public void testConstructor(boolean fair) {
        for (int permits : new int[] { -42, -1, 0, 1, 42 }) {
            Semaphore s = new Semaphore(permits, fair);
            assertEquals(permits, s.availablePermits());
            assertEquals(fair, s.isFair());
        }
    }

    /**
     * Constructor without fairness argument behaves as nonfair
     */
    public void testConstructorDefaultsToNonFair() {
        for (int permits : new int[] { -42, -1, 0, 1, 42 }) {
            Semaphore s = new Semaphore(permits);
            assertEquals(permits, s.availablePermits());
            assertFalse(s.isFair());
        }
    }

    /**
     * tryAcquire succeeds when sufficient permits, else fails
     */
    public void testTryAcquireInSameThread()      { testTryAcquireInSameThread(false); }
    public void testTryAcquireInSameThread_fair() { testTryAcquireInSameThread(true); }
    public void testTryAcquireInSameThread(boolean fair) {
        Semaphore s = new Semaphore(2, fair);
        assertEquals(2, s.availablePermits());
        assertTrue(s.tryAcquire());
        assertTrue(s.tryAcquire());
        assertEquals(0, s.availablePermits());
        assertFalse(s.tryAcquire());
        assertFalse(s.tryAcquire());
        assertEquals(0, s.availablePermits());
    }

    /**
     * timed tryAcquire times out
     */
    public void testTryAcquire_timeout()      { testTryAcquire_timeout(false); }
    public void testTryAcquire_timeout_fair() { testTryAcquire_timeout(true); }
    public void testTryAcquire_timeout(boolean fair) {
        Semaphore s = new Semaphore(0, fair);
        long startTime = System.nanoTime();
        try { assertFalse(s.tryAcquire(timeoutMillis(), MILLISECONDS)); }
        catch (InterruptedException e) { threadUnexpectedException(e); }
        assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
    }

    /**
     * timed tryAcquire(N) times out
     */
    public void testTryAcquireN_timeout()      { testTryAcquireN_timeout(false); }
    public void testTryAcquireN_timeout_fair() { testTryAcquireN_timeout(true); }
    public void testTryAcquireN_timeout(boolean fair) {
        Semaphore s = new Semaphore(2, fair);
        long startTime = System.nanoTime();
        try { assertFalse(s.tryAcquire(3, timeoutMillis(), MILLISECONDS)); }
        catch (InterruptedException e) { threadUnexpectedException(e); }
        assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
    }

    /**
     * acquire(), acquire(N), timed tryAcquired, timed tryAcquire(N)
     * are interruptible
     */
    public void testInterruptible_acquire()               { testInterruptible(false, AcquireMethod.acquire); }
    public void testInterruptible_acquire_fair()          { testInterruptible(true,  AcquireMethod.acquire); }
    public void testInterruptible_acquireN()              { testInterruptible(false, AcquireMethod.acquireN); }
    public void testInterruptible_acquireN_fair()         { testInterruptible(true,  AcquireMethod.acquireN); }
    public void testInterruptible_tryAcquireTimed()       { testInterruptible(false, AcquireMethod.tryAcquireTimed); }
    public void testInterruptible_tryAcquireTimed_fair()  { testInterruptible(true,  AcquireMethod.tryAcquireTimed); }
    public void testInterruptible_tryAcquireTimedN()      { testInterruptible(false, AcquireMethod.tryAcquireTimedN); }
    public void testInterruptible_tryAcquireTimedN_fair() { testInterruptible(true,  AcquireMethod.tryAcquireTimedN); }
    public void testInterruptible(boolean fair, final AcquireMethod acquirer) {
        final PublicSemaphore s = new PublicSemaphore(0, fair);
        final Semaphore pleaseInterrupt = new Semaphore(0, fair);
        Thread t = newStartedThread(new CheckedRunnable() {
            public void realRun() {
                // Interrupt before acquire
                Thread.currentThread().interrupt();
                try {
                    acquirer.acquire(s);
                    shouldThrow();
                } catch (InterruptedException success) {}

                // Interrupt during acquire
                try {
                    acquirer.acquire(s);
                    shouldThrow();
                } catch (InterruptedException success) {}

                // Interrupt before acquire(N)
                Thread.currentThread().interrupt();
                try {
                    acquirer.acquire(s, 3);
                    shouldThrow();
                } catch (InterruptedException success) {}

                pleaseInterrupt.release();

                // Interrupt during acquire(N)
                try {
                    acquirer.acquire(s, 3);
                    shouldThrow();
                } catch (InterruptedException success) {}
            }});

        waitForQueuedThread(s, t);
        t.interrupt();
        await(pleaseInterrupt);
        waitForQueuedThread(s, t);
        t.interrupt();
        awaitTermination(t);
    }

    /**
     * acquireUninterruptibly(), acquireUninterruptibly(N) are
     * uninterruptible
     */
    public void testUninterruptible_acquireUninterruptibly()       { testUninterruptible(false, AcquireMethod.acquireUninterruptibly); }
    public void testUninterruptible_acquireUninterruptibly_fair()  { testUninterruptible(true,  AcquireMethod.acquireUninterruptibly); }
    public void testUninterruptible_acquireUninterruptiblyN()      { testUninterruptible(false, AcquireMethod.acquireUninterruptiblyN); }
    public void testUninterruptible_acquireUninterruptiblyN_fair() { testUninterruptible(true,  AcquireMethod.acquireUninterruptiblyN); }
    public void testUninterruptible(boolean fair, final AcquireMethod acquirer) {
        final PublicSemaphore s = new PublicSemaphore(0, fair);
        final Semaphore pleaseInterrupt = new Semaphore(-1, fair);

        Thread t1 = newStartedThread(new CheckedRunnable() {
            public void realRun() throws InterruptedException {
                // Interrupt before acquire
                pleaseInterrupt.release();
                Thread.currentThread().interrupt();
                acquirer.acquire(s);
                assertTrue(Thread.interrupted());
            }});

        Thread t2 = newStartedThread(new CheckedRunnable() {
            public void realRun() throws InterruptedException {
                // Interrupt during acquire
                pleaseInterrupt.release();
                acquirer.acquire(s);
                assertTrue(Thread.interrupted());
            }});

        await(pleaseInterrupt);
        waitForQueuedThread(s, t1);
        waitForQueuedThread(s, t2);
        t2.interrupt();

        assertThreadStaysAlive(t1);
        assertTrue(t2.isAlive());

        s.release(2);

        awaitTermination(t1);
        awaitTermination(t2);
    }

    /**
     * hasQueuedThreads reports whether there are waiting threads
     */
    public void testHasQueuedThreads()      { testHasQueuedThreads(false); }
    public void testHasQueuedThreads_fair() { testHasQueuedThreads(true); }
    public void testHasQueuedThreads(boolean fair) {
        final PublicSemaphore lock = new PublicSemaphore(1, fair);
        assertFalse(lock.hasQueuedThreads());
        lock.acquireUninterruptibly();
        Thread t1 = newStartedThread(new InterruptedLockRunnable(lock));
        waitForQueuedThread(lock, t1);
        assertTrue(lock.hasQueuedThreads());
        Thread t2 = newStartedThread(new InterruptibleLockRunnable(lock));
        waitForQueuedThread(lock, t2);
        assertTrue(lock.hasQueuedThreads());
        t1.interrupt();
        awaitTermination(t1);
        assertTrue(lock.hasQueuedThreads());
        lock.release();
        awaitTermination(t2);
        assertFalse(lock.hasQueuedThreads());
    }

    /**
     * getQueueLength reports number of waiting threads
     */
    public void testGetQueueLength()      { testGetQueueLength(false); }
    public void testGetQueueLength_fair() { testGetQueueLength(true); }
    public void testGetQueueLength(boolean fair) {
        final PublicSemaphore lock = new PublicSemaphore(1, fair);
        assertEquals(0, lock.getQueueLength());
        lock.acquireUninterruptibly();
        Thread t1 = newStartedThread(new InterruptedLockRunnable(lock));
        waitForQueuedThread(lock, t1);
        assertEquals(1, lock.getQueueLength());
        Thread t2 = newStartedThread(new InterruptibleLockRunnable(lock));
        waitForQueuedThread(lock, t2);
        assertEquals(2, lock.getQueueLength());
        t1.interrupt();
        awaitTermination(t1);
        assertEquals(1, lock.getQueueLength());
        lock.release();
        awaitTermination(t2);
        assertEquals(0, lock.getQueueLength());
    }

    /**
     * getQueuedThreads includes waiting threads
     */
    public void testGetQueuedThreads()      { testGetQueuedThreads(false); }
    public void testGetQueuedThreads_fair() { testGetQueuedThreads(true); }
    public void testGetQueuedThreads(boolean fair) {
        final PublicSemaphore lock = new PublicSemaphore(1, fair);
        assertTrue(lock.getQueuedThreads().isEmpty());
        lock.acquireUninterruptibly();
        assertTrue(lock.getQueuedThreads().isEmpty());
        Thread t1 = newStartedThread(new InterruptedLockRunnable(lock));
        waitForQueuedThread(lock, t1);
        assertTrue(lock.getQueuedThreads().contains(t1));
        Thread t2 = newStartedThread(new InterruptibleLockRunnable(lock));
        waitForQueuedThread(lock, t2);
        assertTrue(lock.getQueuedThreads().contains(t1));
        assertTrue(lock.getQueuedThreads().contains(t2));
        t1.interrupt();
        awaitTermination(t1);
        assertFalse(lock.getQueuedThreads().contains(t1));
        assertTrue(lock.getQueuedThreads().contains(t2));
        lock.release();
        awaitTermination(t2);
        assertTrue(lock.getQueuedThreads().isEmpty());
    }

    /**
     * drainPermits reports and removes given number of permits
     */
    public void testDrainPermits()      { testDrainPermits(false); }
    public void testDrainPermits_fair() { testDrainPermits(true); }
    public void testDrainPermits(boolean fair) {
        Semaphore s = new Semaphore(0, fair);
        assertEquals(0, s.availablePermits());
        assertEquals(0, s.drainPermits());
        s.release(10);
        assertEquals(10, s.availablePermits());
        assertEquals(10, s.drainPermits());
        assertEquals(0, s.availablePermits());
        assertEquals(0, s.drainPermits());
    }

    /**
     * release(-N) throws IllegalArgumentException
     */
    public void testReleaseIAE()      { testReleaseIAE(false); }
    public void testReleaseIAE_fair() { testReleaseIAE(true); }
    public void testReleaseIAE(boolean fair) {
        Semaphore s = new Semaphore(10, fair);
        try {
            s.release(-1);
            shouldThrow();
        } catch (IllegalArgumentException success) {}
    }

    /**
     * reducePermits(-N) throws IllegalArgumentException
     */
    public void testReducePermitsIAE()      { testReducePermitsIAE(false); }
    public void testReducePermitsIAE_fair() { testReducePermitsIAE(true); }
    public void testReducePermitsIAE(boolean fair) {
        PublicSemaphore s = new PublicSemaphore(10, fair);
        try {
            s.reducePermits(-1);
            shouldThrow();
        } catch (IllegalArgumentException success) {}
    }

    /**
     * reducePermits reduces number of permits
     */
    public void testReducePermits()      { testReducePermits(false); }
    public void testReducePermits_fair() { testReducePermits(true); }
    public void testReducePermits(boolean fair) {
        PublicSemaphore s = new PublicSemaphore(10, fair);
        assertEquals(10, s.availablePermits());
        s.reducePermits(0);
        assertEquals(10, s.availablePermits());
        s.reducePermits(1);
        assertEquals(9, s.availablePermits());
        s.reducePermits(10);
        assertEquals(-1, s.availablePermits());
        s.reducePermits(10);
        assertEquals(-11, s.availablePermits());
        s.reducePermits(0);
        assertEquals(-11, s.availablePermits());
    }

    /**
     * a reserialized semaphore has same number of permits and
     * fairness, but no queued threads
     */
    public void testSerialization()      { testSerialization(false); }
    public void testSerialization_fair() { testSerialization(true); }
    public void testSerialization(boolean fair) {
        try {
            Semaphore s = new Semaphore(3, fair);
            s.acquire();
            s.acquire();
            s.release();

            Semaphore clone = serialClone(s);
            assertEquals(fair, s.isFair());
            assertEquals(fair, clone.isFair());
            assertEquals(2, s.availablePermits());
            assertEquals(2, clone.availablePermits());
            clone.acquire();
            clone.acquire();
            clone.release();
            assertEquals(2, s.availablePermits());
            assertEquals(1, clone.availablePermits());
            assertFalse(s.hasQueuedThreads());
            assertFalse(clone.hasQueuedThreads());
        } catch (InterruptedException e) { threadUnexpectedException(e); }

        {
            PublicSemaphore s = new PublicSemaphore(0, fair);
            Thread t = newStartedThread(new InterruptibleLockRunnable(s));
            // waitForQueuedThreads(s); // suffers from "flicker", so ...
            waitForQueuedThread(s, t);  // ... we use this instead
            PublicSemaphore clone = serialClone(s);
            assertEquals(fair, s.isFair());
            assertEquals(fair, clone.isFair());
            assertEquals(0, s.availablePermits());
            assertEquals(0, clone.availablePermits());
            assertTrue(s.hasQueuedThreads());
            assertFalse(clone.hasQueuedThreads());
            s.release();
            awaitTermination(t);
            assertFalse(s.hasQueuedThreads());
            assertFalse(clone.hasQueuedThreads());
        }
    }

    /**
     * tryAcquire(n) succeeds when sufficient permits, else fails
     */
    public void testTryAcquireNInSameThread()      { testTryAcquireNInSameThread(false); }
    public void testTryAcquireNInSameThread_fair() { testTryAcquireNInSameThread(true); }
    public void testTryAcquireNInSameThread(boolean fair) {
        Semaphore s = new Semaphore(2, fair);
        assertEquals(2, s.availablePermits());
        assertFalse(s.tryAcquire(3));
        assertEquals(2, s.availablePermits());
        assertTrue(s.tryAcquire(2));
        assertEquals(0, s.availablePermits());
        assertFalse(s.tryAcquire(1));
        assertFalse(s.tryAcquire(2));
        assertEquals(0, s.availablePermits());
    }

    /**
     * acquire succeeds if permits available
     */
    public void testReleaseAcquireSameThread_acquire()       { testReleaseAcquireSameThread(false, AcquireMethod.acquire); }
    public void testReleaseAcquireSameThread_acquire_fair()  { testReleaseAcquireSameThread(true, AcquireMethod.acquire); }
    public void testReleaseAcquireSameThread_acquireN()      { testReleaseAcquireSameThread(false, AcquireMethod.acquireN); }
    public void testReleaseAcquireSameThread_acquireN_fair() { testReleaseAcquireSameThread(true, AcquireMethod.acquireN); }
    public void testReleaseAcquireSameThread_acquireUninterruptibly()       { testReleaseAcquireSameThread(false, AcquireMethod.acquireUninterruptibly); }
    public void testReleaseAcquireSameThread_acquireUninterruptibly_fair()  { testReleaseAcquireSameThread(true, AcquireMethod.acquireUninterruptibly); }
    public void testReleaseAcquireSameThread_acquireUninterruptiblyN()      { testReleaseAcquireSameThread(false, AcquireMethod.acquireUninterruptibly); }
    public void testReleaseAcquireSameThread_acquireUninterruptiblyN_fair() { testReleaseAcquireSameThread(true, AcquireMethod.acquireUninterruptibly); }
    public void testReleaseAcquireSameThread_tryAcquire()       { testReleaseAcquireSameThread(false, AcquireMethod.tryAcquire); }
    public void testReleaseAcquireSameThread_tryAcquire_fair()  { testReleaseAcquireSameThread(true, AcquireMethod.tryAcquire); }
    public void testReleaseAcquireSameThread_tryAcquireN()      { testReleaseAcquireSameThread(false, AcquireMethod.tryAcquireN); }
    public void testReleaseAcquireSameThread_tryAcquireN_fair() { testReleaseAcquireSameThread(true, AcquireMethod.tryAcquireN); }
    public void testReleaseAcquireSameThread_tryAcquireTimed()       { testReleaseAcquireSameThread(false, AcquireMethod.tryAcquireTimed); }
    public void testReleaseAcquireSameThread_tryAcquireTimed_fair()  { testReleaseAcquireSameThread(true, AcquireMethod.tryAcquireTimed); }
    public void testReleaseAcquireSameThread_tryAcquireTimedN()      { testReleaseAcquireSameThread(false, AcquireMethod.tryAcquireTimedN); }
    public void testReleaseAcquireSameThread_tryAcquireTimedN_fair() { testReleaseAcquireSameThread(true, AcquireMethod.tryAcquireTimedN); }
    public void testReleaseAcquireSameThread(boolean fair,
                                             final AcquireMethod acquirer) {
        Semaphore s = new Semaphore(1, fair);
        for (int i = 1; i < 6; i++) {
            s.release(i);
            assertEquals(1 + i, s.availablePermits());
            try {
                acquirer.acquire(s, i);
            } catch (InterruptedException e) { threadUnexpectedException(e); }
            assertEquals(1, s.availablePermits());
        }
    }

    /**
     * release in one thread enables acquire in another thread
     */
    public void testReleaseAcquireDifferentThreads_acquire()       { testReleaseAcquireDifferentThreads(false, AcquireMethod.acquire); }
    public void testReleaseAcquireDifferentThreads_acquire_fair()  { testReleaseAcquireDifferentThreads(true, AcquireMethod.acquire); }
    public void testReleaseAcquireDifferentThreads_acquireN()      { testReleaseAcquireDifferentThreads(false, AcquireMethod.acquireN); }
    public void testReleaseAcquireDifferentThreads_acquireN_fair() { testReleaseAcquireDifferentThreads(true, AcquireMethod.acquireN); }
    public void testReleaseAcquireDifferentThreads_acquireUninterruptibly()       { testReleaseAcquireDifferentThreads(false, AcquireMethod.acquireUninterruptibly); }
    public void testReleaseAcquireDifferentThreads_acquireUninterruptibly_fair()  { testReleaseAcquireDifferentThreads(true, AcquireMethod.acquireUninterruptibly); }
    public void testReleaseAcquireDifferentThreads_acquireUninterruptiblyN()      { testReleaseAcquireDifferentThreads(false, AcquireMethod.acquireUninterruptibly); }
    public void testReleaseAcquireDifferentThreads_acquireUninterruptiblyN_fair() { testReleaseAcquireDifferentThreads(true, AcquireMethod.acquireUninterruptibly); }
    public void testReleaseAcquireDifferentThreads_tryAcquireTimed()       { testReleaseAcquireDifferentThreads(false, AcquireMethod.tryAcquireTimed); }
    public void testReleaseAcquireDifferentThreads_tryAcquireTimed_fair()  { testReleaseAcquireDifferentThreads(true, AcquireMethod.tryAcquireTimed); }
    public void testReleaseAcquireDifferentThreads_tryAcquireTimedN()      { testReleaseAcquireDifferentThreads(false, AcquireMethod.tryAcquireTimedN); }
    public void testReleaseAcquireDifferentThreads_tryAcquireTimedN_fair() { testReleaseAcquireDifferentThreads(true, AcquireMethod.tryAcquireTimedN); }
    public void testReleaseAcquireDifferentThreads(boolean fair,
                                                   final AcquireMethod acquirer) {
        final Semaphore s = new Semaphore(0, fair);
        final int rounds = 4;
        long startTime = System.nanoTime();
        Thread t = newStartedThread(new CheckedRunnable() {
            public void realRun() throws InterruptedException {
                for (int i = 0; i < rounds; i++) {
                    assertFalse(s.hasQueuedThreads());
                    if (i % 2 == 0)
                        acquirer.acquire(s);
                    else
                        acquirer.acquire(s, 3);
                }}});

        for (int i = 0; i < rounds; i++) {
            while (! (s.availablePermits() == 0 && s.hasQueuedThreads()))
                Thread.yield();
            assertTrue(t.isAlive());
            if (i % 2 == 0)
                s.release();
            else
                s.release(3);
        }
        awaitTermination(t);
        assertEquals(0, s.availablePermits());
        assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
    }

    /**
     * fair locks are strictly FIFO
     */
    public void testFairLocksFifo() {
        final PublicSemaphore s = new PublicSemaphore(1, true);
        final CountDownLatch pleaseRelease = new CountDownLatch(1);
        Thread t1 = newStartedThread(new CheckedRunnable() {
            public void realRun() throws InterruptedException {
                // Will block; permits are available, but not three
                s.acquire(3);
            }});

        waitForQueuedThread(s, t1);

        Thread t2 = newStartedThread(new CheckedRunnable() {
            public void realRun() throws InterruptedException {
                // Will fail, even though 1 permit is available
                assertFalse(s.tryAcquire(0L, MILLISECONDS));
                assertFalse(s.tryAcquire(1, 0L, MILLISECONDS));

                // untimed tryAcquire will barge and succeed
                assertTrue(s.tryAcquire());
                s.release(2);
                assertTrue(s.tryAcquire(2));
                s.release();

                pleaseRelease.countDown();
                // Will queue up behind t1, even though 1 permit is available
                s.acquire();
            }});

        await(pleaseRelease);
        waitForQueuedThread(s, t2);
        s.release(2);
        awaitTermination(t1);
        assertTrue(t2.isAlive());
        s.release();
        awaitTermination(t2);
    }

    /**
     * toString indicates current number of permits
     */
    public void testToString()      { testToString(false); }
    public void testToString_fair() { testToString(true); }
    public void testToString(boolean fair) {
        PublicSemaphore s = new PublicSemaphore(0, fair);
        assertTrue(s.toString().contains("Permits = 0"));
        s.release();
        assertTrue(s.toString().contains("Permits = 1"));
        s.release(2);
        assertTrue(s.toString().contains("Permits = 3"));
        s.reducePermits(5);
        assertTrue(s.toString().contains("Permits = -2"));
    }

}
