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