< prev index next >
test/jdk/java/util/concurrent/tck/CompletableFutureTest.java
Print this page
8210971: Add exception handling methods to CompletionStage and CompletableFuture
Reviewed-by: martin, chegar
@@ -84,29 +84,37 @@
void checkIncomplete(CompletableFuture<?> f) {
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();
}
catch (TimeoutException success) {}
catch (Throwable fail) { threadUnexpectedException(fail); }
}
- <T> void checkCompletedNormally(CompletableFuture<T> f, T value) {
- checkTimedGet(f, value);
+ <T> void checkCompletedNormally(CompletableFuture<T> 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());
assertTrue(f.toString().matches(".*\\[.*Completed normally.*\\]"));
}
@@ -568,13 +576,32 @@
{
CompletableFutureInc(ExecutionMode m) { super(m); }
public CompletableFuture<Integer> apply(Integer x) {
invoked();
value = x;
- CompletableFuture<Integer> f = new CompletableFuture<>();
- assertTrue(f.complete(inc(x)));
- return f;
+ return CompletableFuture.completedFuture(inc(x));
+ }
+ }
+
+ static class FailingExceptionalCompletableFutureFunction extends CheckedAction
+ implements Function<Throwable, CompletableFuture<Integer>>
+ {
+ final CFException ex;
+ FailingExceptionalCompletableFutureFunction(ExecutionMode m) { super(m); ex = new CFException(); }
+ public CompletableFuture<Integer> apply(Throwable x) {
+ invoked();
+ throw ex;
+ }
+ }
+
+ static class ExceptionalCompletableFutureFunction extends CheckedAction
+ implements Function<Throwable, CompletionStage<Integer>> {
+ final Integer value = 3;
+ ExceptionalCompletableFutureFunction(ExecutionMode m) { super(m); }
+ public CompletionStage<Integer> apply(Throwable x) {
+ invoked();
+ return CompletableFuture.completedFuture(value);
}
}
static class FailingCompletableFutureFunction extends CheckedIntegerAction
implements Function<Integer, CompletableFuture<Integer>>
@@ -689,12 +716,20 @@
(CompletableFuture<T> f,
CompletionStage<? extends T> g,
Function<? super T,U> a) {
return f.applyToEither(g, a);
}
+ public <T> CompletableFuture<T> exceptionally
+ (CompletableFuture<T> f,
+ Function<Throwable, ? extends T> fn) {
+ return f.exceptionally(fn);
+ }
+ public <T> CompletableFuture<T> exceptionallyCompose
+ (CompletableFuture<T> f, Function<Throwable, ? extends CompletionStage<T>> fn) {
+ return f.exceptionallyCompose(fn);
+ }
},
-
ASYNC {
public void checkExecutionMode() {
assertEquals(defaultExecutorIsCommonPool,
(ForkJoinPool.commonPool() == ForkJoinTask.getPool()));
}
@@ -763,10 +798,21 @@
(CompletableFuture<T> f,
CompletionStage<? extends T> g,
Function<? super T,U> a) {
return f.applyToEitherAsync(g, a);
}
+ public <T> CompletableFuture<T> exceptionally
+ (CompletableFuture<T> f,
+ Function<Throwable, ? extends T> fn) {
+ return f.exceptionallyAsync(fn);
+ }
+
+ public <T> CompletableFuture<T> exceptionallyCompose
+ (CompletableFuture<T> f, Function<Throwable, ? extends CompletionStage<T>> fn) {
+ return f.exceptionallyComposeAsync(fn);
+ }
+
},
EXECUTOR {
public void checkExecutionMode() {
assertTrue(ThreadExecutor.startedCurrentThread());
@@ -836,10 +882,20 @@
(CompletableFuture<T> f,
CompletionStage<? extends T> g,
Function<? super T,U> a) {
return f.applyToEitherAsync(g, a, new ThreadExecutor());
}
+ public <T> CompletableFuture<T> exceptionally
+ (CompletableFuture<T> f,
+ Function<Throwable, ? extends T> fn) {
+ return f.exceptionallyAsync(fn, new ThreadExecutor());
+ }
+ public <T> CompletableFuture<T> exceptionallyCompose
+ (CompletableFuture<T> f, Function<Throwable, ? extends CompletionStage<T>> fn) {
+ return f.exceptionallyComposeAsync(fn, new ThreadExecutor());
+ }
+
};
public abstract void checkExecutionMode();
public abstract CompletableFuture<Void> runAsync(Runnable a);
public abstract <U> CompletableFuture<U> supplyAsync(Supplier<U> a);
@@ -878,51 +934,56 @@
Consumer<? super T> a);
public abstract <T,U> CompletableFuture<U> applyToEither
(CompletableFuture<T> f,
CompletionStage<? extends T> g,
Function<? super T,U> a);
+ public abstract <T> CompletableFuture<T> exceptionally
+ (CompletableFuture<T> f,
+ Function<Throwable, ? extends T> fn);
+ public abstract <T> CompletableFuture<T> exceptionallyCompose
+ (CompletableFuture<T> f,
+ Function<Throwable, ? extends CompletionStage<T>> fn);
}
/**
* exceptionally action is not invoked when source completes
* 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<Integer> f = new CompletableFuture<>();
if (!createIncomplete) assertTrue(f.complete(v1));
- final CompletableFuture<Integer> g = f.exceptionally
- ((Throwable t) -> {
- a.getAndIncrement();
+ final CompletableFuture<Integer> g = m.exceptionally
+ (f, (Throwable t) -> {
threadFail("should not be called");
return null; // unreached
});
if (createIncomplete) assertTrue(f.complete(v1));
checkCompletedNormally(g, v1);
checkCompletedNormally(f, v1);
- assertEquals(0, a.get());
}}
/**
* exceptionally action completes with function value on source
* exception
*/
public void testExceptionally_exceptionalCompletion() {
+ 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 CFException ex = new CFException();
final CompletableFuture<Integer> f = new CompletableFuture<>();
if (!createIncomplete) f.completeExceptionally(ex);
- final CompletableFuture<Integer> g = f.exceptionally
- ((Throwable t) -> {
- ExecutionMode.SYNC.checkExecutionMode();
+ final CompletableFuture<Integer> g = m.exceptionally
+ (f, (Throwable t) -> {
+ m.checkExecutionMode();
threadAssertSame(t, ex);
a.getAndIncrement();
return v1;
});
if (createIncomplete) f.completeExceptionally(ex);
@@ -934,20 +995,21 @@
/**
* If an "exceptionally action" throws an exception, it completes
* 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);
final CFException ex1 = new CFException();
final CFException ex2 = new CFException();
final CompletableFuture<Integer> f = new CompletableFuture<>();
if (!createIncomplete) f.completeExceptionally(ex1);
- final CompletableFuture<Integer> g = f.exceptionally
- ((Throwable t) -> {
- ExecutionMode.SYNC.checkExecutionMode();
+ final CompletableFuture<Integer> g = m.exceptionally
+ (f, (Throwable t) -> {
+ m.checkExecutionMode();
threadAssertSame(t, ex1);
a.getAndIncrement();
throw ex2;
});
if (createIncomplete) f.completeExceptionally(ex1);
@@ -3114,10 +3176,125 @@
checkCompletedExceptionally(g, ex);
checkCompletedWithWrappedException(h, ex);
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<Integer> f = new CompletableFuture<>();
+ final ExceptionalCompletableFutureFunction r =
+ new ExceptionalCompletableFutureFunction(m);
+ if (!createIncomplete) assertTrue(f.complete(v1));
+ final CompletableFuture<Integer> 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<Integer> f = new CompletableFuture<>();
+ if (!createIncomplete) f.completeExceptionally(ex);
+ final CompletableFuture<Integer> 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<Integer> f = new CompletableFuture<>();
+ final FailingExceptionalCompletableFutureFunction r
+ = new FailingExceptionalCompletableFutureFunction(m);
+ if (!createIncomplete) f.completeExceptionally(ex);
+ final CompletableFuture<Integer> 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<Integer> f = new CompletableFuture<>();
+ final CompletableFuture<Integer> g = new CompletableFuture<>();
+ final CompletableFuture<Integer> 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
/**
* allOf(no component futures) returns a future completed normally
* with the value null
@@ -4525,6 +4702,431 @@
// static <U> boolean isDone2(CompletionStage<U> stage) {
// return stage.toCompletableFuture().copy().isDone();
// }
+ // For testing default implementations
+ // Only non-default interface methods defined.
+ static final class DelegatedCompletionStage<T> implements CompletionStage<T> {
+ final CompletableFuture<T> cf;
+ DelegatedCompletionStage(CompletableFuture<T> cf) { this.cf = cf; }
+ public CompletableFuture<T> toCompletableFuture() {
+ return cf; }
+ public CompletionStage<Void> thenRun
+ (Runnable action) {
+ return cf.thenRun(action); }
+ public CompletionStage<Void> thenRunAsync
+ (Runnable action) {
+ return cf.thenRunAsync(action); }
+ public CompletionStage<Void> thenRunAsync
+ (Runnable action,
+ Executor executor) {
+ return cf.thenRunAsync(action, executor); }
+ public CompletionStage<Void> thenAccept
+ (Consumer<? super T> action) {
+ return cf.thenAccept(action); }
+ public CompletionStage<Void> thenAcceptAsync
+ (Consumer<? super T> action) {
+ return cf.thenAcceptAsync(action); }
+ public CompletionStage<Void> thenAcceptAsync
+ (Consumer<? super T> action,
+ Executor executor) {
+ return cf.thenAcceptAsync(action, executor); }
+ public <U> CompletionStage<U> thenApply
+ (Function<? super T,? extends U> a) {
+ return cf.thenApply(a); }
+ public <U> CompletionStage<U> thenApplyAsync
+ (Function<? super T,? extends U> fn) {
+ return cf.thenApplyAsync(fn); }
+ public <U> CompletionStage<U> thenApplyAsync
+ (Function<? super T,? extends U> fn,
+ Executor executor) {
+ return cf.thenApplyAsync(fn, executor); }
+ public <U,V> CompletionStage<V> thenCombine
+ (CompletionStage<? extends U> other,
+ BiFunction<? super T,? super U,? extends V> fn) {
+ return cf.thenCombine(other, fn); }
+ public <U,V> CompletionStage<V> thenCombineAsync
+ (CompletionStage<? extends U> other,
+ BiFunction<? super T,? super U,? extends V> fn) {
+ return cf.thenCombineAsync(other, fn); }
+ public <U,V> CompletionStage<V> thenCombineAsync
+ (CompletionStage<? extends U> other,
+ BiFunction<? super T,? super U,? extends V> fn,
+ Executor executor) {
+ return cf.thenCombineAsync(other, fn, executor); }
+ public <U> CompletionStage<Void> thenAcceptBoth
+ (CompletionStage<? extends U> other,
+ BiConsumer<? super T, ? super U> action) {
+ return cf.thenAcceptBoth(other, action); }
+ public <U> CompletionStage<Void> thenAcceptBothAsync
+ (CompletionStage<? extends U> other,
+ BiConsumer<? super T, ? super U> action) {
+ return cf.thenAcceptBothAsync(other, action); }
+ public <U> CompletionStage<Void> thenAcceptBothAsync
+ (CompletionStage<? extends U> other,
+ BiConsumer<? super T, ? super U> action,
+ Executor executor) {
+ return cf.thenAcceptBothAsync(other, action, executor); }
+ public CompletionStage<Void> runAfterBoth
+ (CompletionStage<?> other,
+ Runnable action) {
+ return cf.runAfterBoth(other, action); }
+ public CompletionStage<Void> runAfterBothAsync
+ (CompletionStage<?> other,
+ Runnable action) {
+ return cf.runAfterBothAsync(other, action); }
+ public CompletionStage<Void> runAfterBothAsync
+ (CompletionStage<?> other,
+ Runnable action,
+ Executor executor) {
+ return cf.runAfterBothAsync(other, action, executor); }
+ public <U> CompletionStage<U> applyToEither
+ (CompletionStage<? extends T> other,
+ Function<? super T, U> fn) {
+ return cf.applyToEither(other, fn); }
+ public <U> CompletionStage<U> applyToEitherAsync
+ (CompletionStage<? extends T> other,
+ Function<? super T, U> fn) {
+ return cf.applyToEitherAsync(other, fn); }
+ public <U> CompletionStage<U> applyToEitherAsync
+ (CompletionStage<? extends T> other,
+ Function<? super T, U> fn,
+ Executor executor) {
+ return cf.applyToEitherAsync(other, fn, executor); }
+ public CompletionStage<Void> acceptEither
+ (CompletionStage<? extends T> other,
+ Consumer<? super T> action) {
+ return cf.acceptEither(other, action); }
+ public CompletionStage<Void> acceptEitherAsync
+ (CompletionStage<? extends T> other,
+ Consumer<? super T> action) {
+ return cf.acceptEitherAsync(other, action); }
+ public CompletionStage<Void> acceptEitherAsync
+ (CompletionStage<? extends T> other,
+ Consumer<? super T> action,
+ Executor executor) {
+ return cf.acceptEitherAsync(other, action, executor); }
+ public CompletionStage<Void> runAfterEither
+ (CompletionStage<?> other,
+ Runnable action) {
+ return cf.runAfterEither(other, action); }
+ public CompletionStage<Void> runAfterEitherAsync
+ (CompletionStage<?> other,
+ Runnable action) {
+ return cf.runAfterEitherAsync(other, action); }
+ public CompletionStage<Void> runAfterEitherAsync
+ (CompletionStage<?> other,
+ Runnable action,
+ Executor executor) {
+ return cf.runAfterEitherAsync(other, action, executor); }
+ public <U> CompletionStage<U> thenCompose
+ (Function<? super T, ? extends CompletionStage<U>> fn) {
+ return cf.thenCompose(fn); }
+ public <U> CompletionStage<U> thenComposeAsync
+ (Function<? super T, ? extends CompletionStage<U>> fn) {
+ return cf.thenComposeAsync(fn); }
+ public <U> CompletionStage<U> thenComposeAsync
+ (Function<? super T, ? extends CompletionStage<U>> fn,
+ Executor executor) {
+ return cf.thenComposeAsync(fn, executor); }
+ public <U> CompletionStage<U> handle
+ (BiFunction<? super T, Throwable, ? extends U> fn) {
+ return cf.handle(fn); }
+ public <U> CompletionStage<U> handleAsync
+ (BiFunction<? super T, Throwable, ? extends U> fn) {
+ return cf.handleAsync(fn); }
+ public <U> CompletionStage<U> handleAsync
+ (BiFunction<? super T, Throwable, ? extends U> fn,
+ Executor executor) {
+ return cf.handleAsync(fn, executor); }
+ public CompletionStage<T> whenComplete
+ (BiConsumer<? super T, ? super Throwable> action) {
+ return cf.whenComplete(action); }
+ public CompletionStage<T> whenCompleteAsync
+ (BiConsumer<? super T, ? super Throwable> action) {
+ return cf.whenCompleteAsync(action); }
+ public CompletionStage<T> whenCompleteAsync
+ (BiConsumer<? super T, ? super Throwable> action,
+ Executor executor) {
+ return cf.whenCompleteAsync(action, executor); }
+ public CompletionStage<T> exceptionally
+ (Function<Throwable, ? extends T> 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<Integer> f = new CompletableFuture<>();
+ final DelegatedCompletionStage<Integer> d =
+ new DelegatedCompletionStage<Integer>(f);
+ if (!createIncomplete) assertTrue(f.complete(v1));
+ final CompletionStage<Integer> 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<Integer> f = new CompletableFuture<>();
+ final DelegatedCompletionStage<Integer> d =
+ new DelegatedCompletionStage<Integer>(f);
+ if (!createIncomplete) f.completeExceptionally(ex);
+ final CompletionStage<Integer> 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<Integer> f = new CompletableFuture<>();
+ final DelegatedCompletionStage<Integer> d =
+ new DelegatedCompletionStage<Integer>(f);
+ if (!createIncomplete) f.completeExceptionally(ex1);
+ final CompletionStage<Integer> 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<Integer> f = new CompletableFuture<>();
+ final ExceptionalCompletableFutureFunction r =
+ new ExceptionalCompletableFutureFunction(ExecutionMode.SYNC);
+ final DelegatedCompletionStage<Integer> d =
+ new DelegatedCompletionStage<Integer>(f);
+ if (!createIncomplete) assertTrue(f.complete(v1));
+ final CompletionStage<Integer> 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<Integer> f = new CompletableFuture<>();
+ final DelegatedCompletionStage<Integer> d =
+ new DelegatedCompletionStage<Integer>(f);
+ if (!createIncomplete) f.completeExceptionally(ex);
+ final CompletionStage<Integer> 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<Integer> f = new CompletableFuture<>();
+ final FailingExceptionalCompletableFutureFunction r
+ = new FailingExceptionalCompletableFutureFunction(ExecutionMode.SYNC);
+ final DelegatedCompletionStage<Integer> d =
+ new DelegatedCompletionStage<Integer>(f);
+ if (!createIncomplete) f.completeExceptionally(ex);
+ final CompletionStage<Integer> 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<Integer> f = new CompletableFuture<>();
+ final ExceptionalCompletableFutureFunction r =
+ new ExceptionalCompletableFutureFunction(ExecutionMode.ASYNC);
+ final DelegatedCompletionStage<Integer> d =
+ new DelegatedCompletionStage<Integer>(f);
+ if (!createIncomplete) assertTrue(f.complete(v1));
+ final CompletionStage<Integer> 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<Integer> f = new CompletableFuture<>();
+ final DelegatedCompletionStage<Integer> d =
+ new DelegatedCompletionStage<Integer>(f);
+ if (!createIncomplete) f.completeExceptionally(ex);
+ final CompletionStage<Integer> 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<Integer> f = new CompletableFuture<>();
+ final FailingExceptionalCompletableFutureFunction r
+ = new FailingExceptionalCompletableFutureFunction(ExecutionMode.ASYNC);
+ final DelegatedCompletionStage<Integer> d =
+ new DelegatedCompletionStage<Integer>(f);
+ if (!createIncomplete) f.completeExceptionally(ex);
+ final CompletionStage<Integer> 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<Integer> f = new CompletableFuture<>();
+ final ExceptionalCompletableFutureFunction r =
+ new ExceptionalCompletableFutureFunction(ExecutionMode.EXECUTOR);
+ final DelegatedCompletionStage<Integer> d =
+ new DelegatedCompletionStage<Integer>(f);
+ if (!createIncomplete) assertTrue(f.complete(v1));
+ final CompletionStage<Integer> 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<Integer> f = new CompletableFuture<>();
+ final DelegatedCompletionStage<Integer> d =
+ new DelegatedCompletionStage<Integer>(f);
+ if (!createIncomplete) f.completeExceptionally(ex);
+ final CompletionStage<Integer> 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<Integer> f = new CompletableFuture<>();
+ final FailingExceptionalCompletableFutureFunction r
+ = new FailingExceptionalCompletableFutureFunction(ExecutionMode.EXECUTOR);
+ final DelegatedCompletionStage<Integer> d =
+ new DelegatedCompletionStage<Integer>(f);
+ if (!createIncomplete) f.completeExceptionally(ex);
+ final CompletionStage<Integer> g = d.exceptionallyComposeAsync(r, new ThreadExecutor());
+ if (createIncomplete) f.completeExceptionally(ex);
+
+ checkCompletedExceptionally(f, ex);
+ checkCompletedWithWrappedException(g.toCompletableFuture(), r.ex);
+ r.assertInvoked();
+ }}
+
}
< prev index next >