diff --git a/src/java.base/share/classes/java/util/ArrayList.java b/src/java.base/share/classes/java/util/ArrayList.java --- a/src/java.base/share/classes/java/util/ArrayList.java +++ b/src/java.base/share/classes/java/util/ArrayList.java @@ -1729,7 +1729,6 @@ @Override public void replaceAll(UnaryOperator operator) { replaceAllRange(operator, 0, size); - modCount++; } private void replaceAllRange(UnaryOperator operator, int i, int end) { diff --git a/src/java.base/share/classes/java/util/Vector.java b/src/java.base/share/classes/java/util/Vector.java --- a/src/java.base/share/classes/java/util/Vector.java +++ b/src/java.base/share/classes/java/util/Vector.java @@ -1402,7 +1402,6 @@ es[i] = operator.apply(elementAt(es, i)); if (modCount != expectedModCount) throw new ConcurrentModificationException(); - modCount++; } @SuppressWarnings("unchecked") diff --git a/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java b/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java --- a/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java +++ b/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java @@ -957,17 +957,17 @@ @SuppressWarnings("serial") static final class UniExceptionally extends UniCompletion { Function fn; - UniExceptionally(CompletableFuture dep, CompletableFuture src, + UniExceptionally(Executor executor, + CompletableFuture dep, CompletableFuture src, Function fn) { - super(null, dep, src); this.fn = fn; + super(executor, dep, src); this.fn = fn; } - final CompletableFuture tryFire(int mode) { // never ASYNC - // assert mode != ASYNC; + final CompletableFuture tryFire(int mode) { CompletableFuture d; CompletableFuture a; Object r; Function f; if ((d = dep) == null || (f = fn) == null || (a = src) == null || (r = a.result) == null - || !d.uniExceptionally(r, f, this)) + || !d.uniExceptionally(r, f, mode > 0 ? null : this)) return null; dep = null; src = null; fn = null; return d.postFire(a, mode); @@ -980,11 +980,11 @@ Throwable x; if (result == null) { try { - if (r instanceof AltResult && (x = ((AltResult)r).ex) != null) { - if (c != null && !c.claim()) - return false; + if (c != null && !c.claim()) + return false; + if (r instanceof AltResult && (x = ((AltResult)r).ex) != null) completeValue(f.apply(x)); - } else + else internalComplete(r); } catch (Throwable ex) { completeThrowable(ex); @@ -994,14 +994,88 @@ } private CompletableFuture uniExceptionallyStage( - Function f) { + Executor e, Function f) { if (f == null) throw new NullPointerException(); CompletableFuture d = newIncompleteFuture(); Object r; if ((r = result) == null) - unipush(new UniExceptionally(d, this, f)); + unipush(new UniExceptionally(e, d, this, f)); + else if (e == null) + d.uniExceptionally(r, f, null); + else { + try { + e.execute(new UniExceptionally(null, d, this, f)); + } catch (Throwable ex) { + d.result = encodeThrowable(ex); + } + } + return d; + } + + @SuppressWarnings("serial") + static final class UniComposeExceptionally extends UniCompletion { + Function> fn; + UniComposeExceptionally(Executor executor, CompletableFuture dep, + CompletableFuture src, + Function> fn) { + super(executor, dep, src); this.fn = fn; + } + final CompletableFuture tryFire(int mode) { + CompletableFuture d; CompletableFuture a; + Function> f; + Object r; Throwable x; + if ((d = dep) == null || (f = fn) == null + || (a = src) == null || (r = a.result) == null) + return null; + if (d.result == null) { + if ((r instanceof AltResult) && + (x = ((AltResult)r).ex) != null) { + try { + if (mode <= 0 && !claim()) + return null; + CompletableFuture g = f.apply(x).toCompletableFuture(); + if ((r = g.result) != null) + d.completeRelay(r); + else { + g.unipush(new UniRelay(d, g)); + if (d.result == null) + return null; + } + } catch (Throwable ex) { + d.completeThrowable(ex); + } + } + else + d.internalComplete(r); + } + dep = null; src = null; fn = null; + return d.postFire(a, mode); + } + } + + private CompletableFuture uniComposeExceptionallyStage( + Executor e, Function> f) { + if (f == null) throw new NullPointerException(); + CompletableFuture d = newIncompleteFuture(); + Object r, s; Throwable x; + if ((r = result) == null) + unipush(new UniComposeExceptionally(e, d, this, f)); + else if (!(r instanceof AltResult) || (x = ((AltResult)r).ex) == null) + d.internalComplete(r); else - d.uniExceptionally(r, f, null); + try { + if (e != null) + e.execute(new UniComposeExceptionally(null, d, this, f)); + else { + CompletableFuture g = f.apply(x).toCompletableFuture(); + if ((s = g.result) != null) + d.result = encodeRelay(s); + else + g.unipush(new UniRelay(d, g)); + } + } catch (Throwable ex) { + d.result = encodeThrowable(ex); + } return d; } @@ -1093,7 +1167,7 @@ Object r, s; Throwable x; if ((r = result) == null) unipush(new UniCompose(e, d, this, f)); - else if (e == null) { + else { if (r instanceof AltResult) { if ((x = ((AltResult)r).ex) != null) { d.result = encodeThrowable(x, r); @@ -1102,23 +1176,20 @@ r = null; } try { - @SuppressWarnings("unchecked") T t = (T) r; - CompletableFuture g = f.apply(t).toCompletableFuture(); - if ((s = g.result) != null) - d.result = encodeRelay(s); + if (e != null) + e.execute(new UniCompose(null, d, this, f)); else { - g.unipush(new UniRelay(d, g)); + @SuppressWarnings("unchecked") T t = (T) r; + CompletableFuture g = f.apply(t).toCompletableFuture(); + if ((s = g.result) != null) + d.result = encodeRelay(s); + else + g.unipush(new UniRelay(d, g)); } } catch (Throwable ex) { d.result = encodeThrowable(ex); } } - else - try { - e.execute(new UniCompose(null, d, this, f)); - } catch (Throwable ex) { - d.result = encodeThrowable(ex); - } return d; } @@ -1898,7 +1969,7 @@ * Creates a new complete CompletableFuture with given encoded result. */ CompletableFuture(Object r) { - this.result = r; + RESULT.setRelease(this, r); } /** @@ -2285,28 +2356,36 @@ return this; } - // not in interface CompletionStage - - /** - * Returns a new CompletableFuture that is completed when this - * CompletableFuture completes, with the result of the given - * function of the exception triggering this CompletableFuture's - * completion when it completes exceptionally; otherwise, if this - * CompletableFuture completes normally, then the returned - * CompletableFuture also completes normally with the same value. - * Note: More flexible versions of this functionality are - * available using methods {@code whenComplete} and {@code handle}. - * - * @param fn the function to use to compute the value of the - * returned CompletableFuture if this CompletableFuture completed - * exceptionally - * @return the new CompletableFuture - */ public CompletableFuture exceptionally( Function fn) { - return uniExceptionallyStage(fn); + return uniExceptionallyStage(null, fn); + } + + public CompletableFuture exceptionallyAsync( + Function fn) { + return uniExceptionallyStage(defaultExecutor(), fn); + } + + public CompletableFuture exceptionallyAsync( + Function fn, Executor executor) { + return uniExceptionallyStage(screenExecutor(executor), fn); } + public CompletableFuture exceptionallyCompose( + Function> fn) { + return uniComposeExceptionallyStage(null, fn); + } + + public CompletableFuture exceptionallyComposeAsync( + Function> fn) { + return uniComposeExceptionallyStage(defaultExecutor(), fn); + } + + public CompletableFuture exceptionallyComposeAsync( + Function> fn, + Executor executor) { + return uniComposeExceptionallyStage(screenExecutor(executor), fn); + } /* ------------- Arbitrary-arity constructions -------------- */ diff --git a/src/java.base/share/classes/java/util/concurrent/CompletionStage.java b/src/java.base/share/classes/java/util/concurrent/CompletionStage.java --- a/src/java.base/share/classes/java/util/concurrent/CompletionStage.java +++ b/src/java.base/share/classes/java/util/concurrent/CompletionStage.java @@ -851,6 +851,130 @@ (Function fn); /** + * Returns a new CompletionStage that, when this stage completes + * exceptionally, is executed with this stage's exception as the + * argument to the supplied function, using this stage's default + * asynchronous execution facility. Otherwise, if this stage + * completes normally, then the returned stage also completes + * normally with the same value. + * + * @implSpec The default implementation invokes {@link #handle}, + * relaying to {@link #handleAsync} on exception, then {@link + * #thenCompose} for result. + * + * @param fn the function to use to compute the value of the + * returned CompletionStage if this CompletionStage completed + * exceptionally + * @return the new CompletionStage + * @since 12 + */ + public default CompletionStage exceptionallyAsync + (Function fn) { + return handle((r, ex) -> (ex == null) + ? this + : this.handleAsync((r1, ex1) -> fn.apply(ex1))) + .thenCompose(Function.identity()); + } + + /** + * Returns a new CompletionStage that, when this stage completes + * exceptionally, is executed with this stage's exception as the + * argument to the supplied function, using the supplied Executor. + * Otherwise, if this stage completes normally, then the returned + * stage also completes normally with the same value. + * + * @implSpec The default implementation invokes {@link #handle}, + * relaying to {@link #handleAsync} on exception, then {@link + * #thenCompose} for result. + * + * @param fn the function to use to compute the value of the + * returned CompletionStage if this CompletionStage completed + * exceptionally + * @param executor the executor to use for asynchronous execution + * @return the new CompletionStage + * @since 12 + */ + public default CompletionStage exceptionallyAsync + (Function fn, Executor executor) { + return handle((r, ex) -> (ex == null) + ? this + : this.handleAsync((r1, ex1) -> fn.apply(ex1), executor)) + .thenCompose(Function.identity()); + } + + /** + * Returns a new CompletionStage that, when this stage completes + * exceptionally, is composed using the results of the supplied + * function applied to this stage's exception. + * + * @implSpec The default implementation invokes {@link #handle}, + * invoking the given function on exception, then {@link + * #thenCompose} for result. + * + * @param fn the function to use to compute the returned + * CompletionStage if this CompletionStage completed exceptionally + * @return the new CompletionStage + * @since 12 + */ + public default CompletionStage exceptionallyCompose + (Function> fn) { + return handle((r, ex) -> (ex == null) + ? this + : fn.apply(ex)) + .thenCompose(Function.identity()); + } + + /** + * Returns a new CompletionStage that, when this stage completes + * exceptionally, is composed using the results of the supplied + * function applied to this stage's exception, using this stage's + * default asynchronous execution facility. + * + * @implSpec The default implementation invokes {@link #handle}, + * relaying to {@link #handleAsync} on exception, then {@link + * #thenCompose} for result. + * + * @param fn the function to use to compute the returned + * CompletionStage if this CompletionStage completed exceptionally + * @return the new CompletionStage + * @since 12 + */ + public default CompletionStage exceptionallyComposeAsync + (Function> fn) { + return handle((r, ex) -> (ex == null) + ? this + : this.handleAsync((r1, ex1) -> fn.apply(ex1)) + .thenCompose(Function.identity())) + .thenCompose(Function.identity()); + } + + /** + * Returns a new CompletionStage that, when this stage completes + * exceptionally, is composed using the results of the supplied + * function applied to this stage's exception, using the + * supplied Executor. + * + * @implSpec The default implementation invokes {@link #handle}, + * relaying to {@link #handleAsync} on exception, then {@link + * #thenCompose} for result. + * + * @param fn the function to use to compute the returned + * CompletionStage if this CompletionStage completed exceptionally + * @param executor the executor to use for asynchronous execution + * @return the new CompletionStage + * @since 12 + */ + public default CompletionStage exceptionallyComposeAsync + (Function> fn, + Executor executor) { + return handle((r, ex) -> (ex == null) + ? this + : this.handleAsync((r1, ex1) -> fn.apply(ex1), executor) + .thenCompose(Function.identity())) + .thenCompose(Function.identity()); + } + + /** * Returns a {@link CompletableFuture} maintaining the same * completion properties as this stage. If this stage is already a * CompletableFuture, this method may return this stage itself. diff --git a/test/jdk/java/util/Collections/EmptyNavigableSet.java b/test/jdk/java/util/Collections/EmptyNavigableSet.java --- a/test/jdk/java/util/Collections/EmptyNavigableSet.java +++ b/test/jdk/java/util/Collections/EmptyNavigableSet.java @@ -45,6 +45,7 @@ import java.util.TreeSet; import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertNull; import static org.testng.Assert.assertSame; import static org.testng.Assert.assertTrue; @@ -369,7 +370,7 @@ assertSame(emptyNavigableSetArray, result); - assertTrue(result[0] == null); + assertNull(result[0]); } @DataProvider(name = "NavigableSet", parallel = true) diff --git a/test/jdk/java/util/PriorityQueue/AddNonComparable.java b/test/jdk/java/util/PriorityQueue/AddNonComparable.java --- a/test/jdk/java/util/PriorityQueue/AddNonComparable.java +++ b/test/jdk/java/util/PriorityQueue/AddNonComparable.java @@ -42,6 +42,7 @@ import java.util.function.Supplier; import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; public class AddNonComparable { @@ -64,7 +65,7 @@ test(new PriorityQueue<>(), AComparable::new, (q, e) -> { assertEquals(q.size(), 1); - assertTrue(e == null); + assertNull(e); }); test(new PriorityBlockingQueue<>(), NonComparable::new, @@ -75,7 +76,7 @@ test(new PriorityBlockingQueue<>(), AComparable::new, (q, e) -> { assertEquals(q.size(), 1); - assertTrue(e == null); + assertNull(e); }); } @@ -98,7 +99,7 @@ test(new TreeSet<>(), AComparable::new, (s, e) -> { assertEquals(s.size(), 1); - assertTrue(e == null); + assertNull(e); }); test(new ConcurrentSkipListSet<>(), NonComparable::new, @@ -109,7 +110,7 @@ test(new ConcurrentSkipListSet<>(), AComparable::new, (s, e) -> { assertEquals(s.size(), 1); - assertTrue(e == null); + assertNull(e); }); } @@ -131,7 +132,7 @@ test(new TreeMap<>(), AComparable::new, (m, e) -> { assertEquals(m.size(), 1); - assertTrue(e == null); + assertNull(e); }); test(new ConcurrentSkipListMap<>(), NonComparable::new, @@ -142,7 +143,7 @@ test(new ConcurrentSkipListMap<>(), AComparable::new, (s, e) -> { assertEquals(s.size(), 1); - assertTrue(e == null); + assertNull(e); }); } diff --git a/test/jdk/java/util/concurrent/tck/AbstractQueuedSynchronizerTest.java b/test/jdk/java/util/concurrent/tck/AbstractQueuedSynchronizerTest.java --- a/test/jdk/java/util/concurrent/tck/AbstractQueuedSynchronizerTest.java +++ b/test/jdk/java/util/concurrent/tck/AbstractQueuedSynchronizerTest.java @@ -1310,7 +1310,7 @@ try { s.acquireInterruptibly(1); shouldThrow(); - } catch (InterruptedException expected) {} + } catch (InterruptedException success) {} }; for (int i = 0; i < 2; i++) { Thread thread = new Thread(failedAcquire); diff --git a/test/jdk/java/util/concurrent/tck/Collection8Test.java b/test/jdk/java/util/concurrent/tck/Collection8Test.java --- a/test/jdk/java/util/concurrent/tck/Collection8Test.java +++ b/test/jdk/java/util/concurrent/tck/Collection8Test.java @@ -979,7 +979,7 @@ } catch (java.io.NotSerializableException acceptable) {} } - public void DISABLED_testReplaceAllIsNotStructuralModification() { + public void testReplaceAllIsNotStructuralModification() { Collection c = impl.emptyCollection(); if (!(c instanceof List)) return; diff --git a/test/jdk/java/util/concurrent/tck/CompletableFutureTest.java b/test/jdk/java/util/concurrent/tck/CompletableFutureTest.java --- a/test/jdk/java/util/concurrent/tck/CompletableFutureTest.java +++ b/test/jdk/java/util/concurrent/tck/CompletableFutureTest.java @@ -86,9 +86,13 @@ assertFalse(f.isDone()); assertFalse(f.isCancelled()); 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(randomExpiredTimeout(), randomTimeUnit()); shouldThrow(); @@ -97,14 +101,18 @@ 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()); - assertEquals(value, f.getNow(null)); - assertEquals(value, f.get()); + result = f.get(); } catch (Throwable fail) { threadUnexpectedException(fail); } + assertEquals(expectedValue, result); + assertTrue(f.isDone()); assertFalse(f.isCancelled()); assertFalse(f.isCompletedExceptionally()); @@ -570,9 +578,28 @@ public CompletableFuture apply(Integer x) { invoked(); value = x; - CompletableFuture f = new CompletableFuture<>(); - assertTrue(f.complete(inc(x))); - return f; + return CompletableFuture.completedFuture(inc(x)); + } + } + + 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(); + return CompletableFuture.completedFuture(value); } } @@ -691,8 +718,16 @@ 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, @@ -765,6 +800,17 @@ 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 { @@ -838,6 +884,16 @@ 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(); @@ -880,6 +936,12 @@ (CompletableFuture f, CompletionStage g, Function a); + public abstract CompletableFuture exceptionally + (CompletableFuture f, + Function fn); + public abstract CompletableFuture exceptionallyCompose + (CompletableFuture f, + Function> fn); } /** @@ -887,15 +949,14 @@ * 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) -> { - a.getAndIncrement(); + final CompletableFuture g = m.exceptionally + (f, (Throwable t) -> { threadFail("should not be called"); return null; // unreached }); @@ -903,7 +964,6 @@ checkCompletedNormally(g, v1); checkCompletedNormally(f, v1); - assertEquals(0, a.get()); }} /** @@ -911,6 +971,7 @@ * exception */ public void testExceptionally_exceptionalCompletion() { + for (ExecutionMode m : ExecutionMode.values()) for (boolean createIncomplete : new boolean[] { true, false }) for (Integer v1 : new Integer[] { 1, null }) { @@ -918,9 +979,9 @@ 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; @@ -936,6 +997,7 @@ * 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); @@ -943,9 +1005,9 @@ 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; @@ -3116,6 +3178,121 @@ 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 }) + { + 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(); + }} + + /** + * exceptionallyCompose result completes exceptionally if the + * result of the action does + */ + public void testExceptionallyCompose_actionReturnsFailingFuture() { + for (ExecutionMode m : ExecutionMode.values()) + for (int order = 0; order < 6; order++) + { + final CFException ex0 = new CFException(); + final CFException ex = new CFException(); + final CompletableFuture f = new CompletableFuture<>(); + final CompletableFuture g = new CompletableFuture<>(); + final CompletableFuture h; + // Test all permutations of orders + switch (order) { + case 0: + assertTrue(f.completeExceptionally(ex0)); + assertTrue(g.completeExceptionally(ex)); + h = m.exceptionallyCompose(f, (x -> g)); + break; + case 1: + assertTrue(f.completeExceptionally(ex0)); + h = m.exceptionallyCompose(f, (x -> g)); + assertTrue(g.completeExceptionally(ex)); + break; + case 2: + assertTrue(g.completeExceptionally(ex)); + assertTrue(f.completeExceptionally(ex0)); + h = m.exceptionallyCompose(f, (x -> g)); + break; + case 3: + assertTrue(g.completeExceptionally(ex)); + h = m.exceptionallyCompose(f, (x -> g)); + assertTrue(f.completeExceptionally(ex0)); + break; + case 4: + h = m.exceptionallyCompose(f, (x -> g)); + assertTrue(f.completeExceptionally(ex0)); + assertTrue(g.completeExceptionally(ex)); + break; + case 5: + h = m.exceptionallyCompose(f, (x -> g)); + assertTrue(f.completeExceptionally(ex0)); + assertTrue(g.completeExceptionally(ex)); + break; + default: throw new AssertionError(); + } + + checkCompletedExceptionally(g, ex); + checkCompletedWithWrappedException(h, ex); + checkCompletedExceptionally(f, ex0); + }} + // other static methods /** @@ -4527,4 +4704,429 @@ // return stage.toCompletableFuture().copy().isDone(); // } + // For testing default implementations + // Only non-default interface methods defined. + static final class DelegatedCompletionStage implements CompletionStage { + final CompletableFuture cf; + DelegatedCompletionStage(CompletableFuture cf) { this.cf = cf; } + public CompletableFuture toCompletableFuture() { + return cf; } + public CompletionStage thenRun + (Runnable action) { + return cf.thenRun(action); } + public CompletionStage thenRunAsync + (Runnable action) { + return cf.thenRunAsync(action); } + public CompletionStage thenRunAsync + (Runnable action, + Executor executor) { + return cf.thenRunAsync(action, executor); } + public CompletionStage thenAccept + (Consumer action) { + return cf.thenAccept(action); } + public CompletionStage thenAcceptAsync + (Consumer action) { + return cf.thenAcceptAsync(action); } + public CompletionStage thenAcceptAsync + (Consumer action, + Executor executor) { + return cf.thenAcceptAsync(action, executor); } + public CompletionStage thenApply + (Function a) { + return cf.thenApply(a); } + public CompletionStage thenApplyAsync + (Function fn) { + return cf.thenApplyAsync(fn); } + public CompletionStage thenApplyAsync + (Function fn, + Executor executor) { + return cf.thenApplyAsync(fn, executor); } + public CompletionStage thenCombine + (CompletionStage other, + BiFunction fn) { + return cf.thenCombine(other, fn); } + public CompletionStage thenCombineAsync + (CompletionStage other, + BiFunction fn) { + return cf.thenCombineAsync(other, fn); } + public CompletionStage thenCombineAsync + (CompletionStage other, + BiFunction fn, + Executor executor) { + return cf.thenCombineAsync(other, fn, executor); } + public CompletionStage thenAcceptBoth + (CompletionStage other, + BiConsumer action) { + return cf.thenAcceptBoth(other, action); } + public CompletionStage thenAcceptBothAsync + (CompletionStage other, + BiConsumer action) { + return cf.thenAcceptBothAsync(other, action); } + public CompletionStage thenAcceptBothAsync + (CompletionStage other, + BiConsumer action, + Executor executor) { + return cf.thenAcceptBothAsync(other, action, executor); } + public CompletionStage runAfterBoth + (CompletionStage other, + Runnable action) { + return cf.runAfterBoth(other, action); } + public CompletionStage runAfterBothAsync + (CompletionStage other, + Runnable action) { + return cf.runAfterBothAsync(other, action); } + public CompletionStage runAfterBothAsync + (CompletionStage other, + Runnable action, + Executor executor) { + return cf.runAfterBothAsync(other, action, executor); } + public CompletionStage applyToEither + (CompletionStage other, + Function fn) { + return cf.applyToEither(other, fn); } + public CompletionStage applyToEitherAsync + (CompletionStage other, + Function fn) { + return cf.applyToEitherAsync(other, fn); } + public CompletionStage applyToEitherAsync + (CompletionStage other, + Function fn, + Executor executor) { + return cf.applyToEitherAsync(other, fn, executor); } + public CompletionStage acceptEither + (CompletionStage other, + Consumer action) { + return cf.acceptEither(other, action); } + public CompletionStage acceptEitherAsync + (CompletionStage other, + Consumer action) { + return cf.acceptEitherAsync(other, action); } + public CompletionStage acceptEitherAsync + (CompletionStage other, + Consumer action, + Executor executor) { + return cf.acceptEitherAsync(other, action, executor); } + public CompletionStage runAfterEither + (CompletionStage other, + Runnable action) { + return cf.runAfterEither(other, action); } + public CompletionStage runAfterEitherAsync + (CompletionStage other, + Runnable action) { + return cf.runAfterEitherAsync(other, action); } + public CompletionStage runAfterEitherAsync + (CompletionStage other, + Runnable action, + Executor executor) { + return cf.runAfterEitherAsync(other, action, executor); } + public CompletionStage thenCompose + (Function> fn) { + return cf.thenCompose(fn); } + public CompletionStage thenComposeAsync + (Function> fn) { + return cf.thenComposeAsync(fn); } + public CompletionStage thenComposeAsync + (Function> fn, + Executor executor) { + return cf.thenComposeAsync(fn, executor); } + public CompletionStage handle + (BiFunction fn) { + return cf.handle(fn); } + public CompletionStage handleAsync + (BiFunction fn) { + return cf.handleAsync(fn); } + public CompletionStage handleAsync + (BiFunction fn, + Executor executor) { + return cf.handleAsync(fn, executor); } + public CompletionStage whenComplete + (BiConsumer action) { + return cf.whenComplete(action); } + public CompletionStage whenCompleteAsync + (BiConsumer action) { + return cf.whenCompleteAsync(action); } + public CompletionStage whenCompleteAsync + (BiConsumer action, + Executor executor) { + return cf.whenCompleteAsync(action, executor); } + public CompletionStage exceptionally + (Function fn) { + return cf.exceptionally(fn); } + } + + /** + * default-implemented exceptionallyAsync action is not invoked when + * source completes normally, and source result is propagated + */ + public void testDefaultExceptionallyAsync_normalCompletion() { + for (boolean createIncomplete : new boolean[] { true, false }) + for (Integer v1 : new Integer[] { 1, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final DelegatedCompletionStage d = + new DelegatedCompletionStage(f); + if (!createIncomplete) assertTrue(f.complete(v1)); + final CompletionStage g = d.exceptionallyAsync + ((Throwable t) -> { + threadFail("should not be called"); + return null; // unreached + }); + if (createIncomplete) assertTrue(f.complete(v1)); + + checkCompletedNormally(g.toCompletableFuture(), v1); + }} + + /** + * default-implemented exceptionallyAsync action completes with + * function value on source exception + */ + public void testDefaultExceptionallyAsync_exceptionalCompletion() { + for (boolean createIncomplete : new boolean[] { true, false }) + for (Integer v1 : new Integer[] { 1, null }) + { + final AtomicInteger a = new AtomicInteger(0); + final CFException ex = new CFException(); + final CompletableFuture f = new CompletableFuture<>(); + final DelegatedCompletionStage d = + new DelegatedCompletionStage(f); + if (!createIncomplete) f.completeExceptionally(ex); + final CompletionStage g = d.exceptionallyAsync + ((Throwable t) -> { + threadAssertSame(t, ex); + a.getAndIncrement(); + return v1; + }); + if (createIncomplete) f.completeExceptionally(ex); + + checkCompletedNormally(g.toCompletableFuture(), v1); + assertEquals(1, a.get()); + }} + + /** + * Under default implementation, if an "exceptionally action" + * throws an exception, it completes exceptionally with that + * exception + */ + public void testDefaultExceptionallyAsync_exceptionalCompletionActionFailed() { + for (boolean createIncomplete : new boolean[] { true, false }) + { + final AtomicInteger a = new AtomicInteger(0); + final CFException ex1 = new CFException(); + final CFException ex2 = new CFException(); + final CompletableFuture f = new CompletableFuture<>(); + final DelegatedCompletionStage d = + new DelegatedCompletionStage(f); + if (!createIncomplete) f.completeExceptionally(ex1); + final CompletionStage g = d.exceptionallyAsync + ((Throwable t) -> { + threadAssertSame(t, ex1); + a.getAndIncrement(); + throw ex2; + }); + if (createIncomplete) f.completeExceptionally(ex1); + + checkCompletedWithWrappedException(g.toCompletableFuture(), ex2); + checkCompletedExceptionally(f, ex1); + checkCompletedExceptionally(d.toCompletableFuture(), ex1); + assertEquals(1, a.get()); + }} + + /** + * default-implemented exceptionallyCompose result completes + * normally after normal completion of source + */ + public void testDefaultExceptionallyCompose_normalCompletion() { + for (boolean createIncomplete : new boolean[] { true, false }) + for (Integer v1 : new Integer[] { 1, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final ExceptionalCompletableFutureFunction r = + new ExceptionalCompletableFutureFunction(ExecutionMode.SYNC); + final DelegatedCompletionStage d = + new DelegatedCompletionStage(f); + if (!createIncomplete) assertTrue(f.complete(v1)); + final CompletionStage g = d.exceptionallyCompose(r); + if (createIncomplete) assertTrue(f.complete(v1)); + + checkCompletedNormally(f, v1); + checkCompletedNormally(g.toCompletableFuture(), v1); + r.assertNotInvoked(); + }} + + /** + * default-implemented exceptionallyCompose result completes + * normally after exceptional completion of source + */ + public void testDefaultExceptionallyCompose_exceptionalCompletion() { + for (boolean createIncomplete : new boolean[] { true, false }) + { + final CFException ex = new CFException(); + final ExceptionalCompletableFutureFunction r = + new ExceptionalCompletableFutureFunction(ExecutionMode.SYNC); + final CompletableFuture f = new CompletableFuture<>(); + final DelegatedCompletionStage d = + new DelegatedCompletionStage(f); + if (!createIncomplete) f.completeExceptionally(ex); + final CompletionStage g = d.exceptionallyCompose(r); + if (createIncomplete) f.completeExceptionally(ex); + + checkCompletedExceptionally(f, ex); + checkCompletedNormally(g.toCompletableFuture(), r.value); + r.assertInvoked(); + }} + + /** + * default-implemented exceptionallyCompose completes + * exceptionally on exception if action does + */ + public void testDefaultExceptionallyCompose_actionFailed() { + for (boolean createIncomplete : new boolean[] { true, false }) + { + final CFException ex = new CFException(); + final CompletableFuture f = new CompletableFuture<>(); + final FailingExceptionalCompletableFutureFunction r + = new FailingExceptionalCompletableFutureFunction(ExecutionMode.SYNC); + final DelegatedCompletionStage d = + new DelegatedCompletionStage(f); + if (!createIncomplete) f.completeExceptionally(ex); + final CompletionStage g = d.exceptionallyCompose(r); + if (createIncomplete) f.completeExceptionally(ex); + + checkCompletedExceptionally(f, ex); + checkCompletedWithWrappedException(g.toCompletableFuture(), r.ex); + r.assertInvoked(); + }} + + /** + * default-implemented exceptionallyComposeAsync result completes + * normally after normal completion of source + */ + public void testDefaultExceptionallyComposeAsync_normalCompletion() { + for (boolean createIncomplete : new boolean[] { true, false }) + for (Integer v1 : new Integer[] { 1, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final ExceptionalCompletableFutureFunction r = + new ExceptionalCompletableFutureFunction(ExecutionMode.ASYNC); + final DelegatedCompletionStage d = + new DelegatedCompletionStage(f); + if (!createIncomplete) assertTrue(f.complete(v1)); + final CompletionStage g = d.exceptionallyComposeAsync(r); + if (createIncomplete) assertTrue(f.complete(v1)); + + checkCompletedNormally(f, v1); + checkCompletedNormally(g.toCompletableFuture(), v1); + r.assertNotInvoked(); + }} + + /** + * default-implemented exceptionallyComposeAsync result completes + * normally after exceptional completion of source + */ + public void testDefaultExceptionallyComposeAsync_exceptionalCompletion() { + for (boolean createIncomplete : new boolean[] { true, false }) + { + final CFException ex = new CFException(); + final ExceptionalCompletableFutureFunction r = + new ExceptionalCompletableFutureFunction(ExecutionMode.ASYNC); + final CompletableFuture f = new CompletableFuture<>(); + final DelegatedCompletionStage d = + new DelegatedCompletionStage(f); + if (!createIncomplete) f.completeExceptionally(ex); + final CompletionStage g = d.exceptionallyComposeAsync(r); + if (createIncomplete) f.completeExceptionally(ex); + + checkCompletedExceptionally(f, ex); + checkCompletedNormally(g.toCompletableFuture(), r.value); + r.assertInvoked(); + }} + + /** + * default-implemented exceptionallyComposeAsync completes + * exceptionally on exception if action does + */ + public void testDefaultExceptionallyComposeAsync_actionFailed() { + for (boolean createIncomplete : new boolean[] { true, false }) + { + final CFException ex = new CFException(); + final CompletableFuture f = new CompletableFuture<>(); + final FailingExceptionalCompletableFutureFunction r + = new FailingExceptionalCompletableFutureFunction(ExecutionMode.ASYNC); + final DelegatedCompletionStage d = + new DelegatedCompletionStage(f); + if (!createIncomplete) f.completeExceptionally(ex); + final CompletionStage g = d.exceptionallyComposeAsync(r); + if (createIncomplete) f.completeExceptionally(ex); + + checkCompletedExceptionally(f, ex); + checkCompletedWithWrappedException(g.toCompletableFuture(), r.ex); + r.assertInvoked(); + }} + + /** + * default-implemented exceptionallyComposeAsync result completes + * normally after normal completion of source + */ + public void testDefaultExceptionallyComposeAsyncExecutor_normalCompletion() { + for (boolean createIncomplete : new boolean[] { true, false }) + for (Integer v1 : new Integer[] { 1, null }) + { + final CompletableFuture f = new CompletableFuture<>(); + final ExceptionalCompletableFutureFunction r = + new ExceptionalCompletableFutureFunction(ExecutionMode.EXECUTOR); + final DelegatedCompletionStage d = + new DelegatedCompletionStage(f); + if (!createIncomplete) assertTrue(f.complete(v1)); + final CompletionStage g = d.exceptionallyComposeAsync(r, new ThreadExecutor()); + if (createIncomplete) assertTrue(f.complete(v1)); + + checkCompletedNormally(f, v1); + checkCompletedNormally(g.toCompletableFuture(), v1); + r.assertNotInvoked(); + }} + + /** + * default-implemented exceptionallyComposeAsync result completes + * normally after exceptional completion of source + */ + public void testDefaultExceptionallyComposeAsyncExecutor_exceptionalCompletion() { + for (boolean createIncomplete : new boolean[] { true, false }) + { + final CFException ex = new CFException(); + final ExceptionalCompletableFutureFunction r = + new ExceptionalCompletableFutureFunction(ExecutionMode.EXECUTOR); + final CompletableFuture f = new CompletableFuture<>(); + final DelegatedCompletionStage d = + new DelegatedCompletionStage(f); + if (!createIncomplete) f.completeExceptionally(ex); + final CompletionStage g = d.exceptionallyComposeAsync(r, new ThreadExecutor()); + if (createIncomplete) f.completeExceptionally(ex); + + checkCompletedExceptionally(f, ex); + checkCompletedNormally(g.toCompletableFuture(), r.value); + r.assertInvoked(); + }} + + /** + * default-implemented exceptionallyComposeAsync completes + * exceptionally on exception if action does + */ + public void testDefaultExceptionallyComposeAsyncExecutor_actionFailed() { + for (boolean createIncomplete : new boolean[] { true, false }) + { + final CFException ex = new CFException(); + final CompletableFuture f = new CompletableFuture<>(); + final FailingExceptionalCompletableFutureFunction r + = new FailingExceptionalCompletableFutureFunction(ExecutionMode.EXECUTOR); + final DelegatedCompletionStage d = + new DelegatedCompletionStage(f); + if (!createIncomplete) f.completeExceptionally(ex); + final CompletionStage g = d.exceptionallyComposeAsync(r, new ThreadExecutor()); + if (createIncomplete) f.completeExceptionally(ex); + + checkCompletedExceptionally(f, ex); + checkCompletedWithWrappedException(g.toCompletableFuture(), r.ex); + r.assertInvoked(); + }} + } diff --git a/test/jdk/java/util/concurrent/tck/CountedCompleterTest.java b/test/jdk/java/util/concurrent/tck/CountedCompleterTest.java --- a/test/jdk/java/util/concurrent/tck/CountedCompleterTest.java +++ b/test/jdk/java/util/concurrent/tck/CountedCompleterTest.java @@ -135,10 +135,14 @@ assertFalse(a.cancel(false)); assertFalse(a.cancel(true)); + + Object v1 = null, v2 = null; try { - assertNull(a.get()); - assertNull(a.get(randomTimeout(), randomTimeUnit())); + v1 = a.get(); + v2 = a.get(randomTimeout(), randomTimeUnit()); } catch (Throwable fail) { threadUnexpectedException(fail); } + assertNull(v1); + assertNull(v2); } void checkCancelled(CountedCompleter a) { diff --git a/test/jdk/java/util/concurrent/tck/DelayQueueTest.java b/test/jdk/java/util/concurrent/tck/DelayQueueTest.java --- a/test/jdk/java/util/concurrent/tck/DelayQueueTest.java +++ b/test/jdk/java/util/concurrent/tck/DelayQueueTest.java @@ -96,7 +96,7 @@ // suppress [overrides] javac warning public int hashCode() { return pseudodelay; } public long getDelay(TimeUnit ignore) { - return Integer.MIN_VALUE + pseudodelay; + return (long) Integer.MIN_VALUE + pseudodelay; } public String toString() { return String.valueOf(pseudodelay); diff --git a/test/jdk/java/util/concurrent/tck/ForkJoinPool8Test.java b/test/jdk/java/util/concurrent/tck/ForkJoinPool8Test.java --- a/test/jdk/java/util/concurrent/tck/ForkJoinPool8Test.java +++ b/test/jdk/java/util/concurrent/tck/ForkJoinPool8Test.java @@ -133,10 +133,14 @@ assertNull(a.join()); assertFalse(a.cancel(false)); assertFalse(a.cancel(true)); + + Object v1 = null, v2 = null; try { - assertNull(a.get()); - assertNull(a.get(randomTimeout(), randomTimeUnit())); + v1 = a.get(); + v2 = a.get(randomTimeout(), randomTimeUnit()); } catch (Throwable fail) { threadUnexpectedException(fail); } + assertNull(v1); + assertNull(v2); } void checkCancelled(ForkJoinTask a) { diff --git a/test/jdk/java/util/concurrent/tck/ForkJoinTask8Test.java b/test/jdk/java/util/concurrent/tck/ForkJoinTask8Test.java --- a/test/jdk/java/util/concurrent/tck/ForkJoinTask8Test.java +++ b/test/jdk/java/util/concurrent/tck/ForkJoinTask8Test.java @@ -140,13 +140,13 @@ checkCompletedNormally(a, null); } - void checkCompletedNormally(ForkJoinTask a, T expected) { + void checkCompletedNormally(ForkJoinTask a, T expectedValue) { assertTrue(a.isDone()); assertFalse(a.isCancelled()); assertTrue(a.isCompletedNormally()); assertFalse(a.isCompletedAbnormally()); assertNull(a.getException()); - assertSame(expected, a.getRawResult()); + assertSame(expectedValue, a.getRawResult()); if (a instanceof BinaryAsyncAction) assertEquals(COMPLETE_STATE, ((BinaryAsyncAction)a).getForkJoinTaskTag()); @@ -154,7 +154,7 @@ { Thread.currentThread().interrupt(); long startTime = System.nanoTime(); - assertSame(expected, a.join()); + assertSame(expectedValue, a.join()); assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); Thread.interrupted(); } @@ -169,10 +169,14 @@ assertFalse(a.cancel(false)); assertFalse(a.cancel(true)); + + T v1 = null, v2 = null; try { - assertSame(expected, a.get()); - assertSame(expected, a.get(randomTimeout(), randomTimeUnit())); + v1 = a.get(); + v2 = a.get(randomTimeout(), randomTimeUnit()); } catch (Throwable fail) { threadUnexpectedException(fail); } + assertSame(expectedValue, v1); + assertSame(expectedValue, v2); } void checkCompletedAbnormally(ForkJoinTask a, Throwable t) { diff --git a/test/jdk/java/util/concurrent/tck/ForkJoinTaskTest.java b/test/jdk/java/util/concurrent/tck/ForkJoinTaskTest.java --- a/test/jdk/java/util/concurrent/tck/ForkJoinTaskTest.java +++ b/test/jdk/java/util/concurrent/tck/ForkJoinTaskTest.java @@ -114,18 +114,18 @@ checkCompletedNormally(a, null); } - void checkCompletedNormally(ForkJoinTask a, T expected) { + void checkCompletedNormally(ForkJoinTask a, T expectedValue) { assertTrue(a.isDone()); assertFalse(a.isCancelled()); assertTrue(a.isCompletedNormally()); assertFalse(a.isCompletedAbnormally()); assertNull(a.getException()); - assertSame(expected, a.getRawResult()); + assertSame(expectedValue, a.getRawResult()); { Thread.currentThread().interrupt(); long startTime = System.nanoTime(); - assertSame(expected, a.join()); + assertSame(expectedValue, a.join()); assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); Thread.interrupted(); } @@ -140,10 +140,14 @@ assertFalse(a.cancel(false)); assertFalse(a.cancel(true)); + + T v1 = null, v2 = null; try { - assertSame(expected, a.get()); - assertSame(expected, a.get(randomTimeout(), randomTimeUnit())); + v1 = a.get(); + v2 = a.get(randomTimeout(), randomTimeUnit()); } catch (Throwable fail) { threadUnexpectedException(fail); } + assertSame(expectedValue, v1); + assertSame(expectedValue, v2); } void checkCancelled(ForkJoinTask a) { diff --git a/test/jdk/java/util/concurrent/tck/FutureTaskTest.java b/test/jdk/java/util/concurrent/tck/FutureTaskTest.java --- a/test/jdk/java/util/concurrent/tck/FutureTaskTest.java +++ b/test/jdk/java/util/concurrent/tck/FutureTaskTest.java @@ -87,8 +87,9 @@ pf.run(); pf.runAndReset(); assertEquals(savedRunCount, pf.runCount()); + Object r2 = null; try { - assertSame(r, f.get()); + r2 = f.get(); } catch (CancellationException t) { assertSame(exInfo, CancellationException.class); } catch (ExecutionException t) { @@ -96,6 +97,8 @@ } catch (Throwable t) { threadUnexpectedException(t); } + if (exInfo == null) + assertSame(r, r2); assertTrue(f.isDone()); } } @@ -128,14 +131,17 @@ } } - void checkCompletedNormally(Future f, T expected) { + void checkCompletedNormally(Future f, T expectedValue) { checkIsDone(f); assertFalse(f.isCancelled()); + T v1 = null, v2 = null; try { - assertSame(expected, f.get()); - assertSame(expected, f.get(randomTimeout(), randomTimeUnit())); + v1 = f.get(); + v2 = f.get(randomTimeout(), randomTimeUnit()); } catch (Throwable fail) { threadUnexpectedException(fail); } + assertSame(expectedValue, v1); + assertSame(expectedValue, v2); } void checkCancelled(Future f) { @@ -485,7 +491,7 @@ try { task.cancel(true); shouldThrow(); - } catch (SecurityException expected) {} + } catch (SecurityException success) {} // We failed to deliver the interrupt, but the world retains // its sanity, as if we had done task.cancel(false) diff --git a/test/jdk/java/util/concurrent/tck/JSR166TestCase.java b/test/jdk/java/util/concurrent/tck/JSR166TestCase.java --- a/test/jdk/java/util/concurrent/tck/JSR166TestCase.java +++ b/test/jdk/java/util/concurrent/tck/JSR166TestCase.java @@ -1415,9 +1415,11 @@ */ void checkTimedGet(Future f, T expectedValue, long timeoutMillis) { long startTime = System.nanoTime(); + T actual = null; try { - assertEquals(expectedValue, f.get(timeoutMillis, MILLISECONDS)); + actual = f.get(timeoutMillis, MILLISECONDS); } catch (Throwable fail) { threadUnexpectedException(fail); } + assertEquals(expectedValue, actual); if (millisElapsedSince(startTime) > timeoutMillis/2) throw new AssertionError("timed get did not return promptly"); } @@ -1596,13 +1598,15 @@ } public void await(CountDownLatch latch, long timeoutMillis) { + boolean timedOut = false; try { - if (!latch.await(timeoutMillis, MILLISECONDS)) - fail("timed out waiting for CountDownLatch for " - + (timeoutMillis/1000) + " sec"); + timedOut = !latch.await(timeoutMillis, MILLISECONDS); } catch (Throwable fail) { threadUnexpectedException(fail); } + if (timedOut) + fail("timed out waiting for CountDownLatch for " + + (timeoutMillis/1000) + " sec"); } public void await(CountDownLatch latch) { @@ -1610,13 +1614,15 @@ } public void await(Semaphore semaphore) { + boolean timedOut = false; try { - if (!semaphore.tryAcquire(LONG_DELAY_MS, MILLISECONDS)) - fail("timed out waiting for Semaphore for " - + (LONG_DELAY_MS/1000) + " sec"); + timedOut = !semaphore.tryAcquire(LONG_DELAY_MS, MILLISECONDS); } catch (Throwable fail) { threadUnexpectedException(fail); } + if (timedOut) + fail("timed out waiting for Semaphore for " + + (LONG_DELAY_MS/1000) + " sec"); } public void await(CyclicBarrier barrier) { @@ -1802,17 +1808,17 @@ @SuppressWarnings("unchecked") T serialClone(T o) { + T clone = null; try { ObjectInputStream ois = new ObjectInputStream (new ByteArrayInputStream(serialBytes(o))); - T clone = (T) ois.readObject(); - if (o == clone) assertImmutable(o); - assertSame(o.getClass(), clone.getClass()); - return clone; + clone = (T) ois.readObject(); } catch (Throwable fail) { threadUnexpectedException(fail); - return null; } + if (o == clone) assertImmutable(o); + else assertSame(o.getClass(), clone.getClass()); + return clone; } /** @@ -1831,7 +1837,7 @@ (new ByteArrayInputStream(bos.toByteArray())); T clone = (T) ois.readObject(); if (o == clone) assertImmutable(o); - assertSame(o.getClass(), clone.getClass()); + else assertSame(o.getClass(), clone.getClass()); return clone; } diff --git a/test/jdk/java/util/concurrent/tck/RecursiveActionTest.java b/test/jdk/java/util/concurrent/tck/RecursiveActionTest.java --- a/test/jdk/java/util/concurrent/tck/RecursiveActionTest.java +++ b/test/jdk/java/util/concurrent/tck/RecursiveActionTest.java @@ -123,10 +123,14 @@ assertNull(a.join()); assertFalse(a.cancel(false)); assertFalse(a.cancel(true)); + + Object v1 = null, v2 = null; try { - assertNull(a.get()); - assertNull(a.get(randomTimeout(), randomTimeUnit())); + v1 = a.get(); + v2 = a.get(randomTimeout(), randomTimeUnit()); } catch (Throwable fail) { threadUnexpectedException(fail); } + assertNull(v1); + assertNull(v2); } void checkCancelled(RecursiveAction a) { diff --git a/test/jdk/java/util/concurrent/tck/RecursiveTaskTest.java b/test/jdk/java/util/concurrent/tck/RecursiveTaskTest.java --- a/test/jdk/java/util/concurrent/tck/RecursiveTaskTest.java +++ b/test/jdk/java/util/concurrent/tck/RecursiveTaskTest.java @@ -109,29 +109,33 @@ } catch (Throwable fail) { threadUnexpectedException(fail); } } - void checkCompletedNormally(RecursiveTask a, T expected) { + void checkCompletedNormally(RecursiveTask a, T expectedValue) { assertTrue(a.isDone()); assertFalse(a.isCancelled()); assertTrue(a.isCompletedNormally()); assertFalse(a.isCompletedAbnormally()); assertNull(a.getException()); - assertSame(expected, a.getRawResult()); - assertSame(expected, a.join()); + assertSame(expectedValue, a.getRawResult()); + assertSame(expectedValue, a.join()); assertFalse(a.cancel(false)); assertFalse(a.cancel(true)); + + T v1 = null, v2 = null; try { - assertSame(expected, a.get()); - assertSame(expected, a.get(randomTimeout(), randomTimeUnit())); + v1 = a.get(); + v2 = a.get(randomTimeout(), randomTimeUnit()); } catch (Throwable fail) { threadUnexpectedException(fail); } + assertSame(expectedValue, v1); + assertSame(expectedValue, v2); } /** * Waits for the task to complete, and checks that when it does, * it will have an Integer result equals to the given int. */ - void checkCompletesNormally(RecursiveTask a, int expected) { + void checkCompletesNormally(RecursiveTask a, int expectedValue) { Integer r = a.join(); - assertEquals(expected, (int) r); + assertEquals(expectedValue, (int) r); checkCompletedNormally(a, r); } @@ -139,9 +143,9 @@ * Like checkCompletesNormally, but verifies that the task has * already completed. */ - void checkCompletedNormally(RecursiveTask a, int expected) { + void checkCompletedNormally(RecursiveTask a, int expectedValue) { Integer r = a.getRawResult(); - assertEquals(expected, (int) r); + assertEquals(expectedValue, (int) r); checkCompletedNormally(a, r); } diff --git a/test/jdk/java/util/concurrent/tck/ReentrantLockTest.java b/test/jdk/java/util/concurrent/tck/ReentrantLockTest.java --- a/test/jdk/java/util/concurrent/tck/ReentrantLockTest.java +++ b/test/jdk/java/util/concurrent/tck/ReentrantLockTest.java @@ -1187,7 +1187,7 @@ await(cond, awaitMethod); throw new AssertionError("should throw"); } - catch (IllegalMonitorStateException expected) {} + catch (IllegalMonitorStateException success) {} catch (Throwable fail) { threadUnexpectedException(fail); }}}; Thread rogueThread = new Thread(rogue, "rogue"); threads.add(rogueThread); diff --git a/test/jdk/java/util/concurrent/tck/SubmissionPublisherTest.java b/test/jdk/java/util/concurrent/tck/SubmissionPublisherTest.java --- a/test/jdk/java/util/concurrent/tck/SubmissionPublisherTest.java +++ b/test/jdk/java/util/concurrent/tck/SubmissionPublisherTest.java @@ -1029,7 +1029,9 @@ public void onComplete() {} } pub.subscribe(new Sub()); - CompletableFuture.runAsync(() -> pub.submit(Boolean.TRUE)); + checkTimedGet( + CompletableFuture.runAsync(() -> pub.submit(Boolean.TRUE)), + null); await(finished); } }