--- jsr166/src/test/tck/ReentrantReadWriteLockTest.java 2011/05/09 20:00:19 1.60 +++ jsr166/src/test/tck/ReentrantReadWriteLockTest.java 2015/04/25 04:55:31 1.73 @@ -6,17 +6,24 @@ * Pat Fisher, Mike Judd. */ -import junit.framework.*; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.locks.*; -import java.util.concurrent.*; import static java.util.concurrent.TimeUnit.MILLISECONDS; -import java.io.*; -import java.util.*; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +import junit.framework.AssertionFailedError; +import junit.framework.Test; +import junit.framework.TestSuite; public class ReentrantReadWriteLockTest extends JSR166TestCase { public static void main(String[] args) { - junit.textui.TestRunner.run(suite()); + main(suite(), args); } public static Test suite() { return new TestSuite(ReentrantReadWriteLockTest.class); @@ -67,7 +74,7 @@ public class ReentrantReadWriteLockTest */ void releaseWriteLock(PublicReentrantReadWriteLock lock) { ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock(); - assertWriteLockedBy(lock, Thread.currentThread()); + assertWriteLockedByMoi(lock); assertEquals(1, lock.getWriteHoldCount()); writeLock.unlock(); assertNotWriteLocked(lock); @@ -80,11 +87,11 @@ public class ReentrantReadWriteLockTest long startTime = System.nanoTime(); while (!lock.hasQueuedThread(t)) { if (millisElapsedSince(startTime) > LONG_DELAY_MS) - throw new AssertionError("timed out"); + throw new AssertionFailedError("timed out"); Thread.yield(); } assertTrue(t.isAlive()); - assertTrue(lock.getOwner() != t); + assertNotSame(t, lock.getOwner()); } /** @@ -94,8 +101,9 @@ public class ReentrantReadWriteLockTest assertFalse(lock.isWriteLocked()); assertFalse(lock.isWriteLockedByCurrentThread()); assertFalse(lock.writeLock().isHeldByCurrentThread()); - assertNull(lock.getOwner()); assertEquals(0, lock.getWriteHoldCount()); + assertEquals(0, lock.writeLock().getHoldCount()); + assertNull(lock.getOwner()); } /** @@ -110,10 +118,19 @@ public class ReentrantReadWriteLockTest lock.writeLock().isHeldByCurrentThread()); assertEquals(t == Thread.currentThread(), lock.getWriteHoldCount() > 0); + assertEquals(t == Thread.currentThread(), + lock.writeLock().getHoldCount() > 0); assertEquals(0, lock.getReadLockCount()); } /** + * Checks that lock is write-locked by the current thread. + */ + void assertWriteLockedByMoi(PublicReentrantReadWriteLock lock) { + assertWriteLockedBy(lock, Thread.currentThread()); + } + + /** * Checks that condition c has no waiters. */ void assertHasNoWaiters(PublicReentrantReadWriteLock lock, Condition c) { @@ -135,10 +152,10 @@ public class ReentrantReadWriteLockTest lock.writeLock().unlock(); } - enum AwaitMethod { await, awaitNanos, awaitUntil }; + enum AwaitMethod { await, awaitTimed, awaitNanos, awaitUntil } /** - * Awaits condition using the specified AwaitMethod + * Awaits condition using the specified AwaitMethod. */ void await(Condition c, AwaitMethod awaitMethod) throws InterruptedException { @@ -146,6 +163,9 @@ public class ReentrantReadWriteLockTest case await: c.await(); break; + case awaitTimed: + assertTrue(c.await(2 * LONG_DELAY_MS, MILLISECONDS)); + break; case awaitNanos: long nanosRemaining = c.awaitNanos(MILLISECONDS.toNanos(2 * LONG_DELAY_MS)); assertTrue(nanosRemaining > 0); @@ -154,6 +174,8 @@ public class ReentrantReadWriteLockTest java.util.Date d = new java.util.Date(); assertTrue(c.awaitUntil(new java.util.Date(d.getTime() + 2 * LONG_DELAY_MS))); break; + default: + throw new AssertionError(); } } @@ -189,7 +211,7 @@ public class ReentrantReadWriteLockTest new PublicReentrantReadWriteLock(fair); assertNotWriteLocked(lock); lock.writeLock().lock(); - assertWriteLockedBy(lock, Thread.currentThread()); + assertWriteLockedByMoi(lock); lock.writeLock().unlock(); assertNotWriteLocked(lock); assertEquals(0, lock.getReadLockCount()); @@ -359,6 +381,22 @@ public class ReentrantReadWriteLockTest } /** + * write-tryLock on an unlocked lock succeeds + */ + public void testWriteTryLock() { testWriteTryLock(false); } + public void testWriteTryLock_fair() { testWriteTryLock(true); } + public void testWriteTryLock(boolean fair) { + final PublicReentrantReadWriteLock lock = + new PublicReentrantReadWriteLock(fair); + assertTrue(lock.writeLock().tryLock()); + assertWriteLockedByMoi(lock); + assertTrue(lock.writeLock().tryLock()); + assertWriteLockedByMoi(lock); + lock.writeLock().unlock(); + releaseWriteLock(lock); + } + + /** * write-tryLock fails if locked */ public void testWriteTryLockWhenLocked() { testWriteTryLockWhenLocked(false); } @@ -478,7 +516,7 @@ public class ReentrantReadWriteLockTest /** * A thread that tries to acquire a fair read lock (non-reentrantly) - * will block if there is a waiting writer thread. + * will block if there is a waiting writer thread */ public void testReaderWriterReaderFairFifo() { final PublicReentrantReadWriteLock lock = @@ -555,7 +593,8 @@ public class ReentrantReadWriteLockTest } /** - * Read trylock succeeds (barging) even in the presence of waiting readers and/or writers. + * Read trylock succeeds (barging) even in the presence of waiting + * readers and/or writers */ public void testReadTryLockBarging() { testReadTryLockBarging(false); } public void testReadTryLockBarging_fair() { testReadTryLockBarging(true); } @@ -622,7 +661,7 @@ public class ReentrantReadWriteLockTest waitForQueuedThread(lock, t1); waitForQueuedThread(lock, t2); - assertWriteLockedBy(lock, Thread.currentThread()); + assertWriteLockedByMoi(lock); lock.readLock().lock(); lock.readLock().unlock(); releaseWriteLock(lock); @@ -656,10 +695,10 @@ public class ReentrantReadWriteLockTest waitForQueuedThread(lock, t1); waitForQueuedThread(lock, t2); - assertWriteLockedBy(lock, Thread.currentThread()); + assertWriteLockedByMoi(lock); lock.readLock().lock(); lock.readLock().unlock(); - assertWriteLockedBy(lock, Thread.currentThread()); + assertWriteLockedByMoi(lock); lock.writeLock().unlock(); awaitTermination(t1); awaitTermination(t2); @@ -691,13 +730,13 @@ public class ReentrantReadWriteLockTest waitForQueuedThread(lock, t1); waitForQueuedThread(lock, t2); - assertWriteLockedBy(lock, Thread.currentThread()); + assertWriteLockedByMoi(lock); assertEquals(1, lock.getWriteHoldCount()); lock.writeLock().lock(); - assertWriteLockedBy(lock, Thread.currentThread()); + assertWriteLockedByMoi(lock); assertEquals(2, lock.getWriteHoldCount()); lock.writeLock().unlock(); - assertWriteLockedBy(lock, Thread.currentThread()); + assertWriteLockedByMoi(lock); assertEquals(1, lock.getWriteHoldCount()); lock.writeLock().unlock(); awaitTermination(t1); @@ -745,7 +784,8 @@ public class ReentrantReadWriteLockTest public void testWriteTryLock_Timeout() { testWriteTryLock_Timeout(false); } public void testWriteTryLock_Timeout_fair() { testWriteTryLock_Timeout(true); } public void testWriteTryLock_Timeout(boolean fair) { - final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair); + final PublicReentrantReadWriteLock lock = + new PublicReentrantReadWriteLock(fair); lock.writeLock().lock(); Thread t = newStartedThread(new CheckedRunnable() { public void realRun() throws InterruptedException { @@ -756,8 +796,7 @@ public class ReentrantReadWriteLockTest }}); awaitTermination(t); - assertTrue(lock.writeLock().isHeldByCurrentThread()); - lock.writeLock().unlock(); + releaseWriteLock(lock); } /** @@ -782,7 +821,7 @@ public class ReentrantReadWriteLockTest } /** - * write lockInterruptibly succeeds if lock free else is interruptible + * write lockInterruptibly succeeds if unlocked, else is interruptible */ public void testWriteLockInterruptibly() { testWriteLockInterruptibly(false); } public void testWriteLockInterruptibly_fair() { testWriteLockInterruptibly(true); } @@ -791,9 +830,7 @@ public class ReentrantReadWriteLockTest new PublicReentrantReadWriteLock(fair); try { lock.writeLock().lockInterruptibly(); - } catch (Throwable t) { - threadUnexpectedException(t); - } + } catch (InterruptedException fail) { threadUnexpectedException(fail); } Thread t = newStartedThread(new CheckedInterruptedRunnable() { public void realRun() throws InterruptedException { lock.writeLock().lockInterruptibly(); @@ -801,6 +838,7 @@ public class ReentrantReadWriteLockTest waitForQueuedThread(lock, t); t.interrupt(); + assertTrue(lock.writeLock().isHeldByCurrentThread()); awaitTermination(t); releaseWriteLock(lock); } @@ -817,9 +855,7 @@ public class ReentrantReadWriteLockTest lock.readLock().lockInterruptibly(); lock.readLock().unlock(); lock.writeLock().lockInterruptibly(); - } catch (Throwable t) { - threadUnexpectedException(t); - } + } catch (InterruptedException fail) { threadUnexpectedException(fail); } Thread t = newStartedThread(new CheckedInterruptedRunnable() { public void realRun() throws InterruptedException { lock.readLock().lockInterruptibly(); @@ -839,28 +875,17 @@ public class ReentrantReadWriteLockTest public void testAwait_IMSE(boolean fair) { final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair); final Condition c = lock.writeLock().newCondition(); - long startTime = System.nanoTime(); - try { - try { - c.await(); - shouldThrow(); - } catch (IllegalMonitorStateException success) {} - try { - c.await(LONG_DELAY_MS, MILLISECONDS); - shouldThrow(); - } catch (IllegalMonitorStateException success) {} - try { - c.awaitNanos(MILLISECONDS.toNanos(LONG_DELAY_MS)); - shouldThrow(); - } catch (IllegalMonitorStateException success) {} + for (AwaitMethod awaitMethod : AwaitMethod.values()) { + long startTime = System.nanoTime(); try { - c.awaitUninterruptibly(); + await(c, awaitMethod); shouldThrow(); - } catch (IllegalMonitorStateException success) {} - } catch (Throwable t) { - threadUnexpectedException(t); + } catch (IllegalMonitorStateException success) { + } catch (InterruptedException fail) { + threadUnexpectedException(fail); + } + assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); } - assertTrue(millisElapsedSince(startTime) < MEDIUM_DELAY_MS); } /** @@ -909,9 +934,7 @@ public class ReentrantReadWriteLockTest assertTrue(nanosRemaining <= 0); assertTrue(millisElapsedSince(startTime) >= timeoutMillis); lock.writeLock().unlock(); - } catch (InterruptedException e) { - threadUnexpectedException(e); - } + } catch (InterruptedException fail) { threadUnexpectedException(fail); } } /** @@ -930,9 +953,7 @@ public class ReentrantReadWriteLockTest assertFalse(c.await(timeoutMillis, MILLISECONDS)); assertTrue(millisElapsedSince(startTime) >= timeoutMillis); lock.writeLock().unlock(); - } catch (InterruptedException e) { - threadUnexpectedException(e); - } + } catch (InterruptedException fail) { threadUnexpectedException(fail); } } /** @@ -952,9 +973,7 @@ public class ReentrantReadWriteLockTest assertFalse(c.awaitUntil(new java.util.Date(d.getTime() + timeoutMillis))); assertTrue(millisElapsedSince(startTime) >= timeoutMillis); lock.writeLock().unlock(); - } catch (InterruptedException e) { - threadUnexpectedException(e); - } + } catch (InterruptedException fail) { threadUnexpectedException(fail); } } /** @@ -986,33 +1005,50 @@ public class ReentrantReadWriteLockTest } /** - * awaitUninterruptibly doesn't abort on interrupt + * awaitUninterruptibly is uninterruptible */ public void testAwaitUninterruptibly() { testAwaitUninterruptibly(false); } public void testAwaitUninterruptibly_fair() { testAwaitUninterruptibly(true); } public void testAwaitUninterruptibly(boolean fair) { final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair); final Condition c = lock.writeLock().newCondition(); - final CountDownLatch locked = new CountDownLatch(1); - Thread t = newStartedThread(new CheckedRunnable() { + final CountDownLatch pleaseInterrupt = new CountDownLatch(2); + + Thread t1 = newStartedThread(new CheckedRunnable() { public void realRun() { + // Interrupt before awaitUninterruptibly lock.writeLock().lock(); - locked.countDown(); + pleaseInterrupt.countDown(); + Thread.currentThread().interrupt(); c.awaitUninterruptibly(); assertTrue(Thread.interrupted()); lock.writeLock().unlock(); }}); - await(locked); + Thread t2 = newStartedThread(new CheckedRunnable() { + public void realRun() { + // Interrupt during awaitUninterruptibly + lock.writeLock().lock(); + pleaseInterrupt.countDown(); + c.awaitUninterruptibly(); + assertTrue(Thread.interrupted()); + lock.writeLock().unlock(); + }}); + + await(pleaseInterrupt); lock.writeLock().lock(); lock.writeLock().unlock(); - t.interrupt(); - long timeoutMillis = 10; - assertThreadJoinTimesOut(t, timeoutMillis); + t2.interrupt(); + + assertThreadStaysAlive(t1); + assertTrue(t2.isAlive()); + lock.writeLock().lock(); - c.signal(); + c.signalAll(); lock.writeLock().unlock(); - awaitTermination(t); + + awaitTermination(t1); + awaitTermination(t2); } /** @@ -1020,6 +1056,8 @@ public class ReentrantReadWriteLockTest */ public void testInterruptible_await() { testInterruptible(false, AwaitMethod.await); } public void testInterruptible_await_fair() { testInterruptible(true, AwaitMethod.await); } + public void testInterruptible_awaitTimed() { testInterruptible(false, AwaitMethod.awaitTimed); } + public void testInterruptible_awaitTimed_fair() { testInterruptible(true, AwaitMethod.awaitTimed); } public void testInterruptible_awaitNanos() { testInterruptible(false, AwaitMethod.awaitNanos); } public void testInterruptible_awaitNanos_fair() { testInterruptible(true, AwaitMethod.awaitNanos); } public void testInterruptible_awaitUntil() { testInterruptible(false, AwaitMethod.awaitUntil); } @@ -1032,13 +1070,13 @@ public class ReentrantReadWriteLockTest Thread t = newStartedThread(new CheckedInterruptedRunnable() { public void realRun() throws InterruptedException { lock.writeLock().lock(); - assertWriteLockedBy(lock, Thread.currentThread()); + assertWriteLockedByMoi(lock); assertHasNoWaiters(lock, c); locked.countDown(); try { await(c, awaitMethod); } finally { - assertWriteLockedBy(lock, Thread.currentThread()); + assertWriteLockedByMoi(lock); assertHasNoWaiters(lock, c); lock.writeLock().unlock(); assertFalse(Thread.interrupted()); @@ -1057,6 +1095,8 @@ public class ReentrantReadWriteLockTest */ public void testSignalAll_await() { testSignalAll(false, AwaitMethod.await); } public void testSignalAll_await_fair() { testSignalAll(true, AwaitMethod.await); } + public void testSignalAll_awaitTimed() { testSignalAll(false, AwaitMethod.awaitTimed); } + public void testSignalAll_awaitTimed_fair() { testSignalAll(true, AwaitMethod.awaitTimed); } public void testSignalAll_awaitNanos() { testSignalAll(false, AwaitMethod.awaitNanos); } public void testSignalAll_awaitNanos_fair() { testSignalAll(true, AwaitMethod.awaitNanos); } public void testSignalAll_awaitUntil() { testSignalAll(false, AwaitMethod.awaitUntil); } @@ -1090,7 +1130,7 @@ public class ReentrantReadWriteLockTest } /** - * signal wakes up waiting threads in FIFO order. + * signal wakes up waiting threads in FIFO order */ public void testSignalWakesFifo() { testSignalWakesFifo(false); } public void testSignalWakesFifo_fair() { testSignalWakesFifo(true); } @@ -1150,11 +1190,11 @@ public class ReentrantReadWriteLockTest Thread t1 = newStartedThread(new CheckedRunnable() { public void realRun() throws InterruptedException { lock.writeLock().lock(); - assertWriteLockedBy(lock, Thread.currentThread()); + assertWriteLockedByMoi(lock); assertEquals(1, lock.writeLock().getHoldCount()); locked.countDown(); c.await(); - assertWriteLockedBy(lock, Thread.currentThread()); + assertWriteLockedByMoi(lock); assertEquals(1, lock.writeLock().getHoldCount()); lock.writeLock().unlock(); }}); @@ -1163,11 +1203,11 @@ public class ReentrantReadWriteLockTest public void realRun() throws InterruptedException { lock.writeLock().lock(); lock.writeLock().lock(); - assertWriteLockedBy(lock, Thread.currentThread()); + assertWriteLockedByMoi(lock); assertEquals(2, lock.writeLock().getHoldCount()); locked.countDown(); c.await(); - assertWriteLockedBy(lock, Thread.currentThread()); + assertWriteLockedByMoi(lock); assertEquals(2, lock.writeLock().getHoldCount()); lock.writeLock().unlock(); lock.writeLock().unlock(); @@ -1205,6 +1245,9 @@ public class ReentrantReadWriteLockTest assertEquals(1, clone.getReadLockCount()); clone.readLock().unlock(); clone.writeLock().unlock(); + assertFalse(clone.isWriteLocked()); + assertEquals(1, lock.getReadLockCount()); + assertEquals(0, clone.getReadLockCount()); } /** @@ -1248,7 +1291,7 @@ public class ReentrantReadWriteLockTest } /** - * hasQueuedThread reports whether a thread is queued. + * hasQueuedThread reports whether a thread is queued */ public void testHasQueuedThread() { testHasQueuedThread(false); } public void testHasQueuedThread_fair() { testHasQueuedThread(true); } @@ -1589,19 +1632,16 @@ public class ReentrantReadWriteLockTest public void testToString_fair() { testToString(true); } public void testToString(boolean fair) { ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair); - String us = lock.toString(); - assertTrue(us.indexOf("Write locks = 0") >= 0); - assertTrue(us.indexOf("Read locks = 0") >= 0); - lock.writeLock().lock(); - String ws = lock.toString(); - assertTrue(ws.indexOf("Write locks = 1") >= 0); - assertTrue(ws.indexOf("Read locks = 0") >= 0); + assertTrue(lock.toString().contains("Write locks = 0")); + assertTrue(lock.toString().contains("Read locks = 0")); + lock.writeLock().lock(); + assertTrue(lock.toString().contains("Write locks = 1")); + assertTrue(lock.toString().contains("Read locks = 0")); lock.writeLock().unlock(); lock.readLock().lock(); lock.readLock().lock(); - String rs = lock.toString(); - assertTrue(rs.indexOf("Write locks = 0") >= 0); - assertTrue(rs.indexOf("Read locks = 2") >= 0); + assertTrue(lock.toString().contains("Write locks = 0")); + assertTrue(lock.toString().contains("Read locks = 2")); } /** @@ -1611,12 +1651,10 @@ public class ReentrantReadWriteLockTest public void testReadLockToString_fair() { testReadLockToString(true); } public void testReadLockToString(boolean fair) { ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair); - String us = lock.readLock().toString(); - assertTrue(us.indexOf("Read locks = 0") >= 0); + assertTrue(lock.readLock().toString().contains("Read locks = 0")); lock.readLock().lock(); lock.readLock().lock(); - String rs = lock.readLock().toString(); - assertTrue(rs.indexOf("Read locks = 2") >= 0); + assertTrue(lock.readLock().toString().contains("Read locks = 2")); } /** @@ -1626,11 +1664,11 @@ public class ReentrantReadWriteLockTest public void testWriteLockToString_fair() { testWriteLockToString(true); } public void testWriteLockToString(boolean fair) { ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair); - String us = lock.writeLock().toString(); - assertTrue(us.indexOf("Unlocked") >= 0); + assertTrue(lock.writeLock().toString().contains("Unlocked")); lock.writeLock().lock(); - String ls = lock.writeLock().toString(); - assertTrue(ls.indexOf("Locked") >= 0); + assertTrue(lock.writeLock().toString().contains("Locked")); + lock.writeLock().unlock(); + assertTrue(lock.writeLock().toString().contains("Unlocked")); } }