--- jsr166/src/test/tck/CompletableFutureTest.java 2013/03/22 16:10:19 1.6 +++ jsr166/src/test/tck/CompletableFutureTest.java 2013/04/04 04:16:02 1.17 @@ -53,7 +53,7 @@ public class CompletableFutureTest exten catch (Throwable fail) { threadUnexpectedException(fail); } } - void checkCompletedNormally(CompletableFuture f, Object value) { + void checkCompletedNormally(CompletableFuture f, T value) { try { assertEquals(value, f.join()); } catch (Throwable fail) { threadUnexpectedException(fail); } @@ -75,95 +75,84 @@ public class CompletableFutureTest exten try { f.join(); shouldThrow(); - } catch (Throwable ex) { - assertTrue(ex instanceof CompletionException && - ((CompletionException)ex).getCause() instanceof CFException); + } catch (CompletionException success) { + assertTrue(success.getCause() instanceof CFException); } try { f.getNow(null); shouldThrow(); - } catch (Throwable ex) { - assertTrue(ex instanceof CompletionException && - ((CompletionException)ex).getCause() instanceof CFException); + } catch (CompletionException success) { + assertTrue(success.getCause() instanceof CFException); } try { f.get(); shouldThrow(); - } catch (Throwable ex) { - assertTrue(ex instanceof ExecutionException && - ((ExecutionException)ex).getCause() instanceof CFException); - } + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof CFException); + } catch (Throwable fail) { threadUnexpectedException(fail); } try { f.get(0L, SECONDS); shouldThrow(); - } catch (Throwable ex) { - assertTrue(ex instanceof ExecutionException && - ((ExecutionException)ex).getCause() instanceof CFException); - } + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof CFException); + } catch (Throwable fail) { threadUnexpectedException(fail); } assertTrue(f.isDone()); assertFalse(f.isCancelled()); + assertTrue(f.toString().contains("[Completed exceptionally]")); } void checkCancelled(CompletableFuture f) { try { f.join(); shouldThrow(); - } catch (Throwable ex) { - assertTrue(ex instanceof CancellationException); - } + } catch (CancellationException success) {} try { f.getNow(null); shouldThrow(); - } catch (Throwable ex) { - assertTrue(ex instanceof CancellationException); - } + } catch (CancellationException success) {} try { f.get(); shouldThrow(); - } catch (Throwable ex) { - assertTrue(ex instanceof CancellationException); - } + } catch (CancellationException success) { + } catch (Throwable fail) { threadUnexpectedException(fail); } try { f.get(0L, SECONDS); shouldThrow(); - } catch (Throwable ex) { - assertTrue(ex instanceof CancellationException); - } + } catch (CancellationException success) { + } catch (Throwable fail) { threadUnexpectedException(fail); } assertTrue(f.isDone()); assertTrue(f.isCancelled()); + assertTrue(f.toString().contains("[Completed exceptionally]")); } void checkCompletedWithWrappedCancellationException(CompletableFuture f) { try { f.join(); shouldThrow(); - } catch (Throwable ex) { - assertTrue(ex instanceof CompletionException && - ((CompletionException)ex).getCause() instanceof CancellationException); + } catch (CompletionException success) { + assertTrue(success.getCause() instanceof CancellationException); } try { f.getNow(null); shouldThrow(); - } catch (Throwable ex) { - assertTrue(ex instanceof CompletionException && - ((CompletionException)ex).getCause() instanceof CancellationException); + } catch (CompletionException success) { + assertTrue(success.getCause() instanceof CancellationException); } try { f.get(); shouldThrow(); - } catch (Throwable ex) { - assertTrue(ex instanceof ExecutionException && - ((ExecutionException)ex).getCause() instanceof CancellationException); - } + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof CancellationException); + } catch (Throwable fail) { threadUnexpectedException(fail); } try { f.get(0L, SECONDS); shouldThrow(); - } catch (Throwable ex) { - assertTrue(ex instanceof ExecutionException && - ((ExecutionException)ex).getCause() instanceof CancellationException); - } + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof CancellationException); + } catch (Throwable fail) { threadUnexpectedException(fail); } assertTrue(f.isDone()); assertFalse(f.isCancelled()); + assertTrue(f.toString().contains("[Completed exceptionally]")); } /** @@ -285,6 +274,14 @@ public class CompletableFutureTest exten assertTrue(f.toString().contains("[Completed exceptionally]")); } + /** + * completedFuture returns a completed CompletableFuture with given value + */ + public void testCompletedFuture() { + CompletableFuture f = CompletableFuture.completedFuture("test"); + checkCompletedNormally(f, "test"); + } + static final Supplier supplyOne = () -> Integer.valueOf(1); static final Function inc = @@ -348,7 +345,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(); } } @@ -358,7 +358,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; } } @@ -387,16 +389,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); } @@ -408,6 +427,7 @@ public class CompletableFutureTest exten CompletableFuture f = CompletableFuture.runAsync(r); assertNull(f.join()); assertTrue(r.ran); + checkCompletedNormally(f, null); } /** @@ -415,9 +435,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()); } /** @@ -434,16 +457,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); } /** @@ -456,7 +483,7 @@ public class CompletableFutureTest exten assertTrue(r.ran); } - // seq conmpletion methods + // seq completion methods /** * thenRun result completes normally after normal completion of source @@ -1671,7 +1698,8 @@ public class CompletableFutureTest exten } /** - * thenCompse result completes normally after normal completion of source + * thenComposeAsync result completes normally after normal + * completion of source */ public void testThenComposeAsync() { CompletableFuture f = new CompletableFuture(); @@ -1682,8 +1710,8 @@ public class CompletableFutureTest exten } /** - * thenComposeAsync result completes exceptionally after exceptional - * completion of source + * thenComposeAsync result completes exceptionally after + * exceptional completion of source */ public void testThenComposeAsync2() { CompletableFuture f = new CompletableFuture(); @@ -1716,7 +1744,7 @@ public class CompletableFutureTest exten } - // aaync with explicit executors + // async with explicit executors /** * thenRunAsync result completes normally after normal completion of source @@ -2293,7 +2321,8 @@ public class CompletableFutureTest exten } /** - * thenCompse result completes normally after normal completion of source + * thenComposeAsync result completes normally after normal + * completion of source */ public void testThenComposeAsyncE() { CompletableFuture f = new CompletableFuture(); @@ -2304,8 +2333,8 @@ public class CompletableFutureTest exten } /** - * thenComposeAsync result completes exceptionally after exceptional - * completion of source + * thenComposeAsync result completes exceptionally after + * exceptional completion of source */ public void testThenComposeAsync2E() { CompletableFuture f = new CompletableFuture(); @@ -2356,13 +2385,12 @@ public class CompletableFutureTest exten CompletableFuture[] fs = new CompletableFuture[k]; for (int i = 0; i < k; ++i) fs[i] = new CompletableFuture(); - CompletableFuture f = CompletableFuture.allOf(fs); + CompletableFuture f = CompletableFuture.allOf(fs); for (int i = 0; i < k; ++i) { checkIncomplete(f); fs[i].complete(one); } - assertTrue(f.isDone()); - assertFalse(f.isCancelled()); + checkCompletedNormally(f, null); } } @@ -2375,18 +2403,18 @@ public class CompletableFutureTest exten } /** - * allOf returns a future completed when any components complete + * anyOf returns a future completed when any components complete */ public void testAnyOf() throws Exception { for (int k = 1; k < 20; ++k) { CompletableFuture[] fs = new CompletableFuture[k]; for (int i = 0; i < k; ++i) fs[i] = new CompletableFuture(); - CompletableFuture f = CompletableFuture.anyOf(fs); + CompletableFuture f = CompletableFuture.anyOf(fs); checkIncomplete(f); for (int i = 0; i < k; ++i) { fs[i].complete(one); - assertTrue(f.isDone()); + checkCompletedNormally(f, one); } } } @@ -2397,39 +2425,106 @@ public class CompletableFutureTest exten public void testNPE() { CompletableFuture f = new CompletableFuture(); CompletableFuture g = new CompletableFuture(); - CompletableFuture h; - try { h = f.thenApply(null); } catch (NullPointerException ok) {} - try { h = f.thenAccept(null); } catch (NullPointerException ok) {} - try { h = f.thenRun(null); } catch (NullPointerException ok) {} - try { h = f.thenCombine(g, null); } catch (NullPointerException ok) {} - try { h = f.thenCombine(null, null); } catch (NullPointerException ok) {} - try { h = f.applyToEither(g, null); } catch (NullPointerException ok) {} - try { h = f.applyToEither(null, null); } catch (NullPointerException ok) {} - try { h = f.thenAcceptBoth(g, null); } catch (NullPointerException ok) {} - try { h = f.thenAcceptBoth(null, null); } catch (NullPointerException ok) {} - try { h = f.runAfterEither(g, null); } catch (NullPointerException ok) {} - try { h = f.runAfterEither(null, null); } catch (NullPointerException ok) {} - try { h = f.runAfterBoth(g, null); } catch (NullPointerException ok) {} - try { h = f.runAfterBoth(null, null); } catch (NullPointerException ok) {} - try { h = f.exceptionally(null); } catch (NullPointerException ok) {} - try { h = f.handle(null); } catch (NullPointerException ok) {} - try { h = f.thenCompose(null); } catch (NullPointerException ok) {} - - try { h = f.thenApplyAsync(null); } catch (NullPointerException ok) {} - try { h = f.thenAcceptAsync(null); } catch (NullPointerException ok) {} - try { h = f.thenRunAsync(null); } catch (NullPointerException ok) {} - try { h = f.thenCombineAsync(g, null); } catch (NullPointerException ok) {} - try { h = f.thenCombineAsync(null, null); } catch (NullPointerException ok) {} - try { h = f.applyToEitherAsync(g, null); } catch (NullPointerException ok) {} - try { h = f.applyToEitherAsync(null, null); } catch (NullPointerException ok) {} - try { h = f.thenAcceptBothAsync(g, null); } catch (NullPointerException ok) {} - try { h = f.thenAcceptBothAsync(null, null); } catch (NullPointerException ok) {} - try { h = f.runAfterEitherAsync(g, null); } catch (NullPointerException ok) {} - try { h = f.runAfterEitherAsync(null, null); } catch (NullPointerException ok) {} - try { h = f.runAfterBothAsync(g, null); } catch (NullPointerException ok) {} - try { h = f.runAfterBothAsync(null, null); } catch (NullPointerException ok) {} + CompletableFuture nullFuture = (CompletableFuture)null; + CompletableFuture h; + ThreadExecutor exec = new ThreadExecutor(); + + Runnable[] throwingActions = { + () -> { CompletableFuture.supplyAsync(null); }, + () -> { CompletableFuture.supplyAsync(null, exec); }, + () -> { CompletableFuture.supplyAsync(supplyOne, null); }, + + () -> { CompletableFuture.runAsync(null); }, + () -> { CompletableFuture.runAsync(null, exec); }, + () -> { CompletableFuture.runAsync(() -> {}, null); }, + + () -> { f.completeExceptionally(null); }, + + () -> { f.thenApply(null); }, + () -> { f.thenApplyAsync(null); }, + () -> { f.thenApplyAsync((x) -> x, null); }, + () -> { f.thenApplyAsync(null, exec); }, + + () -> { f.thenAccept(null); }, + () -> { f.thenAcceptAsync(null); }, + () -> { f.thenAcceptAsync((x) -> { ; }, null); }, + () -> { f.thenAcceptAsync(null, exec); }, + + () -> { f.thenRun(null); }, + () -> { f.thenRunAsync(null); }, + () -> { f.thenRunAsync(() -> { ; }, null); }, + () -> { f.thenRunAsync(null, exec); }, + + () -> { f.thenCombine(g, null); }, + () -> { f.thenCombineAsync(g, null); }, + () -> { f.thenCombineAsync(g, null, exec); }, + () -> { f.thenCombine(nullFuture, (x, y) -> x); }, + () -> { f.thenCombineAsync(nullFuture, (x, y) -> x); }, + () -> { f.thenCombineAsync(nullFuture, (x, y) -> x, exec); }, + () -> { f.thenCombineAsync(g, (x, y) -> x, null); }, + + () -> { f.thenAcceptBoth(g, null); }, + () -> { f.thenAcceptBothAsync(g, null); }, + () -> { f.thenAcceptBothAsync(g, null, exec); }, + () -> { f.thenAcceptBoth(nullFuture, (x, y) -> {}); }, + () -> { f.thenAcceptBothAsync(nullFuture, (x, y) -> {}); }, + () -> { f.thenAcceptBothAsync(nullFuture, (x, y) -> {}, exec); }, + () -> { f.thenAcceptBothAsync(g, (x, y) -> {}, null); }, + + () -> { f.runAfterBoth(g, null); }, + () -> { f.runAfterBothAsync(g, null); }, + () -> { f.runAfterBothAsync(g, null, exec); }, + () -> { f.runAfterBoth(nullFuture, () -> {}); }, + () -> { f.runAfterBothAsync(nullFuture, () -> {}); }, + () -> { f.runAfterBothAsync(nullFuture, () -> {}, exec); }, + () -> { f.runAfterBothAsync(g, () -> {}, null); }, + + () -> { f.applyToEither(g, null); }, + () -> { f.applyToEitherAsync(g, null); }, + () -> { f.applyToEitherAsync(g, null, exec); }, + () -> { f.applyToEither(nullFuture, (x) -> x); }, + () -> { f.applyToEitherAsync(nullFuture, (x) -> x); }, + () -> { f.applyToEitherAsync(nullFuture, (x) -> x, exec); }, + () -> { f.applyToEitherAsync(g, (x) -> x, null); }, + + () -> { f.acceptEither(g, null); }, + () -> { f.acceptEitherAsync(g, null); }, + () -> { f.acceptEitherAsync(g, null, exec); }, + () -> { f.acceptEither(nullFuture, (x) -> {}); }, + () -> { f.acceptEitherAsync(nullFuture, (x) -> {}); }, + () -> { f.acceptEitherAsync(nullFuture, (x) -> {}, exec); }, + () -> { f.acceptEitherAsync(g, (x) -> {}, null); }, + + () -> { f.runAfterEither(g, null); }, + () -> { f.runAfterEitherAsync(g, null); }, + () -> { f.runAfterEitherAsync(g, null, exec); }, + () -> { f.runAfterEither(nullFuture, () -> {}); }, + () -> { f.runAfterEitherAsync(nullFuture, () -> {}); }, + () -> { f.runAfterEitherAsync(nullFuture, () -> {}, exec); }, + () -> { f.runAfterEitherAsync(g, () -> {}, null); }, + + () -> { f.thenCompose(null); }, + () -> { f.thenComposeAsync(null); }, + () -> { f.thenComposeAsync(new CompletableFutureInc(), null); }, + () -> { f.thenComposeAsync(null, exec); }, + + () -> { f.exceptionally(null); }, + + () -> { f.handle(null); }, + + () -> { CompletableFuture.allOf((CompletableFuture)null); }, + () -> { CompletableFuture.allOf((CompletableFuture[])null); }, + () -> { CompletableFuture.allOf(f, null); }, + () -> { CompletableFuture.allOf(null, f); }, + + () -> { CompletableFuture.anyOf((CompletableFuture)null); }, + () -> { CompletableFuture.anyOf((CompletableFuture[])null); }, + () -> { CompletableFuture.anyOf(f, null); }, + () -> { CompletableFuture.anyOf(null, f); }, + }; + assertThrows(NullPointerException.class, throwingActions); + assertEquals(0, exec.count.get()); } - }