--- jsr166/src/test/tck/CompletableFutureTest.java 2015/11/15 01:33:02 1.129 +++ jsr166/src/test/tck/CompletableFutureTest.java 2015/11/15 19:39:25 1.133 @@ -982,7 +982,7 @@ public class CompletableFutureTest exten * If a whenComplete action throws an exception when triggered by * a normal completion, it completes exceptionally */ - public void testWhenComplete_actionFailed() { + public void testWhenComplete_sourceCompletedNormallyActionFailed() { for (boolean createIncomplete : new boolean[] { true, false }) for (ExecutionMode m : ExecutionMode.values()) for (Integer v1 : new Integer[] { 1, null }) @@ -1152,6 +1152,10 @@ public class CompletableFutureTest exten assertEquals(1, a.get()); }} + /** + * If a "handle action" throws an exception when triggered by + * a normal completion, it completes exceptionally + */ public void testHandle_sourceCompletedNormallyActionFailed() { for (ExecutionMode m : ExecutionMode.values()) for (boolean createIncomplete : new boolean[] { true, false }) @@ -3764,8 +3768,8 @@ public class CompletableFutureTest exten } static class Monad { - static class MonadError extends Error { - public MonadError() { super("monadic zero"); } + static class ZeroException extends RuntimeException { + public ZeroException() { super("monadic zero"); } } // "return", "unit" static CompletableFuture unit(T value) { @@ -3773,7 +3777,7 @@ public class CompletableFutureTest exten } // monadic zero ? static CompletableFuture zero() { - return failedFuture(new MonadError()); + return failedFuture(new ZeroException()); } // >=> static Function> compose @@ -3787,7 +3791,7 @@ public class CompletableFutureTest exten f.getNow(null); throw new AssertionFailedError("should throw"); } catch (CompletionException success) { - assertTrue(success.getCause() instanceof MonadError); + assertTrue(success.getCause() instanceof ZeroException); } } @@ -3819,7 +3823,7 @@ public class CompletableFutureTest exten CompletableFuture g) { PlusFuture plus = new PlusFuture(); BiConsumer action = (T result, Throwable ex) -> { - if (result != null) { + if (ex == null) { if (plus.complete(result)) if (plus.firstFailure.get() != null) plus.firstFailure.set(null); @@ -3827,9 +3831,16 @@ public class CompletableFutureTest exten else if (plus.firstFailure.compareAndSet(null, ex)) { if (plus.isDone()) plus.firstFailure.set(null); - } else { - if (plus.completeExceptionally(ex)) - plus.firstFailure.set(null); + } + else { + // first failure has precedence + Throwable first = plus.firstFailure.getAndSet(null); + + // may fail with "Self-suppression not permitted" + try { first.addSuppressed(ex); } + catch (Exception ignored) {} + + plus.completeExceptionally(first); } }; f.whenComplete(action);