--- jsr166/src/test/tck/CompletableFutureTest.java 2014/06/01 23:51:44 1.38 +++ jsr166/src/test/tck/CompletableFutureTest.java 2014/06/02 06:07:34 1.45 @@ -339,7 +339,6 @@ public class CompletableFutureTest exten static final class IncAction implements Consumer { int invocationCount = 0; Integer value; - public boolean ran() { return invocationCount == 1; } public void accept(Integer x) { invocationCount++; value = inc(x); @@ -348,7 +347,6 @@ public class CompletableFutureTest exten static final class IncFunction implements Function { int invocationCount = 0; Integer value; - public boolean ran() { return invocationCount == 1; } public Integer apply(Integer x) { invocationCount++; return value = inc(x); @@ -358,7 +356,6 @@ public class CompletableFutureTest exten int invocationCount = 0; Integer 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) { invocationCount++; value = subtract(x, y); @@ -368,58 +365,78 @@ public class CompletableFutureTest exten int invocationCount = 0; Integer 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 value = subtract(x, y); } } static final class Noop implements Runnable { - boolean ran; - public void run() { ran = true; } + int invocationCount = 0; + public void run() { + invocationCount++; + } } static final class FailingSupplier implements Supplier { - boolean ran; - public Integer get() { ran = true; throw new CFException(); } + int invocationCount = 0; + public Integer get() { + invocationCount++; + throw new CFException(); + } } static final class FailingConsumer implements Consumer { - boolean ran; - public void accept(Integer x) { ran = true; throw new CFException(); } + int invocationCount = 0; + public void accept(Integer x) { + invocationCount++; + throw new CFException(); + } } static final class FailingBiConsumer implements BiConsumer { - boolean ran; - public void accept(Integer x, Integer y) { ran = true; throw new CFException(); } + int invocationCount = 0; + public void accept(Integer x, Integer y) { + invocationCount++; + throw new CFException(); + } } static final class FailingFunction implements Function { - boolean ran; - public Integer apply(Integer x) { ran = true; throw new CFException(); } + int invocationCount = 0; + public Integer apply(Integer x) { + invocationCount++; + throw new CFException(); + } } static final class FailingBiFunction implements BiFunction { - boolean ran; - public Integer apply(Integer x, Integer y) { ran = true; throw new CFException(); } + int invocationCount = 0; + public Integer apply(Integer x, Integer y) { + invocationCount++; + throw new CFException(); + } } static final class FailingNoop implements Runnable { - boolean ran; - public void run() { ran = true; throw new CFException(); } + int invocationCount = 0; + public void run() { + invocationCount++; + throw new CFException(); + } } static final class CompletableFutureInc implements Function> { - boolean ran; + int invocationCount = 0; public CompletableFuture apply(Integer x) { - ran = true; + invocationCount++; CompletableFuture f = new CompletableFuture<>(); - f.complete(Integer.valueOf(x.intValue() + 1)); + f.complete(inc(x)); return f; } } static final class FailingCompletableFutureFunction implements Function> { - boolean ran; + int invocationCount = 0; public CompletableFuture apply(Integer x) { - ran = true; throw new CFException(); + invocationCount++; + throw new CFException(); } } @@ -438,9 +455,9 @@ public class CompletableFutureTest exten } static final class IntegerHandler implements BiFunction { - boolean ran; + int invocationCount = 0; public Integer apply(Integer x, Throwable t) { - ran = true; + invocationCount++; return (t == null) ? two : three; } } @@ -497,20 +514,6 @@ public class CompletableFutureTest exten } }, -// /** 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) { @@ -558,19 +561,6 @@ public class CompletableFutureTest exten } }, -// 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) { @@ -679,27 +669,28 @@ public class CompletableFutureTest exten f = new CompletableFuture<>(); f.completeExceptionally(new CFException()); g = f.handle(r = new IntegerHandler()); - assertTrue(r.ran); + assertEquals(1, r.invocationCount); + assertEquals(1, r.invocationCount); checkCompletedNormally(g, three); f = new CompletableFuture<>(); g = f.handle(r = new IntegerHandler()); - assertFalse(r.ran); + assertEquals(0, r.invocationCount); f.completeExceptionally(new CFException()); checkCompletedNormally(g, three); - assertTrue(r.ran); + assertEquals(1, r.invocationCount); f = new CompletableFuture<>(); f.complete(one); g = f.handle(r = new IntegerHandler()); - assertTrue(r.ran); + assertEquals(1, r.invocationCount); checkCompletedNormally(g, two); f = new CompletableFuture<>(); g = f.handle(r = new IntegerHandler()); - assertFalse(r.ran); + assertEquals(0, r.invocationCount); f.complete(one); - assertTrue(r.ran); + assertEquals(1, r.invocationCount); checkCompletedNormally(g, two); } @@ -710,7 +701,7 @@ public class CompletableFutureTest exten Noop r = new Noop(); CompletableFuture f = CompletableFuture.runAsync(r); assertNull(f.join()); - assertTrue(r.ran); + assertEquals(1, r.invocationCount); checkCompletedNormally(f, null); } @@ -722,7 +713,7 @@ public class CompletableFutureTest exten ThreadExecutor exec = new ThreadExecutor(); CompletableFuture f = CompletableFuture.runAsync(r, exec); assertNull(f.join()); - assertTrue(r.ran); + assertEquals(1, r.invocationCount); checkCompletedNormally(f, null); assertEquals(1, exec.count.get()); } @@ -734,7 +725,7 @@ public class CompletableFutureTest exten FailingNoop r = new FailingNoop(); CompletableFuture f = CompletableFuture.runAsync(r); checkCompletedWithWrappedCFException(f); - assertTrue(r.ran); + assertEquals(1, r.invocationCount); } /** @@ -764,7 +755,7 @@ public class CompletableFutureTest exten FailingSupplier r = new FailingSupplier(); CompletableFuture f = CompletableFuture.supplyAsync(r); checkCompletedWithWrappedCFException(f); - assertTrue(r.ran); + assertEquals(1, r.invocationCount); } // seq completion methods @@ -781,13 +772,13 @@ public class CompletableFutureTest exten g = f.thenRun(r = new Noop()); f.complete(null); checkCompletedNormally(g, null); - assertTrue(r.ran); + assertEquals(1, r.invocationCount); f = new CompletableFuture<>(); f.complete(null); g = f.thenRun(r = new Noop()); checkCompletedNormally(g, null); - assertTrue(r.ran); + assertEquals(1, r.invocationCount); } /** @@ -803,13 +794,13 @@ public class CompletableFutureTest exten g = f.thenRun(r = new Noop()); f.completeExceptionally(new CFException()); checkCompletedWithWrappedCFException(g); - assertFalse(r.ran); + assertEquals(0, r.invocationCount); f = new CompletableFuture<>(); f.completeExceptionally(new CFException()); g = f.thenRun(r = new Noop()); checkCompletedWithWrappedCFException(g); - assertFalse(r.ran); + assertEquals(0, r.invocationCount); } /** @@ -924,7 +915,7 @@ public class CompletableFutureTest exten CompletableFuture g = f.thenAccept(r); f.complete(one); checkCompletedWithWrappedCFException(g); - assertTrue(r.ran); + assertEquals(1, r.invocationCount); } /** @@ -943,6 +934,8 @@ public class CompletableFutureTest exten * of sources */ public void testThenCombine_normalCompletion1() { + for (boolean createIncomplete : new boolean[] { true, false }) + for (boolean fFirst : new boolean[] { true, false }) for (ExecutionMode m : ExecutionMode.values()) for (Integer v1 : new Integer[] { 1, null }) for (Integer v2 : new Integer[] { 2, null }) { @@ -950,75 +943,25 @@ public class CompletableFutureTest exten 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); - } - } - - 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); - } - } - - 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); - } - } - - 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(); + CompletableFuture h = null; + if (createIncomplete) h = m.thenCombine(f, g, r); - f.complete(v1); - g.complete(v2); - final CompletableFuture h = m.thenCombine(f, g, r); + if (fFirst) + f.complete(v1); + else + g.complete(v2); + if (createIncomplete) checkIncomplete(h); + assertEquals(0, r.invocationCount); + if (!fFirst) + f.complete(v1); + else + g.complete(v2); + if (!createIncomplete) h = m.thenCombine(f, g, r); checkCompletedNormally(h, subtract(v1, v2)); checkCompletedNormally(f, v1); checkCompletedNormally(g, v2); + assertEquals(1, r.invocationCount); } } @@ -1042,7 +985,7 @@ public class CompletableFutureTest exten checkCompletedWithWrappedCFException(h, ex); checkCompletedWithWrappedCFException(f, ex); - assertFalse(r.ran()); + assertEquals(0, r.invocationCount); checkCompletedNormally(g, v1); } } @@ -1063,7 +1006,7 @@ public class CompletableFutureTest exten checkCompletedWithWrappedCFException(h, ex); checkCompletedWithWrappedCFException(g, ex); - assertFalse(r.ran()); + assertEquals(0, r.invocationCount); checkCompletedNormally(f, v1); } } @@ -1083,7 +1026,7 @@ public class CompletableFutureTest exten checkCompletedWithWrappedCFException(h, ex); checkCompletedWithWrappedCFException(g, ex); - assertFalse(r.ran()); + assertEquals(0, r.invocationCount); checkCompletedNormally(f, v1); } } @@ -1103,7 +1046,7 @@ public class CompletableFutureTest exten checkCompletedWithWrappedCFException(h, ex); checkCompletedWithWrappedCFException(f, ex); - assertFalse(r.ran()); + assertEquals(0, r.invocationCount); checkCompletedNormally(g, v1); } } @@ -1170,7 +1113,7 @@ public class CompletableFutureTest exten checkCompletedWithWrappedCancellationException(h); checkCancelled(f); - assertFalse(r.ran()); + assertEquals(0, r.invocationCount); checkCompletedNormally(g, v1); } } @@ -1191,7 +1134,7 @@ public class CompletableFutureTest exten checkCompletedWithWrappedCancellationException(h); checkCancelled(g); - assertFalse(r.ran()); + assertEquals(0, r.invocationCount); checkCompletedNormally(f, v1); } } @@ -1211,7 +1154,7 @@ public class CompletableFutureTest exten checkCompletedWithWrappedCancellationException(h); checkCancelled(g); - assertFalse(r.ran()); + assertEquals(0, r.invocationCount); checkCompletedNormally(f, v1); } } @@ -1231,7 +1174,7 @@ public class CompletableFutureTest exten checkCompletedWithWrappedCancellationException(h); checkCancelled(f); - assertFalse(r.ran()); + assertEquals(0, r.invocationCount); checkCompletedNormally(g, v1); } } @@ -1252,7 +1195,7 @@ public class CompletableFutureTest exten f.complete(v1); checkIncomplete(h); - assertFalse(r.ran()); + assertEquals(0, r.invocationCount); g.complete(v2); checkCompletedNormally(h, null); @@ -1274,7 +1217,7 @@ public class CompletableFutureTest exten g.complete(v2); checkIncomplete(h); - assertFalse(r.ran()); + assertEquals(0, r.invocationCount); f.complete(v1); checkCompletedNormally(h, null); @@ -1344,7 +1287,7 @@ public class CompletableFutureTest exten checkCompletedWithWrappedCFException(h, ex); checkCompletedWithWrappedCFException(f, ex); - assertFalse(r.ran()); + assertEquals(0, r.invocationCount); checkCompletedNormally(g, v1); } } @@ -1365,7 +1308,7 @@ public class CompletableFutureTest exten checkCompletedWithWrappedCFException(h, ex); checkCompletedWithWrappedCFException(g, ex); - assertFalse(r.ran()); + assertEquals(0, r.invocationCount); checkCompletedNormally(f, v1); } } @@ -1385,7 +1328,7 @@ public class CompletableFutureTest exten checkCompletedWithWrappedCFException(h, ex); checkCompletedWithWrappedCFException(g, ex); - assertFalse(r.ran()); + assertEquals(0, r.invocationCount); checkCompletedNormally(f, v1); } } @@ -1405,7 +1348,7 @@ public class CompletableFutureTest exten checkCompletedWithWrappedCFException(h, ex); checkCompletedWithWrappedCFException(f, ex); - assertFalse(r.ran()); + assertEquals(0, r.invocationCount); checkCompletedNormally(g, v1); } } @@ -1472,7 +1415,7 @@ public class CompletableFutureTest exten checkCompletedWithWrappedCancellationException(h); checkCancelled(f); - assertFalse(r.ran()); + assertEquals(0, r.invocationCount); checkCompletedNormally(g, v1); } } @@ -1493,7 +1436,7 @@ public class CompletableFutureTest exten checkCompletedWithWrappedCancellationException(h); checkCancelled(g); - assertFalse(r.ran()); + assertEquals(0, r.invocationCount); checkCompletedNormally(f, v1); } } @@ -1513,7 +1456,7 @@ public class CompletableFutureTest exten checkCompletedWithWrappedCancellationException(h); checkCancelled(g); - assertFalse(r.ran()); + assertEquals(0, r.invocationCount); checkCompletedNormally(f, v1); } } @@ -1533,7 +1476,7 @@ public class CompletableFutureTest exten checkCompletedWithWrappedCancellationException(h); checkCancelled(f); - assertFalse(r.ran()); + assertEquals(0, r.invocationCount); checkCompletedNormally(g, v1); } } @@ -1554,11 +1497,11 @@ public class CompletableFutureTest exten f.complete(v1); checkIncomplete(h); - assertFalse(r.ran); + assertEquals(0, r.invocationCount); g.complete(v2); checkCompletedNormally(h, null); - assertTrue(r.ran); + assertEquals(1, r.invocationCount); checkCompletedNormally(f, v1); checkCompletedNormally(g, v2); } @@ -1576,11 +1519,11 @@ public class CompletableFutureTest exten g.complete(v2); checkIncomplete(h); - assertFalse(r.ran); + assertEquals(0, r.invocationCount); f.complete(v1); checkCompletedNormally(h, null); - assertTrue(r.ran); + assertEquals(1, r.invocationCount); checkCompletedNormally(f, v1); checkCompletedNormally(g, v2); } @@ -1600,7 +1543,7 @@ public class CompletableFutureTest exten final CompletableFuture h = m.runAfterBoth(f, g, r); checkCompletedNormally(h, null); - assertTrue(r.ran); + assertEquals(1, r.invocationCount); checkCompletedNormally(f, v1); checkCompletedNormally(g, v2); } @@ -1620,7 +1563,7 @@ public class CompletableFutureTest exten final CompletableFuture h = m.runAfterBoth(f, g, r); checkCompletedNormally(h, null); - assertTrue(r.ran); + assertEquals(1, r.invocationCount); checkCompletedNormally(f, v1); checkCompletedNormally(g, v2); } @@ -1646,7 +1589,7 @@ public class CompletableFutureTest exten checkCompletedWithWrappedCFException(h, ex); checkCompletedWithWrappedCFException(f, ex); - assertFalse(r.ran); + assertEquals(0, r.invocationCount); checkCompletedNormally(g, v1); } } @@ -1667,7 +1610,7 @@ public class CompletableFutureTest exten checkCompletedWithWrappedCFException(h, ex); checkCompletedWithWrappedCFException(g, ex); - assertFalse(r.ran); + assertEquals(0, r.invocationCount); checkCompletedNormally(f, v1); } } @@ -1687,7 +1630,7 @@ public class CompletableFutureTest exten checkCompletedWithWrappedCFException(h, ex); checkCompletedWithWrappedCFException(g, ex); - assertFalse(r.ran); + assertEquals(0, r.invocationCount); checkCompletedNormally(f, v1); } } @@ -1707,7 +1650,7 @@ public class CompletableFutureTest exten checkCompletedWithWrappedCFException(h, ex); checkCompletedWithWrappedCFException(f, ex); - assertFalse(r.ran); + assertEquals(0, r.invocationCount); checkCompletedNormally(g, v1); } } @@ -1774,7 +1717,7 @@ public class CompletableFutureTest exten checkCompletedWithWrappedCancellationException(h); checkCancelled(f); - assertFalse(r.ran); + assertEquals(0, r.invocationCount); checkCompletedNormally(g, v1); } } @@ -1795,7 +1738,7 @@ public class CompletableFutureTest exten checkCompletedWithWrappedCancellationException(h); checkCancelled(g); - assertFalse(r.ran); + assertEquals(0, r.invocationCount); checkCompletedNormally(f, v1); } } @@ -1815,7 +1758,7 @@ public class CompletableFutureTest exten checkCompletedWithWrappedCancellationException(h); checkCancelled(g); - assertFalse(r.ran); + assertEquals(0, r.invocationCount); checkCompletedNormally(f, v1); } } @@ -1835,7 +1778,7 @@ public class CompletableFutureTest exten checkCompletedWithWrappedCancellationException(h); checkCancelled(f); - assertFalse(r.ran); + assertEquals(0, r.invocationCount); checkCompletedNormally(g, v1); } } @@ -1844,287 +1787,1052 @@ public class CompletableFutureTest exten * applyToEither result completes normally after normal completion * of either source */ - public void testApplyToEither() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - CompletableFuture g = f.applyToEither(f2, inc); - f.complete(one); - checkCompletedNormally(g, two); - f2.complete(one); - checkCompletedNormally(g, two); + public void testApplyToEither_normalCompletion1() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) + for (Integer v2 : new Integer[] { 2, null }) { - f = new CompletableFuture<>(); - f.complete(one); - f2 = new CompletableFuture<>(); - g = f.applyToEither(f2, inc); - checkCompletedNormally(g, two); + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final IncFunction r = new IncFunction(); + final CompletableFuture h = m.applyToEither(f, g, r); + + f.complete(v1); + checkCompletedNormally(h, inc(v1)); + g.complete(v2); + + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + checkCompletedNormally(h, inc(v1)); + } + } + + public void testApplyToEither_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 IncFunction r = new IncFunction(); + final CompletableFuture h = m.applyToEither(f, g, r); + + g.complete(v2); + checkCompletedNormally(h, inc(v2)); + f.complete(v1); + + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + checkCompletedNormally(h, inc(v2)); + } + } + public void testApplyToEither_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 IncFunction r = new IncFunction(); + + f.complete(v1); + g.complete(v2); + final CompletableFuture h = m.applyToEither(f, g, r); + + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + + // unspecified behavior + assertTrue(Objects.equals(h.join(), inc(v1)) || + Objects.equals(h.join(), inc(v2))); + assertEquals(1, r.invocationCount); + } } /** * applyToEither result completes exceptionally after exceptional * completion of either source */ - public void testApplyToEither2() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - CompletableFuture g = f.applyToEither(f2, inc); - f.completeExceptionally(new CFException()); - f2.complete(one); - checkCompletedWithWrappedCFException(g); + public void testApplyToEither_exceptionalCompletion1() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) { - f = new CompletableFuture<>(); - f2 = new CompletableFuture<>(); - f2.completeExceptionally(new CFException()); - g = f.applyToEither(f2, inc); - checkCompletedWithWrappedCFException(g); + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final IncFunction r = new IncFunction(); + final CompletableFuture h = m.applyToEither(f, g, r); + final CFException ex = new CFException(); + + f.completeExceptionally(ex); + checkCompletedWithWrappedCFException(h, ex); + g.complete(v1); + + assertEquals(0, r.invocationCount); + checkCompletedNormally(g, v1); + checkCompletedWithWrappedCFException(f, ex); + checkCompletedWithWrappedCFException(h, ex); + } + } + + public void testApplyToEither_exceptionalCompletion2() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) { + + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final IncFunction r = new IncFunction(); + final CompletableFuture h = m.applyToEither(f, g, r); + final CFException ex = new CFException(); + + g.completeExceptionally(ex); + checkCompletedWithWrappedCFException(h, ex); + f.complete(v1); + + assertEquals(0, r.invocationCount); + checkCompletedNormally(f, v1); + checkCompletedWithWrappedCFException(g, ex); + checkCompletedWithWrappedCFException(h, ex); + } + } + + public void testApplyToEither_exceptionalCompletion3() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) { + + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final IncFunction r = new IncFunction(); + final CFException ex = new CFException(); + + g.completeExceptionally(ex); + f.complete(v1); + final CompletableFuture h = m.applyToEither(f, g, r); + + // unspecified behavior + Integer v; + try { + assertEquals(h.join(), inc(v1)); + assertEquals(1, r.invocationCount); + } catch (CompletionException ok) { + checkCompletedWithWrappedCFException(h, ex); + assertEquals(0, r.invocationCount); + } + + checkCompletedWithWrappedCFException(g, ex); + checkCompletedNormally(f, v1); + } + } + + public void testApplyToEither_exceptionalCompletion4() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) { + + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final IncFunction r = new IncFunction(); + final CFException ex = new CFException(); + + f.completeExceptionally(ex); + g.complete(v1); + final CompletableFuture h = m.applyToEither(f, g, r); + + // unspecified behavior + Integer v; + try { + assertEquals(h.join(), inc(v1)); + assertEquals(1, r.invocationCount); + } catch (CompletionException ok) { + checkCompletedWithWrappedCFException(h, ex); + assertEquals(0, r.invocationCount); + } + + checkCompletedWithWrappedCFException(f, ex); + checkCompletedNormally(g, v1); + } } /** * applyToEither result completes exceptionally if action does */ - public void testApplyToEither3() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - FailingFunction r = new FailingFunction(); - CompletableFuture g = f.applyToEither(f2, r); - f2.complete(two); - checkCompletedWithWrappedCFException(g); + public void testApplyToEither_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 FailingFunction r = new FailingFunction(); + final CompletableFuture h = m.applyToEither(f, g, r); + + f.complete(v1); + checkCompletedWithWrappedCFException(h); + g.complete(v2); + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + } + } + + public void testApplyToEither_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 FailingFunction r = new FailingFunction(); + final CompletableFuture h = m.applyToEither(f, g, r); + + g.complete(v2); + checkCompletedWithWrappedCFException(h); + f.complete(v1); + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + } } /** * applyToEither result completes exceptionally if either source cancelled */ - public void testApplyToEither4() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - CompletableFuture g = f.applyToEither(f2, inc); - assertTrue(f.cancel(true)); - checkCompletedWithWrappedCancellationException(g); - f = new CompletableFuture<>(); - f2 = new CompletableFuture<>(); - assertTrue(f2.cancel(true)); - checkCompletedWithWrappedCancellationException(g); + public void testApplyToEither_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 IncFunction r = new IncFunction(); + final CompletableFuture h = m.applyToEither(f, g, r); + + assertTrue(f.cancel(mayInterruptIfRunning)); + checkCompletedWithWrappedCancellationException(h); + g.complete(v1); + + checkCancelled(f); + assertEquals(0, r.invocationCount); + checkCompletedNormally(g, v1); + checkCompletedWithWrappedCancellationException(h); + } + } + + public void testApplyToEither_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 IncFunction r = new IncFunction(); + final CompletableFuture h = m.applyToEither(f, g, r); + + assertTrue(g.cancel(mayInterruptIfRunning)); + checkCompletedWithWrappedCancellationException(h); + f.complete(v1); + + checkCancelled(g); + assertEquals(0, r.invocationCount); + checkCompletedNormally(f, v1); + checkCompletedWithWrappedCancellationException(h); + } + } + + public void testApplyToEither_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 IncFunction r = new IncFunction(); + + assertTrue(g.cancel(mayInterruptIfRunning)); + f.complete(v1); + final CompletableFuture h = m.applyToEither(f, g, r); + + // unspecified behavior + Integer v; + try { + assertEquals(h.join(), inc(v1)); + assertEquals(1, r.invocationCount); + } catch (CompletionException ok) { + checkCompletedWithWrappedCancellationException(h); + assertEquals(0, r.invocationCount); + } + + checkCancelled(g); + checkCompletedNormally(f, v1); + } + } + + public void testApplyToEither_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 IncFunction r = new IncFunction(); + + assertTrue(f.cancel(mayInterruptIfRunning)); + g.complete(v1); + final CompletableFuture h = m.applyToEither(f, g, r); + + // unspecified behavior + Integer v; + try { + assertEquals(h.join(), inc(v1)); + assertEquals(1, r.invocationCount); + } catch (CompletionException ok) { + checkCompletedWithWrappedCancellationException(h); + assertEquals(0, r.invocationCount); + } + + checkCancelled(f); + checkCompletedNormally(g, v1); + } } /** * acceptEither result completes normally after normal completion * of either source */ - public void testAcceptEither() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - IncAction r = new IncAction(); - CompletableFuture g = f.acceptEither(f2, r); - f.complete(one); - checkCompletedNormally(g, null); - f2.complete(one); - checkCompletedNormally(g, null); - assertEquals(r.value, (Integer) 2); + public void testAcceptEither_normalCompletion1() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) + for (Integer v2 : new Integer[] { 2, null }) { - r = new IncAction(); - f = new CompletableFuture<>(); - f.complete(one); - f2 = new CompletableFuture<>(); - g = f.acceptEither(f2, r); - checkCompletedNormally(g, null); - assertEquals(r.value, (Integer) 2); + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final IncAction r = new IncAction(); + final CompletableFuture h = m.acceptEither(f, g, r); + + f.complete(v1); + checkCompletedNormally(h, null); + assertEquals(r.value, inc(v1)); + g.complete(v2); + + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + checkCompletedNormally(h, null); + } + } + + public void testAcceptEither_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 IncAction r = new IncAction(); + final CompletableFuture h = m.acceptEither(f, g, r); + + g.complete(v2); + checkCompletedNormally(h, null); + assertEquals(r.value, inc(v2)); + f.complete(v1); + + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + checkCompletedNormally(h, null); + } + } + public void testAcceptEither_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 IncAction r = new IncAction(); + + f.complete(v1); + g.complete(v2); + final CompletableFuture h = m.acceptEither(f, g, r); + + checkCompletedNormally(h, null); + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + + // unspecified behavior + assertTrue(Objects.equals(r.value, inc(v1)) || + Objects.equals(r.value, inc(v2))); + } } /** * acceptEither result completes exceptionally after exceptional * completion of either source */ - public void testAcceptEither2() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - IncAction r = new IncAction(); - CompletableFuture g = f.acceptEither(f2, r); - f.completeExceptionally(new CFException()); - f2.complete(one); - checkCompletedWithWrappedCFException(g); + public void testAcceptEither_exceptionalCompletion1() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) { - r = new IncAction(); - f = new CompletableFuture<>(); - f2 = new CompletableFuture<>(); - f2.completeExceptionally(new CFException()); - g = f.acceptEither(f2, r); - checkCompletedWithWrappedCFException(g); + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final IncAction r = new IncAction(); + final CompletableFuture h = m.acceptEither(f, g, r); + final CFException ex = new CFException(); + + f.completeExceptionally(ex); + checkCompletedWithWrappedCFException(h, ex); + g.complete(v1); + + assertEquals(0, r.invocationCount); + checkCompletedNormally(g, v1); + checkCompletedWithWrappedCFException(f, ex); + checkCompletedWithWrappedCFException(h, ex); + } + } + + public void testAcceptEither_exceptionalCompletion2() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) { + + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final IncAction r = new IncAction(); + final CompletableFuture h = m.acceptEither(f, g, r); + final CFException ex = new CFException(); + + g.completeExceptionally(ex); + checkCompletedWithWrappedCFException(h, ex); + f.complete(v1); + + assertEquals(0, r.invocationCount); + checkCompletedNormally(f, v1); + checkCompletedWithWrappedCFException(g, ex); + checkCompletedWithWrappedCFException(h, ex); + } + } + + public void testAcceptEither_exceptionalCompletion3() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) { + + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final IncAction r = new IncAction(); + final CFException ex = new CFException(); + + g.completeExceptionally(ex); + f.complete(v1); + final CompletableFuture h = m.acceptEither(f, g, r); + + // unspecified behavior + Integer v; + try { + assertEquals(h.join(), null); + assertEquals(1, r.invocationCount); + assertEquals(inc(v1), r.value); + } catch (CompletionException ok) { + checkCompletedWithWrappedCFException(h, ex); + assertEquals(0, r.invocationCount); + } + + checkCompletedWithWrappedCFException(g, ex); + checkCompletedNormally(f, v1); + } + } + + public void testAcceptEither_exceptionalCompletion4() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) { + + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final IncAction r = new IncAction(); + final CFException ex = new CFException(); + + f.completeExceptionally(ex); + g.complete(v1); + final CompletableFuture h = m.acceptEither(f, g, r); + + // unspecified behavior + Integer v; + try { + assertEquals(h.join(), null); + assertEquals(1, r.invocationCount); + assertEquals(inc(v1), r.value); + } catch (CompletionException ok) { + checkCompletedWithWrappedCFException(h, ex); + assertEquals(0, r.invocationCount); + } + + checkCompletedWithWrappedCFException(f, ex); + checkCompletedNormally(g, v1); + } } /** * acceptEither result completes exceptionally if action does */ - public void testAcceptEither3() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - FailingConsumer r = new FailingConsumer(); - CompletableFuture g = f.acceptEither(f2, r); - f2.complete(two); - checkCompletedWithWrappedCFException(g); + public void testAcceptEither_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 FailingConsumer r = new FailingConsumer(); + final CompletableFuture h = m.acceptEither(f, g, r); + + f.complete(v1); + checkCompletedWithWrappedCFException(h); + g.complete(v2); + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + } + } + + public void testAcceptEither_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 FailingConsumer r = new FailingConsumer(); + final CompletableFuture h = m.acceptEither(f, g, r); + + g.complete(v2); + checkCompletedWithWrappedCFException(h); + f.complete(v1); + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + } } /** * acceptEither result completes exceptionally if either source cancelled */ - public void testAcceptEither4() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - IncAction r = new IncAction(); - CompletableFuture g = f.acceptEither(f2, r); - assertTrue(f.cancel(true)); - checkCompletedWithWrappedCancellationException(g); - f = new CompletableFuture<>(); - f2 = new CompletableFuture<>(); - assertTrue(f2.cancel(true)); - checkCompletedWithWrappedCancellationException(g); + public void testAcceptEither_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 IncAction r = new IncAction(); + final CompletableFuture h = m.acceptEither(f, g, r); + + assertTrue(f.cancel(mayInterruptIfRunning)); + checkCompletedWithWrappedCancellationException(h); + g.complete(v1); + + checkCancelled(f); + assertEquals(0, r.invocationCount); + checkCompletedNormally(g, v1); + checkCompletedWithWrappedCancellationException(h); + } + } + + public void testAcceptEither_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 IncAction r = new IncAction(); + final CompletableFuture h = m.acceptEither(f, g, r); + + assertTrue(g.cancel(mayInterruptIfRunning)); + checkCompletedWithWrappedCancellationException(h); + f.complete(v1); + + checkCancelled(g); + assertEquals(0, r.invocationCount); + checkCompletedNormally(f, v1); + checkCompletedWithWrappedCancellationException(h); + } + } + + public void testAcceptEither_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 IncAction r = new IncAction(); + + assertTrue(g.cancel(mayInterruptIfRunning)); + f.complete(v1); + final CompletableFuture h = m.acceptEither(f, g, r); + + // unspecified behavior + Integer v; + try { + assertEquals(h.join(), null); + assertEquals(1, r.invocationCount); + assertEquals(inc(v1), r.value); + } catch (CompletionException ok) { + checkCompletedWithWrappedCancellationException(h); + assertEquals(0, r.invocationCount); + } + + checkCancelled(g); + checkCompletedNormally(f, v1); + } + } + + public void testAcceptEither_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 IncAction r = new IncAction(); + + assertTrue(f.cancel(mayInterruptIfRunning)); + g.complete(v1); + final CompletableFuture h = m.acceptEither(f, g, r); + + // unspecified behavior + Integer v; + try { + assertEquals(h.join(), null); + assertEquals(1, r.invocationCount); + assertEquals(inc(v1), r.value); + } catch (CompletionException ok) { + checkCompletedWithWrappedCancellationException(h); + assertEquals(0, r.invocationCount); + } + + checkCancelled(f); + checkCompletedNormally(g, v1); + } } /** * runAfterEither result completes normally after normal completion * of either source */ - public void testRunAfterEither() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - Noop r = new Noop(); - CompletableFuture g = f.runAfterEither(f2, r); - f.complete(one); - checkCompletedNormally(g, null); - f2.complete(one); - checkCompletedNormally(g, null); - assertTrue(r.ran); + public void testRunAfterEither_normalCompletion1() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) + for (Integer v2 : new Integer[] { 2, null }) { - r = new Noop(); - f = new CompletableFuture<>(); - f.complete(one); - f2 = new CompletableFuture<>(); - g = f.runAfterEither(f2, r); - checkCompletedNormally(g, null); - assertTrue(r.ran); + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final Noop r = new Noop(); + final CompletableFuture h = m.runAfterEither(f, g, r); + + f.complete(v1); + checkCompletedNormally(h, null); + assertEquals(1, r.invocationCount); + g.complete(v2); + + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + checkCompletedNormally(h, null); + assertEquals(1, r.invocationCount); + } + } + + public void testRunAfterEither_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.runAfterEither(f, g, r); + + g.complete(v2); + checkCompletedNormally(h, null); + assertEquals(1, r.invocationCount); + f.complete(v1); + + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + checkCompletedNormally(h, null); + assertEquals(1, r.invocationCount); + } + } + public void testRunAfterEither_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(); + + f.complete(v1); + g.complete(v2); + final CompletableFuture h = m.runAfterEither(f, g, r); + + checkCompletedNormally(h, null); + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + assertEquals(1, r.invocationCount); + } } /** * runAfterEither result completes exceptionally after exceptional * completion of either source */ - public void testRunAfterEither2() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - Noop r = new Noop(); - CompletableFuture g = f.runAfterEither(f2, r); - f.completeExceptionally(new CFException()); - f2.complete(one); - checkCompletedWithWrappedCFException(g); + public void testRunAfterEither_exceptionalCompletion1() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) { - r = new Noop(); - f = new CompletableFuture<>(); - f2 = new CompletableFuture<>(); - f2.completeExceptionally(new CFException()); - g = f.runAfterEither(f2, r); - checkCompletedWithWrappedCFException(g); + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final Noop r = new Noop(); + final CompletableFuture h = m.runAfterEither(f, g, r); + final CFException ex = new CFException(); + + f.completeExceptionally(ex); + checkCompletedWithWrappedCFException(h, ex); + g.complete(v1); + + assertEquals(0, r.invocationCount); + checkCompletedNormally(g, v1); + checkCompletedWithWrappedCFException(f, ex); + checkCompletedWithWrappedCFException(h, ex); + } + } + + public void testRunAfterEither_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.runAfterEither(f, g, r); + final CFException ex = new CFException(); + + g.completeExceptionally(ex); + checkCompletedWithWrappedCFException(h, ex); + f.complete(v1); + + assertEquals(0, r.invocationCount); + checkCompletedNormally(f, v1); + checkCompletedWithWrappedCFException(g, ex); + checkCompletedWithWrappedCFException(h, ex); + } + } + + public void testRunAfterEither_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.runAfterEither(f, g, r); + + // unspecified behavior + Integer v; + try { + assertEquals(h.join(), null); + assertEquals(1, r.invocationCount); + } catch (CompletionException ok) { + checkCompletedWithWrappedCFException(h, ex); + assertEquals(0, r.invocationCount); + } + + checkCompletedWithWrappedCFException(g, ex); + checkCompletedNormally(f, v1); + } + } + + public void testRunAfterEither_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.runAfterEither(f, g, r); + + // unspecified behavior + Integer v; + try { + assertEquals(h.join(), null); + assertEquals(1, r.invocationCount); + } catch (CompletionException ok) { + checkCompletedWithWrappedCFException(h, ex); + assertEquals(0, r.invocationCount); + } + + checkCompletedWithWrappedCFException(f, ex); + checkCompletedNormally(g, v1); + } } /** * runAfterEither result completes exceptionally if action does */ - public void testRunAfterEither3() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - FailingNoop r = new FailingNoop(); - CompletableFuture g = f.runAfterEither(f2, r); - f2.complete(two); - checkCompletedWithWrappedCFException(g); + public void testRunAfterEither_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.runAfterEither(f, g, r); + + f.complete(v1); + checkCompletedWithWrappedCFException(h); + g.complete(v2); + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + } + } + + public void testRunAfterEither_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.runAfterEither(f, g, r); + + g.complete(v2); + checkCompletedWithWrappedCFException(h); + f.complete(v1); + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v2); + } } /** * runAfterEither result completes exceptionally if either source cancelled */ - public void testRunAfterEither4() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - Noop r = new Noop(); - CompletableFuture g = f.runAfterEither(f2, r); - assertTrue(f.cancel(true)); - checkCompletedWithWrappedCancellationException(g); - f = new CompletableFuture<>(); - f2 = new CompletableFuture<>(); - assertTrue(f2.cancel(true)); - checkCompletedWithWrappedCancellationException(g); + public void testRunAfterEither_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.runAfterEither(f, g, r); + + assertTrue(f.cancel(mayInterruptIfRunning)); + checkCompletedWithWrappedCancellationException(h); + g.complete(v1); + + checkCancelled(f); + assertEquals(0, r.invocationCount); + checkCompletedNormally(g, v1); + checkCompletedWithWrappedCancellationException(h); + } + } + + public void testRunAfterEither_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.runAfterEither(f, g, r); + + assertTrue(g.cancel(mayInterruptIfRunning)); + checkCompletedWithWrappedCancellationException(h); + f.complete(v1); + + checkCancelled(g); + assertEquals(0, r.invocationCount); + checkCompletedNormally(f, v1); + checkCompletedWithWrappedCancellationException(h); + } + } + + public void testRunAfterEither_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.runAfterEither(f, g, r); + + // unspecified behavior + Integer v; + try { + assertEquals(h.join(), null); + assertEquals(1, r.invocationCount); + } catch (CompletionException ok) { + checkCompletedWithWrappedCancellationException(h); + assertEquals(0, r.invocationCount); + } + + checkCancelled(g); + checkCompletedNormally(f, v1); + } + } + + public void testRunAfterEither_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.runAfterEither(f, g, r); + + // unspecified behavior + Integer v; + try { + assertEquals(h.join(), null); + assertEquals(1, r.invocationCount); + } catch (CompletionException ok) { + checkCompletedWithWrappedCancellationException(h); + assertEquals(0, r.invocationCount); + } + + checkCancelled(f); + checkCompletedNormally(g, v1); + } } /** * thenCompose result completes normally after normal completion of source */ - public void testThenCompose() { - CompletableFuture f, g; - CompletableFutureInc r; + public void testThenCompose_normalCompletion1() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) { - f = new CompletableFuture<>(); - g = f.thenCompose(r = new CompletableFutureInc()); - f.complete(one); - checkCompletedNormally(g, two); - assertTrue(r.ran); + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFutureInc r = new CompletableFutureInc(); + final CompletableFuture g = f.thenCompose(r); + f.complete(v1); + checkCompletedNormally(g, inc(v1)); + checkCompletedNormally(f, v1); + assertEquals(1, r.invocationCount); + } + } - f = new CompletableFuture<>(); - f.complete(one); - g = f.thenCompose(r = new CompletableFutureInc()); - checkCompletedNormally(g, two); - assertTrue(r.ran); + public void testThenCompose_normalCompletion2() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) { + + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFutureInc r = new CompletableFutureInc(); + f.complete(v1); + final CompletableFuture g = f.thenCompose(r); + checkCompletedNormally(g, inc(v1)); + checkCompletedNormally(f, v1); + assertEquals(1, r.invocationCount); + } } /** * thenCompose result completes exceptionally after exceptional * completion of source */ - public void testThenCompose2() { - CompletableFuture f, g; - CompletableFutureInc r; + public void testThenCompose_exceptionalCompletion1() { + for (ExecutionMode m : ExecutionMode.values()) { - f = new CompletableFuture<>(); - g = f.thenCompose(r = new CompletableFutureInc()); - f.completeExceptionally(new CFException()); - checkCompletedWithWrappedCFException(g); + final CFException ex = new CFException(); + final CompletableFutureInc r = new CompletableFutureInc(); + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = f.thenCompose(r); + f.completeExceptionally(ex); + checkCompletedWithWrappedCFException(g, ex); + checkCompletedWithWrappedCFException(f, ex); + } + } - f = new CompletableFuture<>(); - f.completeExceptionally(new CFException()); - g = f.thenCompose(r = new CompletableFutureInc()); - checkCompletedWithWrappedCFException(g); + public void testThenCompose_exceptionalCompletion2() { + for (ExecutionMode m : ExecutionMode.values()) { + + final CFException ex = new CFException(); + final CompletableFuture f = new CompletableFuture<>(); + f.completeExceptionally(ex); + final CompletableFutureInc r = new CompletableFutureInc(); + final CompletableFuture g = f.thenCompose(r); + checkCompletedWithWrappedCFException(g, ex); + checkCompletedWithWrappedCFException(f, ex); + } } /** * thenCompose result completes exceptionally if action does */ - public void testThenCompose3() { - CompletableFuture f, g; - FailingCompletableFutureFunction r; + public void testThenCompose_actionFailed1() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) { - f = new CompletableFuture<>(); - g = f.thenCompose(r = new FailingCompletableFutureFunction()); - f.complete(one); + final CompletableFuture f = new CompletableFuture<>(); + final FailingCompletableFutureFunction r + = new FailingCompletableFutureFunction(); + final CompletableFuture g = f.thenCompose(r); + f.complete(v1); checkCompletedWithWrappedCFException(g); + checkCompletedNormally(f, v1); + } + } - f = new CompletableFuture<>(); - f.complete(one); - g = f.thenCompose(r = new FailingCompletableFutureFunction()); + public void testThenCompose_actionFailed2() { + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) { + + final CompletableFuture f = new CompletableFuture<>(); + f.complete(v1); + final FailingCompletableFutureFunction r + = new FailingCompletableFutureFunction(); + final CompletableFuture g = f.thenCompose(r); checkCompletedWithWrappedCFException(g); + checkCompletedNormally(f, v1); + } } /** * thenCompose result completes exceptionally if source cancelled */ - public void testThenCompose4() { - CompletableFuture f, g; - CompletableFutureInc r; + public void testThenCompose_sourceCancelled1() { + for (ExecutionMode m : ExecutionMode.values()) + for (boolean mayInterruptIfRunning : new boolean[] { true, false }) { - f = new CompletableFuture<>(); - g = f.thenCompose(r = new CompletableFutureInc()); - assertTrue(f.cancel(true)); + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFutureInc r = new CompletableFutureInc(); + final CompletableFuture g = f.thenCompose(r); + assertTrue(f.cancel(mayInterruptIfRunning)); checkCompletedWithWrappedCancellationException(g); + checkCancelled(f); + } + } - f = new CompletableFuture<>(); - assertTrue(f.cancel(true)); - g = f.thenCompose(r = new CompletableFutureInc()); + public void testThenCompose_sourceCancelled2() { + for (ExecutionMode m : ExecutionMode.values()) + for (boolean mayInterruptIfRunning : new boolean[] { true, false }) { + + final CompletableFuture f = new CompletableFuture<>(); + assertTrue(f.cancel(mayInterruptIfRunning)); + final CompletableFutureInc r = new CompletableFutureInc(); + final CompletableFuture g = f.thenCompose(r); checkCompletedWithWrappedCancellationException(g); + checkCancelled(f); + } } // asyncs @@ -2274,298 +2982,6 @@ public class CompletableFutureTest exten checkCompletedWithWrappedCancellationException(g); } - /** - * applyToEitherAsync result completes normally after normal - * completion of sources - */ - public void testApplyToEitherAsync() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - CompletableFuture g = f.applyToEitherAsync(f2, inc); - f.complete(one); - checkCompletedNormally(g, two); - - f = new CompletableFuture<>(); - f.complete(one); - f2 = new CompletableFuture<>(); - g = f.applyToEitherAsync(f2, inc); - checkCompletedNormally(g, two); - } - - /** - * applyToEitherAsync result completes exceptionally after exceptional - * completion of source - */ - public void testApplyToEitherAsync2() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - CompletableFuture g = f.applyToEitherAsync(f2, inc); - f.completeExceptionally(new CFException()); - checkCompletedWithWrappedCFException(g); - - f = new CompletableFuture<>(); - f2 = new CompletableFuture<>(); - f2.completeExceptionally(new CFException()); - g = f.applyToEitherAsync(f2, inc); - f.complete(one); - checkCompletedWithWrappedCFException(g); - } - - /** - * applyToEitherAsync result completes exceptionally if action does - */ - public void testApplyToEitherAsync3() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - FailingFunction r = new FailingFunction(); - CompletableFuture g = f.applyToEitherAsync(f2, r); - f.complete(one); - checkCompletedWithWrappedCFException(g); - } - - /** - * applyToEitherAsync result completes exceptionally if either source cancelled - */ - public void testApplyToEitherAsync4() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - CompletableFuture g = f.applyToEitherAsync(f2, inc); - assertTrue(f.cancel(true)); - checkCompletedWithWrappedCancellationException(g); - - f = new CompletableFuture<>(); - f2 = new CompletableFuture<>(); - assertTrue(f2.cancel(true)); - g = f.applyToEitherAsync(f2, inc); - checkCompletedWithWrappedCancellationException(g); - } - - /** - * acceptEitherAsync result completes normally after normal - * completion of sources - */ - public void testAcceptEitherAsync() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - IncAction r = new IncAction(); - CompletableFuture g = f.acceptEitherAsync(f2, r); - f.complete(one); - checkCompletedNormally(g, null); - assertEquals(r.value, (Integer) 2); - - r = new IncAction(); - f = new CompletableFuture<>(); - f.complete(one); - f2 = new CompletableFuture<>(); - g = f.acceptEitherAsync(f2, r); - checkCompletedNormally(g, null); - assertEquals(r.value, (Integer) 2); - } - - /** - * acceptEitherAsync result completes exceptionally after exceptional - * completion of source - */ - public void testAcceptEitherAsync2() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - IncAction r = new IncAction(); - CompletableFuture g = f.acceptEitherAsync(f2, r); - f.completeExceptionally(new CFException()); - checkCompletedWithWrappedCFException(g); - - r = new IncAction(); - f = new CompletableFuture<>(); - f2 = new CompletableFuture<>(); - f2.completeExceptionally(new CFException()); - g = f.acceptEitherAsync(f2, r); - f.complete(one); - checkCompletedWithWrappedCFException(g); - } - - /** - * acceptEitherAsync result completes exceptionally if action does - */ - public void testAcceptEitherAsync3() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - FailingConsumer r = new FailingConsumer(); - CompletableFuture g = f.acceptEitherAsync(f2, r); - f.complete(one); - checkCompletedWithWrappedCFException(g); - } - - /** - * acceptEitherAsync result completes exceptionally if either - * source cancelled - */ - public void testAcceptEitherAsync4() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - IncAction r = new IncAction(); - CompletableFuture g = f.acceptEitherAsync(f2, r); - assertTrue(f.cancel(true)); - checkCompletedWithWrappedCancellationException(g); - - r = new IncAction(); - f = new CompletableFuture<>(); - f2 = new CompletableFuture<>(); - assertTrue(f2.cancel(true)); - g = f.acceptEitherAsync(f2, r); - checkCompletedWithWrappedCancellationException(g); - } - - /** - * runAfterEitherAsync result completes normally after normal - * completion of sources - */ - public void testRunAfterEitherAsync() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - Noop r = new Noop(); - CompletableFuture g = f.runAfterEitherAsync(f2, r); - f.complete(one); - checkCompletedNormally(g, null); - assertTrue(r.ran); - - r = new Noop(); - f = new CompletableFuture<>(); - f.complete(one); - f2 = new CompletableFuture<>(); - g = f.runAfterEitherAsync(f2, r); - checkCompletedNormally(g, null); - assertTrue(r.ran); - } - - /** - * runAfterEitherAsync result completes exceptionally after exceptional - * completion of source - */ - public void testRunAfterEitherAsync2() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - Noop r = new Noop(); - CompletableFuture g = f.runAfterEitherAsync(f2, r); - f.completeExceptionally(new CFException()); - checkCompletedWithWrappedCFException(g); - - r = new Noop(); - f = new CompletableFuture<>(); - f2 = new CompletableFuture<>(); - f2.completeExceptionally(new CFException()); - g = f.runAfterEitherAsync(f2, r); - f.complete(one); - checkCompletedWithWrappedCFException(g); - } - - /** - * runAfterEitherAsync result completes exceptionally if action does - */ - public void testRunAfterEitherAsync3() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - FailingNoop r = new FailingNoop(); - CompletableFuture g = f.runAfterEitherAsync(f2, r); - f.complete(one); - checkCompletedWithWrappedCFException(g); - } - - /** - * runAfterEitherAsync result completes exceptionally if either - * source cancelled - */ - public void testRunAfterEitherAsync4() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - Noop r = new Noop(); - CompletableFuture g = f.runAfterEitherAsync(f2, r); - assertTrue(f.cancel(true)); - checkCompletedWithWrappedCancellationException(g); - - r = new Noop(); - f = new CompletableFuture<>(); - f2 = new CompletableFuture<>(); - assertTrue(f2.cancel(true)); - g = f.runAfterEitherAsync(f2, r); - checkCompletedWithWrappedCancellationException(g); - } - - /** - * thenComposeAsync result completes normally after normal - * completion of source - */ - public void testThenComposeAsync() { - CompletableFuture f, g; - CompletableFutureInc r; - - f = new CompletableFuture<>(); - g = f.thenComposeAsync(r = new CompletableFutureInc()); - f.complete(one); - checkCompletedNormally(g, two); - - f = new CompletableFuture<>(); - f.complete(one); - g = f.thenComposeAsync(r = new CompletableFutureInc()); - checkCompletedNormally(g, two); - } - - /** - * thenComposeAsync result completes exceptionally after - * exceptional completion of source - */ - public void testThenComposeAsync2() { - CompletableFuture f, g; - CompletableFutureInc r; - - f = new CompletableFuture<>(); - g = f.thenComposeAsync(r = new CompletableFutureInc()); - f.completeExceptionally(new CFException()); - checkCompletedWithWrappedCFException(g); - assertFalse(r.ran); - - f = new CompletableFuture<>(); - f.completeExceptionally(new CFException()); - g = f.thenComposeAsync(r = new CompletableFutureInc()); - checkCompletedWithWrappedCFException(g); - assertFalse(r.ran); - } - - /** - * thenComposeAsync result completes exceptionally if action does - */ - public void testThenComposeAsync3() { - CompletableFuture f, g; - FailingCompletableFutureFunction r; - - f = new CompletableFuture<>(); - g = f.thenComposeAsync(r = new FailingCompletableFutureFunction()); - f.complete(one); - checkCompletedWithWrappedCFException(g); - - f = new CompletableFuture<>(); - f.complete(one); - g = f.thenComposeAsync(r = new FailingCompletableFutureFunction()); - checkCompletedWithWrappedCFException(g); - } - - /** - * thenComposeAsync result completes exceptionally if source cancelled - */ - public void testThenComposeAsync4() { - CompletableFuture f, g; - CompletableFutureInc r; - - f = new CompletableFuture<>(); - g = f.thenComposeAsync(r = new CompletableFutureInc()); - assertTrue(f.cancel(true)); - checkCompletedWithWrappedCancellationException(g); - - f = new CompletableFuture<>(); - assertTrue(f.cancel(true)); - g = f.thenComposeAsync(r = new CompletableFutureInc()); - checkCompletedWithWrappedCancellationException(g); - } - // async with explicit executors /** @@ -2713,268 +3129,6 @@ public class CompletableFutureTest exten checkCompletedWithWrappedCancellationException(g); } - /** - * applyToEitherAsync result completes normally after normal - * completion of sources - */ - public void testApplyToEitherAsyncE() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - CompletableFuture g = f.applyToEitherAsync(f2, inc, new ThreadExecutor()); - f.complete(one); - checkCompletedNormally(g, two); - - f = new CompletableFuture<>(); - f.complete(one); - f2 = new CompletableFuture<>(); - g = f.applyToEitherAsync(f2, inc, new ThreadExecutor()); - checkCompletedNormally(g, two); - } - - /** - * applyToEitherAsync result completes exceptionally after exceptional - * completion of source - */ - public void testApplyToEitherAsync2E() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - CompletableFuture g = f.applyToEitherAsync(f2, inc, new ThreadExecutor()); - f.completeExceptionally(new CFException()); - checkCompletedWithWrappedCFException(g); - - f = new CompletableFuture<>(); - f2 = new CompletableFuture<>(); - f2.completeExceptionally(new CFException()); - g = f.applyToEitherAsync(f2, inc, new ThreadExecutor()); - f.complete(one); - checkCompletedWithWrappedCFException(g); - } - - /** - * applyToEitherAsync result completes exceptionally if action does - */ - public void testApplyToEitherAsync3E() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - FailingFunction r = new FailingFunction(); - CompletableFuture g = f.applyToEitherAsync(f2, r, new ThreadExecutor()); - f.complete(one); - checkCompletedWithWrappedCFException(g); - } - - /** - * applyToEitherAsync result completes exceptionally if either source cancelled - */ - public void testApplyToEitherAsync4E() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - CompletableFuture g = f.applyToEitherAsync(f2, inc, new ThreadExecutor()); - assertTrue(f.cancel(true)); - checkCompletedWithWrappedCancellationException(g); - - f = new CompletableFuture<>(); - f2 = new CompletableFuture<>(); - assertTrue(f2.cancel(true)); - g = f.applyToEitherAsync(f2, inc, new ThreadExecutor()); - checkCompletedWithWrappedCancellationException(g); - } - - /** - * acceptEitherAsync result completes normally after normal - * completion of sources - */ - public void testAcceptEitherAsyncE() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - IncAction r = new IncAction(); - CompletableFuture g = f.acceptEitherAsync(f2, r, new ThreadExecutor()); - f.complete(one); - checkCompletedNormally(g, null); - assertEquals(r.value, (Integer) 2); - - r = new IncAction(); - f = new CompletableFuture<>(); - f.complete(one); - f2 = new CompletableFuture<>(); - g = f.acceptEitherAsync(f2, r, new ThreadExecutor()); - checkCompletedNormally(g, null); - assertEquals(r.value, (Integer) 2); - } - - /** - * acceptEitherAsync result completes exceptionally after exceptional - * completion of source - */ - public void testAcceptEitherAsync2E() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - IncAction r = new IncAction(); - CompletableFuture g = f.acceptEitherAsync(f2, r, new ThreadExecutor()); - f.completeExceptionally(new CFException()); - checkCompletedWithWrappedCFException(g); - - r = new IncAction(); - f = new CompletableFuture<>(); - f2 = new CompletableFuture<>(); - f2.completeExceptionally(new CFException()); - g = f.acceptEitherAsync(f2, r, new ThreadExecutor()); - f.complete(one); - checkCompletedWithWrappedCFException(g); - } - - /** - * acceptEitherAsync result completes exceptionally if action does - */ - public void testAcceptEitherAsync3E() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - FailingConsumer r = new FailingConsumer(); - CompletableFuture g = f.acceptEitherAsync(f2, r, new ThreadExecutor()); - f.complete(one); - checkCompletedWithWrappedCFException(g); - } - - /** - * acceptEitherAsync result completes exceptionally if either - * source cancelled - */ - public void testAcceptEitherAsync4E() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - IncAction r = new IncAction(); - CompletableFuture g = f.acceptEitherAsync(f2, r, new ThreadExecutor()); - assertTrue(f.cancel(true)); - checkCompletedWithWrappedCancellationException(g); - - r = new IncAction(); - f = new CompletableFuture<>(); - f2 = new CompletableFuture<>(); - assertTrue(f2.cancel(true)); - g = f.acceptEitherAsync(f2, r, new ThreadExecutor()); - checkCompletedWithWrappedCancellationException(g); - } - - /** - * runAfterEitherAsync result completes normally after normal - * completion of sources - */ - public void testRunAfterEitherAsyncE() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - Noop r = new Noop(); - CompletableFuture g = f.runAfterEitherAsync(f2, r, new ThreadExecutor()); - f.complete(one); - checkCompletedNormally(g, null); - assertTrue(r.ran); - - r = new Noop(); - f = new CompletableFuture<>(); - f.complete(one); - f2 = new CompletableFuture<>(); - g = f.runAfterEitherAsync(f2, r, new ThreadExecutor()); - checkCompletedNormally(g, null); - assertTrue(r.ran); - } - - /** - * runAfterEitherAsync result completes exceptionally after exceptional - * completion of source - */ - public void testRunAfterEitherAsync2E() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - Noop r = new Noop(); - CompletableFuture g = f.runAfterEitherAsync(f2, r, new ThreadExecutor()); - f.completeExceptionally(new CFException()); - checkCompletedWithWrappedCFException(g); - - r = new Noop(); - f = new CompletableFuture<>(); - f2 = new CompletableFuture<>(); - f2.completeExceptionally(new CFException()); - g = f.runAfterEitherAsync(f2, r, new ThreadExecutor()); - f.complete(one); - checkCompletedWithWrappedCFException(g); - } - - /** - * runAfterEitherAsync result completes exceptionally if action does - */ - public void testRunAfterEitherAsync3E() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - FailingNoop r = new FailingNoop(); - CompletableFuture g = f.runAfterEitherAsync(f2, r, new ThreadExecutor()); - f.complete(one); - checkCompletedWithWrappedCFException(g); - } - - /** - * runAfterEitherAsync result completes exceptionally if either - * source cancelled - */ - public void testRunAfterEitherAsync4E() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture f2 = new CompletableFuture<>(); - Noop r = new Noop(); - CompletableFuture g = f.runAfterEitherAsync(f2, r, new ThreadExecutor()); - assertTrue(f.cancel(true)); - checkCompletedWithWrappedCancellationException(g); - - r = new Noop(); - f = new CompletableFuture<>(); - f2 = new CompletableFuture<>(); - assertTrue(f2.cancel(true)); - g = f.runAfterEitherAsync(f2, r, new ThreadExecutor()); - checkCompletedWithWrappedCancellationException(g); - } - - /** - * thenComposeAsync result completes normally after normal - * completion of source - */ - public void testThenComposeAsyncE() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFutureInc r = new CompletableFutureInc(); - CompletableFuture g = f.thenComposeAsync(r, new ThreadExecutor()); - f.complete(one); - checkCompletedNormally(g, two); - } - - /** - * thenComposeAsync result completes exceptionally after - * exceptional completion of source - */ - public void testThenComposeAsync2E() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFutureInc r = new CompletableFutureInc(); - CompletableFuture g = f.thenComposeAsync(r, new ThreadExecutor()); - f.completeExceptionally(new CFException()); - checkCompletedWithWrappedCFException(g); - } - - /** - * thenComposeAsync result completes exceptionally if action does - */ - public void testThenComposeAsync3E() { - CompletableFuture f = new CompletableFuture<>(); - FailingCompletableFutureFunction r = new FailingCompletableFutureFunction(); - CompletableFuture g = f.thenComposeAsync(r, new ThreadExecutor()); - f.complete(one); - checkCompletedWithWrappedCFException(g); - } - - /** - * thenComposeAsync result completes exceptionally if source cancelled - */ - public void testThenComposeAsync4E() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFutureInc r = new CompletableFutureInc(); - CompletableFuture g = f.thenComposeAsync(r, new ThreadExecutor()); - assertTrue(f.cancel(true)); - checkCompletedWithWrappedCancellationException(g); - } - // other static methods /** @@ -3173,137 +3327,107 @@ public class CompletableFutureTest exten * whenComplete action executes on normal completion, propagating * source result. */ - public void testWhenComplete1() { + public void testWhenComplete_normalCompletion1() { + for (boolean createIncomplete : new boolean[] { true, false }) + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) { + final AtomicInteger a = new AtomicInteger(); - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture g = - f.whenComplete((Integer x, Throwable t) -> a.getAndIncrement()); - f.complete(three); - checkCompletedNormally(f, three); - checkCompletedNormally(g, three); + final CompletableFuture f = new CompletableFuture<>(); + if (!createIncomplete) f.complete(v1); + final CompletableFuture g = + m.whenComplete(f, + (Integer x, Throwable t) -> { + threadAssertSame(x, v1); + threadAssertNull(t); + a.getAndIncrement(); + }); + if (createIncomplete) f.complete(v1); + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v1); assertEquals(a.get(), 1); + } } /** * whenComplete action executes on exceptional completion, propagating * source result. */ - public void testWhenComplete2() { + public void testWhenComplete_exceptionalCompletion() { + for (boolean createIncomplete : new boolean[] { true, false }) + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) { + final AtomicInteger a = new AtomicInteger(); - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture g = - f.whenComplete((Integer x, Throwable t) -> a.getAndIncrement()); - f.completeExceptionally(new CFException()); - assertTrue(f.isCompletedExceptionally()); - assertTrue(g.isCompletedExceptionally()); + final CFException ex = new CFException(); + final CompletableFuture f = new CompletableFuture<>(); + if (!createIncomplete) f.completeExceptionally(ex); + final CompletableFuture g = m.whenComplete + (f, + (Integer x, Throwable t) -> { + threadAssertNull(x); + threadAssertSame(t, ex); + a.getAndIncrement(); + }); + if (createIncomplete) f.completeExceptionally(ex); + checkCompletedWithWrappedCFException(f, ex); + checkCompletedWithWrappedCFException(g, ex); assertEquals(a.get(), 1); + } } /** * If a whenComplete action throws an exception when triggered by * a normal completion, it completes exceptionally */ - public void testWhenComplete3() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture g = - f.whenComplete((Integer x, Throwable t) -> - { throw new CFException(); } ); - f.complete(three); - checkCompletedNormally(f, three); - assertTrue(g.isCompletedExceptionally()); - checkCompletedWithWrappedCFException(g); - } - - /** - * whenCompleteAsync action executes on normal completion, propagating - * source result. - */ - public void testWhenCompleteAsync1() { - final AtomicInteger a = new AtomicInteger(); - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture g = - f.whenCompleteAsync((Integer x, Throwable t) -> a.getAndIncrement()); - f.complete(three); - checkCompletedNormally(f, three); - checkCompletedNormally(g, three); - assertEquals(a.get(), 1); - } + public void testWhenComplete_actionFailed() { + for (boolean createIncomplete : new boolean[] { true, false }) + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) { - /** - * whenCompleteAsync action executes on exceptional completion, propagating - * source result. - */ - public void testWhenCompleteAsync2() { - final AtomicInteger a = new AtomicInteger(); - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture g = - f.whenCompleteAsync((Integer x, Throwable t) -> a.getAndIncrement()); - f.completeExceptionally(new CFException()); - checkCompletedWithWrappedCFException(f); - checkCompletedWithWrappedCFException(g); + final CFException ex = new CFException(); + final CompletableFuture f = new CompletableFuture<>(); + if (!createIncomplete) f.complete(v1); + final CompletableFuture g = m.whenComplete + (f, + (Integer x, Throwable t) -> { + threadAssertSame(x, v1); + threadAssertNull(t); + throw ex; + }); + if (createIncomplete) f.complete(v1); + checkCompletedNormally(f, v1); + checkCompletedWithWrappedCFException(g, ex); + } } /** - * If a whenCompleteAsync action throws an exception when - * triggered by a normal completion, it completes exceptionally + * If a whenComplete action throws an exception when triggered by + * a source completion that also throws an exception, the source + * exception takes precedence. */ - public void testWhenCompleteAsync3() { - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture g = - f.whenCompleteAsync((Integer x, Throwable t) -> - { throw new CFException(); } ); - f.complete(three); - checkCompletedNormally(f, three); - checkCompletedWithWrappedCFException(g); - } + public void testWhenComplete_actionFailedSourceFailed() { + for (boolean createIncomplete : new boolean[] { true, false }) + for (ExecutionMode m : ExecutionMode.values()) + for (Integer v1 : new Integer[] { 1, null }) { - /** - * whenCompleteAsync action executes on normal completion, propagating - * source result. - */ - public void testWhenCompleteAsync1e() { - final AtomicInteger a = new AtomicInteger(); - ThreadExecutor exec = new ThreadExecutor(); - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture g = - f.whenCompleteAsync((Integer x, Throwable t) -> a.getAndIncrement(), - exec); - f.complete(three); - checkCompletedNormally(f, three); - checkCompletedNormally(g, three); - assertEquals(a.get(), 1); - } + final CFException ex1 = new CFException(); + final CFException ex2 = new CFException(); + final CompletableFuture f = new CompletableFuture<>(); - /** - * whenCompleteAsync action executes on exceptional completion, propagating - * source result. - */ - public void testWhenCompleteAsync2e() { - final AtomicInteger a = new AtomicInteger(); - ThreadExecutor exec = new ThreadExecutor(); - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture g = - f.whenCompleteAsync((Integer x, Throwable t) -> a.getAndIncrement(), - exec); - f.completeExceptionally(new CFException()); - checkCompletedWithWrappedCFException(f); - checkCompletedWithWrappedCFException(g); - } + if (!createIncomplete) f.completeExceptionally(ex1); + final CompletableFuture g = m.whenComplete + (f, + (Integer x, Throwable t) -> { + threadAssertSame(t, ex1); + threadAssertNull(x); + throw ex2; + }); + if (createIncomplete) f.completeExceptionally(ex1); - /** - * If a whenCompleteAsync action throws an exception when triggered - * by a normal completion, it completes exceptionally - */ - public void testWhenCompleteAsync3e() { - ThreadExecutor exec = new ThreadExecutor(); - CompletableFuture f = new CompletableFuture<>(); - CompletableFuture g = - f.whenCompleteAsync((Integer x, Throwable t) -> - { throw new CFException(); }, - exec); - f.complete(three); - checkCompletedNormally(f, three); - checkCompletedWithWrappedCFException(g); + checkCompletedWithWrappedCFException(f, ex1); + checkCompletedWithWrappedCFException(g, ex1); + } } /** @@ -3316,35 +3440,35 @@ public class CompletableFutureTest exten f = new CompletableFuture<>(); g = f.handleAsync(r = new IntegerHandler()); - assertFalse(r.ran); + assertEquals(0, r.invocationCount); f.completeExceptionally(new CFException()); checkCompletedWithWrappedCFException(f); checkCompletedNormally(g, three); - assertTrue(r.ran); + assertEquals(1, r.invocationCount); f = new CompletableFuture<>(); g = f.handleAsync(r = new IntegerHandler()); - assertFalse(r.ran); + assertEquals(0, r.invocationCount); f.completeExceptionally(new CFException()); checkCompletedWithWrappedCFException(f); checkCompletedNormally(g, three); - assertTrue(r.ran); + assertEquals(1, r.invocationCount); f = new CompletableFuture<>(); g = f.handleAsync(r = new IntegerHandler()); - assertFalse(r.ran); + assertEquals(0, r.invocationCount); f.complete(one); checkCompletedNormally(f, one); checkCompletedNormally(g, two); - assertTrue(r.ran); + assertEquals(1, r.invocationCount); f = new CompletableFuture<>(); g = f.handleAsync(r = new IntegerHandler()); - assertFalse(r.ran); + assertEquals(0, r.invocationCount); f.complete(one); checkCompletedNormally(f, one); checkCompletedNormally(g, two); - assertTrue(r.ran); + assertEquals(1, r.invocationCount); } /** @@ -3359,35 +3483,35 @@ public class CompletableFutureTest exten f = new CompletableFuture<>(); g = f.handleAsync(r = new IntegerHandler(), exec); - assertFalse(r.ran); + assertEquals(0, r.invocationCount); f.completeExceptionally(new CFException()); checkCompletedWithWrappedCFException(f); checkCompletedNormally(g, three); - assertTrue(r.ran); + assertEquals(1, r.invocationCount); f = new CompletableFuture<>(); g = f.handleAsync(r = new IntegerHandler(), exec); - assertFalse(r.ran); + assertEquals(0, r.invocationCount); f.completeExceptionally(new CFException()); checkCompletedWithWrappedCFException(f); checkCompletedNormally(g, three); - assertTrue(r.ran); + assertEquals(1, r.invocationCount); f = new CompletableFuture<>(); g = f.handleAsync(r = new IntegerHandler(), exec); - assertFalse(r.ran); + assertEquals(0, r.invocationCount); f.complete(one); checkCompletedNormally(f, one); checkCompletedNormally(g, two); - assertTrue(r.ran); + assertEquals(1, r.invocationCount); f = new CompletableFuture<>(); g = f.handleAsync(r = new IntegerHandler(), exec); - assertFalse(r.ran); + assertEquals(0, r.invocationCount); f.complete(one); checkCompletedNormally(f, one); checkCompletedNormally(g, two); - assertTrue(r.ran); + assertEquals(1, r.invocationCount); } }