--- jsr166/src/test/tck/CompletableFutureTest.java 2013/07/15 03:50:08 1.29 +++ jsr166/src/test/tck/CompletableFutureTest.java 2014/06/01 23:12:45 1.36 @@ -16,6 +16,7 @@ import java.util.concurrent.ExecutionExc import java.util.concurrent.Future; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; +import java.util.concurrent.CompletionStage; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; import static java.util.concurrent.TimeUnit.MILLISECONDS; @@ -102,6 +103,37 @@ public class CompletableFutureTest exten assertTrue(f.toString().contains("[Completed exceptionally]")); } + void checkCompletedWithWrappedCFException(CompletableFuture f, + CFException ex) { + try { + f.get(LONG_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (ExecutionException success) { + assertSame(ex, success.getCause()); + } catch (Throwable fail) { threadUnexpectedException(fail); } + try { + f.join(); + shouldThrow(); + } catch (CompletionException success) { + assertSame(ex, success.getCause()); + } + try { + f.getNow(null); + shouldThrow(); + } catch (CompletionException success) { + assertSame(ex, success.getCause()); + } + try { + f.get(); + shouldThrow(); + } catch (ExecutionException success) { + assertSame(ex, success.getCause()); + } catch (Throwable fail) { threadUnexpectedException(fail); } + assertTrue(f.isDone()); + assertFalse(f.isCancelled()); + assertTrue(f.toString().contains("[Completed exceptionally]")); + } + void checkCancelled(CompletableFuture f) { try { f.get(LONG_DELAY_MS, MILLISECONDS); @@ -286,20 +318,40 @@ public class CompletableFutureTest exten // Choose non-commutative actions for better coverage + // A non-commutative function that handles null values as well + public static int subtract(Integer x, Integer y) { + return ((x == null) ? 42 : x.intValue()) + - ((y == null) ? 99 : y.intValue()); + } + static final Supplier supplyOne = () -> Integer.valueOf(1); static final Function inc = (Integer x) -> Integer.valueOf(x.intValue() + 1); static final BiFunction subtract = - (Integer x, Integer y) -> Integer.valueOf(x.intValue() - y.intValue()); + (Integer x, Integer y) -> subtract(x, y); static final class IncAction implements Consumer { int value; public void accept(Integer x) { value = x.intValue() + 1; } } static final class SubtractAction implements BiConsumer { + volatile int invocationCount = 0; int value; + // Check this action was invoked exactly once when result is computed. + public boolean ran() { return invocationCount == 1; } public void accept(Integer x, Integer y) { - value = x.intValue() - y.intValue(); + invocationCount++; + value = subtract(x, y); + } + } + static final class SubtractFunction implements BiFunction { + volatile int invocationCount = 0; + int value; + // Check this action was invoked exactly once when result is computed. + public boolean ran() { return invocationCount == 1; } + public Integer apply(Integer x, Integer y) { + invocationCount++; + return subtract(x, y); } } static final class Noop implements Runnable { @@ -374,8 +426,109 @@ public class CompletableFutureTest exten } /** + * Permits the testing of parallel code for the 3 different + * execution modes without repeating all the testing code. + */ + enum ExecutionMode { + DEFAULT { + public CompletableFuture runAfterBoth + (CompletableFuture f, CompletableFuture g, Runnable a) { + return f.runAfterBoth(g, a); + } + public CompletableFuture thenAcceptBoth + (CompletableFuture f, + CompletionStage g, + BiConsumer a) { + return f.thenAcceptBoth(g, a); + } + public CompletableFuture thenCombine + (CompletableFuture f, + CompletionStage g, + BiFunction a) { + return f.thenCombine(g, a); + } + }, + +// /** Experimental way to do more testing */ +// REVERSE_DEFAULT { +// public CompletableFuture runAfterBoth +// (CompletableFuture f, CompletableFuture g, Runnable a) { +// return g.runAfterBoth(f, a); +// } +// public CompletableFuture thenAcceptBoth +// (CompletableFuture f, +// CompletionStage g, +// BiConsumer a) { +// return DEFAULT.thenAcceptBoth(f, g, a); +// } +// }, + + DEFAULT_ASYNC { + public CompletableFuture runAfterBoth + (CompletableFuture f, CompletableFuture g, Runnable a) { + return f.runAfterBothAsync(g, a); + } + public CompletableFuture thenAcceptBoth + (CompletableFuture f, + CompletionStage g, + BiConsumer a) { + return f.thenAcceptBothAsync(g, a); + } + public CompletableFuture thenCombine + (CompletableFuture f, + CompletionStage g, + BiFunction a) { + return f.thenCombineAsync(g, a); + } + }, + +// REVERSE_DEFAULT_ASYNC { +// public CompletableFuture runAfterBoth +// (CompletableFuture f, CompletableFuture g, Runnable a) { +// return f.runAfterBothAsync(g, a); +// } +// public CompletableFuture thenAcceptBoth +// (CompletableFuture f, +// CompletionStage g, +// BiConsumer a) { +// return DEFAULT_ASYNC.thenAcceptBoth(f, g, a); +// } +// }, + + EXECUTOR { + public CompletableFuture runAfterBoth + (CompletableFuture f, CompletableFuture g, Runnable a) { + return f.runAfterBothAsync(g, a, new ThreadExecutor()); + } + public CompletableFuture thenAcceptBoth + (CompletableFuture f, + CompletionStage g, + BiConsumer a) { + return f.thenAcceptBothAsync(g, a, new ThreadExecutor()); + } + public CompletableFuture thenCombine + (CompletableFuture f, + CompletionStage g, + BiFunction a) { + return f.thenCombineAsync(g, a, new ThreadExecutor()); + } + }; + + public abstract CompletableFuture runAfterBoth + (CompletableFuture f, CompletableFuture g, Runnable a); + public abstract CompletableFuture thenAcceptBoth + (CompletableFuture f, + CompletionStage g, + BiConsumer a); + public abstract CompletableFuture thenCombine + (CompletableFuture f, + CompletionStage g, + BiFunction a); + } + + /** * exceptionally action completes with function value on source - * exception; otherwise with source value + * exception; otherwise with source value */ public void testExceptionally() { CompletableFuture f = new CompletableFuture<>(); @@ -665,368 +818,902 @@ public class CompletableFutureTest exten * thenCombine result completes normally after normal completion * of sources */ - public void testThenCombine() { - CompletableFuture f, g, h; + public void testThenCombine_normalCompletion1() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) + for (Integer v2 : new Integer[] { 2, null }) { + + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final SubtractFunction r = new SubtractFunction(); + final CompletableFuture h = m.thenCombine(f, g, r); + + f.complete(v1); + checkIncomplete(h); + assertFalse(r.ran()); + g.complete(v2); + + checkCompletedNormally(h, subtract(v1, v2)); + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + } + } - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenCombine(g, subtract); - f.complete(3); - checkIncomplete(h); - g.complete(1); - checkCompletedNormally(h, 2); + public void testThenCombine_normalCompletion2() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) + for (Integer v2 : new Integer[] { 2, null }) { + + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final SubtractFunction r = new SubtractFunction(); + final CompletableFuture h = m.thenCombine(f, g, r); + + g.complete(v2); + checkIncomplete(h); + assertFalse(r.ran()); + f.complete(v1); + + checkCompletedNormally(h, subtract(v1, v2)); + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + } + } - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenCombine(g, subtract); - g.complete(1); - checkIncomplete(h); - f.complete(3); - checkCompletedNormally(h, 2); + public void testThenCombine_normalCompletion3() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) + for (Integer v2 : new Integer[] { 2, null }) { + + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final SubtractFunction r = new SubtractFunction(); + + g.complete(v2); + f.complete(v1); + final CompletableFuture h = m.thenCombine(f, g, r); + + checkCompletedNormally(h, subtract(v1, v2)); + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + } + } - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - g.complete(1); - f.complete(3); - h = f.thenCombine(g, subtract); - checkCompletedNormally(h, 2); + public void testThenCombine_normalCompletion4() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) + for (Integer v2 : new Integer[] { 2, null }) { + + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final SubtractFunction r = new SubtractFunction(); + + f.complete(v1); + g.complete(v2); + final CompletableFuture h = m.thenCombine(f, g, r); + + checkCompletedNormally(h, subtract(v1, v2)); + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + } } /** * thenCombine result completes exceptionally after exceptional * completion of either source */ - public void testThenCombine2() { - CompletableFuture f, g, h; - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenCombine(g, subtract); - f.completeExceptionally(new CFException()); - checkIncomplete(h); - g.complete(1); - checkCompletedWithWrappedCFException(h); + public void testThenCombine_exceptionalCompletion1() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) { + + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final SubtractFunction r = new SubtractFunction(); + final CompletableFuture h = m.thenCombine(f, g, r); + final CFException ex = new CFException(); + + f.completeExceptionally(ex); + checkIncomplete(h); + g.complete(v1); + + checkCompletedWithWrappedCFException(h, ex); + checkCompletedWithWrappedCFException(f, ex); + assertFalse(r.ran()); + checkCompletedNormally(g, v1); + } + } - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenCombine(g, subtract); - g.completeExceptionally(new CFException()); - checkIncomplete(h); - f.complete(3); - checkCompletedWithWrappedCFException(h); + public void testThenCombine_exceptionalCompletion2() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) { + + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final SubtractFunction r = new SubtractFunction(); + final CompletableFuture h = m.thenCombine(f, g, subtract); + final CFException ex = new CFException(); + + g.completeExceptionally(ex); + checkIncomplete(h); + f.complete(v1); + + checkCompletedWithWrappedCFException(h, ex); + checkCompletedWithWrappedCFException(g, ex); + assertFalse(r.ran()); + checkCompletedNormally(f, v1); + } + } - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - f.complete(3); - g.completeExceptionally(new CFException()); - h = f.thenCombine(g, subtract); - checkCompletedWithWrappedCFException(h); + public void testThenCombine_exceptionalCompletion3() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) { + + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final SubtractFunction r = new SubtractFunction(); + final CFException ex = new CFException(); + + g.completeExceptionally(ex); + f.complete(v1); + final CompletableFuture h = m.thenCombine(f, g, r); + + checkCompletedWithWrappedCFException(h, ex); + checkCompletedWithWrappedCFException(g, ex); + assertFalse(r.ran()); + checkCompletedNormally(f, v1); + } + } - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - f.completeExceptionally(new CFException()); - g.complete(3); - h = f.thenCombine(g, subtract); - checkCompletedWithWrappedCFException(h); + public void testThenCombine_exceptionalCompletion4() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) { + + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final SubtractFunction r = new SubtractFunction(); + final CFException ex = new CFException(); + + f.completeExceptionally(ex); + g.complete(v1); + final CompletableFuture h = m.thenCombine(f, g, subtract); + + checkCompletedWithWrappedCFException(h, ex); + checkCompletedWithWrappedCFException(f, ex); + assertFalse(r.ran()); + checkCompletedNormally(g, v1); + } } /** * thenCombine result completes exceptionally if action does */ - public void testThenCombine3() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - FailingBiFunction r = new FailingBiFunction(); - CompletableFuture g = f.thenCombine(f2, r); - f.complete(one); - checkIncomplete(g); - assertFalse(r.ran); - f2.complete(two); - checkCompletedWithWrappedCFException(g); - assertTrue(r.ran); + public void testThenCombine_actionFailed1() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) + for (Integer v2 : new Integer[] { 2, null }) { + + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final FailingBiFunction r = new FailingBiFunction(); + final CompletableFuture h = m.thenCombine(f, g, r); + + f.complete(v1); + checkIncomplete(h); + g.complete(v2); + + checkCompletedWithWrappedCFException(h); + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + } + } + + public void testThenCombine_actionFailed2() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) + for (Integer v2 : new Integer[] { 2, null }) { + + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final FailingBiFunction r = new FailingBiFunction(); + final CompletableFuture h = m.thenCombine(f, g, r); + + g.complete(v2); + checkIncomplete(h); + f.complete(v1); + + checkCompletedWithWrappedCFException(h); + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + } } /** * thenCombine result completes exceptionally if either source cancelled */ - public void testThenCombine4() { - CompletableFuture f, g, h; + public void testThenCombine_sourceCancelled1() { + 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 SubtractFunction r = new SubtractFunction(); + final CompletableFuture h = m.thenCombine(f, g, r); - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenCombine(g, subtract); - assertTrue(f.cancel(true)); + assertTrue(f.cancel(mayInterruptIfRunning)); checkIncomplete(h); - g.complete(1); + g.complete(v1); + checkCompletedWithWrappedCancellationException(h); + checkCancelled(f); + assertFalse(r.ran()); + checkCompletedNormally(g, v1); + } + } - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenCombine(g, subtract); - assertTrue(g.cancel(true)); + public void testThenCombine_sourceCancelled2() { + 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 SubtractFunction r = new SubtractFunction(); + final CompletableFuture h = m.thenCombine(f, g, r); + + assertTrue(g.cancel(mayInterruptIfRunning)); checkIncomplete(h); - f.complete(3); + f.complete(v1); + checkCompletedWithWrappedCancellationException(h); + checkCancelled(g); + assertFalse(r.ran()); + checkCompletedNormally(f, v1); + } + } + + public void testThenCombine_sourceCancelled3() { + 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 SubtractFunction r = new SubtractFunction(); + + assertTrue(g.cancel(mayInterruptIfRunning)); + f.complete(v1); + final CompletableFuture h = m.thenCombine(f, g, r); + + checkCompletedWithWrappedCancellationException(h); + checkCancelled(g); + assertFalse(r.ran()); + checkCompletedNormally(f, v1); + } + } + + public void testThenCombine_sourceCancelled4() { + 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 SubtractFunction r = new SubtractFunction(); + + assertTrue(f.cancel(mayInterruptIfRunning)); + g.complete(v1); + final CompletableFuture h = m.thenCombine(f, g, r); - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - assertTrue(f.cancel(true)); - assertTrue(g.cancel(true)); - h = f.thenCombine(g, subtract); checkCompletedWithWrappedCancellationException(h); + checkCancelled(f); + assertFalse(r.ran()); + checkCompletedNormally(g, v1); + } } /** * thenAcceptBoth result completes normally after normal * completion of sources */ - public void testThenAcceptBoth() { - CompletableFuture f, g; - CompletableFuture h; - SubtractAction r; + public void testThenAcceptBoth_normalCompletion1() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) + for (Integer v2 : new Integer[] { 2, null }) { + + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final SubtractAction r = new SubtractAction(); + final CompletableFuture h = m.thenAcceptBoth(f, g, r); - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenAcceptBoth(g, r = new SubtractAction()); - f.complete(3); + f.complete(v1); checkIncomplete(h); - g.complete(1); + assertEquals(r.value, 0); + g.complete(v2); + checkCompletedNormally(h, null); - assertEquals(r.value, 2); + assertEquals(r.value, subtract(v1, v2)); + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + } + } - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenAcceptBoth(g, r = new SubtractAction()); - g.complete(1); + public void testThenAcceptBoth_normalCompletion2() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) + for (Integer v2 : new Integer[] { 2, null }) { + + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final SubtractAction r = new SubtractAction(); + final CompletableFuture h = m.thenAcceptBoth(f, g, r); + + g.complete(v2); checkIncomplete(h); - f.complete(3); + assertEquals(r.value, 0); + f.complete(v1); + checkCompletedNormally(h, null); - assertEquals(r.value, 2); + assertEquals(r.value, subtract(v1, v2)); + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + } + } + + public void testThenAcceptBoth_normalCompletion3() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) + for (Integer v2 : new Integer[] { 2, null }) { + + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final SubtractAction r = new SubtractAction(); + + g.complete(v2); + f.complete(v1); + final CompletableFuture h = m.thenAcceptBoth(f, g, r); - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - g.complete(1); - f.complete(3); - h = f.thenAcceptBoth(g, r = new SubtractAction()); checkCompletedNormally(h, null); - assertEquals(r.value, 2); + assertEquals(r.value, subtract(v1, v2)); + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + } + } + + public void testThenAcceptBoth_normalCompletion4() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) + for (Integer v2 : new Integer[] { 2, null }) { + + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final SubtractAction r = new SubtractAction(); + + f.complete(v1); + g.complete(v2); + final CompletableFuture h = m.thenAcceptBoth(f, g, r); + + checkCompletedNormally(h, null); + assertEquals(r.value, subtract(v1, v2)); + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + } } /** * thenAcceptBoth result completes exceptionally after exceptional * completion of either source */ - public void testThenAcceptBoth2() { - CompletableFuture f, g; - CompletableFuture h; - SubtractAction r; - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenAcceptBoth(g, r = new SubtractAction()); - f.completeExceptionally(new CFException()); - checkIncomplete(h); - g.complete(1); - checkCompletedWithWrappedCFException(h); + public void testThenAcceptBoth_exceptionalCompletion1() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) { + + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final SubtractAction r = new SubtractAction(); + final CompletableFuture h = m.thenAcceptBoth(f, g, r); + final CFException ex = new CFException(); + + f.completeExceptionally(ex); + checkIncomplete(h); + g.complete(v1); + + checkCompletedWithWrappedCFException(h, ex); + checkCompletedWithWrappedCFException(f, ex); + assertFalse(r.ran()); + checkCompletedNormally(g, v1); + } + } - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenAcceptBoth(g, r = new SubtractAction()); - g.completeExceptionally(new CFException()); - checkIncomplete(h); - f.complete(3); - checkCompletedWithWrappedCFException(h); + public void testThenAcceptBoth_exceptionalCompletion2() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) { + + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final SubtractAction r = new SubtractAction(); + final CompletableFuture h = m.thenAcceptBoth(f, g, r); + final CFException ex = new CFException(); + + g.completeExceptionally(ex); + checkIncomplete(h); + f.complete(v1); + + checkCompletedWithWrappedCFException(h, ex); + checkCompletedWithWrappedCFException(g, ex); + assertFalse(r.ran()); + checkCompletedNormally(f, v1); + } + } - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - f.complete(3); - g.completeExceptionally(new CFException()); - h = f.thenAcceptBoth(g, r = new SubtractAction()); - checkCompletedWithWrappedCFException(h); + public void testThenAcceptBoth_exceptionalCompletion3() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) { + + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final SubtractAction r = new SubtractAction(); + final CFException ex = new CFException(); + + g.completeExceptionally(ex); + f.complete(v1); + final CompletableFuture h = m.thenAcceptBoth(f, g, r); + + checkCompletedWithWrappedCFException(h, ex); + checkCompletedWithWrappedCFException(g, ex); + assertFalse(r.ran()); + checkCompletedNormally(f, v1); + } + } - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - f.completeExceptionally(new CFException()); - g.complete(3); - h = f.thenAcceptBoth(g, r = new SubtractAction()); - checkCompletedWithWrappedCFException(h); + public void testThenAcceptBoth_exceptionalCompletion4() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) { + + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final SubtractAction r = new SubtractAction(); + final CFException ex = new CFException(); + + f.completeExceptionally(ex); + g.complete(v1); + final CompletableFuture h = m.thenAcceptBoth(f, g, r); + + checkCompletedWithWrappedCFException(h, ex); + checkCompletedWithWrappedCFException(f, ex); + assertFalse(r.ran()); + checkCompletedNormally(g, v1); + } } /** * thenAcceptBoth result completes exceptionally if action does */ - public void testThenAcceptBoth3() { - CompletableFuture f, g; - CompletableFuture h; - FailingBiConsumer r; + public void testThenAcceptBoth_actionFailed1() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) + for (Integer v2 : new Integer[] { 2, null }) { - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenAcceptBoth(g, r = new FailingBiConsumer()); - f.complete(3); + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final FailingBiConsumer r = new FailingBiConsumer(); + final CompletableFuture h = m.thenAcceptBoth(f, g, r); + + f.complete(v1); checkIncomplete(h); - g.complete(1); + g.complete(v2); + checkCompletedWithWrappedCFException(h); + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + } + } + + public void testThenAcceptBoth_actionFailed2() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) + for (Integer v2 : new Integer[] { 2, null }) { + + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final FailingBiConsumer r = new FailingBiConsumer(); + final CompletableFuture h = m.thenAcceptBoth(f, g, r); + + g.complete(v2); + checkIncomplete(h); + f.complete(v1); - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - f.complete(3); - g.complete(1); - h = f.thenAcceptBoth(g, r = new FailingBiConsumer()); checkCompletedWithWrappedCFException(h); + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + } } /** * thenAcceptBoth result completes exceptionally if either source cancelled */ - public void testThenAcceptBoth4() { - CompletableFuture f, g; - CompletableFuture h; - SubtractAction r; + public void testThenAcceptBoth_sourceCancelled1() { + 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 SubtractAction r = new SubtractAction(); + final CompletableFuture h = m.thenAcceptBoth(f, g, r); - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenAcceptBoth(g, r = new SubtractAction()); - assertTrue(f.cancel(true)); + assertTrue(f.cancel(mayInterruptIfRunning)); checkIncomplete(h); - g.complete(1); + g.complete(v1); + checkCompletedWithWrappedCancellationException(h); + checkCancelled(f); + assertFalse(r.ran()); + checkCompletedNormally(g, v1); + } + } - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenAcceptBoth(g, r = new SubtractAction()); - assertTrue(g.cancel(true)); + public void testThenAcceptBoth_sourceCancelled2() { + 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 SubtractAction r = new SubtractAction(); + final CompletableFuture h = m.thenAcceptBoth(f, g, r); + + assertTrue(g.cancel(mayInterruptIfRunning)); checkIncomplete(h); - f.complete(3); - checkCompletedWithWrappedCancellationException(h); + f.complete(v1); - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - f.complete(3); - assertTrue(g.cancel(true)); - h = f.thenAcceptBoth(g, r = new SubtractAction()); checkCompletedWithWrappedCancellationException(h); + checkCancelled(g); + assertFalse(r.ran()); + checkCompletedNormally(f, v1); + } + } + + public void testThenAcceptBoth_sourceCancelled3() { + 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 SubtractAction r = new SubtractAction(); + + assertTrue(g.cancel(mayInterruptIfRunning)); + f.complete(v1); + final CompletableFuture h = m.thenAcceptBoth(f, g, r); + + checkCompletedWithWrappedCancellationException(h); + checkCancelled(g); + assertFalse(r.ran()); + checkCompletedNormally(f, v1); + } + } + + public void testThenAcceptBoth_sourceCancelled4() { + 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 SubtractAction r = new SubtractAction(); + + assertTrue(f.cancel(mayInterruptIfRunning)); + g.complete(v1); + final CompletableFuture h = m.thenAcceptBoth(f, g, r); - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - assertTrue(f.cancel(true)); - g.complete(3); - h = f.thenAcceptBoth(g, r = new SubtractAction()); checkCompletedWithWrappedCancellationException(h); + checkCancelled(f); + assertFalse(r.ran()); + checkCompletedNormally(g, v1); + } } /** * runAfterBoth result completes normally after normal * completion of sources */ - public void testRunAfterBoth() { - CompletableFuture f, g; - CompletableFuture h; - Noop r; + public void testRunAfterBoth_normalCompletion1() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) + for (Integer v2 : new Integer[] { 2, null }) { + + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final Noop r = new Noop(); + final CompletableFuture h = m.runAfterBoth(f, g, r); - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.runAfterBoth(g, r = new Noop()); - f.complete(3); + f.complete(v1); checkIncomplete(h); - g.complete(1); + assertFalse(r.ran); + g.complete(v2); + checkCompletedNormally(h, null); assertTrue(r.ran); + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + } + } - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.runAfterBoth(g, r = new Noop()); - g.complete(1); + public void testRunAfterBoth_normalCompletion2() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) + for (Integer v2 : new Integer[] { 2, null }) { + + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final Noop r = new Noop(); + final CompletableFuture h = m.runAfterBoth(f, g, r); + + g.complete(v2); checkIncomplete(h); - f.complete(3); + assertFalse(r.ran); + f.complete(v1); + + checkCompletedNormally(h, null); + assertTrue(r.ran); + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + } + } + + public void testRunAfterBoth_normalCompletion3() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) + for (Integer v2 : new Integer[] { 2, null }) { + + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final Noop r = new Noop(); + + g.complete(v2); + f.complete(v1); + final CompletableFuture h = m.runAfterBoth(f, g, r); + checkCompletedNormally(h, null); assertTrue(r.ran); + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + } + } + + public void testRunAfterBoth_normalCompletion4() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) + for (Integer v2 : new Integer[] { 2, null }) { + + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final Noop r = new Noop(); + + f.complete(v1); + g.complete(v2); + final CompletableFuture h = m.runAfterBoth(f, g, r); - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - g.complete(1); - f.complete(3); - h = f.runAfterBoth(g, r = new Noop()); checkCompletedNormally(h, null); assertTrue(r.ran); + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + } } /** * runAfterBoth result completes exceptionally after exceptional * completion of either source */ - public void testRunAfterBoth2() { - CompletableFuture f, g; - CompletableFuture h; - Noop r; + public void testRunAfterBoth_exceptionalCompletion1() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) { + + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final Noop r = new Noop(); + final CompletableFuture h = m.runAfterBoth(f, g, r); + final CFException ex = new CFException(); - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.runAfterBoth(g, r = new Noop()); - f.completeExceptionally(new CFException()); + f.completeExceptionally(ex); checkIncomplete(h); - g.complete(1); - checkCompletedWithWrappedCFException(h); + g.complete(v1); + + checkCompletedWithWrappedCFException(h, ex); + checkCompletedWithWrappedCFException(f, ex); assertFalse(r.ran); + checkCompletedNormally(g, v1); + } + } - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.runAfterBoth(g, r = new Noop()); - g.completeExceptionally(new CFException()); + public void testRunAfterBoth_exceptionalCompletion2() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) { + + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final Noop r = new Noop(); + final CompletableFuture h = m.runAfterBoth(f, g, r); + final CFException ex = new CFException(); + + g.completeExceptionally(ex); checkIncomplete(h); - f.complete(3); - checkCompletedWithWrappedCFException(h); + f.complete(v1); + + checkCompletedWithWrappedCFException(h, ex); + checkCompletedWithWrappedCFException(g, ex); assertFalse(r.ran); + checkCompletedNormally(f, v1); + } + } - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - g.completeExceptionally(new CFException()); - f.complete(3); - h = f.runAfterBoth(g, r = new Noop()); - checkCompletedWithWrappedCFException(h); + public void testRunAfterBoth_exceptionalCompletion3() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) { + + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final Noop r = new Noop(); + final CFException ex = new CFException(); + + g.completeExceptionally(ex); + f.complete(v1); + final CompletableFuture h = m.runAfterBoth(f, g, r); + + checkCompletedWithWrappedCFException(h, ex); + checkCompletedWithWrappedCFException(g, ex); assertFalse(r.ran); + checkCompletedNormally(f, v1); + } + } - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - f.completeExceptionally(new CFException()); - g.complete(1); - h = f.runAfterBoth(g, r = new Noop()); - checkCompletedWithWrappedCFException(h); + public void testRunAfterBoth_exceptionalCompletion4() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) { + + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final Noop r = new Noop(); + final CFException ex = new CFException(); + + f.completeExceptionally(ex); + g.complete(v1); + final CompletableFuture h = m.runAfterBoth(f, g, r); + + checkCompletedWithWrappedCFException(h, ex); + checkCompletedWithWrappedCFException(f, ex); assertFalse(r.ran); + checkCompletedNormally(g, v1); + } } /** * runAfterBoth result completes exceptionally if action does */ - public void testRunAfterBoth3() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - FailingNoop r = new FailingNoop(); - CompletableFuture g = f.runAfterBoth(f2, r); - f.complete(one); - checkIncomplete(g); - f2.complete(two); - checkCompletedWithWrappedCFException(g); + public void testRunAfterBoth_actionFailed1() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) + for (Integer v2 : new Integer[] { 2, null }) { + + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final FailingNoop r = new FailingNoop(); + final CompletableFuture h = m.runAfterBoth(f, g, r); + + f.complete(v1); + checkIncomplete(h); + g.complete(v2); + + checkCompletedWithWrappedCFException(h); + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + } + } + + public void testRunAfterBoth_actionFailed2() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) + for (Integer v2 : new Integer[] { 2, null }) { + + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final FailingNoop r = new FailingNoop(); + final CompletableFuture h = m.runAfterBoth(f, g, r); + + g.complete(v2); + checkIncomplete(h); + f.complete(v1); + + checkCompletedWithWrappedCFException(h); + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + } } /** * runAfterBoth result completes exceptionally if either source cancelled */ - public void testRunAfterBoth4() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - Noop r = new Noop(); - CompletableFuture g = f.runAfterBoth(f2, r); - assertTrue(f.cancel(true)); - f2.complete(two); - checkCompletedWithWrappedCancellationException(g); - f = new CompletableFuture<>(); - f2 = new CompletableFuture<>(); - r = new Noop(); - g = f.runAfterBoth(f2, r); - f.complete(one); - assertTrue(f2.cancel(true)); - checkCompletedWithWrappedCancellationException(g); + public void testRunAfterBoth_sourceCancelled1() { + 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 r = new Noop(); + final CompletableFuture h = m.runAfterBoth(f, g, r); + + assertTrue(f.cancel(mayInterruptIfRunning)); + checkIncomplete(h); + g.complete(v1); + + checkCompletedWithWrappedCancellationException(h); + checkCancelled(f); + assertFalse(r.ran); + checkCompletedNormally(g, v1); + } + } + + public void testRunAfterBoth_sourceCancelled2() { + 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 r = new Noop(); + final CompletableFuture h = m.runAfterBoth(f, g, r); + + assertTrue(g.cancel(mayInterruptIfRunning)); + checkIncomplete(h); + f.complete(v1); + + checkCompletedWithWrappedCancellationException(h); + checkCancelled(g); + assertFalse(r.ran); + checkCompletedNormally(f, v1); + } + } + + public void testRunAfterBoth_sourceCancelled3() { + 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 r = new Noop(); + + assertTrue(g.cancel(mayInterruptIfRunning)); + f.complete(v1); + final CompletableFuture h = m.runAfterBoth(f, g, r); + + checkCompletedWithWrappedCancellationException(h); + checkCancelled(g); + assertFalse(r.ran); + checkCompletedNormally(f, v1); + } + } + + public void testRunAfterBoth_sourceCancelled4() { + 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 r = new Noop(); + + assertTrue(f.cancel(mayInterruptIfRunning)); + g.complete(v1); + final CompletableFuture h = m.runAfterBoth(f, g, r); + + checkCompletedWithWrappedCancellationException(h); + checkCancelled(f); + assertFalse(r.ran); + checkCompletedNormally(g, v1); + } } /** @@ -1464,333 +2151,6 @@ public class CompletableFutureTest exten } /** - * thenCombineAsync result completes normally after normal - * completion of sources - */ - public void testThenCombineAsync() { - CompletableFuture f, g, h; - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenCombineAsync(g, subtract); - f.complete(3); - checkIncomplete(h); - g.complete(1); - checkCompletedNormally(h, 2); - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenCombineAsync(g, subtract); - g.complete(1); - checkIncomplete(h); - f.complete(3); - checkCompletedNormally(h, 2); - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - g.complete(1); - f.complete(3); - h = f.thenCombineAsync(g, subtract); - checkCompletedNormally(h, 2); - } - - /** - * thenCombineAsync result completes exceptionally after exceptional - * completion of either source - */ - public void testThenCombineAsync2() { - CompletableFuture f, g, h; - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenCombineAsync(g, subtract); - f.completeExceptionally(new CFException()); - checkIncomplete(h); - g.complete(1); - checkCompletedWithWrappedCFException(h); - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenCombineAsync(g, subtract); - g.completeExceptionally(new CFException()); - checkIncomplete(h); - f.complete(3); - checkCompletedWithWrappedCFException(h); - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - g.completeExceptionally(new CFException()); - f.complete(3); - h = f.thenCombineAsync(g, subtract); - checkCompletedWithWrappedCFException(h); - } - - /** - * thenCombineAsync result completes exceptionally if action does - */ - public void testThenCombineAsync3() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - FailingBiFunction r = new FailingBiFunction(); - CompletableFuture g = f.thenCombineAsync(f2, r); - f.complete(one); - checkIncomplete(g); - assertFalse(r.ran); - f2.complete(two); - checkCompletedWithWrappedCFException(g); - assertTrue(r.ran); - } - - /** - * thenCombineAsync result completes exceptionally if either source cancelled - */ - public void testThenCombineAsync4() { - CompletableFuture f, g, h; - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenCombineAsync(g, subtract); - assertTrue(f.cancel(true)); - checkIncomplete(h); - g.complete(1); - checkCompletedWithWrappedCancellationException(h); - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenCombineAsync(g, subtract); - assertTrue(g.cancel(true)); - checkIncomplete(h); - f.complete(3); - checkCompletedWithWrappedCancellationException(h); - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - g.complete(3); - assertTrue(f.cancel(true)); - h = f.thenCombineAsync(g, subtract); - checkCompletedWithWrappedCancellationException(h); - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - f.complete(3); - assertTrue(g.cancel(true)); - h = f.thenCombineAsync(g, subtract); - checkCompletedWithWrappedCancellationException(h); - } - - /** - * thenAcceptBothAsync result completes normally after normal - * completion of sources - */ - public void testThenAcceptBothAsync() { - CompletableFuture f, g; - CompletableFuture h; - SubtractAction r; - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenAcceptBothAsync(g, r = new SubtractAction()); - f.complete(3); - checkIncomplete(h); - g.complete(1); - checkCompletedNormally(h, null); - assertEquals(r.value, 2); - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenAcceptBothAsync(g, r = new SubtractAction()); - g.complete(1); - checkIncomplete(h); - f.complete(3); - checkCompletedNormally(h, null); - assertEquals(r.value, 2); - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - g.complete(1); - f.complete(3); - h = f.thenAcceptBothAsync(g, r = new SubtractAction()); - checkCompletedNormally(h, null); - assertEquals(r.value, 2); - } - - /** - * thenAcceptBothAsync result completes exceptionally after exceptional - * completion of source - */ - public void testThenAcceptBothAsync2() { - CompletableFuture f, g; - CompletableFuture h; - SubtractAction r; - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenAcceptBothAsync(g, r = new SubtractAction()); - f.completeExceptionally(new CFException()); - checkIncomplete(h); - g.complete(1); - checkCompletedWithWrappedCFException(h); - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenAcceptBothAsync(g, r = new SubtractAction()); - g.completeExceptionally(new CFException()); - checkIncomplete(h); - f.complete(3); - checkCompletedWithWrappedCFException(h); - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - f.complete(3); - g.completeExceptionally(new CFException()); - h = f.thenAcceptBothAsync(g, r = new SubtractAction()); - checkCompletedWithWrappedCFException(h); - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - f.completeExceptionally(new CFException()); - g.complete(3); - h = f.thenAcceptBothAsync(g, r = new SubtractAction()); - checkCompletedWithWrappedCFException(h); - } - - /** - * thenAcceptBothAsync result completes exceptionally if action does - */ - public void testThenAcceptBothAsync3() { - CompletableFuture f, g; - CompletableFuture h; - FailingBiConsumer r; - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenAcceptBothAsync(g, r = new FailingBiConsumer()); - f.complete(3); - checkIncomplete(h); - g.complete(1); - checkCompletedWithWrappedCFException(h); - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - f.complete(3); - g.complete(1); - h = f.thenAcceptBothAsync(g, r = new FailingBiConsumer()); - checkCompletedWithWrappedCFException(h); - } - - /** - * thenAcceptBothAsync result completes exceptionally if either source cancelled - */ - public void testThenAcceptBothAsync4() { - CompletableFuture f, g; - CompletableFuture h; - SubtractAction r; - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenAcceptBothAsync(g, r = new SubtractAction()); - assertTrue(f.cancel(true)); - checkIncomplete(h); - g.complete(1); - checkCompletedWithWrappedCancellationException(h); - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenAcceptBothAsync(g, r = new SubtractAction()); - assertTrue(g.cancel(true)); - checkIncomplete(h); - f.complete(3); - checkCompletedWithWrappedCancellationException(h); - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - f.complete(3); - assertTrue(g.cancel(true)); - h = f.thenAcceptBothAsync(g, r = new SubtractAction()); - checkCompletedWithWrappedCancellationException(h); - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - assertTrue(f.cancel(true)); - g.complete(3); - h = f.thenAcceptBothAsync(g, r = new SubtractAction()); - checkCompletedWithWrappedCancellationException(h); - } - - /** - * runAfterBothAsync result completes normally after normal - * completion of sources - */ - public void testRunAfterBothAsync() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - Noop r = new Noop(); - CompletableFuture g = f.runAfterBothAsync(f2, r); - f.complete(one); - checkIncomplete(g); - f2.complete(two); - checkCompletedNormally(g, null); - assertTrue(r.ran); - } - - /** - * runAfterBothAsync result completes exceptionally after exceptional - * completion of source - */ - public void testRunAfterBothAsync2() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - Noop r = new Noop(); - CompletableFuture g = f.runAfterBothAsync(f2, r); - f.completeExceptionally(new CFException()); - f2.complete(two); - checkCompletedWithWrappedCFException(g); - - r = new Noop(); - f = new CompletableFuture<>(); - f2 = new CompletableFuture<>(); - g = f.runAfterBothAsync(f2, r); - f.complete(one); - f2.completeExceptionally(new CFException()); - checkCompletedWithWrappedCFException(g); - } - - /** - * runAfterBothAsync result completes exceptionally if action does - */ - public void testRunAfterBothAsync3() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - FailingNoop r = new FailingNoop(); - CompletableFuture g = f.runAfterBothAsync(f2, r); - f.complete(one); - checkIncomplete(g); - f2.complete(two); - checkCompletedWithWrappedCFException(g); - } - - /** - * runAfterBothAsync result completes exceptionally if either source cancelled - */ - public void testRunAfterBothAsync4() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - Noop r = new Noop(); - CompletableFuture g = f.runAfterBothAsync(f2, r); - assertTrue(f.cancel(true)); - f2.complete(two); - checkCompletedWithWrappedCancellationException(g); - - r = new Noop(); - f = new CompletableFuture<>(); - f2 = new CompletableFuture<>(); - g = f.runAfterBothAsync(f2, r); - f.complete(one); - assertTrue(f2.cancel(true)); - checkCompletedWithWrappedCancellationException(g); - } - - /** * applyToEitherAsync result completes normally after normal * completion of sources */ @@ -2230,359 +2590,6 @@ public class CompletableFutureTest exten } /** - * thenCombineAsync result completes normally after normal - * completion of sources - */ - public void testThenCombineAsyncE() { - CompletableFuture f, g, h; - ThreadExecutor e = new ThreadExecutor(); - int count = 0; - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenCombineAsync(g, subtract, e); - f.complete(3); - checkIncomplete(h); - g.complete(1); - checkCompletedNormally(h, 2); - assertEquals(++count, e.count.get()); - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenCombineAsync(g, subtract, e); - g.complete(1); - checkIncomplete(h); - f.complete(3); - checkCompletedNormally(h, 2); - assertEquals(++count, e.count.get()); - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - g.complete(1); - f.complete(3); - h = f.thenCombineAsync(g, subtract, e); - checkCompletedNormally(h, 2); - assertEquals(++count, e.count.get()); - } - - /** - * thenCombineAsync result completes exceptionally after exceptional - * completion of either source - */ - public void testThenCombineAsync2E() { - CompletableFuture f, g, h; - ThreadExecutor e = new ThreadExecutor(); - int count = 0; - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenCombineAsync(g, subtract, e); - f.completeExceptionally(new CFException()); - checkIncomplete(h); - g.complete(1); - checkCompletedWithWrappedCFException(h); - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenCombineAsync(g, subtract, e); - g.completeExceptionally(new CFException()); - checkIncomplete(h); - f.complete(3); - checkCompletedWithWrappedCFException(h); - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - g.completeExceptionally(new CFException()); - h = f.thenCombineAsync(g, subtract, e); - checkIncomplete(h); - f.complete(3); - checkCompletedWithWrappedCFException(h); - - assertEquals(0, e.count.get()); - } - - /** - * thenCombineAsync result completes exceptionally if action does - */ - public void testThenCombineAsync3E() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - FailingBiFunction r = new FailingBiFunction(); - CompletableFuture g = f.thenCombineAsync(f2, r, new ThreadExecutor()); - f.complete(one); - checkIncomplete(g); - assertFalse(r.ran); - f2.complete(two); - checkCompletedWithWrappedCFException(g); - assertTrue(r.ran); - } - - /** - * thenCombineAsync result completes exceptionally if either source cancelled - */ - public void testThenCombineAsync4E() { - CompletableFuture f, g, h; - ThreadExecutor e = new ThreadExecutor(); - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenCombineAsync(g, subtract, e); - assertTrue(f.cancel(true)); - checkIncomplete(h); - g.complete(1); - checkCompletedWithWrappedCancellationException(h); - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenCombineAsync(g, subtract, e); - assertTrue(g.cancel(true)); - checkIncomplete(h); - f.complete(3); - checkCompletedWithWrappedCancellationException(h); - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - assertTrue(g.cancel(true)); - h = f.thenCombineAsync(g, subtract, e); - checkIncomplete(h); - f.complete(3); - checkCompletedWithWrappedCancellationException(h); - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - assertTrue(f.cancel(true)); - assertTrue(g.cancel(true)); - h = f.thenCombineAsync(g, subtract, e); - checkCompletedWithWrappedCancellationException(h); - - assertEquals(0, e.count.get()); - } - - /** - * thenAcceptBothAsync result completes normally after normal - * completion of sources - */ - public void testThenAcceptBothAsyncE() { - CompletableFuture f, g; - CompletableFuture h; - SubtractAction r; - ThreadExecutor e = new ThreadExecutor(); - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenAcceptBothAsync(g, r = new SubtractAction(), e); - f.complete(3); - checkIncomplete(h); - g.complete(1); - checkCompletedNormally(h, null); - assertEquals(r.value, 2); - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenAcceptBothAsync(g, r = new SubtractAction(), e); - g.complete(1); - checkIncomplete(h); - f.complete(3); - checkCompletedNormally(h, null); - assertEquals(r.value, 2); - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - g.complete(1); - f.complete(3); - h = f.thenAcceptBothAsync(g, r = new SubtractAction(), e); - checkCompletedNormally(h, null); - assertEquals(r.value, 2); - - assertEquals(3, e.count.get()); - } - - /** - * thenAcceptBothAsync result completes exceptionally after exceptional - * completion of source - */ - public void testThenAcceptBothAsync2E() { - CompletableFuture f, g; - CompletableFuture h; - SubtractAction r; - ThreadExecutor e = new ThreadExecutor(); - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenAcceptBothAsync(g, r = new SubtractAction(), e); - f.completeExceptionally(new CFException()); - checkIncomplete(h); - g.complete(1); - checkCompletedWithWrappedCFException(h); - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenAcceptBothAsync(g, r = new SubtractAction(), e); - g.completeExceptionally(new CFException()); - checkIncomplete(h); - f.complete(3); - checkCompletedWithWrappedCFException(h); - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - f.complete(3); - g.completeExceptionally(new CFException()); - h = f.thenAcceptBothAsync(g, r = new SubtractAction(), e); - checkCompletedWithWrappedCFException(h); - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - f.completeExceptionally(new CFException()); - g.complete(3); - h = f.thenAcceptBothAsync(g, r = new SubtractAction(), e); - checkCompletedWithWrappedCFException(h); - - assertEquals(0, e.count.get()); - } - - /** - * thenAcceptBothAsync result completes exceptionally if action does - */ - public void testThenAcceptBothAsync3E() { - CompletableFuture f, g; - CompletableFuture h; - FailingBiConsumer r; - ThreadExecutor e = new ThreadExecutor(); - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenAcceptBothAsync(g, r = new FailingBiConsumer(), e); - f.complete(3); - checkIncomplete(h); - g.complete(1); - checkCompletedWithWrappedCFException(h); - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - f.complete(3); - g.complete(1); - h = f.thenAcceptBothAsync(g, r = new FailingBiConsumer(), e); - checkCompletedWithWrappedCFException(h); - - assertEquals(2, e.count.get()); - } - - /** - * thenAcceptBothAsync result completes exceptionally if either source cancelled - */ - public void testThenAcceptBothAsync4E() { - CompletableFuture f, g; - CompletableFuture h; - SubtractAction r; - ThreadExecutor e = new ThreadExecutor(); - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenAcceptBothAsync(g, r = new SubtractAction(), e); - assertTrue(f.cancel(true)); - checkIncomplete(h); - g.complete(1); - checkCompletedWithWrappedCancellationException(h); - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - h = f.thenAcceptBothAsync(g, r = new SubtractAction(), e); - assertTrue(g.cancel(true)); - checkIncomplete(h); - f.complete(3); - checkCompletedWithWrappedCancellationException(h); - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - f.complete(3); - assertTrue(g.cancel(true)); - h = f.thenAcceptBothAsync(g, r = new SubtractAction(), e); - checkCompletedWithWrappedCancellationException(h); - - f = new CompletableFuture<>(); - g = new CompletableFuture<>(); - assertTrue(f.cancel(true)); - g.complete(3); - h = f.thenAcceptBothAsync(g, r = new SubtractAction(), e); - checkCompletedWithWrappedCancellationException(h); - - assertEquals(0, e.count.get()); - } - - /** - * runAfterBothAsync result completes normally after normal - * completion of sources - */ - public void testRunAfterBothAsyncE() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - Noop r = new Noop(); - CompletableFuture g = f.runAfterBothAsync(f2, r, new ThreadExecutor()); - f.complete(one); - checkIncomplete(g); - f2.complete(two); - checkCompletedNormally(g, null); - assertTrue(r.ran); - } - - /** - * runAfterBothAsync result completes exceptionally after exceptional - * completion of source - */ - public void testRunAfterBothAsync2E() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - Noop r = new Noop(); - CompletableFuture g = f.runAfterBothAsync(f2, r, new ThreadExecutor()); - f.completeExceptionally(new CFException()); - f2.complete(two); - checkCompletedWithWrappedCFException(g); - - r = new Noop(); - f = new CompletableFuture<>(); - f2 = new CompletableFuture<>(); - g = f.runAfterBothAsync(f2, r, new ThreadExecutor()); - f.complete(one); - f2.completeExceptionally(new CFException()); - checkCompletedWithWrappedCFException(g); - } - - /** - * runAfterBothAsync result completes exceptionally if action does - */ - public void testRunAfterBothAsync3E() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - FailingNoop r = new FailingNoop(); - CompletableFuture g = f.runAfterBothAsync(f2, r, new ThreadExecutor()); - f.complete(one); - checkIncomplete(g); - f2.complete(two); - checkCompletedWithWrappedCFException(g); - } - - /** - * runAfterBothAsync result completes exceptionally if either source cancelled - */ - public void testRunAfterBothAsync4E() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - Noop r = new Noop(); - CompletableFuture g = f.runAfterBothAsync(f2, r, new ThreadExecutor()); - assertTrue(f.cancel(true)); - f2.complete(two); - checkCompletedWithWrappedCancellationException(g); - - r = new Noop(); - f = new CompletableFuture<>(); - f2 = new CompletableFuture<>(); - g = f.runAfterBothAsync(f2, r, new ThreadExecutor()); - f.complete(one); - assertTrue(f2.cancel(true)); - checkCompletedWithWrappedCancellationException(g); - } - - /** * applyToEitherAsync result completes normally after normal * completion of sources */ @@ -2931,97 +2938,99 @@ public class CompletableFutureTest exten ThreadExecutor exec = new ThreadExecutor(); Runnable[] throwingActions = { - () -> { CompletableFuture.supplyAsync(null); }, - () -> { CompletableFuture.supplyAsync(null, exec); }, - () -> { CompletableFuture.supplyAsync(supplyOne, null); }, - - () -> { CompletableFuture.runAsync(null); }, - () -> { CompletableFuture.runAsync(null, exec); }, - () -> { CompletableFuture.runAsync(() -> {}, null); }, - - () -> { f.completeExceptionally(null); }, - - () -> { f.thenApply(null); }, - () -> { f.thenApplyAsync(null); }, - () -> { f.thenApplyAsync((x) -> x, null); }, - () -> { f.thenApplyAsync(null, exec); }, - - () -> { f.thenAccept(null); }, - () -> { f.thenAcceptAsync(null); }, - () -> { f.thenAcceptAsync((x) -> { ; }, null); }, - () -> { f.thenAcceptAsync(null, exec); }, - - () -> { f.thenRun(null); }, - () -> { f.thenRunAsync(null); }, - () -> { f.thenRunAsync(() -> { ; }, null); }, - () -> { f.thenRunAsync(null, exec); }, - - () -> { f.thenCombine(g, null); }, - () -> { f.thenCombineAsync(g, null); }, - () -> { f.thenCombineAsync(g, null, exec); }, - () -> { f.thenCombine(nullFuture, (x, y) -> x); }, - () -> { f.thenCombineAsync(nullFuture, (x, y) -> x); }, - () -> { f.thenCombineAsync(nullFuture, (x, y) -> x, exec); }, - () -> { f.thenCombineAsync(g, (x, y) -> x, null); }, - - () -> { f.thenAcceptBoth(g, null); }, - () -> { f.thenAcceptBothAsync(g, null); }, - () -> { f.thenAcceptBothAsync(g, null, exec); }, - () -> { f.thenAcceptBoth(nullFuture, (x, y) -> {}); }, - () -> { f.thenAcceptBothAsync(nullFuture, (x, y) -> {}); }, - () -> { f.thenAcceptBothAsync(nullFuture, (x, y) -> {}, exec); }, - () -> { f.thenAcceptBothAsync(g, (x, y) -> {}, null); }, - - () -> { f.runAfterBoth(g, null); }, - () -> { f.runAfterBothAsync(g, null); }, - () -> { f.runAfterBothAsync(g, null, exec); }, - () -> { f.runAfterBoth(nullFuture, () -> {}); }, - () -> { f.runAfterBothAsync(nullFuture, () -> {}); }, - () -> { f.runAfterBothAsync(nullFuture, () -> {}, exec); }, - () -> { f.runAfterBothAsync(g, () -> {}, null); }, - - () -> { f.applyToEither(g, null); }, - () -> { f.applyToEitherAsync(g, null); }, - () -> { f.applyToEitherAsync(g, null, exec); }, - () -> { f.applyToEither(nullFuture, (x) -> x); }, - () -> { f.applyToEitherAsync(nullFuture, (x) -> x); }, - () -> { f.applyToEitherAsync(nullFuture, (x) -> x, exec); }, - () -> { f.applyToEitherAsync(g, (x) -> x, null); }, - - () -> { f.acceptEither(g, null); }, - () -> { f.acceptEitherAsync(g, null); }, - () -> { f.acceptEitherAsync(g, null, exec); }, - () -> { f.acceptEither(nullFuture, (x) -> {}); }, - () -> { f.acceptEitherAsync(nullFuture, (x) -> {}); }, - () -> { f.acceptEitherAsync(nullFuture, (x) -> {}, exec); }, - () -> { f.acceptEitherAsync(g, (x) -> {}, null); }, - - () -> { f.runAfterEither(g, null); }, - () -> { f.runAfterEitherAsync(g, null); }, - () -> { f.runAfterEitherAsync(g, null, exec); }, - () -> { f.runAfterEither(nullFuture, () -> {}); }, - () -> { f.runAfterEitherAsync(nullFuture, () -> {}); }, - () -> { f.runAfterEitherAsync(nullFuture, () -> {}, exec); }, - () -> { f.runAfterEitherAsync(g, () -> {}, null); }, - - () -> { f.thenCompose(null); }, - () -> { f.thenComposeAsync(null); }, - () -> { f.thenComposeAsync(new CompletableFutureInc(), null); }, - () -> { f.thenComposeAsync(null, exec); }, - - () -> { f.exceptionally(null); }, - - () -> { f.handle(null); }, - - () -> { CompletableFuture.allOf((CompletableFuture)null); }, - () -> { CompletableFuture.allOf((CompletableFuture[])null); }, - () -> { CompletableFuture.allOf(f, null); }, - () -> { CompletableFuture.allOf(null, f); }, - - () -> { CompletableFuture.anyOf((CompletableFuture)null); }, - () -> { CompletableFuture.anyOf((CompletableFuture[])null); }, - () -> { CompletableFuture.anyOf(f, null); }, - () -> { CompletableFuture.anyOf(null, f); }, + () -> CompletableFuture.supplyAsync(null), + () -> CompletableFuture.supplyAsync(null, exec), + () -> CompletableFuture.supplyAsync(supplyOne, null), + + () -> CompletableFuture.runAsync(null), + () -> CompletableFuture.runAsync(null, exec), + () -> CompletableFuture.runAsync(() -> {}, null), + + () -> f.completeExceptionally(null), + + () -> f.thenApply(null), + () -> f.thenApplyAsync(null), + () -> f.thenApplyAsync((x) -> x, null), + () -> f.thenApplyAsync(null, exec), + + () -> f.thenAccept(null), + () -> f.thenAcceptAsync(null), + () -> f.thenAcceptAsync((x) -> {} , null), + () -> f.thenAcceptAsync(null, exec), + + () -> f.thenRun(null), + () -> f.thenRunAsync(null), + () -> f.thenRunAsync(() -> {} , null), + () -> f.thenRunAsync(null, exec), + + () -> f.thenCombine(g, null), + () -> f.thenCombineAsync(g, null), + () -> f.thenCombineAsync(g, null, exec), + () -> f.thenCombine(nullFuture, (x, y) -> x), + () -> f.thenCombineAsync(nullFuture, (x, y) -> x), + () -> f.thenCombineAsync(nullFuture, (x, y) -> x, exec), + () -> f.thenCombineAsync(g, (x, y) -> x, null), + + () -> f.thenAcceptBoth(g, null), + () -> f.thenAcceptBothAsync(g, null), + () -> f.thenAcceptBothAsync(g, null, exec), + () -> f.thenAcceptBoth(nullFuture, (x, y) -> {}), + () -> f.thenAcceptBothAsync(nullFuture, (x, y) -> {}), + () -> f.thenAcceptBothAsync(nullFuture, (x, y) -> {}, exec), + () -> f.thenAcceptBothAsync(g, (x, y) -> {}, null), + + () -> f.runAfterBoth(g, null), + () -> f.runAfterBothAsync(g, null), + () -> f.runAfterBothAsync(g, null, exec), + () -> f.runAfterBoth(nullFuture, () -> {}), + () -> f.runAfterBothAsync(nullFuture, () -> {}), + () -> f.runAfterBothAsync(nullFuture, () -> {}, exec), + () -> f.runAfterBothAsync(g, () -> {}, null), + + () -> f.applyToEither(g, null), + () -> f.applyToEitherAsync(g, null), + () -> f.applyToEitherAsync(g, null, exec), + () -> f.applyToEither(nullFuture, (x) -> x), + () -> f.applyToEitherAsync(nullFuture, (x) -> x), + () -> f.applyToEitherAsync(nullFuture, (x) -> x, exec), + () -> f.applyToEitherAsync(g, (x) -> x, null), + + () -> f.acceptEither(g, null), + () -> f.acceptEitherAsync(g, null), + () -> f.acceptEitherAsync(g, null, exec), + () -> f.acceptEither(nullFuture, (x) -> {}), + () -> f.acceptEitherAsync(nullFuture, (x) -> {}), + () -> f.acceptEitherAsync(nullFuture, (x) -> {}, exec), + () -> f.acceptEitherAsync(g, (x) -> {}, null), + + () -> f.runAfterEither(g, null), + () -> f.runAfterEitherAsync(g, null), + () -> f.runAfterEitherAsync(g, null, exec), + () -> f.runAfterEither(nullFuture, () -> {}), + () -> f.runAfterEitherAsync(nullFuture, () -> {}), + () -> f.runAfterEitherAsync(nullFuture, () -> {}, exec), + () -> f.runAfterEitherAsync(g, () -> {}, null), + + () -> f.thenCompose(null), + () -> f.thenComposeAsync(null), + () -> f.thenComposeAsync(new CompletableFutureInc(), null), + () -> f.thenComposeAsync(null, exec), + + () -> f.exceptionally(null), + + () -> f.handle(null), + + () -> CompletableFuture.allOf((CompletableFuture)null), + () -> CompletableFuture.allOf((CompletableFuture[])null), + () -> CompletableFuture.allOf(f, null), + () -> CompletableFuture.allOf(null, f), + + () -> CompletableFuture.anyOf((CompletableFuture)null), + () -> CompletableFuture.anyOf((CompletableFuture[])null), + () -> CompletableFuture.anyOf(f, null), + () -> CompletableFuture.anyOf(null, f), + + () -> f.obtrudeException(null), }; assertThrows(NullPointerException.class, throwingActions);