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.util.concurrent.Futures.allAsList; 21 import static com.google.common.util.concurrent.Futures.get; 22 import static com.google.common.util.concurrent.Futures.getUnchecked; 23 import static com.google.common.util.concurrent.Futures.immediateFailedFuture; 24 import static com.google.common.util.concurrent.Futures.immediateFuture; 25 import static com.google.common.util.concurrent.Futures.successfulAsList; 26 import static java.util.concurrent.Executors.newSingleThreadExecutor; 27 import static java.util.concurrent.TimeUnit.MILLISECONDS; 28 import static java.util.concurrent.TimeUnit.SECONDS; 29 import static org.junit.contrib.truth.Truth.ASSERT; 30 31 import com.google.common.base.Function; 32 import com.google.common.base.Functions; 33 import com.google.common.base.Joiner; 34 import com.google.common.collect.ImmutableList; 35 import com.google.common.collect.ImmutableSet; 36 import com.google.common.collect.Iterables; 37 import com.google.common.collect.Sets; 38 import com.google.common.testing.NullPointerTester; 39 import com.google.common.util.concurrent.ForwardingFuture.SimpleForwardingFuture; 40 41 import junit.framework.AssertionFailedError; 42 import junit.framework.TestCase; 43 44 import org.easymock.EasyMock; 45 import org.easymock.IMocksControl; 46 47 import java.io.IOException; 48 import java.util.Arrays; 49 import java.util.List; 50 import java.util.Set; 51 import java.util.concurrent.Callable; 52 import java.util.concurrent.CancellationException; 53 import java.util.concurrent.CountDownLatch; 54 import java.util.concurrent.ExecutionException; 55 import java.util.concurrent.Executor; 56 import java.util.concurrent.ExecutorService; 57 import java.util.concurrent.Future; 58 import java.util.concurrent.TimeUnit; 59 import java.util.concurrent.TimeoutException; 60 61 import javax.annotation.Nullable; 62 63 /** 64 * Unit tests for {@link Futures}. 65 * 66 * TODO: Add tests for other Futures methods 67 * 68 * @author Nishant Thakkar 69 */ 70 public class FuturesTest extends TestCase { 71 private static final String DATA1 = "data"; 72 private static final String DATA2 = "more data"; 73 private static final String DATA3 = "most data"; 74 75 private IMocksControl mocksControl; 76 setUp()77 @Override protected void setUp() throws Exception { 78 super.setUp(); 79 80 mocksControl = EasyMock.createControl(); 81 } 82 tearDown()83 @Override protected void tearDown() throws Exception { 84 /* 85 * Clear interrupt for future tests. 86 * 87 * (Ideally we would perform interrupts only in threads that we create, but 88 * it's hard to imagine that anything will break in practice.) 89 */ 90 Thread.interrupted(); 91 92 super.tearDown(); 93 } 94 testImmediateFuture()95 public void testImmediateFuture() throws Exception { 96 ListenableFuture<String> future = Futures.immediateFuture(DATA1); 97 98 // Verify that the proper object is returned without waiting 99 assertSame(DATA1, future.get(0L, TimeUnit.MILLISECONDS)); 100 } 101 testMultipleImmediateFutures()102 public void testMultipleImmediateFutures() throws Exception { 103 ListenableFuture<String> future1 = Futures.immediateFuture(DATA1); 104 ListenableFuture<String> future2 = Futures.immediateFuture(DATA2); 105 106 // Verify that the proper objects are returned without waiting 107 assertSame(DATA1, future1.get(0L, TimeUnit.MILLISECONDS)); 108 assertSame(DATA2, future2.get(0L, TimeUnit.MILLISECONDS)); 109 } 110 testImmediateFailedFuture()111 public void testImmediateFailedFuture() throws Exception { 112 Exception exception = new Exception(); 113 ListenableFuture<String> future = 114 Futures.immediateFailedFuture(exception); 115 116 try { 117 future.get(0L, TimeUnit.MILLISECONDS); 118 fail("This call was supposed to throw an ExecutionException"); 119 } catch (ExecutionException expected) { 120 // This is good and expected 121 assertSame(exception, expected.getCause()); 122 } 123 } 124 125 private static class MyException extends Exception {} 126 testImmediateCheckedFuture()127 public void testImmediateCheckedFuture() throws Exception { 128 CheckedFuture<String, MyException> future = Futures.immediateCheckedFuture( 129 DATA1); 130 131 // Verify that the proper object is returned without waiting 132 assertSame(DATA1, future.get(0L, TimeUnit.MILLISECONDS)); 133 assertSame(DATA1, future.checkedGet(0L, TimeUnit.MILLISECONDS)); 134 } 135 testMultipleImmediateCheckedFutures()136 public void testMultipleImmediateCheckedFutures() throws Exception { 137 CheckedFuture<String, MyException> future1 = Futures.immediateCheckedFuture( 138 DATA1); 139 CheckedFuture<String, MyException> future2 = Futures.immediateCheckedFuture( 140 DATA2); 141 142 // Verify that the proper objects are returned without waiting 143 assertSame(DATA1, future1.get(0L, TimeUnit.MILLISECONDS)); 144 assertSame(DATA1, future1.checkedGet(0L, TimeUnit.MILLISECONDS)); 145 assertSame(DATA2, future2.get(0L, TimeUnit.MILLISECONDS)); 146 assertSame(DATA2, future2.checkedGet(0L, TimeUnit.MILLISECONDS)); 147 } 148 testImmediateFailedCheckedFuture()149 public void testImmediateFailedCheckedFuture() throws Exception { 150 MyException exception = new MyException(); 151 CheckedFuture<String, MyException> future = 152 Futures.immediateFailedCheckedFuture(exception); 153 154 try { 155 future.get(0L, TimeUnit.MILLISECONDS); 156 fail("This call was supposed to throw an ExecutionException"); 157 } catch (ExecutionException expected) { 158 // This is good and expected 159 assertSame(exception, expected.getCause()); 160 } 161 162 try { 163 future.checkedGet(0L, TimeUnit.MILLISECONDS); 164 fail("This call was supposed to throw an MyException"); 165 } catch (MyException expected) { 166 // This is good and expected 167 assertSame(exception, expected); 168 } 169 } 170 171 // Class hierarchy for generics sanity checks 172 private static class Foo {} 173 private static class FooChild extends Foo {} 174 private static class Bar {} 175 private static class BarChild extends Bar {} 176 testTransform_ListenableFuture_genericsNull()177 public void testTransform_ListenableFuture_genericsNull() throws Exception { 178 ListenableFuture<?> nullFuture = Futures.immediateFuture(null); 179 ListenableFuture<?> transformedFuture = 180 Futures.transform(nullFuture, Functions.constant(null)); 181 assertNull(transformedFuture.get()); 182 } 183 testTransform_ListenableFuture_genericsHierarchy()184 public void testTransform_ListenableFuture_genericsHierarchy() 185 throws Exception { 186 ListenableFuture<FooChild> future = Futures.immediateFuture(null); 187 final BarChild barChild = new BarChild(); 188 Function<Foo, BarChild> function = new Function<Foo, BarChild>() { 189 @Override public BarChild apply(Foo unused) { 190 return barChild; 191 } 192 }; 193 Bar bar = Futures.transform(future, function).get(); 194 assertSame(barChild, bar); 195 } 196 197 /** 198 * {@link ListenableFuture} variant of 199 * {@link #testTransformValueRemainsMemoized_Future()}. 200 */ testTransformValueRemainsMemoized_ListenableFuture()201 public void testTransformValueRemainsMemoized_ListenableFuture() 202 throws Exception { 203 class Holder { 204 int value = 2; 205 } 206 final Holder holder = new Holder(); 207 208 // This function adds the holder's value to the input value. 209 Function<Integer, Integer> adder = new Function<Integer, Integer>() { 210 @Override public Integer apply(Integer from) { 211 return from + holder.value; 212 } 213 }; 214 215 // Since holder.value is 2, applying 4 should yield 6. 216 assertEquals(6, adder.apply(4).intValue()); 217 218 ListenableFuture<Integer> immediateFuture = Futures.immediateFuture(4); 219 Future<Integer> transformedFuture = Futures.transform(immediateFuture, adder); 220 221 // The composed future also yields 6. 222 assertEquals(6, transformedFuture.get().intValue()); 223 224 // Repeated calls yield the same value even though the function's behavior 225 // changes 226 holder.value = 3; 227 assertEquals(6, transformedFuture.get().intValue()); 228 assertEquals(7, adder.apply(4).intValue()); 229 230 // Once more, with feeling. 231 holder.value = 4; 232 assertEquals(6, transformedFuture.get().intValue()); 233 assertEquals(8, adder.apply(4).intValue()); 234 235 // Memoized get also retains the value. 236 assertEquals(6, transformedFuture.get(1000, TimeUnit.SECONDS).intValue()); 237 238 // Unsurprisingly, recomposing the future will return an updated value. 239 assertEquals(8, Futures.transform(immediateFuture, adder).get().intValue()); 240 241 // Repeating, with the timeout version 242 assertEquals(8, Futures.transform(immediateFuture, adder).get( 243 1000, TimeUnit.SECONDS).intValue()); 244 } 245 246 static class MyError extends Error {} 247 static class MyRuntimeException extends RuntimeException {} 248 249 /** 250 * {@link ListenableFuture} variant of 251 * {@link #testTransformExceptionRemainsMemoized_Future()}. 252 */ testTransformExceptionRemainsMemoized_ListenableFuture()253 public void testTransformExceptionRemainsMemoized_ListenableFuture() 254 throws Throwable { 255 SettableFuture<Integer> input = SettableFuture.create(); 256 257 ListenableFuture<Integer> exceptionComposedFuture = 258 Futures.transform(input, newOneTimeExceptionThrower()); 259 ListenableFuture<Integer> errorComposedFuture = 260 Futures.transform(input, newOneTimeErrorThrower()); 261 262 try { 263 input.set(0); 264 fail(); 265 } catch (MyError expected) { 266 /* 267 * The ListenableFuture variant rethrows errors from execute() as well 268 * as assigning them to the output of the future. 269 */ 270 } 271 272 runGetIdempotencyTest(exceptionComposedFuture, MyRuntimeException.class); 273 runGetIdempotencyTest(errorComposedFuture, MyError.class); 274 275 /* 276 * Try again when the input's value is already filled in, since the flow is 277 * slightly different in that case. 278 */ 279 exceptionComposedFuture = 280 Futures.transform(input, newOneTimeExceptionThrower()); 281 runGetIdempotencyTest(exceptionComposedFuture, MyRuntimeException.class); 282 283 try { 284 Futures.transform(input, newOneTimeErrorThrower()); 285 fail(); 286 } catch (MyError expected) { 287 } 288 } 289 runGetIdempotencyTest(Future<Integer> transformedFuture, Class<? extends Throwable> expectedExceptionClass)290 private static void runGetIdempotencyTest(Future<Integer> transformedFuture, 291 Class<? extends Throwable> expectedExceptionClass) throws Throwable { 292 for (int i = 0; i < 5; i++) { 293 try { 294 transformedFuture.get(); 295 fail(); 296 } catch (ExecutionException expected) { 297 if (!expectedExceptionClass.isInstance(expected.getCause())) { 298 throw expected.getCause(); 299 } 300 } 301 } 302 } 303 newOneTimeValueReturner(final O output)304 private static <I, O> Function<I, O> newOneTimeValueReturner(final O output) { 305 return new Function<I, O>() { 306 int calls = 0; 307 308 @Override 309 public O apply(I arg0) { 310 if (++calls > 1) { 311 fail(); 312 } 313 return output; 314 } 315 }; 316 } 317 newOneTimeExceptionThrower()318 private static Function<Integer, Integer> newOneTimeExceptionThrower() { 319 return new Function<Integer, Integer>() { 320 int calls = 0; 321 322 @Override public Integer apply(Integer from) { 323 if (++calls > 1) { 324 fail(); 325 } 326 throw new MyRuntimeException(); 327 } 328 }; 329 } 330 331 private static Function<Integer, Integer> newOneTimeErrorThrower() { 332 return new Function<Integer, Integer>() { 333 int calls = 0; 334 335 @Override public Integer apply(Integer from) { 336 if (++calls > 1) { 337 fail(); 338 } 339 throw new MyError(); 340 } 341 }; 342 } 343 344 // TODO(cpovirk): top-level class? 345 static class ExecutorSpy implements Executor { 346 Executor delegate; 347 boolean wasExecuted; 348 349 public ExecutorSpy(Executor delegate) { 350 this.delegate = delegate; 351 } 352 353 @Override public void execute(Runnable command) { 354 delegate.execute(command); 355 wasExecuted = true; 356 } 357 } 358 359 public void testTransform_Executor() throws Exception { 360 Object value = new Object(); 361 ExecutorSpy spy = new ExecutorSpy(MoreExecutors.sameThreadExecutor()); 362 363 assertFalse(spy.wasExecuted); 364 365 ListenableFuture<Object> future = Futures.transform( 366 Futures.immediateFuture(value), 367 Functions.identity(), spy); 368 369 assertSame(value, future.get()); 370 assertTrue(spy.wasExecuted); 371 } 372 373 public void testLazyTransform() throws Exception { 374 FunctionSpy<Object, String> spy = 375 new FunctionSpy<Object, String>(Functions.constant("bar")); 376 Future<String> input = Futures.immediateFuture("foo"); 377 Future<String> transformed = Futures.lazyTransform(input, spy); 378 assertEquals(0, spy.getApplyCount()); 379 assertEquals("bar", transformed.get()); 380 assertEquals(1, spy.getApplyCount()); 381 assertEquals("bar", transformed.get()); 382 assertEquals(2, spy.getApplyCount()); 383 } 384 385 private static class FunctionSpy<I, O> implements Function<I, O> { 386 private int applyCount; 387 private final Function<I, O> delegate; 388 389 public FunctionSpy(Function<I, O> delegate) { 390 this.delegate = delegate; 391 } 392 393 @Override 394 public O apply(I input) { 395 applyCount++; 396 return delegate.apply(input); 397 } 398 399 public int getApplyCount() { 400 return applyCount; 401 } 402 } 403 404 public void testTransform_genericsWildcard_AsyncFunction() throws Exception { 405 ListenableFuture<?> nullFuture = Futures.immediateFuture(null); 406 ListenableFuture<?> chainedFuture = 407 Futures.transform(nullFuture, constantAsyncFunction(nullFuture)); 408 assertNull(chainedFuture.get()); 409 } 410 411 private static <I, O> AsyncFunction<I, O> constantAsyncFunction( 412 final ListenableFuture<O> output) { 413 return new AsyncFunction<I, O>() { 414 @Override 415 public ListenableFuture<O> apply(I input) { 416 return output; 417 } 418 }; 419 } 420 421 public void testTransform_genericsHierarchy_AsyncFunction() throws Exception { 422 ListenableFuture<FooChild> future = Futures.immediateFuture(null); 423 final BarChild barChild = new BarChild(); 424 AsyncFunction<Foo, BarChild> function = 425 new AsyncFunction<Foo, BarChild>() { 426 @Override public AbstractFuture<BarChild> apply(Foo unused) { 427 AbstractFuture<BarChild> future = new AbstractFuture<BarChild>() {}; 428 future.set(barChild); 429 return future; 430 } 431 }; 432 Bar bar = Futures.transform(future, function).get(); 433 assertSame(barChild, bar); 434 } 435 436 public void testTransform_delegatesBlockingGet_AsyncFunction() throws Exception { 437 performAsyncFunctionTransformedFutureDelgationTest(0, null); 438 } 439 440 public void testTransform_delegatesTimedGet_AsyncFunction() throws Exception { 441 performAsyncFunctionTransformedFutureDelgationTest(25, TimeUnit.SECONDS); 442 } 443 444 private void performAsyncFunctionTransformedFutureDelgationTest( 445 long timeout, TimeUnit unit) 446 throws InterruptedException, ExecutionException, TimeoutException { 447 final Foo foo = new Foo(); 448 MockRequiresGetCallFuture<Foo> fooFuture = 449 new MockRequiresGetCallFuture<Foo>(foo); 450 451 Bar bar = new Bar(); 452 final MockRequiresGetCallFuture<Bar> barFuture = 453 new MockRequiresGetCallFuture<Bar>(bar); 454 AsyncFunction<Foo, Bar> function = 455 new AsyncFunction<Foo, Bar>() { 456 @Override public ListenableFuture<Bar> apply(Foo from) { 457 assertSame(foo, from); 458 return barFuture; 459 } 460 }; 461 462 ListenableFuture<Bar> chainFuture = Futures.transform(fooFuture, function); 463 Bar theBar; 464 if (unit != null) { 465 theBar = chainFuture.get(timeout, unit); 466 } else { 467 theBar = chainFuture.get(); 468 } 469 assertSame(bar, theBar); 470 assertTrue(fooFuture.getWasGetCalled()); 471 assertTrue(barFuture.getWasGetCalled()); 472 } 473 474 /** 475 * A mock listenable future that requires the caller invoke 476 * either form of get() before the future will make its value 477 * available or invoke listeners. 478 */ 479 private static class MockRequiresGetCallFuture<T> extends AbstractFuture<T> { 480 481 private final T value; 482 private boolean getWasCalled; 483 484 MockRequiresGetCallFuture(T value) { 485 this.value = value; 486 } 487 488 @Override public T get() throws InterruptedException, ExecutionException { 489 set(value); 490 getWasCalled = true; 491 return super.get(); 492 } 493 494 @Override public T get(long timeout, TimeUnit unit) 495 throws TimeoutException, ExecutionException, InterruptedException { 496 set(value); 497 getWasCalled = true; 498 return super.get(timeout, unit); 499 } 500 501 boolean getWasGetCalled() { 502 return getWasCalled; 503 } 504 } 505 506 /** 507 * Runnable which can be called a single time, and only after 508 * {@link #expectCall} is called. 509 */ 510 // TODO(cpovirk): top-level class? 511 static class SingleCallListener implements Runnable { 512 private boolean expectCall = false; 513 private final CountDownLatch calledCountDown = 514 new CountDownLatch(1); 515 516 @Override public void run() { 517 assertTrue("Listener called before it was expected", expectCall); 518 assertFalse("Listener called more than once", wasCalled()); 519 calledCountDown.countDown(); 520 } 521 522 public void expectCall() { 523 assertFalse("expectCall is already true", expectCall); 524 expectCall = true; 525 } 526 527 public boolean wasCalled() { 528 return calledCountDown.getCount() == 0; 529 } 530 531 public void waitForCall() throws InterruptedException { 532 assertTrue("expectCall is false", expectCall); 533 calledCountDown.await(); 534 } 535 } 536 537 public void testAllAsList() throws Exception { 538 // Create input and output 539 SettableFuture<String> future1 = SettableFuture.create(); 540 SettableFuture<String> future2 = SettableFuture.create(); 541 SettableFuture<String> future3 = SettableFuture.create(); 542 @SuppressWarnings("unchecked") // array is never modified 543 ListenableFuture<List<String>> compound = 544 Futures.allAsList(future1, future2, future3); 545 546 // Attach a listener 547 SingleCallListener listener = new SingleCallListener(); 548 compound.addListener(listener, MoreExecutors.sameThreadExecutor()); 549 550 // Satisfy each input and check the output 551 assertFalse(compound.isDone()); 552 future1.set(DATA1); 553 assertFalse(compound.isDone()); 554 future2.set(DATA2); 555 assertFalse(compound.isDone()); 556 listener.expectCall(); 557 future3.set(DATA3); 558 assertTrue(compound.isDone()); 559 assertTrue(listener.wasCalled()); 560 561 List<String> results = compound.get(); 562 ASSERT.that(results).hasContentsInOrder(DATA1, DATA2, DATA3); 563 } 564 565 public void testAllAsList_emptyList() throws Exception { 566 SingleCallListener listener = new SingleCallListener(); 567 listener.expectCall(); 568 List<ListenableFuture<String>> futures = ImmutableList.of(); 569 ListenableFuture<List<String>> compound = Futures.allAsList(futures); 570 compound.addListener(listener, MoreExecutors.sameThreadExecutor()); 571 assertTrue(compound.isDone()); 572 assertTrue(compound.get().isEmpty()); 573 assertTrue(listener.wasCalled()); 574 } 575 576 public void testAllAsList_emptyArray() throws Exception { 577 SingleCallListener listener = new SingleCallListener(); 578 listener.expectCall(); 579 @SuppressWarnings("unchecked") // array is never modified 580 ListenableFuture<List<String>> compound = Futures.allAsList(); 581 compound.addListener(listener, MoreExecutors.sameThreadExecutor()); 582 assertTrue(compound.isDone()); 583 assertTrue(compound.get().isEmpty()); 584 assertTrue(listener.wasCalled()); 585 } 586 587 public void testAllAsList_failure() throws Exception { 588 SingleCallListener listener = new SingleCallListener(); 589 SettableFuture<String> future1 = SettableFuture.create(); 590 SettableFuture<String> future2 = SettableFuture.create(); 591 @SuppressWarnings("unchecked") // array is never modified 592 ListenableFuture<List<String>> compound = 593 Futures.allAsList(future1, future2); 594 compound.addListener(listener, MoreExecutors.sameThreadExecutor()); 595 596 listener.expectCall(); 597 Throwable exception = new Throwable("failed1"); 598 future1.setException(exception); 599 assertTrue(compound.isDone()); 600 assertTrue(listener.wasCalled()); 601 future2.set("result2"); 602 603 try { 604 compound.get(); 605 fail("Expected exception not thrown"); 606 } catch (ExecutionException e) { 607 assertSame(exception, e.getCause()); 608 } 609 } 610 611 public void testAllAsList_singleFailure() throws Exception { 612 Throwable exception = new Throwable("failed"); 613 ListenableFuture<String> future = Futures.immediateFailedFuture(exception); 614 ListenableFuture<List<String>> compound = Futures.allAsList(ImmutableList.of(future)); 615 616 try { 617 compound.get(); 618 fail("Expected exception not thrown"); 619 } catch (ExecutionException e) { 620 assertSame(exception, e.getCause()); 621 } 622 } 623 624 public void testAllAsList_immediateFailure() throws Exception { 625 Throwable exception = new Throwable("failed"); 626 ListenableFuture<String> future1 = Futures.immediateFailedFuture(exception); 627 ListenableFuture<String> future2 = Futures.immediateFuture("results"); 628 ListenableFuture<List<String>> compound = Futures.allAsList(ImmutableList.of(future1, future2)); 629 630 try { 631 compound.get(); 632 fail("Expected exception not thrown"); 633 } catch (ExecutionException e) { 634 assertSame(exception, e.getCause()); 635 } 636 } 637 638 public void testAllAsList_cancelled() throws Exception { 639 SingleCallListener listener = new SingleCallListener(); 640 SettableFuture<String> future1 = SettableFuture.create(); 641 SettableFuture<String> future2 = SettableFuture.create(); 642 @SuppressWarnings("unchecked") // array is never modified 643 ListenableFuture<List<String>> compound = 644 Futures.allAsList(future1, future2); 645 compound.addListener(listener, MoreExecutors.sameThreadExecutor()); 646 647 listener.expectCall(); 648 future1.cancel(true); 649 assertTrue(compound.isDone()); 650 assertTrue(listener.wasCalled()); 651 future2.setException(new Throwable("failed2")); 652 653 try { 654 compound.get(); 655 fail("Expected exception not thrown"); 656 } catch (CancellationException e) { 657 // Expected 658 } 659 } 660 661 public void testAllAsList_buggyInputFutures() throws Exception { 662 final Foo foo1 = new Foo(); 663 MockRequiresGetCallFuture<Foo> foo1Future = 664 new MockRequiresGetCallFuture<Foo>(foo1); 665 final Foo foo2 = new Foo(); 666 MockRequiresGetCallFuture<Foo> foo2Future = 667 new MockRequiresGetCallFuture<Foo>(foo2); 668 669 @SuppressWarnings("unchecked") // array is never modified 670 ListenableFuture<List<Foo>> compound = 671 Futures.allAsList(foo1Future, foo2Future); 672 673 assertFalse(compound.isDone()); 674 ASSERT.that(compound.get()).hasContentsAnyOrder(foo1, foo2); 675 assertTrue(foo1Future.getWasGetCalled()); 676 assertTrue(foo2Future.getWasGetCalled()); 677 } 678 679 /** 680 * Test the case where the futures are fulfilled prior to 681 * constructing the ListFuture. There was a bug where the 682 * loop that connects a Listener to each of the futures would die 683 * on the last loop-check as done() on ListFuture nulled out the 684 * variable being looped over (the list of futures). 685 */ 686 public void testAllAsList_doneFutures() throws Exception { 687 // Create input and output 688 SettableFuture<String> future1 = SettableFuture.create(); 689 SettableFuture<String> future2 = SettableFuture.create(); 690 SettableFuture<String> future3 = SettableFuture.create(); 691 692 // Satisfy each input prior to creating compound and check the output 693 future1.set(DATA1); 694 future2.set(DATA2); 695 future3.set(DATA3); 696 697 @SuppressWarnings("unchecked") // array is never modified 698 ListenableFuture<List<String>> compound = 699 Futures.allAsList(future1, future2, future3); 700 701 // Attach a listener 702 SingleCallListener listener = new SingleCallListener(); 703 listener.expectCall(); 704 compound.addListener(listener, MoreExecutors.sameThreadExecutor()); 705 706 assertTrue(compound.isDone()); 707 assertTrue(listener.wasCalled()); 708 709 List<String> results = compound.get(); 710 ASSERT.that(results).hasContentsInOrder(DATA1, DATA2, DATA3); 711 } 712 713 private String createCombinedResult(Integer i, Boolean b) { 714 return "-" + i + "-" + b; 715 } 716 717 /* 718 * TODO(cpovirk): maybe pass around TestFuture instances instead of 719 * ListenableFuture instances 720 */ 721 /** 722 * A future in {@link TestFutureBatch} that also has a name for debugging 723 * purposes and a {@code finisher}, a task that will complete the future in 724 * some fashion when it is called, allowing for testing both before and after 725 * the completion of the future. 726 */ 727 private static final class TestFuture { 728 final ListenableFuture<String> future; 729 final String name; 730 final Runnable finisher; 731 732 TestFuture( 733 ListenableFuture<String> future, String name, Runnable finisher) { 734 this.future = future; 735 this.name = name; 736 this.finisher = finisher; 737 } 738 } 739 740 /** 741 * A collection of several futures, covering cancellation, success, and 742 * failure (both {@link ExecutionException} and {@link RuntimeException}), 743 * both immediate and delayed. We use each possible pair of these futures in 744 * {@link FuturesTest#runExtensiveMergerTest}. 745 * 746 * <p>Each test requires a new {@link TestFutureBatch} because we need new 747 * delayed futures each time, as the old delayed futures were completed as 748 * part of the old test. 749 */ 750 private static final class TestFutureBatch { 751 final ListenableFuture<String> doneSuccess = immediateFuture("a"); 752 final ListenableFuture<String> doneFailed = 753 immediateFailedFuture(new Exception()); 754 final SettableFuture<String> doneCancelled = SettableFuture.create(); 755 { 756 doneCancelled.cancel(true); 757 } 758 759 final ListenableFuture<String> doneRuntimeException = 760 new ForwardingListenableFuture<String>() { 761 final ListenableFuture<String> delegate = 762 immediateFuture("Should never be seen"); 763 764 @Override 765 protected ListenableFuture<String> delegate() { 766 return delegate; 767 } 768 769 @Override 770 public String get() { 771 throw new RuntimeException(); 772 } 773 774 @Override 775 public String get(long timeout, TimeUnit unit) { 776 throw new RuntimeException(); 777 } 778 }; 779 780 final SettableFuture<String> delayedSuccess = SettableFuture.create(); 781 final SettableFuture<String> delayedFailed = SettableFuture.create(); 782 final SettableFuture<String> delayedCancelled = SettableFuture.create(); 783 784 final SettableFuture<String> delegateForDelayedRuntimeException = 785 SettableFuture.create(); 786 final ListenableFuture<String> delayedRuntimeException = 787 new ForwardingListenableFuture<String>() { 788 @Override 789 protected ListenableFuture<String> delegate() { 790 return delegateForDelayedRuntimeException; 791 } 792 793 @Override 794 public String get() throws ExecutionException, InterruptedException { 795 delegateForDelayedRuntimeException.get(); 796 throw new RuntimeException(); 797 } 798 799 @Override 800 public String get(long timeout, TimeUnit unit) throws 801 ExecutionException, InterruptedException, TimeoutException { 802 delegateForDelayedRuntimeException.get(timeout, unit); 803 throw new RuntimeException(); 804 } 805 }; 806 807 final Runnable doNothing = new Runnable() { 808 @Override 809 public void run() { 810 } 811 }; 812 final Runnable finishSuccess = new Runnable() { 813 @Override 814 public void run() { 815 delayedSuccess.set("b"); 816 } 817 }; 818 final Runnable finishFailure = new Runnable() { 819 @Override 820 public void run() { 821 delayedFailed.setException(new Exception()); 822 } 823 }; 824 final Runnable finishCancelled = new Runnable() { 825 @Override 826 public void run() { 827 delayedCancelled.cancel(true); 828 } 829 }; 830 final Runnable finishRuntimeException = new Runnable() { 831 @Override 832 public void run() { 833 delegateForDelayedRuntimeException.set("Should never be seen"); 834 } 835 }; 836 837 /** 838 * All the futures, together with human-readable names for use by 839 * {@link #smartToString}. 840 */ 841 final ImmutableList<TestFuture> allFutures = 842 ImmutableList.of(new TestFuture(doneSuccess, "doneSuccess", doNothing), 843 new TestFuture(doneFailed, "doneFailed", doNothing), 844 new TestFuture(doneCancelled, "doneCancelled", doNothing), 845 new TestFuture( 846 doneRuntimeException, "doneRuntimeException", doNothing), 847 new TestFuture(delayedSuccess, "delayedSuccess", finishSuccess), 848 new TestFuture(delayedFailed, "delayedFailed", finishFailure), 849 new TestFuture( 850 delayedCancelled, "delayedCancelled", finishCancelled), 851 new TestFuture(delayedRuntimeException, "delayedRuntimeException", 852 finishRuntimeException)); 853 854 final Function<ListenableFuture<String>, String> nameGetter = 855 new Function<ListenableFuture<String>, String>() { 856 @Override 857 public String apply(ListenableFuture<String> input) { 858 for (TestFuture future : allFutures) { 859 if (future.future == input) { 860 return future.name; 861 } 862 } 863 throw new IllegalArgumentException(input.toString()); 864 } 865 }; 866 867 static boolean intersect(Set<?> a, Set<?> b) { 868 return !Sets.intersection(a, b).isEmpty(); 869 } 870 871 /** 872 * Like {@code inputs.toString()}, but with the nonsense {@code toString} 873 * representations replaced with the name of each future from 874 * {@link #allFutures}. 875 */ 876 String smartToString(ImmutableSet<ListenableFuture<String>> inputs) { 877 Iterable<String> inputNames = Iterables.transform(inputs, nameGetter); 878 return Joiner.on(", ").join(inputNames); 879 } 880 881 void smartAssertTrue(ImmutableSet<ListenableFuture<String>> inputs, 882 Exception cause, boolean expression) { 883 if (!expression) { 884 failWithCause(cause, smartToString(inputs)); 885 } 886 } 887 888 boolean hasDelayed(ListenableFuture<String> a, ListenableFuture<String> b) { 889 ImmutableSet<ListenableFuture<String>> inputs = ImmutableSet.of(a, b); 890 return intersect(inputs, ImmutableSet.of( 891 delayedSuccess, delayedFailed, delayedCancelled, 892 delayedRuntimeException)); 893 } 894 895 void assertHasDelayed( 896 ListenableFuture<String> a, ListenableFuture<String> b, Exception e) { 897 ImmutableSet<ListenableFuture<String>> inputs = ImmutableSet.of(a, b); 898 smartAssertTrue(inputs, e, hasDelayed(a, b)); 899 } 900 901 void assertHasFailure( 902 ListenableFuture<String> a, ListenableFuture<String> b, Exception e) { 903 ImmutableSet<ListenableFuture<String>> inputs = ImmutableSet.of(a, b); 904 smartAssertTrue(inputs, e, intersect(inputs, ImmutableSet.of(doneFailed, 905 doneRuntimeException, delayedFailed, delayedRuntimeException))); 906 } 907 908 void assertHasCancel( 909 ListenableFuture<String> a, ListenableFuture<String> b, Exception e) { 910 ImmutableSet<ListenableFuture<String>> inputs = ImmutableSet.of(a, b); 911 smartAssertTrue(inputs, e, 912 intersect(inputs, ImmutableSet.of(doneCancelled, delayedCancelled))); 913 } 914 915 void assertHasImmediateFailure( 916 ListenableFuture<String> a, ListenableFuture<String> b, Exception e) { 917 ImmutableSet<ListenableFuture<String>> inputs = ImmutableSet.of(a, b); 918 smartAssertTrue(inputs, e, intersect( 919 inputs, ImmutableSet.of(doneFailed, doneRuntimeException))); 920 } 921 922 void assertHasImmediateCancel( 923 ListenableFuture<String> a, ListenableFuture<String> b, Exception e) { 924 ImmutableSet<ListenableFuture<String>> inputs = ImmutableSet.of(a, b); 925 smartAssertTrue(inputs, e, 926 intersect(inputs, ImmutableSet.of(doneCancelled))); 927 } 928 } 929 930 /** 931 * {@link Futures#allAsList(Iterable)} or 932 * {@link Futures#successfulAsList(Iterable)}, hidden behind a common 933 * interface for testing. 934 */ 935 private interface Merger { 936 ListenableFuture<List<String>> merged( 937 ListenableFuture<String> a, ListenableFuture<String> b); 938 939 Merger allMerger = new Merger() { 940 @Override 941 public ListenableFuture<List<String>> merged( 942 ListenableFuture<String> a, ListenableFuture<String> b) { 943 return allAsList(ImmutableSet.of(a, b)); 944 } 945 }; 946 Merger successMerger = new Merger() { 947 @Override 948 public ListenableFuture<List<String>> merged( 949 ListenableFuture<String> a, ListenableFuture<String> b) { 950 return successfulAsList(ImmutableSet.of(a, b)); 951 } 952 }; 953 } 954 955 /** 956 * Very rough equivalent of a timed get, produced by calling the no-arg get 957 * method in another thread and waiting a short time for it. 958 * 959 * <p>We need this to test the behavior of no-arg get methods without hanging 960 * the main test thread forever in the case of failure. 961 */ 962 private static <V> V pseudoTimedGet( 963 final Future<V> input, long timeout, TimeUnit unit) 964 throws InterruptedException, ExecutionException, TimeoutException { 965 ExecutorService executor = newSingleThreadExecutor(); 966 Future<V> waiter = executor.submit(new Callable<V>() { 967 @Override 968 public V call() throws Exception { 969 return input.get(); 970 } 971 }); 972 973 try { 974 return waiter.get(timeout, unit); 975 } catch (ExecutionException e) { 976 propagateIfInstanceOf(e.getCause(), ExecutionException.class); 977 propagateIfInstanceOf(e.getCause(), CancellationException.class); 978 AssertionFailedError error = 979 new AssertionFailedError("Unexpected exception"); 980 error.initCause(e); 981 throw error; 982 } finally { 983 executor.shutdownNow(); 984 assertTrue(executor.awaitTermination(10, SECONDS)); 985 } 986 } 987 988 /** 989 * For each possible pair of futures from {@link TestFutureBatch}, for each 990 * possible completion order of those futures, test that various get calls 991 * (timed before future completion, untimed before future completion, and 992 * untimed after future completion) return or throw the proper values. 993 */ 994 private static void runExtensiveMergerTest(Merger merger) 995 throws InterruptedException { 996 int inputCount = new TestFutureBatch().allFutures.size(); 997 998 for (int i = 0; i < inputCount; i++) { 999 for (int j = 0; j < inputCount; j++) { 1000 for (boolean iBeforeJ : new boolean[] { true, false }) { 1001 TestFutureBatch inputs = new TestFutureBatch(); 1002 ListenableFuture<String> iFuture = inputs.allFutures.get(i).future; 1003 ListenableFuture<String> jFuture = inputs.allFutures.get(j).future; 1004 ListenableFuture<List<String>> future = 1005 merger.merged(iFuture, jFuture); 1006 1007 // Test timed get before we've completed any delayed futures. 1008 try { 1009 List<String> result = future.get(0, MILLISECONDS); 1010 assertTrue("Got " + result, 1011 Arrays.asList("a", null).containsAll(result)); 1012 } catch (CancellationException e) { 1013 assertTrue(merger == Merger.allMerger); 1014 inputs.assertHasImmediateCancel(iFuture, jFuture, e); 1015 } catch (ExecutionException e) { 1016 assertTrue(merger == Merger.allMerger); 1017 inputs.assertHasImmediateFailure(iFuture, jFuture, e); 1018 } catch (TimeoutException e) { 1019 inputs.assertHasDelayed(iFuture, jFuture, e); 1020 } 1021 1022 // Same tests with pseudoTimedGet. 1023 try { 1024 List<String> result = conditionalPseudoTimedGet( 1025 inputs, iFuture, jFuture, future, 20, MILLISECONDS); 1026 assertTrue("Got " + result, 1027 Arrays.asList("a", null).containsAll(result)); 1028 } catch (CancellationException e) { 1029 assertTrue(merger == Merger.allMerger); 1030 inputs.assertHasImmediateCancel(iFuture, jFuture, e); 1031 } catch (ExecutionException e) { 1032 assertTrue(merger == Merger.allMerger); 1033 inputs.assertHasImmediateFailure(iFuture, jFuture, e); 1034 } catch (TimeoutException e) { 1035 inputs.assertHasDelayed(iFuture, jFuture, e); 1036 } 1037 1038 // Finish the two futures in the currently specified order: 1039 inputs.allFutures.get(iBeforeJ ? i : j).finisher.run(); 1040 inputs.allFutures.get(iBeforeJ ? j : i).finisher.run(); 1041 1042 // Test untimed get now that we've completed any delayed futures. 1043 try { 1044 List<String> result = future.get(); 1045 assertTrue("Got " + result, 1046 Arrays.asList("a", "b", null).containsAll(result)); 1047 } catch (CancellationException e) { 1048 assertTrue(merger == Merger.allMerger); 1049 inputs.assertHasCancel(iFuture, jFuture, e); 1050 } catch (ExecutionException e) { 1051 assertTrue(merger == Merger.allMerger); 1052 inputs.assertHasFailure(iFuture, jFuture, e); 1053 } 1054 } 1055 } 1056 } 1057 } 1058 1059 /** 1060 * Call the non-timed {@link Future#get()} in a way that allows us to abort if 1061 * it's expected to hang forever. More precisely, if it's expected to return, 1062 * we simply call it[*], but if it's expected to hang (because one of the 1063 * input futures that we know makes it up isn't done yet), then we call it in 1064 * a separate thread (using pseudoTimedGet). The result is that we wait as 1065 * long as necessary when the method is expected to return (at the cost of 1066 * hanging forever if there is a bug in the class under test) but that we time 1067 * out fairly promptly when the method is expected to hang (possibly too 1068 * quickly, but too-quick failures should be very unlikely, given that we used 1069 * to bail after 20ms during the expected-successful tests, and there we saw a 1070 * failure rate of ~1/5000, meaning that the other thread's get() call nearly 1071 * always completes within 20ms if it's going to complete at all). 1072 * 1073 * [*] To avoid hangs, I've disabled the in-thread calls. This makes the test 1074 * take (very roughly) 2.5s longer. (2.5s is also the maximum length of time 1075 * we will wait for a timed get that is expected to succeed; the fact that the 1076 * numbers match is only a coincidence.) See the comment below for how to 1077 * restore the fast but hang-y version. 1078 */ 1079 private static List<String> conditionalPseudoTimedGet( 1080 TestFutureBatch inputs, 1081 ListenableFuture<String> iFuture, 1082 ListenableFuture<String> jFuture, 1083 ListenableFuture<List<String>> future, 1084 int timeout, 1085 TimeUnit unit) 1086 throws InterruptedException, ExecutionException, TimeoutException { 1087 /* 1088 * For faster tests (that may hang indefinitely if the class under test has 1089 * a bug!), switch the second branch to call untimed future.get() instead of 1090 * pseudoTimedGet. 1091 */ 1092 return (inputs.hasDelayed(iFuture, jFuture)) 1093 ? pseudoTimedGet(future, timeout, unit) 1094 : pseudoTimedGet(future, 2500, MILLISECONDS); 1095 } 1096 1097 public void testAllAsList_extensive() throws InterruptedException { 1098 runExtensiveMergerTest(Merger.allMerger); 1099 } 1100 1101 public void testSuccessfulAsList_extensive() throws InterruptedException { 1102 runExtensiveMergerTest(Merger.successMerger); 1103 } 1104 1105 public void testSuccessfulAsList() throws Exception { 1106 // Create input and output 1107 SettableFuture<String> future1 = SettableFuture.create(); 1108 SettableFuture<String> future2 = SettableFuture.create(); 1109 SettableFuture<String> future3 = SettableFuture.create(); 1110 @SuppressWarnings("unchecked") // array is never modified 1111 ListenableFuture<List<String>> compound = 1112 Futures.successfulAsList(future1, future2, future3); 1113 1114 // Attach a listener 1115 SingleCallListener listener = new SingleCallListener(); 1116 compound.addListener(listener, MoreExecutors.sameThreadExecutor()); 1117 1118 // Satisfy each input and check the output 1119 assertFalse(compound.isDone()); 1120 future1.set(DATA1); 1121 assertFalse(compound.isDone()); 1122 future2.set(DATA2); 1123 assertFalse(compound.isDone()); 1124 listener.expectCall(); 1125 future3.set(DATA3); 1126 assertTrue(compound.isDone()); 1127 assertTrue(listener.wasCalled()); 1128 1129 List<String> results = compound.get(); 1130 ASSERT.that(results).hasContentsInOrder(DATA1, DATA2, DATA3); 1131 } 1132 1133 public void testSuccessfulAsList_emptyList() throws Exception { 1134 SingleCallListener listener = new SingleCallListener(); 1135 listener.expectCall(); 1136 List<ListenableFuture<String>> futures = ImmutableList.of(); 1137 ListenableFuture<List<String>> compound = Futures.successfulAsList(futures); 1138 compound.addListener(listener, MoreExecutors.sameThreadExecutor()); 1139 assertTrue(compound.isDone()); 1140 assertTrue(compound.get().isEmpty()); 1141 assertTrue(listener.wasCalled()); 1142 } 1143 1144 public void testSuccessfulAsList_emptyArray() throws Exception { 1145 SingleCallListener listener = new SingleCallListener(); 1146 listener.expectCall(); 1147 @SuppressWarnings("unchecked") // array is never modified 1148 ListenableFuture<List<String>> compound = Futures.successfulAsList(); 1149 compound.addListener(listener, MoreExecutors.sameThreadExecutor()); 1150 assertTrue(compound.isDone()); 1151 assertTrue(compound.get().isEmpty()); 1152 assertTrue(listener.wasCalled()); 1153 } 1154 1155 public void testSuccessfulAsList_partialFailure() throws Exception { 1156 SingleCallListener listener = new SingleCallListener(); 1157 SettableFuture<String> future1 = SettableFuture.create(); 1158 SettableFuture<String> future2 = SettableFuture.create(); 1159 @SuppressWarnings("unchecked") // array is never modified 1160 ListenableFuture<List<String>> compound = 1161 Futures.successfulAsList(future1, future2); 1162 compound.addListener(listener, MoreExecutors.sameThreadExecutor()); 1163 1164 assertFalse(compound.isDone()); 1165 future1.setException(new Throwable("failed1")); 1166 assertFalse(compound.isDone()); 1167 listener.expectCall(); 1168 future2.set(DATA2); 1169 assertTrue(compound.isDone()); 1170 assertTrue(listener.wasCalled()); 1171 1172 List<String> results = compound.get(); 1173 ASSERT.that(results).hasContentsInOrder(null, DATA2); 1174 } 1175 1176 public void testSuccessfulAsList_totalFailure() throws Exception { 1177 SingleCallListener listener = new SingleCallListener(); 1178 SettableFuture<String> future1 = SettableFuture.create(); 1179 SettableFuture<String> future2 = SettableFuture.create(); 1180 @SuppressWarnings("unchecked") // array is never modified 1181 ListenableFuture<List<String>> compound = 1182 Futures.successfulAsList(future1, future2); 1183 compound.addListener(listener, MoreExecutors.sameThreadExecutor()); 1184 1185 assertFalse(compound.isDone()); 1186 future1.setException(new Throwable("failed1")); 1187 assertFalse(compound.isDone()); 1188 listener.expectCall(); 1189 future2.setException(new Throwable("failed2")); 1190 assertTrue(compound.isDone()); 1191 assertTrue(listener.wasCalled()); 1192 1193 List<String> results = compound.get(); 1194 ASSERT.that(results).hasContentsInOrder(null, null); 1195 } 1196 1197 public void testSuccessfulAsList_cancelled() throws Exception { 1198 SingleCallListener listener = new SingleCallListener(); 1199 SettableFuture<String> future1 = SettableFuture.create(); 1200 SettableFuture<String> future2 = SettableFuture.create(); 1201 @SuppressWarnings("unchecked") // array is never modified 1202 ListenableFuture<List<String>> compound = 1203 Futures.successfulAsList(future1, future2); 1204 compound.addListener(listener, MoreExecutors.sameThreadExecutor()); 1205 1206 assertFalse(compound.isDone()); 1207 future1.cancel(true); 1208 assertFalse(compound.isDone()); 1209 listener.expectCall(); 1210 future2.set(DATA2); 1211 assertTrue(compound.isDone()); 1212 assertTrue(listener.wasCalled()); 1213 1214 List<String> results = compound.get(); 1215 ASSERT.that(results).hasContentsInOrder(null, DATA2); 1216 } 1217 1218 public void testSuccessfulAsList_mixed() throws Exception { 1219 SingleCallListener listener = new SingleCallListener(); 1220 SettableFuture<String> future1 = SettableFuture.create(); 1221 SettableFuture<String> future2 = SettableFuture.create(); 1222 SettableFuture<String> future3 = SettableFuture.create(); 1223 @SuppressWarnings("unchecked") // array is never modified 1224 ListenableFuture<List<String>> compound = 1225 Futures.successfulAsList(future1, future2, future3); 1226 compound.addListener(listener, MoreExecutors.sameThreadExecutor()); 1227 1228 // First is cancelled, second fails, third succeeds 1229 assertFalse(compound.isDone()); 1230 future1.cancel(true); 1231 assertFalse(compound.isDone()); 1232 future2.setException(new Throwable("failed2")); 1233 assertFalse(compound.isDone()); 1234 listener.expectCall(); 1235 future3.set(DATA3); 1236 assertTrue(compound.isDone()); 1237 assertTrue(listener.wasCalled()); 1238 1239 List<String> results = compound.get(); 1240 ASSERT.that(results).hasContentsInOrder(null, null, DATA3); 1241 } 1242 1243 public void testSuccessfulAsList_buggyInputFutures() throws Exception { 1244 final Foo foo1 = new Foo(); 1245 MockRequiresGetCallFuture<Foo> foo1Future = 1246 new MockRequiresGetCallFuture<Foo>(foo1); 1247 final Foo foo2 = new Foo(); 1248 MockRequiresGetCallFuture<Foo> foo2Future = 1249 new MockRequiresGetCallFuture<Foo>(foo2); 1250 1251 @SuppressWarnings("unchecked") // array is never modified 1252 ListenableFuture<List<Foo>> compound = 1253 Futures.successfulAsList(foo1Future, foo2Future); 1254 1255 assertFalse(compound.isDone()); 1256 ASSERT.that(compound.get()).hasContentsAnyOrder(foo1, foo2); 1257 assertTrue(foo1Future.getWasGetCalled()); 1258 assertTrue(foo2Future.getWasGetCalled()); 1259 } 1260 1261 private static class TestException extends Exception { 1262 TestException(@Nullable Throwable cause) { 1263 super(cause); 1264 } 1265 } 1266 1267 private static final Function<Exception, TestException> mapper = 1268 new Function<Exception, TestException>() { 1269 @Override public TestException apply(Exception from) { 1270 if (from instanceof ExecutionException) { 1271 return new TestException(from.getCause()); 1272 } else { 1273 assertTrue("got " + from.getClass(), 1274 from instanceof InterruptedException 1275 || from instanceof CancellationException); 1276 return new TestException(from); 1277 } 1278 } 1279 }; 1280 1281 public void testMakeChecked_mapsExecutionExceptions() throws Exception { 1282 SettableFuture<String> future = SettableFuture.create(); 1283 1284 CheckedFuture<String, TestException> checked = Futures.makeChecked( 1285 future, mapper); 1286 1287 future.setException(new IOException("checked")); 1288 1289 assertTrue(checked.isDone()); 1290 assertFalse(checked.isCancelled()); 1291 1292 try { 1293 checked.get(); 1294 fail(); 1295 } catch (ExecutionException e) { 1296 assertTrue(e.getCause() instanceof IOException); 1297 } 1298 1299 try { 1300 checked.get(5, TimeUnit.SECONDS); 1301 fail(); 1302 } catch (ExecutionException e) { 1303 assertTrue(e.getCause() instanceof IOException); 1304 } 1305 1306 try { 1307 checked.checkedGet(); 1308 fail(); 1309 } catch (TestException e) { 1310 assertTrue(e.getCause() instanceof IOException); 1311 } 1312 1313 try { 1314 checked.checkedGet(5, TimeUnit.SECONDS); 1315 fail(); 1316 } catch (TestException e) { 1317 assertTrue(e.getCause() instanceof IOException); 1318 } 1319 } 1320 1321 public void testMakeChecked_mapsInterruption() throws Exception { 1322 SettableFuture<String> future = SettableFuture.create(); 1323 1324 CheckedFuture<String, TestException> checked = Futures.makeChecked( 1325 future, mapper); 1326 1327 Thread.currentThread().interrupt(); 1328 1329 try { 1330 checked.get(); 1331 fail(); 1332 } catch (InterruptedException e) { 1333 // Expected. 1334 } 1335 1336 Thread.currentThread().interrupt(); 1337 1338 try { 1339 checked.get(5, TimeUnit.SECONDS); 1340 fail(); 1341 } catch (InterruptedException e) { 1342 // Expected. 1343 } 1344 1345 Thread.currentThread().interrupt(); 1346 1347 try { 1348 checked.checkedGet(); 1349 fail(); 1350 } catch (TestException e) { 1351 assertTrue(e.getCause() instanceof InterruptedException); 1352 } 1353 1354 Thread.currentThread().interrupt(); 1355 1356 try { 1357 checked.checkedGet(5, TimeUnit.SECONDS); 1358 fail(); 1359 } catch (TestException e) { 1360 assertTrue(e.getCause() instanceof InterruptedException); 1361 } 1362 } 1363 1364 public void testMakeChecked_mapsCancellation() throws Exception { 1365 SettableFuture<String> future = SettableFuture.create(); 1366 1367 CheckedFuture<String, TestException> checked = Futures.makeChecked( 1368 future, mapper); 1369 1370 assertTrue(future.cancel(true)); // argument is ignored 1371 1372 try { 1373 checked.get(); 1374 fail(); 1375 } catch (CancellationException expected) {} 1376 1377 try { 1378 checked.get(5, TimeUnit.SECONDS); 1379 fail(); 1380 } catch (CancellationException expected) {} 1381 1382 try { 1383 checked.checkedGet(); 1384 fail(); 1385 } catch (TestException expected) { 1386 assertTrue(expected.getCause() instanceof CancellationException); 1387 } 1388 1389 try { 1390 checked.checkedGet(5, TimeUnit.SECONDS); 1391 fail(); 1392 } catch (TestException expected) { 1393 assertTrue(expected.getCause() instanceof CancellationException); 1394 } 1395 } 1396 1397 public void testMakeChecked_propagatesFailedMappers() throws Exception { 1398 SettableFuture<String> future = SettableFuture.create(); 1399 1400 CheckedFuture<String, TestException> checked = Futures.makeChecked( 1401 future, new Function<Exception, TestException>() { 1402 @Override public TestException apply(Exception from) { 1403 throw new NullPointerException(); 1404 } 1405 }); 1406 1407 future.setException(new Exception("failed")); 1408 1409 try { 1410 checked.checkedGet(); 1411 fail(); 1412 } catch (NullPointerException expected) {} 1413 1414 try { 1415 checked.checkedGet(5, TimeUnit.SECONDS); 1416 fail(); 1417 } catch (NullPointerException expected) {} 1418 } 1419 1420 public void testMakeChecked_listenersRunOnceCompleted() throws Exception { 1421 SettableFuture<String> future = SettableFuture.create(); 1422 1423 CheckedFuture<String, TestException> checked = Futures.makeChecked( 1424 future, new Function<Exception, TestException>() { 1425 @Override public TestException apply(Exception from) { 1426 throw new NullPointerException(); 1427 } 1428 }); 1429 1430 ListenableFutureTester tester = new ListenableFutureTester(checked); 1431 tester.setUp(); 1432 future.set(DATA1); 1433 tester.testCompletedFuture(DATA1); 1434 tester.tearDown(); 1435 } 1436 1437 public void testMakeChecked_listenersRunOnCancel() throws Exception { 1438 SettableFuture<String> future = SettableFuture.create(); 1439 1440 CheckedFuture<String, TestException> checked = Futures.makeChecked( 1441 future, new Function<Exception, TestException>() { 1442 @Override public TestException apply(Exception from) { 1443 throw new NullPointerException(); 1444 } 1445 }); 1446 1447 ListenableFutureTester tester = new ListenableFutureTester(checked); 1448 tester.setUp(); 1449 future.cancel(true); // argument is ignored 1450 tester.testCancelledFuture(); 1451 tester.tearDown(); 1452 } 1453 1454 public void testMakeChecked_listenersRunOnFailure() throws Exception { 1455 SettableFuture<String> future = SettableFuture.create(); 1456 1457 CheckedFuture<String, TestException> checked = Futures.makeChecked( 1458 future, new Function<Exception, TestException>() { 1459 @Override public TestException apply(Exception from) { 1460 throw new NullPointerException(); 1461 } 1462 }); 1463 1464 ListenableFutureTester tester = new ListenableFutureTester(checked); 1465 tester.setUp(); 1466 future.setException(new Exception("failed")); 1467 tester.testFailedFuture("failed"); 1468 tester.tearDown(); 1469 } 1470 1471 private interface MapperFunction extends Function<Throwable, Exception> {} 1472 1473 private static final class OtherThrowable extends Throwable {} 1474 1475 private static final Exception CHECKED_EXCEPTION = new Exception("mymessage"); 1476 private static final Future<String> FAILED_FUTURE_CHECKED_EXCEPTION = 1477 immediateFailedFuture(CHECKED_EXCEPTION); 1478 private static final RuntimeException UNCHECKED_EXCEPTION = 1479 new RuntimeException("mymessage"); 1480 private static final Future<String> FAILED_FUTURE_UNCHECKED_EXCEPTION = 1481 immediateFailedFuture(UNCHECKED_EXCEPTION); 1482 private static final RuntimeException RUNTIME_EXCEPTION = 1483 new RuntimeException(); 1484 private static final OtherThrowable OTHER_THROWABLE = new OtherThrowable(); 1485 private static final Future<String> FAILED_FUTURE_OTHER_THROWABLE = 1486 immediateFailedFuture(OTHER_THROWABLE); 1487 private static final Error ERROR = new Error("mymessage"); 1488 private static final Future<String> FAILED_FUTURE_ERROR; 1489 /* 1490 * We can't write "= immediateFailedFuture(ERROR)" because setException 1491 * rethrows the error.... 1492 */ 1493 static { 1494 SettableFuture<String> f = SettableFuture.create(); 1495 try { 1496 f.setException(ERROR); 1497 } catch (Error e) { 1498 assertEquals(e, ERROR); 1499 } 1500 FAILED_FUTURE_ERROR = f; 1501 } 1502 private static final Future<String> RUNTIME_EXCEPTION_FUTURE = 1503 new SimpleForwardingFuture<String>(FAILED_FUTURE_CHECKED_EXCEPTION) { 1504 @Override public String get() { 1505 throw RUNTIME_EXCEPTION; 1506 } 1507 1508 @Override public String get(long timeout, TimeUnit unit) { 1509 throw RUNTIME_EXCEPTION; 1510 } 1511 }; 1512 1513 // Boring untimed-get tests: 1514 1515 public void testGetUntimed_success() 1516 throws TwoArgConstructorException { 1517 assertEquals("foo", 1518 get(immediateFuture("foo"), TwoArgConstructorException.class)); 1519 } 1520 1521 public void testGetUntimed_interrupted() { 1522 Thread.currentThread().interrupt(); 1523 try { 1524 get(immediateFuture("foo"), TwoArgConstructorException.class); 1525 fail(); 1526 } catch (TwoArgConstructorException expected) { 1527 assertTrue(expected.getCause() instanceof InterruptedException); 1528 assertTrue(Thread.currentThread().isInterrupted()); 1529 } finally { 1530 Thread.interrupted(); 1531 } 1532 } 1533 1534 public void testGetUntimed_cancelled() 1535 throws TwoArgConstructorException { 1536 SettableFuture<String> future = SettableFuture.create(); 1537 future.cancel(true); 1538 try { 1539 get(future, TwoArgConstructorException.class); 1540 fail(); 1541 } catch (CancellationException expected) { 1542 } 1543 } 1544 1545 public void testGetUntimed_ExecutionExceptionChecked() { 1546 try { 1547 get(FAILED_FUTURE_CHECKED_EXCEPTION, TwoArgConstructorException.class); 1548 fail(); 1549 } catch (TwoArgConstructorException expected) { 1550 assertEquals(CHECKED_EXCEPTION, expected.getCause()); 1551 } 1552 } 1553 1554 public void testGetUntimed_ExecutionExceptionUnchecked() 1555 throws TwoArgConstructorException { 1556 try { 1557 get(FAILED_FUTURE_UNCHECKED_EXCEPTION, TwoArgConstructorException.class); 1558 fail(); 1559 } catch (UncheckedExecutionException expected) { 1560 assertEquals(UNCHECKED_EXCEPTION, expected.getCause()); 1561 } 1562 } 1563 1564 public void testGetUntimed_ExecutionExceptionError() 1565 throws TwoArgConstructorException { 1566 try { 1567 get(FAILED_FUTURE_ERROR, TwoArgConstructorException.class); 1568 fail(); 1569 } catch (ExecutionError expected) { 1570 assertEquals(ERROR, expected.getCause()); 1571 } 1572 } 1573 1574 public void testGetUntimed_ExecutionExceptionOtherThrowable() { 1575 try { 1576 get(FAILED_FUTURE_OTHER_THROWABLE, TwoArgConstructorException.class); 1577 fail(); 1578 } catch (TwoArgConstructorException expected) { 1579 assertEquals(OTHER_THROWABLE, expected.getCause()); 1580 } 1581 } 1582 1583 public void testGetUntimed_RuntimeException() 1584 throws TwoArgConstructorException { 1585 try { 1586 get(RUNTIME_EXCEPTION_FUTURE, TwoArgConstructorException.class); 1587 fail(); 1588 } catch (RuntimeException expected) { 1589 assertEquals(RUNTIME_EXCEPTION, expected); 1590 } 1591 } 1592 1593 // Boring timed-get tests: 1594 1595 public void testGetTimed_success() 1596 throws TwoArgConstructorException { 1597 assertEquals("foo", get( 1598 immediateFuture("foo"), 0, SECONDS, TwoArgConstructorException.class)); 1599 } 1600 1601 public void testGetTimed_interrupted() { 1602 Thread.currentThread().interrupt(); 1603 try { 1604 get(immediateFuture("foo"), 0, SECONDS, TwoArgConstructorException.class); 1605 fail(); 1606 } catch (TwoArgConstructorException expected) { 1607 assertTrue(expected.getCause() instanceof InterruptedException); 1608 assertTrue(Thread.currentThread().isInterrupted()); 1609 } finally { 1610 Thread.interrupted(); 1611 } 1612 } 1613 1614 public void testGetTimed_cancelled() 1615 throws TwoArgConstructorException { 1616 SettableFuture<String> future = SettableFuture.create(); 1617 future.cancel(true); 1618 try { 1619 get(future, 0, SECONDS, TwoArgConstructorException.class); 1620 fail(); 1621 } catch (CancellationException expected) { 1622 } 1623 } 1624 1625 public void testGetTimed_ExecutionExceptionChecked() { 1626 try { 1627 get(FAILED_FUTURE_CHECKED_EXCEPTION, 0, SECONDS, 1628 TwoArgConstructorException.class); 1629 fail(); 1630 } catch (TwoArgConstructorException expected) { 1631 assertEquals(CHECKED_EXCEPTION, expected.getCause()); 1632 } 1633 } 1634 1635 public void testGetTimed_ExecutionExceptionUnchecked() 1636 throws TwoArgConstructorException { 1637 try { 1638 get(FAILED_FUTURE_UNCHECKED_EXCEPTION, 0, SECONDS, 1639 TwoArgConstructorException.class); 1640 fail(); 1641 } catch (UncheckedExecutionException expected) { 1642 assertEquals(UNCHECKED_EXCEPTION, expected.getCause()); 1643 } 1644 } 1645 1646 public void testGetTimed_ExecutionExceptionError() 1647 throws TwoArgConstructorException { 1648 try { 1649 get(FAILED_FUTURE_ERROR, 0, SECONDS, TwoArgConstructorException.class); 1650 fail(); 1651 } catch (ExecutionError expected) { 1652 assertEquals(ERROR, expected.getCause()); 1653 } 1654 } 1655 1656 public void testGetTimed_ExecutionExceptionOtherThrowable() { 1657 try { 1658 get(FAILED_FUTURE_OTHER_THROWABLE, 0, SECONDS, 1659 TwoArgConstructorException.class); 1660 fail(); 1661 } catch (TwoArgConstructorException expected) { 1662 assertEquals(OTHER_THROWABLE, expected.getCause()); 1663 } 1664 } 1665 1666 public void testGetTimed_RuntimeException() 1667 throws TwoArgConstructorException { 1668 try { 1669 get(RUNTIME_EXCEPTION_FUTURE, 0, SECONDS, 1670 TwoArgConstructorException.class); 1671 fail(); 1672 } catch (RuntimeException expected) { 1673 assertEquals(RUNTIME_EXCEPTION, expected); 1674 } 1675 } 1676 1677 public void testGetTimed_TimeoutException() { 1678 SettableFuture<String> future = SettableFuture.create(); 1679 try { 1680 get(future, 0, SECONDS, TwoArgConstructorException.class); 1681 fail(); 1682 } catch (TwoArgConstructorException expected) { 1683 assertTrue(expected.getCause() instanceof TimeoutException); 1684 } 1685 } 1686 1687 // Boring getUnchecked tests: 1688 1689 public void testGetUnchecked_success() { 1690 assertEquals("foo", getUnchecked(immediateFuture("foo"))); 1691 } 1692 1693 public void testGetUnchecked_interrupted() { 1694 Thread.currentThread().interrupt(); 1695 try { 1696 assertEquals("foo", getUnchecked(immediateFuture("foo"))); 1697 assertTrue(Thread.currentThread().isInterrupted()); 1698 } finally { 1699 Thread.interrupted(); 1700 } 1701 } 1702 1703 public void testGetUnchecked_cancelled() { 1704 SettableFuture<String> future = SettableFuture.create(); 1705 future.cancel(true); 1706 try { 1707 getUnchecked(future); 1708 fail(); 1709 } catch (CancellationException expected) { 1710 } 1711 } 1712 1713 public void testGetUnchecked_ExecutionExceptionChecked() { 1714 try { 1715 getUnchecked(FAILED_FUTURE_CHECKED_EXCEPTION); 1716 fail(); 1717 } catch (UncheckedExecutionException expected) { 1718 assertEquals(CHECKED_EXCEPTION, expected.getCause()); 1719 } 1720 } 1721 1722 public void testGetUnchecked_ExecutionExceptionUnchecked() { 1723 try { 1724 getUnchecked(FAILED_FUTURE_UNCHECKED_EXCEPTION); 1725 fail(); 1726 } catch (UncheckedExecutionException expected) { 1727 assertEquals(UNCHECKED_EXCEPTION, expected.getCause()); 1728 } 1729 } 1730 1731 public void testGetUnchecked_ExecutionExceptionError() { 1732 try { 1733 getUnchecked(FAILED_FUTURE_ERROR); 1734 fail(); 1735 } catch (ExecutionError expected) { 1736 assertEquals(ERROR, expected.getCause()); 1737 } 1738 } 1739 1740 public void testGetUnchecked_ExecutionExceptionOtherThrowable() { 1741 try { 1742 getUnchecked(FAILED_FUTURE_OTHER_THROWABLE); 1743 fail(); 1744 } catch (UncheckedExecutionException expected) { 1745 assertEquals(OTHER_THROWABLE, expected.getCause()); 1746 } 1747 } 1748 1749 public void testGetUnchecked_RuntimeException() { 1750 try { 1751 getUnchecked(RUNTIME_EXCEPTION_FUTURE); 1752 fail(); 1753 } catch (RuntimeException expected) { 1754 assertEquals(RUNTIME_EXCEPTION, expected); 1755 } 1756 } 1757 1758 // Edge case tests of the exception-construction code through untimed get(): 1759 1760 public void testGetUntimed_exceptionClassIsRuntimeException() { 1761 try { 1762 get(FAILED_FUTURE_CHECKED_EXCEPTION, 1763 TwoArgConstructorRuntimeException.class); 1764 fail(); 1765 } catch (IllegalArgumentException expected) { 1766 } 1767 } 1768 1769 public void testGetUntimed_exceptionClassSomePublicConstructors() { 1770 try { 1771 get(FAILED_FUTURE_CHECKED_EXCEPTION, 1772 ExceptionWithSomePrivateConstructors.class); 1773 fail(); 1774 } catch (ExceptionWithSomePrivateConstructors expected) { 1775 } 1776 } 1777 1778 public void testGetUntimed_exceptionClassNoPublicConstructor() 1779 throws ExceptionWithPrivateConstructor { 1780 try { 1781 get(FAILED_FUTURE_CHECKED_EXCEPTION, 1782 ExceptionWithPrivateConstructor.class); 1783 fail(); 1784 } catch (IllegalArgumentException expected) { 1785 } 1786 } 1787 1788 public void testGetUntimed_exceptionClassPublicConstructorWrongType() 1789 throws ExceptionWithWrongTypesConstructor { 1790 try { 1791 get(FAILED_FUTURE_CHECKED_EXCEPTION, 1792 ExceptionWithWrongTypesConstructor.class); 1793 fail(); 1794 } catch (IllegalArgumentException expected) { 1795 } 1796 } 1797 1798 public void testGetUntimed_exceptionClassPrefersStringConstructor() { 1799 try { 1800 get(FAILED_FUTURE_CHECKED_EXCEPTION, 1801 ExceptionWithManyConstructors.class); 1802 fail(); 1803 } catch (ExceptionWithManyConstructors expected) { 1804 assertTrue(expected.usedExpectedConstructor); 1805 } 1806 } 1807 1808 public void testGetUntimed_exceptionClassUsedInitCause() { 1809 try { 1810 get(FAILED_FUTURE_CHECKED_EXCEPTION, 1811 ExceptionWithoutThrowableConstructor.class); 1812 fail(); 1813 } catch (ExceptionWithoutThrowableConstructor expected) { 1814 ASSERT.that(expected.getMessage()).contains("mymessage"); 1815 assertEquals(CHECKED_EXCEPTION, expected.getCause()); 1816 } 1817 } 1818 1819 public static final class TwoArgConstructorException extends Exception { 1820 public TwoArgConstructorException(String message, Throwable cause) { 1821 super(message, cause); 1822 } 1823 } 1824 1825 public static final class TwoArgConstructorRuntimeException 1826 extends RuntimeException { 1827 public TwoArgConstructorRuntimeException(String message, Throwable cause) { 1828 super(message, cause); 1829 } 1830 } 1831 1832 public static final class ExceptionWithPrivateConstructor extends Exception { 1833 private ExceptionWithPrivateConstructor(String message, Throwable cause) { 1834 super(message, cause); 1835 } 1836 } 1837 1838 @SuppressWarnings("unused") // we're testing that they're not used 1839 public static final class ExceptionWithSomePrivateConstructors 1840 extends Exception { 1841 private ExceptionWithSomePrivateConstructors(String a) { 1842 } 1843 1844 private ExceptionWithSomePrivateConstructors(String a, String b) { 1845 } 1846 1847 public ExceptionWithSomePrivateConstructors( 1848 String a, String b, String c) { 1849 } 1850 1851 private ExceptionWithSomePrivateConstructors( 1852 String a, String b, String c, String d) { 1853 } 1854 1855 private ExceptionWithSomePrivateConstructors( 1856 String a, String b, String c, String d, String e) { 1857 } 1858 } 1859 1860 public static final class ExceptionWithManyConstructors extends Exception { 1861 boolean usedExpectedConstructor; 1862 1863 public ExceptionWithManyConstructors() { 1864 } 1865 1866 public ExceptionWithManyConstructors(Integer i) { 1867 } 1868 1869 public ExceptionWithManyConstructors(Throwable a) { 1870 } 1871 1872 public ExceptionWithManyConstructors(Throwable a, Throwable b) { 1873 } 1874 1875 public ExceptionWithManyConstructors(String s, Throwable b) { 1876 usedExpectedConstructor = true; 1877 } 1878 1879 public ExceptionWithManyConstructors( 1880 Throwable a, Throwable b, Throwable c) { 1881 } 1882 1883 public ExceptionWithManyConstructors( 1884 Throwable a, Throwable b, Throwable c, Throwable d) { 1885 } 1886 1887 public ExceptionWithManyConstructors( 1888 Throwable a, Throwable b, Throwable c, Throwable d, Throwable e) { 1889 } 1890 1891 public ExceptionWithManyConstructors(Throwable a, Throwable b, Throwable c, 1892 Throwable d, Throwable e, String s, Integer i) { 1893 } 1894 } 1895 1896 public static final class ExceptionWithoutThrowableConstructor 1897 extends Exception { 1898 public ExceptionWithoutThrowableConstructor(String s) { 1899 super(s); 1900 } 1901 } 1902 1903 public static final class ExceptionWithWrongTypesConstructor 1904 extends Exception { 1905 public ExceptionWithWrongTypesConstructor(Integer i, String s) { 1906 super(s); 1907 } 1908 } 1909 1910 public void testNullArguments() throws Exception { 1911 NullPointerTester tester = new NullPointerTester(); 1912 tester.setDefault(ListenableFuture.class, Futures.immediateFuture(DATA1)); 1913 tester.setDefault(ListenableFuture[].class, 1914 new ListenableFuture[] {Futures.immediateFuture(DATA1)}); 1915 tester.setDefault(Future.class, Futures.immediateFuture(DATA1)); 1916 tester.setDefault(Executor.class, MoreExecutors.sameThreadExecutor()); 1917 tester.setDefault(Callable.class, Callables.returning(null)); 1918 tester.setDefault(AsyncFunction.class, new AsyncFunction() { 1919 @Override 1920 public ListenableFuture apply(Object input) throws Exception { 1921 return immediateFuture(DATA1); 1922 } 1923 }); 1924 1925 FutureCallback<Object> callback = 1926 new FutureCallback<Object>() { 1927 @Override 1928 public void onSuccess(Object result) {} 1929 @Override 1930 public void onFailure(Throwable t) {} 1931 }; 1932 tester.setDefault(FutureCallback.class, callback); 1933 1934 tester.testAllPublicStaticMethods(Futures.class); 1935 } 1936 1937 private static void failWithCause(Throwable cause, String message) { 1938 AssertionFailedError failure = new AssertionFailedError(message); 1939 failure.initCause(cause); 1940 throw failure; 1941 } 1942 } 1943