--- jsr166/src/test/tck/AbstractQueuedSynchronizerTest.java 2011/05/21 06:24:33 1.41 +++ jsr166/src/test/tck/AbstractQueuedSynchronizerTest.java 2017/05/14 02:20:48 1.55 @@ -6,15 +6,22 @@ * Pat Fisher, Mike Judd. */ -import junit.framework.*; -import java.util.*; import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.NANOSECONDS; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; import java.util.concurrent.locks.AbstractQueuedSynchronizer; import java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject; +import junit.framework.AssertionFailedError; +import junit.framework.Test; +import junit.framework.TestSuite; + public class AbstractQueuedSynchronizerTest extends JSR166TestCase { public static void main(String[] args) { - junit.textui.TestRunner.run(suite()); + main(suite(), args); } public static Test suite() { return new TestSuite(AbstractQueuedSynchronizerTest.class); @@ -121,7 +128,7 @@ public class AbstractQueuedSynchronizerT } /** A constant to clarify calls to checking methods below. */ - final static Thread[] NO_THREADS = new Thread[0]; + static final Thread[] NO_THREADS = new Thread[0]; /** * Spin-waits until sync.isQueued(t) becomes true. @@ -198,7 +205,7 @@ public class AbstractQueuedSynchronizerT new HashSet(Arrays.asList(threads))); } - enum AwaitMethod { await, awaitTimed, awaitNanos, awaitUntil }; + enum AwaitMethod { await, awaitTimed, awaitNanos, awaitUntil } /** * Awaits condition using the specified AwaitMethod. @@ -221,6 +228,8 @@ public class AbstractQueuedSynchronizerT case awaitUntil: assertTrue(c.awaitUntil(delayedDate(timeoutMillis))); break; + default: + throw new AssertionError(); } } @@ -229,26 +238,34 @@ public class AbstractQueuedSynchronizerT * default timeout duration). */ void assertAwaitTimesOut(ConditionObject c, AwaitMethod awaitMethod) { - long timeoutMillis = timeoutMillis(); - long startTime = System.nanoTime(); + final long timeoutMillis = timeoutMillis(); + final long startTime; try { switch (awaitMethod) { case awaitTimed: + startTime = System.nanoTime(); assertFalse(c.await(timeoutMillis, MILLISECONDS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis); break; case awaitNanos: + startTime = System.nanoTime(); long nanosTimeout = MILLISECONDS.toNanos(timeoutMillis); long nanosRemaining = c.awaitNanos(nanosTimeout); assertTrue(nanosRemaining <= 0); + assertTrue(nanosRemaining > -MILLISECONDS.toNanos(LONG_DELAY_MS)); + assertTrue(millisElapsedSince(startTime) >= timeoutMillis); break; case awaitUntil: + // We shouldn't assume that nanoTime and currentTimeMillis + // use the same time source, so don't use nanoTime here. + java.util.Date delayedDate = delayedDate(timeoutMillis); assertFalse(c.awaitUntil(delayedDate(timeoutMillis))); + assertTrue(new java.util.Date().getTime() >= delayedDate.getTime()); break; default: throw new UnsupportedOperationException(); } } catch (InterruptedException ie) { threadUnexpectedException(ie); } - assertTrue(millisElapsedSince(startTime) >= timeoutMillis); } /** @@ -947,34 +964,34 @@ public class AbstractQueuedSynchronizerT } /** - * awaitUninterruptibly doesn't abort on interrupt + * awaitUninterruptibly is uninterruptible */ public void testAwaitUninterruptibly() { final Mutex sync = new Mutex(); - final ConditionObject c = sync.newCondition(); - final BooleanLatch acquired = new BooleanLatch(); + final ConditionObject condition = sync.newCondition(); + final BooleanLatch pleaseInterrupt = new BooleanLatch(); Thread t = newStartedThread(new CheckedRunnable() { public void realRun() { sync.acquire(); - assertTrue(acquired.releaseShared(0)); - c.awaitUninterruptibly(); + assertTrue(pleaseInterrupt.releaseShared(0)); + condition.awaitUninterruptibly(); assertTrue(Thread.interrupted()); - assertHasWaitersLocked(sync, c, NO_THREADS); + assertHasWaitersLocked(sync, condition, NO_THREADS); sync.release(); }}); - acquired.acquireShared(0); + pleaseInterrupt.acquireShared(0); sync.acquire(); - assertHasWaitersLocked(sync, c, t); + assertHasWaitersLocked(sync, condition, t); sync.release(); t.interrupt(); - assertHasWaitersUnlocked(sync, c, t); - assertThreadStaysAlive(t); + assertHasWaitersUnlocked(sync, condition, t); + assertThreadBlocks(t, Thread.State.WAITING); sync.acquire(); - assertHasWaitersLocked(sync, c, t); + assertHasWaitersLocked(sync, condition, t); assertHasExclusiveQueuedThreads(sync, NO_THREADS); - c.signal(); - assertHasWaitersLocked(sync, c, NO_THREADS); + condition.signal(); + assertHasWaitersLocked(sync, condition, NO_THREADS); assertHasExclusiveQueuedThreads(sync, t); sync.release(); awaitTermination(t); @@ -990,15 +1007,15 @@ public class AbstractQueuedSynchronizerT public void testInterruptible(final AwaitMethod awaitMethod) { final Mutex sync = new Mutex(); final ConditionObject c = sync.newCondition(); - final BooleanLatch acquired = new BooleanLatch(); + final BooleanLatch pleaseInterrupt = new BooleanLatch(); Thread t = newStartedThread(new CheckedInterruptedRunnable() { public void realRun() throws InterruptedException { sync.acquire(); - assertTrue(acquired.releaseShared(0)); + assertTrue(pleaseInterrupt.releaseShared(0)); await(c, awaitMethod); }}); - acquired.acquireShared(0); + pleaseInterrupt.acquireShared(0); t.interrupt(); awaitTermination(t); } @@ -1117,7 +1134,7 @@ public class AbstractQueuedSynchronizerT waitForQueuedThread(l, t); assertFalse(l.isSignalled()); - assertThreadStaysAlive(t); + assertThreadBlocks(t, Thread.State.WAITING); assertHasSharedQueuedThreads(l, t); assertTrue(l.releaseShared(0)); assertTrue(l.isSignalled()); @@ -1190,20 +1207,50 @@ public class AbstractQueuedSynchronizerT */ public void testTryAcquireSharedNanos_Timeout() { final BooleanLatch l = new BooleanLatch(); + final BooleanLatch observedQueued = new BooleanLatch(); Thread t = newStartedThread(new CheckedRunnable() { public void realRun() throws InterruptedException { assertFalse(l.isSignalled()); - long startTime = System.nanoTime(); - long nanos = MILLISECONDS.toNanos(timeoutMillis()); - assertFalse(l.tryAcquireSharedNanos(0, nanos)); - assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); + for (long millis = timeoutMillis(); + !observedQueued.isSignalled(); + millis *= 2) { + long nanos = MILLISECONDS.toNanos(millis); + long startTime = System.nanoTime(); + assertFalse(l.tryAcquireSharedNanos(0, nanos)); + assertTrue(millisElapsedSince(startTime) >= millis); + } assertFalse(l.isSignalled()); }}); waitForQueuedThread(l, t); + observedQueued.releaseShared(0); assertFalse(l.isSignalled()); awaitTermination(t); assertFalse(l.isSignalled()); } + /** + * awaitNanos/timed await with 0 wait times out immediately + */ + public void testAwait_Zero() throws InterruptedException { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + sync.acquire(); + assertTrue(c.awaitNanos(0L) <= 0); + assertFalse(c.await(0L, NANOSECONDS)); + sync.release(); + } + + /** + * awaitNanos/timed await with maximum negative wait times does not underflow + */ + public void testAwait_NegativeInfinity() throws InterruptedException { + final Mutex sync = new Mutex(); + final ConditionObject c = sync.newCondition(); + sync.acquire(); + assertTrue(c.awaitNanos(Long.MIN_VALUE) <= 0); + assertFalse(c.await(Long.MIN_VALUE, NANOSECONDS)); + sync.release(); + } + }