--- jsr166/src/test/tck/CompletableFutureTest.java 2014/06/16 17:41:26 1.81 +++ jsr166/src/test/tck/CompletableFutureTest.java 2014/06/16 20:20:08 1.84 @@ -3118,22 +3118,91 @@ public class CompletableFutureTest exten assertSame(f, f.toCompletableFuture()); } -// public void testRunAfterEither_resultDeterminedAtTimeOfCreation() { -// for (ExecutionMode m : ExecutionMode.values()) -// for (boolean mayInterruptIfRunning : new boolean[] { true, false }) -// for (Integer v1 : new Integer[] { 1, null }) -// { -// final CompletableFuture f = new CompletableFuture<>(); -// final CompletableFuture g = new CompletableFuture<>(); -// final Noop[] rs = new Noop[2]; -// for (int i = 0; i < rs.length; i++) rs[i] = new Noop(m); -// f.complete(v1); -// final CompletableFuture h0 = m.runAfterEither(f, g, rs[0]); -// final CompletableFuture h1 = m.runAfterEither(g, f, rs[1]); -// assertTrue(g.cancel(mayInterruptIfRunning)); -// checkCompletedNormally(h0, null); -// checkCompletedNormally(h1, null); -// for (Noop r : rs) r.assertInvoked(); -// }} + //--- tests of implementation details; not part of official tck --- + + Object resultOf(CompletableFuture f) { + try { + java.lang.reflect.Field resultField + = CompletableFuture.class.getDeclaredField("result"); + resultField.setAccessible(true); + return resultField.get(f); + } catch (Throwable t) { throw new AssertionError(t); } + } + + public void testExceptionPropagationReusesResultObject() { + if (!testImplementationDetails) return; + for (ExecutionMode m : ExecutionMode.values()) + { + final CFException ex = new CFException(); + final CompletableFuture v42 = CompletableFuture.completedFuture(42); + final CompletableFuture incomplete = new CompletableFuture<>(); + + List, CompletableFuture>> dependentFactories + = new ArrayList<>(); + + dependentFactories.add((y) -> m.thenRun(y, new Noop(m))); + dependentFactories.add((y) -> m.thenAccept(y, new NoopConsumer(m))); + dependentFactories.add((y) -> m.thenApply(y, new IncFunction(m))); + + dependentFactories.add((y) -> m.runAfterEither(y, incomplete, new Noop(m))); + dependentFactories.add((y) -> m.acceptEither(y, incomplete, new NoopConsumer(m))); + dependentFactories.add((y) -> m.applyToEither(y, incomplete, new IncFunction(m))); + + dependentFactories.add((y) -> m.runAfterBoth(y, v42, new Noop(m))); + dependentFactories.add((y) -> m.thenAcceptBoth(y, v42, new SubtractAction(m))); + dependentFactories.add((y) -> m.thenCombine(y, v42, new SubtractFunction(m))); + + dependentFactories.add((y) -> m.whenComplete(y, (Integer x, Throwable t) -> {})); + + dependentFactories.add((y) -> m.thenCompose(y, new CompletableFutureInc(m))); + + for (Function, CompletableFuture> + dependentFactory : dependentFactories) { + CompletableFuture f = new CompletableFuture<>(); + f.completeExceptionally(ex); + CompletableFuture src = m.thenApply(f, new IncFunction(m)); + checkCompletedWithWrappedException(src, ex); + CompletableFuture dep = dependentFactory.apply(src); + checkCompletedWithWrappedException(dep, ex); + assertSame(resultOf(src), resultOf(dep)); + } + + for (Function, CompletableFuture> + dependentFactory : dependentFactories) { + CompletableFuture f = new CompletableFuture<>(); + CompletableFuture src = m.thenApply(f, new IncFunction(m)); + CompletableFuture dep = dependentFactory.apply(src); + f.completeExceptionally(ex); + checkCompletedWithWrappedException(src, ex); + checkCompletedWithWrappedException(dep, ex); + assertSame(resultOf(src), resultOf(dep)); + } + + for (boolean mayInterruptIfRunning : new boolean[] { true, false }) + for (Function, CompletableFuture> + dependentFactory : dependentFactories) { + CompletableFuture f = new CompletableFuture<>(); + f.cancel(mayInterruptIfRunning); + checkCancelled(f); + CompletableFuture src = m.thenApply(f, new IncFunction(m)); + checkCompletedWithWrappedCancellationException(src); + CompletableFuture dep = dependentFactory.apply(src); + checkCompletedWithWrappedCancellationException(dep); + assertSame(resultOf(src), resultOf(dep)); + } + + for (boolean mayInterruptIfRunning : new boolean[] { true, false }) + for (Function, CompletableFuture> + dependentFactory : dependentFactories) { + CompletableFuture f = new CompletableFuture<>(); + CompletableFuture src = m.thenApply(f, new IncFunction(m)); + CompletableFuture dep = dependentFactory.apply(src); + f.cancel(mayInterruptIfRunning); + checkCancelled(f); + checkCompletedWithWrappedCancellationException(src); + checkCompletedWithWrappedCancellationException(dep); + assertSame(resultOf(src), resultOf(dep)); + } + }} }