--- jsr166/src/test/tck/CompletableFutureTest.java 2013/04/01 20:06:25 1.14 +++ jsr166/src/test/tck/CompletableFutureTest.java 2013/04/07 14:54:06 1.18 @@ -282,12 +282,14 @@ public class CompletableFutureTest exten checkCompletedNormally(f, "test"); } + // Choose non-commutative actions for better coverage + static final Supplier supplyOne = () -> Integer.valueOf(1); static final Function inc = (Integer x) -> Integer.valueOf(x.intValue() + 1); - static final BiFunction add = - (Integer x, Integer y) -> Integer.valueOf(x.intValue() + y.intValue()); + static final BiFunction subtract = + (Integer x, Integer y) -> Integer.valueOf(x.intValue() - y.intValue()); static final class IncAction implements Consumer { int value; public void accept(Integer x) { value = x.intValue() + 1; } @@ -328,7 +330,8 @@ public class CompletableFutureTest exten public void run() { ran = true; throw new CFException(); } } - static final class CompletableFutureInc implements Function> { + static final class CompletableFutureInc + implements Function> { public CompletableFuture apply(Integer x) { CompletableFuture f = new CompletableFuture(); f.complete(Integer.valueOf(x.intValue() + 1)); @@ -336,7 +339,8 @@ public class CompletableFutureTest exten } } - static final class FailingCompletableFutureFunction implements Function> { + static final class FailingCompletableFutureFunction + implements Function> { boolean ran; public CompletableFuture apply(Integer x) { ran = true; throw new CFException(); @@ -345,7 +349,10 @@ public class CompletableFutureTest exten // Used for explicit executor tests static final class ThreadExecutor implements Executor { + AtomicInteger count = new AtomicInteger(0); + public void execute(Runnable r) { + count.getAndIncrement(); new Thread(r).start(); } } @@ -355,7 +362,9 @@ public class CompletableFutureTest exten } static final class IntegerHandler implements BiFunction { + boolean ran; public Integer apply(Integer x, Throwable t) { + ran = true; return (t == null) ? two : three; } } @@ -384,16 +393,33 @@ public class CompletableFutureTest exten * normal or exceptional completion of source */ public void testHandle() { - CompletableFuture f = new CompletableFuture(); - IntegerHandler r = new IntegerHandler(); - CompletableFuture g = f.handle(r); + CompletableFuture f, g; + IntegerHandler r; + + f = new CompletableFuture(); + f.completeExceptionally(new CFException()); + g = f.handle(r = new IntegerHandler()); + assertTrue(r.ran); + checkCompletedNormally(g, three); + + f = new CompletableFuture(); + g = f.handle(r = new IntegerHandler()); + assertFalse(r.ran); f.completeExceptionally(new CFException()); checkCompletedNormally(g, three); + assertTrue(r.ran); f = new CompletableFuture(); - r = new IntegerHandler(); - g = f.handle(r); f.complete(one); + g = f.handle(r = new IntegerHandler()); + assertTrue(r.ran); + checkCompletedNormally(g, two); + + f = new CompletableFuture(); + g = f.handle(r = new IntegerHandler()); + assertFalse(r.ran); + f.complete(one); + assertTrue(r.ran); checkCompletedNormally(g, two); } @@ -413,10 +439,12 @@ public class CompletableFutureTest exten */ public void testRunAsync2() { Noop r = new Noop(); - CompletableFuture f = CompletableFuture.runAsync(r, new ThreadExecutor()); + ThreadExecutor exec = new ThreadExecutor(); + CompletableFuture f = CompletableFuture.runAsync(r, exec); assertNull(f.join()); assertTrue(r.ran); checkCompletedNormally(f, null); + assertEquals(1, exec.count.get()); } /** @@ -433,16 +461,20 @@ public class CompletableFutureTest exten * supplyAsync completes with result of supplier */ public void testSupplyAsync() { - CompletableFuture f = CompletableFuture.supplyAsync(supplyOne); + CompletableFuture f; + f = CompletableFuture.supplyAsync(supplyOne); assertEquals(f.join(), one); + checkCompletedNormally(f, one); } /** * supplyAsync with executor completes with result of supplier */ public void testSupplyAsync2() { - CompletableFuture f = CompletableFuture.supplyAsync(supplyOne, new ThreadExecutor()); + CompletableFuture f; + f = CompletableFuture.supplyAsync(supplyOne, new ThreadExecutor()); assertEquals(f.join(), one); + checkCompletedNormally(f, one); } /** @@ -598,24 +630,34 @@ public class CompletableFutureTest exten /** - * thenCombine result completes normally after normal completion of sources + * thenCombine result completes normally after normal completion + * of sources */ public void testThenCombine() { - CompletableFuture f = new CompletableFuture(); - CompletableFuture f2 = new CompletableFuture(); - CompletableFuture g = f.thenCombine(f2, add); - f.complete(one); - checkIncomplete(g); - f2.complete(two); - checkCompletedNormally(g, three); + CompletableFuture f, g, h; f = new CompletableFuture(); - f.complete(one); - f2 = new CompletableFuture(); - g = f.thenCombine(f2, add); - checkIncomplete(g); - f2.complete(two); - checkCompletedNormally(g, three); + g = new CompletableFuture(); + h = f.thenCombine(g, subtract); + f.complete(3); + checkIncomplete(h); + g.complete(1); + checkCompletedNormally(h, 2); + + f = new CompletableFuture(); + g = new CompletableFuture(); + h = f.thenCombine(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.thenCombine(g, subtract); + checkCompletedNormally(h, 2); } /** @@ -623,19 +665,37 @@ public class CompletableFutureTest exten * completion of either source */ public void testThenCombine2() { - CompletableFuture f = new CompletableFuture(); - CompletableFuture f2 = new CompletableFuture(); - CompletableFuture g = f.thenCombine(f2, add); + CompletableFuture f, g, h; + + f = new CompletableFuture(); + g = new CompletableFuture(); + h = f.thenCombine(g, subtract); f.completeExceptionally(new CFException()); - f2.complete(two); - checkCompletedWithWrappedCFException(g); + checkIncomplete(h); + g.complete(1); + checkCompletedWithWrappedCFException(h); f = new CompletableFuture(); - f.complete(one); - f2 = new CompletableFuture(); - g = f.thenCombine(f2, add); - f2.completeExceptionally(new CFException()); - checkCompletedWithWrappedCFException(g); + g = new CompletableFuture(); + h = f.thenCombine(g, subtract); + 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.thenCombine(g, subtract); + checkCompletedWithWrappedCFException(h); + + f = new CompletableFuture(); + g = new CompletableFuture(); + f.completeExceptionally(new CFException()); + g.complete(3); + h = f.thenCombine(g, subtract); + checkCompletedWithWrappedCFException(h); } /** @@ -648,26 +708,40 @@ public class CompletableFutureTest exten CompletableFuture g = f.thenCombine(f2, r); f.complete(one); checkIncomplete(g); + assertFalse(r.ran); f2.complete(two); checkCompletedWithWrappedCFException(g); + assertTrue(r.ran); } /** * thenCombine result completes exceptionally if either source cancelled */ public void testThenCombine4() { - CompletableFuture f = new CompletableFuture(); - CompletableFuture f2 = new CompletableFuture(); - CompletableFuture g = f.thenCombine(f2, add); + CompletableFuture f, g, h; + + f = new CompletableFuture(); + g = new CompletableFuture(); + h = f.thenCombine(g, subtract); assertTrue(f.cancel(true)); - f2.complete(two); - checkCompletedWithWrappedCancellationException(g); + checkIncomplete(h); + g.complete(1); + checkCompletedWithWrappedCancellationException(h); + f = new CompletableFuture(); - f2 = new CompletableFuture(); - g = f.thenCombine(f2, add); - f.complete(one); - assertTrue(f2.cancel(true)); - checkCompletedWithWrappedCancellationException(g); + g = new CompletableFuture(); + h = f.thenCombine(g, subtract); + assertTrue(g.cancel(true)); + checkIncomplete(h); + f.complete(3); + checkCompletedWithWrappedCancellationException(h); + + f = new CompletableFuture(); + g = new CompletableFuture(); + assertTrue(f.cancel(true)); + assertTrue(g.cancel(true)); + h = f.thenCombine(g, subtract); + checkCompletedWithWrappedCancellationException(h); } /** @@ -1245,33 +1319,61 @@ public class CompletableFutureTest exten * completion of sources */ public void testThenCombineAsync() { - CompletableFuture f = new CompletableFuture(); - CompletableFuture f2 = new CompletableFuture(); - CompletableFuture g = f.thenCombineAsync(f2, add); - f.complete(one); - checkIncomplete(g); - f2.complete(two); - checkCompletedNormally(g, three); + 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 source + * completion of either source */ public void testThenCombineAsync2() { - CompletableFuture f = new CompletableFuture(); - CompletableFuture f2 = new CompletableFuture(); - CompletableFuture g = f.thenCombineAsync(f2, add); + CompletableFuture f, g, h; + + f = new CompletableFuture(); + g = new CompletableFuture(); + h = f.thenCombineAsync(g, subtract); f.completeExceptionally(new CFException()); - f2.complete(two); - checkCompletedWithWrappedCFException(g); + checkIncomplete(h); + g.complete(1); + checkCompletedWithWrappedCFException(h); f = new CompletableFuture(); - f2 = new CompletableFuture(); - g = f.thenCombineAsync(f2, add); - f.complete(one); - f2.completeExceptionally(new CFException()); - checkCompletedWithWrappedCFException(g); + 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); } /** @@ -1284,27 +1386,47 @@ public class CompletableFutureTest exten 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 = new CompletableFuture(); - CompletableFuture f2 = new CompletableFuture(); - CompletableFuture g = f.thenCombineAsync(f2, add); + CompletableFuture f, g, h; + + f = new CompletableFuture(); + g = new CompletableFuture(); + h = f.thenCombineAsync(g, subtract); assertTrue(f.cancel(true)); - f2.complete(two); - checkCompletedWithWrappedCancellationException(g); + checkIncomplete(h); + g.complete(1); + checkCompletedWithWrappedCancellationException(h); f = new CompletableFuture(); - f2 = new CompletableFuture(); - g = f.thenCombineAsync(f2, add); - f.complete(one); - assertTrue(f2.cancel(true)); - checkCompletedWithWrappedCancellationException(g); + 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); } /** @@ -1863,38 +1985,77 @@ public class CompletableFutureTest exten assertTrue(f.cancel(true)); checkCompletedWithWrappedCancellationException(g); } + /** * thenCombineAsync result completes normally after normal * completion of sources */ public void testThenCombineAsyncE() { - CompletableFuture f = new CompletableFuture(); - CompletableFuture f2 = new CompletableFuture(); - CompletableFuture g = f.thenCombineAsync(f2, add, new ThreadExecutor()); - f.complete(one); - checkIncomplete(g); - f2.complete(two); - checkCompletedNormally(g, three); + 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 source + * completion of either source */ public void testThenCombineAsync2E() { - CompletableFuture f = new CompletableFuture(); - CompletableFuture f2 = new CompletableFuture(); - CompletableFuture g = f.thenCombineAsync(f2, add, new ThreadExecutor()); + 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()); - f2.complete(two); - checkCompletedWithWrappedCFException(g); + checkIncomplete(h); + g.complete(1); + checkCompletedWithWrappedCFException(h); f = new CompletableFuture(); - f2 = new CompletableFuture(); - g = f.thenCombineAsync(f2, add, new ThreadExecutor()); - f.complete(one); - f2.completeExceptionally(new CFException()); - checkCompletedWithWrappedCFException(g); + 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()); } /** @@ -1907,27 +2068,51 @@ public class CompletableFutureTest exten 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 = new CompletableFuture(); - CompletableFuture f2 = new CompletableFuture(); - CompletableFuture g = f.thenCombineAsync(f2, add, new ThreadExecutor()); + CompletableFuture f, g, h; + ThreadExecutor e = new ThreadExecutor(); + + f = new CompletableFuture(); + g = new CompletableFuture(); + h = f.thenCombineAsync(g, subtract, e); assertTrue(f.cancel(true)); - f2.complete(two); - checkCompletedWithWrappedCancellationException(g); + checkIncomplete(h); + g.complete(1); + checkCompletedWithWrappedCancellationException(h); f = new CompletableFuture(); - f2 = new CompletableFuture(); - g = f.thenCombineAsync(f2, add, new ThreadExecutor()); - f.complete(one); - assertTrue(f2.cancel(true)); - checkCompletedWithWrappedCancellationException(g); + 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()); } /** @@ -2399,12 +2584,12 @@ public class CompletableFutureTest exten CompletableFuture g = new CompletableFuture(); CompletableFuture nullFuture = (CompletableFuture)null; CompletableFuture h; - Executor exec = new ThreadExecutor(); + ThreadExecutor exec = new ThreadExecutor(); Runnable[] throwingActions = { () -> { CompletableFuture.supplyAsync(null); }, () -> { CompletableFuture.supplyAsync(null, exec); }, - () -> { CompletableFuture.supplyAsync(() -> one, null); }, + () -> { CompletableFuture.supplyAsync(supplyOne, null); }, () -> { CompletableFuture.runAsync(null); }, () -> { CompletableFuture.runAsync(null, exec); }, @@ -2493,14 +2678,10 @@ public class CompletableFutureTest exten () -> { CompletableFuture.anyOf((CompletableFuture[])null); }, () -> { CompletableFuture.anyOf(f, null); }, () -> { CompletableFuture.anyOf(null, f); }, - - // TODO: Crashes javac with lambda-8-2013-03-31... - //() -> { CompletableFuture x = f.thenAccept(null); }, - //() -> { CompletableFuture x = f.thenRun(null); }, - //() -> { CompletableFuture x = f.thenApply(() -> { ; }); }, }; assertThrows(NullPointerException.class, throwingActions); + assertEquals(0, exec.count.get()); } }