ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/CompletableFutureTest.java
(Generate patch)

Comparing jsr166/src/test/tck/CompletableFutureTest.java (file contents):
Revision 1.1 by jsr166, Wed Feb 6 19:55:06 2013 UTC vs.
Revision 1.154 by jsr166, Sun Jun 26 19:27:42 2016 UTC

# Line 1 | Line 1
1   /*
2 < * Written by Doug Lea with assistance from members of JCP JSR-166
3 < * Expert Group and released to the public domain, as explained at
2 > * Written by Doug Lea and Martin Buchholz with assistance from
3 > * members of JCP JSR-166 Expert Group and released to the public
4 > * domain, as explained at
5   * http://creativecommons.org/publicdomain/zero/1.0/
5 * Other contributors include Andrew Wright, Jeffrey Hayes,
6 * Pat Fisher, Mike Judd.
6   */
7  
8 < import junit.framework.*;
8 > import static java.util.concurrent.TimeUnit.MILLISECONDS;
9 > import static java.util.concurrent.TimeUnit.SECONDS;
10 > import static java.util.concurrent.CompletableFuture.completedFuture;
11 > import static java.util.concurrent.CompletableFuture.failedFuture;
12 >
13 > import java.lang.reflect.Method;
14 > import java.lang.reflect.Modifier;
15 >
16 > import java.util.stream.Collectors;
17 > import java.util.stream.Stream;
18 >
19 > import java.util.ArrayList;
20 > import java.util.Arrays;
21 > import java.util.List;
22 > import java.util.Objects;
23 > import java.util.Set;
24   import java.util.concurrent.Callable;
25   import java.util.concurrent.CancellationException;
12 import java.util.concurrent.CountDownLatch;
13 import java.util.concurrent.ExecutionException;
14 import java.util.concurrent.Future;
26   import java.util.concurrent.CompletableFuture;
27 + import java.util.concurrent.CompletionException;
28 + import java.util.concurrent.CompletionStage;
29 + import java.util.concurrent.ExecutionException;
30 + import java.util.concurrent.Executor;
31 + import java.util.concurrent.ForkJoinPool;
32 + import java.util.concurrent.ForkJoinTask;
33 + import java.util.concurrent.RejectedExecutionException;
34   import java.util.concurrent.TimeoutException;
35 + import java.util.concurrent.TimeUnit;
36   import java.util.concurrent.atomic.AtomicInteger;
37 < import static java.util.concurrent.TimeUnit.MILLISECONDS;
38 < import static java.util.concurrent.TimeUnit.SECONDS;
39 < import java.util.*;
37 > import java.util.concurrent.atomic.AtomicReference;
38 > import java.util.function.BiConsumer;
39 > import java.util.function.BiFunction;
40 > import java.util.function.Consumer;
41 > import java.util.function.Function;
42 > import java.util.function.Predicate;
43 > import java.util.function.Supplier;
44 >
45 > import junit.framework.AssertionFailedError;
46 > import junit.framework.Test;
47 > import junit.framework.TestSuite;
48  
49   public class CompletableFutureTest extends JSR166TestCase {
50  
51      public static void main(String[] args) {
52 <        junit.textui.TestRunner.run(suite());
52 >        main(suite(), args);
53      }
54      public static Test suite() {
55          return new TestSuite(CompletableFutureTest.class);
56      }
57  
58 +    static class CFException extends RuntimeException {}
59 +
60 +    void checkIncomplete(CompletableFuture<?> f) {
61 +        assertFalse(f.isDone());
62 +        assertFalse(f.isCancelled());
63 +        assertTrue(f.toString().contains("Not completed"));
64 +        try {
65 +            assertNull(f.getNow(null));
66 +        } catch (Throwable fail) { threadUnexpectedException(fail); }
67 +        try {
68 +            f.get(0L, SECONDS);
69 +            shouldThrow();
70 +        }
71 +        catch (TimeoutException success) {}
72 +        catch (Throwable fail) { threadUnexpectedException(fail); }
73 +    }
74 +
75 +    <T> void checkCompletedNormally(CompletableFuture<T> f, T value) {
76 +        checkTimedGet(f, value);
77 +
78 +        try {
79 +            assertEquals(value, f.join());
80 +        } catch (Throwable fail) { threadUnexpectedException(fail); }
81 +        try {
82 +            assertEquals(value, f.getNow(null));
83 +        } catch (Throwable fail) { threadUnexpectedException(fail); }
84 +        try {
85 +            assertEquals(value, f.get());
86 +        } catch (Throwable fail) { threadUnexpectedException(fail); }
87 +        assertTrue(f.isDone());
88 +        assertFalse(f.isCancelled());
89 +        assertFalse(f.isCompletedExceptionally());
90 +        assertTrue(f.toString().contains("[Completed normally]"));
91 +    }
92 +
93 +    /**
94 +     * Returns the "raw" internal exceptional completion of f,
95 +     * without any additional wrapping with CompletionException.
96 +     */
97 +    <U> Throwable exceptionalCompletion(CompletableFuture<U> f) {
98 +        // handle (and whenComplete) can distinguish between "direct"
99 +        // and "wrapped" exceptional completion
100 +        return f.handle((U u, Throwable t) -> t).join();
101 +    }
102 +
103 +    void checkCompletedExceptionally(CompletableFuture<?> f,
104 +                                     boolean wrapped,
105 +                                     Consumer<Throwable> checker) {
106 +        Throwable cause = exceptionalCompletion(f);
107 +        if (wrapped) {
108 +            assertTrue(cause instanceof CompletionException);
109 +            cause = cause.getCause();
110 +        }
111 +        checker.accept(cause);
112 +
113 +        long startTime = System.nanoTime();
114 +        try {
115 +            f.get(LONG_DELAY_MS, MILLISECONDS);
116 +            shouldThrow();
117 +        } catch (ExecutionException success) {
118 +            assertSame(cause, success.getCause());
119 +        } catch (Throwable fail) { threadUnexpectedException(fail); }
120 +        assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS / 2);
121 +
122 +        try {
123 +            f.join();
124 +            shouldThrow();
125 +        } catch (CompletionException success) {
126 +            assertSame(cause, success.getCause());
127 +        } catch (Throwable fail) { threadUnexpectedException(fail); }
128 +
129 +        try {
130 +            f.getNow(null);
131 +            shouldThrow();
132 +        } catch (CompletionException success) {
133 +            assertSame(cause, success.getCause());
134 +        } catch (Throwable fail) { threadUnexpectedException(fail); }
135 +
136 +        try {
137 +            f.get();
138 +            shouldThrow();
139 +        } catch (ExecutionException success) {
140 +            assertSame(cause, success.getCause());
141 +        } catch (Throwable fail) { threadUnexpectedException(fail); }
142 +
143 +        assertFalse(f.isCancelled());
144 +        assertTrue(f.isDone());
145 +        assertTrue(f.isCompletedExceptionally());
146 +        assertTrue(f.toString().contains("[Completed exceptionally]"));
147 +    }
148 +
149 +    void checkCompletedWithWrappedCFException(CompletableFuture<?> f) {
150 +        checkCompletedExceptionally(f, true,
151 +            (t) -> assertTrue(t instanceof CFException));
152 +    }
153 +
154 +    void checkCompletedWithWrappedCancellationException(CompletableFuture<?> f) {
155 +        checkCompletedExceptionally(f, true,
156 +            (t) -> assertTrue(t instanceof CancellationException));
157 +    }
158 +
159 +    void checkCompletedWithTimeoutException(CompletableFuture<?> f) {
160 +        checkCompletedExceptionally(f, false,
161 +            (t) -> assertTrue(t instanceof TimeoutException));
162 +    }
163 +
164 +    void checkCompletedWithWrappedException(CompletableFuture<?> f,
165 +                                            Throwable ex) {
166 +        checkCompletedExceptionally(f, true, (t) -> assertSame(t, ex));
167 +    }
168 +
169 +    void checkCompletedExceptionally(CompletableFuture<?> f, Throwable ex) {
170 +        checkCompletedExceptionally(f, false, (t) -> assertSame(t, ex));
171 +    }
172 +
173 +    void checkCancelled(CompletableFuture<?> f) {
174 +        long startTime = System.nanoTime();
175 +        try {
176 +            f.get(LONG_DELAY_MS, MILLISECONDS);
177 +            shouldThrow();
178 +        } catch (CancellationException success) {
179 +        } catch (Throwable fail) { threadUnexpectedException(fail); }
180 +        assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS / 2);
181 +
182 +        try {
183 +            f.join();
184 +            shouldThrow();
185 +        } catch (CancellationException success) {}
186 +        try {
187 +            f.getNow(null);
188 +            shouldThrow();
189 +        } catch (CancellationException success) {}
190 +        try {
191 +            f.get();
192 +            shouldThrow();
193 +        } catch (CancellationException success) {
194 +        } catch (Throwable fail) { threadUnexpectedException(fail); }
195 +
196 +        assertTrue(exceptionalCompletion(f) instanceof CancellationException);
197 +
198 +        assertTrue(f.isDone());
199 +        assertTrue(f.isCompletedExceptionally());
200 +        assertTrue(f.isCancelled());
201 +        assertTrue(f.toString().contains("[Completed exceptionally]"));
202 +    }
203 +
204 +    /**
205 +     * A newly constructed CompletableFuture is incomplete, as indicated
206 +     * by methods isDone, isCancelled, and getNow
207 +     */
208 +    public void testConstructor() {
209 +        CompletableFuture<Integer> f = new CompletableFuture<>();
210 +        checkIncomplete(f);
211 +    }
212 +
213 +    /**
214 +     * complete completes normally, as indicated by methods isDone,
215 +     * isCancelled, join, get, and getNow
216 +     */
217 +    public void testComplete() {
218 +        for (Integer v1 : new Integer[] { 1, null })
219 +    {
220 +        CompletableFuture<Integer> f = new CompletableFuture<>();
221 +        checkIncomplete(f);
222 +        assertTrue(f.complete(v1));
223 +        assertFalse(f.complete(v1));
224 +        checkCompletedNormally(f, v1);
225 +    }}
226 +
227 +    /**
228 +     * completeExceptionally completes exceptionally, as indicated by
229 +     * methods isDone, isCancelled, join, get, and getNow
230 +     */
231 +    public void testCompleteExceptionally() {
232 +        CompletableFuture<Integer> f = new CompletableFuture<>();
233 +        CFException ex = new CFException();
234 +        checkIncomplete(f);
235 +        f.completeExceptionally(ex);
236 +        checkCompletedExceptionally(f, ex);
237 +    }
238 +
239 +    /**
240 +     * cancel completes exceptionally and reports cancelled, as indicated by
241 +     * methods isDone, isCancelled, join, get, and getNow
242 +     */
243 +    public void testCancel() {
244 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
245 +    {
246 +        CompletableFuture<Integer> f = new CompletableFuture<>();
247 +        checkIncomplete(f);
248 +        assertTrue(f.cancel(mayInterruptIfRunning));
249 +        assertTrue(f.cancel(mayInterruptIfRunning));
250 +        assertTrue(f.cancel(!mayInterruptIfRunning));
251 +        checkCancelled(f);
252 +    }}
253 +
254 +    /**
255 +     * obtrudeValue forces completion with given value
256 +     */
257 +    public void testObtrudeValue() {
258 +        CompletableFuture<Integer> f = new CompletableFuture<>();
259 +        checkIncomplete(f);
260 +        assertTrue(f.complete(one));
261 +        checkCompletedNormally(f, one);
262 +        f.obtrudeValue(three);
263 +        checkCompletedNormally(f, three);
264 +        f.obtrudeValue(two);
265 +        checkCompletedNormally(f, two);
266 +        f = new CompletableFuture<>();
267 +        f.obtrudeValue(three);
268 +        checkCompletedNormally(f, three);
269 +        f.obtrudeValue(null);
270 +        checkCompletedNormally(f, null);
271 +        f = new CompletableFuture<>();
272 +        f.completeExceptionally(new CFException());
273 +        f.obtrudeValue(four);
274 +        checkCompletedNormally(f, four);
275 +    }
276 +
277 +    /**
278 +     * obtrudeException forces completion with given exception
279 +     */
280 +    public void testObtrudeException() {
281 +        for (Integer v1 : new Integer[] { 1, null })
282 +    {
283 +        CFException ex;
284 +        CompletableFuture<Integer> f;
285 +
286 +        f = new CompletableFuture<>();
287 +        assertTrue(f.complete(v1));
288 +        for (int i = 0; i < 2; i++) {
289 +            f.obtrudeException(ex = new CFException());
290 +            checkCompletedExceptionally(f, ex);
291 +        }
292 +
293 +        f = new CompletableFuture<>();
294 +        for (int i = 0; i < 2; i++) {
295 +            f.obtrudeException(ex = new CFException());
296 +            checkCompletedExceptionally(f, ex);
297 +        }
298 +
299 +        f = new CompletableFuture<>();
300 +        f.completeExceptionally(ex = new CFException());
301 +        f.obtrudeValue(v1);
302 +        checkCompletedNormally(f, v1);
303 +        f.obtrudeException(ex = new CFException());
304 +        checkCompletedExceptionally(f, ex);
305 +        f.completeExceptionally(new CFException());
306 +        checkCompletedExceptionally(f, ex);
307 +        assertFalse(f.complete(v1));
308 +        checkCompletedExceptionally(f, ex);
309 +    }}
310 +
311 +    /**
312 +     * getNumberOfDependents returns number of dependent tasks
313 +     */
314 +    public void testGetNumberOfDependents() {
315 +        for (ExecutionMode m : ExecutionMode.values())
316 +        for (Integer v1 : new Integer[] { 1, null })
317 +    {
318 +        CompletableFuture<Integer> f = new CompletableFuture<>();
319 +        assertEquals(0, f.getNumberOfDependents());
320 +        final CompletableFuture<Void> g = m.thenRun(f, new Noop(m));
321 +        assertEquals(1, f.getNumberOfDependents());
322 +        assertEquals(0, g.getNumberOfDependents());
323 +        final CompletableFuture<Void> h = m.thenRun(f, new Noop(m));
324 +        assertEquals(2, f.getNumberOfDependents());
325 +        assertEquals(0, h.getNumberOfDependents());
326 +        assertTrue(f.complete(v1));
327 +        checkCompletedNormally(g, null);
328 +        checkCompletedNormally(h, null);
329 +        assertEquals(0, f.getNumberOfDependents());
330 +        assertEquals(0, g.getNumberOfDependents());
331 +        assertEquals(0, h.getNumberOfDependents());
332 +    }}
333 +
334 +    /**
335 +     * toString indicates current completion state
336 +     */
337      public void testToString() {
338          CompletableFuture<String> f;
339 <        assertTrue(new CompletableFuture<String>().toString()
34 <                   .contains("[Not completed]"));
339 >
340          f = new CompletableFuture<String>();
341 <        f.complete("foo");
341 >        assertTrue(f.toString().contains("[Not completed]"));
342 >
343 >        assertTrue(f.complete("foo"));
344          assertTrue(f.toString().contains("[Completed normally]"));
345 +
346          f = new CompletableFuture<String>();
347 <        f.completeExceptionally(new IndexOutOfBoundsException());
347 >        assertTrue(f.completeExceptionally(new IndexOutOfBoundsException()));
348          assertTrue(f.toString().contains("[Completed exceptionally]"));
349 +
350 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false }) {
351 +            f = new CompletableFuture<String>();
352 +            assertTrue(f.cancel(mayInterruptIfRunning));
353 +            assertTrue(f.toString().contains("[Completed exceptionally]"));
354 +        }
355 +    }
356 +
357 +    /**
358 +     * completedFuture returns a completed CompletableFuture with given value
359 +     */
360 +    public void testCompletedFuture() {
361 +        CompletableFuture<String> f = CompletableFuture.completedFuture("test");
362 +        checkCompletedNormally(f, "test");
363      }
364 +
365 +    abstract class CheckedAction {
366 +        int invocationCount = 0;
367 +        final ExecutionMode m;
368 +        CheckedAction(ExecutionMode m) { this.m = m; }
369 +        void invoked() {
370 +            m.checkExecutionMode();
371 +            assertEquals(0, invocationCount++);
372 +        }
373 +        void assertNotInvoked() { assertEquals(0, invocationCount); }
374 +        void assertInvoked() { assertEquals(1, invocationCount); }
375 +    }
376 +
377 +    abstract class CheckedIntegerAction extends CheckedAction {
378 +        Integer value;
379 +        CheckedIntegerAction(ExecutionMode m) { super(m); }
380 +        void assertValue(Integer expected) {
381 +            assertInvoked();
382 +            assertEquals(expected, value);
383 +        }
384 +    }
385 +
386 +    class IntegerSupplier extends CheckedAction
387 +        implements Supplier<Integer>
388 +    {
389 +        final Integer value;
390 +        IntegerSupplier(ExecutionMode m, Integer value) {
391 +            super(m);
392 +            this.value = value;
393 +        }
394 +        public Integer get() {
395 +            invoked();
396 +            return value;
397 +        }
398 +    }
399 +
400 +    // A function that handles and produces null values as well.
401 +    static Integer inc(Integer x) {
402 +        return (x == null) ? null : x + 1;
403 +    }
404 +
405 +    class NoopConsumer extends CheckedIntegerAction
406 +        implements Consumer<Integer>
407 +    {
408 +        NoopConsumer(ExecutionMode m) { super(m); }
409 +        public void accept(Integer x) {
410 +            invoked();
411 +            value = x;
412 +        }
413 +    }
414 +
415 +    class IncFunction extends CheckedIntegerAction
416 +        implements Function<Integer,Integer>
417 +    {
418 +        IncFunction(ExecutionMode m) { super(m); }
419 +        public Integer apply(Integer x) {
420 +            invoked();
421 +            return value = inc(x);
422 +        }
423 +    }
424 +
425 +    // Choose non-commutative actions for better coverage
426 +    // A non-commutative function that handles and produces null values as well.
427 +    static Integer subtract(Integer x, Integer y) {
428 +        return (x == null && y == null) ? null :
429 +            ((x == null) ? 42 : x.intValue())
430 +            - ((y == null) ? 99 : y.intValue());
431 +    }
432 +
433 +    class SubtractAction extends CheckedIntegerAction
434 +        implements BiConsumer<Integer, Integer>
435 +    {
436 +        SubtractAction(ExecutionMode m) { super(m); }
437 +        public void accept(Integer x, Integer y) {
438 +            invoked();
439 +            value = subtract(x, y);
440 +        }
441 +    }
442 +
443 +    class SubtractFunction extends CheckedIntegerAction
444 +        implements BiFunction<Integer, Integer, Integer>
445 +    {
446 +        SubtractFunction(ExecutionMode m) { super(m); }
447 +        public Integer apply(Integer x, Integer y) {
448 +            invoked();
449 +            return value = subtract(x, y);
450 +        }
451 +    }
452 +
453 +    class Noop extends CheckedAction implements Runnable {
454 +        Noop(ExecutionMode m) { super(m); }
455 +        public void run() {
456 +            invoked();
457 +        }
458 +    }
459 +
460 +    class FailingSupplier extends CheckedAction
461 +        implements Supplier<Integer>
462 +    {
463 +        final CFException ex;
464 +        FailingSupplier(ExecutionMode m) { super(m); ex = new CFException(); }
465 +        public Integer get() {
466 +            invoked();
467 +            throw ex;
468 +        }
469 +    }
470 +
471 +    class FailingConsumer extends CheckedIntegerAction
472 +        implements Consumer<Integer>
473 +    {
474 +        final CFException ex;
475 +        FailingConsumer(ExecutionMode m) { super(m); ex = new CFException(); }
476 +        public void accept(Integer x) {
477 +            invoked();
478 +            value = x;
479 +            throw ex;
480 +        }
481 +    }
482 +
483 +    class FailingBiConsumer extends CheckedIntegerAction
484 +        implements BiConsumer<Integer, Integer>
485 +    {
486 +        final CFException ex;
487 +        FailingBiConsumer(ExecutionMode m) { super(m); ex = new CFException(); }
488 +        public void accept(Integer x, Integer y) {
489 +            invoked();
490 +            value = subtract(x, y);
491 +            throw ex;
492 +        }
493 +    }
494 +
495 +    class FailingFunction extends CheckedIntegerAction
496 +        implements Function<Integer, Integer>
497 +    {
498 +        final CFException ex;
499 +        FailingFunction(ExecutionMode m) { super(m); ex = new CFException(); }
500 +        public Integer apply(Integer x) {
501 +            invoked();
502 +            value = x;
503 +            throw ex;
504 +        }
505 +    }
506 +
507 +    class FailingBiFunction extends CheckedIntegerAction
508 +        implements BiFunction<Integer, Integer, Integer>
509 +    {
510 +        final CFException ex;
511 +        FailingBiFunction(ExecutionMode m) { super(m); ex = new CFException(); }
512 +        public Integer apply(Integer x, Integer y) {
513 +            invoked();
514 +            value = subtract(x, y);
515 +            throw ex;
516 +        }
517 +    }
518 +
519 +    class FailingRunnable extends CheckedAction implements Runnable {
520 +        final CFException ex;
521 +        FailingRunnable(ExecutionMode m) { super(m); ex = new CFException(); }
522 +        public void run() {
523 +            invoked();
524 +            throw ex;
525 +        }
526 +    }
527 +
528 +    class CompletableFutureInc extends CheckedIntegerAction
529 +        implements Function<Integer, CompletableFuture<Integer>>
530 +    {
531 +        CompletableFutureInc(ExecutionMode m) { super(m); }
532 +        public CompletableFuture<Integer> apply(Integer x) {
533 +            invoked();
534 +            value = x;
535 +            CompletableFuture<Integer> f = new CompletableFuture<>();
536 +            assertTrue(f.complete(inc(x)));
537 +            return f;
538 +        }
539 +    }
540 +
541 +    class FailingCompletableFutureFunction extends CheckedIntegerAction
542 +        implements Function<Integer, CompletableFuture<Integer>>
543 +    {
544 +        final CFException ex;
545 +        FailingCompletableFutureFunction(ExecutionMode m) { super(m); ex = new CFException(); }
546 +        public CompletableFuture<Integer> apply(Integer x) {
547 +            invoked();
548 +            value = x;
549 +            throw ex;
550 +        }
551 +    }
552 +
553 +    // Used for explicit executor tests
554 +    static final class ThreadExecutor implements Executor {
555 +        final AtomicInteger count = new AtomicInteger(0);
556 +        static final ThreadGroup tg = new ThreadGroup("ThreadExecutor");
557 +        static boolean startedCurrentThread() {
558 +            return Thread.currentThread().getThreadGroup() == tg;
559 +        }
560 +
561 +        public void execute(Runnable r) {
562 +            count.getAndIncrement();
563 +            new Thread(tg, r).start();
564 +        }
565 +    }
566 +
567 +    static final boolean defaultExecutorIsCommonPool
568 +        = ForkJoinPool.getCommonPoolParallelism() > 1;
569 +
570 +    /**
571 +     * Permits the testing of parallel code for the 3 different
572 +     * execution modes without copy/pasting all the test methods.
573 +     */
574 +    enum ExecutionMode {
575 +        SYNC {
576 +            public void checkExecutionMode() {
577 +                assertFalse(ThreadExecutor.startedCurrentThread());
578 +                assertNull(ForkJoinTask.getPool());
579 +            }
580 +            public CompletableFuture<Void> runAsync(Runnable a) {
581 +                throw new UnsupportedOperationException();
582 +            }
583 +            public <U> CompletableFuture<U> supplyAsync(Supplier<U> a) {
584 +                throw new UnsupportedOperationException();
585 +            }
586 +            public <T> CompletableFuture<Void> thenRun
587 +                (CompletableFuture<T> f, Runnable a) {
588 +                return f.thenRun(a);
589 +            }
590 +            public <T> CompletableFuture<Void> thenAccept
591 +                (CompletableFuture<T> f, Consumer<? super T> a) {
592 +                return f.thenAccept(a);
593 +            }
594 +            public <T,U> CompletableFuture<U> thenApply
595 +                (CompletableFuture<T> f, Function<? super T,U> a) {
596 +                return f.thenApply(a);
597 +            }
598 +            public <T,U> CompletableFuture<U> thenCompose
599 +                (CompletableFuture<T> f,
600 +                 Function<? super T,? extends CompletionStage<U>> a) {
601 +                return f.thenCompose(a);
602 +            }
603 +            public <T,U> CompletableFuture<U> handle
604 +                (CompletableFuture<T> f,
605 +                 BiFunction<? super T,Throwable,? extends U> a) {
606 +                return f.handle(a);
607 +            }
608 +            public <T> CompletableFuture<T> whenComplete
609 +                (CompletableFuture<T> f,
610 +                 BiConsumer<? super T,? super Throwable> a) {
611 +                return f.whenComplete(a);
612 +            }
613 +            public <T,U> CompletableFuture<Void> runAfterBoth
614 +                (CompletableFuture<T> f, CompletableFuture<U> g, Runnable a) {
615 +                return f.runAfterBoth(g, a);
616 +            }
617 +            public <T,U> CompletableFuture<Void> thenAcceptBoth
618 +                (CompletableFuture<T> f,
619 +                 CompletionStage<? extends U> g,
620 +                 BiConsumer<? super T,? super U> a) {
621 +                return f.thenAcceptBoth(g, a);
622 +            }
623 +            public <T,U,V> CompletableFuture<V> thenCombine
624 +                (CompletableFuture<T> f,
625 +                 CompletionStage<? extends U> g,
626 +                 BiFunction<? super T,? super U,? extends V> a) {
627 +                return f.thenCombine(g, a);
628 +            }
629 +            public <T> CompletableFuture<Void> runAfterEither
630 +                (CompletableFuture<T> f,
631 +                 CompletionStage<?> g,
632 +                 java.lang.Runnable a) {
633 +                return f.runAfterEither(g, a);
634 +            }
635 +            public <T> CompletableFuture<Void> acceptEither
636 +                (CompletableFuture<T> f,
637 +                 CompletionStage<? extends T> g,
638 +                 Consumer<? super T> a) {
639 +                return f.acceptEither(g, a);
640 +            }
641 +            public <T,U> CompletableFuture<U> applyToEither
642 +                (CompletableFuture<T> f,
643 +                 CompletionStage<? extends T> g,
644 +                 Function<? super T,U> a) {
645 +                return f.applyToEither(g, a);
646 +            }
647 +        },
648 +
649 +        ASYNC {
650 +            public void checkExecutionMode() {
651 +                assertEquals(defaultExecutorIsCommonPool,
652 +                             (ForkJoinPool.commonPool() == ForkJoinTask.getPool()));
653 +            }
654 +            public CompletableFuture<Void> runAsync(Runnable a) {
655 +                return CompletableFuture.runAsync(a);
656 +            }
657 +            public <U> CompletableFuture<U> supplyAsync(Supplier<U> a) {
658 +                return CompletableFuture.supplyAsync(a);
659 +            }
660 +            public <T> CompletableFuture<Void> thenRun
661 +                (CompletableFuture<T> f, Runnable a) {
662 +                return f.thenRunAsync(a);
663 +            }
664 +            public <T> CompletableFuture<Void> thenAccept
665 +                (CompletableFuture<T> f, Consumer<? super T> a) {
666 +                return f.thenAcceptAsync(a);
667 +            }
668 +            public <T,U> CompletableFuture<U> thenApply
669 +                (CompletableFuture<T> f, Function<? super T,U> a) {
670 +                return f.thenApplyAsync(a);
671 +            }
672 +            public <T,U> CompletableFuture<U> thenCompose
673 +                (CompletableFuture<T> f,
674 +                 Function<? super T,? extends CompletionStage<U>> a) {
675 +                return f.thenComposeAsync(a);
676 +            }
677 +            public <T,U> CompletableFuture<U> handle
678 +                (CompletableFuture<T> f,
679 +                 BiFunction<? super T,Throwable,? extends U> a) {
680 +                return f.handleAsync(a);
681 +            }
682 +            public <T> CompletableFuture<T> whenComplete
683 +                (CompletableFuture<T> f,
684 +                 BiConsumer<? super T,? super Throwable> a) {
685 +                return f.whenCompleteAsync(a);
686 +            }
687 +            public <T,U> CompletableFuture<Void> runAfterBoth
688 +                (CompletableFuture<T> f, CompletableFuture<U> g, Runnable a) {
689 +                return f.runAfterBothAsync(g, a);
690 +            }
691 +            public <T,U> CompletableFuture<Void> thenAcceptBoth
692 +                (CompletableFuture<T> f,
693 +                 CompletionStage<? extends U> g,
694 +                 BiConsumer<? super T,? super U> a) {
695 +                return f.thenAcceptBothAsync(g, a);
696 +            }
697 +            public <T,U,V> CompletableFuture<V> thenCombine
698 +                (CompletableFuture<T> f,
699 +                 CompletionStage<? extends U> g,
700 +                 BiFunction<? super T,? super U,? extends V> a) {
701 +                return f.thenCombineAsync(g, a);
702 +            }
703 +            public <T> CompletableFuture<Void> runAfterEither
704 +                (CompletableFuture<T> f,
705 +                 CompletionStage<?> g,
706 +                 java.lang.Runnable a) {
707 +                return f.runAfterEitherAsync(g, a);
708 +            }
709 +            public <T> CompletableFuture<Void> acceptEither
710 +                (CompletableFuture<T> f,
711 +                 CompletionStage<? extends T> g,
712 +                 Consumer<? super T> a) {
713 +                return f.acceptEitherAsync(g, a);
714 +            }
715 +            public <T,U> CompletableFuture<U> applyToEither
716 +                (CompletableFuture<T> f,
717 +                 CompletionStage<? extends T> g,
718 +                 Function<? super T,U> a) {
719 +                return f.applyToEitherAsync(g, a);
720 +            }
721 +        },
722 +
723 +        EXECUTOR {
724 +            public void checkExecutionMode() {
725 +                assertTrue(ThreadExecutor.startedCurrentThread());
726 +            }
727 +            public CompletableFuture<Void> runAsync(Runnable a) {
728 +                return CompletableFuture.runAsync(a, new ThreadExecutor());
729 +            }
730 +            public <U> CompletableFuture<U> supplyAsync(Supplier<U> a) {
731 +                return CompletableFuture.supplyAsync(a, new ThreadExecutor());
732 +            }
733 +            public <T> CompletableFuture<Void> thenRun
734 +                (CompletableFuture<T> f, Runnable a) {
735 +                return f.thenRunAsync(a, new ThreadExecutor());
736 +            }
737 +            public <T> CompletableFuture<Void> thenAccept
738 +                (CompletableFuture<T> f, Consumer<? super T> a) {
739 +                return f.thenAcceptAsync(a, new ThreadExecutor());
740 +            }
741 +            public <T,U> CompletableFuture<U> thenApply
742 +                (CompletableFuture<T> f, Function<? super T,U> a) {
743 +                return f.thenApplyAsync(a, new ThreadExecutor());
744 +            }
745 +            public <T,U> CompletableFuture<U> thenCompose
746 +                (CompletableFuture<T> f,
747 +                 Function<? super T,? extends CompletionStage<U>> a) {
748 +                return f.thenComposeAsync(a, new ThreadExecutor());
749 +            }
750 +            public <T,U> CompletableFuture<U> handle
751 +                (CompletableFuture<T> f,
752 +                 BiFunction<? super T,Throwable,? extends U> a) {
753 +                return f.handleAsync(a, new ThreadExecutor());
754 +            }
755 +            public <T> CompletableFuture<T> whenComplete
756 +                (CompletableFuture<T> f,
757 +                 BiConsumer<? super T,? super Throwable> a) {
758 +                return f.whenCompleteAsync(a, new ThreadExecutor());
759 +            }
760 +            public <T,U> CompletableFuture<Void> runAfterBoth
761 +                (CompletableFuture<T> f, CompletableFuture<U> g, Runnable a) {
762 +                return f.runAfterBothAsync(g, a, new ThreadExecutor());
763 +            }
764 +            public <T,U> CompletableFuture<Void> thenAcceptBoth
765 +                (CompletableFuture<T> f,
766 +                 CompletionStage<? extends U> g,
767 +                 BiConsumer<? super T,? super U> a) {
768 +                return f.thenAcceptBothAsync(g, a, new ThreadExecutor());
769 +            }
770 +            public <T,U,V> CompletableFuture<V> thenCombine
771 +                (CompletableFuture<T> f,
772 +                 CompletionStage<? extends U> g,
773 +                 BiFunction<? super T,? super U,? extends V> a) {
774 +                return f.thenCombineAsync(g, a, new ThreadExecutor());
775 +            }
776 +            public <T> CompletableFuture<Void> runAfterEither
777 +                (CompletableFuture<T> f,
778 +                 CompletionStage<?> g,
779 +                 java.lang.Runnable a) {
780 +                return f.runAfterEitherAsync(g, a, new ThreadExecutor());
781 +            }
782 +            public <T> CompletableFuture<Void> acceptEither
783 +                (CompletableFuture<T> f,
784 +                 CompletionStage<? extends T> g,
785 +                 Consumer<? super T> a) {
786 +                return f.acceptEitherAsync(g, a, new ThreadExecutor());
787 +            }
788 +            public <T,U> CompletableFuture<U> applyToEither
789 +                (CompletableFuture<T> f,
790 +                 CompletionStage<? extends T> g,
791 +                 Function<? super T,U> a) {
792 +                return f.applyToEitherAsync(g, a, new ThreadExecutor());
793 +            }
794 +        };
795 +
796 +        public abstract void checkExecutionMode();
797 +        public abstract CompletableFuture<Void> runAsync(Runnable a);
798 +        public abstract <U> CompletableFuture<U> supplyAsync(Supplier<U> a);
799 +        public abstract <T> CompletableFuture<Void> thenRun
800 +            (CompletableFuture<T> f, Runnable a);
801 +        public abstract <T> CompletableFuture<Void> thenAccept
802 +            (CompletableFuture<T> f, Consumer<? super T> a);
803 +        public abstract <T,U> CompletableFuture<U> thenApply
804 +            (CompletableFuture<T> f, Function<? super T,U> a);
805 +        public abstract <T,U> CompletableFuture<U> thenCompose
806 +            (CompletableFuture<T> f,
807 +             Function<? super T,? extends CompletionStage<U>> a);
808 +        public abstract <T,U> CompletableFuture<U> handle
809 +            (CompletableFuture<T> f,
810 +             BiFunction<? super T,Throwable,? extends U> a);
811 +        public abstract <T> CompletableFuture<T> whenComplete
812 +            (CompletableFuture<T> f,
813 +             BiConsumer<? super T,? super Throwable> a);
814 +        public abstract <T,U> CompletableFuture<Void> runAfterBoth
815 +            (CompletableFuture<T> f, CompletableFuture<U> g, Runnable a);
816 +        public abstract <T,U> CompletableFuture<Void> thenAcceptBoth
817 +            (CompletableFuture<T> f,
818 +             CompletionStage<? extends U> g,
819 +             BiConsumer<? super T,? super U> a);
820 +        public abstract <T,U,V> CompletableFuture<V> thenCombine
821 +            (CompletableFuture<T> f,
822 +             CompletionStage<? extends U> g,
823 +             BiFunction<? super T,? super U,? extends V> a);
824 +        public abstract <T> CompletableFuture<Void> runAfterEither
825 +            (CompletableFuture<T> f,
826 +             CompletionStage<?> g,
827 +             java.lang.Runnable a);
828 +        public abstract <T> CompletableFuture<Void> acceptEither
829 +            (CompletableFuture<T> f,
830 +             CompletionStage<? extends T> g,
831 +             Consumer<? super T> a);
832 +        public abstract <T,U> CompletableFuture<U> applyToEither
833 +            (CompletableFuture<T> f,
834 +             CompletionStage<? extends T> g,
835 +             Function<? super T,U> a);
836 +    }
837 +
838 +    /**
839 +     * exceptionally action is not invoked when source completes
840 +     * normally, and source result is propagated
841 +     */
842 +    public void testExceptionally_normalCompletion() {
843 +        for (boolean createIncomplete : new boolean[] { true, false })
844 +        for (Integer v1 : new Integer[] { 1, null })
845 +    {
846 +        final AtomicInteger a = new AtomicInteger(0);
847 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
848 +        if (!createIncomplete) assertTrue(f.complete(v1));
849 +        final CompletableFuture<Integer> g = f.exceptionally
850 +            ((Throwable t) -> {
851 +                a.getAndIncrement();
852 +                threadFail("should not be called");
853 +                return null;            // unreached
854 +            });
855 +        if (createIncomplete) assertTrue(f.complete(v1));
856 +
857 +        checkCompletedNormally(g, v1);
858 +        checkCompletedNormally(f, v1);
859 +        assertEquals(0, a.get());
860 +    }}
861 +
862 +    /**
863 +     * exceptionally action completes with function value on source
864 +     * exception
865 +     */
866 +    public void testExceptionally_exceptionalCompletion() {
867 +        for (boolean createIncomplete : new boolean[] { true, false })
868 +        for (Integer v1 : new Integer[] { 1, null })
869 +    {
870 +        final AtomicInteger a = new AtomicInteger(0);
871 +        final CFException ex = new CFException();
872 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
873 +        if (!createIncomplete) f.completeExceptionally(ex);
874 +        final CompletableFuture<Integer> g = f.exceptionally
875 +            ((Throwable t) -> {
876 +                ExecutionMode.SYNC.checkExecutionMode();
877 +                threadAssertSame(t, ex);
878 +                a.getAndIncrement();
879 +                return v1;
880 +            });
881 +        if (createIncomplete) f.completeExceptionally(ex);
882 +
883 +        checkCompletedNormally(g, v1);
884 +        assertEquals(1, a.get());
885 +    }}
886 +
887 +    /**
888 +     * If an "exceptionally action" throws an exception, it completes
889 +     * exceptionally with that exception
890 +     */
891 +    public void testExceptionally_exceptionalCompletionActionFailed() {
892 +        for (boolean createIncomplete : new boolean[] { true, false })
893 +    {
894 +        final AtomicInteger a = new AtomicInteger(0);
895 +        final CFException ex1 = new CFException();
896 +        final CFException ex2 = new CFException();
897 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
898 +        if (!createIncomplete) f.completeExceptionally(ex1);
899 +        final CompletableFuture<Integer> g = f.exceptionally
900 +            ((Throwable t) -> {
901 +                ExecutionMode.SYNC.checkExecutionMode();
902 +                threadAssertSame(t, ex1);
903 +                a.getAndIncrement();
904 +                throw ex2;
905 +            });
906 +        if (createIncomplete) f.completeExceptionally(ex1);
907 +
908 +        checkCompletedWithWrappedException(g, ex2);
909 +        checkCompletedExceptionally(f, ex1);
910 +        assertEquals(1, a.get());
911 +    }}
912 +
913 +    /**
914 +     * whenComplete action executes on normal completion, propagating
915 +     * source result.
916 +     */
917 +    public void testWhenComplete_normalCompletion() {
918 +        for (ExecutionMode m : ExecutionMode.values())
919 +        for (boolean createIncomplete : new boolean[] { true, false })
920 +        for (Integer v1 : new Integer[] { 1, null })
921 +    {
922 +        final AtomicInteger a = new AtomicInteger(0);
923 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
924 +        if (!createIncomplete) assertTrue(f.complete(v1));
925 +        final CompletableFuture<Integer> g = m.whenComplete
926 +            (f,
927 +             (Integer result, Throwable t) -> {
928 +                m.checkExecutionMode();
929 +                threadAssertSame(result, v1);
930 +                threadAssertNull(t);
931 +                a.getAndIncrement();
932 +            });
933 +        if (createIncomplete) assertTrue(f.complete(v1));
934 +
935 +        checkCompletedNormally(g, v1);
936 +        checkCompletedNormally(f, v1);
937 +        assertEquals(1, a.get());
938 +    }}
939 +
940 +    /**
941 +     * whenComplete action executes on exceptional completion, propagating
942 +     * source result.
943 +     */
944 +    public void testWhenComplete_exceptionalCompletion() {
945 +        for (ExecutionMode m : ExecutionMode.values())
946 +        for (boolean createIncomplete : new boolean[] { true, false })
947 +    {
948 +        final AtomicInteger a = new AtomicInteger(0);
949 +        final CFException ex = new CFException();
950 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
951 +        if (!createIncomplete) f.completeExceptionally(ex);
952 +        final CompletableFuture<Integer> g = m.whenComplete
953 +            (f,
954 +             (Integer result, Throwable t) -> {
955 +                m.checkExecutionMode();
956 +                threadAssertNull(result);
957 +                threadAssertSame(t, ex);
958 +                a.getAndIncrement();
959 +            });
960 +        if (createIncomplete) f.completeExceptionally(ex);
961 +
962 +        checkCompletedWithWrappedException(g, ex);
963 +        checkCompletedExceptionally(f, ex);
964 +        assertEquals(1, a.get());
965 +    }}
966 +
967 +    /**
968 +     * whenComplete action executes on cancelled source, propagating
969 +     * CancellationException.
970 +     */
971 +    public void testWhenComplete_sourceCancelled() {
972 +        for (ExecutionMode m : ExecutionMode.values())
973 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
974 +        for (boolean createIncomplete : new boolean[] { true, false })
975 +    {
976 +        final AtomicInteger a = new AtomicInteger(0);
977 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
978 +        if (!createIncomplete) assertTrue(f.cancel(mayInterruptIfRunning));
979 +        final CompletableFuture<Integer> g = m.whenComplete
980 +            (f,
981 +             (Integer result, Throwable t) -> {
982 +                m.checkExecutionMode();
983 +                threadAssertNull(result);
984 +                threadAssertTrue(t instanceof CancellationException);
985 +                a.getAndIncrement();
986 +            });
987 +        if (createIncomplete) assertTrue(f.cancel(mayInterruptIfRunning));
988 +
989 +        checkCompletedWithWrappedCancellationException(g);
990 +        checkCancelled(f);
991 +        assertEquals(1, a.get());
992 +    }}
993 +
994 +    /**
995 +     * If a whenComplete action throws an exception when triggered by
996 +     * a normal completion, it completes exceptionally
997 +     */
998 +    public void testWhenComplete_sourceCompletedNormallyActionFailed() {
999 +        for (boolean createIncomplete : new boolean[] { true, false })
1000 +        for (ExecutionMode m : ExecutionMode.values())
1001 +        for (Integer v1 : new Integer[] { 1, null })
1002 +    {
1003 +        final AtomicInteger a = new AtomicInteger(0);
1004 +        final CFException ex = new CFException();
1005 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1006 +        if (!createIncomplete) assertTrue(f.complete(v1));
1007 +        final CompletableFuture<Integer> g = m.whenComplete
1008 +            (f,
1009 +             (Integer result, Throwable t) -> {
1010 +                m.checkExecutionMode();
1011 +                threadAssertSame(result, v1);
1012 +                threadAssertNull(t);
1013 +                a.getAndIncrement();
1014 +                throw ex;
1015 +            });
1016 +        if (createIncomplete) assertTrue(f.complete(v1));
1017 +
1018 +        checkCompletedWithWrappedException(g, ex);
1019 +        checkCompletedNormally(f, v1);
1020 +        assertEquals(1, a.get());
1021 +    }}
1022 +
1023 +    /**
1024 +     * If a whenComplete action throws an exception when triggered by
1025 +     * a source completion that also throws an exception, the source
1026 +     * exception takes precedence (unlike handle)
1027 +     */
1028 +    public void testWhenComplete_sourceFailedActionFailed() {
1029 +        for (boolean createIncomplete : new boolean[] { true, false })
1030 +        for (ExecutionMode m : ExecutionMode.values())
1031 +    {
1032 +        final AtomicInteger a = new AtomicInteger(0);
1033 +        final CFException ex1 = new CFException();
1034 +        final CFException ex2 = new CFException();
1035 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1036 +
1037 +        if (!createIncomplete) f.completeExceptionally(ex1);
1038 +        final CompletableFuture<Integer> g = m.whenComplete
1039 +            (f,
1040 +             (Integer result, Throwable t) -> {
1041 +                m.checkExecutionMode();
1042 +                threadAssertSame(t, ex1);
1043 +                threadAssertNull(result);
1044 +                a.getAndIncrement();
1045 +                throw ex2;
1046 +            });
1047 +        if (createIncomplete) f.completeExceptionally(ex1);
1048 +
1049 +        checkCompletedWithWrappedException(g, ex1);
1050 +        checkCompletedExceptionally(f, ex1);
1051 +        if (testImplementationDetails) {
1052 +            assertEquals(1, ex1.getSuppressed().length);
1053 +            assertSame(ex2, ex1.getSuppressed()[0]);
1054 +        }
1055 +        assertEquals(1, a.get());
1056 +    }}
1057 +
1058 +    /**
1059 +     * handle action completes normally with function value on normal
1060 +     * completion of source
1061 +     */
1062 +    public void testHandle_normalCompletion() {
1063 +        for (ExecutionMode m : ExecutionMode.values())
1064 +        for (boolean createIncomplete : new boolean[] { true, false })
1065 +        for (Integer v1 : new Integer[] { 1, null })
1066 +    {
1067 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1068 +        final AtomicInteger a = new AtomicInteger(0);
1069 +        if (!createIncomplete) assertTrue(f.complete(v1));
1070 +        final CompletableFuture<Integer> g = m.handle
1071 +            (f,
1072 +             (Integer result, Throwable t) -> {
1073 +                m.checkExecutionMode();
1074 +                threadAssertSame(result, v1);
1075 +                threadAssertNull(t);
1076 +                a.getAndIncrement();
1077 +                return inc(v1);
1078 +            });
1079 +        if (createIncomplete) assertTrue(f.complete(v1));
1080 +
1081 +        checkCompletedNormally(g, inc(v1));
1082 +        checkCompletedNormally(f, v1);
1083 +        assertEquals(1, a.get());
1084 +    }}
1085 +
1086 +    /**
1087 +     * handle action completes normally with function value on
1088 +     * exceptional completion of source
1089 +     */
1090 +    public void testHandle_exceptionalCompletion() {
1091 +        for (ExecutionMode m : ExecutionMode.values())
1092 +        for (boolean createIncomplete : new boolean[] { true, false })
1093 +        for (Integer v1 : new Integer[] { 1, null })
1094 +    {
1095 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1096 +        final AtomicInteger a = new AtomicInteger(0);
1097 +        final CFException ex = new CFException();
1098 +        if (!createIncomplete) f.completeExceptionally(ex);
1099 +        final CompletableFuture<Integer> g = m.handle
1100 +            (f,
1101 +             (Integer result, Throwable t) -> {
1102 +                m.checkExecutionMode();
1103 +                threadAssertNull(result);
1104 +                threadAssertSame(t, ex);
1105 +                a.getAndIncrement();
1106 +                return v1;
1107 +            });
1108 +        if (createIncomplete) f.completeExceptionally(ex);
1109 +
1110 +        checkCompletedNormally(g, v1);
1111 +        checkCompletedExceptionally(f, ex);
1112 +        assertEquals(1, a.get());
1113 +    }}
1114 +
1115 +    /**
1116 +     * handle action completes normally with function value on
1117 +     * cancelled source
1118 +     */
1119 +    public void testHandle_sourceCancelled() {
1120 +        for (ExecutionMode m : ExecutionMode.values())
1121 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
1122 +        for (boolean createIncomplete : new boolean[] { true, false })
1123 +        for (Integer v1 : new Integer[] { 1, null })
1124 +    {
1125 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1126 +        final AtomicInteger a = new AtomicInteger(0);
1127 +        if (!createIncomplete) assertTrue(f.cancel(mayInterruptIfRunning));
1128 +        final CompletableFuture<Integer> g = m.handle
1129 +            (f,
1130 +             (Integer result, Throwable t) -> {
1131 +                m.checkExecutionMode();
1132 +                threadAssertNull(result);
1133 +                threadAssertTrue(t instanceof CancellationException);
1134 +                a.getAndIncrement();
1135 +                return v1;
1136 +            });
1137 +        if (createIncomplete) assertTrue(f.cancel(mayInterruptIfRunning));
1138 +
1139 +        checkCompletedNormally(g, v1);
1140 +        checkCancelled(f);
1141 +        assertEquals(1, a.get());
1142 +    }}
1143 +
1144 +    /**
1145 +     * If a "handle action" throws an exception when triggered by
1146 +     * a normal completion, it completes exceptionally
1147 +     */
1148 +    public void testHandle_sourceCompletedNormallyActionFailed() {
1149 +        for (ExecutionMode m : ExecutionMode.values())
1150 +        for (boolean createIncomplete : new boolean[] { true, false })
1151 +        for (Integer v1 : new Integer[] { 1, null })
1152 +    {
1153 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1154 +        final AtomicInteger a = new AtomicInteger(0);
1155 +        final CFException ex = new CFException();
1156 +        if (!createIncomplete) assertTrue(f.complete(v1));
1157 +        final CompletableFuture<Integer> g = m.handle
1158 +            (f,
1159 +             (Integer result, Throwable t) -> {
1160 +                m.checkExecutionMode();
1161 +                threadAssertSame(result, v1);
1162 +                threadAssertNull(t);
1163 +                a.getAndIncrement();
1164 +                throw ex;
1165 +            });
1166 +        if (createIncomplete) assertTrue(f.complete(v1));
1167 +
1168 +        checkCompletedWithWrappedException(g, ex);
1169 +        checkCompletedNormally(f, v1);
1170 +        assertEquals(1, a.get());
1171 +    }}
1172 +
1173 +    /**
1174 +     * If a "handle action" throws an exception when triggered by
1175 +     * a source completion that also throws an exception, the action
1176 +     * exception takes precedence (unlike whenComplete)
1177 +     */
1178 +    public void testHandle_sourceFailedActionFailed() {
1179 +        for (boolean createIncomplete : new boolean[] { true, false })
1180 +        for (ExecutionMode m : ExecutionMode.values())
1181 +    {
1182 +        final AtomicInteger a = new AtomicInteger(0);
1183 +        final CFException ex1 = new CFException();
1184 +        final CFException ex2 = new CFException();
1185 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1186 +
1187 +        if (!createIncomplete) f.completeExceptionally(ex1);
1188 +        final CompletableFuture<Integer> g = m.handle
1189 +            (f,
1190 +             (Integer result, Throwable t) -> {
1191 +                m.checkExecutionMode();
1192 +                threadAssertNull(result);
1193 +                threadAssertSame(ex1, t);
1194 +                a.getAndIncrement();
1195 +                throw ex2;
1196 +            });
1197 +        if (createIncomplete) f.completeExceptionally(ex1);
1198 +
1199 +        checkCompletedWithWrappedException(g, ex2);
1200 +        checkCompletedExceptionally(f, ex1);
1201 +        assertEquals(1, a.get());
1202 +    }}
1203 +
1204 +    /**
1205 +     * runAsync completes after running Runnable
1206 +     */
1207 +    public void testRunAsync_normalCompletion() {
1208 +        ExecutionMode[] executionModes = {
1209 +            ExecutionMode.ASYNC,
1210 +            ExecutionMode.EXECUTOR,
1211 +        };
1212 +        for (ExecutionMode m : executionModes)
1213 +    {
1214 +        final Noop r = new Noop(m);
1215 +        final CompletableFuture<Void> f = m.runAsync(r);
1216 +        assertNull(f.join());
1217 +        checkCompletedNormally(f, null);
1218 +        r.assertInvoked();
1219 +    }}
1220 +
1221 +    /**
1222 +     * failing runAsync completes exceptionally after running Runnable
1223 +     */
1224 +    public void testRunAsync_exceptionalCompletion() {
1225 +        ExecutionMode[] executionModes = {
1226 +            ExecutionMode.ASYNC,
1227 +            ExecutionMode.EXECUTOR,
1228 +        };
1229 +        for (ExecutionMode m : executionModes)
1230 +    {
1231 +        final FailingRunnable r = new FailingRunnable(m);
1232 +        final CompletableFuture<Void> f = m.runAsync(r);
1233 +        checkCompletedWithWrappedException(f, r.ex);
1234 +        r.assertInvoked();
1235 +    }}
1236 +
1237 +    /**
1238 +     * supplyAsync completes with result of supplier
1239 +     */
1240 +    public void testSupplyAsync_normalCompletion() {
1241 +        ExecutionMode[] executionModes = {
1242 +            ExecutionMode.ASYNC,
1243 +            ExecutionMode.EXECUTOR,
1244 +        };
1245 +        for (ExecutionMode m : executionModes)
1246 +        for (Integer v1 : new Integer[] { 1, null })
1247 +    {
1248 +        final IntegerSupplier r = new IntegerSupplier(m, v1);
1249 +        final CompletableFuture<Integer> f = m.supplyAsync(r);
1250 +        assertSame(v1, f.join());
1251 +        checkCompletedNormally(f, v1);
1252 +        r.assertInvoked();
1253 +    }}
1254 +
1255 +    /**
1256 +     * Failing supplyAsync completes exceptionally
1257 +     */
1258 +    public void testSupplyAsync_exceptionalCompletion() {
1259 +        ExecutionMode[] executionModes = {
1260 +            ExecutionMode.ASYNC,
1261 +            ExecutionMode.EXECUTOR,
1262 +        };
1263 +        for (ExecutionMode m : executionModes)
1264 +    {
1265 +        FailingSupplier r = new FailingSupplier(m);
1266 +        CompletableFuture<Integer> f = m.supplyAsync(r);
1267 +        checkCompletedWithWrappedException(f, r.ex);
1268 +        r.assertInvoked();
1269 +    }}
1270 +
1271 +    // seq completion methods
1272 +
1273 +    /**
1274 +     * thenRun result completes normally after normal completion of source
1275 +     */
1276 +    public void testThenRun_normalCompletion() {
1277 +        for (ExecutionMode m : ExecutionMode.values())
1278 +        for (Integer v1 : new Integer[] { 1, null })
1279 +    {
1280 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1281 +        final Noop[] rs = new Noop[6];
1282 +        for (int i = 0; i < rs.length; i++) rs[i] = new Noop(m);
1283 +
1284 +        final CompletableFuture<Void> h0 = m.thenRun(f, rs[0]);
1285 +        final CompletableFuture<Void> h1 = m.runAfterBoth(f, f, rs[1]);
1286 +        final CompletableFuture<Void> h2 = m.runAfterEither(f, f, rs[2]);
1287 +        checkIncomplete(h0);
1288 +        checkIncomplete(h1);
1289 +        checkIncomplete(h2);
1290 +        assertTrue(f.complete(v1));
1291 +        final CompletableFuture<Void> h3 = m.thenRun(f, rs[3]);
1292 +        final CompletableFuture<Void> h4 = m.runAfterBoth(f, f, rs[4]);
1293 +        final CompletableFuture<Void> h5 = m.runAfterEither(f, f, rs[5]);
1294 +
1295 +        checkCompletedNormally(h0, null);
1296 +        checkCompletedNormally(h1, null);
1297 +        checkCompletedNormally(h2, null);
1298 +        checkCompletedNormally(h3, null);
1299 +        checkCompletedNormally(h4, null);
1300 +        checkCompletedNormally(h5, null);
1301 +        checkCompletedNormally(f, v1);
1302 +        for (Noop r : rs) r.assertInvoked();
1303 +    }}
1304 +
1305 +    /**
1306 +     * thenRun result completes exceptionally after exceptional
1307 +     * completion of source
1308 +     */
1309 +    public void testThenRun_exceptionalCompletion() {
1310 +        for (ExecutionMode m : ExecutionMode.values())
1311 +    {
1312 +        final CFException ex = new CFException();
1313 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1314 +        final Noop[] rs = new Noop[6];
1315 +        for (int i = 0; i < rs.length; i++) rs[i] = new Noop(m);
1316 +
1317 +        final CompletableFuture<Void> h0 = m.thenRun(f, rs[0]);
1318 +        final CompletableFuture<Void> h1 = m.runAfterBoth(f, f, rs[1]);
1319 +        final CompletableFuture<Void> h2 = m.runAfterEither(f, f, rs[2]);
1320 +        checkIncomplete(h0);
1321 +        checkIncomplete(h1);
1322 +        checkIncomplete(h2);
1323 +        assertTrue(f.completeExceptionally(ex));
1324 +        final CompletableFuture<Void> h3 = m.thenRun(f, rs[3]);
1325 +        final CompletableFuture<Void> h4 = m.runAfterBoth(f, f, rs[4]);
1326 +        final CompletableFuture<Void> h5 = m.runAfterEither(f, f, rs[5]);
1327 +
1328 +        checkCompletedWithWrappedException(h0, ex);
1329 +        checkCompletedWithWrappedException(h1, ex);
1330 +        checkCompletedWithWrappedException(h2, ex);
1331 +        checkCompletedWithWrappedException(h3, ex);
1332 +        checkCompletedWithWrappedException(h4, ex);
1333 +        checkCompletedWithWrappedException(h5, ex);
1334 +        checkCompletedExceptionally(f, ex);
1335 +        for (Noop r : rs) r.assertNotInvoked();
1336 +    }}
1337 +
1338 +    /**
1339 +     * thenRun result completes exceptionally if source cancelled
1340 +     */
1341 +    public void testThenRun_sourceCancelled() {
1342 +        for (ExecutionMode m : ExecutionMode.values())
1343 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
1344 +    {
1345 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1346 +        final Noop[] rs = new Noop[6];
1347 +        for (int i = 0; i < rs.length; i++) rs[i] = new Noop(m);
1348 +
1349 +        final CompletableFuture<Void> h0 = m.thenRun(f, rs[0]);
1350 +        final CompletableFuture<Void> h1 = m.runAfterBoth(f, f, rs[1]);
1351 +        final CompletableFuture<Void> h2 = m.runAfterEither(f, f, rs[2]);
1352 +        checkIncomplete(h0);
1353 +        checkIncomplete(h1);
1354 +        checkIncomplete(h2);
1355 +        assertTrue(f.cancel(mayInterruptIfRunning));
1356 +        final CompletableFuture<Void> h3 = m.thenRun(f, rs[3]);
1357 +        final CompletableFuture<Void> h4 = m.runAfterBoth(f, f, rs[4]);
1358 +        final CompletableFuture<Void> h5 = m.runAfterEither(f, f, rs[5]);
1359 +
1360 +        checkCompletedWithWrappedCancellationException(h0);
1361 +        checkCompletedWithWrappedCancellationException(h1);
1362 +        checkCompletedWithWrappedCancellationException(h2);
1363 +        checkCompletedWithWrappedCancellationException(h3);
1364 +        checkCompletedWithWrappedCancellationException(h4);
1365 +        checkCompletedWithWrappedCancellationException(h5);
1366 +        checkCancelled(f);
1367 +        for (Noop r : rs) r.assertNotInvoked();
1368 +    }}
1369 +
1370 +    /**
1371 +     * thenRun result completes exceptionally if action does
1372 +     */
1373 +    public void testThenRun_actionFailed() {
1374 +        for (ExecutionMode m : ExecutionMode.values())
1375 +        for (Integer v1 : new Integer[] { 1, null })
1376 +    {
1377 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1378 +        final FailingRunnable[] rs = new FailingRunnable[6];
1379 +        for (int i = 0; i < rs.length; i++) rs[i] = new FailingRunnable(m);
1380 +
1381 +        final CompletableFuture<Void> h0 = m.thenRun(f, rs[0]);
1382 +        final CompletableFuture<Void> h1 = m.runAfterBoth(f, f, rs[1]);
1383 +        final CompletableFuture<Void> h2 = m.runAfterEither(f, f, rs[2]);
1384 +        assertTrue(f.complete(v1));
1385 +        final CompletableFuture<Void> h3 = m.thenRun(f, rs[3]);
1386 +        final CompletableFuture<Void> h4 = m.runAfterBoth(f, f, rs[4]);
1387 +        final CompletableFuture<Void> h5 = m.runAfterEither(f, f, rs[5]);
1388 +
1389 +        checkCompletedWithWrappedException(h0, rs[0].ex);
1390 +        checkCompletedWithWrappedException(h1, rs[1].ex);
1391 +        checkCompletedWithWrappedException(h2, rs[2].ex);
1392 +        checkCompletedWithWrappedException(h3, rs[3].ex);
1393 +        checkCompletedWithWrappedException(h4, rs[4].ex);
1394 +        checkCompletedWithWrappedException(h5, rs[5].ex);
1395 +        checkCompletedNormally(f, v1);
1396 +    }}
1397 +
1398 +    /**
1399 +     * thenApply result completes normally after normal completion of source
1400 +     */
1401 +    public void testThenApply_normalCompletion() {
1402 +        for (ExecutionMode m : ExecutionMode.values())
1403 +        for (Integer v1 : new Integer[] { 1, null })
1404 +    {
1405 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1406 +        final IncFunction[] rs = new IncFunction[4];
1407 +        for (int i = 0; i < rs.length; i++) rs[i] = new IncFunction(m);
1408 +
1409 +        final CompletableFuture<Integer> h0 = m.thenApply(f, rs[0]);
1410 +        final CompletableFuture<Integer> h1 = m.applyToEither(f, f, rs[1]);
1411 +        checkIncomplete(h0);
1412 +        checkIncomplete(h1);
1413 +        assertTrue(f.complete(v1));
1414 +        final CompletableFuture<Integer> h2 = m.thenApply(f, rs[2]);
1415 +        final CompletableFuture<Integer> h3 = m.applyToEither(f, f, rs[3]);
1416 +
1417 +        checkCompletedNormally(h0, inc(v1));
1418 +        checkCompletedNormally(h1, inc(v1));
1419 +        checkCompletedNormally(h2, inc(v1));
1420 +        checkCompletedNormally(h3, inc(v1));
1421 +        checkCompletedNormally(f, v1);
1422 +        for (IncFunction r : rs) r.assertValue(inc(v1));
1423 +    }}
1424 +
1425 +    /**
1426 +     * thenApply result completes exceptionally after exceptional
1427 +     * completion of source
1428 +     */
1429 +    public void testThenApply_exceptionalCompletion() {
1430 +        for (ExecutionMode m : ExecutionMode.values())
1431 +    {
1432 +        final CFException ex = new CFException();
1433 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1434 +        final IncFunction[] rs = new IncFunction[4];
1435 +        for (int i = 0; i < rs.length; i++) rs[i] = new IncFunction(m);
1436 +
1437 +        final CompletableFuture<Integer> h0 = m.thenApply(f, rs[0]);
1438 +        final CompletableFuture<Integer> h1 = m.applyToEither(f, f, rs[1]);
1439 +        assertTrue(f.completeExceptionally(ex));
1440 +        final CompletableFuture<Integer> h2 = m.thenApply(f, rs[2]);
1441 +        final CompletableFuture<Integer> h3 = m.applyToEither(f, f, rs[3]);
1442 +
1443 +        checkCompletedWithWrappedException(h0, ex);
1444 +        checkCompletedWithWrappedException(h1, ex);
1445 +        checkCompletedWithWrappedException(h2, ex);
1446 +        checkCompletedWithWrappedException(h3, ex);
1447 +        checkCompletedExceptionally(f, ex);
1448 +        for (IncFunction r : rs) r.assertNotInvoked();
1449 +    }}
1450 +
1451 +    /**
1452 +     * thenApply result completes exceptionally if source cancelled
1453 +     */
1454 +    public void testThenApply_sourceCancelled() {
1455 +        for (ExecutionMode m : ExecutionMode.values())
1456 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
1457 +    {
1458 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1459 +        final IncFunction[] rs = new IncFunction[4];
1460 +        for (int i = 0; i < rs.length; i++) rs[i] = new IncFunction(m);
1461 +
1462 +        final CompletableFuture<Integer> h0 = m.thenApply(f, rs[0]);
1463 +        final CompletableFuture<Integer> h1 = m.applyToEither(f, f, rs[1]);
1464 +        assertTrue(f.cancel(mayInterruptIfRunning));
1465 +        final CompletableFuture<Integer> h2 = m.thenApply(f, rs[2]);
1466 +        final CompletableFuture<Integer> h3 = m.applyToEither(f, f, rs[3]);
1467 +
1468 +        checkCompletedWithWrappedCancellationException(h0);
1469 +        checkCompletedWithWrappedCancellationException(h1);
1470 +        checkCompletedWithWrappedCancellationException(h2);
1471 +        checkCompletedWithWrappedCancellationException(h3);
1472 +        checkCancelled(f);
1473 +        for (IncFunction r : rs) r.assertNotInvoked();
1474 +    }}
1475 +
1476 +    /**
1477 +     * thenApply result completes exceptionally if action does
1478 +     */
1479 +    public void testThenApply_actionFailed() {
1480 +        for (ExecutionMode m : ExecutionMode.values())
1481 +        for (Integer v1 : new Integer[] { 1, null })
1482 +    {
1483 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1484 +        final FailingFunction[] rs = new FailingFunction[4];
1485 +        for (int i = 0; i < rs.length; i++) rs[i] = new FailingFunction(m);
1486 +
1487 +        final CompletableFuture<Integer> h0 = m.thenApply(f, rs[0]);
1488 +        final CompletableFuture<Integer> h1 = m.applyToEither(f, f, rs[1]);
1489 +        assertTrue(f.complete(v1));
1490 +        final CompletableFuture<Integer> h2 = m.thenApply(f, rs[2]);
1491 +        final CompletableFuture<Integer> h3 = m.applyToEither(f, f, rs[3]);
1492 +
1493 +        checkCompletedWithWrappedException(h0, rs[0].ex);
1494 +        checkCompletedWithWrappedException(h1, rs[1].ex);
1495 +        checkCompletedWithWrappedException(h2, rs[2].ex);
1496 +        checkCompletedWithWrappedException(h3, rs[3].ex);
1497 +        checkCompletedNormally(f, v1);
1498 +    }}
1499 +
1500 +    /**
1501 +     * thenAccept result completes normally after normal completion of source
1502 +     */
1503 +    public void testThenAccept_normalCompletion() {
1504 +        for (ExecutionMode m : ExecutionMode.values())
1505 +        for (Integer v1 : new Integer[] { 1, null })
1506 +    {
1507 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1508 +        final NoopConsumer[] rs = new NoopConsumer[4];
1509 +        for (int i = 0; i < rs.length; i++) rs[i] = new NoopConsumer(m);
1510 +
1511 +        final CompletableFuture<Void> h0 = m.thenAccept(f, rs[0]);
1512 +        final CompletableFuture<Void> h1 = m.acceptEither(f, f, rs[1]);
1513 +        checkIncomplete(h0);
1514 +        checkIncomplete(h1);
1515 +        assertTrue(f.complete(v1));
1516 +        final CompletableFuture<Void> h2 = m.thenAccept(f, rs[2]);
1517 +        final CompletableFuture<Void> h3 = m.acceptEither(f, f, rs[3]);
1518 +
1519 +        checkCompletedNormally(h0, null);
1520 +        checkCompletedNormally(h1, null);
1521 +        checkCompletedNormally(h2, null);
1522 +        checkCompletedNormally(h3, null);
1523 +        checkCompletedNormally(f, v1);
1524 +        for (NoopConsumer r : rs) r.assertValue(v1);
1525 +    }}
1526 +
1527 +    /**
1528 +     * thenAccept result completes exceptionally after exceptional
1529 +     * completion of source
1530 +     */
1531 +    public void testThenAccept_exceptionalCompletion() {
1532 +        for (ExecutionMode m : ExecutionMode.values())
1533 +    {
1534 +        final CFException ex = new CFException();
1535 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1536 +        final NoopConsumer[] rs = new NoopConsumer[4];
1537 +        for (int i = 0; i < rs.length; i++) rs[i] = new NoopConsumer(m);
1538 +
1539 +        final CompletableFuture<Void> h0 = m.thenAccept(f, rs[0]);
1540 +        final CompletableFuture<Void> h1 = m.acceptEither(f, f, rs[1]);
1541 +        assertTrue(f.completeExceptionally(ex));
1542 +        final CompletableFuture<Void> h2 = m.thenAccept(f, rs[2]);
1543 +        final CompletableFuture<Void> h3 = m.acceptEither(f, f, rs[3]);
1544 +
1545 +        checkCompletedWithWrappedException(h0, ex);
1546 +        checkCompletedWithWrappedException(h1, ex);
1547 +        checkCompletedWithWrappedException(h2, ex);
1548 +        checkCompletedWithWrappedException(h3, ex);
1549 +        checkCompletedExceptionally(f, ex);
1550 +        for (NoopConsumer r : rs) r.assertNotInvoked();
1551 +    }}
1552 +
1553 +    /**
1554 +     * thenAccept result completes exceptionally if source cancelled
1555 +     */
1556 +    public void testThenAccept_sourceCancelled() {
1557 +        for (ExecutionMode m : ExecutionMode.values())
1558 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
1559 +    {
1560 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1561 +        final NoopConsumer[] rs = new NoopConsumer[4];
1562 +        for (int i = 0; i < rs.length; i++) rs[i] = new NoopConsumer(m);
1563 +
1564 +        final CompletableFuture<Void> h0 = m.thenAccept(f, rs[0]);
1565 +        final CompletableFuture<Void> h1 = m.acceptEither(f, f, rs[1]);
1566 +        assertTrue(f.cancel(mayInterruptIfRunning));
1567 +        final CompletableFuture<Void> h2 = m.thenAccept(f, rs[2]);
1568 +        final CompletableFuture<Void> h3 = m.acceptEither(f, f, rs[3]);
1569 +
1570 +        checkCompletedWithWrappedCancellationException(h0);
1571 +        checkCompletedWithWrappedCancellationException(h1);
1572 +        checkCompletedWithWrappedCancellationException(h2);
1573 +        checkCompletedWithWrappedCancellationException(h3);
1574 +        checkCancelled(f);
1575 +        for (NoopConsumer r : rs) r.assertNotInvoked();
1576 +    }}
1577 +
1578 +    /**
1579 +     * thenAccept result completes exceptionally if action does
1580 +     */
1581 +    public void testThenAccept_actionFailed() {
1582 +        for (ExecutionMode m : ExecutionMode.values())
1583 +        for (Integer v1 : new Integer[] { 1, null })
1584 +    {
1585 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1586 +        final FailingConsumer[] rs = new FailingConsumer[4];
1587 +        for (int i = 0; i < rs.length; i++) rs[i] = new FailingConsumer(m);
1588 +
1589 +        final CompletableFuture<Void> h0 = m.thenAccept(f, rs[0]);
1590 +        final CompletableFuture<Void> h1 = m.acceptEither(f, f, rs[1]);
1591 +        assertTrue(f.complete(v1));
1592 +        final CompletableFuture<Void> h2 = m.thenAccept(f, rs[2]);
1593 +        final CompletableFuture<Void> h3 = m.acceptEither(f, f, rs[3]);
1594 +
1595 +        checkCompletedWithWrappedException(h0, rs[0].ex);
1596 +        checkCompletedWithWrappedException(h1, rs[1].ex);
1597 +        checkCompletedWithWrappedException(h2, rs[2].ex);
1598 +        checkCompletedWithWrappedException(h3, rs[3].ex);
1599 +        checkCompletedNormally(f, v1);
1600 +    }}
1601 +
1602 +    /**
1603 +     * thenCombine result completes normally after normal completion
1604 +     * of sources
1605 +     */
1606 +    public void testThenCombine_normalCompletion() {
1607 +        for (ExecutionMode m : ExecutionMode.values())
1608 +        for (boolean fFirst : new boolean[] { true, false })
1609 +        for (Integer v1 : new Integer[] { 1, null })
1610 +        for (Integer v2 : new Integer[] { 2, null })
1611 +    {
1612 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1613 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1614 +        final SubtractFunction[] rs = new SubtractFunction[6];
1615 +        for (int i = 0; i < rs.length; i++) rs[i] = new SubtractFunction(m);
1616 +
1617 +        final CompletableFuture<Integer> fst =  fFirst ? f : g;
1618 +        final CompletableFuture<Integer> snd = !fFirst ? f : g;
1619 +        final Integer w1 =  fFirst ? v1 : v2;
1620 +        final Integer w2 = !fFirst ? v1 : v2;
1621 +
1622 +        final CompletableFuture<Integer> h0 = m.thenCombine(f, g, rs[0]);
1623 +        final CompletableFuture<Integer> h1 = m.thenCombine(fst, fst, rs[1]);
1624 +        assertTrue(fst.complete(w1));
1625 +        final CompletableFuture<Integer> h2 = m.thenCombine(f, g, rs[2]);
1626 +        final CompletableFuture<Integer> h3 = m.thenCombine(fst, fst, rs[3]);
1627 +        checkIncomplete(h0); rs[0].assertNotInvoked();
1628 +        checkIncomplete(h2); rs[2].assertNotInvoked();
1629 +        checkCompletedNormally(h1, subtract(w1, w1));
1630 +        checkCompletedNormally(h3, subtract(w1, w1));
1631 +        rs[1].assertValue(subtract(w1, w1));
1632 +        rs[3].assertValue(subtract(w1, w1));
1633 +        assertTrue(snd.complete(w2));
1634 +        final CompletableFuture<Integer> h4 = m.thenCombine(f, g, rs[4]);
1635 +
1636 +        checkCompletedNormally(h0, subtract(v1, v2));
1637 +        checkCompletedNormally(h2, subtract(v1, v2));
1638 +        checkCompletedNormally(h4, subtract(v1, v2));
1639 +        rs[0].assertValue(subtract(v1, v2));
1640 +        rs[2].assertValue(subtract(v1, v2));
1641 +        rs[4].assertValue(subtract(v1, v2));
1642 +
1643 +        checkCompletedNormally(f, v1);
1644 +        checkCompletedNormally(g, v2);
1645 +    }}
1646 +
1647 +    /**
1648 +     * thenCombine result completes exceptionally after exceptional
1649 +     * completion of either source
1650 +     */
1651 +    public void testThenCombine_exceptionalCompletion() throws Throwable {
1652 +        for (ExecutionMode m : ExecutionMode.values())
1653 +        for (boolean fFirst : new boolean[] { true, false })
1654 +        for (boolean failFirst : new boolean[] { true, false })
1655 +        for (Integer v1 : new Integer[] { 1, null })
1656 +    {
1657 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1658 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1659 +        final CFException ex = new CFException();
1660 +        final SubtractFunction r1 = new SubtractFunction(m);
1661 +        final SubtractFunction r2 = new SubtractFunction(m);
1662 +        final SubtractFunction r3 = new SubtractFunction(m);
1663 +
1664 +        final CompletableFuture<Integer> fst =  fFirst ? f : g;
1665 +        final CompletableFuture<Integer> snd = !fFirst ? f : g;
1666 +        final Callable<Boolean> complete1 = failFirst ?
1667 +            () -> fst.completeExceptionally(ex) :
1668 +            () -> fst.complete(v1);
1669 +        final Callable<Boolean> complete2 = failFirst ?
1670 +            () -> snd.complete(v1) :
1671 +            () -> snd.completeExceptionally(ex);
1672 +
1673 +        final CompletableFuture<Integer> h1 = m.thenCombine(f, g, r1);
1674 +        assertTrue(complete1.call());
1675 +        final CompletableFuture<Integer> h2 = m.thenCombine(f, g, r2);
1676 +        checkIncomplete(h1);
1677 +        checkIncomplete(h2);
1678 +        assertTrue(complete2.call());
1679 +        final CompletableFuture<Integer> h3 = m.thenCombine(f, g, r3);
1680 +
1681 +        checkCompletedWithWrappedException(h1, ex);
1682 +        checkCompletedWithWrappedException(h2, ex);
1683 +        checkCompletedWithWrappedException(h3, ex);
1684 +        r1.assertNotInvoked();
1685 +        r2.assertNotInvoked();
1686 +        r3.assertNotInvoked();
1687 +        checkCompletedNormally(failFirst ? snd : fst, v1);
1688 +        checkCompletedExceptionally(failFirst ? fst : snd, ex);
1689 +    }}
1690 +
1691 +    /**
1692 +     * thenCombine result completes exceptionally if either source cancelled
1693 +     */
1694 +    public void testThenCombine_sourceCancelled() throws Throwable {
1695 +        for (ExecutionMode m : ExecutionMode.values())
1696 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
1697 +        for (boolean fFirst : new boolean[] { true, false })
1698 +        for (boolean failFirst : new boolean[] { true, false })
1699 +        for (Integer v1 : new Integer[] { 1, null })
1700 +    {
1701 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1702 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1703 +        final SubtractFunction r1 = new SubtractFunction(m);
1704 +        final SubtractFunction r2 = new SubtractFunction(m);
1705 +        final SubtractFunction r3 = new SubtractFunction(m);
1706 +
1707 +        final CompletableFuture<Integer> fst =  fFirst ? f : g;
1708 +        final CompletableFuture<Integer> snd = !fFirst ? f : g;
1709 +        final Callable<Boolean> complete1 = failFirst ?
1710 +            () -> fst.cancel(mayInterruptIfRunning) :
1711 +            () -> fst.complete(v1);
1712 +        final Callable<Boolean> complete2 = failFirst ?
1713 +            () -> snd.complete(v1) :
1714 +            () -> snd.cancel(mayInterruptIfRunning);
1715 +
1716 +        final CompletableFuture<Integer> h1 = m.thenCombine(f, g, r1);
1717 +        assertTrue(complete1.call());
1718 +        final CompletableFuture<Integer> h2 = m.thenCombine(f, g, r2);
1719 +        checkIncomplete(h1);
1720 +        checkIncomplete(h2);
1721 +        assertTrue(complete2.call());
1722 +        final CompletableFuture<Integer> h3 = m.thenCombine(f, g, r3);
1723 +
1724 +        checkCompletedWithWrappedCancellationException(h1);
1725 +        checkCompletedWithWrappedCancellationException(h2);
1726 +        checkCompletedWithWrappedCancellationException(h3);
1727 +        r1.assertNotInvoked();
1728 +        r2.assertNotInvoked();
1729 +        r3.assertNotInvoked();
1730 +        checkCompletedNormally(failFirst ? snd : fst, v1);
1731 +        checkCancelled(failFirst ? fst : snd);
1732 +    }}
1733 +
1734 +    /**
1735 +     * thenCombine result completes exceptionally if action does
1736 +     */
1737 +    public void testThenCombine_actionFailed() {
1738 +        for (ExecutionMode m : ExecutionMode.values())
1739 +        for (boolean fFirst : new boolean[] { true, false })
1740 +        for (Integer v1 : new Integer[] { 1, null })
1741 +        for (Integer v2 : new Integer[] { 2, null })
1742 +    {
1743 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1744 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1745 +        final FailingBiFunction r1 = new FailingBiFunction(m);
1746 +        final FailingBiFunction r2 = new FailingBiFunction(m);
1747 +        final FailingBiFunction r3 = new FailingBiFunction(m);
1748 +
1749 +        final CompletableFuture<Integer> fst =  fFirst ? f : g;
1750 +        final CompletableFuture<Integer> snd = !fFirst ? f : g;
1751 +        final Integer w1 =  fFirst ? v1 : v2;
1752 +        final Integer w2 = !fFirst ? v1 : v2;
1753 +
1754 +        final CompletableFuture<Integer> h1 = m.thenCombine(f, g, r1);
1755 +        assertTrue(fst.complete(w1));
1756 +        final CompletableFuture<Integer> h2 = m.thenCombine(f, g, r2);
1757 +        assertTrue(snd.complete(w2));
1758 +        final CompletableFuture<Integer> h3 = m.thenCombine(f, g, r3);
1759 +
1760 +        checkCompletedWithWrappedException(h1, r1.ex);
1761 +        checkCompletedWithWrappedException(h2, r2.ex);
1762 +        checkCompletedWithWrappedException(h3, r3.ex);
1763 +        r1.assertInvoked();
1764 +        r2.assertInvoked();
1765 +        r3.assertInvoked();
1766 +        checkCompletedNormally(f, v1);
1767 +        checkCompletedNormally(g, v2);
1768 +    }}
1769 +
1770 +    /**
1771 +     * thenAcceptBoth result completes normally after normal
1772 +     * completion of sources
1773 +     */
1774 +    public void testThenAcceptBoth_normalCompletion() {
1775 +        for (ExecutionMode m : ExecutionMode.values())
1776 +        for (boolean fFirst : new boolean[] { true, false })
1777 +        for (Integer v1 : new Integer[] { 1, null })
1778 +        for (Integer v2 : new Integer[] { 2, null })
1779 +    {
1780 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1781 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1782 +        final SubtractAction r1 = new SubtractAction(m);
1783 +        final SubtractAction r2 = new SubtractAction(m);
1784 +        final SubtractAction r3 = new SubtractAction(m);
1785 +
1786 +        final CompletableFuture<Integer> fst =  fFirst ? f : g;
1787 +        final CompletableFuture<Integer> snd = !fFirst ? f : g;
1788 +        final Integer w1 =  fFirst ? v1 : v2;
1789 +        final Integer w2 = !fFirst ? v1 : v2;
1790 +
1791 +        final CompletableFuture<Void> h1 = m.thenAcceptBoth(f, g, r1);
1792 +        assertTrue(fst.complete(w1));
1793 +        final CompletableFuture<Void> h2 = m.thenAcceptBoth(f, g, r2);
1794 +        checkIncomplete(h1);
1795 +        checkIncomplete(h2);
1796 +        r1.assertNotInvoked();
1797 +        r2.assertNotInvoked();
1798 +        assertTrue(snd.complete(w2));
1799 +        final CompletableFuture<Void> h3 = m.thenAcceptBoth(f, g, r3);
1800 +
1801 +        checkCompletedNormally(h1, null);
1802 +        checkCompletedNormally(h2, null);
1803 +        checkCompletedNormally(h3, null);
1804 +        r1.assertValue(subtract(v1, v2));
1805 +        r2.assertValue(subtract(v1, v2));
1806 +        r3.assertValue(subtract(v1, v2));
1807 +        checkCompletedNormally(f, v1);
1808 +        checkCompletedNormally(g, v2);
1809 +    }}
1810 +
1811 +    /**
1812 +     * thenAcceptBoth result completes exceptionally after exceptional
1813 +     * completion of either source
1814 +     */
1815 +    public void testThenAcceptBoth_exceptionalCompletion() throws Throwable {
1816 +        for (ExecutionMode m : ExecutionMode.values())
1817 +        for (boolean fFirst : new boolean[] { true, false })
1818 +        for (boolean failFirst : new boolean[] { true, false })
1819 +        for (Integer v1 : new Integer[] { 1, null })
1820 +    {
1821 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1822 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1823 +        final CFException ex = new CFException();
1824 +        final SubtractAction r1 = new SubtractAction(m);
1825 +        final SubtractAction r2 = new SubtractAction(m);
1826 +        final SubtractAction r3 = new SubtractAction(m);
1827 +
1828 +        final CompletableFuture<Integer> fst =  fFirst ? f : g;
1829 +        final CompletableFuture<Integer> snd = !fFirst ? f : g;
1830 +        final Callable<Boolean> complete1 = failFirst ?
1831 +            () -> fst.completeExceptionally(ex) :
1832 +            () -> fst.complete(v1);
1833 +        final Callable<Boolean> complete2 = failFirst ?
1834 +            () -> snd.complete(v1) :
1835 +            () -> snd.completeExceptionally(ex);
1836 +
1837 +        final CompletableFuture<Void> h1 = m.thenAcceptBoth(f, g, r1);
1838 +        assertTrue(complete1.call());
1839 +        final CompletableFuture<Void> h2 = m.thenAcceptBoth(f, g, r2);
1840 +        checkIncomplete(h1);
1841 +        checkIncomplete(h2);
1842 +        assertTrue(complete2.call());
1843 +        final CompletableFuture<Void> h3 = m.thenAcceptBoth(f, g, r3);
1844 +
1845 +        checkCompletedWithWrappedException(h1, ex);
1846 +        checkCompletedWithWrappedException(h2, ex);
1847 +        checkCompletedWithWrappedException(h3, ex);
1848 +        r1.assertNotInvoked();
1849 +        r2.assertNotInvoked();
1850 +        r3.assertNotInvoked();
1851 +        checkCompletedNormally(failFirst ? snd : fst, v1);
1852 +        checkCompletedExceptionally(failFirst ? fst : snd, ex);
1853 +    }}
1854 +
1855 +    /**
1856 +     * thenAcceptBoth result completes exceptionally if either source cancelled
1857 +     */
1858 +    public void testThenAcceptBoth_sourceCancelled() throws Throwable {
1859 +        for (ExecutionMode m : ExecutionMode.values())
1860 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
1861 +        for (boolean fFirst : new boolean[] { true, false })
1862 +        for (boolean failFirst : new boolean[] { true, false })
1863 +        for (Integer v1 : new Integer[] { 1, null })
1864 +    {
1865 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1866 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1867 +        final SubtractAction r1 = new SubtractAction(m);
1868 +        final SubtractAction r2 = new SubtractAction(m);
1869 +        final SubtractAction r3 = new SubtractAction(m);
1870 +
1871 +        final CompletableFuture<Integer> fst =  fFirst ? f : g;
1872 +        final CompletableFuture<Integer> snd = !fFirst ? f : g;
1873 +        final Callable<Boolean> complete1 = failFirst ?
1874 +            () -> fst.cancel(mayInterruptIfRunning) :
1875 +            () -> fst.complete(v1);
1876 +        final Callable<Boolean> complete2 = failFirst ?
1877 +            () -> snd.complete(v1) :
1878 +            () -> snd.cancel(mayInterruptIfRunning);
1879 +
1880 +        final CompletableFuture<Void> h1 = m.thenAcceptBoth(f, g, r1);
1881 +        assertTrue(complete1.call());
1882 +        final CompletableFuture<Void> h2 = m.thenAcceptBoth(f, g, r2);
1883 +        checkIncomplete(h1);
1884 +        checkIncomplete(h2);
1885 +        assertTrue(complete2.call());
1886 +        final CompletableFuture<Void> h3 = m.thenAcceptBoth(f, g, r3);
1887 +
1888 +        checkCompletedWithWrappedCancellationException(h1);
1889 +        checkCompletedWithWrappedCancellationException(h2);
1890 +        checkCompletedWithWrappedCancellationException(h3);
1891 +        r1.assertNotInvoked();
1892 +        r2.assertNotInvoked();
1893 +        r3.assertNotInvoked();
1894 +        checkCompletedNormally(failFirst ? snd : fst, v1);
1895 +        checkCancelled(failFirst ? fst : snd);
1896 +    }}
1897 +
1898 +    /**
1899 +     * thenAcceptBoth result completes exceptionally if action does
1900 +     */
1901 +    public void testThenAcceptBoth_actionFailed() {
1902 +        for (ExecutionMode m : ExecutionMode.values())
1903 +        for (boolean fFirst : new boolean[] { true, false })
1904 +        for (Integer v1 : new Integer[] { 1, null })
1905 +        for (Integer v2 : new Integer[] { 2, null })
1906 +    {
1907 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1908 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1909 +        final FailingBiConsumer r1 = new FailingBiConsumer(m);
1910 +        final FailingBiConsumer r2 = new FailingBiConsumer(m);
1911 +        final FailingBiConsumer r3 = new FailingBiConsumer(m);
1912 +
1913 +        final CompletableFuture<Integer> fst =  fFirst ? f : g;
1914 +        final CompletableFuture<Integer> snd = !fFirst ? f : g;
1915 +        final Integer w1 =  fFirst ? v1 : v2;
1916 +        final Integer w2 = !fFirst ? v1 : v2;
1917 +
1918 +        final CompletableFuture<Void> h1 = m.thenAcceptBoth(f, g, r1);
1919 +        assertTrue(fst.complete(w1));
1920 +        final CompletableFuture<Void> h2 = m.thenAcceptBoth(f, g, r2);
1921 +        assertTrue(snd.complete(w2));
1922 +        final CompletableFuture<Void> h3 = m.thenAcceptBoth(f, g, r3);
1923 +
1924 +        checkCompletedWithWrappedException(h1, r1.ex);
1925 +        checkCompletedWithWrappedException(h2, r2.ex);
1926 +        checkCompletedWithWrappedException(h3, r3.ex);
1927 +        r1.assertInvoked();
1928 +        r2.assertInvoked();
1929 +        r3.assertInvoked();
1930 +        checkCompletedNormally(f, v1);
1931 +        checkCompletedNormally(g, v2);
1932 +    }}
1933 +
1934 +    /**
1935 +     * runAfterBoth result completes normally after normal
1936 +     * completion of sources
1937 +     */
1938 +    public void testRunAfterBoth_normalCompletion() {
1939 +        for (ExecutionMode m : ExecutionMode.values())
1940 +        for (boolean fFirst : new boolean[] { true, false })
1941 +        for (Integer v1 : new Integer[] { 1, null })
1942 +        for (Integer v2 : new Integer[] { 2, null })
1943 +    {
1944 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1945 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1946 +        final Noop r1 = new Noop(m);
1947 +        final Noop r2 = new Noop(m);
1948 +        final Noop r3 = new Noop(m);
1949 +
1950 +        final CompletableFuture<Integer> fst =  fFirst ? f : g;
1951 +        final CompletableFuture<Integer> snd = !fFirst ? f : g;
1952 +        final Integer w1 =  fFirst ? v1 : v2;
1953 +        final Integer w2 = !fFirst ? v1 : v2;
1954 +
1955 +        final CompletableFuture<Void> h1 = m.runAfterBoth(f, g, r1);
1956 +        assertTrue(fst.complete(w1));
1957 +        final CompletableFuture<Void> h2 = m.runAfterBoth(f, g, r2);
1958 +        checkIncomplete(h1);
1959 +        checkIncomplete(h2);
1960 +        r1.assertNotInvoked();
1961 +        r2.assertNotInvoked();
1962 +        assertTrue(snd.complete(w2));
1963 +        final CompletableFuture<Void> h3 = m.runAfterBoth(f, g, r3);
1964 +
1965 +        checkCompletedNormally(h1, null);
1966 +        checkCompletedNormally(h2, null);
1967 +        checkCompletedNormally(h3, null);
1968 +        r1.assertInvoked();
1969 +        r2.assertInvoked();
1970 +        r3.assertInvoked();
1971 +        checkCompletedNormally(f, v1);
1972 +        checkCompletedNormally(g, v2);
1973 +    }}
1974 +
1975 +    /**
1976 +     * runAfterBoth result completes exceptionally after exceptional
1977 +     * completion of either source
1978 +     */
1979 +    public void testRunAfterBoth_exceptionalCompletion() throws Throwable {
1980 +        for (ExecutionMode m : ExecutionMode.values())
1981 +        for (boolean fFirst : new boolean[] { true, false })
1982 +        for (boolean failFirst : new boolean[] { true, false })
1983 +        for (Integer v1 : new Integer[] { 1, null })
1984 +    {
1985 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1986 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1987 +        final CFException ex = new CFException();
1988 +        final Noop r1 = new Noop(m);
1989 +        final Noop r2 = new Noop(m);
1990 +        final Noop r3 = new Noop(m);
1991 +
1992 +        final CompletableFuture<Integer> fst =  fFirst ? f : g;
1993 +        final CompletableFuture<Integer> snd = !fFirst ? f : g;
1994 +        final Callable<Boolean> complete1 = failFirst ?
1995 +            () -> fst.completeExceptionally(ex) :
1996 +            () -> fst.complete(v1);
1997 +        final Callable<Boolean> complete2 = failFirst ?
1998 +            () -> snd.complete(v1) :
1999 +            () -> snd.completeExceptionally(ex);
2000 +
2001 +        final CompletableFuture<Void> h1 = m.runAfterBoth(f, g, r1);
2002 +        assertTrue(complete1.call());
2003 +        final CompletableFuture<Void> h2 = m.runAfterBoth(f, g, r2);
2004 +        checkIncomplete(h1);
2005 +        checkIncomplete(h2);
2006 +        assertTrue(complete2.call());
2007 +        final CompletableFuture<Void> h3 = m.runAfterBoth(f, g, r3);
2008 +
2009 +        checkCompletedWithWrappedException(h1, ex);
2010 +        checkCompletedWithWrappedException(h2, ex);
2011 +        checkCompletedWithWrappedException(h3, ex);
2012 +        r1.assertNotInvoked();
2013 +        r2.assertNotInvoked();
2014 +        r3.assertNotInvoked();
2015 +        checkCompletedNormally(failFirst ? snd : fst, v1);
2016 +        checkCompletedExceptionally(failFirst ? fst : snd, ex);
2017 +    }}
2018 +
2019 +    /**
2020 +     * runAfterBoth result completes exceptionally if either source cancelled
2021 +     */
2022 +    public void testRunAfterBoth_sourceCancelled() throws Throwable {
2023 +        for (ExecutionMode m : ExecutionMode.values())
2024 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
2025 +        for (boolean fFirst : new boolean[] { true, false })
2026 +        for (boolean failFirst : new boolean[] { true, false })
2027 +        for (Integer v1 : new Integer[] { 1, null })
2028 +    {
2029 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2030 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2031 +        final Noop r1 = new Noop(m);
2032 +        final Noop r2 = new Noop(m);
2033 +        final Noop r3 = new Noop(m);
2034 +
2035 +        final CompletableFuture<Integer> fst =  fFirst ? f : g;
2036 +        final CompletableFuture<Integer> snd = !fFirst ? f : g;
2037 +        final Callable<Boolean> complete1 = failFirst ?
2038 +            () -> fst.cancel(mayInterruptIfRunning) :
2039 +            () -> fst.complete(v1);
2040 +        final Callable<Boolean> complete2 = failFirst ?
2041 +            () -> snd.complete(v1) :
2042 +            () -> snd.cancel(mayInterruptIfRunning);
2043 +
2044 +        final CompletableFuture<Void> h1 = m.runAfterBoth(f, g, r1);
2045 +        assertTrue(complete1.call());
2046 +        final CompletableFuture<Void> h2 = m.runAfterBoth(f, g, r2);
2047 +        checkIncomplete(h1);
2048 +        checkIncomplete(h2);
2049 +        assertTrue(complete2.call());
2050 +        final CompletableFuture<Void> h3 = m.runAfterBoth(f, g, r3);
2051 +
2052 +        checkCompletedWithWrappedCancellationException(h1);
2053 +        checkCompletedWithWrappedCancellationException(h2);
2054 +        checkCompletedWithWrappedCancellationException(h3);
2055 +        r1.assertNotInvoked();
2056 +        r2.assertNotInvoked();
2057 +        r3.assertNotInvoked();
2058 +        checkCompletedNormally(failFirst ? snd : fst, v1);
2059 +        checkCancelled(failFirst ? fst : snd);
2060 +    }}
2061 +
2062 +    /**
2063 +     * runAfterBoth result completes exceptionally if action does
2064 +     */
2065 +    public void testRunAfterBoth_actionFailed() {
2066 +        for (ExecutionMode m : ExecutionMode.values())
2067 +        for (boolean fFirst : new boolean[] { true, false })
2068 +        for (Integer v1 : new Integer[] { 1, null })
2069 +        for (Integer v2 : new Integer[] { 2, null })
2070 +    {
2071 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2072 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2073 +        final FailingRunnable r1 = new FailingRunnable(m);
2074 +        final FailingRunnable r2 = new FailingRunnable(m);
2075 +        final FailingRunnable r3 = new FailingRunnable(m);
2076 +
2077 +        final CompletableFuture<Integer> fst =  fFirst ? f : g;
2078 +        final CompletableFuture<Integer> snd = !fFirst ? f : g;
2079 +        final Integer w1 =  fFirst ? v1 : v2;
2080 +        final Integer w2 = !fFirst ? v1 : v2;
2081 +
2082 +        final CompletableFuture<Void> h1 = m.runAfterBoth(f, g, r1);
2083 +        assertTrue(fst.complete(w1));
2084 +        final CompletableFuture<Void> h2 = m.runAfterBoth(f, g, r2);
2085 +        assertTrue(snd.complete(w2));
2086 +        final CompletableFuture<Void> h3 = m.runAfterBoth(f, g, r3);
2087 +
2088 +        checkCompletedWithWrappedException(h1, r1.ex);
2089 +        checkCompletedWithWrappedException(h2, r2.ex);
2090 +        checkCompletedWithWrappedException(h3, r3.ex);
2091 +        r1.assertInvoked();
2092 +        r2.assertInvoked();
2093 +        r3.assertInvoked();
2094 +        checkCompletedNormally(f, v1);
2095 +        checkCompletedNormally(g, v2);
2096 +    }}
2097 +
2098 +    /**
2099 +     * applyToEither result completes normally after normal completion
2100 +     * of either source
2101 +     */
2102 +    public void testApplyToEither_normalCompletion() {
2103 +        for (ExecutionMode m : ExecutionMode.values())
2104 +        for (Integer v1 : new Integer[] { 1, null })
2105 +        for (Integer v2 : new Integer[] { 2, null })
2106 +    {
2107 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2108 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2109 +        final IncFunction[] rs = new IncFunction[6];
2110 +        for (int i = 0; i < rs.length; i++) rs[i] = new IncFunction(m);
2111 +
2112 +        final CompletableFuture<Integer> h0 = m.applyToEither(f, g, rs[0]);
2113 +        final CompletableFuture<Integer> h1 = m.applyToEither(g, f, rs[1]);
2114 +        checkIncomplete(h0);
2115 +        checkIncomplete(h1);
2116 +        rs[0].assertNotInvoked();
2117 +        rs[1].assertNotInvoked();
2118 +        f.complete(v1);
2119 +        checkCompletedNormally(h0, inc(v1));
2120 +        checkCompletedNormally(h1, inc(v1));
2121 +        final CompletableFuture<Integer> h2 = m.applyToEither(f, g, rs[2]);
2122 +        final CompletableFuture<Integer> h3 = m.applyToEither(g, f, rs[3]);
2123 +        checkCompletedNormally(h2, inc(v1));
2124 +        checkCompletedNormally(h3, inc(v1));
2125 +        g.complete(v2);
2126 +
2127 +        // unspecified behavior - both source completions available
2128 +        final CompletableFuture<Integer> h4 = m.applyToEither(f, g, rs[4]);
2129 +        final CompletableFuture<Integer> h5 = m.applyToEither(g, f, rs[5]);
2130 +        rs[4].assertValue(h4.join());
2131 +        rs[5].assertValue(h5.join());
2132 +        assertTrue(Objects.equals(inc(v1), h4.join()) ||
2133 +                   Objects.equals(inc(v2), h4.join()));
2134 +        assertTrue(Objects.equals(inc(v1), h5.join()) ||
2135 +                   Objects.equals(inc(v2), h5.join()));
2136 +
2137 +        checkCompletedNormally(f, v1);
2138 +        checkCompletedNormally(g, v2);
2139 +        checkCompletedNormally(h0, inc(v1));
2140 +        checkCompletedNormally(h1, inc(v1));
2141 +        checkCompletedNormally(h2, inc(v1));
2142 +        checkCompletedNormally(h3, inc(v1));
2143 +        for (int i = 0; i < 4; i++) rs[i].assertValue(inc(v1));
2144 +    }}
2145 +
2146 +    /**
2147 +     * applyToEither result completes exceptionally after exceptional
2148 +     * completion of either source
2149 +     */
2150 +    public void testApplyToEither_exceptionalCompletion() {
2151 +        for (ExecutionMode m : ExecutionMode.values())
2152 +        for (Integer v1 : new Integer[] { 1, null })
2153 +    {
2154 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2155 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2156 +        final CFException ex = new CFException();
2157 +        final IncFunction[] rs = new IncFunction[6];
2158 +        for (int i = 0; i < rs.length; i++) rs[i] = new IncFunction(m);
2159 +
2160 +        final CompletableFuture<Integer> h0 = m.applyToEither(f, g, rs[0]);
2161 +        final CompletableFuture<Integer> h1 = m.applyToEither(g, f, rs[1]);
2162 +        checkIncomplete(h0);
2163 +        checkIncomplete(h1);
2164 +        rs[0].assertNotInvoked();
2165 +        rs[1].assertNotInvoked();
2166 +        f.completeExceptionally(ex);
2167 +        checkCompletedWithWrappedException(h0, ex);
2168 +        checkCompletedWithWrappedException(h1, ex);
2169 +        final CompletableFuture<Integer> h2 = m.applyToEither(f, g, rs[2]);
2170 +        final CompletableFuture<Integer> h3 = m.applyToEither(g, f, rs[3]);
2171 +        checkCompletedWithWrappedException(h2, ex);
2172 +        checkCompletedWithWrappedException(h3, ex);
2173 +        g.complete(v1);
2174 +
2175 +        // unspecified behavior - both source completions available
2176 +        final CompletableFuture<Integer> h4 = m.applyToEither(f, g, rs[4]);
2177 +        final CompletableFuture<Integer> h5 = m.applyToEither(g, f, rs[5]);
2178 +        try {
2179 +            assertEquals(inc(v1), h4.join());
2180 +            rs[4].assertValue(inc(v1));
2181 +        } catch (CompletionException ok) {
2182 +            checkCompletedWithWrappedException(h4, ex);
2183 +            rs[4].assertNotInvoked();
2184 +        }
2185 +        try {
2186 +            assertEquals(inc(v1), h5.join());
2187 +            rs[5].assertValue(inc(v1));
2188 +        } catch (CompletionException ok) {
2189 +            checkCompletedWithWrappedException(h5, ex);
2190 +            rs[5].assertNotInvoked();
2191 +        }
2192 +
2193 +        checkCompletedExceptionally(f, ex);
2194 +        checkCompletedNormally(g, v1);
2195 +        checkCompletedWithWrappedException(h0, ex);
2196 +        checkCompletedWithWrappedException(h1, ex);
2197 +        checkCompletedWithWrappedException(h2, ex);
2198 +        checkCompletedWithWrappedException(h3, ex);
2199 +        checkCompletedWithWrappedException(h4, ex);
2200 +        for (int i = 0; i < 4; i++) rs[i].assertNotInvoked();
2201 +    }}
2202 +
2203 +    public void testApplyToEither_exceptionalCompletion2() {
2204 +        for (ExecutionMode m : ExecutionMode.values())
2205 +        for (boolean fFirst : new boolean[] { true, false })
2206 +        for (Integer v1 : new Integer[] { 1, null })
2207 +    {
2208 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2209 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2210 +        final CFException ex = new CFException();
2211 +        final IncFunction[] rs = new IncFunction[6];
2212 +        for (int i = 0; i < rs.length; i++) rs[i] = new IncFunction(m);
2213 +
2214 +        final CompletableFuture<Integer> h0 = m.applyToEither(f, g, rs[0]);
2215 +        final CompletableFuture<Integer> h1 = m.applyToEither(g, f, rs[1]);
2216 +        assertTrue(fFirst ? f.complete(v1) : g.completeExceptionally(ex));
2217 +        assertTrue(!fFirst ? f.complete(v1) : g.completeExceptionally(ex));
2218 +        final CompletableFuture<Integer> h2 = m.applyToEither(f, g, rs[2]);
2219 +        final CompletableFuture<Integer> h3 = m.applyToEither(g, f, rs[3]);
2220 +
2221 +        // unspecified behavior - both source completions available
2222 +        try {
2223 +            assertEquals(inc(v1), h0.join());
2224 +            rs[0].assertValue(inc(v1));
2225 +        } catch (CompletionException ok) {
2226 +            checkCompletedWithWrappedException(h0, ex);
2227 +            rs[0].assertNotInvoked();
2228 +        }
2229 +        try {
2230 +            assertEquals(inc(v1), h1.join());
2231 +            rs[1].assertValue(inc(v1));
2232 +        } catch (CompletionException ok) {
2233 +            checkCompletedWithWrappedException(h1, ex);
2234 +            rs[1].assertNotInvoked();
2235 +        }
2236 +        try {
2237 +            assertEquals(inc(v1), h2.join());
2238 +            rs[2].assertValue(inc(v1));
2239 +        } catch (CompletionException ok) {
2240 +            checkCompletedWithWrappedException(h2, ex);
2241 +            rs[2].assertNotInvoked();
2242 +        }
2243 +        try {
2244 +            assertEquals(inc(v1), h3.join());
2245 +            rs[3].assertValue(inc(v1));
2246 +        } catch (CompletionException ok) {
2247 +            checkCompletedWithWrappedException(h3, ex);
2248 +            rs[3].assertNotInvoked();
2249 +        }
2250 +
2251 +        checkCompletedNormally(f, v1);
2252 +        checkCompletedExceptionally(g, ex);
2253 +    }}
2254 +
2255 +    /**
2256 +     * applyToEither result completes exceptionally if either source cancelled
2257 +     */
2258 +    public void testApplyToEither_sourceCancelled() {
2259 +        for (ExecutionMode m : ExecutionMode.values())
2260 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
2261 +        for (Integer v1 : new Integer[] { 1, null })
2262 +    {
2263 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2264 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2265 +        final IncFunction[] rs = new IncFunction[6];
2266 +        for (int i = 0; i < rs.length; i++) rs[i] = new IncFunction(m);
2267 +
2268 +        final CompletableFuture<Integer> h0 = m.applyToEither(f, g, rs[0]);
2269 +        final CompletableFuture<Integer> h1 = m.applyToEither(g, f, rs[1]);
2270 +        checkIncomplete(h0);
2271 +        checkIncomplete(h1);
2272 +        rs[0].assertNotInvoked();
2273 +        rs[1].assertNotInvoked();
2274 +        f.cancel(mayInterruptIfRunning);
2275 +        checkCompletedWithWrappedCancellationException(h0);
2276 +        checkCompletedWithWrappedCancellationException(h1);
2277 +        final CompletableFuture<Integer> h2 = m.applyToEither(f, g, rs[2]);
2278 +        final CompletableFuture<Integer> h3 = m.applyToEither(g, f, rs[3]);
2279 +        checkCompletedWithWrappedCancellationException(h2);
2280 +        checkCompletedWithWrappedCancellationException(h3);
2281 +        g.complete(v1);
2282 +
2283 +        // unspecified behavior - both source completions available
2284 +        final CompletableFuture<Integer> h4 = m.applyToEither(f, g, rs[4]);
2285 +        final CompletableFuture<Integer> h5 = m.applyToEither(g, f, rs[5]);
2286 +        try {
2287 +            assertEquals(inc(v1), h4.join());
2288 +            rs[4].assertValue(inc(v1));
2289 +        } catch (CompletionException ok) {
2290 +            checkCompletedWithWrappedCancellationException(h4);
2291 +            rs[4].assertNotInvoked();
2292 +        }
2293 +        try {
2294 +            assertEquals(inc(v1), h5.join());
2295 +            rs[5].assertValue(inc(v1));
2296 +        } catch (CompletionException ok) {
2297 +            checkCompletedWithWrappedCancellationException(h5);
2298 +            rs[5].assertNotInvoked();
2299 +        }
2300 +
2301 +        checkCancelled(f);
2302 +        checkCompletedNormally(g, v1);
2303 +        checkCompletedWithWrappedCancellationException(h0);
2304 +        checkCompletedWithWrappedCancellationException(h1);
2305 +        checkCompletedWithWrappedCancellationException(h2);
2306 +        checkCompletedWithWrappedCancellationException(h3);
2307 +        for (int i = 0; i < 4; i++) rs[i].assertNotInvoked();
2308 +    }}
2309 +
2310 +    public void testApplyToEither_sourceCancelled2() {
2311 +        for (ExecutionMode m : ExecutionMode.values())
2312 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
2313 +        for (boolean fFirst : new boolean[] { true, false })
2314 +        for (Integer v1 : new Integer[] { 1, null })
2315 +    {
2316 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2317 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2318 +        final IncFunction[] rs = new IncFunction[6];
2319 +        for (int i = 0; i < rs.length; i++) rs[i] = new IncFunction(m);
2320 +
2321 +        final CompletableFuture<Integer> h0 = m.applyToEither(f, g, rs[0]);
2322 +        final CompletableFuture<Integer> h1 = m.applyToEither(g, f, rs[1]);
2323 +        assertTrue(fFirst ? f.complete(v1) : g.cancel(mayInterruptIfRunning));
2324 +        assertTrue(!fFirst ? f.complete(v1) : g.cancel(mayInterruptIfRunning));
2325 +        final CompletableFuture<Integer> h2 = m.applyToEither(f, g, rs[2]);
2326 +        final CompletableFuture<Integer> h3 = m.applyToEither(g, f, rs[3]);
2327 +
2328 +        // unspecified behavior - both source completions available
2329 +        try {
2330 +            assertEquals(inc(v1), h0.join());
2331 +            rs[0].assertValue(inc(v1));
2332 +        } catch (CompletionException ok) {
2333 +            checkCompletedWithWrappedCancellationException(h0);
2334 +            rs[0].assertNotInvoked();
2335 +        }
2336 +        try {
2337 +            assertEquals(inc(v1), h1.join());
2338 +            rs[1].assertValue(inc(v1));
2339 +        } catch (CompletionException ok) {
2340 +            checkCompletedWithWrappedCancellationException(h1);
2341 +            rs[1].assertNotInvoked();
2342 +        }
2343 +        try {
2344 +            assertEquals(inc(v1), h2.join());
2345 +            rs[2].assertValue(inc(v1));
2346 +        } catch (CompletionException ok) {
2347 +            checkCompletedWithWrappedCancellationException(h2);
2348 +            rs[2].assertNotInvoked();
2349 +        }
2350 +        try {
2351 +            assertEquals(inc(v1), h3.join());
2352 +            rs[3].assertValue(inc(v1));
2353 +        } catch (CompletionException ok) {
2354 +            checkCompletedWithWrappedCancellationException(h3);
2355 +            rs[3].assertNotInvoked();
2356 +        }
2357 +
2358 +        checkCompletedNormally(f, v1);
2359 +        checkCancelled(g);
2360 +    }}
2361 +
2362 +    /**
2363 +     * applyToEither result completes exceptionally if action does
2364 +     */
2365 +    public void testApplyToEither_actionFailed() {
2366 +        for (ExecutionMode m : ExecutionMode.values())
2367 +        for (Integer v1 : new Integer[] { 1, null })
2368 +        for (Integer v2 : new Integer[] { 2, null })
2369 +    {
2370 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2371 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2372 +        final FailingFunction[] rs = new FailingFunction[6];
2373 +        for (int i = 0; i < rs.length; i++) rs[i] = new FailingFunction(m);
2374 +
2375 +        final CompletableFuture<Integer> h0 = m.applyToEither(f, g, rs[0]);
2376 +        final CompletableFuture<Integer> h1 = m.applyToEither(g, f, rs[1]);
2377 +        f.complete(v1);
2378 +        final CompletableFuture<Integer> h2 = m.applyToEither(f, g, rs[2]);
2379 +        final CompletableFuture<Integer> h3 = m.applyToEither(g, f, rs[3]);
2380 +        checkCompletedWithWrappedException(h0, rs[0].ex);
2381 +        checkCompletedWithWrappedException(h1, rs[1].ex);
2382 +        checkCompletedWithWrappedException(h2, rs[2].ex);
2383 +        checkCompletedWithWrappedException(h3, rs[3].ex);
2384 +        for (int i = 0; i < 4; i++) rs[i].assertValue(v1);
2385 +
2386 +        g.complete(v2);
2387 +
2388 +        // unspecified behavior - both source completions available
2389 +        final CompletableFuture<Integer> h4 = m.applyToEither(f, g, rs[4]);
2390 +        final CompletableFuture<Integer> h5 = m.applyToEither(g, f, rs[5]);
2391 +
2392 +        checkCompletedWithWrappedException(h4, rs[4].ex);
2393 +        assertTrue(Objects.equals(v1, rs[4].value) ||
2394 +                   Objects.equals(v2, rs[4].value));
2395 +        checkCompletedWithWrappedException(h5, rs[5].ex);
2396 +        assertTrue(Objects.equals(v1, rs[5].value) ||
2397 +                   Objects.equals(v2, rs[5].value));
2398 +
2399 +        checkCompletedNormally(f, v1);
2400 +        checkCompletedNormally(g, v2);
2401 +    }}
2402 +
2403 +    /**
2404 +     * acceptEither result completes normally after normal completion
2405 +     * of either source
2406 +     */
2407 +    public void testAcceptEither_normalCompletion() {
2408 +        for (ExecutionMode m : ExecutionMode.values())
2409 +        for (Integer v1 : new Integer[] { 1, null })
2410 +        for (Integer v2 : new Integer[] { 2, null })
2411 +    {
2412 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2413 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2414 +        final NoopConsumer[] rs = new NoopConsumer[6];
2415 +        for (int i = 0; i < rs.length; i++) rs[i] = new NoopConsumer(m);
2416 +
2417 +        final CompletableFuture<Void> h0 = m.acceptEither(f, g, rs[0]);
2418 +        final CompletableFuture<Void> h1 = m.acceptEither(g, f, rs[1]);
2419 +        checkIncomplete(h0);
2420 +        checkIncomplete(h1);
2421 +        rs[0].assertNotInvoked();
2422 +        rs[1].assertNotInvoked();
2423 +        f.complete(v1);
2424 +        checkCompletedNormally(h0, null);
2425 +        checkCompletedNormally(h1, null);
2426 +        rs[0].assertValue(v1);
2427 +        rs[1].assertValue(v1);
2428 +        final CompletableFuture<Void> h2 = m.acceptEither(f, g, rs[2]);
2429 +        final CompletableFuture<Void> h3 = m.acceptEither(g, f, rs[3]);
2430 +        checkCompletedNormally(h2, null);
2431 +        checkCompletedNormally(h3, null);
2432 +        rs[2].assertValue(v1);
2433 +        rs[3].assertValue(v1);
2434 +        g.complete(v2);
2435 +
2436 +        // unspecified behavior - both source completions available
2437 +        final CompletableFuture<Void> h4 = m.acceptEither(f, g, rs[4]);
2438 +        final CompletableFuture<Void> h5 = m.acceptEither(g, f, rs[5]);
2439 +        checkCompletedNormally(h4, null);
2440 +        checkCompletedNormally(h5, null);
2441 +        assertTrue(Objects.equals(v1, rs[4].value) ||
2442 +                   Objects.equals(v2, rs[4].value));
2443 +        assertTrue(Objects.equals(v1, rs[5].value) ||
2444 +                   Objects.equals(v2, rs[5].value));
2445 +
2446 +        checkCompletedNormally(f, v1);
2447 +        checkCompletedNormally(g, v2);
2448 +        checkCompletedNormally(h0, null);
2449 +        checkCompletedNormally(h1, null);
2450 +        checkCompletedNormally(h2, null);
2451 +        checkCompletedNormally(h3, null);
2452 +        for (int i = 0; i < 4; i++) rs[i].assertValue(v1);
2453 +    }}
2454 +
2455 +    /**
2456 +     * acceptEither result completes exceptionally after exceptional
2457 +     * completion of either source
2458 +     */
2459 +    public void testAcceptEither_exceptionalCompletion() {
2460 +        for (ExecutionMode m : ExecutionMode.values())
2461 +        for (Integer v1 : new Integer[] { 1, null })
2462 +    {
2463 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2464 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2465 +        final CFException ex = new CFException();
2466 +        final NoopConsumer[] rs = new NoopConsumer[6];
2467 +        for (int i = 0; i < rs.length; i++) rs[i] = new NoopConsumer(m);
2468 +
2469 +        final CompletableFuture<Void> h0 = m.acceptEither(f, g, rs[0]);
2470 +        final CompletableFuture<Void> h1 = m.acceptEither(g, f, rs[1]);
2471 +        checkIncomplete(h0);
2472 +        checkIncomplete(h1);
2473 +        rs[0].assertNotInvoked();
2474 +        rs[1].assertNotInvoked();
2475 +        f.completeExceptionally(ex);
2476 +        checkCompletedWithWrappedException(h0, ex);
2477 +        checkCompletedWithWrappedException(h1, ex);
2478 +        final CompletableFuture<Void> h2 = m.acceptEither(f, g, rs[2]);
2479 +        final CompletableFuture<Void> h3 = m.acceptEither(g, f, rs[3]);
2480 +        checkCompletedWithWrappedException(h2, ex);
2481 +        checkCompletedWithWrappedException(h3, ex);
2482 +
2483 +        g.complete(v1);
2484 +
2485 +        // unspecified behavior - both source completions available
2486 +        final CompletableFuture<Void> h4 = m.acceptEither(f, g, rs[4]);
2487 +        final CompletableFuture<Void> h5 = m.acceptEither(g, f, rs[5]);
2488 +        try {
2489 +            assertNull(h4.join());
2490 +            rs[4].assertValue(v1);
2491 +        } catch (CompletionException ok) {
2492 +            checkCompletedWithWrappedException(h4, ex);
2493 +            rs[4].assertNotInvoked();
2494 +        }
2495 +        try {
2496 +            assertNull(h5.join());
2497 +            rs[5].assertValue(v1);
2498 +        } catch (CompletionException ok) {
2499 +            checkCompletedWithWrappedException(h5, ex);
2500 +            rs[5].assertNotInvoked();
2501 +        }
2502 +
2503 +        checkCompletedExceptionally(f, ex);
2504 +        checkCompletedNormally(g, v1);
2505 +        checkCompletedWithWrappedException(h0, ex);
2506 +        checkCompletedWithWrappedException(h1, ex);
2507 +        checkCompletedWithWrappedException(h2, ex);
2508 +        checkCompletedWithWrappedException(h3, ex);
2509 +        checkCompletedWithWrappedException(h4, ex);
2510 +        for (int i = 0; i < 4; i++) rs[i].assertNotInvoked();
2511 +    }}
2512 +
2513 +    public void testAcceptEither_exceptionalCompletion2() {
2514 +        for (ExecutionMode m : ExecutionMode.values())
2515 +        for (boolean fFirst : new boolean[] { true, false })
2516 +        for (Integer v1 : new Integer[] { 1, null })
2517 +    {
2518 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2519 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2520 +        final CFException ex = new CFException();
2521 +        final NoopConsumer[] rs = new NoopConsumer[6];
2522 +        for (int i = 0; i < rs.length; i++) rs[i] = new NoopConsumer(m);
2523 +
2524 +        final CompletableFuture<Void> h0 = m.acceptEither(f, g, rs[0]);
2525 +        final CompletableFuture<Void> h1 = m.acceptEither(g, f, rs[1]);
2526 +        assertTrue(fFirst ? f.complete(v1) : g.completeExceptionally(ex));
2527 +        assertTrue(!fFirst ? f.complete(v1) : g.completeExceptionally(ex));
2528 +        final CompletableFuture<Void> h2 = m.acceptEither(f, g, rs[2]);
2529 +        final CompletableFuture<Void> h3 = m.acceptEither(g, f, rs[3]);
2530 +
2531 +        // unspecified behavior - both source completions available
2532 +        try {
2533 +            assertEquals(null, h0.join());
2534 +            rs[0].assertValue(v1);
2535 +        } catch (CompletionException ok) {
2536 +            checkCompletedWithWrappedException(h0, ex);
2537 +            rs[0].assertNotInvoked();
2538 +        }
2539 +        try {
2540 +            assertEquals(null, h1.join());
2541 +            rs[1].assertValue(v1);
2542 +        } catch (CompletionException ok) {
2543 +            checkCompletedWithWrappedException(h1, ex);
2544 +            rs[1].assertNotInvoked();
2545 +        }
2546 +        try {
2547 +            assertEquals(null, h2.join());
2548 +            rs[2].assertValue(v1);
2549 +        } catch (CompletionException ok) {
2550 +            checkCompletedWithWrappedException(h2, ex);
2551 +            rs[2].assertNotInvoked();
2552 +        }
2553 +        try {
2554 +            assertEquals(null, h3.join());
2555 +            rs[3].assertValue(v1);
2556 +        } catch (CompletionException ok) {
2557 +            checkCompletedWithWrappedException(h3, ex);
2558 +            rs[3].assertNotInvoked();
2559 +        }
2560 +
2561 +        checkCompletedNormally(f, v1);
2562 +        checkCompletedExceptionally(g, ex);
2563 +    }}
2564 +
2565 +    /**
2566 +     * acceptEither result completes exceptionally if either source cancelled
2567 +     */
2568 +    public void testAcceptEither_sourceCancelled() {
2569 +        for (ExecutionMode m : ExecutionMode.values())
2570 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
2571 +        for (Integer v1 : new Integer[] { 1, null })
2572 +    {
2573 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2574 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2575 +        final NoopConsumer[] rs = new NoopConsumer[6];
2576 +        for (int i = 0; i < rs.length; i++) rs[i] = new NoopConsumer(m);
2577 +
2578 +        final CompletableFuture<Void> h0 = m.acceptEither(f, g, rs[0]);
2579 +        final CompletableFuture<Void> h1 = m.acceptEither(g, f, rs[1]);
2580 +        checkIncomplete(h0);
2581 +        checkIncomplete(h1);
2582 +        rs[0].assertNotInvoked();
2583 +        rs[1].assertNotInvoked();
2584 +        f.cancel(mayInterruptIfRunning);
2585 +        checkCompletedWithWrappedCancellationException(h0);
2586 +        checkCompletedWithWrappedCancellationException(h1);
2587 +        final CompletableFuture<Void> h2 = m.acceptEither(f, g, rs[2]);
2588 +        final CompletableFuture<Void> h3 = m.acceptEither(g, f, rs[3]);
2589 +        checkCompletedWithWrappedCancellationException(h2);
2590 +        checkCompletedWithWrappedCancellationException(h3);
2591 +
2592 +        g.complete(v1);
2593 +
2594 +        // unspecified behavior - both source completions available
2595 +        final CompletableFuture<Void> h4 = m.acceptEither(f, g, rs[4]);
2596 +        final CompletableFuture<Void> h5 = m.acceptEither(g, f, rs[5]);
2597 +        try {
2598 +            assertNull(h4.join());
2599 +            rs[4].assertValue(v1);
2600 +        } catch (CompletionException ok) {
2601 +            checkCompletedWithWrappedCancellationException(h4);
2602 +            rs[4].assertNotInvoked();
2603 +        }
2604 +        try {
2605 +            assertNull(h5.join());
2606 +            rs[5].assertValue(v1);
2607 +        } catch (CompletionException ok) {
2608 +            checkCompletedWithWrappedCancellationException(h5);
2609 +            rs[5].assertNotInvoked();
2610 +        }
2611 +
2612 +        checkCancelled(f);
2613 +        checkCompletedNormally(g, v1);
2614 +        checkCompletedWithWrappedCancellationException(h0);
2615 +        checkCompletedWithWrappedCancellationException(h1);
2616 +        checkCompletedWithWrappedCancellationException(h2);
2617 +        checkCompletedWithWrappedCancellationException(h3);
2618 +        for (int i = 0; i < 4; i++) rs[i].assertNotInvoked();
2619 +    }}
2620 +
2621 +    /**
2622 +     * acceptEither result completes exceptionally if action does
2623 +     */
2624 +    public void testAcceptEither_actionFailed() {
2625 +        for (ExecutionMode m : ExecutionMode.values())
2626 +        for (Integer v1 : new Integer[] { 1, null })
2627 +        for (Integer v2 : new Integer[] { 2, null })
2628 +    {
2629 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2630 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2631 +        final FailingConsumer[] rs = new FailingConsumer[6];
2632 +        for (int i = 0; i < rs.length; i++) rs[i] = new FailingConsumer(m);
2633 +
2634 +        final CompletableFuture<Void> h0 = m.acceptEither(f, g, rs[0]);
2635 +        final CompletableFuture<Void> h1 = m.acceptEither(g, f, rs[1]);
2636 +        f.complete(v1);
2637 +        final CompletableFuture<Void> h2 = m.acceptEither(f, g, rs[2]);
2638 +        final CompletableFuture<Void> h3 = m.acceptEither(g, f, rs[3]);
2639 +        checkCompletedWithWrappedException(h0, rs[0].ex);
2640 +        checkCompletedWithWrappedException(h1, rs[1].ex);
2641 +        checkCompletedWithWrappedException(h2, rs[2].ex);
2642 +        checkCompletedWithWrappedException(h3, rs[3].ex);
2643 +        for (int i = 0; i < 4; i++) rs[i].assertValue(v1);
2644 +
2645 +        g.complete(v2);
2646 +
2647 +        // unspecified behavior - both source completions available
2648 +        final CompletableFuture<Void> h4 = m.acceptEither(f, g, rs[4]);
2649 +        final CompletableFuture<Void> h5 = m.acceptEither(g, f, rs[5]);
2650 +
2651 +        checkCompletedWithWrappedException(h4, rs[4].ex);
2652 +        assertTrue(Objects.equals(v1, rs[4].value) ||
2653 +                   Objects.equals(v2, rs[4].value));
2654 +        checkCompletedWithWrappedException(h5, rs[5].ex);
2655 +        assertTrue(Objects.equals(v1, rs[5].value) ||
2656 +                   Objects.equals(v2, rs[5].value));
2657 +
2658 +        checkCompletedNormally(f, v1);
2659 +        checkCompletedNormally(g, v2);
2660 +    }}
2661 +
2662 +    /**
2663 +     * runAfterEither result completes normally after normal completion
2664 +     * of either source
2665 +     */
2666 +    public void testRunAfterEither_normalCompletion() {
2667 +        for (ExecutionMode m : ExecutionMode.values())
2668 +        for (Integer v1 : new Integer[] { 1, null })
2669 +        for (Integer v2 : new Integer[] { 2, null })
2670 +    {
2671 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2672 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2673 +        final Noop[] rs = new Noop[6];
2674 +        for (int i = 0; i < rs.length; i++) rs[i] = new Noop(m);
2675 +
2676 +        final CompletableFuture<Void> h0 = m.runAfterEither(f, g, rs[0]);
2677 +        final CompletableFuture<Void> h1 = m.runAfterEither(g, f, rs[1]);
2678 +        checkIncomplete(h0);
2679 +        checkIncomplete(h1);
2680 +        rs[0].assertNotInvoked();
2681 +        rs[1].assertNotInvoked();
2682 +        f.complete(v1);
2683 +        checkCompletedNormally(h0, null);
2684 +        checkCompletedNormally(h1, null);
2685 +        rs[0].assertInvoked();
2686 +        rs[1].assertInvoked();
2687 +        final CompletableFuture<Void> h2 = m.runAfterEither(f, g, rs[2]);
2688 +        final CompletableFuture<Void> h3 = m.runAfterEither(g, f, rs[3]);
2689 +        checkCompletedNormally(h2, null);
2690 +        checkCompletedNormally(h3, null);
2691 +        rs[2].assertInvoked();
2692 +        rs[3].assertInvoked();
2693 +
2694 +        g.complete(v2);
2695 +
2696 +        final CompletableFuture<Void> h4 = m.runAfterEither(f, g, rs[4]);
2697 +        final CompletableFuture<Void> h5 = m.runAfterEither(g, f, rs[5]);
2698 +
2699 +        checkCompletedNormally(f, v1);
2700 +        checkCompletedNormally(g, v2);
2701 +        checkCompletedNormally(h0, null);
2702 +        checkCompletedNormally(h1, null);
2703 +        checkCompletedNormally(h2, null);
2704 +        checkCompletedNormally(h3, null);
2705 +        checkCompletedNormally(h4, null);
2706 +        checkCompletedNormally(h5, null);
2707 +        for (int i = 0; i < 6; i++) rs[i].assertInvoked();
2708 +    }}
2709 +
2710 +    /**
2711 +     * runAfterEither result completes exceptionally after exceptional
2712 +     * completion of either source
2713 +     */
2714 +    public void testRunAfterEither_exceptionalCompletion() {
2715 +        for (ExecutionMode m : ExecutionMode.values())
2716 +        for (Integer v1 : new Integer[] { 1, null })
2717 +    {
2718 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2719 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2720 +        final CFException ex = new CFException();
2721 +        final Noop[] rs = new Noop[6];
2722 +        for (int i = 0; i < rs.length; i++) rs[i] = new Noop(m);
2723 +
2724 +        final CompletableFuture<Void> h0 = m.runAfterEither(f, g, rs[0]);
2725 +        final CompletableFuture<Void> h1 = m.runAfterEither(g, f, rs[1]);
2726 +        checkIncomplete(h0);
2727 +        checkIncomplete(h1);
2728 +        rs[0].assertNotInvoked();
2729 +        rs[1].assertNotInvoked();
2730 +        assertTrue(f.completeExceptionally(ex));
2731 +        checkCompletedWithWrappedException(h0, ex);
2732 +        checkCompletedWithWrappedException(h1, ex);
2733 +        final CompletableFuture<Void> h2 = m.runAfterEither(f, g, rs[2]);
2734 +        final CompletableFuture<Void> h3 = m.runAfterEither(g, f, rs[3]);
2735 +        checkCompletedWithWrappedException(h2, ex);
2736 +        checkCompletedWithWrappedException(h3, ex);
2737 +
2738 +        assertTrue(g.complete(v1));
2739 +
2740 +        // unspecified behavior - both source completions available
2741 +        final CompletableFuture<Void> h4 = m.runAfterEither(f, g, rs[4]);
2742 +        final CompletableFuture<Void> h5 = m.runAfterEither(g, f, rs[5]);
2743 +        try {
2744 +            assertNull(h4.join());
2745 +            rs[4].assertInvoked();
2746 +        } catch (CompletionException ok) {
2747 +            checkCompletedWithWrappedException(h4, ex);
2748 +            rs[4].assertNotInvoked();
2749 +        }
2750 +        try {
2751 +            assertNull(h5.join());
2752 +            rs[5].assertInvoked();
2753 +        } catch (CompletionException ok) {
2754 +            checkCompletedWithWrappedException(h5, ex);
2755 +            rs[5].assertNotInvoked();
2756 +        }
2757 +
2758 +        checkCompletedExceptionally(f, ex);
2759 +        checkCompletedNormally(g, v1);
2760 +        checkCompletedWithWrappedException(h0, ex);
2761 +        checkCompletedWithWrappedException(h1, ex);
2762 +        checkCompletedWithWrappedException(h2, ex);
2763 +        checkCompletedWithWrappedException(h3, ex);
2764 +        checkCompletedWithWrappedException(h4, ex);
2765 +        for (int i = 0; i < 4; i++) rs[i].assertNotInvoked();
2766 +    }}
2767 +
2768 +    public void testRunAfterEither_exceptionalCompletion2() {
2769 +        for (ExecutionMode m : ExecutionMode.values())
2770 +        for (boolean fFirst : new boolean[] { true, false })
2771 +        for (Integer v1 : new Integer[] { 1, null })
2772 +    {
2773 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2774 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2775 +        final CFException ex = new CFException();
2776 +        final Noop[] rs = new Noop[6];
2777 +        for (int i = 0; i < rs.length; i++) rs[i] = new Noop(m);
2778 +
2779 +        final CompletableFuture<Void> h0 = m.runAfterEither(f, g, rs[0]);
2780 +        final CompletableFuture<Void> h1 = m.runAfterEither(g, f, rs[1]);
2781 +        assertTrue( fFirst ? f.complete(v1) : g.completeExceptionally(ex));
2782 +        assertTrue(!fFirst ? f.complete(v1) : g.completeExceptionally(ex));
2783 +        final CompletableFuture<Void> h2 = m.runAfterEither(f, g, rs[2]);
2784 +        final CompletableFuture<Void> h3 = m.runAfterEither(g, f, rs[3]);
2785 +
2786 +        // unspecified behavior - both source completions available
2787 +        try {
2788 +            assertEquals(null, h0.join());
2789 +            rs[0].assertInvoked();
2790 +        } catch (CompletionException ok) {
2791 +            checkCompletedWithWrappedException(h0, ex);
2792 +            rs[0].assertNotInvoked();
2793 +        }
2794 +        try {
2795 +            assertEquals(null, h1.join());
2796 +            rs[1].assertInvoked();
2797 +        } catch (CompletionException ok) {
2798 +            checkCompletedWithWrappedException(h1, ex);
2799 +            rs[1].assertNotInvoked();
2800 +        }
2801 +        try {
2802 +            assertEquals(null, h2.join());
2803 +            rs[2].assertInvoked();
2804 +        } catch (CompletionException ok) {
2805 +            checkCompletedWithWrappedException(h2, ex);
2806 +            rs[2].assertNotInvoked();
2807 +        }
2808 +        try {
2809 +            assertEquals(null, h3.join());
2810 +            rs[3].assertInvoked();
2811 +        } catch (CompletionException ok) {
2812 +            checkCompletedWithWrappedException(h3, ex);
2813 +            rs[3].assertNotInvoked();
2814 +        }
2815 +
2816 +        checkCompletedNormally(f, v1);
2817 +        checkCompletedExceptionally(g, ex);
2818 +    }}
2819 +
2820 +    /**
2821 +     * runAfterEither result completes exceptionally if either source cancelled
2822 +     */
2823 +    public void testRunAfterEither_sourceCancelled() {
2824 +        for (ExecutionMode m : ExecutionMode.values())
2825 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
2826 +        for (Integer v1 : new Integer[] { 1, null })
2827 +    {
2828 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2829 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2830 +        final Noop[] rs = new Noop[6];
2831 +        for (int i = 0; i < rs.length; i++) rs[i] = new Noop(m);
2832 +
2833 +        final CompletableFuture<Void> h0 = m.runAfterEither(f, g, rs[0]);
2834 +        final CompletableFuture<Void> h1 = m.runAfterEither(g, f, rs[1]);
2835 +        checkIncomplete(h0);
2836 +        checkIncomplete(h1);
2837 +        rs[0].assertNotInvoked();
2838 +        rs[1].assertNotInvoked();
2839 +        f.cancel(mayInterruptIfRunning);
2840 +        checkCompletedWithWrappedCancellationException(h0);
2841 +        checkCompletedWithWrappedCancellationException(h1);
2842 +        final CompletableFuture<Void> h2 = m.runAfterEither(f, g, rs[2]);
2843 +        final CompletableFuture<Void> h3 = m.runAfterEither(g, f, rs[3]);
2844 +        checkCompletedWithWrappedCancellationException(h2);
2845 +        checkCompletedWithWrappedCancellationException(h3);
2846 +
2847 +        assertTrue(g.complete(v1));
2848 +
2849 +        // unspecified behavior - both source completions available
2850 +        final CompletableFuture<Void> h4 = m.runAfterEither(f, g, rs[4]);
2851 +        final CompletableFuture<Void> h5 = m.runAfterEither(g, f, rs[5]);
2852 +        try {
2853 +            assertNull(h4.join());
2854 +            rs[4].assertInvoked();
2855 +        } catch (CompletionException ok) {
2856 +            checkCompletedWithWrappedCancellationException(h4);
2857 +            rs[4].assertNotInvoked();
2858 +        }
2859 +        try {
2860 +            assertNull(h5.join());
2861 +            rs[5].assertInvoked();
2862 +        } catch (CompletionException ok) {
2863 +            checkCompletedWithWrappedCancellationException(h5);
2864 +            rs[5].assertNotInvoked();
2865 +        }
2866 +
2867 +        checkCancelled(f);
2868 +        checkCompletedNormally(g, v1);
2869 +        checkCompletedWithWrappedCancellationException(h0);
2870 +        checkCompletedWithWrappedCancellationException(h1);
2871 +        checkCompletedWithWrappedCancellationException(h2);
2872 +        checkCompletedWithWrappedCancellationException(h3);
2873 +        for (int i = 0; i < 4; i++) rs[i].assertNotInvoked();
2874 +    }}
2875 +
2876 +    /**
2877 +     * runAfterEither result completes exceptionally if action does
2878 +     */
2879 +    public void testRunAfterEither_actionFailed() {
2880 +        for (ExecutionMode m : ExecutionMode.values())
2881 +        for (Integer v1 : new Integer[] { 1, null })
2882 +        for (Integer v2 : new Integer[] { 2, null })
2883 +    {
2884 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2885 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2886 +        final FailingRunnable[] rs = new FailingRunnable[6];
2887 +        for (int i = 0; i < rs.length; i++) rs[i] = new FailingRunnable(m);
2888 +
2889 +        final CompletableFuture<Void> h0 = m.runAfterEither(f, g, rs[0]);
2890 +        final CompletableFuture<Void> h1 = m.runAfterEither(g, f, rs[1]);
2891 +        assertTrue(f.complete(v1));
2892 +        final CompletableFuture<Void> h2 = m.runAfterEither(f, g, rs[2]);
2893 +        final CompletableFuture<Void> h3 = m.runAfterEither(g, f, rs[3]);
2894 +        checkCompletedWithWrappedException(h0, rs[0].ex);
2895 +        checkCompletedWithWrappedException(h1, rs[1].ex);
2896 +        checkCompletedWithWrappedException(h2, rs[2].ex);
2897 +        checkCompletedWithWrappedException(h3, rs[3].ex);
2898 +        for (int i = 0; i < 4; i++) rs[i].assertInvoked();
2899 +        assertTrue(g.complete(v2));
2900 +        final CompletableFuture<Void> h4 = m.runAfterEither(f, g, rs[4]);
2901 +        final CompletableFuture<Void> h5 = m.runAfterEither(g, f, rs[5]);
2902 +        checkCompletedWithWrappedException(h4, rs[4].ex);
2903 +        checkCompletedWithWrappedException(h5, rs[5].ex);
2904 +
2905 +        checkCompletedNormally(f, v1);
2906 +        checkCompletedNormally(g, v2);
2907 +        for (int i = 0; i < 6; i++) rs[i].assertInvoked();
2908 +    }}
2909 +
2910 +    /**
2911 +     * thenCompose result completes normally after normal completion of source
2912 +     */
2913 +    public void testThenCompose_normalCompletion() {
2914 +        for (ExecutionMode m : ExecutionMode.values())
2915 +        for (boolean createIncomplete : new boolean[] { true, false })
2916 +        for (Integer v1 : new Integer[] { 1, null })
2917 +    {
2918 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2919 +        final CompletableFutureInc r = new CompletableFutureInc(m);
2920 +        if (!createIncomplete) assertTrue(f.complete(v1));
2921 +        final CompletableFuture<Integer> g = m.thenCompose(f, r);
2922 +        if (createIncomplete) assertTrue(f.complete(v1));
2923 +
2924 +        checkCompletedNormally(g, inc(v1));
2925 +        checkCompletedNormally(f, v1);
2926 +        r.assertValue(v1);
2927 +    }}
2928 +
2929 +    /**
2930 +     * thenCompose result completes exceptionally after exceptional
2931 +     * completion of source
2932 +     */
2933 +    public void testThenCompose_exceptionalCompletion() {
2934 +        for (ExecutionMode m : ExecutionMode.values())
2935 +        for (boolean createIncomplete : new boolean[] { true, false })
2936 +    {
2937 +        final CFException ex = new CFException();
2938 +        final CompletableFutureInc r = new CompletableFutureInc(m);
2939 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2940 +        if (!createIncomplete) f.completeExceptionally(ex);
2941 +        final CompletableFuture<Integer> g = m.thenCompose(f, r);
2942 +        if (createIncomplete) f.completeExceptionally(ex);
2943 +
2944 +        checkCompletedWithWrappedException(g, ex);
2945 +        checkCompletedExceptionally(f, ex);
2946 +        r.assertNotInvoked();
2947 +    }}
2948 +
2949 +    /**
2950 +     * thenCompose result completes exceptionally if action does
2951 +     */
2952 +    public void testThenCompose_actionFailed() {
2953 +        for (ExecutionMode m : ExecutionMode.values())
2954 +        for (boolean createIncomplete : new boolean[] { true, false })
2955 +        for (Integer v1 : new Integer[] { 1, null })
2956 +    {
2957 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2958 +        final FailingCompletableFutureFunction r
2959 +            = new FailingCompletableFutureFunction(m);
2960 +        if (!createIncomplete) assertTrue(f.complete(v1));
2961 +        final CompletableFuture<Integer> g = m.thenCompose(f, r);
2962 +        if (createIncomplete) assertTrue(f.complete(v1));
2963 +
2964 +        checkCompletedWithWrappedException(g, r.ex);
2965 +        checkCompletedNormally(f, v1);
2966 +    }}
2967 +
2968 +    /**
2969 +     * thenCompose result completes exceptionally if source cancelled
2970 +     */
2971 +    public void testThenCompose_sourceCancelled() {
2972 +        for (ExecutionMode m : ExecutionMode.values())
2973 +        for (boolean createIncomplete : new boolean[] { true, false })
2974 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
2975 +    {
2976 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2977 +        final CompletableFutureInc r = new CompletableFutureInc(m);
2978 +        if (!createIncomplete) assertTrue(f.cancel(mayInterruptIfRunning));
2979 +        final CompletableFuture<Integer> g = m.thenCompose(f, r);
2980 +        if (createIncomplete) {
2981 +            checkIncomplete(g);
2982 +            assertTrue(f.cancel(mayInterruptIfRunning));
2983 +        }
2984 +
2985 +        checkCompletedWithWrappedCancellationException(g);
2986 +        checkCancelled(f);
2987 +    }}
2988 +
2989 +    /**
2990 +     * thenCompose result completes exceptionally if the result of the action does
2991 +     */
2992 +    public void testThenCompose_actionReturnsFailingFuture() {
2993 +        for (ExecutionMode m : ExecutionMode.values())
2994 +        for (int order = 0; order < 6; order++)
2995 +        for (Integer v1 : new Integer[] { 1, null })
2996 +    {
2997 +        final CFException ex = new CFException();
2998 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2999 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
3000 +        final CompletableFuture<Integer> h;
3001 +        // Test all permutations of orders
3002 +        switch (order) {
3003 +        case 0:
3004 +            assertTrue(f.complete(v1));
3005 +            assertTrue(g.completeExceptionally(ex));
3006 +            h = m.thenCompose(f, (x -> g));
3007 +            break;
3008 +        case 1:
3009 +            assertTrue(f.complete(v1));
3010 +            h = m.thenCompose(f, (x -> g));
3011 +            assertTrue(g.completeExceptionally(ex));
3012 +            break;
3013 +        case 2:
3014 +            assertTrue(g.completeExceptionally(ex));
3015 +            assertTrue(f.complete(v1));
3016 +            h = m.thenCompose(f, (x -> g));
3017 +            break;
3018 +        case 3:
3019 +            assertTrue(g.completeExceptionally(ex));
3020 +            h = m.thenCompose(f, (x -> g));
3021 +            assertTrue(f.complete(v1));
3022 +            break;
3023 +        case 4:
3024 +            h = m.thenCompose(f, (x -> g));
3025 +            assertTrue(f.complete(v1));
3026 +            assertTrue(g.completeExceptionally(ex));
3027 +            break;
3028 +        case 5:
3029 +            h = m.thenCompose(f, (x -> g));
3030 +            assertTrue(f.complete(v1));
3031 +            assertTrue(g.completeExceptionally(ex));
3032 +            break;
3033 +        default: throw new AssertionError();
3034 +        }
3035 +
3036 +        checkCompletedExceptionally(g, ex);
3037 +        checkCompletedWithWrappedException(h, ex);
3038 +        checkCompletedNormally(f, v1);
3039 +    }}
3040 +
3041 +    // other static methods
3042 +
3043 +    /**
3044 +     * allOf(no component futures) returns a future completed normally
3045 +     * with the value null
3046 +     */
3047 +    public void testAllOf_empty() throws Exception {
3048 +        CompletableFuture<Void> f = CompletableFuture.allOf();
3049 +        checkCompletedNormally(f, null);
3050 +    }
3051 +
3052 +    /**
3053 +     * allOf returns a future completed normally with the value null
3054 +     * when all components complete normally
3055 +     */
3056 +    public void testAllOf_normal() throws Exception {
3057 +        for (int k = 1; k < 10; k++) {
3058 +            CompletableFuture<Integer>[] fs
3059 +                = (CompletableFuture<Integer>[]) new CompletableFuture[k];
3060 +            for (int i = 0; i < k; i++)
3061 +                fs[i] = new CompletableFuture<>();
3062 +            CompletableFuture<Void> f = CompletableFuture.allOf(fs);
3063 +            for (int i = 0; i < k; i++) {
3064 +                checkIncomplete(f);
3065 +                checkIncomplete(CompletableFuture.allOf(fs));
3066 +                fs[i].complete(one);
3067 +            }
3068 +            checkCompletedNormally(f, null);
3069 +            checkCompletedNormally(CompletableFuture.allOf(fs), null);
3070 +        }
3071 +    }
3072 +
3073 +    public void testAllOf_normal_backwards() throws Exception {
3074 +        for (int k = 1; k < 10; k++) {
3075 +            CompletableFuture<Integer>[] fs
3076 +                = (CompletableFuture<Integer>[]) new CompletableFuture[k];
3077 +            for (int i = 0; i < k; i++)
3078 +                fs[i] = new CompletableFuture<>();
3079 +            CompletableFuture<Void> f = CompletableFuture.allOf(fs);
3080 +            for (int i = k - 1; i >= 0; i--) {
3081 +                checkIncomplete(f);
3082 +                checkIncomplete(CompletableFuture.allOf(fs));
3083 +                fs[i].complete(one);
3084 +            }
3085 +            checkCompletedNormally(f, null);
3086 +            checkCompletedNormally(CompletableFuture.allOf(fs), null);
3087 +        }
3088 +    }
3089 +
3090 +    public void testAllOf_exceptional() throws Exception {
3091 +        for (int k = 1; k < 10; k++) {
3092 +            CompletableFuture<Integer>[] fs
3093 +                = (CompletableFuture<Integer>[]) new CompletableFuture[k];
3094 +            CFException ex = new CFException();
3095 +            for (int i = 0; i < k; i++)
3096 +                fs[i] = new CompletableFuture<>();
3097 +            CompletableFuture<Void> f = CompletableFuture.allOf(fs);
3098 +            for (int i = 0; i < k; i++) {
3099 +                checkIncomplete(f);
3100 +                checkIncomplete(CompletableFuture.allOf(fs));
3101 +                if (i != k / 2) {
3102 +                    fs[i].complete(i);
3103 +                    checkCompletedNormally(fs[i], i);
3104 +                } else {
3105 +                    fs[i].completeExceptionally(ex);
3106 +                    checkCompletedExceptionally(fs[i], ex);
3107 +                }
3108 +            }
3109 +            checkCompletedWithWrappedException(f, ex);
3110 +            checkCompletedWithWrappedException(CompletableFuture.allOf(fs), ex);
3111 +        }
3112 +    }
3113 +
3114 +    /**
3115 +     * anyOf(no component futures) returns an incomplete future
3116 +     */
3117 +    public void testAnyOf_empty() throws Exception {
3118 +        for (Integer v1 : new Integer[] { 1, null })
3119 +    {
3120 +        CompletableFuture<Object> f = CompletableFuture.anyOf();
3121 +        checkIncomplete(f);
3122 +
3123 +        f.complete(v1);
3124 +        checkCompletedNormally(f, v1);
3125 +    }}
3126 +
3127 +    /**
3128 +     * anyOf returns a future completed normally with a value when
3129 +     * a component future does
3130 +     */
3131 +    public void testAnyOf_normal() throws Exception {
3132 +        for (int k = 0; k < 10; k++) {
3133 +            CompletableFuture[] fs = new CompletableFuture[k];
3134 +            for (int i = 0; i < k; i++)
3135 +                fs[i] = new CompletableFuture<>();
3136 +            CompletableFuture<Object> f = CompletableFuture.anyOf(fs);
3137 +            checkIncomplete(f);
3138 +            for (int i = 0; i < k; i++) {
3139 +                fs[i].complete(i);
3140 +                checkCompletedNormally(f, 0);
3141 +                int x = (int) CompletableFuture.anyOf(fs).join();
3142 +                assertTrue(0 <= x && x <= i);
3143 +            }
3144 +        }
3145 +    }
3146 +    public void testAnyOf_normal_backwards() throws Exception {
3147 +        for (int k = 0; k < 10; k++) {
3148 +            CompletableFuture[] fs = new CompletableFuture[k];
3149 +            for (int i = 0; i < k; i++)
3150 +                fs[i] = new CompletableFuture<>();
3151 +            CompletableFuture<Object> f = CompletableFuture.anyOf(fs);
3152 +            checkIncomplete(f);
3153 +            for (int i = k - 1; i >= 0; i--) {
3154 +                fs[i].complete(i);
3155 +                checkCompletedNormally(f, k - 1);
3156 +                int x = (int) CompletableFuture.anyOf(fs).join();
3157 +                assertTrue(i <= x && x <= k - 1);
3158 +            }
3159 +        }
3160 +    }
3161 +
3162 +    /**
3163 +     * anyOf result completes exceptionally when any component does.
3164 +     */
3165 +    public void testAnyOf_exceptional() throws Exception {
3166 +        for (int k = 0; k < 10; k++) {
3167 +            CompletableFuture[] fs = new CompletableFuture[k];
3168 +            CFException[] exs = new CFException[k];
3169 +            for (int i = 0; i < k; i++) {
3170 +                fs[i] = new CompletableFuture<>();
3171 +                exs[i] = new CFException();
3172 +            }
3173 +            CompletableFuture<Object> f = CompletableFuture.anyOf(fs);
3174 +            checkIncomplete(f);
3175 +            for (int i = 0; i < k; i++) {
3176 +                fs[i].completeExceptionally(exs[i]);
3177 +                checkCompletedWithWrappedException(f, exs[0]);
3178 +                checkCompletedWithWrappedCFException(CompletableFuture.anyOf(fs));
3179 +            }
3180 +        }
3181 +    }
3182 +
3183 +    public void testAnyOf_exceptional_backwards() throws Exception {
3184 +        for (int k = 0; k < 10; k++) {
3185 +            CompletableFuture[] fs = new CompletableFuture[k];
3186 +            CFException[] exs = new CFException[k];
3187 +            for (int i = 0; i < k; i++) {
3188 +                fs[i] = new CompletableFuture<>();
3189 +                exs[i] = new CFException();
3190 +            }
3191 +            CompletableFuture<Object> f = CompletableFuture.anyOf(fs);
3192 +            checkIncomplete(f);
3193 +            for (int i = k - 1; i >= 0; i--) {
3194 +                fs[i].completeExceptionally(exs[i]);
3195 +                checkCompletedWithWrappedException(f, exs[k - 1]);
3196 +                checkCompletedWithWrappedCFException(CompletableFuture.anyOf(fs));
3197 +            }
3198 +        }
3199 +    }
3200 +
3201 +    /**
3202 +     * Completion methods throw NullPointerException with null arguments
3203 +     */
3204 +    public void testNPE() {
3205 +        CompletableFuture<Integer> f = new CompletableFuture<>();
3206 +        CompletableFuture<Integer> g = new CompletableFuture<>();
3207 +        CompletableFuture<Integer> nullFuture = (CompletableFuture<Integer>)null;
3208 +        ThreadExecutor exec = new ThreadExecutor();
3209 +
3210 +        Runnable[] throwingActions = {
3211 +            () -> CompletableFuture.supplyAsync(null),
3212 +            () -> CompletableFuture.supplyAsync(null, exec),
3213 +            () -> CompletableFuture.supplyAsync(new IntegerSupplier(ExecutionMode.SYNC, 42), null),
3214 +
3215 +            () -> CompletableFuture.runAsync(null),
3216 +            () -> CompletableFuture.runAsync(null, exec),
3217 +            () -> CompletableFuture.runAsync(() -> {}, null),
3218 +
3219 +            () -> f.completeExceptionally(null),
3220 +
3221 +            () -> f.thenApply(null),
3222 +            () -> f.thenApplyAsync(null),
3223 +            () -> f.thenApplyAsync((x) -> x, null),
3224 +            () -> f.thenApplyAsync(null, exec),
3225 +
3226 +            () -> f.thenAccept(null),
3227 +            () -> f.thenAcceptAsync(null),
3228 +            () -> f.thenAcceptAsync((x) -> {} , null),
3229 +            () -> f.thenAcceptAsync(null, exec),
3230 +
3231 +            () -> f.thenRun(null),
3232 +            () -> f.thenRunAsync(null),
3233 +            () -> f.thenRunAsync(() -> {} , null),
3234 +            () -> f.thenRunAsync(null, exec),
3235 +
3236 +            () -> f.thenCombine(g, null),
3237 +            () -> f.thenCombineAsync(g, null),
3238 +            () -> f.thenCombineAsync(g, null, exec),
3239 +            () -> f.thenCombine(nullFuture, (x, y) -> x),
3240 +            () -> f.thenCombineAsync(nullFuture, (x, y) -> x),
3241 +            () -> f.thenCombineAsync(nullFuture, (x, y) -> x, exec),
3242 +            () -> f.thenCombineAsync(g, (x, y) -> x, null),
3243 +
3244 +            () -> f.thenAcceptBoth(g, null),
3245 +            () -> f.thenAcceptBothAsync(g, null),
3246 +            () -> f.thenAcceptBothAsync(g, null, exec),
3247 +            () -> f.thenAcceptBoth(nullFuture, (x, y) -> {}),
3248 +            () -> f.thenAcceptBothAsync(nullFuture, (x, y) -> {}),
3249 +            () -> f.thenAcceptBothAsync(nullFuture, (x, y) -> {}, exec),
3250 +            () -> f.thenAcceptBothAsync(g, (x, y) -> {}, null),
3251 +
3252 +            () -> f.runAfterBoth(g, null),
3253 +            () -> f.runAfterBothAsync(g, null),
3254 +            () -> f.runAfterBothAsync(g, null, exec),
3255 +            () -> f.runAfterBoth(nullFuture, () -> {}),
3256 +            () -> f.runAfterBothAsync(nullFuture, () -> {}),
3257 +            () -> f.runAfterBothAsync(nullFuture, () -> {}, exec),
3258 +            () -> f.runAfterBothAsync(g, () -> {}, null),
3259 +
3260 +            () -> f.applyToEither(g, null),
3261 +            () -> f.applyToEitherAsync(g, null),
3262 +            () -> f.applyToEitherAsync(g, null, exec),
3263 +            () -> f.applyToEither(nullFuture, (x) -> x),
3264 +            () -> f.applyToEitherAsync(nullFuture, (x) -> x),
3265 +            () -> f.applyToEitherAsync(nullFuture, (x) -> x, exec),
3266 +            () -> f.applyToEitherAsync(g, (x) -> x, null),
3267 +
3268 +            () -> f.acceptEither(g, null),
3269 +            () -> f.acceptEitherAsync(g, null),
3270 +            () -> f.acceptEitherAsync(g, null, exec),
3271 +            () -> f.acceptEither(nullFuture, (x) -> {}),
3272 +            () -> f.acceptEitherAsync(nullFuture, (x) -> {}),
3273 +            () -> f.acceptEitherAsync(nullFuture, (x) -> {}, exec),
3274 +            () -> f.acceptEitherAsync(g, (x) -> {}, null),
3275 +
3276 +            () -> f.runAfterEither(g, null),
3277 +            () -> f.runAfterEitherAsync(g, null),
3278 +            () -> f.runAfterEitherAsync(g, null, exec),
3279 +            () -> f.runAfterEither(nullFuture, () -> {}),
3280 +            () -> f.runAfterEitherAsync(nullFuture, () -> {}),
3281 +            () -> f.runAfterEitherAsync(nullFuture, () -> {}, exec),
3282 +            () -> f.runAfterEitherAsync(g, () -> {}, null),
3283 +
3284 +            () -> f.thenCompose(null),
3285 +            () -> f.thenComposeAsync(null),
3286 +            () -> f.thenComposeAsync(new CompletableFutureInc(ExecutionMode.EXECUTOR), null),
3287 +            () -> f.thenComposeAsync(null, exec),
3288 +
3289 +            () -> f.exceptionally(null),
3290 +
3291 +            () -> f.handle(null),
3292 +
3293 +            () -> CompletableFuture.allOf((CompletableFuture<?>)null),
3294 +            () -> CompletableFuture.allOf((CompletableFuture<?>[])null),
3295 +            () -> CompletableFuture.allOf(f, null),
3296 +            () -> CompletableFuture.allOf(null, f),
3297 +
3298 +            () -> CompletableFuture.anyOf((CompletableFuture<?>)null),
3299 +            () -> CompletableFuture.anyOf((CompletableFuture<?>[])null),
3300 +            () -> CompletableFuture.anyOf(f, null),
3301 +            () -> CompletableFuture.anyOf(null, f),
3302 +
3303 +            () -> f.obtrudeException(null),
3304 +
3305 +            () -> CompletableFuture.delayedExecutor(1L, SECONDS, null),
3306 +            () -> CompletableFuture.delayedExecutor(1L, null, exec),
3307 +            () -> CompletableFuture.delayedExecutor(1L, null),
3308 +
3309 +            () -> f.orTimeout(1L, null),
3310 +            () -> f.completeOnTimeout(42, 1L, null),
3311 +
3312 +            () -> CompletableFuture.failedFuture(null),
3313 +            () -> CompletableFuture.failedStage(null),
3314 +        };
3315 +
3316 +        assertThrows(NullPointerException.class, throwingActions);
3317 +        assertEquals(0, exec.count.get());
3318 +    }
3319 +
3320 +    static class CountingRejectingExecutor implements Executor {
3321 +        final RejectedExecutionException ex = new RejectedExecutionException();
3322 +        final AtomicInteger count = new AtomicInteger(0);
3323 +        public void execute(Runnable r) {
3324 +            count.getAndIncrement();
3325 +            throw ex;
3326 +        }
3327 +    }
3328 +
3329 +    /**
3330 +     * Test submissions to an executor that rejects all tasks.
3331 +     */
3332 +    public void testRejectingExecutor() {
3333 +        for (Integer v : new Integer[] { 1, null }) {
3334 +
3335 +        final CountingRejectingExecutor e = new CountingRejectingExecutor();
3336 +
3337 +        final CompletableFuture<Integer> complete = CompletableFuture.completedFuture(v);
3338 +        final CompletableFuture<Integer> incomplete = new CompletableFuture<>();
3339 +
3340 +        List<CompletableFuture<?>> futures = new ArrayList<>();
3341 +
3342 +        List<CompletableFuture<Integer>> srcs = new ArrayList<>();
3343 +        srcs.add(complete);
3344 +        srcs.add(incomplete);
3345 +
3346 +        for (CompletableFuture<Integer> src : srcs) {
3347 +            List<CompletableFuture<?>> fs = new ArrayList<>();
3348 +            fs.add(src.thenRunAsync(() -> {}, e));
3349 +            fs.add(src.thenAcceptAsync((z) -> {}, e));
3350 +            fs.add(src.thenApplyAsync((z) -> z, e));
3351 +
3352 +            fs.add(src.thenCombineAsync(src, (x, y) -> x, e));
3353 +            fs.add(src.thenAcceptBothAsync(src, (x, y) -> {}, e));
3354 +            fs.add(src.runAfterBothAsync(src, () -> {}, e));
3355 +
3356 +            fs.add(src.applyToEitherAsync(src, (z) -> z, e));
3357 +            fs.add(src.acceptEitherAsync(src, (z) -> {}, e));
3358 +            fs.add(src.runAfterEitherAsync(src, () -> {}, e));
3359 +
3360 +            fs.add(src.thenComposeAsync((z) -> null, e));
3361 +            fs.add(src.whenCompleteAsync((z, t) -> {}, e));
3362 +            fs.add(src.handleAsync((z, t) -> null, e));
3363 +
3364 +            for (CompletableFuture<?> future : fs) {
3365 +                if (src.isDone())
3366 +                    checkCompletedWithWrappedException(future, e.ex);
3367 +                else
3368 +                    checkIncomplete(future);
3369 +            }
3370 +            futures.addAll(fs);
3371 +        }
3372 +
3373 +        {
3374 +            List<CompletableFuture<?>> fs = new ArrayList<>();
3375 +
3376 +            fs.add(complete.thenCombineAsync(incomplete, (x, y) -> x, e));
3377 +            fs.add(incomplete.thenCombineAsync(complete, (x, y) -> x, e));
3378 +
3379 +            fs.add(complete.thenAcceptBothAsync(incomplete, (x, y) -> {}, e));
3380 +            fs.add(incomplete.thenAcceptBothAsync(complete, (x, y) -> {}, e));
3381 +
3382 +            fs.add(complete.runAfterBothAsync(incomplete, () -> {}, e));
3383 +            fs.add(incomplete.runAfterBothAsync(complete, () -> {}, e));
3384 +
3385 +            for (CompletableFuture<?> future : fs)
3386 +                checkIncomplete(future);
3387 +            futures.addAll(fs);
3388 +        }
3389 +
3390 +        {
3391 +            List<CompletableFuture<?>> fs = new ArrayList<>();
3392 +
3393 +            fs.add(complete.applyToEitherAsync(incomplete, (z) -> z, e));
3394 +            fs.add(incomplete.applyToEitherAsync(complete, (z) -> z, e));
3395 +
3396 +            fs.add(complete.acceptEitherAsync(incomplete, (z) -> {}, e));
3397 +            fs.add(incomplete.acceptEitherAsync(complete, (z) -> {}, e));
3398 +
3399 +            fs.add(complete.runAfterEitherAsync(incomplete, () -> {}, e));
3400 +            fs.add(incomplete.runAfterEitherAsync(complete, () -> {}, e));
3401 +
3402 +            for (CompletableFuture<?> future : fs)
3403 +                checkCompletedWithWrappedException(future, e.ex);
3404 +            futures.addAll(fs);
3405 +        }
3406 +
3407 +        incomplete.complete(v);
3408 +
3409 +        for (CompletableFuture<?> future : futures)
3410 +            checkCompletedWithWrappedException(future, e.ex);
3411 +
3412 +        assertEquals(futures.size(), e.count.get());
3413 +
3414 +        }
3415 +    }
3416 +
3417 +    /**
3418 +     * Test submissions to an executor that rejects all tasks, but
3419 +     * should never be invoked because the dependent future is
3420 +     * explicitly completed.
3421 +     */
3422 +    public void testRejectingExecutorNeverInvoked() {
3423 +        final CountingRejectingExecutor e = new CountingRejectingExecutor();
3424 +
3425 +        for (Integer v : new Integer[] { 1, null }) {
3426 +
3427 +        final CompletableFuture<Integer> complete = CompletableFuture.completedFuture(v);
3428 +        final CompletableFuture<Integer> incomplete = new CompletableFuture<>();
3429 +
3430 +        List<CompletableFuture<?>> futures = new ArrayList<>();
3431 +
3432 +        List<CompletableFuture<Integer>> srcs = new ArrayList<>();
3433 +        srcs.add(complete);
3434 +        srcs.add(incomplete);
3435 +
3436 +        List<CompletableFuture<?>> fs = new ArrayList<>();
3437 +        fs.add(incomplete.thenRunAsync(() -> {}, e));
3438 +        fs.add(incomplete.thenAcceptAsync((z) -> {}, e));
3439 +        fs.add(incomplete.thenApplyAsync((z) -> z, e));
3440 +
3441 +        fs.add(incomplete.thenCombineAsync(incomplete, (x, y) -> x, e));
3442 +        fs.add(incomplete.thenAcceptBothAsync(incomplete, (x, y) -> {}, e));
3443 +        fs.add(incomplete.runAfterBothAsync(incomplete, () -> {}, e));
3444 +
3445 +        fs.add(incomplete.applyToEitherAsync(incomplete, (z) -> z, e));
3446 +        fs.add(incomplete.acceptEitherAsync(incomplete, (z) -> {}, e));
3447 +        fs.add(incomplete.runAfterEitherAsync(incomplete, () -> {}, e));
3448 +
3449 +        fs.add(incomplete.thenComposeAsync((z) -> null, e));
3450 +        fs.add(incomplete.whenCompleteAsync((z, t) -> {}, e));
3451 +        fs.add(incomplete.handleAsync((z, t) -> null, e));
3452 +
3453 +        fs.add(complete.thenCombineAsync(incomplete, (x, y) -> x, e));
3454 +        fs.add(incomplete.thenCombineAsync(complete, (x, y) -> x, e));
3455 +
3456 +        fs.add(complete.thenAcceptBothAsync(incomplete, (x, y) -> {}, e));
3457 +        fs.add(incomplete.thenAcceptBothAsync(complete, (x, y) -> {}, e));
3458 +
3459 +        fs.add(complete.runAfterBothAsync(incomplete, () -> {}, e));
3460 +        fs.add(incomplete.runAfterBothAsync(complete, () -> {}, e));
3461 +
3462 +        for (CompletableFuture<?> future : fs)
3463 +            checkIncomplete(future);
3464 +
3465 +        for (CompletableFuture<?> future : fs)
3466 +            future.complete(null);
3467 +
3468 +        incomplete.complete(v);
3469 +
3470 +        for (CompletableFuture<?> future : fs)
3471 +            checkCompletedNormally(future, null);
3472 +
3473 +        assertEquals(0, e.count.get());
3474 +
3475 +        }
3476 +    }
3477 +
3478 +    /**
3479 +     * toCompletableFuture returns this CompletableFuture.
3480 +     */
3481 +    public void testToCompletableFuture() {
3482 +        CompletableFuture<Integer> f = new CompletableFuture<>();
3483 +        assertSame(f, f.toCompletableFuture());
3484 +    }
3485 +
3486 +    // jdk9
3487 +
3488 +    /**
3489 +     * newIncompleteFuture returns an incomplete CompletableFuture
3490 +     */
3491 +    public void testNewIncompleteFuture() {
3492 +        for (Integer v1 : new Integer[] { 1, null })
3493 +    {
3494 +        CompletableFuture<Integer> f = new CompletableFuture<>();
3495 +        CompletableFuture<Integer> g = f.newIncompleteFuture();
3496 +        checkIncomplete(f);
3497 +        checkIncomplete(g);
3498 +        f.complete(v1);
3499 +        checkCompletedNormally(f, v1);
3500 +        checkIncomplete(g);
3501 +        g.complete(v1);
3502 +        checkCompletedNormally(g, v1);
3503 +        assertSame(g.getClass(), CompletableFuture.class);
3504 +    }}
3505 +
3506 +    /**
3507 +     * completedStage returns a completed CompletionStage
3508 +     */
3509 +    public void testCompletedStage() {
3510 +        AtomicInteger x = new AtomicInteger(0);
3511 +        AtomicReference<Throwable> r = new AtomicReference<Throwable>();
3512 +        CompletionStage<Integer> f = CompletableFuture.completedStage(1);
3513 +        f.whenComplete((v, e) -> {if (e != null) r.set(e); else x.set(v);});
3514 +        assertEquals(x.get(), 1);
3515 +        assertNull(r.get());
3516 +    }
3517 +
3518 +    /**
3519 +     * defaultExecutor by default returns the commonPool if
3520 +     * it supports more than one thread.
3521 +     */
3522 +    public void testDefaultExecutor() {
3523 +        CompletableFuture<Integer> f = new CompletableFuture<>();
3524 +        Executor e = f.defaultExecutor();
3525 +        Executor c = ForkJoinPool.commonPool();
3526 +        if (ForkJoinPool.getCommonPoolParallelism() > 1)
3527 +            assertSame(e, c);
3528 +        else
3529 +            assertNotSame(e, c);
3530 +    }
3531 +
3532 +    /**
3533 +     * failedFuture returns a CompletableFuture completed
3534 +     * exceptionally with the given Exception
3535 +     */
3536 +    public void testFailedFuture() {
3537 +        CFException ex = new CFException();
3538 +        CompletableFuture<Integer> f = CompletableFuture.failedFuture(ex);
3539 +        checkCompletedExceptionally(f, ex);
3540 +    }
3541 +
3542 +    /**
3543 +     * failedFuture(null) throws NPE
3544 +     */
3545 +    public void testFailedFuture_null() {
3546 +        try {
3547 +            CompletableFuture<Integer> f = CompletableFuture.failedFuture(null);
3548 +            shouldThrow();
3549 +        } catch (NullPointerException success) {}
3550 +    }
3551 +
3552 +    /**
3553 +     * copy returns a CompletableFuture that is completed normally,
3554 +     * with the same value, when source is.
3555 +     */
3556 +    public void testCopy() {
3557 +        CompletableFuture<Integer> f = new CompletableFuture<>();
3558 +        CompletableFuture<Integer> g = f.copy();
3559 +        checkIncomplete(f);
3560 +        checkIncomplete(g);
3561 +        f.complete(1);
3562 +        checkCompletedNormally(f, 1);
3563 +        checkCompletedNormally(g, 1);
3564 +    }
3565 +
3566 +    /**
3567 +     * copy returns a CompletableFuture that is completed exceptionally
3568 +     * when source is.
3569 +     */
3570 +    public void testCopy2() {
3571 +        CompletableFuture<Integer> f = new CompletableFuture<>();
3572 +        CompletableFuture<Integer> g = f.copy();
3573 +        checkIncomplete(f);
3574 +        checkIncomplete(g);
3575 +        CFException ex = new CFException();
3576 +        f.completeExceptionally(ex);
3577 +        checkCompletedExceptionally(f, ex);
3578 +        checkCompletedWithWrappedException(g, ex);
3579 +    }
3580 +
3581 +    /**
3582 +     * minimalCompletionStage returns a CompletableFuture that is
3583 +     * completed normally, with the same value, when source is.
3584 +     */
3585 +    public void testMinimalCompletionStage() {
3586 +        CompletableFuture<Integer> f = new CompletableFuture<>();
3587 +        CompletionStage<Integer> g = f.minimalCompletionStage();
3588 +        AtomicInteger x = new AtomicInteger(0);
3589 +        AtomicReference<Throwable> r = new AtomicReference<Throwable>();
3590 +        checkIncomplete(f);
3591 +        g.whenComplete((v, e) -> {if (e != null) r.set(e); else x.set(v);});
3592 +        f.complete(1);
3593 +        checkCompletedNormally(f, 1);
3594 +        assertEquals(x.get(), 1);
3595 +        assertNull(r.get());
3596 +    }
3597 +
3598 +    /**
3599 +     * minimalCompletionStage returns a CompletableFuture that is
3600 +     * completed exceptionally when source is.
3601 +     */
3602 +    public void testMinimalCompletionStage2() {
3603 +        CompletableFuture<Integer> f = new CompletableFuture<>();
3604 +        CompletionStage<Integer> g = f.minimalCompletionStage();
3605 +        AtomicInteger x = new AtomicInteger(0);
3606 +        AtomicReference<Throwable> r = new AtomicReference<Throwable>();
3607 +        g.whenComplete((v, e) -> {if (e != null) r.set(e); else x.set(v);});
3608 +        checkIncomplete(f);
3609 +        CFException ex = new CFException();
3610 +        f.completeExceptionally(ex);
3611 +        checkCompletedExceptionally(f, ex);
3612 +        assertEquals(x.get(), 0);
3613 +        assertEquals(r.get().getCause(), ex);
3614 +    }
3615 +
3616 +    /**
3617 +     * failedStage returns a CompletionStage completed
3618 +     * exceptionally with the given Exception
3619 +     */
3620 +    public void testFailedStage() {
3621 +        CFException ex = new CFException();
3622 +        CompletionStage<Integer> f = CompletableFuture.failedStage(ex);
3623 +        AtomicInteger x = new AtomicInteger(0);
3624 +        AtomicReference<Throwable> r = new AtomicReference<Throwable>();
3625 +        f.whenComplete((v, e) -> {if (e != null) r.set(e); else x.set(v);});
3626 +        assertEquals(x.get(), 0);
3627 +        assertEquals(r.get(), ex);
3628 +    }
3629 +
3630 +    /**
3631 +     * completeAsync completes with value of given supplier
3632 +     */
3633 +    public void testCompleteAsync() {
3634 +        for (Integer v1 : new Integer[] { 1, null })
3635 +    {
3636 +        CompletableFuture<Integer> f = new CompletableFuture<>();
3637 +        f.completeAsync(() -> v1);
3638 +        f.join();
3639 +        checkCompletedNormally(f, v1);
3640 +    }}
3641 +
3642 +    /**
3643 +     * completeAsync completes exceptionally if given supplier throws
3644 +     */
3645 +    public void testCompleteAsync2() {
3646 +        CompletableFuture<Integer> f = new CompletableFuture<>();
3647 +        CFException ex = new CFException();
3648 +        f.completeAsync(() -> {if (true) throw ex; return 1;});
3649 +        try {
3650 +            f.join();
3651 +            shouldThrow();
3652 +        } catch (CompletionException success) {}
3653 +        checkCompletedWithWrappedException(f, ex);
3654 +    }
3655 +
3656 +    /**
3657 +     * completeAsync with given executor completes with value of given supplier
3658 +     */
3659 +    public void testCompleteAsync3() {
3660 +        for (Integer v1 : new Integer[] { 1, null })
3661 +    {
3662 +        CompletableFuture<Integer> f = new CompletableFuture<>();
3663 +        ThreadExecutor executor = new ThreadExecutor();
3664 +        f.completeAsync(() -> v1, executor);
3665 +        assertSame(v1, f.join());
3666 +        checkCompletedNormally(f, v1);
3667 +        assertEquals(1, executor.count.get());
3668 +    }}
3669 +
3670 +    /**
3671 +     * completeAsync with given executor completes exceptionally if
3672 +     * given supplier throws
3673 +     */
3674 +    public void testCompleteAsync4() {
3675 +        CompletableFuture<Integer> f = new CompletableFuture<>();
3676 +        CFException ex = new CFException();
3677 +        ThreadExecutor executor = new ThreadExecutor();
3678 +        f.completeAsync(() -> {if (true) throw ex; return 1;}, executor);
3679 +        try {
3680 +            f.join();
3681 +            shouldThrow();
3682 +        } catch (CompletionException success) {}
3683 +        checkCompletedWithWrappedException(f, ex);
3684 +        assertEquals(1, executor.count.get());
3685 +    }
3686 +
3687 +    /**
3688 +     * orTimeout completes with TimeoutException if not complete
3689 +     */
3690 +    public void testOrTimeout_timesOut() {
3691 +        long timeoutMillis = timeoutMillis();
3692 +        CompletableFuture<Integer> f = new CompletableFuture<>();
3693 +        long startTime = System.nanoTime();
3694 +        assertSame(f, f.orTimeout(timeoutMillis, MILLISECONDS));
3695 +        checkCompletedWithTimeoutException(f);
3696 +        assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
3697 +    }
3698 +
3699 +    /**
3700 +     * orTimeout completes normally if completed before timeout
3701 +     */
3702 +    public void testOrTimeout_completed() {
3703 +        for (Integer v1 : new Integer[] { 1, null })
3704 +    {
3705 +        CompletableFuture<Integer> f = new CompletableFuture<>();
3706 +        CompletableFuture<Integer> g = new CompletableFuture<>();
3707 +        long startTime = System.nanoTime();
3708 +        f.complete(v1);
3709 +        assertSame(f, f.orTimeout(LONG_DELAY_MS, MILLISECONDS));
3710 +        assertSame(g, g.orTimeout(LONG_DELAY_MS, MILLISECONDS));
3711 +        g.complete(v1);
3712 +        checkCompletedNormally(f, v1);
3713 +        checkCompletedNormally(g, v1);
3714 +        assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS / 2);
3715 +    }}
3716 +
3717 +    /**
3718 +     * completeOnTimeout completes with given value if not complete
3719 +     */
3720 +    public void testCompleteOnTimeout_timesOut() {
3721 +        testInParallel(() -> testCompleteOnTimeout_timesOut(42),
3722 +                       () -> testCompleteOnTimeout_timesOut(null));
3723 +    }
3724 +
3725 +    /**
3726 +     * completeOnTimeout completes with given value if not complete
3727 +     */
3728 +    public void testCompleteOnTimeout_timesOut(Integer v) {
3729 +        long timeoutMillis = timeoutMillis();
3730 +        CompletableFuture<Integer> f = new CompletableFuture<>();
3731 +        long startTime = System.nanoTime();
3732 +        assertSame(f, f.completeOnTimeout(v, timeoutMillis, MILLISECONDS));
3733 +        assertSame(v, f.join());
3734 +        assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
3735 +        f.complete(99);         // should have no effect
3736 +        checkCompletedNormally(f, v);
3737 +    }
3738 +
3739 +    /**
3740 +     * completeOnTimeout has no effect if completed within timeout
3741 +     */
3742 +    public void testCompleteOnTimeout_completed() {
3743 +        for (Integer v1 : new Integer[] { 1, null })
3744 +    {
3745 +        CompletableFuture<Integer> f = new CompletableFuture<>();
3746 +        CompletableFuture<Integer> g = new CompletableFuture<>();
3747 +        long startTime = System.nanoTime();
3748 +        f.complete(v1);
3749 +        assertSame(f, f.completeOnTimeout(-1, LONG_DELAY_MS, MILLISECONDS));
3750 +        assertSame(g, g.completeOnTimeout(-1, LONG_DELAY_MS, MILLISECONDS));
3751 +        g.complete(v1);
3752 +        checkCompletedNormally(f, v1);
3753 +        checkCompletedNormally(g, v1);
3754 +        assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS / 2);
3755 +    }}
3756 +
3757 +    /**
3758 +     * delayedExecutor returns an executor that delays submission
3759 +     */
3760 +    public void testDelayedExecutor() {
3761 +        testInParallel(() -> testDelayedExecutor(null, null),
3762 +                       () -> testDelayedExecutor(null, 1),
3763 +                       () -> testDelayedExecutor(new ThreadExecutor(), 1),
3764 +                       () -> testDelayedExecutor(new ThreadExecutor(), 1));
3765 +    }
3766 +
3767 +    public void testDelayedExecutor(Executor executor, Integer v) throws Exception {
3768 +        long timeoutMillis = timeoutMillis();
3769 +        // Use an "unreasonably long" long timeout to catch lingering threads
3770 +        long longTimeoutMillis = 1000 * 60 * 60 * 24;
3771 +        final Executor delayer, longDelayer;
3772 +        if (executor == null) {
3773 +            delayer = CompletableFuture.delayedExecutor(timeoutMillis, MILLISECONDS);
3774 +            longDelayer = CompletableFuture.delayedExecutor(longTimeoutMillis, MILLISECONDS);
3775 +        } else {
3776 +            delayer = CompletableFuture.delayedExecutor(timeoutMillis, MILLISECONDS, executor);
3777 +            longDelayer = CompletableFuture.delayedExecutor(longTimeoutMillis, MILLISECONDS, executor);
3778 +        }
3779 +        long startTime = System.nanoTime();
3780 +        CompletableFuture<Integer> f =
3781 +            CompletableFuture.supplyAsync(() -> v, delayer);
3782 +        CompletableFuture<Integer> g =
3783 +            CompletableFuture.supplyAsync(() -> v, longDelayer);
3784 +
3785 +        assertNull(g.getNow(null));
3786 +
3787 +        assertSame(v, f.get(LONG_DELAY_MS, MILLISECONDS));
3788 +        long millisElapsed = millisElapsedSince(startTime);
3789 +        assertTrue(millisElapsed >= timeoutMillis);
3790 +        assertTrue(millisElapsed < LONG_DELAY_MS / 2);
3791 +
3792 +        checkCompletedNormally(f, v);
3793 +
3794 +        checkIncomplete(g);
3795 +        assertTrue(g.cancel(true));
3796 +    }
3797 +
3798 +    //--- tests of implementation details; not part of official tck ---
3799 +
3800 +    Object resultOf(CompletableFuture<?> f) {
3801 +        SecurityManager sm = System.getSecurityManager();
3802 +        if (sm != null) {
3803 +            try {
3804 +                System.setSecurityManager(null);
3805 +            } catch (SecurityException giveUp) {
3806 +                return "Reflection not available";
3807 +            }
3808 +        }
3809 +
3810 +        try {
3811 +            java.lang.reflect.Field resultField
3812 +                = CompletableFuture.class.getDeclaredField("result");
3813 +            resultField.setAccessible(true);
3814 +            return resultField.get(f);
3815 +        } catch (Throwable t) {
3816 +            throw new AssertionError(t);
3817 +        } finally {
3818 +            if (sm != null) System.setSecurityManager(sm);
3819 +        }
3820 +    }
3821 +
3822 +    public void testExceptionPropagationReusesResultObject() {
3823 +        if (!testImplementationDetails) return;
3824 +        for (ExecutionMode m : ExecutionMode.values())
3825 +    {
3826 +        final CFException ex = new CFException();
3827 +        final CompletableFuture<Integer> v42 = CompletableFuture.completedFuture(42);
3828 +        final CompletableFuture<Integer> incomplete = new CompletableFuture<>();
3829 +
3830 +        List<Function<CompletableFuture<Integer>, CompletableFuture<?>>> funs
3831 +            = new ArrayList<>();
3832 +
3833 +        funs.add((y) -> m.thenRun(y, new Noop(m)));
3834 +        funs.add((y) -> m.thenAccept(y, new NoopConsumer(m)));
3835 +        funs.add((y) -> m.thenApply(y, new IncFunction(m)));
3836 +
3837 +        funs.add((y) -> m.runAfterEither(y, incomplete, new Noop(m)));
3838 +        funs.add((y) -> m.acceptEither(y, incomplete, new NoopConsumer(m)));
3839 +        funs.add((y) -> m.applyToEither(y, incomplete, new IncFunction(m)));
3840 +
3841 +        funs.add((y) -> m.runAfterBoth(y, v42, new Noop(m)));
3842 +        funs.add((y) -> m.runAfterBoth(v42, y, new Noop(m)));
3843 +        funs.add((y) -> m.thenAcceptBoth(y, v42, new SubtractAction(m)));
3844 +        funs.add((y) -> m.thenAcceptBoth(v42, y, new SubtractAction(m)));
3845 +        funs.add((y) -> m.thenCombine(y, v42, new SubtractFunction(m)));
3846 +        funs.add((y) -> m.thenCombine(v42, y, new SubtractFunction(m)));
3847 +
3848 +        funs.add((y) -> m.whenComplete(y, (Integer r, Throwable t) -> {}));
3849 +
3850 +        funs.add((y) -> m.thenCompose(y, new CompletableFutureInc(m)));
3851 +
3852 +        funs.add((y) -> CompletableFuture.allOf(new CompletableFuture<?>[] {y}));
3853 +        funs.add((y) -> CompletableFuture.allOf(new CompletableFuture<?>[] {y, v42}));
3854 +        funs.add((y) -> CompletableFuture.allOf(new CompletableFuture<?>[] {v42, y}));
3855 +        funs.add((y) -> CompletableFuture.anyOf(new CompletableFuture<?>[] {y}));
3856 +        funs.add((y) -> CompletableFuture.anyOf(new CompletableFuture<?>[] {y, incomplete}));
3857 +        funs.add((y) -> CompletableFuture.anyOf(new CompletableFuture<?>[] {incomplete, y}));
3858 +
3859 +        for (Function<CompletableFuture<Integer>, CompletableFuture<?>>
3860 +                 fun : funs) {
3861 +            CompletableFuture<Integer> f = new CompletableFuture<>();
3862 +            f.completeExceptionally(ex);
3863 +            CompletableFuture<Integer> src = m.thenApply(f, new IncFunction(m));
3864 +            checkCompletedWithWrappedException(src, ex);
3865 +            CompletableFuture<?> dep = fun.apply(src);
3866 +            checkCompletedWithWrappedException(dep, ex);
3867 +            assertSame(resultOf(src), resultOf(dep));
3868 +        }
3869 +
3870 +        for (Function<CompletableFuture<Integer>, CompletableFuture<?>>
3871 +                 fun : funs) {
3872 +            CompletableFuture<Integer> f = new CompletableFuture<>();
3873 +            CompletableFuture<Integer> src = m.thenApply(f, new IncFunction(m));
3874 +            CompletableFuture<?> dep = fun.apply(src);
3875 +            f.completeExceptionally(ex);
3876 +            checkCompletedWithWrappedException(src, ex);
3877 +            checkCompletedWithWrappedException(dep, ex);
3878 +            assertSame(resultOf(src), resultOf(dep));
3879 +        }
3880 +
3881 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
3882 +        for (Function<CompletableFuture<Integer>, CompletableFuture<?>>
3883 +                 fun : funs) {
3884 +            CompletableFuture<Integer> f = new CompletableFuture<>();
3885 +            f.cancel(mayInterruptIfRunning);
3886 +            checkCancelled(f);
3887 +            CompletableFuture<Integer> src = m.thenApply(f, new IncFunction(m));
3888 +            checkCompletedWithWrappedCancellationException(src);
3889 +            CompletableFuture<?> dep = fun.apply(src);
3890 +            checkCompletedWithWrappedCancellationException(dep);
3891 +            assertSame(resultOf(src), resultOf(dep));
3892 +        }
3893 +
3894 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
3895 +        for (Function<CompletableFuture<Integer>, CompletableFuture<?>>
3896 +                 fun : funs) {
3897 +            CompletableFuture<Integer> f = new CompletableFuture<>();
3898 +            CompletableFuture<Integer> src = m.thenApply(f, new IncFunction(m));
3899 +            CompletableFuture<?> dep = fun.apply(src);
3900 +            f.cancel(mayInterruptIfRunning);
3901 +            checkCancelled(f);
3902 +            checkCompletedWithWrappedCancellationException(src);
3903 +            checkCompletedWithWrappedCancellationException(dep);
3904 +            assertSame(resultOf(src), resultOf(dep));
3905 +        }
3906 +    }}
3907 +
3908 +    /**
3909 +     * Minimal completion stages throw UOE for all non-CompletionStage methods
3910 +     */
3911 +    public void testMinimalCompletionStage_minimality() {
3912 +        if (!testImplementationDetails) return;
3913 +        Function<Method, String> toSignature =
3914 +            (method) -> method.getName() + Arrays.toString(method.getParameterTypes());
3915 +        Predicate<Method> isNotStatic =
3916 +            (method) -> (method.getModifiers() & Modifier.STATIC) == 0;
3917 +        List<Method> minimalMethods =
3918 +            Stream.of(Object.class, CompletionStage.class)
3919 +            .flatMap((klazz) -> Stream.of(klazz.getMethods()))
3920 +            .filter(isNotStatic)
3921 +            .collect(Collectors.toList());
3922 +        // Methods from CompletableFuture permitted NOT to throw UOE
3923 +        String[] signatureWhitelist = {
3924 +            "newIncompleteFuture[]",
3925 +            "defaultExecutor[]",
3926 +            "minimalCompletionStage[]",
3927 +            "copy[]",
3928 +        };
3929 +        Set<String> permittedMethodSignatures =
3930 +            Stream.concat(minimalMethods.stream().map(toSignature),
3931 +                          Stream.of(signatureWhitelist))
3932 +            .collect(Collectors.toSet());
3933 +        List<Method> allMethods = Stream.of(CompletableFuture.class.getMethods())
3934 +            .filter(isNotStatic)
3935 +            .filter((method) -> !permittedMethodSignatures.contains(toSignature.apply(method)))
3936 +            .collect(Collectors.toList());
3937 +
3938 +        CompletionStage<Integer> minimalStage =
3939 +            new CompletableFuture<Integer>().minimalCompletionStage();
3940 +
3941 +        List<Method> bugs = new ArrayList<>();
3942 +        for (Method method : allMethods) {
3943 +            Class<?>[] parameterTypes = method.getParameterTypes();
3944 +            Object[] args = new Object[parameterTypes.length];
3945 +            // Manufacture boxed primitives for primitive params
3946 +            for (int i = 0; i < args.length; i++) {
3947 +                Class<?> type = parameterTypes[i];
3948 +                if (parameterTypes[i] == boolean.class)
3949 +                    args[i] = false;
3950 +                else if (parameterTypes[i] == int.class)
3951 +                    args[i] = 0;
3952 +                else if (parameterTypes[i] == long.class)
3953 +                    args[i] = 0L;
3954 +            }
3955 +            try {
3956 +                method.invoke(minimalStage, args);
3957 +                bugs.add(method);
3958 +            }
3959 +            catch (java.lang.reflect.InvocationTargetException expected) {
3960 +                if (! (expected.getCause() instanceof UnsupportedOperationException)) {
3961 +                    bugs.add(method);
3962 +                    // expected.getCause().printStackTrace();
3963 +                }
3964 +            }
3965 +            catch (ReflectiveOperationException bad) { throw new Error(bad); }
3966 +        }
3967 +        if (!bugs.isEmpty())
3968 +            throw new Error("Methods did not throw UOE: " + bugs.toString());
3969 +    }
3970 +
3971 +    static class Monad {
3972 +        static class ZeroException extends RuntimeException {
3973 +            public ZeroException() { super("monadic zero"); }
3974 +        }
3975 +        // "return", "unit"
3976 +        static <T> CompletableFuture<T> unit(T value) {
3977 +            return completedFuture(value);
3978 +        }
3979 +        // monadic zero ?
3980 +        static <T> CompletableFuture<T> zero() {
3981 +            return failedFuture(new ZeroException());
3982 +        }
3983 +        // >=>
3984 +        static <T,U,V> Function<T, CompletableFuture<V>> compose
3985 +            (Function<T, CompletableFuture<U>> f,
3986 +             Function<U, CompletableFuture<V>> g) {
3987 +            return (x) -> f.apply(x).thenCompose(g);
3988 +        }
3989 +
3990 +        static void assertZero(CompletableFuture<?> f) {
3991 +            try {
3992 +                f.getNow(null);
3993 +                throw new AssertionFailedError("should throw");
3994 +            } catch (CompletionException success) {
3995 +                assertTrue(success.getCause() instanceof ZeroException);
3996 +            }
3997 +        }
3998 +
3999 +        static <T> void assertFutureEquals(CompletableFuture<T> f,
4000 +                                           CompletableFuture<T> g) {
4001 +            T fval = null, gval = null;
4002 +            Throwable fex = null, gex = null;
4003 +
4004 +            try { fval = f.get(); }
4005 +            catch (ExecutionException ex) { fex = ex.getCause(); }
4006 +            catch (Throwable ex) { fex = ex; }
4007 +
4008 +            try { gval = g.get(); }
4009 +            catch (ExecutionException ex) { gex = ex.getCause(); }
4010 +            catch (Throwable ex) { gex = ex; }
4011 +
4012 +            if (fex != null || gex != null)
4013 +                assertSame(fex.getClass(), gex.getClass());
4014 +            else
4015 +                assertEquals(fval, gval);
4016 +        }
4017 +
4018 +        static class PlusFuture<T> extends CompletableFuture<T> {
4019 +            AtomicReference<Throwable> firstFailure = new AtomicReference<>(null);
4020 +        }
4021 +
4022 +        /** Implements "monadic plus". */
4023 +        static <T> CompletableFuture<T> plus(CompletableFuture<? extends T> f,
4024 +                                             CompletableFuture<? extends T> g) {
4025 +            PlusFuture<T> plus = new PlusFuture<T>();
4026 +            BiConsumer<T, Throwable> action = (T result, Throwable ex) -> {
4027 +                try {
4028 +                    if (ex == null) {
4029 +                        if (plus.complete(result))
4030 +                            if (plus.firstFailure.get() != null)
4031 +                                plus.firstFailure.set(null);
4032 +                    }
4033 +                    else if (plus.firstFailure.compareAndSet(null, ex)) {
4034 +                        if (plus.isDone())
4035 +                            plus.firstFailure.set(null);
4036 +                    }
4037 +                    else {
4038 +                        // first failure has precedence
4039 +                        Throwable first = plus.firstFailure.getAndSet(null);
4040 +
4041 +                        // may fail with "Self-suppression not permitted"
4042 +                        try { first.addSuppressed(ex); }
4043 +                        catch (Exception ignored) {}
4044 +
4045 +                        plus.completeExceptionally(first);
4046 +                    }
4047 +                } catch (Throwable unexpected) {
4048 +                    plus.completeExceptionally(unexpected);
4049 +                }
4050 +            };
4051 +            f.whenComplete(action);
4052 +            g.whenComplete(action);
4053 +            return plus;
4054 +        }
4055 +    }
4056 +
4057 +    /**
4058 +     * CompletableFuture is an additive monad - sort of.
4059 +     * https://en.wikipedia.org/wiki/Monad_(functional_programming)#Additive_monads
4060 +     */
4061 +    public void testAdditiveMonad() throws Throwable {
4062 +        Function<Long, CompletableFuture<Long>> unit = Monad::unit;
4063 +        CompletableFuture<Long> zero = Monad.zero();
4064 +
4065 +        // Some mutually non-commutative functions
4066 +        Function<Long, CompletableFuture<Long>> triple
4067 +            = (x) -> Monad.unit(3 * x);
4068 +        Function<Long, CompletableFuture<Long>> inc
4069 +            = (x) -> Monad.unit(x + 1);
4070 +
4071 +        // unit is a right identity: m >>= unit === m
4072 +        Monad.assertFutureEquals(inc.apply(5L).thenCompose(unit),
4073 +                                 inc.apply(5L));
4074 +        // unit is a left identity: (unit x) >>= f === f x
4075 +        Monad.assertFutureEquals(unit.apply(5L).thenCompose(inc),
4076 +                                 inc.apply(5L));
4077 +
4078 +        // associativity: (m >>= f) >>= g === m >>= ( \x -> (f x >>= g) )
4079 +        Monad.assertFutureEquals(
4080 +            unit.apply(5L).thenCompose(inc).thenCompose(triple),
4081 +            unit.apply(5L).thenCompose((x) -> inc.apply(x).thenCompose(triple)));
4082 +
4083 +        // The case for CompletableFuture as an additive monad is weaker...
4084 +
4085 +        // zero is a monadic zero
4086 +        Monad.assertZero(zero);
4087 +
4088 +        // left zero: zero >>= f === zero
4089 +        Monad.assertZero(zero.thenCompose(inc));
4090 +        // right zero: f >>= (\x -> zero) === zero
4091 +        Monad.assertZero(inc.apply(5L).thenCompose((x) -> zero));
4092 +
4093 +        // f plus zero === f
4094 +        Monad.assertFutureEquals(Monad.unit(5L),
4095 +                                 Monad.plus(Monad.unit(5L), zero));
4096 +        // zero plus f === f
4097 +        Monad.assertFutureEquals(Monad.unit(5L),
4098 +                                 Monad.plus(zero, Monad.unit(5L)));
4099 +        // zero plus zero === zero
4100 +        Monad.assertZero(Monad.plus(zero, zero));
4101 +        {
4102 +            CompletableFuture<Long> f = Monad.plus(Monad.unit(5L),
4103 +                                                   Monad.unit(8L));
4104 +            // non-determinism
4105 +            assertTrue(f.get() == 5L || f.get() == 8L);
4106 +        }
4107 +
4108 +        CompletableFuture<Long> godot = new CompletableFuture<>();
4109 +        // f plus godot === f (doesn't wait for godot)
4110 +        Monad.assertFutureEquals(Monad.unit(5L),
4111 +                                 Monad.plus(Monad.unit(5L), godot));
4112 +        // godot plus f === f (doesn't wait for godot)
4113 +        Monad.assertFutureEquals(Monad.unit(5L),
4114 +                                 Monad.plus(godot, Monad.unit(5L)));
4115 +    }
4116 +
4117 +    /**
4118 +     * A single CompletableFuture with many dependents.
4119 +     * A demo of scalability - runtime is O(n).
4120 +     */
4121 +    public void testManyDependents() throws Throwable {
4122 +        final int n = 1_000;
4123 +        final CompletableFuture<Void> head = new CompletableFuture<>();
4124 +        final CompletableFuture<Void> complete = CompletableFuture.completedFuture((Void)null);
4125 +        final AtomicInteger count = new AtomicInteger(0);
4126 +        for (int i = 0; i < n; i++) {
4127 +            head.thenRun(() -> count.getAndIncrement());
4128 +            head.thenAccept((x) -> count.getAndIncrement());
4129 +            head.thenApply((x) -> count.getAndIncrement());
4130 +
4131 +            head.runAfterBoth(complete, () -> count.getAndIncrement());
4132 +            head.thenAcceptBoth(complete, (x, y) -> count.getAndIncrement());
4133 +            head.thenCombine(complete, (x, y) -> count.getAndIncrement());
4134 +            complete.runAfterBoth(head, () -> count.getAndIncrement());
4135 +            complete.thenAcceptBoth(head, (x, y) -> count.getAndIncrement());
4136 +            complete.thenCombine(head, (x, y) -> count.getAndIncrement());
4137 +
4138 +            head.runAfterEither(new CompletableFuture<Void>(), () -> count.getAndIncrement());
4139 +            head.acceptEither(new CompletableFuture<Void>(), (x) -> count.getAndIncrement());
4140 +            head.applyToEither(new CompletableFuture<Void>(), (x) -> count.getAndIncrement());
4141 +            new CompletableFuture<Void>().runAfterEither(head, () -> count.getAndIncrement());
4142 +            new CompletableFuture<Void>().acceptEither(head, (x) -> count.getAndIncrement());
4143 +            new CompletableFuture<Void>().applyToEither(head, (x) -> count.getAndIncrement());
4144 +        }
4145 +        head.complete(null);
4146 +        assertEquals(5 * 3 * n, count.get());
4147 +    }
4148 +
4149 + //     static <U> U join(CompletionStage<U> stage) {
4150 + //         CompletableFuture<U> f = new CompletableFuture<>();
4151 + //         stage.whenComplete((v, ex) -> {
4152 + //             if (ex != null) f.completeExceptionally(ex); else f.complete(v);
4153 + //         });
4154 + //         return f.join();
4155 + //     }
4156 +
4157 + //     static <U> boolean isDone(CompletionStage<U> stage) {
4158 + //         CompletableFuture<U> f = new CompletableFuture<>();
4159 + //         stage.whenComplete((v, ex) -> {
4160 + //             if (ex != null) f.completeExceptionally(ex); else f.complete(v);
4161 + //         });
4162 + //         return f.isDone();
4163 + //     }
4164 +
4165 + //     static <U> U join2(CompletionStage<U> stage) {
4166 + //         return stage.toCompletableFuture().copy().join();
4167 + //     }
4168 +
4169 + //     static <U> boolean isDone2(CompletionStage<U> stage) {
4170 + //         return stage.toCompletableFuture().copy().isDone();
4171 + //     }
4172 +
4173   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines