• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 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.base.Throwables.propagateIfInstanceOf;
20 import static com.google.common.truth.Truth.assertThat;
21 import static com.google.common.util.concurrent.Futures.allAsList;
22 import static com.google.common.util.concurrent.Futures.get;
23 import static com.google.common.util.concurrent.Futures.getUnchecked;
24 import static com.google.common.util.concurrent.Futures.immediateFailedFuture;
25 import static com.google.common.util.concurrent.Futures.immediateFuture;
26 import static com.google.common.util.concurrent.Futures.successfulAsList;
27 import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
28 import static com.google.common.util.concurrent.MoreExecutors.newDirectExecutorService;
29 import static java.util.concurrent.Executors.newSingleThreadExecutor;
30 import static java.util.concurrent.TimeUnit.MILLISECONDS;
31 import static java.util.concurrent.TimeUnit.SECONDS;
32 import static org.easymock.EasyMock.expect;
33 
34 import com.google.common.base.Function;
35 import com.google.common.base.Functions;
36 import com.google.common.base.Joiner;
37 import com.google.common.collect.ImmutableList;
38 import com.google.common.collect.ImmutableSet;
39 import com.google.common.collect.Iterables;
40 import com.google.common.collect.Lists;
41 import com.google.common.collect.Sets;
42 import com.google.common.testing.ClassSanityTester;
43 import com.google.common.testing.TestLogHandler;
44 import com.google.common.util.concurrent.ForwardingFuture.SimpleForwardingFuture;
45 
46 import junit.framework.AssertionFailedError;
47 import junit.framework.TestCase;
48 
49 import org.easymock.EasyMock;
50 import org.easymock.IMocksControl;
51 
52 import java.io.IOException;
53 import java.util.Arrays;
54 import java.util.List;
55 import java.util.Set;
56 import java.util.concurrent.Callable;
57 import java.util.concurrent.CancellationException;
58 import java.util.concurrent.CountDownLatch;
59 import java.util.concurrent.ExecutionException;
60 import java.util.concurrent.Executor;
61 import java.util.concurrent.ExecutorService;
62 import java.util.concurrent.Executors;
63 import java.util.concurrent.Future;
64 import java.util.concurrent.RejectedExecutionException;
65 import java.util.concurrent.TimeUnit;
66 import java.util.concurrent.TimeoutException;
67 import java.util.logging.Handler;
68 import java.util.logging.LogRecord;
69 import java.util.logging.Logger;
70 
71 import javax.annotation.Nullable;
72 
73 /**
74  * Unit tests for {@link Futures}.
75  *
76  * TODO: Add tests for other Futures methods
77  *
78  * @author Nishant Thakkar
79  */
80 public class FuturesTest extends TestCase {
81   private static final Logger combinedFutureLogger = Logger.getLogger(
82       "com.google.common.util.concurrent.Futures$CombinedFuture");
83   private final TestLogHandler combinedFutureLogHandler = new TestLogHandler();
84 
85   private static final String DATA1 = "data";
86   private static final String DATA2 = "more data";
87   private static final String DATA3 = "most data";
88 
89   private IMocksControl mocksControl;
90 
setUp()91   @Override protected void setUp() throws Exception {
92     super.setUp();
93     combinedFutureLogger.addHandler(combinedFutureLogHandler);
94     mocksControl = EasyMock.createControl();
95   }
96 
tearDown()97   @Override protected void tearDown() throws Exception {
98     /*
99      * Clear interrupt for future tests.
100      *
101      * (Ideally we would perform interrupts only in threads that we create, but
102      * it's hard to imagine that anything will break in practice.)
103      */
104     Thread.interrupted();
105     combinedFutureLogger.removeHandler(combinedFutureLogHandler);
106     super.tearDown();
107   }
108 
testImmediateFuture()109   public void testImmediateFuture() throws Exception {
110     ListenableFuture<String> future = Futures.immediateFuture(DATA1);
111 
112     // Verify that the proper object is returned without waiting
113     assertSame(DATA1, future.get(0L, TimeUnit.MILLISECONDS));
114   }
115 
testMultipleImmediateFutures()116   public void testMultipleImmediateFutures() throws Exception {
117     ListenableFuture<String> future1 = Futures.immediateFuture(DATA1);
118     ListenableFuture<String> future2 = Futures.immediateFuture(DATA2);
119 
120     // Verify that the proper objects are returned without waiting
121     assertSame(DATA1, future1.get(0L, TimeUnit.MILLISECONDS));
122     assertSame(DATA2, future2.get(0L, TimeUnit.MILLISECONDS));
123   }
124 
testImmediateFailedFuture()125   public void testImmediateFailedFuture() throws Exception {
126     Exception exception = new Exception();
127     ListenableFuture<String> future =
128         Futures.immediateFailedFuture(exception);
129 
130     try {
131       future.get(0L, TimeUnit.MILLISECONDS);
132       fail("This call was supposed to throw an ExecutionException");
133     } catch (ExecutionException expected) {
134       // This is good and expected
135       assertSame(exception, expected.getCause());
136     }
137   }
138 
testImmediateFailedFuture_cancellationException()139   public void testImmediateFailedFuture_cancellationException() throws Exception {
140     CancellationException exception = new CancellationException();
141     ListenableFuture<String> future =
142         Futures.immediateFailedFuture(exception);
143 
144     try {
145       future.get(0L, TimeUnit.MILLISECONDS);
146       fail("This call was supposed to throw an ExecutionException");
147     } catch (ExecutionException expected) {
148       // This is good and expected
149       assertSame(exception, expected.getCause());
150       assertFalse(future.isCancelled());
151     }
152   }
153 
testImmediateCancelledFuture()154   public void testImmediateCancelledFuture() throws Exception {
155     ListenableFuture<String> future =
156         Futures.immediateCancelledFuture();
157     assertTrue(future.isCancelled());
158   }
159 
160   private static class MyException extends Exception {}
161 
testImmediateCheckedFuture()162   public void testImmediateCheckedFuture() throws Exception {
163     CheckedFuture<String, MyException> future = Futures.immediateCheckedFuture(
164         DATA1);
165 
166     // Verify that the proper object is returned without waiting
167     assertSame(DATA1, future.get(0L, TimeUnit.MILLISECONDS));
168     assertSame(DATA1, future.checkedGet(0L, TimeUnit.MILLISECONDS));
169   }
170 
testMultipleImmediateCheckedFutures()171   public void testMultipleImmediateCheckedFutures() throws Exception {
172     CheckedFuture<String, MyException> future1 = Futures.immediateCheckedFuture(
173         DATA1);
174     CheckedFuture<String, MyException> future2 = Futures.immediateCheckedFuture(
175         DATA2);
176 
177     // Verify that the proper objects are returned without waiting
178     assertSame(DATA1, future1.get(0L, TimeUnit.MILLISECONDS));
179     assertSame(DATA1, future1.checkedGet(0L, TimeUnit.MILLISECONDS));
180     assertSame(DATA2, future2.get(0L, TimeUnit.MILLISECONDS));
181     assertSame(DATA2, future2.checkedGet(0L, TimeUnit.MILLISECONDS));
182   }
183 
testImmediateFailedCheckedFuture()184   public void testImmediateFailedCheckedFuture() throws Exception {
185     MyException exception = new MyException();
186     CheckedFuture<String, MyException> future =
187         Futures.immediateFailedCheckedFuture(exception);
188 
189     try {
190       future.get(0L, TimeUnit.MILLISECONDS);
191       fail("This call was supposed to throw an ExecutionException");
192     } catch (ExecutionException expected) {
193       // This is good and expected
194       assertSame(exception, expected.getCause());
195     }
196 
197     try {
198       future.checkedGet(0L, TimeUnit.MILLISECONDS);
199       fail("This call was supposed to throw an MyException");
200     } catch (MyException expected) {
201       // This is good and expected
202       assertSame(exception, expected);
203     }
204   }
205 
206   // Class hierarchy for generics sanity checks
207   private static class Foo {}
208   private static class FooChild extends Foo {}
209   private static class Bar {}
210   private static class BarChild extends Bar {}
211 
testTransform_genericsNull()212   public void testTransform_genericsNull() throws Exception {
213     ListenableFuture<?> nullFuture = Futures.immediateFuture(null);
214     ListenableFuture<?> transformedFuture =
215         Futures.transform(nullFuture, Functions.constant(null));
216     assertNull(transformedFuture.get());
217   }
218 
testTransform_genericsHierarchy()219   public void testTransform_genericsHierarchy() throws Exception {
220     ListenableFuture<FooChild> future = Futures.immediateFuture(null);
221     final BarChild barChild = new BarChild();
222     Function<Foo, BarChild> function = new Function<Foo, BarChild>() {
223       @Override public BarChild apply(Foo unused) {
224         return barChild;
225       }
226     };
227     Bar bar = Futures.transform(future, function).get();
228     assertSame(barChild, bar);
229   }
230 
testTransform_cancelPropagatesToInput()231   public void testTransform_cancelPropagatesToInput() throws Exception {
232     SettableFuture<Foo> input = SettableFuture.create();
233     AsyncFunction<Foo, Bar> function = new AsyncFunction<Foo, Bar>() {
234       @Override public ListenableFuture<Bar> apply(Foo unused) {
235         throw new AssertionFailedError("Unexpeted call to apply.");
236       }
237     };
238     assertTrue(Futures.transform(input, function).cancel(false));
239     assertTrue(input.isCancelled());
240     assertFalse(input.wasInterrupted());
241   }
242 
testTransform_interruptPropagatesToInput()243   public void testTransform_interruptPropagatesToInput() throws Exception {
244     SettableFuture<Foo> input = SettableFuture.create();
245     AsyncFunction<Foo, Bar> function = new AsyncFunction<Foo, Bar>() {
246       @Override public ListenableFuture<Bar> apply(Foo unused) {
247         throw new AssertionFailedError("Unexpeted call to apply.");
248       }
249     };
250     assertTrue(Futures.transform(input, function).cancel(true));
251     assertTrue(input.isCancelled());
252     assertTrue(input.wasInterrupted());
253   }
254 
testTransform_cancelPropagatesToAsyncOutput()255   public void testTransform_cancelPropagatesToAsyncOutput() throws Exception {
256     ListenableFuture<Foo> immediate = Futures.immediateFuture(new Foo());
257     final SettableFuture<Bar> secondary = SettableFuture.create();
258     AsyncFunction<Foo, Bar> function = new AsyncFunction<Foo, Bar>() {
259       @Override public ListenableFuture<Bar> apply(Foo unused) {
260         return secondary;
261       }
262     };
263     assertTrue(Futures.transform(immediate, function).cancel(false));
264     assertTrue(secondary.isCancelled());
265     assertFalse(secondary.wasInterrupted());
266   }
267 
testTransform_interruptPropagatesToAsyncOutput()268   public void testTransform_interruptPropagatesToAsyncOutput()
269       throws Exception {
270     ListenableFuture<Foo> immediate = Futures.immediateFuture(new Foo());
271     final SettableFuture<Bar> secondary = SettableFuture.create();
272     AsyncFunction<Foo, Bar> function = new AsyncFunction<Foo, Bar>() {
273       @Override public ListenableFuture<Bar> apply(Foo unused) {
274         return secondary;
275       }
276     };
277     assertTrue(Futures.transform(immediate, function).cancel(true));
278     assertTrue(secondary.isCancelled());
279     assertTrue(secondary.wasInterrupted());
280   }
281 
testTransform_rejectionPropagatesToOutput()282   public void testTransform_rejectionPropagatesToOutput()
283       throws Exception {
284     SettableFuture<Foo> input = SettableFuture.create();
285     ExecutorService executor = newDirectExecutorService();
286     ListenableFuture<String> transformed =
287         Futures.transform(input, Functions.toStringFunction(), executor);
288     executor.shutdown();
289     input.set(new Foo());
290     try {
291       transformed.get(5, TimeUnit.SECONDS);
292       fail();
293     } catch (ExecutionException expected) {
294       assertTrue(expected.getCause() instanceof RejectedExecutionException);
295     }
296   }
297 
298   /**
299    * Tests that the function is invoked only once, even if it throws an
300    * exception.
301    */
testTransformValueRemainsMemoized()302   public void testTransformValueRemainsMemoized() throws Exception {
303     class Holder {
304       int value = 2;
305     }
306     final Holder holder = new Holder();
307 
308     // This function adds the holder's value to the input value.
309     Function<Integer, Integer> adder = new Function<Integer, Integer>() {
310       @Override public Integer apply(Integer from) {
311         return from + holder.value;
312       }
313     };
314 
315     // Since holder.value is 2, applying 4 should yield 6.
316     assertEquals(6, adder.apply(4).intValue());
317 
318     ListenableFuture<Integer> immediateFuture = Futures.immediateFuture(4);
319     Future<Integer> transformedFuture = Futures.transform(immediateFuture, adder);
320 
321     // The composed future also yields 6.
322     assertEquals(6, transformedFuture.get().intValue());
323 
324     // Repeated calls yield the same value even though the function's behavior
325     // changes
326     holder.value = 3;
327     assertEquals(6, transformedFuture.get().intValue());
328     assertEquals(7, adder.apply(4).intValue());
329 
330     // Once more, with feeling.
331     holder.value = 4;
332     assertEquals(6, transformedFuture.get().intValue());
333     assertEquals(8, adder.apply(4).intValue());
334 
335     // Memoized get also retains the value.
336     assertEquals(6, transformedFuture.get(1000, TimeUnit.SECONDS).intValue());
337 
338     // Unsurprisingly, recomposing the future will return an updated value.
339     assertEquals(8, Futures.transform(immediateFuture, adder).get().intValue());
340 
341     // Repeating, with the timeout version
342     assertEquals(8, Futures.transform(immediateFuture, adder).get(
343         1000, TimeUnit.SECONDS).intValue());
344   }
345 
346   static class MyError extends Error {}
347   static class MyRuntimeException extends RuntimeException {}
348 
349   /**
350    * Test that the function is invoked only once, even if it throws an
351    * exception. Also, test that that function's result is wrapped in an
352    * ExecutionException.
353    */
testTransformExceptionRemainsMemoized()354   public void testTransformExceptionRemainsMemoized() throws Throwable {
355     // We need to test with two input futures since ExecutionList.execute
356     // doesn't catch Errors and we cannot depend on the order that our
357     // transformations run. (So it is possible that the Error being thrown
358     // could prevent our second transformations from running).
359     SettableFuture<Integer> exceptionInput = SettableFuture.create();
360     ListenableFuture<Integer> exceptionComposedFuture =
361         Futures.transform(exceptionInput, newOneTimeExceptionThrower());
362     exceptionInput.set(0);
363     runGetIdempotencyTest(exceptionComposedFuture, MyRuntimeException.class);
364 
365     SettableFuture<Integer> errorInput = SettableFuture.create();
366     ListenableFuture<Integer> errorComposedFuture =
367         Futures.transform(errorInput, newOneTimeErrorThrower());
368     errorInput.set(0);
369 
370     runGetIdempotencyTest(errorComposedFuture, MyError.class);
371 
372     /*
373      * Try again when the input's value is already filled in, since the flow is
374      * slightly different in that case.
375      */
376     exceptionComposedFuture =
377         Futures.transform(exceptionInput, newOneTimeExceptionThrower());
378     runGetIdempotencyTest(exceptionComposedFuture, MyRuntimeException.class);
379 
380     runGetIdempotencyTest(Futures.transform(errorInput, newOneTimeErrorThrower()), MyError.class);
381     runGetIdempotencyTest(errorComposedFuture, MyError.class);
382   }
383 
runGetIdempotencyTest(Future<Integer> transformedFuture, Class<? extends Throwable> expectedExceptionClass)384   private static void runGetIdempotencyTest(Future<Integer> transformedFuture,
385       Class<? extends Throwable> expectedExceptionClass) throws Throwable {
386     for (int i = 0; i < 5; i++) {
387       try {
388         transformedFuture.get();
389         fail();
390       } catch (ExecutionException expected) {
391         if (!expectedExceptionClass.isInstance(expected.getCause())) {
392           throw expected.getCause();
393         }
394       }
395     }
396   }
397 
newOneTimeExceptionThrower()398   private static Function<Integer, Integer> newOneTimeExceptionThrower() {
399     return new Function<Integer, Integer>() {
400       int calls = 0;
401 
402       @Override public Integer apply(Integer from) {
403         if (++calls > 1) {
404           fail();
405         }
406         throw new MyRuntimeException();
407       }
408     };
409   }
410 
newOneTimeErrorThrower()411   private static Function<Integer, Integer> newOneTimeErrorThrower() {
412     return new Function<Integer, Integer>() {
413       int calls = 0;
414 
415       @Override public Integer apply(Integer from) {
416         if (++calls > 1) {
417           fail();
418         }
419         throw new MyError();
420       }
421     };
422   }
423 
424   // TODO(cpovirk): top-level class?
425   static class ExecutorSpy implements Executor {
426     Executor delegate;
427     boolean wasExecuted;
428 
429     public ExecutorSpy(Executor delegate) {
430       this.delegate = delegate;
431     }
432 
433     @Override public void execute(Runnable command) {
434       delegate.execute(command);
435       wasExecuted = true;
436     }
437   }
438 
439   public void testTransform_Executor() throws Exception {
440     Object value = new Object();
441     ExecutorSpy spy = new ExecutorSpy(directExecutor());
442 
443     assertFalse(spy.wasExecuted);
444 
445     ListenableFuture<Object> future = Futures.transform(
446         Futures.immediateFuture(value),
447         Functions.identity(), spy);
448 
449     assertSame(value, future.get());
450     assertTrue(spy.wasExecuted);
451   }
452 
453   public void testLazyTransform() throws Exception {
454     FunctionSpy<Object, String> spy =
455         new FunctionSpy<Object, String>(Functions.constant("bar"));
456     Future<String> input = Futures.immediateFuture("foo");
457     Future<String> transformed = Futures.lazyTransform(input, spy);
458     assertEquals(0, spy.getApplyCount());
459     assertEquals("bar", transformed.get());
460     assertEquals(1, spy.getApplyCount());
461     assertEquals("bar", transformed.get());
462     assertEquals(2, spy.getApplyCount());
463   }
464 
465   public void testLazyTransform_exception() throws Exception {
466     final RuntimeException exception = new RuntimeException("deliberate");
467     Function<Integer, String> function = new Function<Integer, String>() {
468       @Override public String apply(Integer input) {
469         throw exception;
470       }
471     };
472     Future<String> transformed = Futures.lazyTransform(Futures.immediateFuture(1), function);
473     try {
474       transformed.get();
475       fail();
476     } catch (ExecutionException expected) {
477       assertSame(exception, expected.getCause());
478     }
479     try {
480       transformed.get(1, TimeUnit.SECONDS);
481       fail();
482     } catch (ExecutionException expected) {
483       assertSame(exception, expected.getCause());
484     }
485   }
486 
487   private static class FunctionSpy<I, O> implements Function<I, O> {
488     private int applyCount;
489     private final Function<I, O> delegate;
490 
491     public FunctionSpy(Function<I, O> delegate) {
492       this.delegate = delegate;
493     }
494 
495     @Override
496     public O apply(I input) {
497       applyCount++;
498       return delegate.apply(input);
499     }
500 
501     public int getApplyCount() {
502       return applyCount;
503     }
504   }
505 
506   @SuppressWarnings("unchecked")
507   public void testWithFallback_inputDoesNotRaiseException() throws Exception {
508     FutureFallback<Integer> fallback = mocksControl.createMock(FutureFallback.class);
509     ListenableFuture<Integer> originalFuture = Futures.immediateFuture(7);
510 
511     mocksControl.replay();
512     ListenableFuture<Integer> faultToleranteFuture = Futures.withFallback(originalFuture, fallback);
513     assertEquals(7, faultToleranteFuture.get().intValue());
514     mocksControl.verify();
515   }
516 
517   @SuppressWarnings("unchecked")
518   public void testWithFallback_inputRaisesException() throws Exception {
519     FutureFallback<Integer> fallback = mocksControl.createMock(FutureFallback.class);
520     RuntimeException raisedException = new RuntimeException();
521     expect(fallback.create(raisedException)).andReturn(Futures.immediateFuture(20));
522     ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(raisedException);
523 
524     mocksControl.replay();
525     ListenableFuture<Integer> faultToleranteFuture = Futures.withFallback(failingFuture, fallback);
526     assertEquals(20, faultToleranteFuture.get().intValue());
527     mocksControl.verify();
528   }
529 
530   public void testWithFallback_fallbackGeneratesRuntimeException() throws Exception {
531     RuntimeException expectedException = new RuntimeException();
532     runExpectedExceptionFallbackTest(expectedException, false);
533   }
534 
535   public void testWithFallback_fallbackGeneratesCheckedException() throws Exception {
536     Exception expectedException = new Exception() {};
537     runExpectedExceptionFallbackTest(expectedException, false);
538   }
539 
540   @SuppressWarnings("unchecked")
541   public void testWithFallback_fallbackGeneratesError() throws Exception {
542     final Error error = new Error("deliberate");
543     FutureFallback<Integer> fallback = new FutureFallback<Integer>() {
544       @Override public ListenableFuture<Integer> create(Throwable t) throws Exception {
545         throw error;
546       }
547     };
548     ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(new RuntimeException());
549     try {
550       Futures.withFallback(failingFuture, fallback).get();
551       fail("An Exception should have been thrown!");
552     } catch (ExecutionException expected) {
553       assertSame(error, expected.getCause());
554     }
555   }
556 
557   public void testWithFallback_fallbackReturnsRuntimeException() throws Exception {
558     RuntimeException expectedException = new RuntimeException();
559     runExpectedExceptionFallbackTest(expectedException, true);
560   }
561 
562   public void testWithFallback_fallbackReturnsCheckedException() throws Exception {
563     Exception expectedException = new Exception() {};
564     runExpectedExceptionFallbackTest(expectedException, true);
565   }
566 
567   @SuppressWarnings("unchecked")
568   private void runExpectedExceptionFallbackTest(
569       Throwable expectedException, boolean wrapInFuture) throws Exception {
570     FutureFallback<Integer> fallback = mocksControl.createMock(FutureFallback.class);
571     RuntimeException raisedException = new RuntimeException();
572     if (!wrapInFuture) {
573       // Exception is thrown in the body of the "fallback" method.
574       expect(fallback.create(raisedException)).andThrow(expectedException);
575     } else {
576       // Exception is wrapped in a future and returned.
577       expect(fallback.create(raisedException)).andReturn(
578           Futures.<Integer>immediateFailedFuture(expectedException));
579     }
580 
581     ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(raisedException);
582 
583     mocksControl.replay();
584     ListenableFuture<Integer> faultToleranteFuture = Futures.withFallback(failingFuture, fallback);
585     try {
586       faultToleranteFuture.get();
587       fail("An Exception should have been thrown!");
588     } catch (ExecutionException ee) {
589       assertSame(expectedException, ee.getCause());
590     }
591     mocksControl.verify();
592   }
593 
594   public void testWithFallback_fallbackNotReady() throws Exception {
595     ListenableFuture<Integer> primary = immediateFailedFuture(new Exception());
596     final SettableFuture<Integer> secondary = SettableFuture.create();
597     FutureFallback<Integer> fallback = new FutureFallback<Integer>() {
598       @Override
599       public ListenableFuture<Integer> create(Throwable t) {
600         return secondary;
601       }
602     };
603     ListenableFuture<Integer> derived = Futures.withFallback(primary, fallback);
604     secondary.set(1);
605     assertEquals(1, (int) derived.get());
606   }
607 
608   @SuppressWarnings("unchecked")
609   public void testWithFallback_resultInterruptedBeforeFallback() throws Exception {
610     SettableFuture<Integer> primary = SettableFuture.create();
611     FutureFallback<Integer> fallback = mocksControl.createMock(FutureFallback.class);
612 
613     mocksControl.replay();
614     ListenableFuture<Integer> derived = Futures.withFallback(primary, fallback);
615     derived.cancel(true);
616     assertTrue(primary.isCancelled());
617     assertTrue(primary.wasInterrupted());
618     mocksControl.verify();
619   }
620 
621   @SuppressWarnings("unchecked")
622   public void testWithFallback_resultCancelledBeforeFallback() throws Exception {
623     SettableFuture<Integer> primary = SettableFuture.create();
624     FutureFallback<Integer> fallback = mocksControl.createMock(FutureFallback.class);
625 
626     mocksControl.replay();
627     ListenableFuture<Integer> derived = Futures.withFallback(primary, fallback);
628     derived.cancel(false);
629     assertTrue(primary.isCancelled());
630     assertFalse(primary.wasInterrupted());
631     mocksControl.verify();
632   }
633 
634   @SuppressWarnings("unchecked")
635   public void testWithFallback_resultCancelledAfterFallback() throws Exception {
636     SettableFuture<Integer> secondary = SettableFuture.create();
637     FutureFallback<Integer> fallback = mocksControl.createMock(FutureFallback.class);
638     RuntimeException raisedException = new RuntimeException();
639     expect(fallback.create(raisedException)).andReturn(secondary);
640     ListenableFuture<Integer> failingFuture = Futures.immediateFailedFuture(raisedException);
641 
642     mocksControl.replay();
643     ListenableFuture<Integer> derived = Futures.withFallback(failingFuture, fallback);
644     derived.cancel(false);
645     assertTrue(secondary.isCancelled());
646     assertFalse(secondary.wasInterrupted());
647     mocksControl.verify();
648   }
649 
650   public void testTransform_genericsWildcard_AsyncFunction() throws Exception {
651     ListenableFuture<?> nullFuture = Futures.immediateFuture(null);
652     ListenableFuture<?> chainedFuture =
653         Futures.transform(nullFuture, constantAsyncFunction(nullFuture));
654     assertNull(chainedFuture.get());
655   }
656 
657   private static <I, O> AsyncFunction<I, O> constantAsyncFunction(
658       final ListenableFuture<O> output) {
659     return new AsyncFunction<I, O>() {
660       @Override
661       public ListenableFuture<O> apply(I input) {
662         return output;
663       }
664     };
665   }
666 
667   public void testTransform_genericsHierarchy_AsyncFunction() throws Exception {
668     ListenableFuture<FooChild> future = Futures.immediateFuture(null);
669     final BarChild barChild = new BarChild();
670     AsyncFunction<Foo, BarChild> function =
671         new AsyncFunction<Foo, BarChild>() {
672           @Override public AbstractFuture<BarChild> apply(Foo unused) {
673             AbstractFuture<BarChild> future = new AbstractFuture<BarChild>() {};
674             future.set(barChild);
675             return future;
676           }
677         };
678     Bar bar = Futures.transform(future, function).get();
679     assertSame(barChild, bar);
680   }
681 
682   public void testTransform_asyncFunction_timeout()
683       throws InterruptedException, ExecutionException {
684     AsyncFunction<String, Integer> function = constantAsyncFunction(Futures.immediateFuture(1));
685     ListenableFuture<Integer> future = Futures.transform(
686         SettableFuture.<String>create(), function);
687     try {
688       future.get(1, TimeUnit.MILLISECONDS);
689       fail();
690     } catch (TimeoutException expected) {}
691   }
692 
693   public void testTransform_asyncFunction_error() throws InterruptedException {
694     final Error error = new Error("deliberate");
695     AsyncFunction<String, Integer> function = new AsyncFunction<String, Integer>() {
696       @Override public ListenableFuture<Integer> apply(String input) {
697         throw error;
698       }
699     };
700     SettableFuture<String> inputFuture = SettableFuture.create();
701     ListenableFuture<Integer> outputFuture = Futures.transform(inputFuture, function);
702     inputFuture.set("value");
703     try {
704       outputFuture.get();
705       fail("should have thrown error");
706     } catch (ExecutionException e) {
707       assertSame(error, e.getCause());
708     }
709   }
710 
711   public void testTransform_asyncFunction_cancelledWhileApplyingFunction()
712       throws InterruptedException, ExecutionException {
713     final CountDownLatch inFunction = new CountDownLatch(1);
714     final CountDownLatch functionDone = new CountDownLatch(1);
715     final SettableFuture<Integer> resultFuture = SettableFuture.create();
716     AsyncFunction<String, Integer> function = new AsyncFunction<String, Integer>() {
717       @Override public ListenableFuture<Integer> apply(String input) throws Exception {
718         inFunction.countDown();
719         functionDone.await();
720         return resultFuture;
721       }
722     };
723     SettableFuture<String> inputFuture = SettableFuture.create();
724     ListenableFuture<Integer> future = Futures.transform(
725         inputFuture, function, Executors.newSingleThreadExecutor());
726     inputFuture.set("value");
727     inFunction.await();
728     future.cancel(false);
729     functionDone.countDown();
730     try {
731       future.get();
732       fail();
733     } catch (CancellationException expected) {}
734     try {
735       resultFuture.get();
736       fail();
737     } catch (CancellationException expected) {}
738   }
739 
740   public void testDereference_genericsWildcard() throws Exception {
741     ListenableFuture<?> inner = Futures.immediateFuture(null);
742     ListenableFuture<ListenableFuture<?>> outer =
743         Futures.<ListenableFuture<?>>immediateFuture(inner);
744     ListenableFuture<?> dereferenced = Futures.dereference(outer);
745     assertNull(dereferenced.get());
746   }
747 
748   public void testDereference_genericsHierarchy() throws Exception {
749     FooChild fooChild = new FooChild();
750     ListenableFuture<FooChild> inner = Futures.immediateFuture(fooChild);
751     ListenableFuture<ListenableFuture<FooChild>> outer = Futures.immediateFuture(inner);
752     ListenableFuture<Foo> dereferenced = Futures.<Foo>dereference(outer);
753     assertSame(fooChild, dereferenced.get());
754   }
755 
756   public void testDereference_resultCancelsOuter() throws Exception {
757     ListenableFuture<ListenableFuture<Foo>> outer = SettableFuture.create();
758     ListenableFuture<Foo> dereferenced = Futures.dereference(outer);
759     dereferenced.cancel(true);
760     assertTrue(outer.isCancelled());
761   }
762 
763   public void testDereference_resultCancelsInner() throws Exception {
764     ListenableFuture<Foo> inner = SettableFuture.create();
765     ListenableFuture<ListenableFuture<Foo>> outer = Futures.immediateFuture(inner);
766     ListenableFuture<Foo> dereferenced = Futures.dereference(outer);
767     dereferenced.cancel(true);
768     assertTrue(inner.isCancelled());
769   }
770 
771   public void testDereference_outerCancelsResult() throws Exception {
772     ListenableFuture<ListenableFuture<Foo>> outer = SettableFuture.create();
773     ListenableFuture<Foo> dereferenced = Futures.dereference(outer);
774     outer.cancel(true);
775     assertTrue(dereferenced.isCancelled());
776   }
777 
778   public void testDereference_innerCancelsResult() throws Exception {
779     ListenableFuture<Foo> inner = SettableFuture.create();
780     ListenableFuture<ListenableFuture<Foo>> outer = Futures.immediateFuture(inner);
781     ListenableFuture<Foo> dereferenced = Futures.dereference(outer);
782     inner.cancel(true);
783     assertTrue(dereferenced.isCancelled());
784   }
785 
786   /**
787    * Runnable which can be called a single time, and only after
788    * {@link #expectCall} is called.
789    */
790   // TODO(cpovirk): top-level class?
791   static class SingleCallListener implements Runnable {
792     private boolean expectCall = false;
793     private final CountDownLatch calledCountDown =
794         new CountDownLatch(1);
795 
796     @Override public void run() {
797       assertTrue("Listener called before it was expected", expectCall);
798       assertFalse("Listener called more than once", wasCalled());
799       calledCountDown.countDown();
800     }
801 
802     public void expectCall() {
803       assertFalse("expectCall is already true", expectCall);
804       expectCall = true;
805     }
806 
807     public boolean wasCalled() {
808       return calledCountDown.getCount() == 0;
809     }
810 
811     public void waitForCall() throws InterruptedException {
812       assertTrue("expectCall is false", expectCall);
813       calledCountDown.await();
814     }
815   }
816 
817   public void testAllAsList() throws Exception {
818     // Create input and output
819     SettableFuture<String> future1 = SettableFuture.create();
820     SettableFuture<String> future2 = SettableFuture.create();
821     SettableFuture<String> future3 = SettableFuture.create();
822     @SuppressWarnings("unchecked") // array is never modified
823     ListenableFuture<List<String>> compound =
824         Futures.allAsList(future1, future2, future3);
825 
826     // Attach a listener
827     SingleCallListener listener = new SingleCallListener();
828     compound.addListener(listener, directExecutor());
829 
830     // Satisfy each input and check the output
831     assertFalse(compound.isDone());
832     future1.set(DATA1);
833     assertFalse(compound.isDone());
834     future2.set(DATA2);
835     assertFalse(compound.isDone());
836     listener.expectCall();
837     future3.set(DATA3);
838     assertTrue(compound.isDone());
839     assertTrue(listener.wasCalled());
840 
841     List<String> results = compound.get();
842     assertThat(results).has().exactly(DATA1, DATA2, DATA3).inOrder();
843   }
844 
845   public void testAllAsList_emptyList() throws Exception {
846     SingleCallListener listener = new SingleCallListener();
847     listener.expectCall();
848     List<ListenableFuture<String>> futures = ImmutableList.of();
849     ListenableFuture<List<String>> compound = Futures.allAsList(futures);
850     compound.addListener(listener, directExecutor());
851     assertTrue(compound.isDone());
852     assertTrue(compound.get().isEmpty());
853     assertTrue(listener.wasCalled());
854   }
855 
856   public void testAllAsList_emptyArray() throws Exception {
857     SingleCallListener listener = new SingleCallListener();
858     listener.expectCall();
859     @SuppressWarnings("unchecked") // array is never modified
860     ListenableFuture<List<String>> compound = Futures.allAsList();
861     compound.addListener(listener, directExecutor());
862     assertTrue(compound.isDone());
863     assertTrue(compound.get().isEmpty());
864     assertTrue(listener.wasCalled());
865   }
866 
867   public void testAllAsList_failure() throws Exception {
868     SingleCallListener listener = new SingleCallListener();
869     SettableFuture<String> future1 = SettableFuture.create();
870     SettableFuture<String> future2 = SettableFuture.create();
871     @SuppressWarnings("unchecked") // array is never modified
872     ListenableFuture<List<String>> compound =
873         Futures.allAsList(future1, future2);
874     compound.addListener(listener, directExecutor());
875 
876     listener.expectCall();
877     Throwable exception = new Throwable("failed1");
878     future1.setException(exception);
879     assertTrue(compound.isDone());
880     assertTrue(listener.wasCalled());
881     future2.set("result2");
882 
883     try {
884       compound.get();
885       fail("Expected exception not thrown");
886     } catch (ExecutionException e) {
887       assertSame(exception, e.getCause());
888     }
889   }
890 
891   public void testAllAsList_singleFailure() throws Exception {
892     Throwable exception = new Throwable("failed");
893     ListenableFuture<String> future = Futures.immediateFailedFuture(exception);
894     ListenableFuture<List<String>> compound = Futures.allAsList(ImmutableList.of(future));
895 
896     try {
897       compound.get();
898       fail("Expected exception not thrown");
899     } catch (ExecutionException e) {
900       assertSame(exception, e.getCause());
901     }
902   }
903 
904   public void testAllAsList_immediateFailure() throws Exception {
905     Throwable exception = new Throwable("failed");
906     ListenableFuture<String> future1 = Futures.immediateFailedFuture(exception);
907     ListenableFuture<String> future2 = Futures.immediateFuture("results");
908     ListenableFuture<List<String>> compound = Futures.allAsList(ImmutableList.of(future1, future2));
909 
910     try {
911       compound.get();
912       fail("Expected exception not thrown");
913     } catch (ExecutionException e) {
914       assertSame(exception, e.getCause());
915     }
916   }
917 
918   public void testAllAsList_error() throws Exception {
919     Error error = new Error("deliberate");
920     SettableFuture<String> future1 = SettableFuture.create();
921     ListenableFuture<String> future2 = Futures.immediateFuture("results");
922     ListenableFuture<List<String>> compound = Futures.allAsList(ImmutableList.of(future1, future2));
923 
924     future1.setException(error);
925     try {
926       compound.get();
927       fail("Expected error not set in compound future.");
928     } catch (ExecutionException ee) {
929       assertSame(error, ee.getCause());
930     }
931   }
932 
933   public void testAllAsList_cancelled() throws Exception {
934     SingleCallListener listener = new SingleCallListener();
935     SettableFuture<String> future1 = SettableFuture.create();
936     SettableFuture<String> future2 = SettableFuture.create();
937     @SuppressWarnings("unchecked") // array is never modified
938     ListenableFuture<List<String>> compound =
939         Futures.allAsList(future1, future2);
940     compound.addListener(listener, directExecutor());
941 
942     listener.expectCall();
943     future1.cancel(true);
944     assertTrue(compound.isDone());
945     assertTrue(listener.wasCalled());
946     future2.setException(new Throwable("failed2"));
947 
948     try {
949       compound.get();
950       fail("Expected exception not thrown");
951     } catch (CancellationException e) {
952       // Expected
953     }
954   }
955 
956   public void testAllAsList_resultCancelled() throws Exception {
957     SettableFuture<String> future1 = SettableFuture.create();
958     SettableFuture<String> future2 = SettableFuture.create();
959     @SuppressWarnings("unchecked") // array is never modified
960     ListenableFuture<List<String>> compound =
961         Futures.allAsList(future1, future2);
962 
963     future2.set(DATA2);
964     assertFalse(compound.isDone());
965     assertTrue(compound.cancel(false));
966     assertTrue(compound.isCancelled());
967     assertTrue(future1.isCancelled());
968     assertFalse(future1.wasInterrupted());
969   }
970 
971   public void testAllAsList_resultInterrupted() throws Exception {
972     SettableFuture<String> future1 = SettableFuture.create();
973     SettableFuture<String> future2 = SettableFuture.create();
974     @SuppressWarnings("unchecked") // array is never modified
975     ListenableFuture<List<String>> compound =
976         Futures.allAsList(future1, future2);
977 
978     future2.set(DATA2);
979     assertFalse(compound.isDone());
980     assertTrue(compound.cancel(true));
981     assertTrue(compound.isCancelled());
982     assertTrue(future1.isCancelled());
983     assertTrue(future1.wasInterrupted());
984   }
985 
986   /**
987    * Test the case where the futures are fulfilled prior to
988    * constructing the ListFuture.  There was a bug where the
989    * loop that connects a Listener to each of the futures would die
990    * on the last loop-check as done() on ListFuture nulled out the
991    * variable being looped over (the list of futures).
992    */
993   public void testAllAsList_doneFutures() throws Exception {
994     // Create input and output
995     SettableFuture<String> future1 = SettableFuture.create();
996     SettableFuture<String> future2 = SettableFuture.create();
997     SettableFuture<String> future3 = SettableFuture.create();
998 
999     // Satisfy each input prior to creating compound and check the output
1000     future1.set(DATA1);
1001     future2.set(DATA2);
1002     future3.set(DATA3);
1003 
1004     @SuppressWarnings("unchecked") // array is never modified
1005     ListenableFuture<List<String>> compound =
1006         Futures.allAsList(future1, future2, future3);
1007 
1008     // Attach a listener
1009     SingleCallListener listener = new SingleCallListener();
1010     listener.expectCall();
1011     compound.addListener(listener, directExecutor());
1012 
1013     assertTrue(compound.isDone());
1014     assertTrue(listener.wasCalled());
1015 
1016     List<String> results = compound.get();
1017     assertThat(results).has().exactly(DATA1, DATA2, DATA3).inOrder();
1018   }
1019 
1020   /**
1021    * A single non-error failure is not logged because it is reported via the output future.
1022    */
1023   @SuppressWarnings("unchecked")
1024   public void testAllAsList_logging_exception() throws Exception {
1025     try {
1026       Futures.allAsList(immediateFailedFuture(new MyException())).get();
1027       fail();
1028     } catch (ExecutionException e) {
1029       assertTrue(e.getCause() instanceof MyException);
1030       assertEquals("Nothing should be logged", 0,
1031           combinedFutureLogHandler.getStoredLogRecords().size());
1032     }
1033   }
1034 
1035   /**
1036    * Ensure that errors are always logged.
1037    */
1038   @SuppressWarnings("unchecked")
1039   public void testAllAsList_logging_error() throws Exception {
1040     try {
1041       Futures.allAsList(immediateFailedFuture(new MyError())).get();
1042       fail();
1043     } catch (ExecutionException e) {
1044       assertTrue(e.getCause() instanceof MyError);
1045       List<LogRecord> logged = combinedFutureLogHandler.getStoredLogRecords();
1046       assertEquals(1, logged.size());  // errors are always logged
1047       assertTrue(logged.get(0).getThrown() instanceof MyError);
1048     }
1049   }
1050 
1051   /**
1052    * All as list will log extra exceptions that occur after failure.
1053    */
1054   @SuppressWarnings("unchecked")
1055   public void testAllAsList_logging_multipleExceptions() throws Exception {
1056     try {
1057       Futures.allAsList(immediateFailedFuture(new MyException()),
1058           immediateFailedFuture(new MyException())).get();
1059       fail();
1060     } catch (ExecutionException e) {
1061       assertTrue(e.getCause() instanceof MyException);
1062       List<LogRecord> logged = combinedFutureLogHandler.getStoredLogRecords();
1063       assertEquals(1, logged.size());  // the second failure is logged
1064       assertTrue(logged.get(0).getThrown() instanceof MyException);
1065     }
1066   }
1067 
1068   private static String createCombinedResult(Integer i, Boolean b) {
1069     return "-" + i + "-" + b;
1070   }
1071 
1072   /*
1073    * TODO(cpovirk): maybe pass around TestFuture instances instead of
1074    * ListenableFuture instances
1075    */
1076   /**
1077    * A future in {@link TestFutureBatch} that also has a name for debugging
1078    * purposes and a {@code finisher}, a task that will complete the future in
1079    * some fashion when it is called, allowing for testing both before and after
1080    * the completion of the future.
1081    */
1082   private static final class TestFuture {
1083     final ListenableFuture<String> future;
1084     final String name;
1085     final Runnable finisher;
1086 
1087     TestFuture(
1088         ListenableFuture<String> future, String name, Runnable finisher) {
1089       this.future = future;
1090       this.name = name;
1091       this.finisher = finisher;
1092     }
1093   }
1094 
1095   /**
1096    * A collection of several futures, covering cancellation, success, and
1097    * failure (both {@link ExecutionException} and {@link RuntimeException}),
1098    * both immediate and delayed. We use each possible pair of these futures in
1099    * {@link FuturesTest#runExtensiveMergerTest}.
1100    *
1101    * <p>Each test requires a new {@link TestFutureBatch} because we need new
1102    * delayed futures each time, as the old delayed futures were completed as
1103    * part of the old test.
1104    */
1105   private static final class TestFutureBatch {
1106     final ListenableFuture<String> doneSuccess = immediateFuture("a");
1107     final ListenableFuture<String> doneFailed =
1108         immediateFailedFuture(new Exception());
1109     final SettableFuture<String> doneCancelled = SettableFuture.create();
1110     {
1111       doneCancelled.cancel(true);
1112     }
1113 
1114     final ListenableFuture<String> doneRuntimeException =
1115         new ForwardingListenableFuture<String>() {
1116           final ListenableFuture<String> delegate =
1117               immediateFuture("Should never be seen");
1118 
1119           @Override
1120           protected ListenableFuture<String> delegate() {
1121             return delegate;
1122           }
1123 
1124           @Override
1125           public String get() {
1126             throw new RuntimeException();
1127           }
1128 
1129           @Override
1130           public String get(long timeout, TimeUnit unit) {
1131             throw new RuntimeException();
1132           }
1133     };
1134 
1135     final SettableFuture<String> delayedSuccess = SettableFuture.create();
1136     final SettableFuture<String> delayedFailed = SettableFuture.create();
1137     final SettableFuture<String> delayedCancelled = SettableFuture.create();
1138 
1139     final SettableFuture<String> delegateForDelayedRuntimeException =
1140         SettableFuture.create();
1141     final ListenableFuture<String> delayedRuntimeException =
1142         new ForwardingListenableFuture<String>() {
1143           @Override
1144           protected ListenableFuture<String> delegate() {
1145             return delegateForDelayedRuntimeException;
1146           }
1147 
1148           @Override
1149           public String get() throws ExecutionException, InterruptedException {
1150             delegateForDelayedRuntimeException.get();
1151             throw new RuntimeException();
1152           }
1153 
1154           @Override
1155           public String get(long timeout, TimeUnit unit) throws
1156               ExecutionException, InterruptedException, TimeoutException {
1157             delegateForDelayedRuntimeException.get(timeout, unit);
1158             throw new RuntimeException();
1159           }
1160     };
1161 
1162     final Runnable doNothing = new Runnable() {
1163       @Override
1164       public void run() {
1165       }
1166     };
1167     final Runnable finishSuccess = new Runnable() {
1168       @Override
1169       public void run() {
1170         delayedSuccess.set("b");
1171       }
1172     };
1173     final Runnable finishFailure = new Runnable() {
1174       @Override
1175       public void run() {
1176         delayedFailed.setException(new Exception());
1177       }
1178     };
1179     final Runnable finishCancelled = new Runnable() {
1180       @Override
1181       public void run() {
1182         delayedCancelled.cancel(true);
1183       }
1184     };
1185     final Runnable finishRuntimeException = new Runnable() {
1186       @Override
1187       public void run() {
1188         delegateForDelayedRuntimeException.set("Should never be seen");
1189       }
1190     };
1191 
1192     /**
1193      * All the futures, together with human-readable names for use by
1194      * {@link #smartToString}.
1195      */
1196     final ImmutableList<TestFuture> allFutures =
1197         ImmutableList.of(new TestFuture(doneSuccess, "doneSuccess", doNothing),
1198             new TestFuture(doneFailed, "doneFailed", doNothing),
1199             new TestFuture(doneCancelled, "doneCancelled", doNothing),
1200             new TestFuture(
1201                 doneRuntimeException, "doneRuntimeException", doNothing),
1202             new TestFuture(delayedSuccess, "delayedSuccess", finishSuccess),
1203             new TestFuture(delayedFailed, "delayedFailed", finishFailure),
1204             new TestFuture(
1205                 delayedCancelled, "delayedCancelled", finishCancelled),
1206             new TestFuture(delayedRuntimeException, "delayedRuntimeException",
1207                 finishRuntimeException));
1208 
1209     final Function<ListenableFuture<String>, String> nameGetter =
1210       new Function<ListenableFuture<String>, String>() {
1211         @Override
1212         public String apply(ListenableFuture<String> input) {
1213           for (TestFuture future : allFutures) {
1214             if (future.future == input) {
1215               return future.name;
1216             }
1217           }
1218           throw new IllegalArgumentException(input.toString());
1219         }
1220       };
1221 
1222     static boolean intersect(Set<?> a, Set<?> b) {
1223       return !Sets.intersection(a, b).isEmpty();
1224     }
1225 
1226     /**
1227      * Like {@code inputs.toString()}, but with the nonsense {@code toString}
1228      * representations replaced with the name of each future from
1229      * {@link #allFutures}.
1230      */
1231     String smartToString(ImmutableSet<ListenableFuture<String>> inputs) {
1232       Iterable<String> inputNames = Iterables.transform(inputs, nameGetter);
1233       return Joiner.on(", ").join(inputNames);
1234     }
1235 
1236     void smartAssertTrue(ImmutableSet<ListenableFuture<String>> inputs,
1237         Exception cause, boolean expression) {
1238       if (!expression) {
1239         failWithCause(cause, smartToString(inputs));
1240       }
1241     }
1242 
1243     boolean hasDelayed(ListenableFuture<String> a, ListenableFuture<String> b) {
1244       ImmutableSet<ListenableFuture<String>> inputs = ImmutableSet.of(a, b);
1245       return intersect(inputs, ImmutableSet.of(
1246           delayedSuccess, delayedFailed, delayedCancelled,
1247           delayedRuntimeException));
1248     }
1249 
1250     void assertHasDelayed(
1251         ListenableFuture<String> a, ListenableFuture<String> b, Exception e) {
1252       ImmutableSet<ListenableFuture<String>> inputs = ImmutableSet.of(a, b);
1253       smartAssertTrue(inputs, e, hasDelayed(a, b));
1254     }
1255 
1256     void assertHasFailure(
1257         ListenableFuture<String> a, ListenableFuture<String> b, Exception e) {
1258       ImmutableSet<ListenableFuture<String>> inputs = ImmutableSet.of(a, b);
1259       smartAssertTrue(inputs, e, intersect(inputs, ImmutableSet.of(doneFailed,
1260           doneRuntimeException, delayedFailed, delayedRuntimeException)));
1261     }
1262 
1263     void assertHasCancel(
1264         ListenableFuture<String> a, ListenableFuture<String> b, Exception e) {
1265       ImmutableSet<ListenableFuture<String>> inputs = ImmutableSet.of(a, b);
1266       smartAssertTrue(inputs, e,
1267           intersect(inputs, ImmutableSet.of(doneCancelled, delayedCancelled)));
1268     }
1269 
1270     void assertHasImmediateFailure(
1271         ListenableFuture<String> a, ListenableFuture<String> b, Exception e) {
1272       ImmutableSet<ListenableFuture<String>> inputs = ImmutableSet.of(a, b);
1273       smartAssertTrue(inputs, e, intersect(
1274           inputs, ImmutableSet.of(doneFailed, doneRuntimeException)));
1275     }
1276 
1277     void assertHasImmediateCancel(
1278         ListenableFuture<String> a, ListenableFuture<String> b, Exception e) {
1279       ImmutableSet<ListenableFuture<String>> inputs = ImmutableSet.of(a, b);
1280       smartAssertTrue(inputs, e,
1281           intersect(inputs, ImmutableSet.of(doneCancelled)));
1282     }
1283   }
1284 
1285   /**
1286    * {@link Futures#allAsList(Iterable)} or
1287    * {@link Futures#successfulAsList(Iterable)}, hidden behind a common
1288    * interface for testing.
1289    */
1290   private interface Merger {
1291     ListenableFuture<List<String>> merged(
1292         ListenableFuture<String> a, ListenableFuture<String> b);
1293 
1294     Merger allMerger = new Merger() {
1295       @Override
1296       public ListenableFuture<List<String>> merged(
1297           ListenableFuture<String> a, ListenableFuture<String> b) {
1298         return allAsList(ImmutableSet.of(a, b));
1299       }
1300     };
1301     Merger successMerger = new Merger() {
1302       @Override
1303       public ListenableFuture<List<String>> merged(
1304           ListenableFuture<String> a, ListenableFuture<String> b) {
1305         return successfulAsList(ImmutableSet.of(a, b));
1306       }
1307     };
1308   }
1309 
1310   /**
1311    * Very rough equivalent of a timed get, produced by calling the no-arg get
1312    * method in another thread and waiting a short time for it.
1313    *
1314    * <p>We need this to test the behavior of no-arg get methods without hanging
1315    * the main test thread forever in the case of failure.
1316    */
1317   private static <V> V pseudoTimedGet(
1318       final Future<V> input, long timeout, TimeUnit unit)
1319       throws InterruptedException, ExecutionException, TimeoutException {
1320     ExecutorService executor = newSingleThreadExecutor();
1321     Future<V> waiter = executor.submit(new Callable<V>() {
1322       @Override
1323       public V call() throws Exception {
1324         return input.get();
1325       }
1326     });
1327 
1328     try {
1329       return waiter.get(timeout, unit);
1330     } catch (ExecutionException e) {
1331       propagateIfInstanceOf(e.getCause(), ExecutionException.class);
1332       propagateIfInstanceOf(e.getCause(), CancellationException.class);
1333       AssertionFailedError error =
1334           new AssertionFailedError("Unexpected exception");
1335       error.initCause(e);
1336       throw error;
1337     } finally {
1338       executor.shutdownNow();
1339       assertTrue(executor.awaitTermination(10, SECONDS));
1340     }
1341   }
1342 
1343   /**
1344    * For each possible pair of futures from {@link TestFutureBatch}, for each
1345    * possible completion order of those futures, test that various get calls
1346    * (timed before future completion, untimed before future completion, and
1347    * untimed after future completion) return or throw the proper values.
1348    */
1349   private static void runExtensiveMergerTest(Merger merger)
1350       throws InterruptedException {
1351     int inputCount = new TestFutureBatch().allFutures.size();
1352 
1353     for (int i = 0; i < inputCount; i++) {
1354       for (int j = 0; j < inputCount; j++) {
1355         for (boolean iBeforeJ : new boolean[] { true, false }) {
1356           TestFutureBatch inputs = new TestFutureBatch();
1357           ListenableFuture<String> iFuture = inputs.allFutures.get(i).future;
1358           ListenableFuture<String> jFuture = inputs.allFutures.get(j).future;
1359           ListenableFuture<List<String>> future =
1360               merger.merged(iFuture, jFuture);
1361 
1362           // Test timed get before we've completed any delayed futures.
1363           try {
1364             List<String> result = future.get(0, MILLISECONDS);
1365             assertTrue("Got " + result,
1366                 Arrays.asList("a", null).containsAll(result));
1367           } catch (CancellationException e) {
1368             assertTrue(merger == Merger.allMerger);
1369             inputs.assertHasImmediateCancel(iFuture, jFuture, e);
1370           } catch (ExecutionException e) {
1371             assertTrue(merger == Merger.allMerger);
1372             inputs.assertHasImmediateFailure(iFuture, jFuture, e);
1373           } catch (TimeoutException e) {
1374             inputs.assertHasDelayed(iFuture, jFuture, e);
1375           }
1376 
1377           // Same tests with pseudoTimedGet.
1378           try {
1379             List<String> result = conditionalPseudoTimedGet(
1380                 inputs, iFuture, jFuture, future, 20, MILLISECONDS);
1381             assertTrue("Got " + result,
1382                 Arrays.asList("a", null).containsAll(result));
1383           } catch (CancellationException e) {
1384             assertTrue(merger == Merger.allMerger);
1385             inputs.assertHasImmediateCancel(iFuture, jFuture, e);
1386           } catch (ExecutionException e) {
1387             assertTrue(merger == Merger.allMerger);
1388             inputs.assertHasImmediateFailure(iFuture, jFuture, e);
1389           } catch (TimeoutException e) {
1390             inputs.assertHasDelayed(iFuture, jFuture, e);
1391           }
1392 
1393           // Finish the two futures in the currently specified order:
1394           inputs.allFutures.get(iBeforeJ ? i : j).finisher.run();
1395           inputs.allFutures.get(iBeforeJ ? j : i).finisher.run();
1396 
1397           // Test untimed get now that we've completed any delayed futures.
1398           try {
1399             List<String> result = future.get();
1400             assertTrue("Got " + result,
1401                 Arrays.asList("a", "b", null).containsAll(result));
1402           } catch (CancellationException e) {
1403             assertTrue(merger == Merger.allMerger);
1404             inputs.assertHasCancel(iFuture, jFuture, e);
1405           } catch (ExecutionException e) {
1406             assertTrue(merger == Merger.allMerger);
1407             inputs.assertHasFailure(iFuture, jFuture, e);
1408           }
1409         }
1410       }
1411     }
1412   }
1413 
1414   /**
1415    * Call the non-timed {@link Future#get()} in a way that allows us to abort if
1416    * it's expected to hang forever. More precisely, if it's expected to return,
1417    * we simply call it[*], but if it's expected to hang (because one of the
1418    * input futures that we know makes it up isn't done yet), then we call it in
1419    * a separate thread (using pseudoTimedGet). The result is that we wait as
1420    * long as necessary when the method is expected to return (at the cost of
1421    * hanging forever if there is a bug in the class under test) but that we time
1422    * out fairly promptly when the method is expected to hang (possibly too
1423    * quickly, but too-quick failures should be very unlikely, given that we used
1424    * to bail after 20ms during the expected-successful tests, and there we saw a
1425    * failure rate of ~1/5000, meaning that the other thread's get() call nearly
1426    * always completes within 20ms if it's going to complete at all).
1427    *
1428    * [*] To avoid hangs, I've disabled the in-thread calls. This makes the test
1429    * take (very roughly) 2.5s longer. (2.5s is also the maximum length of time
1430    * we will wait for a timed get that is expected to succeed; the fact that the
1431    * numbers match is only a coincidence.) See the comment below for how to
1432    * restore the fast but hang-y version.
1433    */
1434   private static List<String> conditionalPseudoTimedGet(
1435       TestFutureBatch inputs,
1436       ListenableFuture<String> iFuture,
1437       ListenableFuture<String> jFuture,
1438       ListenableFuture<List<String>> future,
1439       int timeout,
1440       TimeUnit unit)
1441       throws InterruptedException, ExecutionException, TimeoutException {
1442     /*
1443      * For faster tests (that may hang indefinitely if the class under test has
1444      * a bug!), switch the second branch to call untimed future.get() instead of
1445      * pseudoTimedGet.
1446      */
1447     return (inputs.hasDelayed(iFuture, jFuture))
1448         ? pseudoTimedGet(future, timeout, unit)
1449         : pseudoTimedGet(future, 2500, MILLISECONDS);
1450   }
1451 
1452   public void testAllAsList_extensive() throws InterruptedException {
1453     runExtensiveMergerTest(Merger.allMerger);
1454   }
1455 
1456   public void testSuccessfulAsList_extensive() throws InterruptedException {
1457     runExtensiveMergerTest(Merger.successMerger);
1458   }
1459 
1460   public void testSuccessfulAsList() throws Exception {
1461     // Create input and output
1462     SettableFuture<String> future1 = SettableFuture.create();
1463     SettableFuture<String> future2 = SettableFuture.create();
1464     SettableFuture<String> future3 = SettableFuture.create();
1465     @SuppressWarnings("unchecked") // array is never modified
1466     ListenableFuture<List<String>> compound =
1467         Futures.successfulAsList(future1, future2, future3);
1468 
1469     // Attach a listener
1470     SingleCallListener listener = new SingleCallListener();
1471     compound.addListener(listener, directExecutor());
1472 
1473     // Satisfy each input and check the output
1474     assertFalse(compound.isDone());
1475     future1.set(DATA1);
1476     assertFalse(compound.isDone());
1477     future2.set(DATA2);
1478     assertFalse(compound.isDone());
1479     listener.expectCall();
1480     future3.set(DATA3);
1481     assertTrue(compound.isDone());
1482     assertTrue(listener.wasCalled());
1483 
1484     List<String> results = compound.get();
1485     assertThat(results).has().exactly(DATA1, DATA2, DATA3).inOrder();
1486   }
1487 
1488   public void testSuccessfulAsList_emptyList() throws Exception {
1489     SingleCallListener listener = new SingleCallListener();
1490     listener.expectCall();
1491     List<ListenableFuture<String>> futures = ImmutableList.of();
1492     ListenableFuture<List<String>> compound = Futures.successfulAsList(futures);
1493     compound.addListener(listener, directExecutor());
1494     assertTrue(compound.isDone());
1495     assertTrue(compound.get().isEmpty());
1496     assertTrue(listener.wasCalled());
1497   }
1498 
1499   public void testSuccessfulAsList_emptyArray() throws Exception {
1500     SingleCallListener listener = new SingleCallListener();
1501     listener.expectCall();
1502     @SuppressWarnings("unchecked") // array is never modified
1503     ListenableFuture<List<String>> compound = Futures.successfulAsList();
1504     compound.addListener(listener, directExecutor());
1505     assertTrue(compound.isDone());
1506     assertTrue(compound.get().isEmpty());
1507     assertTrue(listener.wasCalled());
1508   }
1509 
1510   public void testSuccessfulAsList_partialFailure() throws Exception {
1511     SingleCallListener listener = new SingleCallListener();
1512     SettableFuture<String> future1 = SettableFuture.create();
1513     SettableFuture<String> future2 = SettableFuture.create();
1514     @SuppressWarnings("unchecked") // array is never modified
1515     ListenableFuture<List<String>> compound =
1516         Futures.successfulAsList(future1, future2);
1517     compound.addListener(listener, directExecutor());
1518 
1519     assertFalse(compound.isDone());
1520     future1.setException(new Throwable("failed1"));
1521     assertFalse(compound.isDone());
1522     listener.expectCall();
1523     future2.set(DATA2);
1524     assertTrue(compound.isDone());
1525     assertTrue(listener.wasCalled());
1526 
1527     List<String> results = compound.get();
1528     assertThat(results).has().exactly(null, DATA2).inOrder();
1529   }
1530 
1531   public void testSuccessfulAsList_totalFailure() throws Exception {
1532     SingleCallListener listener = new SingleCallListener();
1533     SettableFuture<String> future1 = SettableFuture.create();
1534     SettableFuture<String> future2 = SettableFuture.create();
1535     @SuppressWarnings("unchecked") // array is never modified
1536     ListenableFuture<List<String>> compound =
1537         Futures.successfulAsList(future1, future2);
1538     compound.addListener(listener, directExecutor());
1539 
1540     assertFalse(compound.isDone());
1541     future1.setException(new Throwable("failed1"));
1542     assertFalse(compound.isDone());
1543     listener.expectCall();
1544     future2.setException(new Throwable("failed2"));
1545     assertTrue(compound.isDone());
1546     assertTrue(listener.wasCalled());
1547 
1548     List<String> results = compound.get();
1549     assertThat(results).has().exactly(null, null).inOrder();
1550   }
1551 
1552   public void testSuccessfulAsList_cancelled() throws Exception {
1553     SingleCallListener listener = new SingleCallListener();
1554     SettableFuture<String> future1 = SettableFuture.create();
1555     SettableFuture<String> future2 = SettableFuture.create();
1556     @SuppressWarnings("unchecked") // array is never modified
1557     ListenableFuture<List<String>> compound =
1558         Futures.successfulAsList(future1, future2);
1559     compound.addListener(listener, directExecutor());
1560 
1561     assertFalse(compound.isDone());
1562     future1.cancel(true);
1563     assertFalse(compound.isDone());
1564     listener.expectCall();
1565     future2.set(DATA2);
1566     assertTrue(compound.isDone());
1567     assertTrue(listener.wasCalled());
1568 
1569     List<String> results = compound.get();
1570     assertThat(results).has().exactly(null, DATA2).inOrder();
1571   }
1572 
1573   public void testSuccessfulAsList_resultCancelled() throws Exception {
1574     SettableFuture<String> future1 = SettableFuture.create();
1575     SettableFuture<String> future2 = SettableFuture.create();
1576     @SuppressWarnings("unchecked") // array is never modified
1577     ListenableFuture<List<String>> compound =
1578         Futures.successfulAsList(future1, future2);
1579 
1580     future2.set(DATA2);
1581     assertFalse(compound.isDone());
1582     assertTrue(compound.cancel(false));
1583     assertTrue(compound.isCancelled());
1584     assertTrue(future1.isCancelled());
1585     assertFalse(future1.wasInterrupted());
1586   }
1587 
1588   public void testSuccessfulAsList_resultCancelledRacingInputDone()
1589       throws Exception {
1590     /*
1591      * The IllegalStateException that we're testing for is caught by
1592      * ExecutionList and logged rather than allowed to propagate. We need to
1593      * turn that back into a failure.
1594      */
1595     Handler throwingHandler = new Handler() {
1596       @Override public void publish(@Nullable LogRecord record) {
1597         AssertionFailedError error = new AssertionFailedError();
1598         error.initCause(record.getThrown());
1599         throw error;
1600       }
1601 
1602       @Override public void flush() {}
1603 
1604       @Override public void close() {}
1605     };
1606 
1607     ExecutionList.log.addHandler(throwingHandler);
1608     try {
1609       doTestSuccessfulAsList_resultCancelledRacingInputDone();
1610     } finally {
1611       ExecutionList.log.removeHandler(throwingHandler);
1612     }
1613   }
1614 
1615   private static void doTestSuccessfulAsList_resultCancelledRacingInputDone()
1616       throws Exception {
1617     // Simple (combined.cancel -> input.cancel -> setOneValue):
1618     Futures.successfulAsList(ImmutableList.of(SettableFuture.create()))
1619         .cancel(true);
1620 
1621     /*
1622      * Complex (combined.cancel -> input.cancel -> other.set -> setOneValue),
1623      * to show that this isn't just about problems with the input future we just
1624      * cancelled:
1625      */
1626     final SettableFuture<String> future1 = SettableFuture.create();
1627     final SettableFuture<String> future2 = SettableFuture.create();
1628     @SuppressWarnings("unchecked") // array is never modified
1629     ListenableFuture<List<String>> compound =
1630         Futures.successfulAsList(future1, future2);
1631 
1632     future1.addListener(new Runnable() {
1633       @Override public void run() {
1634         assertTrue(future1.isCancelled());
1635         /*
1636          * This test relies on behavior that's unspecified but currently
1637          * guaranteed by the implementation: Cancellation of inputs is
1638          * performed in the order they were provided to the constructor. Verify
1639          * that as a sanity check:
1640          */
1641         assertFalse(future2.isCancelled());
1642         // Now attempt to trigger the exception:
1643         future2.set(DATA2);
1644       }
1645     }, directExecutor());
1646     assertTrue(compound.cancel(false));
1647     assertTrue(compound.isCancelled());
1648     assertTrue(future1.isCancelled());
1649     assertFalse(future2.isCancelled());
1650 
1651     try {
1652       compound.get();
1653       fail("Expected exception not thrown");
1654     } catch (CancellationException e) {
1655       // Expected
1656     }
1657   }
1658 
1659   public void testSuccessfulAsList_resultInterrupted() throws Exception {
1660     SettableFuture<String> future1 = SettableFuture.create();
1661     SettableFuture<String> future2 = SettableFuture.create();
1662     @SuppressWarnings("unchecked") // array is never modified
1663     ListenableFuture<List<String>> compound =
1664         Futures.successfulAsList(future1, future2);
1665 
1666     future2.set(DATA2);
1667     assertFalse(compound.isDone());
1668     assertTrue(compound.cancel(true));
1669     assertTrue(compound.isCancelled());
1670     assertTrue(future1.isCancelled());
1671     assertTrue(future1.wasInterrupted());
1672   }
1673 
1674   public void testSuccessfulAsList_mixed() throws Exception {
1675     SingleCallListener listener = new SingleCallListener();
1676     SettableFuture<String> future1 = SettableFuture.create();
1677     SettableFuture<String> future2 = SettableFuture.create();
1678     SettableFuture<String> future3 = SettableFuture.create();
1679     @SuppressWarnings("unchecked") // array is never modified
1680     ListenableFuture<List<String>> compound =
1681         Futures.successfulAsList(future1, future2, future3);
1682     compound.addListener(listener, directExecutor());
1683 
1684     // First is cancelled, second fails, third succeeds
1685     assertFalse(compound.isDone());
1686     future1.cancel(true);
1687     assertFalse(compound.isDone());
1688     future2.setException(new Throwable("failed2"));
1689     assertFalse(compound.isDone());
1690     listener.expectCall();
1691     future3.set(DATA3);
1692     assertTrue(compound.isDone());
1693     assertTrue(listener.wasCalled());
1694 
1695     List<String> results = compound.get();
1696     assertThat(results).has().exactly(null, null, DATA3).inOrder();
1697   }
1698 
1699   /** Non-Error exceptions are never logged. */
1700   @SuppressWarnings("unchecked")
1701   public void testSuccessfulAsList_logging_exception() throws Exception {
1702     assertEquals(Lists.newArrayList((Object) null),
1703         Futures.successfulAsList(
1704             immediateFailedFuture(new MyException())).get());
1705     assertEquals("Nothing should be logged", 0,
1706         combinedFutureLogHandler.getStoredLogRecords().size());
1707 
1708     // Not even if there are a bunch of failures.
1709     assertEquals(Lists.newArrayList(null, null, null),
1710         Futures.successfulAsList(
1711             immediateFailedFuture(new MyException()),
1712             immediateFailedFuture(new MyException()),
1713             immediateFailedFuture(new MyException())).get());
1714     assertEquals("Nothing should be logged", 0,
1715         combinedFutureLogHandler.getStoredLogRecords().size());
1716   }
1717 
1718   /**
1719    * Ensure that errors are always logged.
1720    */
1721   @SuppressWarnings("unchecked")
1722   public void testSuccessfulAsList_logging_error() throws Exception {
1723     assertEquals(Lists.newArrayList((Object) null),
1724         Futures.successfulAsList(
1725             immediateFailedFuture(new MyError())).get());
1726     List<LogRecord> logged = combinedFutureLogHandler.getStoredLogRecords();
1727     assertEquals(1, logged.size());  // errors are always logged
1728     assertTrue(logged.get(0).getThrown() instanceof MyError);
1729   }
1730 
1731   public void testNonCancellationPropagating_successful() throws Exception {
1732     SettableFuture<Foo> input = SettableFuture.create();
1733     ListenableFuture<Foo> wrapper = Futures.nonCancellationPropagating(input);
1734     Foo foo = new Foo();
1735 
1736     assertFalse(wrapper.isDone());
1737     input.set(foo);
1738     assertTrue(wrapper.isDone());
1739     assertSame(foo, wrapper.get());
1740   }
1741 
1742   public void testNonCancellationPropagating_failure() throws Exception {
1743     SettableFuture<Foo> input = SettableFuture.create();
1744     ListenableFuture<Foo> wrapper = Futures.nonCancellationPropagating(input);
1745     Throwable failure = new Throwable("thrown");
1746 
1747     assertFalse(wrapper.isDone());
1748     input.setException(failure);
1749     assertTrue(wrapper.isDone());
1750     try {
1751       wrapper.get();
1752       fail("Expected ExecutionException");
1753     } catch (ExecutionException e) {
1754       assertSame(failure, e.getCause());
1755     }
1756   }
1757 
1758   public void testNonCancellationPropagating_delegateCancelled() throws Exception {
1759     SettableFuture<Foo> input = SettableFuture.create();
1760     ListenableFuture<Foo> wrapper = Futures.nonCancellationPropagating(input);
1761 
1762     assertFalse(wrapper.isDone());
1763     assertTrue(input.cancel(false));
1764     assertTrue(wrapper.isCancelled());
1765   }
1766 
1767   public void testNonCancellationPropagating_doesNotPropagate() throws Exception {
1768     SettableFuture<Foo> input = SettableFuture.create();
1769     ListenableFuture<Foo> wrapper = Futures.nonCancellationPropagating(input);
1770 
1771     assertTrue(wrapper.cancel(true));
1772     assertTrue(wrapper.isCancelled());
1773     assertTrue(wrapper.isDone());
1774     assertFalse(input.isCancelled());
1775     assertFalse(input.isDone());
1776   }
1777 
1778   private static class TestException extends Exception {
1779     TestException(@Nullable Throwable cause) {
1780       super(cause);
1781     }
1782   }
1783 
1784   private static final Function<Exception, TestException> mapper =
1785       new Function<Exception, TestException>() {
1786     @Override public TestException apply(Exception from) {
1787       if (from instanceof ExecutionException) {
1788         return new TestException(from.getCause());
1789       } else {
1790         assertTrue("got " + from.getClass(),
1791             from instanceof InterruptedException
1792                 || from instanceof CancellationException);
1793         return new TestException(from);
1794       }
1795     }
1796   };
1797 
1798   public void testMakeChecked_mapsExecutionExceptions() throws Exception {
1799     SettableFuture<String> future = SettableFuture.create();
1800 
1801     CheckedFuture<String, TestException> checked = Futures.makeChecked(
1802         future, mapper);
1803 
1804     future.setException(new IOException("checked"));
1805 
1806     assertTrue(checked.isDone());
1807     assertFalse(checked.isCancelled());
1808 
1809     try {
1810       checked.get();
1811       fail();
1812     } catch (ExecutionException e) {
1813       assertTrue(e.getCause() instanceof IOException);
1814     }
1815 
1816     try {
1817       checked.get(5, TimeUnit.SECONDS);
1818       fail();
1819     } catch (ExecutionException e) {
1820       assertTrue(e.getCause() instanceof IOException);
1821     }
1822 
1823     try {
1824       checked.checkedGet();
1825       fail();
1826     } catch (TestException e) {
1827       assertTrue(e.getCause() instanceof IOException);
1828     }
1829 
1830     try {
1831       checked.checkedGet(5, TimeUnit.SECONDS);
1832       fail();
1833     } catch (TestException e) {
1834       assertTrue(e.getCause() instanceof IOException);
1835     }
1836   }
1837 
1838   public void testMakeChecked_mapsInterruption() throws Exception {
1839     SettableFuture<String> future = SettableFuture.create();
1840 
1841     CheckedFuture<String, TestException> checked = Futures.makeChecked(
1842         future, mapper);
1843 
1844     Thread.currentThread().interrupt();
1845 
1846     try {
1847       checked.get();
1848       fail();
1849     } catch (InterruptedException e) {
1850       // Expected.
1851     }
1852 
1853     Thread.currentThread().interrupt();
1854 
1855     try {
1856       checked.get(5, TimeUnit.SECONDS);
1857       fail();
1858     } catch (InterruptedException e) {
1859       // Expected.
1860     }
1861 
1862     Thread.currentThread().interrupt();
1863 
1864     try {
1865       checked.checkedGet();
1866       fail();
1867     } catch (TestException e) {
1868       assertTrue(e.getCause() instanceof InterruptedException);
1869     }
1870 
1871     Thread.currentThread().interrupt();
1872 
1873     try {
1874       checked.checkedGet(5, TimeUnit.SECONDS);
1875       fail();
1876     } catch (TestException e) {
1877       assertTrue(e.getCause() instanceof InterruptedException);
1878     }
1879   }
1880 
1881   public void testMakeChecked_mapsCancellation() throws Exception {
1882     SettableFuture<String> future = SettableFuture.create();
1883 
1884     CheckedFuture<String, TestException> checked = Futures.makeChecked(
1885         future, mapper);
1886 
1887     assertTrue(future.cancel(true)); // argument is ignored
1888 
1889     try {
1890       checked.get();
1891       fail();
1892     } catch (CancellationException expected) {}
1893 
1894     try {
1895       checked.get(5, TimeUnit.SECONDS);
1896       fail();
1897     } catch (CancellationException expected) {}
1898 
1899     try {
1900       checked.checkedGet();
1901       fail();
1902     } catch (TestException expected) {
1903       assertTrue(expected.getCause() instanceof CancellationException);
1904     }
1905 
1906     try {
1907       checked.checkedGet(5, TimeUnit.SECONDS);
1908       fail();
1909     } catch (TestException expected) {
1910       assertTrue(expected.getCause() instanceof CancellationException);
1911     }
1912   }
1913 
1914   public void testMakeChecked_propagatesFailedMappers() throws Exception {
1915     SettableFuture<String> future = SettableFuture.create();
1916 
1917     CheckedFuture<String, TestException> checked = Futures.makeChecked(
1918         future, new Function<Exception, TestException>() {
1919           @Override public TestException apply(Exception from) {
1920             throw new NullPointerException();
1921           }
1922     });
1923 
1924     future.setException(new Exception("failed"));
1925 
1926     try {
1927       checked.checkedGet();
1928       fail();
1929     } catch (NullPointerException expected) {}
1930 
1931     try {
1932       checked.checkedGet(5, TimeUnit.SECONDS);
1933       fail();
1934     } catch (NullPointerException expected) {}
1935   }
1936 
1937   public void testMakeChecked_listenersRunOnceCompleted() throws Exception {
1938     SettableFuture<String> future = SettableFuture.create();
1939 
1940     CheckedFuture<String, TestException> checked = Futures.makeChecked(
1941         future, new Function<Exception, TestException>() {
1942           @Override public TestException apply(Exception from) {
1943             throw new NullPointerException();
1944           }
1945     });
1946 
1947     ListenableFutureTester tester = new ListenableFutureTester(checked);
1948     tester.setUp();
1949     future.set(DATA1);
1950     tester.testCompletedFuture(DATA1);
1951     tester.tearDown();
1952   }
1953 
1954   public void testMakeChecked_listenersRunOnCancel() throws Exception {
1955     SettableFuture<String> future = SettableFuture.create();
1956 
1957     CheckedFuture<String, TestException> checked = Futures.makeChecked(
1958         future, new Function<Exception, TestException>() {
1959           @Override public TestException apply(Exception from) {
1960             throw new NullPointerException();
1961           }
1962     });
1963 
1964     ListenableFutureTester tester = new ListenableFutureTester(checked);
1965     tester.setUp();
1966     future.cancel(true); // argument is ignored
1967     tester.testCancelledFuture();
1968     tester.tearDown();
1969   }
1970 
1971   public void testMakeChecked_listenersRunOnFailure() throws Exception {
1972     SettableFuture<String> future = SettableFuture.create();
1973 
1974     CheckedFuture<String, TestException> checked = Futures.makeChecked(
1975         future, new Function<Exception, TestException>() {
1976           @Override public TestException apply(Exception from) {
1977             throw new NullPointerException();
1978           }
1979     });
1980 
1981     ListenableFutureTester tester = new ListenableFutureTester(checked);
1982     tester.setUp();
1983     future.setException(new Exception("failed"));
1984     tester.testFailedFuture("failed");
1985     tester.tearDown();
1986   }
1987 
1988   private interface MapperFunction extends Function<Throwable, Exception> {}
1989 
1990   private static final class OtherThrowable extends Throwable {}
1991 
1992   private static final Exception CHECKED_EXCEPTION = new Exception("mymessage");
1993   private static final Future<String> FAILED_FUTURE_CHECKED_EXCEPTION =
1994       immediateFailedFuture(CHECKED_EXCEPTION);
1995   private static final RuntimeException UNCHECKED_EXCEPTION =
1996       new RuntimeException("mymessage");
1997   private static final Future<String> FAILED_FUTURE_UNCHECKED_EXCEPTION =
1998       immediateFailedFuture(UNCHECKED_EXCEPTION);
1999   private static final RuntimeException RUNTIME_EXCEPTION =
2000       new RuntimeException();
2001   private static final OtherThrowable OTHER_THROWABLE = new OtherThrowable();
2002   private static final Future<String> FAILED_FUTURE_OTHER_THROWABLE =
2003       immediateFailedFuture(OTHER_THROWABLE);
2004   private static final Error ERROR = new Error("mymessage");
2005   private static final Future<String> FAILED_FUTURE_ERROR =
2006       immediateFailedFuture(ERROR);
2007   private static final Future<String> RUNTIME_EXCEPTION_FUTURE =
2008       new SimpleForwardingFuture<String>(FAILED_FUTURE_CHECKED_EXCEPTION) {
2009         @Override public String get() {
2010           throw RUNTIME_EXCEPTION;
2011         }
2012 
2013         @Override public String get(long timeout, TimeUnit unit) {
2014           throw RUNTIME_EXCEPTION;
2015         }
2016       };
2017 
2018   // Boring untimed-get tests:
2019 
2020   public void testGetUntimed_success()
2021       throws TwoArgConstructorException {
2022     assertEquals("foo",
2023         get(immediateFuture("foo"), TwoArgConstructorException.class));
2024   }
2025 
2026   public void testGetUntimed_interrupted() {
2027     SettableFuture<String> future = SettableFuture.create();
2028     Thread.currentThread().interrupt();
2029     try {
2030       get(future, TwoArgConstructorException.class);
2031       fail();
2032     } catch (TwoArgConstructorException expected) {
2033       assertTrue(expected.getCause() instanceof InterruptedException);
2034       assertTrue(Thread.currentThread().isInterrupted());
2035     } finally {
2036       Thread.interrupted();
2037     }
2038   }
2039 
2040   public void testGetUntimed_cancelled()
2041       throws TwoArgConstructorException {
2042     SettableFuture<String> future = SettableFuture.create();
2043     future.cancel(true);
2044     try {
2045       get(future, TwoArgConstructorException.class);
2046       fail();
2047     } catch (CancellationException expected) {
2048     }
2049   }
2050 
2051   public void testGetUntimed_ExecutionExceptionChecked() {
2052     try {
2053       get(FAILED_FUTURE_CHECKED_EXCEPTION, TwoArgConstructorException.class);
2054       fail();
2055     } catch (TwoArgConstructorException expected) {
2056       assertEquals(CHECKED_EXCEPTION, expected.getCause());
2057     }
2058   }
2059 
2060   public void testGetUntimed_ExecutionExceptionUnchecked()
2061       throws TwoArgConstructorException {
2062     try {
2063       get(FAILED_FUTURE_UNCHECKED_EXCEPTION, TwoArgConstructorException.class);
2064       fail();
2065     } catch (UncheckedExecutionException expected) {
2066       assertEquals(UNCHECKED_EXCEPTION, expected.getCause());
2067     }
2068   }
2069 
2070   public void testGetUntimed_ExecutionExceptionError()
2071       throws TwoArgConstructorException {
2072     try {
2073       get(FAILED_FUTURE_ERROR, TwoArgConstructorException.class);
2074       fail();
2075     } catch (ExecutionError expected) {
2076       assertEquals(ERROR, expected.getCause());
2077     }
2078   }
2079 
2080   public void testGetUntimed_ExecutionExceptionOtherThrowable() {
2081     try {
2082       get(FAILED_FUTURE_OTHER_THROWABLE, TwoArgConstructorException.class);
2083       fail();
2084     } catch (TwoArgConstructorException expected) {
2085       assertEquals(OTHER_THROWABLE, expected.getCause());
2086     }
2087   }
2088 
2089   public void testGetUntimed_RuntimeException()
2090       throws TwoArgConstructorException {
2091     try {
2092       get(RUNTIME_EXCEPTION_FUTURE, TwoArgConstructorException.class);
2093       fail();
2094     } catch (RuntimeException expected) {
2095       assertEquals(RUNTIME_EXCEPTION, expected);
2096     }
2097   }
2098 
2099   public void testGetUntimed_badExceptionConstructor_wrapsOriginalChecked() throws Exception {
2100     try {
2101       get(FAILED_FUTURE_CHECKED_EXCEPTION, ExceptionWithBadConstructor.class);
2102       fail();
2103     } catch (IllegalArgumentException expected) {
2104       assertSame(CHECKED_EXCEPTION, expected.getCause());
2105     }
2106   }
2107 
2108   public void testGetUntimed_withGoodAndBadExceptionConstructor() throws Exception {
2109     try {
2110       get(FAILED_FUTURE_CHECKED_EXCEPTION, ExceptionWithGoodAndBadConstructor.class);
2111       fail();
2112     } catch (ExceptionWithGoodAndBadConstructor expected) {
2113       assertSame(CHECKED_EXCEPTION, expected.getCause());
2114     }
2115   }
2116 
2117   // Boring timed-get tests:
2118 
2119   public void testGetTimed_success()
2120       throws TwoArgConstructorException {
2121     assertEquals("foo", get(
2122         immediateFuture("foo"), 0, SECONDS, TwoArgConstructorException.class));
2123   }
2124 
2125   public void testGetTimed_interrupted() {
2126     SettableFuture<String> future = SettableFuture.create();
2127     Thread.currentThread().interrupt();
2128     try {
2129       get(future, 0, SECONDS, TwoArgConstructorException.class);
2130       fail();
2131     } catch (TwoArgConstructorException expected) {
2132       assertTrue(expected.getCause() instanceof InterruptedException);
2133       assertTrue(Thread.currentThread().isInterrupted());
2134     } finally {
2135       Thread.interrupted();
2136     }
2137   }
2138 
2139   public void testGetTimed_cancelled()
2140       throws TwoArgConstructorException {
2141     SettableFuture<String> future = SettableFuture.create();
2142     future.cancel(true);
2143     try {
2144       get(future, 0, SECONDS, TwoArgConstructorException.class);
2145       fail();
2146     } catch (CancellationException expected) {
2147     }
2148   }
2149 
2150   public void testGetTimed_ExecutionExceptionChecked() {
2151     try {
2152       get(FAILED_FUTURE_CHECKED_EXCEPTION, 0, SECONDS,
2153           TwoArgConstructorException.class);
2154       fail();
2155     } catch (TwoArgConstructorException expected) {
2156       assertEquals(CHECKED_EXCEPTION, expected.getCause());
2157     }
2158   }
2159 
2160   public void testGetTimed_ExecutionExceptionUnchecked()
2161       throws TwoArgConstructorException {
2162     try {
2163       get(FAILED_FUTURE_UNCHECKED_EXCEPTION, 0, SECONDS,
2164           TwoArgConstructorException.class);
2165       fail();
2166     } catch (UncheckedExecutionException expected) {
2167       assertEquals(UNCHECKED_EXCEPTION, expected.getCause());
2168     }
2169   }
2170 
2171   public void testGetTimed_ExecutionExceptionError()
2172       throws TwoArgConstructorException {
2173     try {
2174       get(FAILED_FUTURE_ERROR, 0, SECONDS, TwoArgConstructorException.class);
2175       fail();
2176     } catch (ExecutionError expected) {
2177       assertEquals(ERROR, expected.getCause());
2178     }
2179   }
2180 
2181   public void testGetTimed_ExecutionExceptionOtherThrowable() {
2182     try {
2183       get(FAILED_FUTURE_OTHER_THROWABLE, 0, SECONDS,
2184           TwoArgConstructorException.class);
2185       fail();
2186     } catch (TwoArgConstructorException expected) {
2187       assertEquals(OTHER_THROWABLE, expected.getCause());
2188     }
2189   }
2190 
2191   public void testGetTimed_RuntimeException()
2192       throws TwoArgConstructorException {
2193     try {
2194       get(RUNTIME_EXCEPTION_FUTURE, 0, SECONDS,
2195           TwoArgConstructorException.class);
2196       fail();
2197     } catch (RuntimeException expected) {
2198       assertEquals(RUNTIME_EXCEPTION, expected);
2199     }
2200   }
2201 
2202   public void testGetTimed_TimeoutException() {
2203     SettableFuture<String> future = SettableFuture.create();
2204     try {
2205       get(future, 0, SECONDS, TwoArgConstructorException.class);
2206       fail();
2207     } catch (TwoArgConstructorException expected) {
2208       assertTrue(expected.getCause() instanceof TimeoutException);
2209     }
2210   }
2211 
2212   public void testGetTimed_badExceptionConstructor_wrapsOriginalChecked() throws Exception {
2213     try {
2214       get(FAILED_FUTURE_CHECKED_EXCEPTION, 1, TimeUnit.SECONDS, ExceptionWithBadConstructor.class);
2215       fail();
2216     } catch (IllegalArgumentException expected) {
2217       assertSame(CHECKED_EXCEPTION, expected.getCause());
2218     }
2219   }
2220 
2221   public void testGetTimed_withGoodAndBadExceptionConstructor() throws Exception {
2222     try {
2223       get(FAILED_FUTURE_CHECKED_EXCEPTION, 1, TimeUnit.SECONDS,
2224           ExceptionWithGoodAndBadConstructor.class);
2225       fail();
2226     } catch (ExceptionWithGoodAndBadConstructor expected) {
2227       assertSame(CHECKED_EXCEPTION, expected.getCause());
2228     }
2229   }
2230 
2231   // Boring getUnchecked tests:
2232 
2233   public void testGetUnchecked_success() {
2234     assertEquals("foo", getUnchecked(immediateFuture("foo")));
2235   }
2236 
2237   public void testGetUnchecked_interrupted() {
2238     Thread.currentThread().interrupt();
2239     try {
2240       assertEquals("foo", getUnchecked(immediateFuture("foo")));
2241       assertTrue(Thread.currentThread().isInterrupted());
2242     } finally {
2243       Thread.interrupted();
2244     }
2245   }
2246 
2247   public void testGetUnchecked_cancelled() {
2248     SettableFuture<String> future = SettableFuture.create();
2249     future.cancel(true);
2250     try {
2251       getUnchecked(future);
2252       fail();
2253     } catch (CancellationException expected) {
2254     }
2255   }
2256 
2257   public void testGetUnchecked_ExecutionExceptionChecked() {
2258     try {
2259       getUnchecked(FAILED_FUTURE_CHECKED_EXCEPTION);
2260       fail();
2261     } catch (UncheckedExecutionException expected) {
2262       assertEquals(CHECKED_EXCEPTION, expected.getCause());
2263     }
2264   }
2265 
2266   public void testGetUnchecked_ExecutionExceptionUnchecked() {
2267     try {
2268       getUnchecked(FAILED_FUTURE_UNCHECKED_EXCEPTION);
2269       fail();
2270     } catch (UncheckedExecutionException expected) {
2271       assertEquals(UNCHECKED_EXCEPTION, expected.getCause());
2272     }
2273   }
2274 
2275   public void testGetUnchecked_ExecutionExceptionError() {
2276     try {
2277       getUnchecked(FAILED_FUTURE_ERROR);
2278       fail();
2279     } catch (ExecutionError expected) {
2280       assertEquals(ERROR, expected.getCause());
2281     }
2282   }
2283 
2284   public void testGetUnchecked_ExecutionExceptionOtherThrowable() {
2285     try {
2286       getUnchecked(FAILED_FUTURE_OTHER_THROWABLE);
2287       fail();
2288     } catch (UncheckedExecutionException expected) {
2289       assertEquals(OTHER_THROWABLE, expected.getCause());
2290     }
2291   }
2292 
2293   public void testGetUnchecked_RuntimeException() {
2294     try {
2295       getUnchecked(RUNTIME_EXCEPTION_FUTURE);
2296       fail();
2297     } catch (RuntimeException expected) {
2298       assertEquals(RUNTIME_EXCEPTION, expected);
2299     }
2300   }
2301 
2302   // Edge case tests of the exception-construction code through untimed get():
2303 
2304   public void testGetUntimed_exceptionClassIsRuntimeException() {
2305     try {
2306       get(FAILED_FUTURE_CHECKED_EXCEPTION,
2307           TwoArgConstructorRuntimeException.class);
2308       fail();
2309     } catch (IllegalArgumentException expected) {
2310     }
2311   }
2312 
2313   public void testGetUntimed_exceptionClassSomePublicConstructors() {
2314     try {
2315       get(FAILED_FUTURE_CHECKED_EXCEPTION,
2316           ExceptionWithSomePrivateConstructors.class);
2317       fail();
2318     } catch (ExceptionWithSomePrivateConstructors expected) {
2319     }
2320   }
2321 
2322   public void testGetUntimed_exceptionClassNoPublicConstructor()
2323       throws ExceptionWithPrivateConstructor {
2324     try {
2325       get(FAILED_FUTURE_CHECKED_EXCEPTION,
2326           ExceptionWithPrivateConstructor.class);
2327       fail();
2328     } catch (IllegalArgumentException expected) {
2329     }
2330   }
2331 
2332   public void testGetUntimed_exceptionClassPublicConstructorWrongType()
2333       throws ExceptionWithWrongTypesConstructor {
2334     try {
2335       get(FAILED_FUTURE_CHECKED_EXCEPTION,
2336           ExceptionWithWrongTypesConstructor.class);
2337       fail();
2338     } catch (IllegalArgumentException expected) {
2339     }
2340   }
2341 
2342   public void testGetUntimed_exceptionClassPrefersStringConstructor() {
2343     try {
2344       get(FAILED_FUTURE_CHECKED_EXCEPTION,
2345           ExceptionWithManyConstructors.class);
2346       fail();
2347     } catch (ExceptionWithManyConstructors expected) {
2348       assertTrue(expected.usedExpectedConstructor);
2349     }
2350   }
2351 
2352   public void testGetUntimed_exceptionClassUsedInitCause() {
2353     try {
2354       get(FAILED_FUTURE_CHECKED_EXCEPTION,
2355           ExceptionWithoutThrowableConstructor.class);
2356       fail();
2357     } catch (ExceptionWithoutThrowableConstructor expected) {
2358       assertThat(expected.getMessage()).contains("mymessage");
2359       assertEquals(CHECKED_EXCEPTION, expected.getCause());
2360     }
2361   }
2362 
2363   public void testCompletionOrder() throws Exception {
2364     SettableFuture<Long> future1 = SettableFuture.create();
2365     SettableFuture<Long> future2 = SettableFuture.create();
2366     SettableFuture<Long> future3 = SettableFuture.create();
2367     SettableFuture<Long> future4 = SettableFuture.create();
2368     SettableFuture<Long> future5 = SettableFuture.create();
2369 
2370     ImmutableList<ListenableFuture<Long>> futures = Futures.inCompletionOrder(
2371         ImmutableList.<ListenableFuture<Long>>of(future1, future2, future3, future4, future5));
2372     future2.set(1L);
2373     future5.set(2L);
2374     future1.set(3L);
2375     future3.set(4L);
2376     future4.set(5L);
2377 
2378     long expected = 1L;
2379     for (ListenableFuture<Long> future : futures) {
2380       assertEquals((Long) expected, future.get());
2381       expected++;
2382     }
2383   }
2384 
2385   public void testCompletionOrderExceptionThrown() throws Exception {
2386     SettableFuture<Long> future1 = SettableFuture.create();
2387     SettableFuture<Long> future2 = SettableFuture.create();
2388     SettableFuture<Long> future3 = SettableFuture.create();
2389     SettableFuture<Long> future4 = SettableFuture.create();
2390     SettableFuture<Long> future5 = SettableFuture.create();
2391 
2392     ImmutableList<ListenableFuture<Long>> futures = Futures.inCompletionOrder(
2393         ImmutableList.<ListenableFuture<Long>>of(future1, future2, future3, future4, future5));
2394     future2.set(1L);
2395     future5.setException(new IllegalStateException("2L"));
2396     future1.set(3L);
2397     future3.set(4L);
2398     future4.set(5L);
2399 
2400     long expected = 1L;
2401     for (ListenableFuture<Long> future : futures) {
2402       if (expected != 2) {
2403         assertEquals((Long) expected, future.get());
2404       } else {
2405         try {
2406           future.get();
2407           fail();
2408         } catch (ExecutionException e) {
2409           // Expected
2410           assertEquals("2L", e.getCause().getMessage());
2411         }
2412       }
2413       expected++;
2414     }
2415   }
2416 
2417   public void testCompletionOrderFutureCancelled() throws Exception {
2418     SettableFuture<Long> future1 = SettableFuture.create();
2419     SettableFuture<Long> future2 = SettableFuture.create();
2420     SettableFuture<Long> future3 = SettableFuture.create();
2421     SettableFuture<Long> future4 = SettableFuture.create();
2422     SettableFuture<Long> future5 = SettableFuture.create();
2423 
2424     ImmutableList<ListenableFuture<Long>> futures = Futures.inCompletionOrder(
2425         ImmutableList.<ListenableFuture<Long>>of(future1, future2, future3, future4, future5));
2426     future2.set(1L);
2427     future5.set(2L);
2428     future1.set(3L);
2429     future3.cancel(true);
2430     future4.set(5L);
2431 
2432     long expected = 1L;
2433     for (ListenableFuture<Long> future : futures) {
2434       if (expected != 4) {
2435         assertEquals((Long) expected, future.get());
2436       } else {
2437         try {
2438           future.get();
2439           fail();
2440         } catch (CancellationException e) {
2441           // Expected
2442         }
2443       }
2444       expected++;
2445     }
2446   }
2447 
2448   public void testCancellingADelegateDoesNotPropagate() throws Exception {
2449     SettableFuture<Long> future1 = SettableFuture.create();
2450     SettableFuture<Long> future2 = SettableFuture.create();
2451 
2452     ImmutableList<ListenableFuture<Long>> delegates = Futures.inCompletionOrder(
2453         ImmutableList.<ListenableFuture<Long>>of(future1, future2));
2454 
2455     future1.set(1L);
2456     // Cannot cancel a complete delegate
2457     assertFalse(delegates.get(0).cancel(true));
2458     // Cancel the delegate before the input future is done
2459     assertTrue(delegates.get(1).cancel(true));
2460     // Setting the future still works since cancellation didn't propagate
2461     assertTrue(future2.set(2L));
2462     // Second check to ensure the input future was not cancelled
2463     assertEquals((Long) 2L, future2.get());
2464   }
2465 
2466   // Mostly an example of how it would look like to use a list of mixed types
2467   public void testCompletionOrderMixedBagOTypes() throws Exception {
2468     SettableFuture<Long> future1 = SettableFuture.create();
2469     SettableFuture<String> future2 = SettableFuture.create();
2470     SettableFuture<Integer> future3 = SettableFuture.create();
2471 
2472     ImmutableList<? extends ListenableFuture<?>> inputs =
2473         ImmutableList.<ListenableFuture<?>>of(future1, future2, future3);
2474     ImmutableList<ListenableFuture<Object>> futures = Futures.inCompletionOrder(inputs);
2475     future2.set("1L");
2476     future1.set(2L);
2477     future3.set(3);
2478 
2479     ImmutableList<?> expected = ImmutableList.of("1L", 2L, 3);
2480     for (int i = 0; i < expected.size(); i++) {
2481       assertEquals(expected.get(i), futures.get(i).get());
2482     }
2483   }
2484 
2485   public static final class TwoArgConstructorException extends Exception {
2486     public TwoArgConstructorException(String message, Throwable cause) {
2487       super(message, cause);
2488     }
2489   }
2490 
2491   public static final class TwoArgConstructorRuntimeException
2492       extends RuntimeException {
2493     public TwoArgConstructorRuntimeException(String message, Throwable cause) {
2494       super(message, cause);
2495     }
2496   }
2497 
2498   public static final class ExceptionWithPrivateConstructor extends Exception {
2499     private ExceptionWithPrivateConstructor(String message, Throwable cause) {
2500       super(message, cause);
2501     }
2502   }
2503 
2504   @SuppressWarnings("unused") // we're testing that they're not used
2505   public static final class ExceptionWithSomePrivateConstructors
2506       extends Exception {
2507     private ExceptionWithSomePrivateConstructors(String a) {
2508     }
2509 
2510     private ExceptionWithSomePrivateConstructors(String a, String b) {
2511     }
2512 
2513     public ExceptionWithSomePrivateConstructors(
2514         String a, String b, String c) {
2515     }
2516 
2517     private ExceptionWithSomePrivateConstructors(
2518         String a, String b, String c, String d) {
2519     }
2520 
2521     private ExceptionWithSomePrivateConstructors(
2522         String a, String b, String c, String d, String e) {
2523     }
2524   }
2525 
2526   public static final class ExceptionWithManyConstructors extends Exception {
2527     boolean usedExpectedConstructor;
2528 
2529     public ExceptionWithManyConstructors() {
2530     }
2531 
2532     public ExceptionWithManyConstructors(Integer i) {
2533     }
2534 
2535     public ExceptionWithManyConstructors(Throwable a) {
2536     }
2537 
2538     public ExceptionWithManyConstructors(Throwable a, Throwable b) {
2539     }
2540 
2541     public ExceptionWithManyConstructors(String s, Throwable b) {
2542       usedExpectedConstructor = true;
2543     }
2544 
2545     public ExceptionWithManyConstructors(
2546         Throwable a, Throwable b, Throwable c) {
2547     }
2548 
2549     public ExceptionWithManyConstructors(
2550         Throwable a, Throwable b, Throwable c, Throwable d) {
2551     }
2552 
2553     public ExceptionWithManyConstructors(
2554         Throwable a, Throwable b, Throwable c, Throwable d, Throwable e) {
2555     }
2556 
2557     public ExceptionWithManyConstructors(Throwable a, Throwable b, Throwable c,
2558         Throwable d, Throwable e, String s, Integer i) {
2559     }
2560   }
2561 
2562   public static final class ExceptionWithoutThrowableConstructor
2563       extends Exception {
2564     public ExceptionWithoutThrowableConstructor(String s) {
2565       super(s);
2566     }
2567   }
2568 
2569   public static final class ExceptionWithWrongTypesConstructor
2570       extends Exception {
2571     public ExceptionWithWrongTypesConstructor(Integer i, String s) {
2572       super(s);
2573     }
2574   }
2575 
2576   private static final class ExceptionWithGoodAndBadConstructor extends Exception {
2577     public ExceptionWithGoodAndBadConstructor(String message, Throwable cause) {
2578       throw new RuntimeException("bad constructor");
2579     }
2580     public ExceptionWithGoodAndBadConstructor(Throwable cause) {
2581       super(cause);
2582     }
2583   }
2584 
2585   private static final class ExceptionWithBadConstructor extends Exception {
2586     public ExceptionWithBadConstructor(String message, Throwable cause) {
2587       throw new RuntimeException("bad constructor");
2588     }
2589   }
2590 
2591   public void testFutures_nullChecks() throws Exception {
2592     new ClassSanityTester()
2593         .forAllPublicStaticMethods(Futures.class)
2594         .thatReturn(Future.class)
2595         .testNulls();
2596   }
2597 
2598   private static void failWithCause(Throwable cause, String message) {
2599     AssertionFailedError failure = new AssertionFailedError(message);
2600     failure.initCause(cause);
2601     throw failure;
2602   }
2603 }
2604