Skip to content

Commit dcbdc60

Browse files
cpovirkGoogle Java Core Libraries
authored andcommitted
Open-source tests for the CountDownLatch overloads of awaitUninterruptibly.
We left these internal in cl/114122813 because they were "intertwined with some other Google-internal tests." This CL de-intertwines them. RELNOTES=n/a PiperOrigin-RevId: 863008683
1 parent f4b5fb9 commit dcbdc60

File tree

2 files changed

+284
-2
lines changed

2 files changed

+284
-2
lines changed

android/guava-tests/test/com/google/common/util/concurrent/UninterruptiblesTest.java

Lines changed: 142 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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;

guava-tests/test/com/google/common/util/concurrent/UninterruptiblesTest.java

Lines changed: 142 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)