--- jsr166/src/test/tck/CompletableFutureTest.java 2016/11/06 22:42:10 1.180 +++ jsr166/src/test/tck/CompletableFutureTest.java 2018/09/17 11:50:55 1.198 @@ -41,7 +41,6 @@ import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; -import junit.framework.AssertionFailedError; import junit.framework.Test; import junit.framework.TestSuite; @@ -59,44 +58,48 @@ public class CompletableFutureTest exten void checkIncomplete(CompletableFuture f) { assertFalse(f.isDone()); assertFalse(f.isCancelled()); - assertTrue(f.toString().contains("Not completed")); + assertTrue(f.toString().matches(".*\\[.*Not completed.*\\]")); + + Object result = null; try { - assertNull(f.getNow(null)); + result = f.getNow(null); } catch (Throwable fail) { threadUnexpectedException(fail); } + assertNull(result); + try { - f.get(0L, SECONDS); + f.get(randomExpiredTimeout(), randomTimeUnit()); shouldThrow(); } catch (TimeoutException success) {} catch (Throwable fail) { threadUnexpectedException(fail); } } - void checkCompletedNormally(CompletableFuture f, T value) { - checkTimedGet(f, value); + void checkCompletedNormally(CompletableFuture f, T expectedValue) { + checkTimedGet(f, expectedValue); + assertEquals(expectedValue, f.join()); + assertEquals(expectedValue, f.getNow(null)); + + T result = null; try { - assertEquals(value, f.join()); - } catch (Throwable fail) { threadUnexpectedException(fail); } - try { - assertEquals(value, f.getNow(null)); - } catch (Throwable fail) { threadUnexpectedException(fail); } - try { - assertEquals(value, f.get()); + result = f.get(); } catch (Throwable fail) { threadUnexpectedException(fail); } + assertEquals(expectedValue, result); + assertTrue(f.isDone()); assertFalse(f.isCancelled()); assertFalse(f.isCompletedExceptionally()); - assertTrue(f.toString().contains("[Completed normally]")); + assertTrue(f.toString().matches(".*\\[.*Completed normally.*\\]")); } /** * Returns the "raw" internal exceptional completion of f, * without any additional wrapping with CompletionException. */ - Throwable exceptionalCompletion(CompletableFuture f) { - // handle (and whenComplete) can distinguish between "direct" - // and "wrapped" exceptional completion - return f.handle((U u, Throwable t) -> t).join(); + Throwable exceptionalCompletion(CompletableFuture f) { + // handle (and whenComplete and exceptionally) can distinguish + // between "direct" and "wrapped" exceptional completion + return f.handle((u, t) -> t).join(); } void checkCompletedExceptionally(CompletableFuture f, @@ -142,7 +145,7 @@ public class CompletableFutureTest exten assertFalse(f.isCancelled()); assertTrue(f.isDone()); assertTrue(f.isCompletedExceptionally()); - assertTrue(f.toString().contains("[Completed exceptionally]")); + assertTrue(f.toString().matches(".*\\[.*Completed exceptionally.*\\]")); } void checkCompletedWithWrappedCFException(CompletableFuture f) { @@ -197,7 +200,7 @@ public class CompletableFutureTest exten assertTrue(f.isDone()); assertTrue(f.isCompletedExceptionally()); assertTrue(f.isCancelled()); - assertTrue(f.toString().contains("[Completed exceptionally]")); + assertTrue(f.toString().matches(".*\\[.*Completed exceptionally.*\\]")); } /** @@ -296,7 +299,7 @@ public class CompletableFutureTest exten } f = new CompletableFuture<>(); - f.completeExceptionally(ex = new CFException()); + f.completeExceptionally(new CFException()); f.obtrudeValue(v1); checkCompletedNormally(f, v1); f.obtrudeException(ex = new CFException()); @@ -333,23 +336,40 @@ public class CompletableFutureTest exten /** * toString indicates current completion state */ - public void testToString() { - CompletableFuture f; - - f = new CompletableFuture(); - assertTrue(f.toString().contains("[Not completed]")); + public void testToString_incomplete() { + CompletableFuture f = new CompletableFuture<>(); + assertTrue(f.toString().matches(".*\\[.*Not completed.*\\]")); + if (testImplementationDetails) + assertEquals(identityString(f) + "[Not completed]", + f.toString()); + } + public void testToString_normal() { + CompletableFuture f = new CompletableFuture<>(); assertTrue(f.complete("foo")); - assertTrue(f.toString().contains("[Completed normally]")); + assertTrue(f.toString().matches(".*\\[.*Completed normally.*\\]")); + if (testImplementationDetails) + assertEquals(identityString(f) + "[Completed normally]", + f.toString()); + } - f = new CompletableFuture(); + public void testToString_exception() { + CompletableFuture f = new CompletableFuture<>(); assertTrue(f.completeExceptionally(new IndexOutOfBoundsException())); - assertTrue(f.toString().contains("[Completed exceptionally]")); + assertTrue(f.toString().matches(".*\\[.*Completed exceptionally.*\\]")); + if (testImplementationDetails) + assertTrue(f.toString().startsWith( + identityString(f) + "[Completed exceptionally: ")); + } + public void testToString_cancelled() { for (boolean mayInterruptIfRunning : new boolean[] { true, false }) { - f = new CompletableFuture(); + CompletableFuture f = new CompletableFuture<>(); assertTrue(f.cancel(mayInterruptIfRunning)); - assertTrue(f.toString().contains("[Completed exceptionally]")); + assertTrue(f.toString().matches(".*\\[.*Completed exceptionally.*\\]")); + if (testImplementationDetails) + assertTrue(f.toString().startsWith( + identityString(f) + "[Completed exceptionally: ")); } } @@ -537,6 +557,29 @@ public class CompletableFutureTest exten } } + static class FailingExceptionalCompletableFutureFunction extends CheckedAction + implements Function> + { + final CFException ex; + FailingExceptionalCompletableFutureFunction(ExecutionMode m) { super(m); ex = new CFException(); } + public CompletableFuture apply(Throwable x) { + invoked(); + throw ex; + } + } + + static class ExceptionalCompletableFutureFunction extends CheckedAction + implements Function> { + final Integer value = 3; + ExceptionalCompletableFutureFunction(ExecutionMode m) { super(m); } + public CompletionStage apply(Throwable x) { + invoked(); + CompletableFuture d = new CompletableFuture(); + d.complete(value); + return d; + } + } + static class FailingCompletableFutureFunction extends CheckedIntegerAction implements Function> { @@ -652,8 +695,16 @@ public class CompletableFutureTest exten Function a) { return f.applyToEither(g, a); } + public CompletableFuture exceptionally + (CompletableFuture f, + Function fn) { + return f.exceptionally(fn); + } + public CompletableFuture exceptionallyCompose + (CompletableFuture f, Function> fn) { + return f.exceptionallyCompose(fn); + } }, - ASYNC { public void checkExecutionMode() { assertEquals(defaultExecutorIsCommonPool, @@ -726,6 +777,17 @@ public class CompletableFutureTest exten Function a) { return f.applyToEitherAsync(g, a); } + public CompletableFuture exceptionally + (CompletableFuture f, + Function fn) { + return f.exceptionallyAsync(fn); + } + + public CompletableFuture exceptionallyCompose + (CompletableFuture f, Function> fn) { + return f.exceptionallyComposeAsync(fn); + } + }, EXECUTOR { @@ -799,6 +861,16 @@ public class CompletableFutureTest exten Function a) { return f.applyToEitherAsync(g, a, new ThreadExecutor()); } + public CompletableFuture exceptionally + (CompletableFuture f, + Function fn) { + return f.exceptionallyAsync(fn, new ThreadExecutor()); + } + public CompletableFuture exceptionallyCompose + (CompletableFuture f, Function> fn) { + return f.exceptionallyComposeAsync(fn, new ThreadExecutor()); + } + }; public abstract void checkExecutionMode(); @@ -841,6 +913,12 @@ public class CompletableFutureTest exten (CompletableFuture f, CompletionStage g, Function a); + public abstract CompletableFuture exceptionally + (CompletableFuture f, + Function fn); + public abstract CompletableFuture exceptionallyCompose + (CompletableFuture f, + Function> fn); } /** @@ -848,14 +926,15 @@ public class CompletableFutureTest exten * normally, and source result is propagated */ public void testExceptionally_normalCompletion() { + for (ExecutionMode m : ExecutionMode.values()) for (boolean createIncomplete : new boolean[] { true, false }) for (Integer v1 : new Integer[] { 1, null }) { final AtomicInteger a = new AtomicInteger(0); final CompletableFuture f = new CompletableFuture<>(); if (!createIncomplete) assertTrue(f.complete(v1)); - final CompletableFuture g = f.exceptionally - ((Throwable t) -> { + final CompletableFuture g = m.exceptionally + (f, (Throwable t) -> { a.getAndIncrement(); threadFail("should not be called"); return null; // unreached @@ -872,6 +951,7 @@ public class CompletableFutureTest exten * exception */ public void testExceptionally_exceptionalCompletion() { + for (ExecutionMode m : ExecutionMode.values()) for (boolean createIncomplete : new boolean[] { true, false }) for (Integer v1 : new Integer[] { 1, null }) { @@ -879,9 +959,9 @@ public class CompletableFutureTest exten final CFException ex = new CFException(); final CompletableFuture f = new CompletableFuture<>(); if (!createIncomplete) f.completeExceptionally(ex); - final CompletableFuture g = f.exceptionally - ((Throwable t) -> { - ExecutionMode.SYNC.checkExecutionMode(); + final CompletableFuture g = m.exceptionally + (f, (Throwable t) -> { + m.checkExecutionMode(); threadAssertSame(t, ex); a.getAndIncrement(); return v1; @@ -897,6 +977,7 @@ public class CompletableFutureTest exten * exceptionally with that exception */ public void testExceptionally_exceptionalCompletionActionFailed() { + for (ExecutionMode m : ExecutionMode.values()) for (boolean createIncomplete : new boolean[] { true, false }) { final AtomicInteger a = new AtomicInteger(0); @@ -904,9 +985,9 @@ public class CompletableFutureTest exten final CFException ex2 = new CFException(); final CompletableFuture f = new CompletableFuture<>(); if (!createIncomplete) f.completeExceptionally(ex1); - final CompletableFuture g = f.exceptionally - ((Throwable t) -> { - ExecutionMode.SYNC.checkExecutionMode(); + final CompletableFuture g = m.exceptionally + (f, (Throwable t) -> { + m.checkExecutionMode(); threadAssertSame(t, ex1); a.getAndIncrement(); throw ex2; @@ -1242,6 +1323,7 @@ public class CompletableFutureTest exten r.assertInvoked(); }} + @SuppressWarnings("FutureReturnValueIgnored") public void testRunAsync_rejectingExecutor() { CountingRejectingExecutor e = new CountingRejectingExecutor(); try { @@ -1288,6 +1370,7 @@ public class CompletableFutureTest exten r.assertInvoked(); }} + @SuppressWarnings("FutureReturnValueIgnored") public void testSupplyAsync_rejectingExecutor() { CountingRejectingExecutor e = new CountingRejectingExecutor(); try { @@ -2562,28 +2645,28 @@ public class CompletableFutureTest exten // unspecified behavior - both source completions available try { - assertEquals(null, h0.join()); + assertNull(h0.join()); rs[0].assertValue(v1); } catch (CompletionException ok) { checkCompletedWithWrappedException(h0, ex); rs[0].assertNotInvoked(); } try { - assertEquals(null, h1.join()); + assertNull(h1.join()); rs[1].assertValue(v1); } catch (CompletionException ok) { checkCompletedWithWrappedException(h1, ex); rs[1].assertNotInvoked(); } try { - assertEquals(null, h2.join()); + assertNull(h2.join()); rs[2].assertValue(v1); } catch (CompletionException ok) { checkCompletedWithWrappedException(h2, ex); rs[2].assertNotInvoked(); } try { - assertEquals(null, h3.join()); + assertNull(h3.join()); rs[3].assertValue(v1); } catch (CompletionException ok) { checkCompletedWithWrappedException(h3, ex); @@ -2822,28 +2905,28 @@ public class CompletableFutureTest exten // unspecified behavior - both source completions available try { - assertEquals(null, h0.join()); + assertNull(h0.join()); rs[0].assertInvoked(); } catch (CompletionException ok) { checkCompletedWithWrappedException(h0, ex); rs[0].assertNotInvoked(); } try { - assertEquals(null, h1.join()); + assertNull(h1.join()); rs[1].assertInvoked(); } catch (CompletionException ok) { checkCompletedWithWrappedException(h1, ex); rs[1].assertNotInvoked(); } try { - assertEquals(null, h2.join()); + assertNull(h2.join()); rs[2].assertInvoked(); } catch (CompletionException ok) { checkCompletedWithWrappedException(h2, ex); rs[2].assertNotInvoked(); } try { - assertEquals(null, h3.join()); + assertNull(h3.join()); rs[3].assertInvoked(); } catch (CompletionException ok) { checkCompletedWithWrappedException(h3, ex); @@ -3075,6 +3158,70 @@ public class CompletableFutureTest exten checkCompletedNormally(f, v1); }} + /** + * exceptionallyCompose result completes normally after normal + * completion of source + */ + public void testExceptionallyCompose_normalCompletion() { + for (ExecutionMode m : ExecutionMode.values()) + for (boolean createIncomplete : new boolean[] { true, false }) + for (Integer v1 : new Integer[] { 1, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final ExceptionalCompletableFutureFunction r = + new ExceptionalCompletableFutureFunction(m); + if (!createIncomplete) assertTrue(f.complete(v1)); + final CompletableFuture g = m.exceptionallyCompose(f, r); + if (createIncomplete) assertTrue(f.complete(v1)); + + checkCompletedNormally(f, v1); + checkCompletedNormally(g, v1); + r.assertNotInvoked(); + }} + + /** + * exceptionallyCompose result completes normally after exceptional + * completion of source + */ + public void testExceptionallyCompose_exceptionalCompletion() { + for (ExecutionMode m : ExecutionMode.values()) + for (boolean createIncomplete : new boolean[] { true, false }) + { + final CFException ex = new CFException(); + final ExceptionalCompletableFutureFunction r = + new ExceptionalCompletableFutureFunction(m); + final CompletableFuture f = new CompletableFuture<>(); + if (!createIncomplete) f.completeExceptionally(ex); + final CompletableFuture g = m.exceptionallyCompose(f, r); + if (createIncomplete) f.completeExceptionally(ex); + + checkCompletedExceptionally(f, ex); + checkCompletedNormally(g, r.value); + r.assertInvoked(); + }} + + /** + * exceptionallyCompose completes exceptionally on exception if action does + */ + public void testExceptionallyCompose_actionFailed() { + for (ExecutionMode m : ExecutionMode.values()) + for (boolean createIncomplete : new boolean[] { true, false }) + for (Integer v1 : new Integer[] { 1, null }) + { + final CFException ex = new CFException(); + final CompletableFuture f = new CompletableFuture<>(); + final FailingExceptionalCompletableFutureFunction r + = new FailingExceptionalCompletableFutureFunction(m); + if (!createIncomplete) f.completeExceptionally(ex); + final CompletableFuture g = m.exceptionallyCompose(f, r); + if (createIncomplete) f.completeExceptionally(ex); + + checkCompletedExceptionally(f, ex); + checkCompletedWithWrappedException(g, r.ex); + r.assertInvoked(); + }} + + // other static methods /** @@ -3238,6 +3385,7 @@ public class CompletableFutureTest exten /** * Completion methods throw NullPointerException with null arguments */ + @SuppressWarnings("FutureReturnValueIgnored") public void testNPE() { CompletableFuture f = new CompletableFuture<>(); CompletableFuture g = new CompletableFuture<>(); @@ -3532,7 +3680,7 @@ public class CompletableFutureTest exten */ public void testCompletedStage() { AtomicInteger x = new AtomicInteger(0); - AtomicReference r = new AtomicReference(); + AtomicReference r = new AtomicReference<>(); CompletionStage f = CompletableFuture.completedStage(1); f.whenComplete((v, e) -> {if (e != null) r.set(e); else x.set(v);}); assertEquals(x.get(), 1); @@ -3634,7 +3782,7 @@ public class CompletableFutureTest exten CompletableFuture f = new CompletableFuture<>(); CompletionStage g = f.minimalCompletionStage(); AtomicInteger x = new AtomicInteger(0); - AtomicReference r = new AtomicReference(); + AtomicReference r = new AtomicReference<>(); checkIncomplete(f); g.whenComplete((v, e) -> {if (e != null) r.set(e); else x.set(v);}); f.complete(1); @@ -3651,7 +3799,7 @@ public class CompletableFutureTest exten CompletableFuture f = new CompletableFuture<>(); CompletionStage g = f.minimalCompletionStage(); AtomicInteger x = new AtomicInteger(0); - AtomicReference r = new AtomicReference(); + AtomicReference r = new AtomicReference<>(); g.whenComplete((v, e) -> {if (e != null) r.set(e); else x.set(v);}); checkIncomplete(f); CFException ex = new CFException(); @@ -3669,7 +3817,7 @@ public class CompletableFutureTest exten CFException ex = new CFException(); CompletionStage f = CompletableFuture.failedStage(ex); AtomicInteger x = new AtomicInteger(0); - AtomicReference r = new AtomicReference(); + AtomicReference r = new AtomicReference<>(); f.whenComplete((v, e) -> {if (e != null) r.set(e); else x.set(v);}); assertEquals(x.get(), 0); assertEquals(r.get(), ex); @@ -3693,7 +3841,7 @@ public class CompletableFutureTest exten public void testCompleteAsync2() { CompletableFuture f = new CompletableFuture<>(); CFException ex = new CFException(); - f.completeAsync(() -> {if (true) throw ex; return 1;}); + f.completeAsync(() -> { throw ex; }); try { f.join(); shouldThrow(); @@ -3723,7 +3871,7 @@ public class CompletableFutureTest exten CompletableFuture f = new CompletableFuture<>(); CFException ex = new CFException(); ThreadExecutor executor = new ThreadExecutor(); - f.completeAsync(() -> {if (true) throw ex; return 1;}, executor); + f.completeAsync(() -> { throw ex; }, executor); try { f.join(); shouldThrow(); @@ -4174,7 +4322,7 @@ public class CompletableFutureTest exten static void assertZero(CompletableFuture f) { try { f.getNow(null); - throw new AssertionFailedError("should throw"); + throw new AssertionError("should throw"); } catch (CompletionException success) { assertTrue(success.getCause() instanceof ZeroException); } @@ -4299,6 +4447,7 @@ public class CompletableFutureTest exten } /** Test long recursive chains of CompletableFutures with cascading completions */ + @SuppressWarnings("FutureReturnValueIgnored") public void testRecursiveChains() throws Throwable { for (ExecutionMode m : ExecutionMode.values()) for (boolean addDeadEnds : new boolean[] { true, false }) @@ -4323,6 +4472,7 @@ public class CompletableFutureTest exten * A single CompletableFuture with many dependents. * A demo of scalability - runtime is O(n). */ + @SuppressWarnings("FutureReturnValueIgnored") public void testManyDependents() throws Throwable { final int n = expensiveTests ? 1_000_000 : 10; final CompletableFuture head = new CompletableFuture<>(); @@ -4352,6 +4502,7 @@ public class CompletableFutureTest exten } /** ant -Dvmoptions=-Xmx8m -Djsr166.expensiveTests=true -Djsr166.tckTestClass=CompletableFutureTest tck */ + @SuppressWarnings("FutureReturnValueIgnored") public void testCoCompletionGarbageRetention() throws Throwable { final int n = expensiveTests ? 1_000_000 : 10; final CompletableFuture incomplete = new CompletableFuture<>(); @@ -4370,7 +4521,7 @@ public class CompletableFutureTest exten f.complete(null); f = new CompletableFuture<>(); - CompletableFuture.anyOf(new CompletableFuture[] { f, incomplete }); + CompletableFuture.anyOf(f, incomplete); f.complete(null); } @@ -4388,7 +4539,7 @@ public class CompletableFutureTest exten f.complete(null); f = new CompletableFuture<>(); - CompletableFuture.anyOf(new CompletableFuture[] { incomplete, f }); + CompletableFuture.anyOf(incomplete, f); f.complete(null); } }