@@ -115,6 +115,80 @@ public void testNull() throws Exception {
115115 // IncrementableCountDownLatch.await() tests
116116
117117 // CountDownLatch.await() tests
118+ public void testAwaitWithNoWait () {
119+ Stopwatch stopwatch = Stopwatch .createStarted ();
120+ CountDownLatch latch = new CountDownLatch (0 );
121+ awaitUninterruptibly (latch );
122+ assertTrue (awaitUninterruptibly (latch , 0 , MILLISECONDS ));
123+ assertTrue (awaitUninterruptibly (latch , -42 , MILLISECONDS ));
124+ assertTrue (awaitUninterruptibly (latch , LONG_DELAY_MS , MILLISECONDS ));
125+ assertTimeNotPassed (stopwatch , LONG_DELAY_MS );
126+ }
127+
128+ public void testAwaitNoInterrupt () {
129+ TimedLatch latch = new TimedLatch (/* countdownInMillis= */ 20 );
130+ latch .awaitSuccessfully ();
131+ assertNotInterrupted ();
132+ }
133+
134+ public void testAwaitTimeoutNoInterruptNotExpired () {
135+ TimedLatch latch = new TimedLatch (/* countdownInMillis= */ 20 );
136+ latch .awaitSuccessfully (LONG_DELAY_MS );
137+ assertNotInterrupted ();
138+ }
139+
140+ public void testAwaitTimeoutNoInterruptExpired () {
141+ TimedLatch latch = new TimedLatch (/* countdownInMillis= */ LONG_DELAY_MS );
142+ latch .awaitUnsuccessfully (30 );
143+ assertNotInterrupted ();
144+ }
145+
146+ public void testAwaitSingleInterrupt () {
147+ TimedLatch latch = new TimedLatch (/* countdownInMillis= */ 50 );
148+ requestInterruptIn (10 );
149+ latch .awaitSuccessfully ();
150+ assertInterrupted ();
151+ }
152+
153+ public void testAwaitTimeoutSingleInterruptNoExpire () {
154+ TimedLatch latch = new TimedLatch (/* countdownInMillis= */ 50 );
155+ requestInterruptIn (10 );
156+ latch .awaitSuccessfully (LONG_DELAY_MS );
157+ assertInterrupted ();
158+ }
159+
160+ public void testAwaitTimeoutSingleInterruptExpired () {
161+ TimedLatch latch = new TimedLatch (/* countdownInMillis= */ LONG_DELAY_MS );
162+ requestInterruptIn (10 );
163+ latch .awaitUnsuccessfully (50 );
164+ assertInterrupted ();
165+ }
166+
167+ public void testAwaitMultiInterrupt () {
168+ TimedLatch latch = new TimedLatch (/* countdownInMillis= */ 100 );
169+ repeatedlyInterruptTestThread (tearDownStack );
170+ latch .awaitSuccessfully ();
171+ assertInterrupted ();
172+ }
173+
174+ public void testAwaitTimeoutMultiInterruptNoExpire () {
175+ TimedLatch latch = new TimedLatch (/* countdownInMillis= */ 100 );
176+ repeatedlyInterruptTestThread (tearDownStack );
177+ latch .awaitSuccessfully (LONG_DELAY_MS );
178+ assertInterrupted ();
179+ }
180+
181+ public void testAwaitTimeoutMultiInterruptExpired () {
182+ /*
183+ * We don't "need" to schedule a countDown() call at all here, but by doing
184+ * so, we come the closest we can to testing that the wait time is
185+ * appropriately decreased on each progressive await() call.
186+ */
187+ TimedLatch latch = new TimedLatch (/* countdownInMillis= */ LONG_DELAY_MS );
188+ repeatedlyInterruptTestThread (tearDownStack );
189+ latch .awaitUnsuccessfully (70 );
190+ assertInterrupted ();
191+ }
118192
119193 // Condition.await() tests
120194
@@ -596,7 +670,72 @@ private static void assertAtLeastTimePassed(Stopwatch stopwatch, long expectedMi
596670 elapsedMillis + 5 >= expectedMillis );
597671 }
598672
599- // TODO(cpovirk): Split this into separate CountDownLatch and IncrementableCountDownLatch classes.
673+ /** Manages a countdown and associated timings. */
674+ private abstract static class AbstractTimedLatch {
675+ final Completion completed ;
676+
677+ AbstractTimedLatch (long countdownInMillis ) {
678+ this .completed = new Completion (countdownInMillis );
679+ }
680+
681+ /** Awaits the latch and asserts that operation completed in the expected timeframe. */
682+ final void awaitSuccessfully () {
683+ awaitLatchUninterruptibly ();
684+ completed .assertCompletionExpected ();
685+ assertEquals (0 , getCount ());
686+ }
687+
688+ /**
689+ * Awaits the latch with a timeout and asserts that operation completed in the expected
690+ * timeframe.
691+ */
692+ final void awaitSuccessfully (long timeoutMillis ) {
693+ assertTrue (awaitLatchUninterruptibly (timeoutMillis , MILLISECONDS ));
694+ completed .assertCompletionExpected ();
695+ }
696+
697+ /**
698+ * Awaits the latch with a timeout and asserts that the wait returned within the expected
699+ * timeout.
700+ */
701+ final void awaitUnsuccessfully (long timeoutMillis ) {
702+ assertFalse (awaitLatchUninterruptibly (timeoutMillis , MILLISECONDS ));
703+ completed .assertCompletionNotExpected (timeoutMillis );
704+ }
705+
706+ abstract void awaitLatchUninterruptibly ();
707+
708+ abstract boolean awaitLatchUninterruptibly (long timeout , TimeUnit unit );
709+
710+ abstract long getCount ();
711+ }
712+
713+ /** Manages a {@link CountDownLatch} and associated timings. */
714+ private static final class TimedLatch extends AbstractTimedLatch {
715+ final CountDownLatch latch ;
716+
717+ TimedLatch (long countdownInMillis ) {
718+ super (countdownInMillis );
719+ this .latch = new CountDownLatch (1 );
720+ // TODO(cpovirk): automatically fail the test if this thread throws
721+ new Thread (new CountDown (latch , countdownInMillis )).start ();
722+ }
723+
724+ @ Override
725+ void awaitLatchUninterruptibly () {
726+ Uninterruptibles .awaitUninterruptibly (latch );
727+ }
728+
729+ @ Override
730+ boolean awaitLatchUninterruptibly (long timeout , TimeUnit unit ) {
731+ return Uninterruptibles .awaitUninterruptibly (latch , timeout , unit );
732+ }
733+
734+ @ Override
735+ long getCount () {
736+ return latch .getCount ();
737+ }
738+ }
600739
601740 /** Manages a {@link BlockingQueue} and associated timings for a {@code put} call. */
602741 private static final class TimedPutQueue {
@@ -911,6 +1050,8 @@ public void run() {
9111050 return thread ;
9121051 }
9131052
1053+ // We are implementing Condition, so our callers are responsible for the loop.
1054+ @ SuppressWarnings ("WaitNotInLoop" )
9141055 private static class TestCondition implements Condition {
9151056 private final Lock lock ;
9161057 private final Condition condition ;
0 commit comments