• 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 
38 /**
39  * Base class for tests for emulated {@link AbstractFuture} that allow subclasses to swap in a
40  * different "source Future" for {@link AbstractFuture#setFuture} calls.
41  */
42 @GwtCompatible(emulated = true)
43 abstract class AbstractAbstractFutureTest extends TestCase {
44   private TestedFuture<Integer> future;
45   private AbstractFuture<Integer> delegate;
46 
newDelegate()47   abstract AbstractFuture<Integer> newDelegate();
48 
49   @Override
setUp()50   protected void setUp() {
51     future = TestedFuture.create();
52     delegate = newDelegate();
53   }
54 
testPending()55   public void testPending() {
56     assertPending(future);
57   }
58 
testSuccessful()59   public void testSuccessful() throws Exception {
60     assertThat(future.set(1)).isTrue();
61     assertSuccessful(future, 1);
62   }
63 
testFailed()64   public void testFailed() throws Exception {
65     Exception cause = new Exception();
66     assertThat(future.setException(cause)).isTrue();
67     assertFailed(future, cause);
68   }
69 
testCanceled()70   public void testCanceled() throws Exception {
71     assertThat(future.cancel(false /* mayInterruptIfRunning */)).isTrue();
72     assertCancelled(future, false);
73   }
74 
testInterrupted()75   public void testInterrupted() throws Exception {
76     assertThat(future.cancel(true /* mayInterruptIfRunning */)).isTrue();
77     assertCancelled(future, true);
78   }
79 
testSetFuturePending()80   public void testSetFuturePending() throws Exception {
81     assertThat(future.setFuture(delegate)).isTrue();
82     assertSetAsynchronously(future);
83   }
84 
testSetFutureThenCancel()85   public void testSetFutureThenCancel() throws Exception {
86     assertThat(future.setFuture(delegate)).isTrue();
87     assertThat(future.cancel(false /* mayInterruptIfRunning */)).isTrue();
88     assertCancelled(future, false);
89     assertCancelled(delegate, false);
90   }
91 
testSetFutureThenInterrupt()92   public void testSetFutureThenInterrupt() throws Exception {
93     assertThat(future.setFuture(delegate)).isTrue();
94     assertThat(future.cancel(true /* mayInterruptIfRunning */)).isTrue();
95     assertCancelled(future, true);
96     assertCancelled(delegate, true);
97   }
98 
testSetFutureDelegateAlreadySuccessful()99   public void testSetFutureDelegateAlreadySuccessful() throws Exception {
100     delegate.set(5);
101     assertThat(future.setFuture(delegate)).isTrue();
102     assertSuccessful(future, 5);
103   }
104 
testSetFutureDelegateLaterSuccessful()105   public void testSetFutureDelegateLaterSuccessful() throws Exception {
106     assertThat(future.setFuture(delegate)).isTrue();
107     delegate.set(6);
108     assertSuccessful(future, 6);
109   }
110 
testSetFutureDelegateAlreadyCancelled()111   public void testSetFutureDelegateAlreadyCancelled() throws Exception {
112     delegate.cancel(
113         false
114         /** mayInterruptIfRunning */
115         );
116     assertThat(future.setFuture(delegate)).isTrue();
117     assertCancelled(future, false);
118   }
119 
testSetFutureDelegateLaterCancelled()120   public void testSetFutureDelegateLaterCancelled() throws Exception {
121     assertThat(future.setFuture(delegate)).isTrue();
122     delegate.cancel(
123         false
124         /** mayInterruptIfRunning */
125         );
126     assertCancelled(future, false);
127   }
128 
testSetFutureDelegateAlreadyInterrupted()129   public void testSetFutureDelegateAlreadyInterrupted() throws Exception {
130     delegate.cancel(
131         true
132         /** mayInterruptIfRunning */
133         );
134     assertThat(future.setFuture(delegate)).isTrue();
135     assertCancelled(future, /* expectWasInterrupted= */ false);
136   }
137 
testSetFutureDelegateLaterInterrupted()138   public void testSetFutureDelegateLaterInterrupted() throws Exception {
139     assertThat(future.setFuture(delegate)).isTrue();
140     delegate.cancel(
141         true
142         /** mayInterruptIfRunning */
143         );
144     assertCancelled(future, /* expectWasInterrupted= */ false);
145   }
146 
testListenLaterSuccessful()147   public void testListenLaterSuccessful() {
148     CountingRunnable listener = new CountingRunnable();
149 
150     future.addListener(listener, directExecutor());
151     listener.assertNotRun();
152 
153     future.set(1);
154     listener.assertRun();
155   }
156 
testListenLaterFailed()157   public void testListenLaterFailed() {
158     CountingRunnable listener = new CountingRunnable();
159 
160     future.addListener(listener, directExecutor());
161     listener.assertNotRun();
162 
163     future.setException(new Exception());
164     listener.assertRun();
165   }
166 
testListenLaterCancelled()167   public void testListenLaterCancelled() {
168     CountingRunnable listener = new CountingRunnable();
169 
170     future.addListener(listener, directExecutor());
171     listener.assertNotRun();
172 
173     future.cancel(false);
174     listener.assertRun();
175   }
176 
testListenLaterInterrupted()177   public void testListenLaterInterrupted() {
178     CountingRunnable listener = new CountingRunnable();
179 
180     future.addListener(listener, directExecutor());
181     listener.assertNotRun();
182 
183     future.cancel(true);
184     listener.assertRun();
185   }
186 
testListenLaterSetAsynchronously()187   public void testListenLaterSetAsynchronously() {
188     CountingRunnable listener = new CountingRunnable();
189 
190     future.addListener(listener, directExecutor());
191     listener.assertNotRun();
192 
193     future.setFuture(delegate);
194     listener.assertNotRun();
195   }
196 
testListenLaterSetAsynchronouslyLaterDelegateSuccessful()197   public void testListenLaterSetAsynchronouslyLaterDelegateSuccessful() {
198     CountingRunnable before = new CountingRunnable();
199     CountingRunnable inBetween = new CountingRunnable();
200     CountingRunnable after = new CountingRunnable();
201 
202     future.addListener(before, directExecutor());
203     future.setFuture(delegate);
204     future.addListener(inBetween, directExecutor());
205     delegate.set(1);
206     future.addListener(after, directExecutor());
207 
208     before.assertRun();
209     inBetween.assertRun();
210     after.assertRun();
211   }
212 
testListenLaterSetAsynchronouslyLaterDelegateFailed()213   public void testListenLaterSetAsynchronouslyLaterDelegateFailed() {
214     CountingRunnable before = new CountingRunnable();
215     CountingRunnable inBetween = new CountingRunnable();
216     CountingRunnable after = new CountingRunnable();
217 
218     future.addListener(before, directExecutor());
219     future.setFuture(delegate);
220     future.addListener(inBetween, directExecutor());
221     delegate.setException(new Exception());
222     future.addListener(after, directExecutor());
223 
224     before.assertRun();
225     inBetween.assertRun();
226     after.assertRun();
227   }
228 
testListenLaterSetAsynchronouslyLaterDelegateCancelled()229   public void testListenLaterSetAsynchronouslyLaterDelegateCancelled() {
230     CountingRunnable before = new CountingRunnable();
231     CountingRunnable inBetween = new CountingRunnable();
232     CountingRunnable after = new CountingRunnable();
233 
234     future.addListener(before, directExecutor());
235     future.setFuture(delegate);
236     future.addListener(inBetween, directExecutor());
237     delegate.cancel(false);
238     future.addListener(after, directExecutor());
239 
240     before.assertRun();
241     inBetween.assertRun();
242     after.assertRun();
243   }
244 
testListenLaterSetAsynchronouslyLaterDelegateInterrupted()245   public void testListenLaterSetAsynchronouslyLaterDelegateInterrupted() {
246     CountingRunnable before = new CountingRunnable();
247     CountingRunnable inBetween = new CountingRunnable();
248     CountingRunnable after = new CountingRunnable();
249 
250     future.addListener(before, directExecutor());
251     future.setFuture(delegate);
252     future.addListener(inBetween, directExecutor());
253     delegate.cancel(true);
254     future.addListener(after, directExecutor());
255 
256     before.assertRun();
257     inBetween.assertRun();
258     after.assertRun();
259   }
260 
testListenLaterSetAsynchronouslyLaterSelfCancelled()261   public void testListenLaterSetAsynchronouslyLaterSelfCancelled() {
262     CountingRunnable before = new CountingRunnable();
263     CountingRunnable inBetween = new CountingRunnable();
264     CountingRunnable after = new CountingRunnable();
265 
266     future.addListener(before, directExecutor());
267     future.setFuture(delegate);
268     future.addListener(inBetween, directExecutor());
269     future.cancel(false);
270     future.addListener(after, directExecutor());
271 
272     before.assertRun();
273     inBetween.assertRun();
274     after.assertRun();
275   }
276 
testListenLaterSetAsynchronouslyLaterSelfInterrupted()277   public void testListenLaterSetAsynchronouslyLaterSelfInterrupted() {
278     CountingRunnable before = new CountingRunnable();
279     CountingRunnable inBetween = new CountingRunnable();
280     CountingRunnable after = new CountingRunnable();
281 
282     future.addListener(before, directExecutor());
283     future.setFuture(delegate);
284     future.addListener(inBetween, directExecutor());
285     future.cancel(true);
286     future.addListener(after, directExecutor());
287 
288     before.assertRun();
289     inBetween.assertRun();
290     after.assertRun();
291   }
292 
testMisbehavingListenerAlreadyDone()293   public void testMisbehavingListenerAlreadyDone() {
294     class BadRunnableException extends RuntimeException {}
295 
296     Runnable bad =
297         new Runnable() {
298           @Override
299           public void run() {
300             throw new BadRunnableException();
301           }
302         };
303 
304     future.set(1);
305     future.addListener(bad, directExecutor()); // BadRunnableException must not propagate.
306   }
307 
testMisbehavingListenerLaterDone()308   public void testMisbehavingListenerLaterDone() {
309     class BadRunnableException extends RuntimeException {}
310 
311     CountingRunnable before = new CountingRunnable();
312     Runnable bad =
313         new Runnable() {
314           @Override
315           public void run() {
316             throw new BadRunnableException();
317           }
318         };
319     CountingRunnable after = new CountingRunnable();
320 
321     future.addListener(before, directExecutor());
322     future.addListener(bad, directExecutor());
323     future.addListener(after, directExecutor());
324 
325     future.set(1); // BadRunnableException must not propagate.
326 
327     before.assertRun();
328     after.assertRun();
329   }
330 
testNullListener()331   public void testNullListener() {
332     try {
333       future.addListener(null, directExecutor());
334       fail();
335     } catch (NullPointerException expected) {
336     }
337   }
338 
testNullExecutor()339   public void testNullExecutor() {
340     try {
341       future.addListener(doNothing(), null);
342       fail();
343     } catch (NullPointerException expected) {
344     }
345   }
346 
testNullTimeUnit()347   public void testNullTimeUnit() throws Exception {
348     future.set(1);
349     try {
350       future.get(0, null);
351       fail();
352     } catch (NullPointerException expected) {
353     }
354   }
355 
testNegativeTimeout()356   public void testNegativeTimeout() throws Exception {
357     future.set(1);
358     assertEquals(1, future.get(-1, SECONDS).intValue());
359   }
360 
361   @GwtIncompatible // threads
362 
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, Integer expectedResult)447   private static void assertSuccessful(AbstractFuture<Integer> future, Integer expectedResult)
448       throws InterruptedException, TimeoutException, ExecutionException {
449     assertDone(future);
450     assertThat(future.isCancelled()).isFalse();
451 
452     assertThat(getDone(future)).isEqualTo(expectedResult);
453     assertThat(getDoneFromTimeoutOverload(future)).isEqualTo(expectedResult);
454   }
455 
assertFailed(AbstractFuture<Integer> future, Throwable expectedException)456   private static void assertFailed(AbstractFuture<Integer> future, Throwable expectedException)
457       throws InterruptedException, TimeoutException {
458     assertDone(future);
459     assertThat(future.isCancelled()).isFalse();
460 
461     try {
462       getDone(future);
463       fail();
464     } catch (ExecutionException e) {
465       assertThat(e.getCause()).isSameAs(expectedException);
466     }
467 
468     try {
469       getDoneFromTimeoutOverload(future);
470       fail();
471     } catch (ExecutionException e) {
472       assertThat(e).hasCauseThat().isSameAs(expectedException);
473     }
474   }
475 
assertCancelled(AbstractFuture<Integer> future, boolean expectWasInterrupted)476   private static void assertCancelled(AbstractFuture<Integer> future, boolean expectWasInterrupted)
477       throws InterruptedException, TimeoutException, ExecutionException {
478     assertDone(future);
479     assertThat(future.isCancelled()).isTrue();
480     assertThat(future.wasInterrupted()).isEqualTo(expectWasInterrupted);
481 
482     try {
483       getDone(future);
484       fail();
485     } catch (CancellationException expected) {
486     }
487 
488     try {
489       getDoneFromTimeoutOverload(future);
490       fail();
491     } catch (CancellationException expected) {
492     }
493   }
494 
assertDone(AbstractFuture<Integer> future)495   private static void assertDone(AbstractFuture<Integer> future) {
496     CountingRunnable listener = new CountingRunnable();
497     future.addListener(listener, directExecutor());
498     listener.assertRun();
499 
500     assertThat(future.isDone()).isTrue();
501     assertCannotSet(future);
502     assertCannotCancel(future);
503   }
504 
assertCannotSet(AbstractFuture<Integer> future)505   private static void assertCannotSet(AbstractFuture<Integer> future) {
506     assertThat(future.set(99)).isFalse();
507     assertThat(future.setException(new IndexOutOfBoundsException())).isFalse();
508     assertThat(future.setFuture(new AbstractFuture<Integer>() {})).isFalse();
509     assertThat(future.setFuture(immediateFuture(99))).isFalse();
510   }
511 
assertCannotCancel(AbstractFuture<Integer> future)512   private static void assertCannotCancel(AbstractFuture<Integer> future) {
513     assertThat(future.cancel(true)).isFalse();
514     assertThat(future.cancel(false)).isFalse();
515   }
516 }
517