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.3 by jsr166, Sat Feb 9 19:33:08 2013 UTC vs.
Revision 1.44 by jsr166, Mon Jun 2 06:06:30 2014 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.*;
9   import java.util.concurrent.Callable;
10 + import java.util.concurrent.Executor;
11 + import java.util.concurrent.ExecutorService;
12 + import java.util.concurrent.Executors;
13   import java.util.concurrent.CancellationException;
14   import java.util.concurrent.CountDownLatch;
15   import java.util.concurrent.ExecutionException;
16   import java.util.concurrent.Future;
17   import java.util.concurrent.CompletableFuture;
18 + import java.util.concurrent.CompletionException;
19 + import java.util.concurrent.CompletionStage;
20   import java.util.concurrent.TimeoutException;
21   import java.util.concurrent.atomic.AtomicInteger;
22   import static java.util.concurrent.TimeUnit.MILLISECONDS;
23   import static java.util.concurrent.TimeUnit.SECONDS;
24   import java.util.*;
25 + import java.util.function.Supplier;
26 + import java.util.function.Consumer;
27 + import java.util.function.BiConsumer;
28 + import java.util.function.Function;
29 + import java.util.function.BiFunction;
30  
31   public class CompletableFutureTest extends JSR166TestCase {
32  
# Line 28 | Line 37 | public class CompletableFutureTest exten
37          return new TestSuite(CompletableFutureTest.class);
38      }
39  
40 <    // XXXX Just a skeleton implementation for now.
41 <    public void testTODO() {
42 <        fail("Please add some real tests!");
40 >    static class CFException extends RuntimeException {}
41 >
42 >    void checkIncomplete(CompletableFuture<?> f) {
43 >        assertFalse(f.isDone());
44 >        assertFalse(f.isCancelled());
45 >        assertTrue(f.toString().contains("[Not completed]"));
46 >        try {
47 >            assertNull(f.getNow(null));
48 >        } catch (Throwable fail) { threadUnexpectedException(fail); }
49 >        try {
50 >            f.get(0L, SECONDS);
51 >            shouldThrow();
52 >        }
53 >        catch (TimeoutException success) {}
54 >        catch (Throwable fail) { threadUnexpectedException(fail); }
55 >    }
56 >
57 >    <T> void checkCompletedNormally(CompletableFuture<T> f, T value) {
58 >        try {
59 >            assertEquals(value, f.get(LONG_DELAY_MS, MILLISECONDS));
60 >        } catch (Throwable fail) { threadUnexpectedException(fail); }
61 >        try {
62 >            assertEquals(value, f.join());
63 >        } catch (Throwable fail) { threadUnexpectedException(fail); }
64 >        try {
65 >            assertEquals(value, f.getNow(null));
66 >        } catch (Throwable fail) { threadUnexpectedException(fail); }
67 >        try {
68 >            assertEquals(value, f.get());
69 >        } catch (Throwable fail) { threadUnexpectedException(fail); }
70 >        assertTrue(f.isDone());
71 >        assertFalse(f.isCancelled());
72 >        assertFalse(f.isCompletedExceptionally());
73 >        assertTrue(f.toString().contains("[Completed normally]"));
74 >    }
75 >
76 >    void checkCompletedWithWrappedCFException(CompletableFuture<?> f) {
77 >        try {
78 >            f.get(LONG_DELAY_MS, MILLISECONDS);
79 >            shouldThrow();
80 >        } catch (ExecutionException success) {
81 >            assertTrue(success.getCause() instanceof CFException);
82 >        } catch (Throwable fail) { threadUnexpectedException(fail); }
83 >        try {
84 >            f.join();
85 >            shouldThrow();
86 >        } catch (CompletionException success) {
87 >            assertTrue(success.getCause() instanceof CFException);
88 >        }
89 >        try {
90 >            f.getNow(null);
91 >            shouldThrow();
92 >        } catch (CompletionException success) {
93 >            assertTrue(success.getCause() instanceof CFException);
94 >        }
95 >        try {
96 >            f.get();
97 >            shouldThrow();
98 >        } catch (ExecutionException success) {
99 >            assertTrue(success.getCause() instanceof CFException);
100 >        } catch (Throwable fail) { threadUnexpectedException(fail); }
101 >        assertTrue(f.isDone());
102 >        assertFalse(f.isCancelled());
103 >        assertTrue(f.toString().contains("[Completed exceptionally]"));
104 >    }
105 >
106 >    void checkCompletedWithWrappedCFException(CompletableFuture<?> f,
107 >                                              CFException ex) {
108 >        try {
109 >            f.get(LONG_DELAY_MS, MILLISECONDS);
110 >            shouldThrow();
111 >        } catch (ExecutionException success) {
112 >            assertSame(ex, success.getCause());
113 >        } catch (Throwable fail) { threadUnexpectedException(fail); }
114 >        try {
115 >            f.join();
116 >            shouldThrow();
117 >        } catch (CompletionException success) {
118 >            assertSame(ex, success.getCause());
119 >        }
120 >        try {
121 >            f.getNow(null);
122 >            shouldThrow();
123 >        } catch (CompletionException success) {
124 >            assertSame(ex, success.getCause());
125 >        }
126 >        try {
127 >            f.get();
128 >            shouldThrow();
129 >        } catch (ExecutionException success) {
130 >            assertSame(ex, success.getCause());
131 >        } catch (Throwable fail) { threadUnexpectedException(fail); }
132 >        assertTrue(f.isDone());
133 >        assertFalse(f.isCancelled());
134 >        assertTrue(f.toString().contains("[Completed exceptionally]"));
135 >    }
136 >
137 >    void checkCancelled(CompletableFuture<?> f) {
138 >        try {
139 >            f.get(LONG_DELAY_MS, MILLISECONDS);
140 >            shouldThrow();
141 >        } catch (CancellationException success) {
142 >        } catch (Throwable fail) { threadUnexpectedException(fail); }
143 >        try {
144 >            f.join();
145 >            shouldThrow();
146 >        } catch (CancellationException success) {}
147 >        try {
148 >            f.getNow(null);
149 >            shouldThrow();
150 >        } catch (CancellationException success) {}
151 >        try {
152 >            f.get();
153 >            shouldThrow();
154 >        } catch (CancellationException success) {
155 >        } catch (Throwable fail) { threadUnexpectedException(fail); }
156 >        assertTrue(f.isDone());
157 >        assertTrue(f.isCompletedExceptionally());
158 >        assertTrue(f.isCancelled());
159 >        assertTrue(f.toString().contains("[Completed exceptionally]"));
160 >    }
161 >
162 >    void checkCompletedWithWrappedCancellationException(CompletableFuture<?> f) {
163 >        try {
164 >            f.get(LONG_DELAY_MS, MILLISECONDS);
165 >            shouldThrow();
166 >        } catch (ExecutionException success) {
167 >            assertTrue(success.getCause() instanceof CancellationException);
168 >        } catch (Throwable fail) { threadUnexpectedException(fail); }
169 >        try {
170 >            f.join();
171 >            shouldThrow();
172 >        } catch (CompletionException success) {
173 >            assertTrue(success.getCause() instanceof CancellationException);
174 >        }
175 >        try {
176 >            f.getNow(null);
177 >            shouldThrow();
178 >        } catch (CompletionException success) {
179 >            assertTrue(success.getCause() instanceof CancellationException);
180 >        }
181 >        try {
182 >            f.get();
183 >            shouldThrow();
184 >        } catch (ExecutionException success) {
185 >            assertTrue(success.getCause() instanceof CancellationException);
186 >        } catch (Throwable fail) { threadUnexpectedException(fail); }
187 >        assertTrue(f.isDone());
188 >        assertFalse(f.isCancelled());
189 >        assertTrue(f.isCompletedExceptionally());
190 >        assertTrue(f.toString().contains("[Completed exceptionally]"));
191 >    }
192 >
193 >    /**
194 >     * A newly constructed CompletableFuture is incomplete, as indicated
195 >     * by methods isDone, isCancelled, and getNow
196 >     */
197 >    public void testConstructor() {
198 >        CompletableFuture<Integer> f = new CompletableFuture<>();
199 >        checkIncomplete(f);
200 >    }
201 >
202 >    /**
203 >     * complete completes normally, as indicated by methods isDone,
204 >     * isCancelled, join, get, and getNow
205 >     */
206 >    public void testComplete() {
207 >        CompletableFuture<Integer> f = new CompletableFuture<>();
208 >        checkIncomplete(f);
209 >        f.complete(one);
210 >        checkCompletedNormally(f, one);
211      }
212  
213 +    /**
214 +     * completeExceptionally completes exceptionally, as indicated by
215 +     * methods isDone, isCancelled, join, get, and getNow
216 +     */
217 +    public void testCompleteExceptionally() {
218 +        CompletableFuture<Integer> f = new CompletableFuture<>();
219 +        checkIncomplete(f);
220 +        f.completeExceptionally(new CFException());
221 +        checkCompletedWithWrappedCFException(f);
222 +    }
223 +
224 +    /**
225 +     * cancel completes exceptionally and reports cancelled, as indicated by
226 +     * methods isDone, isCancelled, join, get, and getNow
227 +     */
228 +    public void testCancel() {
229 +        CompletableFuture<Integer> f = new CompletableFuture<>();
230 +        checkIncomplete(f);
231 +        assertTrue(f.cancel(true));
232 +        checkCancelled(f);
233 +    }
234 +
235 +    /**
236 +     * obtrudeValue forces completion with given value
237 +     */
238 +    public void testObtrudeValue() {
239 +        CompletableFuture<Integer> f = new CompletableFuture<>();
240 +        checkIncomplete(f);
241 +        f.complete(one);
242 +        checkCompletedNormally(f, one);
243 +        f.obtrudeValue(three);
244 +        checkCompletedNormally(f, three);
245 +        f.obtrudeValue(two);
246 +        checkCompletedNormally(f, two);
247 +        f = new CompletableFuture<>();
248 +        f.obtrudeValue(three);
249 +        checkCompletedNormally(f, three);
250 +        f = new CompletableFuture<>();
251 +        f.completeExceptionally(new CFException());
252 +        f.obtrudeValue(four);
253 +        checkCompletedNormally(f, four);
254 +    }
255 +
256 +    /**
257 +     * obtrudeException forces completion with given exception
258 +     */
259 +    public void testObtrudeException() {
260 +        CompletableFuture<Integer> f = new CompletableFuture<>();
261 +        checkIncomplete(f);
262 +        f.complete(one);
263 +        checkCompletedNormally(f, one);
264 +        f.obtrudeException(new CFException());
265 +        checkCompletedWithWrappedCFException(f);
266 +        f = new CompletableFuture<>();
267 +        f.obtrudeException(new CFException());
268 +        checkCompletedWithWrappedCFException(f);
269 +        f = new CompletableFuture<>();
270 +        f.completeExceptionally(new CFException());
271 +        f.obtrudeValue(four);
272 +        checkCompletedNormally(f, four);
273 +        f.obtrudeException(new CFException());
274 +        checkCompletedWithWrappedCFException(f);
275 +    }
276 +
277 +    /**
278 +     * getNumberOfDependents returns number of dependent tasks
279 +     */
280 +    public void testGetNumberOfDependents() {
281 +        CompletableFuture<Integer> f = new CompletableFuture<>();
282 +        assertEquals(f.getNumberOfDependents(), 0);
283 +        CompletableFuture g = f.thenRun(new Noop());
284 +        assertEquals(f.getNumberOfDependents(), 1);
285 +        assertEquals(g.getNumberOfDependents(), 0);
286 +        CompletableFuture h = f.thenRun(new Noop());
287 +        assertEquals(f.getNumberOfDependents(), 2);
288 +        f.complete(1);
289 +        checkCompletedNormally(g, null);
290 +        assertEquals(f.getNumberOfDependents(), 0);
291 +        assertEquals(g.getNumberOfDependents(), 0);
292 +    }
293 +
294 +    /**
295 +     * toString indicates current completion state
296 +     */
297      public void testToString() {
298          CompletableFuture<String> f;
299  
# Line 46 | Line 307 | public class CompletableFutureTest exten
307          f.completeExceptionally(new IndexOutOfBoundsException());
308          assertTrue(f.toString().contains("[Completed exceptionally]"));
309      }
310 +
311 +    /**
312 +     * completedFuture returns a completed CompletableFuture with given value
313 +     */
314 +    public void testCompletedFuture() {
315 +        CompletableFuture<String> f = CompletableFuture.completedFuture("test");
316 +        checkCompletedNormally(f, "test");
317 +    }
318 +
319 +    // Choose non-commutative actions for better coverage
320 +
321 +    // A non-commutative function that handles and produces null values as well.
322 +    static Integer subtract(Integer x, Integer y) {
323 +        return (x == null && y == null) ? null :
324 +            ((x == null) ? 42 : x.intValue())
325 +            - ((y == null) ? 99 : y.intValue());
326 +    }
327 +
328 +    // A function that handles and produces null values as well.
329 +    static Integer inc(Integer x) {
330 +        return (x == null) ? null : x + 1;
331 +    }
332 +
333 +    static final Supplier<Integer> supplyOne =
334 +        () -> Integer.valueOf(1);
335 +    static final Function<Integer, Integer> inc =
336 +        (Integer x) -> Integer.valueOf(x.intValue() + 1);
337 +    static final BiFunction<Integer, Integer, Integer> subtract =
338 +        (Integer x, Integer y) -> subtract(x, y);
339 +    static final class IncAction implements Consumer<Integer> {
340 +        int invocationCount = 0;
341 +        Integer value;
342 +        public void accept(Integer x) {
343 +            invocationCount++;
344 +            value = inc(x);
345 +        }
346 +    }
347 +    static final class IncFunction implements Function<Integer,Integer> {
348 +        int invocationCount = 0;
349 +        Integer value;
350 +        public Integer apply(Integer x) {
351 +            invocationCount++;
352 +            return value = inc(x);
353 +        }
354 +    }
355 +    static final class SubtractAction implements BiConsumer<Integer, Integer> {
356 +        int invocationCount = 0;
357 +        Integer value;
358 +        // Check this action was invoked exactly once when result is computed.
359 +        public void accept(Integer x, Integer y) {
360 +            invocationCount++;
361 +            value = subtract(x, y);
362 +        }
363 +    }
364 +    static final class SubtractFunction implements BiFunction<Integer, Integer, Integer> {
365 +        int invocationCount = 0;
366 +        Integer value;
367 +        // Check this action was invoked exactly once when result is computed.
368 +        public Integer apply(Integer x, Integer y) {
369 +            invocationCount++;
370 +            return value = subtract(x, y);
371 +        }
372 +    }
373 +    static final class Noop implements Runnable {
374 +        int invocationCount = 0;
375 +        public void run() {
376 +            invocationCount++;
377 +        }
378 +    }
379 +
380 +    static final class FailingSupplier implements Supplier<Integer> {
381 +        int invocationCount = 0;
382 +        public Integer get() {
383 +            invocationCount++;
384 +            throw new CFException();
385 +        }
386 +    }
387 +    static final class FailingConsumer implements Consumer<Integer> {
388 +        int invocationCount = 0;
389 +        public void accept(Integer x) {
390 +            invocationCount++;
391 +            throw new CFException();
392 +        }
393 +    }
394 +    static final class FailingBiConsumer implements BiConsumer<Integer, Integer> {
395 +        int invocationCount = 0;
396 +        public void accept(Integer x, Integer y) {
397 +            invocationCount++;
398 +            throw new CFException();
399 +        }
400 +    }
401 +    static final class FailingFunction implements Function<Integer, Integer> {
402 +        int invocationCount = 0;
403 +        public Integer apply(Integer x) {
404 +            invocationCount++;
405 +            throw new CFException();
406 +        }
407 +    }
408 +    static final class FailingBiFunction implements BiFunction<Integer, Integer, Integer> {
409 +        int invocationCount = 0;
410 +        public Integer apply(Integer x, Integer y) {
411 +            invocationCount++;
412 +            throw new CFException();
413 +        }
414 +    }
415 +    static final class FailingNoop implements Runnable {
416 +        int invocationCount = 0;
417 +        public void run() {
418 +            invocationCount++;
419 +            throw new CFException();
420 +        }
421 +    }
422 +
423 +    static final class CompletableFutureInc
424 +        implements Function<Integer, CompletableFuture<Integer>> {
425 +        int invocationCount = 0;
426 +        public CompletableFuture<Integer> apply(Integer x) {
427 +            invocationCount++;
428 +            CompletableFuture<Integer> f = new CompletableFuture<>();
429 +            f.complete(inc(x));
430 +            return f;
431 +        }
432 +    }
433 +
434 +    static final class FailingCompletableFutureFunction
435 +        implements Function<Integer, CompletableFuture<Integer>> {
436 +        int invocationCount = 0;
437 +        public CompletableFuture<Integer> apply(Integer x) {
438 +            invocationCount++;
439 +            throw new CFException();
440 +        }
441 +    }
442 +
443 +    // Used for explicit executor tests
444 +    static final class ThreadExecutor implements Executor {
445 +        AtomicInteger count = new AtomicInteger(0);
446 +
447 +        public void execute(Runnable r) {
448 +            count.getAndIncrement();
449 +            new Thread(r).start();
450 +        }
451 +    }
452 +
453 +    static final class ExceptionToInteger implements Function<Throwable, Integer> {
454 +        public Integer apply(Throwable x) { return Integer.valueOf(3); }
455 +    }
456 +
457 +    static final class IntegerHandler implements BiFunction<Integer, Throwable, Integer> {
458 +        int invocationCount = 0;
459 +        public Integer apply(Integer x, Throwable t) {
460 +            invocationCount++;
461 +            return (t == null) ? two : three;
462 +        }
463 +    }
464 +
465 +    /**
466 +     * Permits the testing of parallel code for the 3 different
467 +     * execution modes without repeating all the testing code.
468 +     */
469 +    enum ExecutionMode {
470 +        DEFAULT {
471 +            public <T,U> CompletableFuture<Void> runAfterBoth
472 +                (CompletableFuture<T> f, CompletableFuture<U> g, Runnable a) {
473 +                return f.runAfterBoth(g, a);
474 +            }
475 +            public <T,U> CompletableFuture<Void> thenAcceptBoth
476 +                (CompletableFuture<T> f,
477 +                 CompletionStage<? extends U> g,
478 +                 BiConsumer<? super T,? super U> a) {
479 +                return f.thenAcceptBoth(g, a);
480 +            }
481 +            public <T,U,V> CompletableFuture<V> thenCombine
482 +                (CompletableFuture<T> f,
483 +                 CompletionStage<? extends U> g,
484 +                 BiFunction<? super T,? super U,? extends V> a) {
485 +                return f.thenCombine(g, a);
486 +            }
487 +            public <T,U> CompletableFuture<U> applyToEither
488 +                (CompletableFuture<T> f,
489 +                 CompletionStage<? extends T> g,
490 +                 Function<? super T,U> a) {
491 +                return f.applyToEither(g, a);
492 +            }
493 +            public <T> CompletableFuture<Void> acceptEither
494 +                (CompletableFuture<T> f,
495 +                 CompletionStage<? extends T> g,
496 +                 Consumer<? super T> a) {
497 +                return f.acceptEither(g, a);
498 +            }
499 +            public <T> CompletableFuture<Void> runAfterEither
500 +                (CompletableFuture<T> f,
501 +                 CompletionStage<?> g,
502 +                 java.lang.Runnable a) {
503 +                return f.runAfterEither(g, a);
504 +            }
505 +            public <T,U> CompletableFuture<U> thenCompose
506 +                (CompletableFuture<T> f,
507 +                 Function<? super T,? extends CompletionStage<U>> a) {
508 +                return f.thenCompose(a);
509 +            }
510 +            public <T> CompletableFuture<T> whenComplete
511 +                (CompletableFuture<T> f,
512 +                 BiConsumer<? super T,? super Throwable> a) {
513 +                return f.whenComplete(a);
514 +            }
515 +        },
516 +
517 + //             /** Experimental way to do more testing */
518 + //         REVERSE_DEFAULT {
519 + //             public <T,U> CompletableFuture<Void> runAfterBoth
520 + //                 (CompletableFuture<T> f, CompletableFuture<U> g, Runnable a) {
521 + //                 return g.runAfterBoth(f, a);
522 + //             }
523 + //             public <T,U> CompletableFuture<Void> thenAcceptBoth
524 + //                 (CompletableFuture<T> f,
525 + //                  CompletionStage<? extends U> g,
526 + //                  BiConsumer<? super T,? super U> a) {
527 + //                 return DEFAULT.thenAcceptBoth(f, g, a);
528 + //             }
529 + //         },
530 +
531 +        DEFAULT_ASYNC {
532 +            public <T,U> CompletableFuture<Void> runAfterBoth
533 +                (CompletableFuture<T> f, CompletableFuture<U> g, Runnable a) {
534 +                return f.runAfterBothAsync(g, a);
535 +            }
536 +            public <T,U> CompletableFuture<Void> thenAcceptBoth
537 +                (CompletableFuture<T> f,
538 +                 CompletionStage<? extends U> g,
539 +                 BiConsumer<? super T,? super U> a) {
540 +                return f.thenAcceptBothAsync(g, a);
541 +            }
542 +            public <T,U,V> CompletableFuture<V> thenCombine
543 +                (CompletableFuture<T> f,
544 +                 CompletionStage<? extends U> g,
545 +                 BiFunction<? super T,? super U,? extends V> a) {
546 +                return f.thenCombineAsync(g, a);
547 +            }
548 +            public <T,U> CompletableFuture<U> applyToEither
549 +                (CompletableFuture<T> f,
550 +                 CompletionStage<? extends T> g,
551 +                 Function<? super T,U> a) {
552 +                return f.applyToEitherAsync(g, a);
553 +            }
554 +            public <T> CompletableFuture<Void> acceptEither
555 +                (CompletableFuture<T> f,
556 +                 CompletionStage<? extends T> g,
557 +                 Consumer<? super T> a) {
558 +                return f.acceptEitherAsync(g, a);
559 +            }
560 +            public <T> CompletableFuture<Void> runAfterEither
561 +                (CompletableFuture<T> f,
562 +                 CompletionStage<?> g,
563 +                 java.lang.Runnable a) {
564 +                return f.runAfterEitherAsync(g, a);
565 +            }
566 +            public <T,U> CompletableFuture<U> thenCompose
567 +                (CompletableFuture<T> f,
568 +                 Function<? super T,? extends CompletionStage<U>> a) {
569 +                return f.thenComposeAsync(a);
570 +            }
571 +            public <T> CompletableFuture<T> whenComplete
572 +                (CompletableFuture<T> f,
573 +                 BiConsumer<? super T,? super Throwable> a) {
574 +                return f.whenCompleteAsync(a);
575 +            }
576 +        },
577 +
578 + //         REVERSE_DEFAULT_ASYNC {
579 + //             public <T,U> CompletableFuture<Void> runAfterBoth
580 + //                 (CompletableFuture<T> f, CompletableFuture<U> g, Runnable a) {
581 + //                 return f.runAfterBothAsync(g, a);
582 + //             }
583 + //             public <T,U> CompletableFuture<Void> thenAcceptBoth
584 + //                 (CompletableFuture<T> f,
585 + //                  CompletionStage<? extends U> g,
586 + //                  BiConsumer<? super T,? super U> a) {
587 + //                 return DEFAULT_ASYNC.thenAcceptBoth(f, g, a);
588 + //             }
589 + //         },
590 +
591 +        EXECUTOR {
592 +            public <T,U> CompletableFuture<Void> runAfterBoth
593 +                (CompletableFuture<T> f, CompletableFuture<U> g, Runnable a) {
594 +                return f.runAfterBothAsync(g, a, new ThreadExecutor());
595 +            }
596 +            public <T,U> CompletableFuture<Void> thenAcceptBoth
597 +                (CompletableFuture<T> f,
598 +                 CompletionStage<? extends U> g,
599 +                 BiConsumer<? super T,? super U> a) {
600 +                return f.thenAcceptBothAsync(g, a, new ThreadExecutor());
601 +            }
602 +            public <T,U,V> CompletableFuture<V> thenCombine
603 +                (CompletableFuture<T> f,
604 +                 CompletionStage<? extends U> g,
605 +                 BiFunction<? super T,? super U,? extends V> a) {
606 +                return f.thenCombineAsync(g, a, new ThreadExecutor());
607 +            }
608 +            public <T,U> CompletableFuture<U> applyToEither
609 +                (CompletableFuture<T> f,
610 +                 CompletionStage<? extends T> g,
611 +                 Function<? super T,U> a) {
612 +                return f.applyToEitherAsync(g, a, new ThreadExecutor());
613 +            }
614 +            public <T> CompletableFuture<Void> acceptEither
615 +                (CompletableFuture<T> f,
616 +                 CompletionStage<? extends T> g,
617 +                 Consumer<? super T> a) {
618 +                return f.acceptEitherAsync(g, a, new ThreadExecutor());
619 +            }
620 +            public <T> CompletableFuture<Void> runAfterEither
621 +                (CompletableFuture<T> f,
622 +                 CompletionStage<?> g,
623 +                 java.lang.Runnable a) {
624 +                return f.runAfterEitherAsync(g, a, new ThreadExecutor());
625 +            }
626 +            public <T,U> CompletableFuture<U> thenCompose
627 +                (CompletableFuture<T> f,
628 +                 Function<? super T,? extends CompletionStage<U>> a) {
629 +                return f.thenComposeAsync(a, new ThreadExecutor());
630 +            }
631 +            public <T> CompletableFuture<T> whenComplete
632 +                (CompletableFuture<T> f,
633 +                 BiConsumer<? super T,? super Throwable> a) {
634 +                return f.whenCompleteAsync(a, new ThreadExecutor());
635 +            }
636 +        };
637 +
638 +        public abstract <T,U> CompletableFuture<Void> runAfterBoth
639 +            (CompletableFuture<T> f, CompletableFuture<U> g, Runnable a);
640 +        public abstract <T,U> CompletableFuture<Void> thenAcceptBoth
641 +            (CompletableFuture<T> f,
642 +             CompletionStage<? extends U> g,
643 +             BiConsumer<? super T,? super U> a);
644 +        public abstract <T,U,V> CompletableFuture<V> thenCombine
645 +            (CompletableFuture<T> f,
646 +             CompletionStage<? extends U> g,
647 +             BiFunction<? super T,? super U,? extends V> a);
648 +        public abstract <T,U> CompletableFuture<U> applyToEither
649 +            (CompletableFuture<T> f,
650 +             CompletionStage<? extends T> g,
651 +             Function<? super T,U> a);
652 +        public abstract <T> CompletableFuture<Void> acceptEither
653 +            (CompletableFuture<T> f,
654 +             CompletionStage<? extends T> g,
655 +             Consumer<? super T> a);
656 +        public abstract <T> CompletableFuture<Void> runAfterEither
657 +            (CompletableFuture<T> f,
658 +             CompletionStage<?> g,
659 +             java.lang.Runnable a);
660 +        public abstract <T,U> CompletableFuture<U> thenCompose
661 +            (CompletableFuture<T> f,
662 +             Function<? super T,? extends CompletionStage<U>> a);
663 +        public abstract <T> CompletableFuture<T> whenComplete
664 +            (CompletableFuture<T> f,
665 +             BiConsumer<? super T,? super Throwable> a);
666 +
667 +
668 +    }
669 +
670 +    /**
671 +     * exceptionally action completes with function value on source
672 +     * exception; otherwise with source value
673 +     */
674 +    public void testExceptionally() {
675 +        CompletableFuture<Integer> f = new CompletableFuture<>();
676 +        ExceptionToInteger r = new ExceptionToInteger();
677 +        CompletableFuture<Integer> g = f.exceptionally(r);
678 +        f.completeExceptionally(new CFException());
679 +        checkCompletedNormally(g, three);
680 +
681 +        f = new CompletableFuture<>();
682 +        r = new ExceptionToInteger();
683 +        g = f.exceptionally(r);
684 +        f.complete(one);
685 +        checkCompletedNormally(g, one);
686 +    }
687 +
688 +    /**
689 +     * handle action completes normally with function value on either
690 +     * normal or exceptional completion of source
691 +     */
692 +    public void testHandle() {
693 +        CompletableFuture<Integer> f, g;
694 +        IntegerHandler r;
695 +
696 +        f = new CompletableFuture<>();
697 +        f.completeExceptionally(new CFException());
698 +        g = f.handle(r = new IntegerHandler());
699 +        assertEquals(1, r.invocationCount);
700 +        assertEquals(1, r.invocationCount);
701 +        checkCompletedNormally(g, three);
702 +
703 +        f = new CompletableFuture<>();
704 +        g = f.handle(r = new IntegerHandler());
705 +        assertEquals(0, r.invocationCount);
706 +        f.completeExceptionally(new CFException());
707 +        checkCompletedNormally(g, three);
708 +        assertEquals(1, r.invocationCount);
709 +
710 +        f = new CompletableFuture<>();
711 +        f.complete(one);
712 +        g = f.handle(r = new IntegerHandler());
713 +        assertEquals(1, r.invocationCount);
714 +        checkCompletedNormally(g, two);
715 +
716 +        f = new CompletableFuture<>();
717 +        g = f.handle(r = new IntegerHandler());
718 +        assertEquals(0, r.invocationCount);
719 +        f.complete(one);
720 +        assertEquals(1, r.invocationCount);
721 +        checkCompletedNormally(g, two);
722 +    }
723 +
724 +    /**
725 +     * runAsync completes after running Runnable
726 +     */
727 +    public void testRunAsync() {
728 +        Noop r = new Noop();
729 +        CompletableFuture<Void> f = CompletableFuture.runAsync(r);
730 +        assertNull(f.join());
731 +        assertEquals(1, r.invocationCount);
732 +        checkCompletedNormally(f, null);
733 +    }
734 +
735 +    /**
736 +     * runAsync with executor completes after running Runnable
737 +     */
738 +    public void testRunAsync2() {
739 +        Noop r = new Noop();
740 +        ThreadExecutor exec = new ThreadExecutor();
741 +        CompletableFuture<Void> f = CompletableFuture.runAsync(r, exec);
742 +        assertNull(f.join());
743 +        assertEquals(1, r.invocationCount);
744 +        checkCompletedNormally(f, null);
745 +        assertEquals(1, exec.count.get());
746 +    }
747 +
748 +    /**
749 +     * failing runAsync completes exceptionally after running Runnable
750 +     */
751 +    public void testRunAsync3() {
752 +        FailingNoop r = new FailingNoop();
753 +        CompletableFuture<Void> f = CompletableFuture.runAsync(r);
754 +        checkCompletedWithWrappedCFException(f);
755 +        assertEquals(1, r.invocationCount);
756 +    }
757 +
758 +    /**
759 +     * supplyAsync completes with result of supplier
760 +     */
761 +    public void testSupplyAsync() {
762 +        CompletableFuture<Integer> f;
763 +        f = CompletableFuture.supplyAsync(supplyOne);
764 +        assertEquals(f.join(), one);
765 +        checkCompletedNormally(f, one);
766 +    }
767 +
768 +    /**
769 +     * supplyAsync with executor completes with result of supplier
770 +     */
771 +    public void testSupplyAsync2() {
772 +        CompletableFuture<Integer> f;
773 +        f = CompletableFuture.supplyAsync(supplyOne, new ThreadExecutor());
774 +        assertEquals(f.join(), one);
775 +        checkCompletedNormally(f, one);
776 +    }
777 +
778 +    /**
779 +     * Failing supplyAsync completes exceptionally
780 +     */
781 +    public void testSupplyAsync3() {
782 +        FailingSupplier r = new FailingSupplier();
783 +        CompletableFuture<Integer> f = CompletableFuture.supplyAsync(r);
784 +        checkCompletedWithWrappedCFException(f);
785 +        assertEquals(1, r.invocationCount);
786 +    }
787 +
788 +    // seq completion methods
789 +
790 +    /**
791 +     * thenRun result completes normally after normal completion of source
792 +     */
793 +    public void testThenRun() {
794 +        CompletableFuture<Integer> f;
795 +        CompletableFuture<Void> g;
796 +        Noop r;
797 +
798 +        f = new CompletableFuture<>();
799 +        g = f.thenRun(r = new Noop());
800 +        f.complete(null);
801 +        checkCompletedNormally(g, null);
802 +        assertEquals(1, r.invocationCount);
803 +
804 +        f = new CompletableFuture<>();
805 +        f.complete(null);
806 +        g = f.thenRun(r = new Noop());
807 +        checkCompletedNormally(g, null);
808 +        assertEquals(1, r.invocationCount);
809 +    }
810 +
811 +    /**
812 +     * thenRun result completes exceptionally after exceptional
813 +     * completion of source
814 +     */
815 +    public void testThenRun2() {
816 +        CompletableFuture<Integer> f;
817 +        CompletableFuture<Void> g;
818 +        Noop r;
819 +
820 +        f = new CompletableFuture<>();
821 +        g = f.thenRun(r = new Noop());
822 +        f.completeExceptionally(new CFException());
823 +        checkCompletedWithWrappedCFException(g);
824 +        assertEquals(0, r.invocationCount);
825 +
826 +        f = new CompletableFuture<>();
827 +        f.completeExceptionally(new CFException());
828 +        g = f.thenRun(r = new Noop());
829 +        checkCompletedWithWrappedCFException(g);
830 +        assertEquals(0, r.invocationCount);
831 +    }
832 +
833 +    /**
834 +     * thenRun result completes exceptionally if action does
835 +     */
836 +    public void testThenRun3() {
837 +        CompletableFuture<Integer> f;
838 +        CompletableFuture<Void> g;
839 +        FailingNoop r;
840 +
841 +        f = new CompletableFuture<>();
842 +        g = f.thenRun(r = new FailingNoop());
843 +        f.complete(null);
844 +        checkCompletedWithWrappedCFException(g);
845 +
846 +        f = new CompletableFuture<>();
847 +        f.complete(null);
848 +        g = f.thenRun(r = new FailingNoop());
849 +        checkCompletedWithWrappedCFException(g);
850 +    }
851 +
852 +    /**
853 +     * thenRun result completes exceptionally if source cancelled
854 +     */
855 +    public void testThenRun4() {
856 +        CompletableFuture<Integer> f;
857 +        CompletableFuture<Void> g;
858 +        Noop r;
859 +
860 +        f = new CompletableFuture<>();
861 +        g = f.thenRun(r = new Noop());
862 +        assertTrue(f.cancel(true));
863 +        checkCompletedWithWrappedCancellationException(g);
864 +
865 +        f = new CompletableFuture<>();
866 +        assertTrue(f.cancel(true));
867 +        g = f.thenRun(r = new Noop());
868 +        checkCompletedWithWrappedCancellationException(g);
869 +    }
870 +
871 +    /**
872 +     * thenApply result completes normally after normal completion of source
873 +     */
874 +    public void testThenApply() {
875 +        CompletableFuture<Integer> f = new CompletableFuture<>();
876 +        CompletableFuture<Integer> g = f.thenApply(inc);
877 +        f.complete(one);
878 +        checkCompletedNormally(g, two);
879 +    }
880 +
881 +    /**
882 +     * thenApply result completes exceptionally after exceptional
883 +     * completion of source
884 +     */
885 +    public void testThenApply2() {
886 +        CompletableFuture<Integer> f = new CompletableFuture<>();
887 +        CompletableFuture<Integer> g = f.thenApply(inc);
888 +        f.completeExceptionally(new CFException());
889 +        checkCompletedWithWrappedCFException(g);
890 +    }
891 +
892 +    /**
893 +     * thenApply result completes exceptionally if action does
894 +     */
895 +    public void testThenApply3() {
896 +        CompletableFuture<Integer> f = new CompletableFuture<>();
897 +        CompletableFuture<Integer> g = f.thenApply(new FailingFunction());
898 +        f.complete(one);
899 +        checkCompletedWithWrappedCFException(g);
900 +    }
901 +
902 +    /**
903 +     * thenApply result completes exceptionally if source cancelled
904 +     */
905 +    public void testThenApply4() {
906 +        CompletableFuture<Integer> f = new CompletableFuture<>();
907 +        CompletableFuture<Integer> g = f.thenApply(inc);
908 +        assertTrue(f.cancel(true));
909 +        checkCompletedWithWrappedCancellationException(g);
910 +    }
911 +
912 +    /**
913 +     * thenAccept result completes normally after normal completion of source
914 +     */
915 +    public void testThenAccept() {
916 +        CompletableFuture<Integer> f = new CompletableFuture<>();
917 +        IncAction r = new IncAction();
918 +        CompletableFuture<Void> g = f.thenAccept(r);
919 +        f.complete(one);
920 +        checkCompletedNormally(g, null);
921 +        assertEquals(r.value, (Integer) 2);
922 +    }
923 +
924 +    /**
925 +     * thenAccept result completes exceptionally after exceptional
926 +     * completion of source
927 +     */
928 +    public void testThenAccept2() {
929 +        CompletableFuture<Integer> f = new CompletableFuture<>();
930 +        IncAction r = new IncAction();
931 +        CompletableFuture<Void> g = f.thenAccept(r);
932 +        f.completeExceptionally(new CFException());
933 +        checkCompletedWithWrappedCFException(g);
934 +    }
935 +
936 +    /**
937 +     * thenAccept result completes exceptionally if action does
938 +     */
939 +    public void testThenAccept3() {
940 +        CompletableFuture<Integer> f = new CompletableFuture<>();
941 +        FailingConsumer r = new FailingConsumer();
942 +        CompletableFuture<Void> g = f.thenAccept(r);
943 +        f.complete(one);
944 +        checkCompletedWithWrappedCFException(g);
945 +        assertEquals(1, r.invocationCount);
946 +    }
947 +
948 +    /**
949 +     * thenAccept result completes exceptionally if source cancelled
950 +     */
951 +    public void testThenAccept4() {
952 +        CompletableFuture<Integer> f = new CompletableFuture<>();
953 +        IncAction r = new IncAction();
954 +        CompletableFuture<Void> g = f.thenAccept(r);
955 +        assertTrue(f.cancel(true));
956 +        checkCompletedWithWrappedCancellationException(g);
957 +    }
958 +
959 +    /**
960 +     * thenCombine result completes normally after normal completion
961 +     * of sources
962 +     */
963 +    public void testThenCombine_normalCompletion1() {
964 +        for (boolean createIncomplete : new boolean[] { true, false })
965 +        for (boolean fFirst : new boolean[] { true, false })
966 +        for (ExecutionMode m : ExecutionMode.values())
967 +        for (Integer v1 : new Integer[] { 1, null })
968 +        for (Integer v2 : new Integer[] { 2, null }) {
969 +
970 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
971 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
972 +        final SubtractFunction r = new SubtractFunction();
973 +        CompletableFuture<Integer> h = null;
974 +        if (createIncomplete) h = m.thenCombine(f, g, r);
975 +
976 +        if (fFirst)
977 +            f.complete(v1);
978 +        else
979 +            g.complete(v2);
980 +        if (createIncomplete) checkIncomplete(h);
981 +        assertEquals(0, r.invocationCount);
982 +        if (!fFirst)
983 +            f.complete(v1);
984 +        else
985 +            g.complete(v2);
986 +        if (!createIncomplete) h = m.thenCombine(f, g, r);
987 +
988 +        checkCompletedNormally(h, subtract(v1, v2));
989 +        checkCompletedNormally(f, v1);
990 +        checkCompletedNormally(g, v2);
991 +        assertEquals(1, r.invocationCount);
992 +        }
993 +    }
994 +
995 +    /**
996 +     * thenCombine result completes exceptionally after exceptional
997 +     * completion of either source
998 +     */
999 +    public void testThenCombine_exceptionalCompletion1() {
1000 +        for (ExecutionMode m : ExecutionMode.values())
1001 +        for (Integer v1 : new Integer[] { 1, null }) {
1002 +
1003 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1004 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1005 +        final SubtractFunction r = new SubtractFunction();
1006 +        final CompletableFuture<Integer> h = m.thenCombine(f, g, r);
1007 +        final CFException ex = new CFException();
1008 +
1009 +        f.completeExceptionally(ex);
1010 +        checkIncomplete(h);
1011 +        g.complete(v1);
1012 +
1013 +        checkCompletedWithWrappedCFException(h, ex);
1014 +        checkCompletedWithWrappedCFException(f, ex);
1015 +        assertEquals(0, r.invocationCount);
1016 +        checkCompletedNormally(g, v1);
1017 +        }
1018 +    }
1019 +
1020 +    public void testThenCombine_exceptionalCompletion2() {
1021 +        for (ExecutionMode m : ExecutionMode.values())
1022 +        for (Integer v1 : new Integer[] { 1, null }) {
1023 +
1024 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1025 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1026 +        final SubtractFunction r = new SubtractFunction();
1027 +        final CompletableFuture<Integer> h = m.thenCombine(f, g, r);
1028 +        final CFException ex = new CFException();
1029 +
1030 +        g.completeExceptionally(ex);
1031 +        checkIncomplete(h);
1032 +        f.complete(v1);
1033 +
1034 +        checkCompletedWithWrappedCFException(h, ex);
1035 +        checkCompletedWithWrappedCFException(g, ex);
1036 +        assertEquals(0, r.invocationCount);
1037 +        checkCompletedNormally(f, v1);
1038 +        }
1039 +    }
1040 +
1041 +    public void testThenCombine_exceptionalCompletion3() {
1042 +        for (ExecutionMode m : ExecutionMode.values())
1043 +        for (Integer v1 : new Integer[] { 1, null }) {
1044 +
1045 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1046 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1047 +        final SubtractFunction r = new SubtractFunction();
1048 +        final CFException ex = new CFException();
1049 +
1050 +        g.completeExceptionally(ex);
1051 +        f.complete(v1);
1052 +        final CompletableFuture<Integer> h = m.thenCombine(f, g, r);
1053 +
1054 +        checkCompletedWithWrappedCFException(h, ex);
1055 +        checkCompletedWithWrappedCFException(g, ex);
1056 +        assertEquals(0, r.invocationCount);
1057 +        checkCompletedNormally(f, v1);
1058 +        }
1059 +    }
1060 +
1061 +    public void testThenCombine_exceptionalCompletion4() {
1062 +        for (ExecutionMode m : ExecutionMode.values())
1063 +        for (Integer v1 : new Integer[] { 1, null }) {
1064 +
1065 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1066 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1067 +        final SubtractFunction r = new SubtractFunction();
1068 +        final CFException ex = new CFException();
1069 +
1070 +        f.completeExceptionally(ex);
1071 +        g.complete(v1);
1072 +        final CompletableFuture<Integer> h = m.thenCombine(f, g, r);
1073 +
1074 +        checkCompletedWithWrappedCFException(h, ex);
1075 +        checkCompletedWithWrappedCFException(f, ex);
1076 +        assertEquals(0, r.invocationCount);
1077 +        checkCompletedNormally(g, v1);
1078 +        }
1079 +    }
1080 +
1081 +    /**
1082 +     * thenCombine result completes exceptionally if action does
1083 +     */
1084 +    public void testThenCombine_actionFailed1() {
1085 +        for (ExecutionMode m : ExecutionMode.values())
1086 +        for (Integer v1 : new Integer[] { 1, null })
1087 +        for (Integer v2 : new Integer[] { 2, null }) {
1088 +
1089 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1090 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1091 +        final FailingBiFunction r = new FailingBiFunction();
1092 +        final CompletableFuture<Integer> h = m.thenCombine(f, g, r);
1093 +
1094 +        f.complete(v1);
1095 +        checkIncomplete(h);
1096 +        g.complete(v2);
1097 +
1098 +        checkCompletedWithWrappedCFException(h);
1099 +        checkCompletedNormally(f, v1);
1100 +        checkCompletedNormally(g, v2);
1101 +        }
1102 +    }
1103 +
1104 +    public void testThenCombine_actionFailed2() {
1105 +        for (ExecutionMode m : ExecutionMode.values())
1106 +        for (Integer v1 : new Integer[] { 1, null })
1107 +        for (Integer v2 : new Integer[] { 2, null }) {
1108 +
1109 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1110 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1111 +        final FailingBiFunction r = new FailingBiFunction();
1112 +        final CompletableFuture<Integer> h = m.thenCombine(f, g, r);
1113 +
1114 +        g.complete(v2);
1115 +        checkIncomplete(h);
1116 +        f.complete(v1);
1117 +
1118 +        checkCompletedWithWrappedCFException(h);
1119 +        checkCompletedNormally(f, v1);
1120 +        checkCompletedNormally(g, v2);
1121 +        }
1122 +    }
1123 +
1124 +    /**
1125 +     * thenCombine result completes exceptionally if either source cancelled
1126 +     */
1127 +    public void testThenCombine_sourceCancelled1() {
1128 +        for (ExecutionMode m : ExecutionMode.values())
1129 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
1130 +        for (Integer v1 : new Integer[] { 1, null }) {
1131 +
1132 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1133 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1134 +        final SubtractFunction r = new SubtractFunction();
1135 +        final CompletableFuture<Integer> h = m.thenCombine(f, g, r);
1136 +
1137 +        assertTrue(f.cancel(mayInterruptIfRunning));
1138 +        checkIncomplete(h);
1139 +        g.complete(v1);
1140 +
1141 +        checkCompletedWithWrappedCancellationException(h);
1142 +        checkCancelled(f);
1143 +        assertEquals(0, r.invocationCount);
1144 +        checkCompletedNormally(g, v1);
1145 +        }
1146 +    }
1147 +
1148 +    public void testThenCombine_sourceCancelled2() {
1149 +        for (ExecutionMode m : ExecutionMode.values())
1150 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
1151 +        for (Integer v1 : new Integer[] { 1, null }) {
1152 +
1153 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1154 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1155 +        final SubtractFunction r = new SubtractFunction();
1156 +        final CompletableFuture<Integer> h = m.thenCombine(f, g, r);
1157 +
1158 +        assertTrue(g.cancel(mayInterruptIfRunning));
1159 +        checkIncomplete(h);
1160 +        f.complete(v1);
1161 +
1162 +        checkCompletedWithWrappedCancellationException(h);
1163 +        checkCancelled(g);
1164 +        assertEquals(0, r.invocationCount);
1165 +        checkCompletedNormally(f, v1);
1166 +        }
1167 +    }
1168 +
1169 +    public void testThenCombine_sourceCancelled3() {
1170 +        for (ExecutionMode m : ExecutionMode.values())
1171 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
1172 +        for (Integer v1 : new Integer[] { 1, null }) {
1173 +
1174 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1175 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1176 +        final SubtractFunction r = new SubtractFunction();
1177 +
1178 +        assertTrue(g.cancel(mayInterruptIfRunning));
1179 +        f.complete(v1);
1180 +        final CompletableFuture<Integer> h = m.thenCombine(f, g, r);
1181 +
1182 +        checkCompletedWithWrappedCancellationException(h);
1183 +        checkCancelled(g);
1184 +        assertEquals(0, r.invocationCount);
1185 +        checkCompletedNormally(f, v1);
1186 +        }
1187 +    }
1188 +
1189 +    public void testThenCombine_sourceCancelled4() {
1190 +        for (ExecutionMode m : ExecutionMode.values())
1191 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
1192 +        for (Integer v1 : new Integer[] { 1, null }) {
1193 +
1194 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1195 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1196 +        final SubtractFunction r = new SubtractFunction();
1197 +
1198 +        assertTrue(f.cancel(mayInterruptIfRunning));
1199 +        g.complete(v1);
1200 +        final CompletableFuture<Integer> h = m.thenCombine(f, g, r);
1201 +
1202 +        checkCompletedWithWrappedCancellationException(h);
1203 +        checkCancelled(f);
1204 +        assertEquals(0, r.invocationCount);
1205 +        checkCompletedNormally(g, v1);
1206 +        }
1207 +    }
1208 +
1209 +    /**
1210 +     * thenAcceptBoth result completes normally after normal
1211 +     * completion of sources
1212 +     */
1213 +    public void testThenAcceptBoth_normalCompletion1() {
1214 +        for (ExecutionMode m : ExecutionMode.values())
1215 +        for (Integer v1 : new Integer[] { 1, null })
1216 +        for (Integer v2 : new Integer[] { 2, null }) {
1217 +
1218 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1219 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1220 +        final SubtractAction r = new SubtractAction();
1221 +        final CompletableFuture<Void> h = m.thenAcceptBoth(f, g, r);
1222 +
1223 +        f.complete(v1);
1224 +        checkIncomplete(h);
1225 +        assertEquals(0, r.invocationCount);
1226 +        g.complete(v2);
1227 +
1228 +        checkCompletedNormally(h, null);
1229 +        assertEquals(r.value, subtract(v1, v2));
1230 +        checkCompletedNormally(f, v1);
1231 +        checkCompletedNormally(g, v2);
1232 +        }
1233 +    }
1234 +
1235 +    public void testThenAcceptBoth_normalCompletion2() {
1236 +        for (ExecutionMode m : ExecutionMode.values())
1237 +        for (Integer v1 : new Integer[] { 1, null })
1238 +        for (Integer v2 : new Integer[] { 2, null }) {
1239 +
1240 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1241 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1242 +        final SubtractAction r = new SubtractAction();
1243 +        final CompletableFuture<Void> h = m.thenAcceptBoth(f, g, r);
1244 +
1245 +        g.complete(v2);
1246 +        checkIncomplete(h);
1247 +        assertEquals(0, r.invocationCount);
1248 +        f.complete(v1);
1249 +
1250 +        checkCompletedNormally(h, null);
1251 +        assertEquals(r.value, subtract(v1, v2));
1252 +        checkCompletedNormally(f, v1);
1253 +        checkCompletedNormally(g, v2);
1254 +        }
1255 +    }
1256 +
1257 +    public void testThenAcceptBoth_normalCompletion3() {
1258 +        for (ExecutionMode m : ExecutionMode.values())
1259 +        for (Integer v1 : new Integer[] { 1, null })
1260 +        for (Integer v2 : new Integer[] { 2, null }) {
1261 +
1262 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1263 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1264 +        final SubtractAction r = new SubtractAction();
1265 +
1266 +        g.complete(v2);
1267 +        f.complete(v1);
1268 +        final CompletableFuture<Void> h = m.thenAcceptBoth(f, g, r);
1269 +
1270 +        checkCompletedNormally(h, null);
1271 +        assertEquals(r.value, subtract(v1, v2));
1272 +        checkCompletedNormally(f, v1);
1273 +        checkCompletedNormally(g, v2);
1274 +        }
1275 +    }
1276 +
1277 +    public void testThenAcceptBoth_normalCompletion4() {
1278 +        for (ExecutionMode m : ExecutionMode.values())
1279 +        for (Integer v1 : new Integer[] { 1, null })
1280 +        for (Integer v2 : new Integer[] { 2, null }) {
1281 +
1282 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1283 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1284 +        final SubtractAction r = new SubtractAction();
1285 +
1286 +        f.complete(v1);
1287 +        g.complete(v2);
1288 +        final CompletableFuture<Void> h = m.thenAcceptBoth(f, g, r);
1289 +
1290 +        checkCompletedNormally(h, null);
1291 +        assertEquals(r.value, subtract(v1, v2));
1292 +        checkCompletedNormally(f, v1);
1293 +        checkCompletedNormally(g, v2);
1294 +        }
1295 +    }
1296 +
1297 +    /**
1298 +     * thenAcceptBoth result completes exceptionally after exceptional
1299 +     * completion of either source
1300 +     */
1301 +    public void testThenAcceptBoth_exceptionalCompletion1() {
1302 +        for (ExecutionMode m : ExecutionMode.values())
1303 +        for (Integer v1 : new Integer[] { 1, null }) {
1304 +
1305 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1306 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1307 +        final SubtractAction r = new SubtractAction();
1308 +        final CompletableFuture<Void> h = m.thenAcceptBoth(f, g, r);
1309 +        final CFException ex = new CFException();
1310 +
1311 +        f.completeExceptionally(ex);
1312 +        checkIncomplete(h);
1313 +        g.complete(v1);
1314 +
1315 +        checkCompletedWithWrappedCFException(h, ex);
1316 +        checkCompletedWithWrappedCFException(f, ex);
1317 +        assertEquals(0, r.invocationCount);
1318 +        checkCompletedNormally(g, v1);
1319 +        }
1320 +    }
1321 +
1322 +    public void testThenAcceptBoth_exceptionalCompletion2() {
1323 +        for (ExecutionMode m : ExecutionMode.values())
1324 +        for (Integer v1 : new Integer[] { 1, null }) {
1325 +
1326 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1327 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1328 +        final SubtractAction r = new SubtractAction();
1329 +        final CompletableFuture<Void> h = m.thenAcceptBoth(f, g, r);
1330 +        final CFException ex = new CFException();
1331 +
1332 +        g.completeExceptionally(ex);
1333 +        checkIncomplete(h);
1334 +        f.complete(v1);
1335 +
1336 +        checkCompletedWithWrappedCFException(h, ex);
1337 +        checkCompletedWithWrappedCFException(g, ex);
1338 +        assertEquals(0, r.invocationCount);
1339 +        checkCompletedNormally(f, v1);
1340 +        }
1341 +    }
1342 +
1343 +    public void testThenAcceptBoth_exceptionalCompletion3() {
1344 +        for (ExecutionMode m : ExecutionMode.values())
1345 +        for (Integer v1 : new Integer[] { 1, null }) {
1346 +
1347 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1348 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1349 +        final SubtractAction r = new SubtractAction();
1350 +        final CFException ex = new CFException();
1351 +
1352 +        g.completeExceptionally(ex);
1353 +        f.complete(v1);
1354 +        final CompletableFuture<Void> h = m.thenAcceptBoth(f, g, r);
1355 +
1356 +        checkCompletedWithWrappedCFException(h, ex);
1357 +        checkCompletedWithWrappedCFException(g, ex);
1358 +        assertEquals(0, r.invocationCount);
1359 +        checkCompletedNormally(f, v1);
1360 +        }
1361 +    }
1362 +
1363 +    public void testThenAcceptBoth_exceptionalCompletion4() {
1364 +        for (ExecutionMode m : ExecutionMode.values())
1365 +        for (Integer v1 : new Integer[] { 1, null }) {
1366 +
1367 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1368 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1369 +        final SubtractAction r = new SubtractAction();
1370 +        final CFException ex = new CFException();
1371 +
1372 +        f.completeExceptionally(ex);
1373 +        g.complete(v1);
1374 +        final CompletableFuture<Void> h = m.thenAcceptBoth(f, g, r);
1375 +
1376 +        checkCompletedWithWrappedCFException(h, ex);
1377 +        checkCompletedWithWrappedCFException(f, ex);
1378 +        assertEquals(0, r.invocationCount);
1379 +        checkCompletedNormally(g, v1);
1380 +        }
1381 +    }
1382 +
1383 +    /**
1384 +     * thenAcceptBoth result completes exceptionally if action does
1385 +     */
1386 +    public void testThenAcceptBoth_actionFailed1() {
1387 +        for (ExecutionMode m : ExecutionMode.values())
1388 +        for (Integer v1 : new Integer[] { 1, null })
1389 +        for (Integer v2 : new Integer[] { 2, null }) {
1390 +
1391 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1392 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1393 +        final FailingBiConsumer r = new FailingBiConsumer();
1394 +        final CompletableFuture<Void> h = m.thenAcceptBoth(f, g, r);
1395 +
1396 +        f.complete(v1);
1397 +        checkIncomplete(h);
1398 +        g.complete(v2);
1399 +
1400 +        checkCompletedWithWrappedCFException(h);
1401 +        checkCompletedNormally(f, v1);
1402 +        checkCompletedNormally(g, v2);
1403 +        }
1404 +    }
1405 +
1406 +    public void testThenAcceptBoth_actionFailed2() {
1407 +        for (ExecutionMode m : ExecutionMode.values())
1408 +        for (Integer v1 : new Integer[] { 1, null })
1409 +        for (Integer v2 : new Integer[] { 2, null }) {
1410 +
1411 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1412 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1413 +        final FailingBiConsumer r = new FailingBiConsumer();
1414 +        final CompletableFuture<Void> h = m.thenAcceptBoth(f, g, r);
1415 +
1416 +        g.complete(v2);
1417 +        checkIncomplete(h);
1418 +        f.complete(v1);
1419 +
1420 +        checkCompletedWithWrappedCFException(h);
1421 +        checkCompletedNormally(f, v1);
1422 +        checkCompletedNormally(g, v2);
1423 +        }
1424 +    }
1425 +
1426 +    /**
1427 +     * thenAcceptBoth result completes exceptionally if either source cancelled
1428 +     */
1429 +    public void testThenAcceptBoth_sourceCancelled1() {
1430 +        for (ExecutionMode m : ExecutionMode.values())
1431 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
1432 +        for (Integer v1 : new Integer[] { 1, null }) {
1433 +
1434 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1435 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1436 +        final SubtractAction r = new SubtractAction();
1437 +        final CompletableFuture<Void> h = m.thenAcceptBoth(f, g, r);
1438 +
1439 +        assertTrue(f.cancel(mayInterruptIfRunning));
1440 +        checkIncomplete(h);
1441 +        g.complete(v1);
1442 +
1443 +        checkCompletedWithWrappedCancellationException(h);
1444 +        checkCancelled(f);
1445 +        assertEquals(0, r.invocationCount);
1446 +        checkCompletedNormally(g, v1);
1447 +        }
1448 +    }
1449 +
1450 +    public void testThenAcceptBoth_sourceCancelled2() {
1451 +        for (ExecutionMode m : ExecutionMode.values())
1452 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
1453 +        for (Integer v1 : new Integer[] { 1, null }) {
1454 +
1455 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1456 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1457 +        final SubtractAction r = new SubtractAction();
1458 +        final CompletableFuture<Void> h = m.thenAcceptBoth(f, g, r);
1459 +
1460 +        assertTrue(g.cancel(mayInterruptIfRunning));
1461 +        checkIncomplete(h);
1462 +        f.complete(v1);
1463 +
1464 +        checkCompletedWithWrappedCancellationException(h);
1465 +        checkCancelled(g);
1466 +        assertEquals(0, r.invocationCount);
1467 +        checkCompletedNormally(f, v1);
1468 +        }
1469 +    }
1470 +
1471 +    public void testThenAcceptBoth_sourceCancelled3() {
1472 +        for (ExecutionMode m : ExecutionMode.values())
1473 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
1474 +        for (Integer v1 : new Integer[] { 1, null }) {
1475 +
1476 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1477 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1478 +        final SubtractAction r = new SubtractAction();
1479 +
1480 +        assertTrue(g.cancel(mayInterruptIfRunning));
1481 +        f.complete(v1);
1482 +        final CompletableFuture<Void> h = m.thenAcceptBoth(f, g, r);
1483 +
1484 +        checkCompletedWithWrappedCancellationException(h);
1485 +        checkCancelled(g);
1486 +        assertEquals(0, r.invocationCount);
1487 +        checkCompletedNormally(f, v1);
1488 +        }
1489 +    }
1490 +
1491 +    public void testThenAcceptBoth_sourceCancelled4() {
1492 +        for (ExecutionMode m : ExecutionMode.values())
1493 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
1494 +        for (Integer v1 : new Integer[] { 1, null }) {
1495 +
1496 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1497 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1498 +        final SubtractAction r = new SubtractAction();
1499 +
1500 +        assertTrue(f.cancel(mayInterruptIfRunning));
1501 +        g.complete(v1);
1502 +        final CompletableFuture<Void> h = m.thenAcceptBoth(f, g, r);
1503 +
1504 +        checkCompletedWithWrappedCancellationException(h);
1505 +        checkCancelled(f);
1506 +        assertEquals(0, r.invocationCount);
1507 +        checkCompletedNormally(g, v1);
1508 +        }
1509 +    }
1510 +
1511 +    /**
1512 +     * runAfterBoth result completes normally after normal
1513 +     * completion of sources
1514 +     */
1515 +    public void testRunAfterBoth_normalCompletion1() {
1516 +        for (ExecutionMode m : ExecutionMode.values())
1517 +        for (Integer v1 : new Integer[] { 1, null })
1518 +        for (Integer v2 : new Integer[] { 2, null }) {
1519 +
1520 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1521 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1522 +        final Noop r = new Noop();
1523 +        final CompletableFuture<Void> h = m.runAfterBoth(f, g, r);
1524 +
1525 +        f.complete(v1);
1526 +        checkIncomplete(h);
1527 +        assertEquals(0, r.invocationCount);
1528 +        g.complete(v2);
1529 +
1530 +        checkCompletedNormally(h, null);
1531 +        assertEquals(1, r.invocationCount);
1532 +        checkCompletedNormally(f, v1);
1533 +        checkCompletedNormally(g, v2);
1534 +        }
1535 +    }
1536 +
1537 +    public void testRunAfterBoth_normalCompletion2() {
1538 +        for (ExecutionMode m : ExecutionMode.values())
1539 +        for (Integer v1 : new Integer[] { 1, null })
1540 +        for (Integer v2 : new Integer[] { 2, null }) {
1541 +
1542 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1543 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1544 +        final Noop r = new Noop();
1545 +        final CompletableFuture<Void> h = m.runAfterBoth(f, g, r);
1546 +
1547 +        g.complete(v2);
1548 +        checkIncomplete(h);
1549 +        assertEquals(0, r.invocationCount);
1550 +        f.complete(v1);
1551 +
1552 +        checkCompletedNormally(h, null);
1553 +        assertEquals(1, r.invocationCount);
1554 +        checkCompletedNormally(f, v1);
1555 +        checkCompletedNormally(g, v2);
1556 +        }
1557 +    }
1558 +
1559 +    public void testRunAfterBoth_normalCompletion3() {
1560 +        for (ExecutionMode m : ExecutionMode.values())
1561 +        for (Integer v1 : new Integer[] { 1, null })
1562 +        for (Integer v2 : new Integer[] { 2, null }) {
1563 +
1564 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1565 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1566 +        final Noop r = new Noop();
1567 +
1568 +        g.complete(v2);
1569 +        f.complete(v1);
1570 +        final CompletableFuture<Void> h = m.runAfterBoth(f, g, r);
1571 +
1572 +        checkCompletedNormally(h, null);
1573 +        assertEquals(1, r.invocationCount);
1574 +        checkCompletedNormally(f, v1);
1575 +        checkCompletedNormally(g, v2);
1576 +        }
1577 +    }
1578 +
1579 +    public void testRunAfterBoth_normalCompletion4() {
1580 +        for (ExecutionMode m : ExecutionMode.values())
1581 +        for (Integer v1 : new Integer[] { 1, null })
1582 +        for (Integer v2 : new Integer[] { 2, null }) {
1583 +
1584 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1585 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1586 +        final Noop r = new Noop();
1587 +
1588 +        f.complete(v1);
1589 +        g.complete(v2);
1590 +        final CompletableFuture<Void> h = m.runAfterBoth(f, g, r);
1591 +
1592 +        checkCompletedNormally(h, null);
1593 +        assertEquals(1, r.invocationCount);
1594 +        checkCompletedNormally(f, v1);
1595 +        checkCompletedNormally(g, v2);
1596 +        }
1597 +    }
1598 +
1599 +    /**
1600 +     * runAfterBoth result completes exceptionally after exceptional
1601 +     * completion of either source
1602 +     */
1603 +    public void testRunAfterBoth_exceptionalCompletion1() {
1604 +        for (ExecutionMode m : ExecutionMode.values())
1605 +        for (Integer v1 : new Integer[] { 1, null }) {
1606 +
1607 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1608 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1609 +        final Noop r = new Noop();
1610 +        final CompletableFuture<Void> h = m.runAfterBoth(f, g, r);
1611 +        final CFException ex = new CFException();
1612 +
1613 +        f.completeExceptionally(ex);
1614 +        checkIncomplete(h);
1615 +        g.complete(v1);
1616 +
1617 +        checkCompletedWithWrappedCFException(h, ex);
1618 +        checkCompletedWithWrappedCFException(f, ex);
1619 +        assertEquals(0, r.invocationCount);
1620 +        checkCompletedNormally(g, v1);
1621 +        }
1622 +    }
1623 +
1624 +    public void testRunAfterBoth_exceptionalCompletion2() {
1625 +        for (ExecutionMode m : ExecutionMode.values())
1626 +        for (Integer v1 : new Integer[] { 1, null }) {
1627 +
1628 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1629 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1630 +        final Noop r = new Noop();
1631 +        final CompletableFuture<Void> h = m.runAfterBoth(f, g, r);
1632 +        final CFException ex = new CFException();
1633 +
1634 +        g.completeExceptionally(ex);
1635 +        checkIncomplete(h);
1636 +        f.complete(v1);
1637 +
1638 +        checkCompletedWithWrappedCFException(h, ex);
1639 +        checkCompletedWithWrappedCFException(g, ex);
1640 +        assertEquals(0, r.invocationCount);
1641 +        checkCompletedNormally(f, v1);
1642 +        }
1643 +    }
1644 +
1645 +    public void testRunAfterBoth_exceptionalCompletion3() {
1646 +        for (ExecutionMode m : ExecutionMode.values())
1647 +        for (Integer v1 : new Integer[] { 1, null }) {
1648 +
1649 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1650 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1651 +        final Noop r = new Noop();
1652 +        final CFException ex = new CFException();
1653 +
1654 +        g.completeExceptionally(ex);
1655 +        f.complete(v1);
1656 +        final CompletableFuture<Void> h = m.runAfterBoth(f, g, r);
1657 +
1658 +        checkCompletedWithWrappedCFException(h, ex);
1659 +        checkCompletedWithWrappedCFException(g, ex);
1660 +        assertEquals(0, r.invocationCount);
1661 +        checkCompletedNormally(f, v1);
1662 +        }
1663 +    }
1664 +
1665 +    public void testRunAfterBoth_exceptionalCompletion4() {
1666 +        for (ExecutionMode m : ExecutionMode.values())
1667 +        for (Integer v1 : new Integer[] { 1, null }) {
1668 +
1669 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1670 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1671 +        final Noop r = new Noop();
1672 +        final CFException ex = new CFException();
1673 +
1674 +        f.completeExceptionally(ex);
1675 +        g.complete(v1);
1676 +        final CompletableFuture<Void> h = m.runAfterBoth(f, g, r);
1677 +
1678 +        checkCompletedWithWrappedCFException(h, ex);
1679 +        checkCompletedWithWrappedCFException(f, ex);
1680 +        assertEquals(0, r.invocationCount);
1681 +        checkCompletedNormally(g, v1);
1682 +        }
1683 +    }
1684 +
1685 +    /**
1686 +     * runAfterBoth result completes exceptionally if action does
1687 +     */
1688 +    public void testRunAfterBoth_actionFailed1() {
1689 +        for (ExecutionMode m : ExecutionMode.values())
1690 +        for (Integer v1 : new Integer[] { 1, null })
1691 +        for (Integer v2 : new Integer[] { 2, null }) {
1692 +
1693 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1694 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1695 +        final FailingNoop r = new FailingNoop();
1696 +        final CompletableFuture<Void> h = m.runAfterBoth(f, g, r);
1697 +
1698 +        f.complete(v1);
1699 +        checkIncomplete(h);
1700 +        g.complete(v2);
1701 +
1702 +        checkCompletedWithWrappedCFException(h);
1703 +        checkCompletedNormally(f, v1);
1704 +        checkCompletedNormally(g, v2);
1705 +        }
1706 +    }
1707 +
1708 +    public void testRunAfterBoth_actionFailed2() {
1709 +        for (ExecutionMode m : ExecutionMode.values())
1710 +        for (Integer v1 : new Integer[] { 1, null })
1711 +        for (Integer v2 : new Integer[] { 2, null }) {
1712 +
1713 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1714 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1715 +        final FailingNoop r = new FailingNoop();
1716 +        final CompletableFuture<Void> h = m.runAfterBoth(f, g, r);
1717 +
1718 +        g.complete(v2);
1719 +        checkIncomplete(h);
1720 +        f.complete(v1);
1721 +
1722 +        checkCompletedWithWrappedCFException(h);
1723 +        checkCompletedNormally(f, v1);
1724 +        checkCompletedNormally(g, v2);
1725 +        }
1726 +    }
1727 +
1728 +    /**
1729 +     * runAfterBoth result completes exceptionally if either source cancelled
1730 +     */
1731 +    public void testRunAfterBoth_sourceCancelled1() {
1732 +        for (ExecutionMode m : ExecutionMode.values())
1733 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
1734 +        for (Integer v1 : new Integer[] { 1, null }) {
1735 +
1736 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1737 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1738 +        final Noop r = new Noop();
1739 +        final CompletableFuture<Void> h = m.runAfterBoth(f, g, r);
1740 +
1741 +        assertTrue(f.cancel(mayInterruptIfRunning));
1742 +        checkIncomplete(h);
1743 +        g.complete(v1);
1744 +
1745 +        checkCompletedWithWrappedCancellationException(h);
1746 +        checkCancelled(f);
1747 +        assertEquals(0, r.invocationCount);
1748 +        checkCompletedNormally(g, v1);
1749 +        }
1750 +    }
1751 +
1752 +    public void testRunAfterBoth_sourceCancelled2() {
1753 +        for (ExecutionMode m : ExecutionMode.values())
1754 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
1755 +        for (Integer v1 : new Integer[] { 1, null }) {
1756 +
1757 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1758 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1759 +        final Noop r = new Noop();
1760 +        final CompletableFuture<Void> h = m.runAfterBoth(f, g, r);
1761 +
1762 +        assertTrue(g.cancel(mayInterruptIfRunning));
1763 +        checkIncomplete(h);
1764 +        f.complete(v1);
1765 +
1766 +        checkCompletedWithWrappedCancellationException(h);
1767 +        checkCancelled(g);
1768 +        assertEquals(0, r.invocationCount);
1769 +        checkCompletedNormally(f, v1);
1770 +        }
1771 +    }
1772 +
1773 +    public void testRunAfterBoth_sourceCancelled3() {
1774 +        for (ExecutionMode m : ExecutionMode.values())
1775 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
1776 +        for (Integer v1 : new Integer[] { 1, null }) {
1777 +
1778 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1779 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1780 +        final Noop r = new Noop();
1781 +
1782 +        assertTrue(g.cancel(mayInterruptIfRunning));
1783 +        f.complete(v1);
1784 +        final CompletableFuture<Void> h = m.runAfterBoth(f, g, r);
1785 +
1786 +        checkCompletedWithWrappedCancellationException(h);
1787 +        checkCancelled(g);
1788 +        assertEquals(0, r.invocationCount);
1789 +        checkCompletedNormally(f, v1);
1790 +        }
1791 +    }
1792 +
1793 +    public void testRunAfterBoth_sourceCancelled4() {
1794 +        for (ExecutionMode m : ExecutionMode.values())
1795 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
1796 +        for (Integer v1 : new Integer[] { 1, null }) {
1797 +
1798 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1799 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1800 +        final Noop r = new Noop();
1801 +
1802 +        assertTrue(f.cancel(mayInterruptIfRunning));
1803 +        g.complete(v1);
1804 +        final CompletableFuture<Void> h = m.runAfterBoth(f, g, r);
1805 +
1806 +        checkCompletedWithWrappedCancellationException(h);
1807 +        checkCancelled(f);
1808 +        assertEquals(0, r.invocationCount);
1809 +        checkCompletedNormally(g, v1);
1810 +        }
1811 +    }
1812 +
1813 +    /**
1814 +     * applyToEither result completes normally after normal completion
1815 +     * of either source
1816 +     */
1817 +    public void testApplyToEither_normalCompletion1() {
1818 +        for (ExecutionMode m : ExecutionMode.values())
1819 +        for (Integer v1 : new Integer[] { 1, null })
1820 +        for (Integer v2 : new Integer[] { 2, null }) {
1821 +
1822 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1823 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1824 +        final IncFunction r = new IncFunction();
1825 +        final CompletableFuture<Integer> h = m.applyToEither(f, g, r);
1826 +
1827 +        f.complete(v1);
1828 +        checkCompletedNormally(h, inc(v1));
1829 +        g.complete(v2);
1830 +
1831 +        checkCompletedNormally(f, v1);
1832 +        checkCompletedNormally(g, v2);
1833 +        checkCompletedNormally(h, inc(v1));
1834 +        }
1835 +    }
1836 +
1837 +    public void testApplyToEither_normalCompletion2() {
1838 +        for (ExecutionMode m : ExecutionMode.values())
1839 +        for (Integer v1 : new Integer[] { 1, null })
1840 +        for (Integer v2 : new Integer[] { 2, null }) {
1841 +
1842 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1843 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1844 +        final IncFunction r = new IncFunction();
1845 +        final CompletableFuture<Integer> h = m.applyToEither(f, g, r);
1846 +
1847 +        g.complete(v2);
1848 +        checkCompletedNormally(h, inc(v2));
1849 +        f.complete(v1);
1850 +
1851 +        checkCompletedNormally(f, v1);
1852 +        checkCompletedNormally(g, v2);
1853 +        checkCompletedNormally(h, inc(v2));
1854 +        }
1855 +    }
1856 +    public void testApplyToEither_normalCompletion3() {
1857 +        for (ExecutionMode m : ExecutionMode.values())
1858 +        for (Integer v1 : new Integer[] { 1, null })
1859 +        for (Integer v2 : new Integer[] { 2, null }) {
1860 +
1861 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1862 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1863 +        final IncFunction r = new IncFunction();
1864 +
1865 +        f.complete(v1);
1866 +        g.complete(v2);
1867 +        final CompletableFuture<Integer> h = m.applyToEither(f, g, r);
1868 +
1869 +        checkCompletedNormally(f, v1);
1870 +        checkCompletedNormally(g, v2);
1871 +
1872 +        // unspecified behavior
1873 +        assertTrue(Objects.equals(h.join(), inc(v1)) ||
1874 +                   Objects.equals(h.join(), inc(v2)));
1875 +        assertEquals(1, r.invocationCount);
1876 +        }
1877 +    }
1878 +
1879 +    /**
1880 +     * applyToEither result completes exceptionally after exceptional
1881 +     * completion of either source
1882 +     */
1883 +    public void testApplyToEither_exceptionalCompletion1() {
1884 +        for (ExecutionMode m : ExecutionMode.values())
1885 +        for (Integer v1 : new Integer[] { 1, null }) {
1886 +
1887 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1888 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1889 +        final IncFunction r = new IncFunction();
1890 +        final CompletableFuture<Integer> h = m.applyToEither(f, g, r);
1891 +        final CFException ex = new CFException();
1892 +
1893 +        f.completeExceptionally(ex);
1894 +        checkCompletedWithWrappedCFException(h, ex);
1895 +        g.complete(v1);
1896 +
1897 +        assertEquals(0, r.invocationCount);
1898 +        checkCompletedNormally(g, v1);
1899 +        checkCompletedWithWrappedCFException(f, ex);
1900 +        checkCompletedWithWrappedCFException(h, ex);
1901 +        }
1902 +    }
1903 +
1904 +    public void testApplyToEither_exceptionalCompletion2() {
1905 +        for (ExecutionMode m : ExecutionMode.values())
1906 +        for (Integer v1 : new Integer[] { 1, null }) {
1907 +
1908 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1909 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1910 +        final IncFunction r = new IncFunction();
1911 +        final CompletableFuture<Integer> h = m.applyToEither(f, g, r);
1912 +        final CFException ex = new CFException();
1913 +
1914 +        g.completeExceptionally(ex);
1915 +        checkCompletedWithWrappedCFException(h, ex);
1916 +        f.complete(v1);
1917 +
1918 +        assertEquals(0, r.invocationCount);
1919 +        checkCompletedNormally(f, v1);
1920 +        checkCompletedWithWrappedCFException(g, ex);
1921 +        checkCompletedWithWrappedCFException(h, ex);
1922 +        }
1923 +    }
1924 +
1925 +    public void testApplyToEither_exceptionalCompletion3() {
1926 +        for (ExecutionMode m : ExecutionMode.values())
1927 +        for (Integer v1 : new Integer[] { 1, null }) {
1928 +
1929 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1930 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1931 +        final IncFunction r = new IncFunction();
1932 +        final CFException ex = new CFException();
1933 +
1934 +        g.completeExceptionally(ex);
1935 +        f.complete(v1);
1936 +        final CompletableFuture<Integer> h = m.applyToEither(f, g, r);
1937 +
1938 +        // unspecified behavior
1939 +        Integer v;
1940 +        try {
1941 +            assertEquals(h.join(), inc(v1));
1942 +            assertEquals(1, r.invocationCount);
1943 +        } catch (CompletionException ok) {
1944 +            checkCompletedWithWrappedCFException(h, ex);
1945 +            assertEquals(0, r.invocationCount);
1946 +        }
1947 +
1948 +        checkCompletedWithWrappedCFException(g, ex);
1949 +        checkCompletedNormally(f, v1);
1950 +        }
1951 +    }
1952 +
1953 +    public void testApplyToEither_exceptionalCompletion4() {
1954 +        for (ExecutionMode m : ExecutionMode.values())
1955 +        for (Integer v1 : new Integer[] { 1, null }) {
1956 +
1957 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1958 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1959 +        final IncFunction r = new IncFunction();
1960 +        final CFException ex = new CFException();
1961 +
1962 +        f.completeExceptionally(ex);
1963 +        g.complete(v1);
1964 +        final CompletableFuture<Integer> h = m.applyToEither(f, g, r);
1965 +
1966 +        // unspecified behavior
1967 +        Integer v;
1968 +        try {
1969 +            assertEquals(h.join(), inc(v1));
1970 +            assertEquals(1, r.invocationCount);
1971 +        } catch (CompletionException ok) {
1972 +            checkCompletedWithWrappedCFException(h, ex);
1973 +            assertEquals(0, r.invocationCount);
1974 +        }
1975 +
1976 +        checkCompletedWithWrappedCFException(f, ex);
1977 +        checkCompletedNormally(g, v1);
1978 +        }
1979 +    }
1980 +
1981 +    /**
1982 +     * applyToEither result completes exceptionally if action does
1983 +     */
1984 +    public void testApplyToEither_actionFailed1() {
1985 +        for (ExecutionMode m : ExecutionMode.values())
1986 +        for (Integer v1 : new Integer[] { 1, null })
1987 +        for (Integer v2 : new Integer[] { 2, null }) {
1988 +
1989 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1990 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1991 +        final FailingFunction r = new FailingFunction();
1992 +        final CompletableFuture<Integer> h = m.applyToEither(f, g, r);
1993 +
1994 +        f.complete(v1);
1995 +        checkCompletedWithWrappedCFException(h);
1996 +        g.complete(v2);
1997 +        checkCompletedNormally(f, v1);
1998 +        checkCompletedNormally(g, v2);
1999 +        }
2000 +    }
2001 +
2002 +    public void testApplyToEither_actionFailed2() {
2003 +        for (ExecutionMode m : ExecutionMode.values())
2004 +        for (Integer v1 : new Integer[] { 1, null })
2005 +        for (Integer v2 : new Integer[] { 2, null }) {
2006 +
2007 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2008 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2009 +        final FailingFunction r = new FailingFunction();
2010 +        final CompletableFuture<Integer> h = m.applyToEither(f, g, r);
2011 +
2012 +        g.complete(v2);
2013 +        checkCompletedWithWrappedCFException(h);
2014 +        f.complete(v1);
2015 +        checkCompletedNormally(f, v1);
2016 +        checkCompletedNormally(g, v2);
2017 +        }
2018 +    }
2019 +
2020 +    /**
2021 +     * applyToEither result completes exceptionally if either source cancelled
2022 +     */
2023 +    public void testApplyToEither_sourceCancelled1() {
2024 +        for (ExecutionMode m : ExecutionMode.values())
2025 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
2026 +        for (Integer v1 : new Integer[] { 1, null }) {
2027 +
2028 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2029 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2030 +        final IncFunction r = new IncFunction();
2031 +        final CompletableFuture<Integer> h = m.applyToEither(f, g, r);
2032 +
2033 +        assertTrue(f.cancel(mayInterruptIfRunning));
2034 +        checkCompletedWithWrappedCancellationException(h);
2035 +        g.complete(v1);
2036 +
2037 +        checkCancelled(f);
2038 +        assertEquals(0, r.invocationCount);
2039 +        checkCompletedNormally(g, v1);
2040 +        checkCompletedWithWrappedCancellationException(h);
2041 +        }
2042 +    }
2043 +
2044 +    public void testApplyToEither_sourceCancelled2() {
2045 +        for (ExecutionMode m : ExecutionMode.values())
2046 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
2047 +        for (Integer v1 : new Integer[] { 1, null }) {
2048 +
2049 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2050 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2051 +        final IncFunction r = new IncFunction();
2052 +        final CompletableFuture<Integer> h = m.applyToEither(f, g, r);
2053 +
2054 +        assertTrue(g.cancel(mayInterruptIfRunning));
2055 +        checkCompletedWithWrappedCancellationException(h);
2056 +        f.complete(v1);
2057 +
2058 +        checkCancelled(g);
2059 +        assertEquals(0, r.invocationCount);
2060 +        checkCompletedNormally(f, v1);
2061 +        checkCompletedWithWrappedCancellationException(h);
2062 +        }
2063 +    }
2064 +
2065 +    public void testApplyToEither_sourceCancelled3() {
2066 +        for (ExecutionMode m : ExecutionMode.values())
2067 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
2068 +        for (Integer v1 : new Integer[] { 1, null }) {
2069 +
2070 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2071 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2072 +        final IncFunction r = new IncFunction();
2073 +
2074 +        assertTrue(g.cancel(mayInterruptIfRunning));
2075 +        f.complete(v1);
2076 +        final CompletableFuture<Integer> h = m.applyToEither(f, g, r);
2077 +
2078 +        // unspecified behavior
2079 +        Integer v;
2080 +        try {
2081 +            assertEquals(h.join(), inc(v1));
2082 +            assertEquals(1, r.invocationCount);
2083 +        } catch (CompletionException ok) {
2084 +            checkCompletedWithWrappedCancellationException(h);
2085 +            assertEquals(0, r.invocationCount);
2086 +        }
2087 +
2088 +        checkCancelled(g);
2089 +        checkCompletedNormally(f, v1);
2090 +        }
2091 +    }
2092 +
2093 +    public void testApplyToEither_sourceCancelled4() {
2094 +        for (ExecutionMode m : ExecutionMode.values())
2095 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
2096 +        for (Integer v1 : new Integer[] { 1, null }) {
2097 +
2098 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2099 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2100 +        final IncFunction r = new IncFunction();
2101 +
2102 +        assertTrue(f.cancel(mayInterruptIfRunning));
2103 +        g.complete(v1);
2104 +        final CompletableFuture<Integer> h = m.applyToEither(f, g, r);
2105 +
2106 +        // unspecified behavior
2107 +        Integer v;
2108 +        try {
2109 +            assertEquals(h.join(), inc(v1));
2110 +            assertEquals(1, r.invocationCount);
2111 +        } catch (CompletionException ok) {
2112 +            checkCompletedWithWrappedCancellationException(h);
2113 +            assertEquals(0, r.invocationCount);
2114 +        }
2115 +
2116 +        checkCancelled(f);
2117 +        checkCompletedNormally(g, v1);
2118 +        }
2119 +    }
2120 +
2121 +    /**
2122 +     * acceptEither result completes normally after normal completion
2123 +     * of either source
2124 +     */
2125 +    public void testAcceptEither_normalCompletion1() {
2126 +        for (ExecutionMode m : ExecutionMode.values())
2127 +        for (Integer v1 : new Integer[] { 1, null })
2128 +        for (Integer v2 : new Integer[] { 2, null }) {
2129 +
2130 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2131 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2132 +        final IncAction r = new IncAction();
2133 +        final CompletableFuture<Void> h = m.acceptEither(f, g, r);
2134 +
2135 +        f.complete(v1);
2136 +        checkCompletedNormally(h, null);
2137 +        assertEquals(r.value, inc(v1));
2138 +        g.complete(v2);
2139 +
2140 +        checkCompletedNormally(f, v1);
2141 +        checkCompletedNormally(g, v2);
2142 +        checkCompletedNormally(h, null);
2143 +        }
2144 +    }
2145 +
2146 +    public void testAcceptEither_normalCompletion2() {
2147 +        for (ExecutionMode m : ExecutionMode.values())
2148 +        for (Integer v1 : new Integer[] { 1, null })
2149 +        for (Integer v2 : new Integer[] { 2, null }) {
2150 +
2151 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2152 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2153 +        final IncAction r = new IncAction();
2154 +        final CompletableFuture<Void> h = m.acceptEither(f, g, r);
2155 +
2156 +        g.complete(v2);
2157 +        checkCompletedNormally(h, null);
2158 +        assertEquals(r.value, inc(v2));
2159 +        f.complete(v1);
2160 +
2161 +        checkCompletedNormally(f, v1);
2162 +        checkCompletedNormally(g, v2);
2163 +        checkCompletedNormally(h, null);
2164 +        }
2165 +    }
2166 +    public void testAcceptEither_normalCompletion3() {
2167 +        for (ExecutionMode m : ExecutionMode.values())
2168 +        for (Integer v1 : new Integer[] { 1, null })
2169 +        for (Integer v2 : new Integer[] { 2, null }) {
2170 +
2171 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2172 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2173 +        final IncAction r = new IncAction();
2174 +
2175 +        f.complete(v1);
2176 +        g.complete(v2);
2177 +        final CompletableFuture<Void> h = m.acceptEither(f, g, r);
2178 +
2179 +        checkCompletedNormally(h, null);
2180 +        checkCompletedNormally(f, v1);
2181 +        checkCompletedNormally(g, v2);
2182 +
2183 +        // unspecified behavior
2184 +        assertTrue(Objects.equals(r.value, inc(v1)) ||
2185 +                   Objects.equals(r.value, inc(v2)));
2186 +        }
2187 +    }
2188 +
2189 +    /**
2190 +     * acceptEither result completes exceptionally after exceptional
2191 +     * completion of either source
2192 +     */
2193 +    public void testAcceptEither_exceptionalCompletion1() {
2194 +        for (ExecutionMode m : ExecutionMode.values())
2195 +        for (Integer v1 : new Integer[] { 1, null }) {
2196 +
2197 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2198 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2199 +        final IncAction r = new IncAction();
2200 +        final CompletableFuture<Void> h = m.acceptEither(f, g, r);
2201 +        final CFException ex = new CFException();
2202 +
2203 +        f.completeExceptionally(ex);
2204 +        checkCompletedWithWrappedCFException(h, ex);
2205 +        g.complete(v1);
2206 +
2207 +        assertEquals(0, r.invocationCount);
2208 +        checkCompletedNormally(g, v1);
2209 +        checkCompletedWithWrappedCFException(f, ex);
2210 +        checkCompletedWithWrappedCFException(h, ex);
2211 +        }
2212 +    }
2213 +
2214 +    public void testAcceptEither_exceptionalCompletion2() {
2215 +        for (ExecutionMode m : ExecutionMode.values())
2216 +        for (Integer v1 : new Integer[] { 1, null }) {
2217 +
2218 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2219 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2220 +        final IncAction r = new IncAction();
2221 +        final CompletableFuture<Void> h = m.acceptEither(f, g, r);
2222 +        final CFException ex = new CFException();
2223 +
2224 +        g.completeExceptionally(ex);
2225 +        checkCompletedWithWrappedCFException(h, ex);
2226 +        f.complete(v1);
2227 +
2228 +        assertEquals(0, r.invocationCount);
2229 +        checkCompletedNormally(f, v1);
2230 +        checkCompletedWithWrappedCFException(g, ex);
2231 +        checkCompletedWithWrappedCFException(h, ex);
2232 +        }
2233 +    }
2234 +
2235 +    public void testAcceptEither_exceptionalCompletion3() {
2236 +        for (ExecutionMode m : ExecutionMode.values())
2237 +        for (Integer v1 : new Integer[] { 1, null }) {
2238 +
2239 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2240 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2241 +        final IncAction r = new IncAction();
2242 +        final CFException ex = new CFException();
2243 +
2244 +        g.completeExceptionally(ex);
2245 +        f.complete(v1);
2246 +        final CompletableFuture<Void> h = m.acceptEither(f, g, r);
2247 +
2248 +        // unspecified behavior
2249 +        Integer v;
2250 +        try {
2251 +            assertEquals(h.join(), null);
2252 +            assertEquals(1, r.invocationCount);
2253 +            assertEquals(inc(v1), r.value);
2254 +        } catch (CompletionException ok) {
2255 +            checkCompletedWithWrappedCFException(h, ex);
2256 +            assertEquals(0, r.invocationCount);
2257 +        }
2258 +
2259 +        checkCompletedWithWrappedCFException(g, ex);
2260 +        checkCompletedNormally(f, v1);
2261 +        }
2262 +    }
2263 +
2264 +    public void testAcceptEither_exceptionalCompletion4() {
2265 +        for (ExecutionMode m : ExecutionMode.values())
2266 +        for (Integer v1 : new Integer[] { 1, null }) {
2267 +
2268 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2269 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2270 +        final IncAction r = new IncAction();
2271 +        final CFException ex = new CFException();
2272 +
2273 +        f.completeExceptionally(ex);
2274 +        g.complete(v1);
2275 +        final CompletableFuture<Void> h = m.acceptEither(f, g, r);
2276 +
2277 +        // unspecified behavior
2278 +        Integer v;
2279 +        try {
2280 +            assertEquals(h.join(), null);
2281 +            assertEquals(1, r.invocationCount);
2282 +            assertEquals(inc(v1), r.value);
2283 +        } catch (CompletionException ok) {
2284 +            checkCompletedWithWrappedCFException(h, ex);
2285 +            assertEquals(0, r.invocationCount);
2286 +        }
2287 +
2288 +        checkCompletedWithWrappedCFException(f, ex);
2289 +        checkCompletedNormally(g, v1);
2290 +        }
2291 +    }
2292 +
2293 +    /**
2294 +     * acceptEither result completes exceptionally if action does
2295 +     */
2296 +    public void testAcceptEither_actionFailed1() {
2297 +        for (ExecutionMode m : ExecutionMode.values())
2298 +        for (Integer v1 : new Integer[] { 1, null })
2299 +        for (Integer v2 : new Integer[] { 2, null }) {
2300 +
2301 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2302 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2303 +        final FailingConsumer r = new FailingConsumer();
2304 +        final CompletableFuture<Void> h = m.acceptEither(f, g, r);
2305 +
2306 +        f.complete(v1);
2307 +        checkCompletedWithWrappedCFException(h);
2308 +        g.complete(v2);
2309 +        checkCompletedNormally(f, v1);
2310 +        checkCompletedNormally(g, v2);
2311 +        }
2312 +    }
2313 +
2314 +    public void testAcceptEither_actionFailed2() {
2315 +        for (ExecutionMode m : ExecutionMode.values())
2316 +        for (Integer v1 : new Integer[] { 1, null })
2317 +        for (Integer v2 : new Integer[] { 2, null }) {
2318 +
2319 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2320 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2321 +        final FailingConsumer r = new FailingConsumer();
2322 +        final CompletableFuture<Void> h = m.acceptEither(f, g, r);
2323 +
2324 +        g.complete(v2);
2325 +        checkCompletedWithWrappedCFException(h);
2326 +        f.complete(v1);
2327 +        checkCompletedNormally(f, v1);
2328 +        checkCompletedNormally(g, v2);
2329 +        }
2330 +    }
2331 +
2332 +    /**
2333 +     * acceptEither result completes exceptionally if either source cancelled
2334 +     */
2335 +    public void testAcceptEither_sourceCancelled1() {
2336 +        for (ExecutionMode m : ExecutionMode.values())
2337 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
2338 +        for (Integer v1 : new Integer[] { 1, null }) {
2339 +
2340 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2341 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2342 +        final IncAction r = new IncAction();
2343 +        final CompletableFuture<Void> h = m.acceptEither(f, g, r);
2344 +
2345 +        assertTrue(f.cancel(mayInterruptIfRunning));
2346 +        checkCompletedWithWrappedCancellationException(h);
2347 +        g.complete(v1);
2348 +
2349 +        checkCancelled(f);
2350 +        assertEquals(0, r.invocationCount);
2351 +        checkCompletedNormally(g, v1);
2352 +        checkCompletedWithWrappedCancellationException(h);
2353 +        }
2354 +    }
2355 +
2356 +    public void testAcceptEither_sourceCancelled2() {
2357 +        for (ExecutionMode m : ExecutionMode.values())
2358 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
2359 +        for (Integer v1 : new Integer[] { 1, null }) {
2360 +
2361 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2362 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2363 +        final IncAction r = new IncAction();
2364 +        final CompletableFuture<Void> h = m.acceptEither(f, g, r);
2365 +
2366 +        assertTrue(g.cancel(mayInterruptIfRunning));
2367 +        checkCompletedWithWrappedCancellationException(h);
2368 +        f.complete(v1);
2369 +
2370 +        checkCancelled(g);
2371 +        assertEquals(0, r.invocationCount);
2372 +        checkCompletedNormally(f, v1);
2373 +        checkCompletedWithWrappedCancellationException(h);
2374 +        }
2375 +    }
2376 +
2377 +    public void testAcceptEither_sourceCancelled3() {
2378 +        for (ExecutionMode m : ExecutionMode.values())
2379 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
2380 +        for (Integer v1 : new Integer[] { 1, null }) {
2381 +
2382 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2383 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2384 +        final IncAction r = new IncAction();
2385 +
2386 +        assertTrue(g.cancel(mayInterruptIfRunning));
2387 +        f.complete(v1);
2388 +        final CompletableFuture<Void> h = m.acceptEither(f, g, r);
2389 +
2390 +        // unspecified behavior
2391 +        Integer v;
2392 +        try {
2393 +            assertEquals(h.join(), null);
2394 +            assertEquals(1, r.invocationCount);
2395 +            assertEquals(inc(v1), r.value);
2396 +        } catch (CompletionException ok) {
2397 +            checkCompletedWithWrappedCancellationException(h);
2398 +            assertEquals(0, r.invocationCount);
2399 +        }
2400 +
2401 +        checkCancelled(g);
2402 +        checkCompletedNormally(f, v1);
2403 +        }
2404 +    }
2405 +
2406 +    public void testAcceptEither_sourceCancelled4() {
2407 +        for (ExecutionMode m : ExecutionMode.values())
2408 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
2409 +        for (Integer v1 : new Integer[] { 1, null }) {
2410 +
2411 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2412 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2413 +        final IncAction r = new IncAction();
2414 +
2415 +        assertTrue(f.cancel(mayInterruptIfRunning));
2416 +        g.complete(v1);
2417 +        final CompletableFuture<Void> h = m.acceptEither(f, g, r);
2418 +
2419 +        // unspecified behavior
2420 +        Integer v;
2421 +        try {
2422 +            assertEquals(h.join(), null);
2423 +            assertEquals(1, r.invocationCount);
2424 +            assertEquals(inc(v1), r.value);
2425 +        } catch (CompletionException ok) {
2426 +            checkCompletedWithWrappedCancellationException(h);
2427 +            assertEquals(0, r.invocationCount);
2428 +        }
2429 +
2430 +        checkCancelled(f);
2431 +        checkCompletedNormally(g, v1);
2432 +        }
2433 +    }
2434 +
2435 +    /**
2436 +     * runAfterEither result completes normally after normal completion
2437 +     * of either source
2438 +     */
2439 +    public void testRunAfterEither_normalCompletion1() {
2440 +        for (ExecutionMode m : ExecutionMode.values())
2441 +        for (Integer v1 : new Integer[] { 1, null })
2442 +        for (Integer v2 : new Integer[] { 2, null }) {
2443 +
2444 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2445 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2446 +        final Noop r = new Noop();
2447 +        final CompletableFuture<Void> h = m.runAfterEither(f, g, r);
2448 +
2449 +        f.complete(v1);
2450 +        checkCompletedNormally(h, null);
2451 +        assertEquals(1, r.invocationCount);
2452 +        g.complete(v2);
2453 +
2454 +        checkCompletedNormally(f, v1);
2455 +        checkCompletedNormally(g, v2);
2456 +        checkCompletedNormally(h, null);
2457 +        assertEquals(1, r.invocationCount);
2458 +        }
2459 +    }
2460 +
2461 +    public void testRunAfterEither_normalCompletion2() {
2462 +        for (ExecutionMode m : ExecutionMode.values())
2463 +        for (Integer v1 : new Integer[] { 1, null })
2464 +        for (Integer v2 : new Integer[] { 2, null }) {
2465 +
2466 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2467 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2468 +        final Noop r = new Noop();
2469 +        final CompletableFuture<Void> h = m.runAfterEither(f, g, r);
2470 +
2471 +        g.complete(v2);
2472 +        checkCompletedNormally(h, null);
2473 +        assertEquals(1, r.invocationCount);
2474 +        f.complete(v1);
2475 +
2476 +        checkCompletedNormally(f, v1);
2477 +        checkCompletedNormally(g, v2);
2478 +        checkCompletedNormally(h, null);
2479 +        assertEquals(1, r.invocationCount);
2480 +        }
2481 +    }
2482 +    public void testRunAfterEither_normalCompletion3() {
2483 +        for (ExecutionMode m : ExecutionMode.values())
2484 +        for (Integer v1 : new Integer[] { 1, null })
2485 +        for (Integer v2 : new Integer[] { 2, null }) {
2486 +
2487 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2488 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2489 +        final Noop r = new Noop();
2490 +
2491 +        f.complete(v1);
2492 +        g.complete(v2);
2493 +        final CompletableFuture<Void> h = m.runAfterEither(f, g, r);
2494 +
2495 +        checkCompletedNormally(h, null);
2496 +        checkCompletedNormally(f, v1);
2497 +        checkCompletedNormally(g, v2);
2498 +        assertEquals(1, r.invocationCount);
2499 +        }
2500 +    }
2501 +
2502 +    /**
2503 +     * runAfterEither result completes exceptionally after exceptional
2504 +     * completion of either source
2505 +     */
2506 +    public void testRunAfterEither_exceptionalCompletion1() {
2507 +        for (ExecutionMode m : ExecutionMode.values())
2508 +        for (Integer v1 : new Integer[] { 1, null }) {
2509 +
2510 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2511 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2512 +        final Noop r = new Noop();
2513 +        final CompletableFuture<Void> h = m.runAfterEither(f, g, r);
2514 +        final CFException ex = new CFException();
2515 +
2516 +        f.completeExceptionally(ex);
2517 +        checkCompletedWithWrappedCFException(h, ex);
2518 +        g.complete(v1);
2519 +
2520 +        assertEquals(0, r.invocationCount);
2521 +        checkCompletedNormally(g, v1);
2522 +        checkCompletedWithWrappedCFException(f, ex);
2523 +        checkCompletedWithWrappedCFException(h, ex);
2524 +        }
2525 +    }
2526 +
2527 +    public void testRunAfterEither_exceptionalCompletion2() {
2528 +        for (ExecutionMode m : ExecutionMode.values())
2529 +        for (Integer v1 : new Integer[] { 1, null }) {
2530 +
2531 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2532 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2533 +        final Noop r = new Noop();
2534 +        final CompletableFuture<Void> h = m.runAfterEither(f, g, r);
2535 +        final CFException ex = new CFException();
2536 +
2537 +        g.completeExceptionally(ex);
2538 +        checkCompletedWithWrappedCFException(h, ex);
2539 +        f.complete(v1);
2540 +
2541 +        assertEquals(0, r.invocationCount);
2542 +        checkCompletedNormally(f, v1);
2543 +        checkCompletedWithWrappedCFException(g, ex);
2544 +        checkCompletedWithWrappedCFException(h, ex);
2545 +        }
2546 +    }
2547 +
2548 +    public void testRunAfterEither_exceptionalCompletion3() {
2549 +        for (ExecutionMode m : ExecutionMode.values())
2550 +        for (Integer v1 : new Integer[] { 1, null }) {
2551 +
2552 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2553 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2554 +        final Noop r = new Noop();
2555 +        final CFException ex = new CFException();
2556 +
2557 +        g.completeExceptionally(ex);
2558 +        f.complete(v1);
2559 +        final CompletableFuture<Void> h = m.runAfterEither(f, g, r);
2560 +
2561 +        // unspecified behavior
2562 +        Integer v;
2563 +        try {
2564 +            assertEquals(h.join(), null);
2565 +            assertEquals(1, r.invocationCount);
2566 +        } catch (CompletionException ok) {
2567 +            checkCompletedWithWrappedCFException(h, ex);
2568 +            assertEquals(0, r.invocationCount);
2569 +        }
2570 +
2571 +        checkCompletedWithWrappedCFException(g, ex);
2572 +        checkCompletedNormally(f, v1);
2573 +        }
2574 +    }
2575 +
2576 +    public void testRunAfterEither_exceptionalCompletion4() {
2577 +        for (ExecutionMode m : ExecutionMode.values())
2578 +        for (Integer v1 : new Integer[] { 1, null }) {
2579 +
2580 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2581 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2582 +        final Noop r = new Noop();
2583 +        final CFException ex = new CFException();
2584 +
2585 +        f.completeExceptionally(ex);
2586 +        g.complete(v1);
2587 +        final CompletableFuture<Void> h = m.runAfterEither(f, g, r);
2588 +
2589 +        // unspecified behavior
2590 +        Integer v;
2591 +        try {
2592 +            assertEquals(h.join(), null);
2593 +            assertEquals(1, r.invocationCount);
2594 +        } catch (CompletionException ok) {
2595 +            checkCompletedWithWrappedCFException(h, ex);
2596 +            assertEquals(0, r.invocationCount);
2597 +        }
2598 +
2599 +        checkCompletedWithWrappedCFException(f, ex);
2600 +        checkCompletedNormally(g, v1);
2601 +        }
2602 +    }
2603 +
2604 +    /**
2605 +     * runAfterEither result completes exceptionally if action does
2606 +     */
2607 +    public void testRunAfterEither_actionFailed1() {
2608 +        for (ExecutionMode m : ExecutionMode.values())
2609 +        for (Integer v1 : new Integer[] { 1, null })
2610 +        for (Integer v2 : new Integer[] { 2, null }) {
2611 +
2612 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2613 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2614 +        final FailingNoop r = new FailingNoop();
2615 +        final CompletableFuture<Void> h = m.runAfterEither(f, g, r);
2616 +
2617 +        f.complete(v1);
2618 +        checkCompletedWithWrappedCFException(h);
2619 +        g.complete(v2);
2620 +        checkCompletedNormally(f, v1);
2621 +        checkCompletedNormally(g, v2);
2622 +        }
2623 +    }
2624 +
2625 +    public void testRunAfterEither_actionFailed2() {
2626 +        for (ExecutionMode m : ExecutionMode.values())
2627 +        for (Integer v1 : new Integer[] { 1, null })
2628 +        for (Integer v2 : new Integer[] { 2, null }) {
2629 +
2630 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2631 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2632 +        final FailingNoop r = new FailingNoop();
2633 +        final CompletableFuture<Void> h = m.runAfterEither(f, g, r);
2634 +
2635 +        g.complete(v2);
2636 +        checkCompletedWithWrappedCFException(h);
2637 +        f.complete(v1);
2638 +        checkCompletedNormally(f, v1);
2639 +        checkCompletedNormally(g, v2);
2640 +        }
2641 +    }
2642 +
2643 +    /**
2644 +     * runAfterEither result completes exceptionally if either source cancelled
2645 +     */
2646 +    public void testRunAfterEither_sourceCancelled1() {
2647 +        for (ExecutionMode m : ExecutionMode.values())
2648 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
2649 +        for (Integer v1 : new Integer[] { 1, null }) {
2650 +
2651 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2652 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2653 +        final Noop r = new Noop();
2654 +        final CompletableFuture<Void> h = m.runAfterEither(f, g, r);
2655 +
2656 +        assertTrue(f.cancel(mayInterruptIfRunning));
2657 +        checkCompletedWithWrappedCancellationException(h);
2658 +        g.complete(v1);
2659 +
2660 +        checkCancelled(f);
2661 +        assertEquals(0, r.invocationCount);
2662 +        checkCompletedNormally(g, v1);
2663 +        checkCompletedWithWrappedCancellationException(h);
2664 +        }
2665 +    }
2666 +
2667 +    public void testRunAfterEither_sourceCancelled2() {
2668 +        for (ExecutionMode m : ExecutionMode.values())
2669 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
2670 +        for (Integer v1 : new Integer[] { 1, null }) {
2671 +
2672 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2673 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2674 +        final Noop r = new Noop();
2675 +        final CompletableFuture<Void> h = m.runAfterEither(f, g, r);
2676 +
2677 +        assertTrue(g.cancel(mayInterruptIfRunning));
2678 +        checkCompletedWithWrappedCancellationException(h);
2679 +        f.complete(v1);
2680 +
2681 +        checkCancelled(g);
2682 +        assertEquals(0, r.invocationCount);
2683 +        checkCompletedNormally(f, v1);
2684 +        checkCompletedWithWrappedCancellationException(h);
2685 +        }
2686 +    }
2687 +
2688 +    public void testRunAfterEither_sourceCancelled3() {
2689 +        for (ExecutionMode m : ExecutionMode.values())
2690 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
2691 +        for (Integer v1 : new Integer[] { 1, null }) {
2692 +
2693 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2694 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2695 +        final Noop r = new Noop();
2696 +
2697 +        assertTrue(g.cancel(mayInterruptIfRunning));
2698 +        f.complete(v1);
2699 +        final CompletableFuture<Void> h = m.runAfterEither(f, g, r);
2700 +
2701 +        // unspecified behavior
2702 +        Integer v;
2703 +        try {
2704 +            assertEquals(h.join(), null);
2705 +            assertEquals(1, r.invocationCount);
2706 +        } catch (CompletionException ok) {
2707 +            checkCompletedWithWrappedCancellationException(h);
2708 +            assertEquals(0, r.invocationCount);
2709 +        }
2710 +
2711 +        checkCancelled(g);
2712 +        checkCompletedNormally(f, v1);
2713 +        }
2714 +    }
2715 +
2716 +    public void testRunAfterEither_sourceCancelled4() {
2717 +        for (ExecutionMode m : ExecutionMode.values())
2718 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
2719 +        for (Integer v1 : new Integer[] { 1, null }) {
2720 +
2721 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2722 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
2723 +        final Noop r = new Noop();
2724 +
2725 +        assertTrue(f.cancel(mayInterruptIfRunning));
2726 +        g.complete(v1);
2727 +        final CompletableFuture<Void> h = m.runAfterEither(f, g, r);
2728 +
2729 +        // unspecified behavior
2730 +        Integer v;
2731 +        try {
2732 +            assertEquals(h.join(), null);
2733 +            assertEquals(1, r.invocationCount);
2734 +        } catch (CompletionException ok) {
2735 +            checkCompletedWithWrappedCancellationException(h);
2736 +            assertEquals(0, r.invocationCount);
2737 +        }
2738 +
2739 +        checkCancelled(f);
2740 +        checkCompletedNormally(g, v1);
2741 +        }
2742 +    }
2743 +
2744 +    /**
2745 +     * thenCompose result completes normally after normal completion of source
2746 +     */
2747 +    public void testThenCompose_normalCompletion1() {
2748 +        for (ExecutionMode m : ExecutionMode.values())
2749 +        for (Integer v1 : new Integer[] { 1, null }) {
2750 +
2751 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2752 +        final CompletableFutureInc r = new CompletableFutureInc();
2753 +        final CompletableFuture<Integer> g = f.thenCompose(r);
2754 +        f.complete(v1);
2755 +        checkCompletedNormally(g, inc(v1));
2756 +        checkCompletedNormally(f, v1);
2757 +        assertEquals(1, r.invocationCount);
2758 +        }
2759 +    }
2760 +
2761 +    public void testThenCompose_normalCompletion2() {
2762 +        for (ExecutionMode m : ExecutionMode.values())
2763 +        for (Integer v1 : new Integer[] { 1, null }) {
2764 +
2765 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2766 +        final CompletableFutureInc r = new CompletableFutureInc();
2767 +        f.complete(v1);
2768 +        final CompletableFuture<Integer> g = f.thenCompose(r);
2769 +        checkCompletedNormally(g, inc(v1));
2770 +        checkCompletedNormally(f, v1);
2771 +        assertEquals(1, r.invocationCount);
2772 +        }
2773 +    }
2774 +
2775 +    /**
2776 +     * thenCompose result completes exceptionally after exceptional
2777 +     * completion of source
2778 +     */
2779 +    public void testThenCompose_exceptionalCompletion1() {
2780 +        for (ExecutionMode m : ExecutionMode.values()) {
2781 +
2782 +        final CFException ex = new CFException();
2783 +        final CompletableFutureInc r = new CompletableFutureInc();
2784 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2785 +        final CompletableFuture<Integer> g = f.thenCompose(r);
2786 +        f.completeExceptionally(ex);
2787 +        checkCompletedWithWrappedCFException(g, ex);
2788 +        checkCompletedWithWrappedCFException(f, ex);
2789 +        }
2790 +    }
2791 +
2792 +    public void testThenCompose_exceptionalCompletion2() {
2793 +        for (ExecutionMode m : ExecutionMode.values()) {
2794 +
2795 +        final CFException ex = new CFException();
2796 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2797 +        f.completeExceptionally(ex);
2798 +        final CompletableFutureInc r = new CompletableFutureInc();
2799 +        final CompletableFuture<Integer> g = f.thenCompose(r);
2800 +        checkCompletedWithWrappedCFException(g, ex);
2801 +        checkCompletedWithWrappedCFException(f, ex);
2802 +        }
2803 +    }
2804 +
2805 +    /**
2806 +     * thenCompose result completes exceptionally if action does
2807 +     */
2808 +    public void testThenCompose_actionFailed1() {
2809 +        for (ExecutionMode m : ExecutionMode.values())
2810 +        for (Integer v1 : new Integer[] { 1, null }) {
2811 +
2812 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2813 +        final FailingCompletableFutureFunction r
2814 +            = new FailingCompletableFutureFunction();
2815 +        final CompletableFuture<Integer> g = f.thenCompose(r);
2816 +        f.complete(v1);
2817 +        checkCompletedWithWrappedCFException(g);
2818 +        checkCompletedNormally(f, v1);
2819 +        }
2820 +    }
2821 +
2822 +    public void testThenCompose_actionFailed2() {
2823 +        for (ExecutionMode m : ExecutionMode.values())
2824 +        for (Integer v1 : new Integer[] { 1, null }) {
2825 +
2826 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2827 +        f.complete(v1);
2828 +        final FailingCompletableFutureFunction r
2829 +            = new FailingCompletableFutureFunction();
2830 +        final CompletableFuture<Integer> g = f.thenCompose(r);
2831 +        checkCompletedWithWrappedCFException(g);
2832 +        checkCompletedNormally(f, v1);
2833 +        }
2834 +    }
2835 +
2836 +    /**
2837 +     * thenCompose result completes exceptionally if source cancelled
2838 +     */
2839 +    public void testThenCompose_sourceCancelled1() {
2840 +        for (ExecutionMode m : ExecutionMode.values())
2841 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false }) {
2842 +
2843 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2844 +        final CompletableFutureInc r = new CompletableFutureInc();
2845 +        final CompletableFuture<Integer> g = f.thenCompose(r);
2846 +        assertTrue(f.cancel(mayInterruptIfRunning));
2847 +        checkCompletedWithWrappedCancellationException(g);
2848 +        checkCancelled(f);
2849 +        }
2850 +    }
2851 +
2852 +    public void testThenCompose_sourceCancelled2() {
2853 +        for (ExecutionMode m : ExecutionMode.values())
2854 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false }) {
2855 +
2856 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
2857 +        assertTrue(f.cancel(mayInterruptIfRunning));
2858 +        final CompletableFutureInc r = new CompletableFutureInc();
2859 +        final CompletableFuture<Integer> g = f.thenCompose(r);
2860 +        checkCompletedWithWrappedCancellationException(g);
2861 +        checkCancelled(f);
2862 +        }
2863 +    }
2864 +
2865 +    // asyncs
2866 +
2867 +    /**
2868 +     * thenRunAsync result completes normally after normal completion of source
2869 +     */
2870 +    public void testThenRunAsync() {
2871 +        CompletableFuture<Integer> f = new CompletableFuture<>();
2872 +        Noop r = new Noop();
2873 +        CompletableFuture<Void> g = f.thenRunAsync(r);
2874 +        f.complete(null);
2875 +        checkCompletedNormally(g, null);
2876 +
2877 +        // reordered version
2878 +        f = new CompletableFuture<>();
2879 +        f.complete(null);
2880 +        r = new Noop();
2881 +        g = f.thenRunAsync(r);
2882 +        checkCompletedNormally(g, null);
2883 +    }
2884 +
2885 +    /**
2886 +     * thenRunAsync result completes exceptionally after exceptional
2887 +     * completion of source
2888 +     */
2889 +    public void testThenRunAsync2() {
2890 +        CompletableFuture<Integer> f = new CompletableFuture<>();
2891 +        Noop r = new Noop();
2892 +        CompletableFuture<Void> g = f.thenRunAsync(r);
2893 +        f.completeExceptionally(new CFException());
2894 +        try {
2895 +            g.join();
2896 +            shouldThrow();
2897 +        } catch (CompletionException success) {}
2898 +        checkCompletedWithWrappedCFException(g);
2899 +    }
2900 +
2901 +    /**
2902 +     * thenRunAsync result completes exceptionally if action does
2903 +     */
2904 +    public void testThenRunAsync3() {
2905 +        CompletableFuture<Integer> f = new CompletableFuture<>();
2906 +        FailingNoop r = new FailingNoop();
2907 +        CompletableFuture<Void> g = f.thenRunAsync(r);
2908 +        f.complete(null);
2909 +        checkCompletedWithWrappedCFException(g);
2910 +    }
2911 +
2912 +    /**
2913 +     * thenRunAsync result completes exceptionally if source cancelled
2914 +     */
2915 +    public void testThenRunAsync4() {
2916 +        CompletableFuture<Integer> f = new CompletableFuture<>();
2917 +        Noop r = new Noop();
2918 +        CompletableFuture<Void> g = f.thenRunAsync(r);
2919 +        assertTrue(f.cancel(true));
2920 +        checkCompletedWithWrappedCancellationException(g);
2921 +    }
2922 +
2923 +    /**
2924 +     * thenApplyAsync result completes normally after normal completion of source
2925 +     */
2926 +    public void testThenApplyAsync() {
2927 +        CompletableFuture<Integer> f = new CompletableFuture<>();
2928 +        CompletableFuture<Integer> g = f.thenApplyAsync(inc);
2929 +        f.complete(one);
2930 +        checkCompletedNormally(g, two);
2931 +    }
2932 +
2933 +    /**
2934 +     * thenApplyAsync result completes exceptionally after exceptional
2935 +     * completion of source
2936 +     */
2937 +    public void testThenApplyAsync2() {
2938 +        CompletableFuture<Integer> f = new CompletableFuture<>();
2939 +        CompletableFuture<Integer> g = f.thenApplyAsync(inc);
2940 +        f.completeExceptionally(new CFException());
2941 +        checkCompletedWithWrappedCFException(g);
2942 +    }
2943 +
2944 +    /**
2945 +     * thenApplyAsync result completes exceptionally if action does
2946 +     */
2947 +    public void testThenApplyAsync3() {
2948 +        CompletableFuture<Integer> f = new CompletableFuture<>();
2949 +        FailingFunction r = new FailingFunction();
2950 +        CompletableFuture<Integer> g = f.thenApplyAsync(r);
2951 +        f.complete(null);
2952 +        checkCompletedWithWrappedCFException(g);
2953 +    }
2954 +
2955 +    /**
2956 +     * thenApplyAsync result completes exceptionally if source cancelled
2957 +     */
2958 +    public void testThenApplyAsync4() {
2959 +        CompletableFuture<Integer> f = new CompletableFuture<>();
2960 +        CompletableFuture<Integer> g = f.thenApplyAsync(inc);
2961 +        assertTrue(f.cancel(true));
2962 +        checkCompletedWithWrappedCancellationException(g);
2963 +    }
2964 +
2965 +    /**
2966 +     * thenAcceptAsync result completes normally after normal
2967 +     * completion of source
2968 +     */
2969 +    public void testThenAcceptAsync() {
2970 +        CompletableFuture<Integer> f = new CompletableFuture<>();
2971 +        IncAction r = new IncAction();
2972 +        CompletableFuture<Void> g = f.thenAcceptAsync(r);
2973 +        f.complete(one);
2974 +        checkCompletedNormally(g, null);
2975 +        assertEquals(r.value, (Integer) 2);
2976 +    }
2977 +
2978 +    /**
2979 +     * thenAcceptAsync result completes exceptionally after exceptional
2980 +     * completion of source
2981 +     */
2982 +    public void testThenAcceptAsync2() {
2983 +        CompletableFuture<Integer> f = new CompletableFuture<>();
2984 +        IncAction r = new IncAction();
2985 +        CompletableFuture<Void> g = f.thenAcceptAsync(r);
2986 +        f.completeExceptionally(new CFException());
2987 +        checkCompletedWithWrappedCFException(g);
2988 +    }
2989 +
2990 +    /**
2991 +     * thenAcceptAsync result completes exceptionally if action does
2992 +     */
2993 +    public void testThenAcceptAsync3() {
2994 +        CompletableFuture<Integer> f = new CompletableFuture<>();
2995 +        FailingConsumer r = new FailingConsumer();
2996 +        CompletableFuture<Void> g = f.thenAcceptAsync(r);
2997 +        f.complete(null);
2998 +        checkCompletedWithWrappedCFException(g);
2999 +    }
3000 +
3001 +    /**
3002 +     * thenAcceptAsync result completes exceptionally if source cancelled
3003 +     */
3004 +    public void testThenAcceptAsync4() {
3005 +        CompletableFuture<Integer> f = new CompletableFuture<>();
3006 +        IncAction r = new IncAction();
3007 +        CompletableFuture<Void> g = f.thenAcceptAsync(r);
3008 +        assertTrue(f.cancel(true));
3009 +        checkCompletedWithWrappedCancellationException(g);
3010 +    }
3011 +
3012 +    // async with explicit executors
3013 +
3014 +    /**
3015 +     * thenRunAsync result completes normally after normal completion of source
3016 +     */
3017 +    public void testThenRunAsyncE() {
3018 +        CompletableFuture<Integer> f = new CompletableFuture<>();
3019 +        Noop r = new Noop();
3020 +        CompletableFuture<Void> g = f.thenRunAsync(r, new ThreadExecutor());
3021 +        f.complete(null);
3022 +        checkCompletedNormally(g, null);
3023 +
3024 +        // reordered version
3025 +        f = new CompletableFuture<>();
3026 +        f.complete(null);
3027 +        r = new Noop();
3028 +        g = f.thenRunAsync(r, new ThreadExecutor());
3029 +        checkCompletedNormally(g, null);
3030 +    }
3031 +
3032 +    /**
3033 +     * thenRunAsync result completes exceptionally after exceptional
3034 +     * completion of source
3035 +     */
3036 +    public void testThenRunAsync2E() {
3037 +        CompletableFuture<Integer> f = new CompletableFuture<>();
3038 +        Noop r = new Noop();
3039 +        CompletableFuture<Void> g = f.thenRunAsync(r, new ThreadExecutor());
3040 +        f.completeExceptionally(new CFException());
3041 +        try {
3042 +            g.join();
3043 +            shouldThrow();
3044 +        } catch (CompletionException success) {}
3045 +        checkCompletedWithWrappedCFException(g);
3046 +    }
3047 +
3048 +    /**
3049 +     * thenRunAsync result completes exceptionally if action does
3050 +     */
3051 +    public void testThenRunAsync3E() {
3052 +        CompletableFuture<Integer> f = new CompletableFuture<>();
3053 +        FailingNoop r = new FailingNoop();
3054 +        CompletableFuture<Void> g = f.thenRunAsync(r, new ThreadExecutor());
3055 +        f.complete(null);
3056 +        checkCompletedWithWrappedCFException(g);
3057 +    }
3058 +
3059 +    /**
3060 +     * thenRunAsync result completes exceptionally if source cancelled
3061 +     */
3062 +    public void testThenRunAsync4E() {
3063 +        CompletableFuture<Integer> f = new CompletableFuture<>();
3064 +        Noop r = new Noop();
3065 +        CompletableFuture<Void> g = f.thenRunAsync(r, new ThreadExecutor());
3066 +        assertTrue(f.cancel(true));
3067 +        checkCompletedWithWrappedCancellationException(g);
3068 +    }
3069 +
3070 +    /**
3071 +     * thenApplyAsync result completes normally after normal completion of source
3072 +     */
3073 +    public void testThenApplyAsyncE() {
3074 +        CompletableFuture<Integer> f = new CompletableFuture<>();
3075 +        CompletableFuture<Integer> g = f.thenApplyAsync(inc, new ThreadExecutor());
3076 +        f.complete(one);
3077 +        checkCompletedNormally(g, two);
3078 +    }
3079 +
3080 +    /**
3081 +     * thenApplyAsync result completes exceptionally after exceptional
3082 +     * completion of source
3083 +     */
3084 +    public void testThenApplyAsync2E() {
3085 +        CompletableFuture<Integer> f = new CompletableFuture<>();
3086 +        CompletableFuture<Integer> g = f.thenApplyAsync(inc, new ThreadExecutor());
3087 +        f.completeExceptionally(new CFException());
3088 +        checkCompletedWithWrappedCFException(g);
3089 +    }
3090 +
3091 +    /**
3092 +     * thenApplyAsync result completes exceptionally if action does
3093 +     */
3094 +    public void testThenApplyAsync3E() {
3095 +        CompletableFuture<Integer> f = new CompletableFuture<>();
3096 +        FailingFunction r = new FailingFunction();
3097 +        CompletableFuture<Integer> g = f.thenApplyAsync(r, new ThreadExecutor());
3098 +        f.complete(null);
3099 +        checkCompletedWithWrappedCFException(g);
3100 +    }
3101 +
3102 +    /**
3103 +     * thenApplyAsync result completes exceptionally if source cancelled
3104 +     */
3105 +    public void testThenApplyAsync4E() {
3106 +        CompletableFuture<Integer> f = new CompletableFuture<>();
3107 +        CompletableFuture<Integer> g = f.thenApplyAsync(inc, new ThreadExecutor());
3108 +        assertTrue(f.cancel(true));
3109 +        checkCompletedWithWrappedCancellationException(g);
3110 +    }
3111 +
3112 +    /**
3113 +     * thenAcceptAsync result completes normally after normal
3114 +     * completion of source
3115 +     */
3116 +    public void testThenAcceptAsyncE() {
3117 +        CompletableFuture<Integer> f = new CompletableFuture<>();
3118 +        IncAction r = new IncAction();
3119 +        CompletableFuture<Void> g = f.thenAcceptAsync(r, new ThreadExecutor());
3120 +        f.complete(one);
3121 +        checkCompletedNormally(g, null);
3122 +        assertEquals(r.value, (Integer) 2);
3123 +    }
3124 +
3125 +    /**
3126 +     * thenAcceptAsync result completes exceptionally after exceptional
3127 +     * completion of source
3128 +     */
3129 +    public void testThenAcceptAsync2E() {
3130 +        CompletableFuture<Integer> f = new CompletableFuture<>();
3131 +        IncAction r = new IncAction();
3132 +        CompletableFuture<Void> g = f.thenAcceptAsync(r, new ThreadExecutor());
3133 +        f.completeExceptionally(new CFException());
3134 +        checkCompletedWithWrappedCFException(g);
3135 +    }
3136 +
3137 +    /**
3138 +     * thenAcceptAsync result completes exceptionally if action does
3139 +     */
3140 +    public void testThenAcceptAsync3E() {
3141 +        CompletableFuture<Integer> f = new CompletableFuture<>();
3142 +        FailingConsumer r = new FailingConsumer();
3143 +        CompletableFuture<Void> g = f.thenAcceptAsync(r, new ThreadExecutor());
3144 +        f.complete(null);
3145 +        checkCompletedWithWrappedCFException(g);
3146 +    }
3147 +
3148 +    /**
3149 +     * thenAcceptAsync result completes exceptionally if source cancelled
3150 +     */
3151 +    public void testThenAcceptAsync4E() {
3152 +        CompletableFuture<Integer> f = new CompletableFuture<>();
3153 +        IncAction r = new IncAction();
3154 +        CompletableFuture<Void> g = f.thenAcceptAsync(r, new ThreadExecutor());
3155 +        assertTrue(f.cancel(true));
3156 +        checkCompletedWithWrappedCancellationException(g);
3157 +    }
3158 +
3159 +    // other static methods
3160 +
3161 +    /**
3162 +     * allOf(no component futures) returns a future completed normally
3163 +     * with the value null
3164 +     */
3165 +    public void testAllOf_empty() throws Exception {
3166 +        CompletableFuture<Void> f = CompletableFuture.allOf();
3167 +        checkCompletedNormally(f, null);
3168 +    }
3169 +
3170 +    /**
3171 +     * allOf returns a future completed normally with the value null
3172 +     * when all components complete normally
3173 +     */
3174 +    public void testAllOf_normal() throws Exception {
3175 +        for (int k = 1; k < 20; ++k) {
3176 +            CompletableFuture<Integer>[] fs = (CompletableFuture<Integer>[]) new CompletableFuture[k];
3177 +            for (int i = 0; i < k; ++i)
3178 +                fs[i] = new CompletableFuture<>();
3179 +            CompletableFuture<Void> f = CompletableFuture.allOf(fs);
3180 +            for (int i = 0; i < k; ++i) {
3181 +                checkIncomplete(f);
3182 +                checkIncomplete(CompletableFuture.allOf(fs));
3183 +                fs[i].complete(one);
3184 +            }
3185 +            checkCompletedNormally(f, null);
3186 +            checkCompletedNormally(CompletableFuture.allOf(fs), null);
3187 +        }
3188 +    }
3189 +
3190 +    /**
3191 +     * anyOf(no component futures) returns an incomplete future
3192 +     */
3193 +    public void testAnyOf_empty() throws Exception {
3194 +        CompletableFuture<Object> f = CompletableFuture.anyOf();
3195 +        checkIncomplete(f);
3196 +    }
3197 +
3198 +    /**
3199 +     * anyOf returns a future completed normally with a value when
3200 +     * a component future does
3201 +     */
3202 +    public void testAnyOf_normal() throws Exception {
3203 +        for (int k = 0; k < 10; ++k) {
3204 +            CompletableFuture[] fs = new CompletableFuture[k];
3205 +            for (int i = 0; i < k; ++i)
3206 +                fs[i] = new CompletableFuture<>();
3207 +            CompletableFuture<Object> f = CompletableFuture.anyOf(fs);
3208 +            checkIncomplete(f);
3209 +            for (int i = 0; i < k; ++i) {
3210 +                fs[i].complete(one);
3211 +                checkCompletedNormally(f, one);
3212 +                checkCompletedNormally(CompletableFuture.anyOf(fs), one);
3213 +            }
3214 +        }
3215 +    }
3216 +
3217 +    /**
3218 +     * anyOf result completes exceptionally when any component does.
3219 +     */
3220 +    public void testAnyOf_exceptional() throws Exception {
3221 +        for (int k = 0; k < 10; ++k) {
3222 +            CompletableFuture[] fs = new CompletableFuture[k];
3223 +            for (int i = 0; i < k; ++i)
3224 +                fs[i] = new CompletableFuture<>();
3225 +            CompletableFuture<Object> f = CompletableFuture.anyOf(fs);
3226 +            checkIncomplete(f);
3227 +            for (int i = 0; i < k; ++i) {
3228 +                fs[i].completeExceptionally(new CFException());
3229 +                checkCompletedWithWrappedCFException(f);
3230 +                checkCompletedWithWrappedCFException(CompletableFuture.anyOf(fs));
3231 +            }
3232 +        }
3233 +    }
3234 +
3235 +    /**
3236 +     * Completion methods throw NullPointerException with null arguments
3237 +     */
3238 +    public void testNPE() {
3239 +        CompletableFuture<Integer> f = new CompletableFuture<>();
3240 +        CompletableFuture<Integer> g = new CompletableFuture<>();
3241 +        CompletableFuture<Integer> nullFuture = (CompletableFuture<Integer>)null;
3242 +        CompletableFuture<?> h;
3243 +        ThreadExecutor exec = new ThreadExecutor();
3244 +
3245 +        Runnable[] throwingActions = {
3246 +            () -> CompletableFuture.supplyAsync(null),
3247 +            () -> CompletableFuture.supplyAsync(null, exec),
3248 +            () -> CompletableFuture.supplyAsync(supplyOne, null),
3249 +
3250 +            () -> CompletableFuture.runAsync(null),
3251 +            () -> CompletableFuture.runAsync(null, exec),
3252 +            () -> CompletableFuture.runAsync(() -> {}, null),
3253 +
3254 +            () -> f.completeExceptionally(null),
3255 +
3256 +            () -> f.thenApply(null),
3257 +            () -> f.thenApplyAsync(null),
3258 +            () -> f.thenApplyAsync((x) -> x, null),
3259 +            () -> f.thenApplyAsync(null, exec),
3260 +
3261 +            () -> f.thenAccept(null),
3262 +            () -> f.thenAcceptAsync(null),
3263 +            () -> f.thenAcceptAsync((x) -> {} , null),
3264 +            () -> f.thenAcceptAsync(null, exec),
3265 +
3266 +            () -> f.thenRun(null),
3267 +            () -> f.thenRunAsync(null),
3268 +            () -> f.thenRunAsync(() -> {} , null),
3269 +            () -> f.thenRunAsync(null, exec),
3270 +
3271 +            () -> f.thenCombine(g, null),
3272 +            () -> f.thenCombineAsync(g, null),
3273 +            () -> f.thenCombineAsync(g, null, exec),
3274 +            () -> f.thenCombine(nullFuture, (x, y) -> x),
3275 +            () -> f.thenCombineAsync(nullFuture, (x, y) -> x),
3276 +            () -> f.thenCombineAsync(nullFuture, (x, y) -> x, exec),
3277 +            () -> f.thenCombineAsync(g, (x, y) -> x, null),
3278 +
3279 +            () -> f.thenAcceptBoth(g, null),
3280 +            () -> f.thenAcceptBothAsync(g, null),
3281 +            () -> f.thenAcceptBothAsync(g, null, exec),
3282 +            () -> f.thenAcceptBoth(nullFuture, (x, y) -> {}),
3283 +            () -> f.thenAcceptBothAsync(nullFuture, (x, y) -> {}),
3284 +            () -> f.thenAcceptBothAsync(nullFuture, (x, y) -> {}, exec),
3285 +            () -> f.thenAcceptBothAsync(g, (x, y) -> {}, null),
3286 +
3287 +            () -> f.runAfterBoth(g, null),
3288 +            () -> f.runAfterBothAsync(g, null),
3289 +            () -> f.runAfterBothAsync(g, null, exec),
3290 +            () -> f.runAfterBoth(nullFuture, () -> {}),
3291 +            () -> f.runAfterBothAsync(nullFuture, () -> {}),
3292 +            () -> f.runAfterBothAsync(nullFuture, () -> {}, exec),
3293 +            () -> f.runAfterBothAsync(g, () -> {}, null),
3294 +
3295 +            () -> f.applyToEither(g, null),
3296 +            () -> f.applyToEitherAsync(g, null),
3297 +            () -> f.applyToEitherAsync(g, null, exec),
3298 +            () -> f.applyToEither(nullFuture, (x) -> x),
3299 +            () -> f.applyToEitherAsync(nullFuture, (x) -> x),
3300 +            () -> f.applyToEitherAsync(nullFuture, (x) -> x, exec),
3301 +            () -> f.applyToEitherAsync(g, (x) -> x, null),
3302 +
3303 +            () -> f.acceptEither(g, null),
3304 +            () -> f.acceptEitherAsync(g, null),
3305 +            () -> f.acceptEitherAsync(g, null, exec),
3306 +            () -> f.acceptEither(nullFuture, (x) -> {}),
3307 +            () -> f.acceptEitherAsync(nullFuture, (x) -> {}),
3308 +            () -> f.acceptEitherAsync(nullFuture, (x) -> {}, exec),
3309 +            () -> f.acceptEitherAsync(g, (x) -> {}, null),
3310 +
3311 +            () -> f.runAfterEither(g, null),
3312 +            () -> f.runAfterEitherAsync(g, null),
3313 +            () -> f.runAfterEitherAsync(g, null, exec),
3314 +            () -> f.runAfterEither(nullFuture, () -> {}),
3315 +            () -> f.runAfterEitherAsync(nullFuture, () -> {}),
3316 +            () -> f.runAfterEitherAsync(nullFuture, () -> {}, exec),
3317 +            () -> f.runAfterEitherAsync(g, () -> {}, null),
3318 +
3319 +            () -> f.thenCompose(null),
3320 +            () -> f.thenComposeAsync(null),
3321 +            () -> f.thenComposeAsync(new CompletableFutureInc(), null),
3322 +            () -> f.thenComposeAsync(null, exec),
3323 +
3324 +            () -> f.exceptionally(null),
3325 +
3326 +            () -> f.handle(null),
3327 +
3328 +            () -> CompletableFuture.allOf((CompletableFuture<?>)null),
3329 +            () -> CompletableFuture.allOf((CompletableFuture<?>[])null),
3330 +            () -> CompletableFuture.allOf(f, null),
3331 +            () -> CompletableFuture.allOf(null, f),
3332 +
3333 +            () -> CompletableFuture.anyOf((CompletableFuture<?>)null),
3334 +            () -> CompletableFuture.anyOf((CompletableFuture<?>[])null),
3335 +            () -> CompletableFuture.anyOf(f, null),
3336 +            () -> CompletableFuture.anyOf(null, f),
3337 +
3338 +            () -> f.obtrudeException(null),
3339 +        };
3340 +
3341 +        assertThrows(NullPointerException.class, throwingActions);
3342 +        assertEquals(0, exec.count.get());
3343 +    }
3344 +
3345 +    /**
3346 +     * toCompletableFuture returns this CompletableFuture.
3347 +     */
3348 +    public void testToCompletableFuture() {
3349 +        CompletableFuture<Integer> f = new CompletableFuture<>();
3350 +        assertSame(f, f.toCompletableFuture());
3351 +    }
3352 +
3353 +    /**
3354 +     * whenComplete action executes on normal completion, propagating
3355 +     * source result.
3356 +     */
3357 +    public void testWhenComplete_normalCompletion1() {
3358 +        for (boolean createIncomplete : new boolean[] { true, false })
3359 +        for (ExecutionMode m : ExecutionMode.values())
3360 +        for (Integer v1 : new Integer[] { 1, null }) {
3361 +
3362 +        final AtomicInteger a = new AtomicInteger();
3363 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
3364 +        if (!createIncomplete) f.complete(v1);
3365 +        final CompletableFuture<Integer> g =
3366 +            m.whenComplete(f,
3367 +                           (Integer x, Throwable t) -> {
3368 +                               threadAssertSame(x, v1);
3369 +                               threadAssertNull(t);
3370 +                               a.getAndIncrement();
3371 +                           });
3372 +        if (createIncomplete) f.complete(v1);
3373 +        checkCompletedNormally(f, v1);
3374 +        checkCompletedNormally(g, v1);
3375 +        assertEquals(a.get(), 1);
3376 +        }
3377 +    }
3378 +
3379 +    /**
3380 +     * whenComplete action executes on exceptional completion, propagating
3381 +     * source result.
3382 +     */
3383 +    public void testWhenComplete_exceptionalCompletion() {
3384 +        for (boolean createIncomplete : new boolean[] { true, false })
3385 +        for (ExecutionMode m : ExecutionMode.values())
3386 +        for (Integer v1 : new Integer[] { 1, null }) {
3387 +
3388 +        final AtomicInteger a = new AtomicInteger();
3389 +        final CFException ex = new CFException();
3390 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
3391 +        if (!createIncomplete) f.completeExceptionally(ex);
3392 +        final CompletableFuture<Integer> g = m.whenComplete
3393 +            (f,
3394 +             (Integer x, Throwable t) -> {
3395 +                threadAssertNull(x);
3396 +                threadAssertSame(t, ex);
3397 +                a.getAndIncrement();
3398 +            });
3399 +        if (createIncomplete) f.completeExceptionally(ex);
3400 +        checkCompletedWithWrappedCFException(f, ex);
3401 +        checkCompletedWithWrappedCFException(g, ex);
3402 +        assertEquals(a.get(), 1);
3403 +        }
3404 +    }
3405 +
3406 +    /**
3407 +     * If a whenComplete action throws an exception when triggered by
3408 +     * a normal completion, it completes exceptionally
3409 +     */
3410 +    public void testWhenComplete_actionFailed() {
3411 +        for (boolean createIncomplete : new boolean[] { true, false })
3412 +        for (ExecutionMode m : ExecutionMode.values())
3413 +        for (Integer v1 : new Integer[] { 1, null }) {
3414 +
3415 +        final CFException ex = new CFException();
3416 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
3417 +        if (!createIncomplete) f.complete(v1);
3418 +        final CompletableFuture<Integer> g = m.whenComplete
3419 +            (f,
3420 +             (Integer x, Throwable t) -> {
3421 +                threadAssertSame(x, v1);
3422 +                threadAssertNull(t);
3423 +                throw ex;
3424 +            });
3425 +        if (createIncomplete) f.complete(v1);
3426 +        checkCompletedNormally(f, v1);
3427 +        checkCompletedWithWrappedCFException(g, ex);
3428 +        }
3429 +    }
3430 +
3431 +    /**
3432 +     * If a whenComplete action throws an exception when triggered by
3433 +     * a source completion that also throws an exception, the source
3434 +     * exception takes precedence.
3435 +     */
3436 +    public void testWhenComplete_actionFailedSourceFailed() {
3437 +        for (boolean createIncomplete : new boolean[] { true, false })
3438 +        for (ExecutionMode m : ExecutionMode.values())
3439 +        for (Integer v1 : new Integer[] { 1, null }) {
3440 +
3441 +        final CFException ex1 = new CFException();
3442 +        final CFException ex2 = new CFException();
3443 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
3444 +
3445 +        if (!createIncomplete) f.completeExceptionally(ex1);
3446 +        final CompletableFuture<Integer> g = m.whenComplete
3447 +            (f,
3448 +             (Integer x, Throwable t) -> {
3449 +                threadAssertSame(t, ex1);
3450 +                threadAssertNull(x);
3451 +                throw ex2;
3452 +            });
3453 +        if (createIncomplete) f.completeExceptionally(ex1);
3454 +
3455 +        checkCompletedWithWrappedCFException(f, ex1);
3456 +        checkCompletedWithWrappedCFException(g, ex1);
3457 +        }
3458 +    }
3459 +
3460 +    /**
3461 +     * handleAsync action completes normally with function value on
3462 +     * either normal or exceptional completion of source
3463 +     */
3464 +    public void testHandleAsync() {
3465 +        CompletableFuture<Integer> f, g;
3466 +        IntegerHandler r;
3467 +
3468 +        f = new CompletableFuture<>();
3469 +        g = f.handleAsync(r = new IntegerHandler());
3470 +        assertEquals(0, r.invocationCount);
3471 +        f.completeExceptionally(new CFException());
3472 +        checkCompletedWithWrappedCFException(f);
3473 +        checkCompletedNormally(g, three);
3474 +        assertEquals(1, r.invocationCount);
3475 +
3476 +        f = new CompletableFuture<>();
3477 +        g = f.handleAsync(r = new IntegerHandler());
3478 +        assertEquals(0, r.invocationCount);
3479 +        f.completeExceptionally(new CFException());
3480 +        checkCompletedWithWrappedCFException(f);
3481 +        checkCompletedNormally(g, three);
3482 +        assertEquals(1, r.invocationCount);
3483 +
3484 +        f = new CompletableFuture<>();
3485 +        g = f.handleAsync(r = new IntegerHandler());
3486 +        assertEquals(0, r.invocationCount);
3487 +        f.complete(one);
3488 +        checkCompletedNormally(f, one);
3489 +        checkCompletedNormally(g, two);
3490 +        assertEquals(1, r.invocationCount);
3491 +
3492 +        f = new CompletableFuture<>();
3493 +        g = f.handleAsync(r = new IntegerHandler());
3494 +        assertEquals(0, r.invocationCount);
3495 +        f.complete(one);
3496 +        checkCompletedNormally(f, one);
3497 +        checkCompletedNormally(g, two);
3498 +        assertEquals(1, r.invocationCount);
3499 +    }
3500 +
3501 +    /**
3502 +     * handleAsync action with Executor completes normally with
3503 +     * function value on either normal or exceptional completion of
3504 +     * source
3505 +     */
3506 +    public void testHandleAsync2() {
3507 +        CompletableFuture<Integer> f, g;
3508 +        ThreadExecutor exec = new ThreadExecutor();
3509 +        IntegerHandler r;
3510 +
3511 +        f = new CompletableFuture<>();
3512 +        g = f.handleAsync(r = new IntegerHandler(), exec);
3513 +        assertEquals(0, r.invocationCount);
3514 +        f.completeExceptionally(new CFException());
3515 +        checkCompletedWithWrappedCFException(f);
3516 +        checkCompletedNormally(g, three);
3517 +        assertEquals(1, r.invocationCount);
3518 +
3519 +        f = new CompletableFuture<>();
3520 +        g = f.handleAsync(r = new IntegerHandler(), exec);
3521 +        assertEquals(0, r.invocationCount);
3522 +        f.completeExceptionally(new CFException());
3523 +        checkCompletedWithWrappedCFException(f);
3524 +        checkCompletedNormally(g, three);
3525 +        assertEquals(1, r.invocationCount);
3526 +
3527 +        f = new CompletableFuture<>();
3528 +        g = f.handleAsync(r = new IntegerHandler(), exec);
3529 +        assertEquals(0, r.invocationCount);
3530 +        f.complete(one);
3531 +        checkCompletedNormally(f, one);
3532 +        checkCompletedNormally(g, two);
3533 +        assertEquals(1, r.invocationCount);
3534 +
3535 +        f = new CompletableFuture<>();
3536 +        g = f.handleAsync(r = new IntegerHandler(), exec);
3537 +        assertEquals(0, r.invocationCount);
3538 +        f.complete(one);
3539 +        checkCompletedNormally(f, one);
3540 +        checkCompletedNormally(g, two);
3541 +        assertEquals(1, r.invocationCount);
3542 +    }
3543 +
3544   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines