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