--- jsr166/src/test/tck/SemaphoreTest.java 2003/09/20 18:20:08 1.4 +++ jsr166/src/test/tck/SemaphoreTest.java 2009/12/01 06:03:49 1.22 @@ -1,44 +1,93 @@ /* - * Written by members of JCP JSR-166 Expert Group and released to the - * public domain. Use, modify, and redistribute this code in any way - * without acknowledgement. Other contributors include Andrew Wright, - * Jeffrey Hayes, Pat Fischer, Mike Judd. + * 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/licenses/publicdomain + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. */ import junit.framework.*; import java.util.*; import java.util.concurrent.*; +import static java.util.concurrent.TimeUnit.MILLISECONDS; import java.io.*; public class SemaphoreTest extends JSR166TestCase { public static void main(String[] args) { - junit.textui.TestRunner.run (suite()); + junit.textui.TestRunner.run (suite()); } public static Test suite() { - return new TestSuite(SemaphoreTest.class); + return new TestSuite(SemaphoreTest.class); } /** - * + * Subclass to expose protected methods */ - public void testConstructor1() { - Semaphore s = new Semaphore(0); - assertEquals(0, s.availablePermits()); + static class PublicSemaphore extends Semaphore { + PublicSemaphore(int p, boolean f) { super(p, f); } + public Collection getQueuedThreads() { + return super.getQueuedThreads(); + } + public void reducePermits(int p) { + super.reducePermits(p); + } + } + + /** + * A runnable calling acquire + */ + class InterruptibleLockRunnable extends CheckedRunnable { + final Semaphore lock; + InterruptibleLockRunnable(Semaphore l) { lock = l; } + 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 l) { lock = l; } + public void realRun() throws InterruptedException { + lock.acquire(); + } } /** - * + * Zero, negative, and positive initial values are allowed in constructor + */ + public void testConstructor() { + for (int permits : new int[] { -1, 0, 1 }) { + for (boolean fair : new boolean[] { false, true }) { + Semaphore s = new Semaphore(permits, fair); + assertEquals(permits, s.availablePermits()); + assertEquals(fair, s.isFair()); + } + } + } + + /** + * Constructor without fairness argument behaves as nonfair */ public void testConstructor2() { - Semaphore s = new Semaphore(-1); - assertEquals(-1, s.availablePermits()); + for (int permits : new int[] { -1, 0, 1 }) { + Semaphore s = new Semaphore(permits); + assertEquals(permits, s.availablePermits()); + assertFalse(s.isFair()); + } } /** - * + * tryAcquire succeeds when sufficient permits, else fails */ public void testTryAcquireInSameThread() { - Semaphore s = new Semaphore(2); + Semaphore s = new Semaphore(2, false); assertEquals(2, s.availablePermits()); assertTrue(s.tryAcquire()); assertTrue(s.tryAcquire()); @@ -47,199 +96,671 @@ public class SemaphoreTest extends JSR16 } /** - * + * Acquire and release of semaphore succeed if initially available */ - public void testAcquireReleaseInSameThread() { - Semaphore s = new Semaphore(1); - try { - s.acquire(); - s.release(); - s.acquire(); - s.release(); - s.acquire(); - s.release(); - s.acquire(); - s.release(); - s.acquire(); - s.release(); - assertEquals(1, s.availablePermits()); - } catch( InterruptedException e){ - unexpectedException(); - } - } - - /** - * - */ - public void testAcquireUninterruptiblyReleaseInSameThread() { - Semaphore s = new Semaphore(1); - try { - s.acquireUninterruptibly(); - s.release(); - s.acquireUninterruptibly(); - s.release(); - s.acquireUninterruptibly(); - s.release(); - s.acquireUninterruptibly(); - s.release(); - s.acquireUninterruptibly(); - s.release(); - assertEquals(1, s.availablePermits()); - } finally { - } + public void testAcquireReleaseInSameThread() + throws InterruptedException { + Semaphore s = new Semaphore(1, false); + s.acquire(); + s.release(); + s.acquire(); + s.release(); + s.acquire(); + s.release(); + s.acquire(); + s.release(); + s.acquire(); + s.release(); + assertEquals(1, s.availablePermits()); + } + + /** + * Uninterruptible acquire and release of semaphore succeed if + * initially available + */ + public void testAcquireUninterruptiblyReleaseInSameThread() + throws InterruptedException { + Semaphore s = new Semaphore(1, false); + s.acquireUninterruptibly(); + s.release(); + s.acquireUninterruptibly(); + s.release(); + s.acquireUninterruptibly(); + s.release(); + s.acquireUninterruptibly(); + s.release(); + s.acquireUninterruptibly(); + s.release(); + assertEquals(1, s.availablePermits()); + } + + /** + * Timed Acquire and release of semaphore succeed if + * initially available + */ + public void testTimedAcquireReleaseInSameThread() + throws InterruptedException { + Semaphore s = new Semaphore(1, false); + assertTrue(s.tryAcquire(SHORT_DELAY_MS, MILLISECONDS)); + s.release(); + assertTrue(s.tryAcquire(SHORT_DELAY_MS, MILLISECONDS)); + s.release(); + assertTrue(s.tryAcquire(SHORT_DELAY_MS, MILLISECONDS)); + s.release(); + assertTrue(s.tryAcquire(SHORT_DELAY_MS, MILLISECONDS)); + s.release(); + assertTrue(s.tryAcquire(SHORT_DELAY_MS, MILLISECONDS)); + s.release(); + assertEquals(1, s.availablePermits()); + } + + /** + * A release in one thread enables an acquire in another thread + */ + public void testAcquireReleaseInDifferentThreads() + throws InterruptedException { + final Semaphore s = new Semaphore(0, false); + Thread t = new Thread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + s.acquire(); + s.release(); + s.release(); + s.acquire(); + }}); + + t.start(); + Thread.sleep(SHORT_DELAY_MS); + s.release(); + s.release(); + s.acquire(); + s.acquire(); + s.release(); + t.join(); + } + + /** + * A release in one thread enables an uninterruptible acquire in another thread + */ + public void testUninterruptibleAcquireReleaseInDifferentThreads() + throws InterruptedException { + final Semaphore s = new Semaphore(0, false); + Thread t = new Thread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + s.acquireUninterruptibly(); + s.release(); + s.release(); + s.acquireUninterruptibly(); + }}); + + t.start(); + Thread.sleep(SHORT_DELAY_MS); + s.release(); + s.release(); + s.acquireUninterruptibly(); + s.acquireUninterruptibly(); + s.release(); + t.join(); + } + + + /** + * A release in one thread enables a timed acquire in another thread + */ + public void testTimedAcquireReleaseInDifferentThreads() + throws InterruptedException { + final Semaphore s = new Semaphore(1, false); + Thread t = new Thread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + s.release(); + threadAssertTrue(s.tryAcquire(SHORT_DELAY_MS, MILLISECONDS)); + s.release(); + threadAssertTrue(s.tryAcquire(SHORT_DELAY_MS, MILLISECONDS)); + }}); + + t.start(); + assertTrue(s.tryAcquire(SHORT_DELAY_MS, MILLISECONDS)); + s.release(); + assertTrue(s.tryAcquire(SHORT_DELAY_MS, MILLISECONDS)); + s.release(); + s.release(); + t.join(); + } + + /** + * A waiting acquire blocks interruptibly + */ + public void testAcquire_InterruptedException() + throws InterruptedException { + final Semaphore s = new Semaphore(0, false); + Thread t = new Thread(new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + s.acquire(); + }}); + + t.start(); + Thread.sleep(SHORT_DELAY_MS); + t.interrupt(); + t.join(); + } + + /** + * A waiting timed acquire blocks interruptibly + */ + public void testTryAcquire_InterruptedException() + throws InterruptedException { + final Semaphore s = new Semaphore(0, false); + Thread t = new Thread(new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + s.tryAcquire(MEDIUM_DELAY_MS, MILLISECONDS); + }}); + + t.start(); + Thread.sleep(SHORT_DELAY_MS); + t.interrupt(); + t.join(); + } + + /** + * hasQueuedThreads reports whether there are waiting threads + */ + public void testHasQueuedThreads() throws InterruptedException { + final Semaphore lock = new Semaphore(1, false); + Thread t1 = new Thread(new InterruptedLockRunnable(lock)); + Thread t2 = new Thread(new InterruptibleLockRunnable(lock)); + assertFalse(lock.hasQueuedThreads()); + lock.acquireUninterruptibly(); + t1.start(); + Thread.sleep(SHORT_DELAY_MS); + assertTrue(lock.hasQueuedThreads()); + t2.start(); + Thread.sleep(SHORT_DELAY_MS); + assertTrue(lock.hasQueuedThreads()); + t1.interrupt(); + Thread.sleep(SHORT_DELAY_MS); + assertTrue(lock.hasQueuedThreads()); + lock.release(); + Thread.sleep(SHORT_DELAY_MS); + assertFalse(lock.hasQueuedThreads()); + t1.join(); + t2.join(); + } + + /** + * getQueueLength reports number of waiting threads + */ + public void testGetQueueLength() throws InterruptedException { + final Semaphore lock = new Semaphore(1, false); + Thread t1 = new Thread(new InterruptedLockRunnable(lock)); + Thread t2 = new Thread(new InterruptibleLockRunnable(lock)); + assertEquals(0, lock.getQueueLength()); + lock.acquireUninterruptibly(); + t1.start(); + Thread.sleep(SHORT_DELAY_MS); + assertEquals(1, lock.getQueueLength()); + t2.start(); + Thread.sleep(SHORT_DELAY_MS); + assertEquals(2, lock.getQueueLength()); + t1.interrupt(); + Thread.sleep(SHORT_DELAY_MS); + assertEquals(1, lock.getQueueLength()); + lock.release(); + Thread.sleep(SHORT_DELAY_MS); + assertEquals(0, lock.getQueueLength()); + t1.join(); + t2.join(); + } + + /** + * getQueuedThreads includes waiting threads + */ + public void testGetQueuedThreads() throws InterruptedException { + final PublicSemaphore lock = new PublicSemaphore(1, false); + Thread t1 = new Thread(new InterruptedLockRunnable(lock)); + Thread t2 = new Thread(new InterruptibleLockRunnable(lock)); + assertTrue(lock.getQueuedThreads().isEmpty()); + lock.acquireUninterruptibly(); + assertTrue(lock.getQueuedThreads().isEmpty()); + t1.start(); + Thread.sleep(SHORT_DELAY_MS); + assertTrue(lock.getQueuedThreads().contains(t1)); + t2.start(); + Thread.sleep(SHORT_DELAY_MS); + assertTrue(lock.getQueuedThreads().contains(t1)); + assertTrue(lock.getQueuedThreads().contains(t2)); + t1.interrupt(); + Thread.sleep(SHORT_DELAY_MS); + assertFalse(lock.getQueuedThreads().contains(t1)); + assertTrue(lock.getQueuedThreads().contains(t2)); + lock.release(); + Thread.sleep(SHORT_DELAY_MS); + assertTrue(lock.getQueuedThreads().isEmpty()); + t1.join(); + t2.join(); } + /** + * drainPermits reports and removes given number of permits + */ + public void testDrainPermits() { + Semaphore s = new Semaphore(0, false); + 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()); + } /** - * - */ - public void testAcquireReleaseInDifferentThreads() { - final Semaphore s = new Semaphore(1); - Thread t = new Thread(new Runnable() { - public void run() { - try { - s.acquire(); - s.release(); - s.release(); - s.acquire(); - } catch(InterruptedException ie){ - threadUnexpectedException(); - } - } - }); - t.start(); - try { - s.release(); - s.release(); - s.acquire(); - s.acquire(); - t.join(); - } catch( InterruptedException e){ - unexpectedException(); - } - } - - /** - * - */ - public void testTimedAcquireReleaseInSameThread() { - Semaphore s = new Semaphore(1); - try { - assertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); - s.release(); - assertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); - s.release(); - assertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); - s.release(); - assertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); - s.release(); - assertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); - s.release(); - assertEquals(1, s.availablePermits()); - } catch( InterruptedException e){ - unexpectedException(); - } - } - - /** - * - */ - public void testTimedAcquireReleaseInDifferentThreads() { - final Semaphore s = new Semaphore(1); - Thread t = new Thread(new Runnable() { - public void run() { - try { - s.release(); - threadAssertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); - s.release(); - threadAssertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); - - } catch(InterruptedException ie){ - threadUnexpectedException(); - } - } - }); - t.start(); - try { - assertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); - s.release(); - assertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); - s.release(); - t.join(); - } catch( InterruptedException e){ - unexpectedException(); - } - } - - /** - * - */ - public void testAcquire_InterruptedException() { - final Semaphore s = new Semaphore(0); - Thread t = new Thread(new Runnable() { - public void run() { - try { - s.acquire(); - threadShouldThrow(); - } catch(InterruptedException success){} - } - }); - t.start(); - try { - Thread.sleep(SHORT_DELAY_MS); - t.interrupt(); - t.join(); - } catch(InterruptedException e){ - unexpectedException(); - } - } - - /** - * - */ - public void testTryAcquire_InterruptedException() { - final Semaphore s = new Semaphore(0); - Thread t = new Thread(new Runnable() { - public void run() { - try { - s.tryAcquire(MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS); - threadShouldThrow(); - } catch(InterruptedException success){ - } - } - }); - t.start(); - try { - Thread.sleep(SHORT_DELAY_MS); - t.interrupt(); - t.join(); - } catch(InterruptedException e){ - unexpectedException(); - } - } - - /** - * - */ - public void testSerialization() { - Semaphore l = new Semaphore(3); - try { - l.acquire(); - l.release(); - ByteArrayOutputStream bout = new ByteArrayOutputStream(10000); - ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout)); - out.writeObject(l); - out.close(); - - ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray()); - ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin)); - Semaphore r = (Semaphore) in.readObject(); - assertEquals(3, r.availablePermits()); - r.acquire(); - r.release(); - } catch(Exception e){ - unexpectedException(); - } + * reducePermits reduces number of permits + */ + public void testReducePermits() { + PublicSemaphore s = new PublicSemaphore(10, false); + assertEquals(10, s.availablePermits()); + s.reducePermits(1); + assertEquals(9, s.availablePermits()); + s.reducePermits(10); + assertEquals(-1, s.availablePermits()); + } + + /** + * a deserialized serialized semaphore has same number of permits + */ + public void testSerialization() throws Exception { + Semaphore l = new Semaphore(3, false); + l.acquire(); + l.release(); + ByteArrayOutputStream bout = new ByteArrayOutputStream(10000); + ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout)); + out.writeObject(l); + out.close(); + + ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray()); + ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin)); + Semaphore r = (Semaphore) in.readObject(); + assertEquals(3, r.availablePermits()); + assertFalse(r.isFair()); + r.acquire(); + r.release(); + } + + + /** + * Zero, negative, and positive initial values are allowed in constructor + */ + public void testConstructor_fair() { + Semaphore s0 = new Semaphore(0, true); + assertEquals(0, s0.availablePermits()); + assertTrue(s0.isFair()); + Semaphore s1 = new Semaphore(-1, true); + assertEquals(-1, s1.availablePermits()); + Semaphore s2 = new Semaphore(-1, true); + assertEquals(-1, s2.availablePermits()); + } + + /** + * tryAcquire succeeds when sufficient permits, else fails + */ + public void testTryAcquireInSameThread_fair() { + Semaphore s = new Semaphore(2, true); + assertEquals(2, s.availablePermits()); + assertTrue(s.tryAcquire()); + assertTrue(s.tryAcquire()); + assertEquals(0, s.availablePermits()); + assertFalse(s.tryAcquire()); + } + + /** + * tryAcquire(n) succeeds when sufficient permits, else fails + */ + public void testTryAcquireNInSameThread_fair() { + Semaphore s = new Semaphore(2, true); + assertEquals(2, s.availablePermits()); + assertTrue(s.tryAcquire(2)); + assertEquals(0, s.availablePermits()); + assertFalse(s.tryAcquire()); + } + + /** + * Acquire and release of semaphore succeed if initially available + */ + public void testAcquireReleaseInSameThread_fair() + throws InterruptedException { + Semaphore s = new Semaphore(1, true); + s.acquire(); + s.release(); + s.acquire(); + s.release(); + s.acquire(); + s.release(); + s.acquire(); + s.release(); + s.acquire(); + s.release(); + assertEquals(1, s.availablePermits()); + } + + /** + * Acquire(n) and release(n) of semaphore succeed if initially available + */ + public void testAcquireReleaseNInSameThread_fair() + throws InterruptedException { + Semaphore s = new Semaphore(1, true); + s.release(1); + s.acquire(1); + s.release(2); + s.acquire(2); + s.release(3); + s.acquire(3); + s.release(4); + s.acquire(4); + s.release(5); + s.acquire(5); + assertEquals(1, s.availablePermits()); + } + + /** + * Acquire(n) and release(n) of semaphore succeed if initially available + */ + public void testAcquireUninterruptiblyReleaseNInSameThread_fair() { + Semaphore s = new Semaphore(1, true); + s.release(1); + s.acquireUninterruptibly(1); + s.release(2); + s.acquireUninterruptibly(2); + s.release(3); + s.acquireUninterruptibly(3); + s.release(4); + s.acquireUninterruptibly(4); + s.release(5); + s.acquireUninterruptibly(5); + assertEquals(1, s.availablePermits()); + } + + /** + * release(n) in one thread enables timed acquire(n) in another thread + */ + public void testTimedAcquireReleaseNInSameThread_fair() + throws InterruptedException { + Semaphore s = new Semaphore(1, true); + s.release(1); + assertTrue(s.tryAcquire(1, SHORT_DELAY_MS, MILLISECONDS)); + s.release(2); + assertTrue(s.tryAcquire(2, SHORT_DELAY_MS, MILLISECONDS)); + s.release(3); + assertTrue(s.tryAcquire(3, SHORT_DELAY_MS, MILLISECONDS)); + s.release(4); + assertTrue(s.tryAcquire(4, SHORT_DELAY_MS, MILLISECONDS)); + s.release(5); + assertTrue(s.tryAcquire(5, SHORT_DELAY_MS, MILLISECONDS)); + assertEquals(1, s.availablePermits()); + } + + /** + * release in one thread enables timed acquire in another thread + */ + public void testTimedAcquireReleaseInSameThread_fair() + throws InterruptedException { + Semaphore s = new Semaphore(1, true); + assertTrue(s.tryAcquire(SHORT_DELAY_MS, MILLISECONDS)); + s.release(); + assertTrue(s.tryAcquire(SHORT_DELAY_MS, MILLISECONDS)); + s.release(); + assertTrue(s.tryAcquire(SHORT_DELAY_MS, MILLISECONDS)); + s.release(); + assertTrue(s.tryAcquire(SHORT_DELAY_MS, MILLISECONDS)); + s.release(); + assertTrue(s.tryAcquire(SHORT_DELAY_MS, MILLISECONDS)); + s.release(); + assertEquals(1, s.availablePermits()); + } + + /** + * A release in one thread enables an acquire in another thread + */ + public void testAcquireReleaseInDifferentThreads_fair() + throws InterruptedException { + final Semaphore s = new Semaphore(0, true); + Thread t = new Thread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + s.acquire(); + s.acquire(); + s.acquire(); + s.acquire(); + }}); + + t.start(); + Thread.sleep(SHORT_DELAY_MS); + s.release(); + s.release(); + s.release(); + s.release(); + s.release(); + s.release(); + t.join(); + assertEquals(2, s.availablePermits()); + } + + /** + * release(n) in one thread enables acquire(n) in another thread + */ + public void testAcquireReleaseNInDifferentThreads_fair() + throws InterruptedException { + final Semaphore s = new Semaphore(0, true); + Thread t = new Thread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + s.acquire(); + s.release(2); + s.acquire(); + }}); + + t.start(); + Thread.sleep(SHORT_DELAY_MS); + s.release(2); + s.acquire(2); + s.release(1); + t.join(); + } + + /** + * release(n) in one thread enables acquire(n) in another thread + */ + public void testAcquireReleaseNInDifferentThreads_fair2() + throws InterruptedException { + final Semaphore s = new Semaphore(0, true); + Thread t = new Thread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + s.acquire(2); + s.acquire(2); + s.release(4); + }}); + + t.start(); + Thread.sleep(SHORT_DELAY_MS); + s.release(6); + s.acquire(2); + s.acquire(2); + s.release(2); + t.join(); + } + + + /** + * release in one thread enables timed acquire in another thread + */ + public void testTimedAcquireReleaseInDifferentThreads_fair() + throws InterruptedException { + final Semaphore s = new Semaphore(1, true); + Thread t = new Thread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + threadAssertTrue(s.tryAcquire(SHORT_DELAY_MS, MILLISECONDS)); + threadAssertTrue(s.tryAcquire(SHORT_DELAY_MS, MILLISECONDS)); + threadAssertTrue(s.tryAcquire(SHORT_DELAY_MS, MILLISECONDS)); + threadAssertTrue(s.tryAcquire(SHORT_DELAY_MS, MILLISECONDS)); + threadAssertTrue(s.tryAcquire(SHORT_DELAY_MS, MILLISECONDS)); + }}); + + t.start(); + s.release(); + s.release(); + s.release(); + s.release(); + s.release(); + t.join(); + } + + /** + * release(n) in one thread enables timed acquire(n) in another thread + */ + public void testTimedAcquireReleaseNInDifferentThreads_fair() + throws InterruptedException { + final Semaphore s = new Semaphore(2, true); + Thread t = new Thread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + assertTrue(s.tryAcquire(2, SHORT_DELAY_MS, MILLISECONDS)); + s.release(2); + assertTrue(s.tryAcquire(2, SHORT_DELAY_MS, MILLISECONDS)); + s.release(2); + }}); + + t.start(); + assertTrue(s.tryAcquire(2, SHORT_DELAY_MS, MILLISECONDS)); + s.release(2); + assertTrue(s.tryAcquire(2, SHORT_DELAY_MS, MILLISECONDS)); + s.release(2); + t.join(); + } + + /** + * A waiting acquire blocks interruptibly + */ + public void testAcquire_InterruptedException_fair() + throws InterruptedException { + final Semaphore s = new Semaphore(0, true); + Thread t = new Thread(new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + s.acquire(); + }}); + + t.start(); + Thread.sleep(SHORT_DELAY_MS); + t.interrupt(); + t.join(); + } + + /** + * A waiting acquire(n) blocks interruptibly + */ + public void testAcquireN_InterruptedException_fair() + throws InterruptedException { + final Semaphore s = new Semaphore(2, true); + Thread t = new Thread(new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + s.acquire(3); + }}); + + t.start(); + Thread.sleep(SHORT_DELAY_MS); + t.interrupt(); + t.join(); + } + + /** + * A waiting tryAcquire blocks interruptibly + */ + public void testTryAcquire_InterruptedException_fair() + throws InterruptedException { + final Semaphore s = new Semaphore(0, true); + Thread t = new Thread(new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + s.tryAcquire(MEDIUM_DELAY_MS, MILLISECONDS); + }}); + + t.start(); + Thread.sleep(SHORT_DELAY_MS); + t.interrupt(); + t.join(); + } + + /** + * A waiting tryAcquire(n) blocks interruptibly + */ + public void testTryAcquireN_InterruptedException_fair() + throws InterruptedException { + final Semaphore s = new Semaphore(1, true); + Thread t = new Thread(new CheckedInterruptedRunnable() { + public void realRun() throws InterruptedException { + s.tryAcquire(4, MEDIUM_DELAY_MS, MILLISECONDS); + }}); + + t.start(); + Thread.sleep(SHORT_DELAY_MS); + t.interrupt(); + t.join(); + } + + /** + * getQueueLength reports number of waiting threads + */ + public void testGetQueueLength_fair() throws InterruptedException { + final Semaphore lock = new Semaphore(1, true); + Thread t1 = new Thread(new InterruptedLockRunnable(lock)); + Thread t2 = new Thread(new InterruptibleLockRunnable(lock)); + assertEquals(0, lock.getQueueLength()); + lock.acquireUninterruptibly(); + t1.start(); + Thread.sleep(SHORT_DELAY_MS); + assertEquals(1, lock.getQueueLength()); + t2.start(); + Thread.sleep(SHORT_DELAY_MS); + assertEquals(2, lock.getQueueLength()); + t1.interrupt(); + Thread.sleep(SHORT_DELAY_MS); + assertEquals(1, lock.getQueueLength()); + lock.release(); + Thread.sleep(SHORT_DELAY_MS); + assertEquals(0, lock.getQueueLength()); + t1.join(); + t2.join(); + } + + + /** + * a deserialized serialized semaphore has same number of permits + */ + public void testSerialization_fair() throws Exception { + Semaphore l = new Semaphore(3, true); + + l.acquire(); + l.release(); + ByteArrayOutputStream bout = new ByteArrayOutputStream(10000); + ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout)); + out.writeObject(l); + out.close(); + + ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray()); + ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin)); + Semaphore r = (Semaphore) in.readObject(); + assertEquals(3, r.availablePermits()); + assertTrue(r.isFair()); + r.acquire(); + r.release(); + } + + /** + * toString indicates current number of permits + */ + public void testToString() { + Semaphore s = new Semaphore(0); + String us = s.toString(); + assertTrue(us.indexOf("Permits = 0") >= 0); + s.release(); + String s1 = s.toString(); + assertTrue(s1.indexOf("Permits = 1") >= 0); + s.release(); + String s2 = s.toString(); + assertTrue(s2.indexOf("Permits = 2") >= 0); } }