• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 The Guava Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.common.util.concurrent;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 import static com.google.common.util.concurrent.Futures.getDone;
21 import static com.google.common.util.concurrent.Futures.immediateFuture;
22 import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
23 import static com.google.common.util.concurrent.Runnables.doNothing;
24 import static com.google.common.util.concurrent.TestPlatform.getDoneFromTimeoutOverload;
25 import static com.google.common.util.concurrent.TestPlatform.verifyGetOnPendingFuture;
26 import static com.google.common.util.concurrent.TestPlatform.verifyTimedGetOnPendingFuture;
27 import static java.util.concurrent.TimeUnit.NANOSECONDS;
28 import static java.util.concurrent.TimeUnit.SECONDS;
29 
30 import com.google.common.annotations.GwtCompatible;
31 import com.google.common.annotations.GwtIncompatible;
32 import com.google.common.annotations.J2ktIncompatible;
33 import com.google.common.util.concurrent.AbstractFutureTest.TimedWaiterThread;
34 import java.util.concurrent.CancellationException;
35 import java.util.concurrent.ExecutionException;
36 import java.util.concurrent.TimeoutException;
37 import junit.framework.TestCase;
38 import org.checkerframework.checker.nullness.qual.Nullable;
39 
40 /**
41  * Base class for tests for emulated {@link AbstractFuture} that allow subclasses to swap in a
42  * different "source Future" for {@link AbstractFuture#setFuture} calls.
43  */
44 @GwtCompatible(emulated = true)
45 abstract class AbstractAbstractFutureTest extends TestCase {
46   private TestedFuture<Integer> future;
47   private AbstractFuture<Integer> delegate;
48 
newDelegate()49   abstract AbstractFuture<Integer> newDelegate();
50 
51   @Override
setUp()52   protected void setUp() {
53     future = TestedFuture.create();
54     delegate = newDelegate();
55   }
56 
testPending()57   public void testPending() {
58     assertPending(future);
59   }
60 
testSuccessful()61   public void testSuccessful() throws Exception {
62     assertThat(future.set(1)).isTrue();
63     assertSuccessful(future, 1);
64   }
65 
testFailed()66   public void testFailed() throws Exception {
67     Exception cause = new Exception();
68     assertThat(future.setException(cause)).isTrue();
69     assertFailed(future, cause);
70   }
71 
testCanceled()72   public void testCanceled() throws Exception {
73     assertThat(future.cancel(false /* mayInterruptIfRunning */)).isTrue();
74     assertCancelled(future, false);
75   }
76 
testInterrupted()77   public void testInterrupted() throws Exception {
78     assertThat(future.cancel(true /* mayInterruptIfRunning */)).isTrue();
79     assertCancelled(future, true);
80   }
81 
testSetFuturePending()82   public void testSetFuturePending() throws Exception {
83     assertThat(future.setFuture(delegate)).isTrue();
84     assertSetAsynchronously(future);
85   }
86 
testSetFutureThenCancel()87   public void testSetFutureThenCancel() throws Exception {
88     assertThat(future.setFuture(delegate)).isTrue();
89     assertThat(future.cancel(false /* mayInterruptIfRunning */)).isTrue();
90     assertCancelled(future, false);
91     assertCancelled(delegate, false);
92   }
93 
testSetFutureThenInterrupt()94   public void testSetFutureThenInterrupt() throws Exception {
95     assertThat(future.setFuture(delegate)).isTrue();
96     assertThat(future.cancel(true /* mayInterruptIfRunning */)).isTrue();
97     assertCancelled(future, true);
98     assertCancelled(delegate, true);
99   }
100 
testSetFutureDelegateAlreadySuccessful()101   public void testSetFutureDelegateAlreadySuccessful() throws Exception {
102     delegate.set(5);
103     assertThat(future.setFuture(delegate)).isTrue();
104     assertSuccessful(future, 5);
105   }
106 
testSetFutureDelegateLaterSuccessful()107   public void testSetFutureDelegateLaterSuccessful() throws Exception {
108     assertThat(future.setFuture(delegate)).isTrue();
109     delegate.set(6);
110     assertSuccessful(future, 6);
111   }
112 
testSetFutureDelegateAlreadyCancelled()113   public void testSetFutureDelegateAlreadyCancelled() throws Exception {
114     delegate.cancel(
115         false
116         /** mayInterruptIfRunning */
117         );
118     assertThat(future.setFuture(delegate)).isTrue();
119     assertCancelled(future, false);
120   }
121 
testSetFutureDelegateLaterCancelled()122   public void testSetFutureDelegateLaterCancelled() throws Exception {
123     assertThat(future.setFuture(delegate)).isTrue();
124     delegate.cancel(
125         false
126         /** mayInterruptIfRunning */
127         );
128     assertCancelled(future, false);
129   }
130 
testSetFutureDelegateAlreadyInterrupted()131   public void testSetFutureDelegateAlreadyInterrupted() throws Exception {
132     delegate.cancel(
133         true
134         /** mayInterruptIfRunning */
135         );
136     assertThat(future.setFuture(delegate)).isTrue();
137     assertCancelled(future, /* expectWasInterrupted= */ false);
138   }
139 
testSetFutureDelegateLaterInterrupted()140   public void testSetFutureDelegateLaterInterrupted() throws Exception {
141     assertThat(future.setFuture(delegate)).isTrue();
142     delegate.cancel(
143         true
144         /** mayInterruptIfRunning */
145         );
146     assertCancelled(future, /* expectWasInterrupted= */ false);
147   }
148 
testListenLaterSuccessful()149   public void testListenLaterSuccessful() {
150     CountingRunnable listener = new CountingRunnable();
151 
152     future.addListener(listener, directExecutor());
153     listener.assertNotRun();
154 
155     future.set(1);
156     listener.assertRun();
157   }
158 
testListenLaterFailed()159   public void testListenLaterFailed() {
160     CountingRunnable listener = new CountingRunnable();
161 
162     future.addListener(listener, directExecutor());
163     listener.assertNotRun();
164 
165     future.setException(new Exception());
166     listener.assertRun();
167   }
168 
testListenLaterCancelled()169   public void testListenLaterCancelled() {
170     CountingRunnable listener = new CountingRunnable();
171 
172     future.addListener(listener, directExecutor());
173     listener.assertNotRun();
174 
175     future.cancel(false);
176     listener.assertRun();
177   }
178 
testListenLaterInterrupted()179   public void testListenLaterInterrupted() {
180     CountingRunnable listener = new CountingRunnable();
181 
182     future.addListener(listener, directExecutor());
183     listener.assertNotRun();
184 
185     future.cancel(true);
186     listener.assertRun();
187   }
188 
testListenLaterSetAsynchronously()189   public void testListenLaterSetAsynchronously() {
190     CountingRunnable listener = new CountingRunnable();
191 
192     future.addListener(listener, directExecutor());
193     listener.assertNotRun();
194 
195     future.setFuture(delegate);
196     listener.assertNotRun();
197   }
198 
testListenLaterSetAsynchronouslyLaterDelegateSuccessful()199   public void testListenLaterSetAsynchronouslyLaterDelegateSuccessful() {
200     CountingRunnable before = new CountingRunnable();
201     CountingRunnable inBetween = new CountingRunnable();
202     CountingRunnable after = new CountingRunnable();
203 
204     future.addListener(before, directExecutor());
205     future.setFuture(delegate);
206     future.addListener(inBetween, directExecutor());
207     delegate.set(1);
208     future.addListener(after, directExecutor());
209 
210     before.assertRun();
211     inBetween.assertRun();
212     after.assertRun();
213   }
214 
testListenLaterSetAsynchronouslyLaterDelegateFailed()215   public void testListenLaterSetAsynchronouslyLaterDelegateFailed() {
216     CountingRunnable before = new CountingRunnable();
217     CountingRunnable inBetween = new CountingRunnable();
218     CountingRunnable after = new CountingRunnable();
219 
220     future.addListener(before, directExecutor());
221     future.setFuture(delegate);
222     future.addListener(inBetween, directExecutor());
223     delegate.setException(new Exception());
224     future.addListener(after, directExecutor());
225 
226     before.assertRun();
227     inBetween.assertRun();
228     after.assertRun();
229   }
230 
testListenLaterSetAsynchronouslyLaterDelegateCancelled()231   public void testListenLaterSetAsynchronouslyLaterDelegateCancelled() {
232     CountingRunnable before = new CountingRunnable();
233     CountingRunnable inBetween = new CountingRunnable();
234     CountingRunnable after = new CountingRunnable();
235 
236     future.addListener(before, directExecutor());
237     future.setFuture(delegate);
238     future.addListener(inBetween, directExecutor());
239     delegate.cancel(false);
240     future.addListener(after, directExecutor());
241 
242     before.assertRun();
243     inBetween.assertRun();
244     after.assertRun();
245   }
246 
testListenLaterSetAsynchronouslyLaterDelegateInterrupted()247   public void testListenLaterSetAsynchronouslyLaterDelegateInterrupted() {
248     CountingRunnable before = new CountingRunnable();
249     CountingRunnable inBetween = new CountingRunnable();
250     CountingRunnable after = new CountingRunnable();
251 
252     future.addListener(before, directExecutor());
253     future.setFuture(delegate);
254     future.addListener(inBetween, directExecutor());
255     delegate.cancel(true);
256     future.addListener(after, directExecutor());
257 
258     before.assertRun();
259     inBetween.assertRun();
260     after.assertRun();
261   }
262 
testListenLaterSetAsynchronouslyLaterSelfCancelled()263   public void testListenLaterSetAsynchronouslyLaterSelfCancelled() {
264     CountingRunnable before = new CountingRunnable();
265     CountingRunnable inBetween = new CountingRunnable();
266     CountingRunnable after = new CountingRunnable();
267 
268     future.addListener(before, directExecutor());
269     future.setFuture(delegate);
270     future.addListener(inBetween, directExecutor());
271     future.cancel(false);
272     future.addListener(after, directExecutor());
273 
274     before.assertRun();
275     inBetween.assertRun();
276     after.assertRun();
277   }
278 
testListenLaterSetAsynchronouslyLaterSelfInterrupted()279   public void testListenLaterSetAsynchronouslyLaterSelfInterrupted() {
280     CountingRunnable before = new CountingRunnable();
281     CountingRunnable inBetween = new CountingRunnable();
282     CountingRunnable after = new CountingRunnable();
283 
284     future.addListener(before, directExecutor());
285     future.setFuture(delegate);
286     future.addListener(inBetween, directExecutor());
287     future.cancel(true);
288     future.addListener(after, directExecutor());
289 
290     before.assertRun();
291     inBetween.assertRun();
292     after.assertRun();
293   }
294 
testMisbehavingListenerAlreadyDone()295   public void testMisbehavingListenerAlreadyDone() {
296     class BadRunnableException extends RuntimeException {}
297 
298     Runnable bad =
299         new Runnable() {
300           @Override
301           public void run() {
302             throw new BadRunnableException();
303           }
304         };
305 
306     future.set(1);
307     future.addListener(bad, directExecutor()); // BadRunnableException must not propagate.
308   }
309 
testMisbehavingListenerLaterDone()310   public void testMisbehavingListenerLaterDone() {
311     class BadRunnableException extends RuntimeException {}
312 
313     CountingRunnable before = new CountingRunnable();
314     Runnable bad =
315         new Runnable() {
316           @Override
317           public void run() {
318             throw new BadRunnableException();
319           }
320         };
321     CountingRunnable after = new CountingRunnable();
322 
323     future.addListener(before, directExecutor());
324     future.addListener(bad, directExecutor());
325     future.addListener(after, directExecutor());
326 
327     future.set(1); // BadRunnableException must not propagate.
328 
329     before.assertRun();
330     after.assertRun();
331   }
332 
testNullListener()333   public void testNullListener() {
334     try {
335       future.addListener(null, directExecutor());
336       fail();
337     } catch (NullPointerException expected) {
338     }
339   }
340 
testNullExecutor()341   public void testNullExecutor() {
342     try {
343       future.addListener(doNothing(), null);
344       fail();
345     } catch (NullPointerException expected) {
346     }
347   }
348 
testNullTimeUnit()349   public void testNullTimeUnit() throws Exception {
350     future.set(1);
351     try {
352       future.get(0, null);
353       fail();
354     } catch (NullPointerException expected) {
355     }
356   }
357 
testNegativeTimeout()358   public void testNegativeTimeout() throws Exception {
359     future.set(1);
360     assertEquals(1, future.get(-1, SECONDS).intValue());
361   }
362 
363   @J2ktIncompatible
364   @GwtIncompatible // threads
testOverflowTimeout()365   public void testOverflowTimeout() throws Exception {
366     // First, sanity check that naive multiplication would really overflow to a negative number:
367     long nanosPerSecond = NANOSECONDS.convert(1, SECONDS);
368     assertThat(nanosPerSecond * Long.MAX_VALUE).isLessThan(0L);
369 
370     // Check that we wait long enough anyway (presumably as long as MAX_VALUE nanos):
371     TimedWaiterThread waiter = new TimedWaiterThread(future, Long.MAX_VALUE, SECONDS);
372     waiter.start();
373     waiter.awaitWaiting();
374 
375     future.set(1);
376     waiter.join();
377   }
378 
379   @J2ktIncompatible // TODO(b/324550390): Enable
testSetNull()380   public void testSetNull() throws Exception {
381     future.set(null);
382     assertSuccessful(future, null);
383   }
384 
testSetExceptionNull()385   public void testSetExceptionNull() throws Exception {
386     try {
387       future.setException(null);
388       fail();
389     } catch (NullPointerException expected) {
390     }
391 
392     assertThat(future.isDone()).isFalse();
393     assertThat(future.set(1)).isTrue();
394     assertSuccessful(future, 1);
395   }
396 
testSetFutureNull()397   public void testSetFutureNull() throws Exception {
398     try {
399       future.setFuture(null);
400       fail();
401     } catch (NullPointerException expected) {
402     }
403 
404     assertThat(future.isDone()).isFalse();
405     assertThat(future.set(1)).isTrue();
406     assertSuccessful(future, 1);
407   }
408 
409   /** Concrete subclass for testing. */
410   private static class TestedFuture<V> extends AbstractFuture<V> {
create()411     private static <V> TestedFuture<V> create() {
412       return new TestedFuture<V>();
413     }
414   }
415 
416   private static final class CountingRunnable implements Runnable {
417     int count;
418 
419     @Override
run()420     public void run() {
421       count++;
422     }
423 
assertNotRun()424     void assertNotRun() {
425       assertEquals(0, count);
426     }
427 
assertRun()428     void assertRun() {
429       assertEquals(1, count);
430     }
431   }
432 
assertSetAsynchronously(AbstractFuture<Integer> future)433   private static void assertSetAsynchronously(AbstractFuture<Integer> future) {
434     assertCannotSet(future);
435     assertPending(future);
436   }
437 
assertPending(AbstractFuture<Integer> future)438   private static void assertPending(AbstractFuture<Integer> future) {
439     assertThat(future.isDone()).isFalse();
440     assertThat(future.isCancelled()).isFalse();
441 
442     CountingRunnable listener = new CountingRunnable();
443     future.addListener(listener, directExecutor());
444     listener.assertNotRun();
445 
446     verifyGetOnPendingFuture(future);
447     verifyTimedGetOnPendingFuture(future);
448   }
449 
assertSuccessful( AbstractFuture<Integer> future, @Nullable Integer expectedResult)450   private static void assertSuccessful(
451       AbstractFuture<Integer> future, @Nullable Integer expectedResult)
452       throws InterruptedException, TimeoutException, ExecutionException {
453     assertDone(future);
454     assertThat(future.isCancelled()).isFalse();
455 
456     assertThat(getDone(future)).isEqualTo(expectedResult);
457     assertThat(getDoneFromTimeoutOverload(future)).isEqualTo(expectedResult);
458   }
459 
assertFailed(AbstractFuture<Integer> future, Throwable expectedException)460   private static void assertFailed(AbstractFuture<Integer> future, Throwable expectedException)
461       throws InterruptedException, TimeoutException {
462     assertDone(future);
463     assertThat(future.isCancelled()).isFalse();
464 
465     try {
466       getDone(future);
467       fail();
468     } catch (ExecutionException e) {
469       assertThat(e.getCause()).isSameInstanceAs(expectedException);
470     }
471 
472     try {
473       getDoneFromTimeoutOverload(future);
474       fail();
475     } catch (ExecutionException e) {
476       assertThat(e).hasCauseThat().isSameInstanceAs(expectedException);
477     }
478   }
479 
assertCancelled(AbstractFuture<Integer> future, boolean expectWasInterrupted)480   private static void assertCancelled(AbstractFuture<Integer> future, boolean expectWasInterrupted)
481       throws InterruptedException, TimeoutException, ExecutionException {
482     assertDone(future);
483     assertThat(future.isCancelled()).isTrue();
484     assertThat(future.wasInterrupted()).isEqualTo(expectWasInterrupted);
485 
486     try {
487       getDone(future);
488       fail();
489     } catch (CancellationException expected) {
490     }
491 
492     try {
493       getDoneFromTimeoutOverload(future);
494       fail();
495     } catch (CancellationException expected) {
496     }
497   }
498 
assertDone(AbstractFuture<Integer> future)499   private static void assertDone(AbstractFuture<Integer> future) {
500     CountingRunnable listener = new CountingRunnable();
501     future.addListener(listener, directExecutor());
502     listener.assertRun();
503 
504     assertThat(future.isDone()).isTrue();
505     assertCannotSet(future);
506     assertCannotCancel(future);
507   }
508 
assertCannotSet(AbstractFuture<Integer> future)509   private static void assertCannotSet(AbstractFuture<Integer> future) {
510     assertThat(future.set(99)).isFalse();
511     assertThat(future.setException(new IndexOutOfBoundsException())).isFalse();
512     assertThat(future.setFuture(new AbstractFuture<Integer>() {})).isFalse();
513     assertThat(future.setFuture(immediateFuture(99))).isFalse();
514   }
515 
assertCannotCancel(AbstractFuture<Integer> future)516   private static void assertCannotCancel(AbstractFuture<Integer> future) {
517     assertThat(future.cancel(true)).isFalse();
518     assertThat(future.cancel(false)).isFalse();
519   }
520 }
521