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.33 by jsr166, Sun Jun 1 20:40:13 2014 UTC vs.
Revision 1.43 by jsr166, Mon Jun 2 04:13:54 2014 UTC

# Line 16 | Line 16 | import java.util.concurrent.ExecutionExc
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;
# Line 317 | Line 318 | public class CompletableFutureTest exten
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) -> Integer.valueOf(x.intValue() - y.intValue());
338 >        (Integer x, Integer y) -> subtract(x, y);
339      static final class IncAction implements Consumer<Integer> {
340 <        int value;
341 <        public void accept(Integer x) { value = x.intValue() + 1; }
340 >        int invocationCount = 0;
341 >        Integer value;
342 >        public boolean ran() { return invocationCount == 1; }
343 >        public void accept(Integer x) {
344 >            invocationCount++;
345 >            value = inc(x);
346 >        }
347 >    }
348 >    static final class IncFunction implements Function<Integer,Integer> {
349 >        int invocationCount = 0;
350 >        Integer value;
351 >        public boolean ran() { return invocationCount == 1; }
352 >        public Integer apply(Integer x) {
353 >            invocationCount++;
354 >            return value = inc(x);
355 >        }
356      }
357      static final class SubtractAction implements BiConsumer<Integer, Integer> {
358 <        int value;
358 >        int invocationCount = 0;
359 >        Integer value;
360 >        // Check this action was invoked exactly once when result is computed.
361 >        public boolean ran() { return invocationCount == 1; }
362          public void accept(Integer x, Integer y) {
363 <            value = x.intValue() - y.intValue();
363 >            invocationCount++;
364 >            value = subtract(x, y);
365 >        }
366 >    }
367 >    static final class SubtractFunction implements BiFunction<Integer, Integer, Integer> {
368 >        int invocationCount = 0;
369 >        Integer value;
370 >        // Check this action was invoked exactly once when result is computed.
371 >        public boolean ran() { return invocationCount == 1; }
372 >        public Integer apply(Integer x, Integer y) {
373 >            invocationCount++;
374 >            return value = subtract(x, y);
375          }
376      }
377      static final class Noop implements Runnable {
378 +        int invocationCount = 0;
379          boolean ran;
380 <        public void run() { ran = true; }
380 >        public void run() {
381 >            invocationCount++;
382 >            ran = true;
383 >        }
384      }
385  
386      static final class FailingSupplier implements Supplier<Integer> {
# Line 405 | Line 450 | public class CompletableFutureTest exten
450      }
451  
452      /**
453 +     * Permits the testing of parallel code for the 3 different
454 +     * execution modes without repeating all the testing code.
455 +     */
456 +    enum ExecutionMode {
457 +        DEFAULT {
458 +            public <T,U> CompletableFuture<Void> runAfterBoth
459 +                (CompletableFuture<T> f, CompletableFuture<U> g, Runnable a) {
460 +                return f.runAfterBoth(g, a);
461 +            }
462 +            public <T,U> CompletableFuture<Void> thenAcceptBoth
463 +                (CompletableFuture<T> f,
464 +                 CompletionStage<? extends U> g,
465 +                 BiConsumer<? super T,? super U> a) {
466 +                return f.thenAcceptBoth(g, a);
467 +            }
468 +            public <T,U,V> CompletableFuture<V> thenCombine
469 +                (CompletableFuture<T> f,
470 +                 CompletionStage<? extends U> g,
471 +                 BiFunction<? super T,? super U,? extends V> a) {
472 +                return f.thenCombine(g, a);
473 +            }
474 +            public <T,U> CompletableFuture<U> applyToEither
475 +                (CompletableFuture<T> f,
476 +                 CompletionStage<? extends T> g,
477 +                 Function<? super T,U> a) {
478 +                return f.applyToEither(g, a);
479 +            }
480 +            public <T> CompletableFuture<Void> acceptEither
481 +                (CompletableFuture<T> f,
482 +                 CompletionStage<? extends T> g,
483 +                 Consumer<? super T> a) {
484 +                return f.acceptEither(g, a);
485 +            }
486 +            public <T> CompletableFuture<Void> runAfterEither
487 +                (CompletableFuture<T> f,
488 +                 CompletionStage<?> g,
489 +                 java.lang.Runnable a) {
490 +                return f.runAfterEither(g, a);
491 +            }
492 +            public <T,U> CompletableFuture<U> thenCompose
493 +                (CompletableFuture<T> f,
494 +                 Function<? super T,? extends CompletionStage<U>> a) {
495 +                return f.thenCompose(a);
496 +            }
497 +            public <T> CompletableFuture<T> whenComplete
498 +                (CompletableFuture<T> f,
499 +                 BiConsumer<? super T,? super Throwable> a) {
500 +                return f.whenComplete(a);
501 +            }
502 +        },
503 +
504 + //             /** Experimental way to do more testing */
505 + //         REVERSE_DEFAULT {
506 + //             public <T,U> CompletableFuture<Void> runAfterBoth
507 + //                 (CompletableFuture<T> f, CompletableFuture<U> g, Runnable a) {
508 + //                 return g.runAfterBoth(f, a);
509 + //             }
510 + //             public <T,U> CompletableFuture<Void> thenAcceptBoth
511 + //                 (CompletableFuture<T> f,
512 + //                  CompletionStage<? extends U> g,
513 + //                  BiConsumer<? super T,? super U> a) {
514 + //                 return DEFAULT.thenAcceptBoth(f, g, a);
515 + //             }
516 + //         },
517 +
518 +        DEFAULT_ASYNC {
519 +            public <T,U> CompletableFuture<Void> runAfterBoth
520 +                (CompletableFuture<T> f, CompletableFuture<U> g, Runnable a) {
521 +                return f.runAfterBothAsync(g, 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 f.thenAcceptBothAsync(g, a);
528 +            }
529 +            public <T,U,V> CompletableFuture<V> thenCombine
530 +                (CompletableFuture<T> f,
531 +                 CompletionStage<? extends U> g,
532 +                 BiFunction<? super T,? super U,? extends V> a) {
533 +                return f.thenCombineAsync(g, a);
534 +            }
535 +            public <T,U> CompletableFuture<U> applyToEither
536 +                (CompletableFuture<T> f,
537 +                 CompletionStage<? extends T> g,
538 +                 Function<? super T,U> a) {
539 +                return f.applyToEitherAsync(g, a);
540 +            }
541 +            public <T> CompletableFuture<Void> acceptEither
542 +                (CompletableFuture<T> f,
543 +                 CompletionStage<? extends T> g,
544 +                 Consumer<? super T> a) {
545 +                return f.acceptEitherAsync(g, a);
546 +            }
547 +            public <T> CompletableFuture<Void> runAfterEither
548 +                (CompletableFuture<T> f,
549 +                 CompletionStage<?> g,
550 +                 java.lang.Runnable a) {
551 +                return f.runAfterEitherAsync(g, a);
552 +            }
553 +            public <T,U> CompletableFuture<U> thenCompose
554 +                (CompletableFuture<T> f,
555 +                 Function<? super T,? extends CompletionStage<U>> a) {
556 +                return f.thenComposeAsync(a);
557 +            }
558 +            public <T> CompletableFuture<T> whenComplete
559 +                (CompletableFuture<T> f,
560 +                 BiConsumer<? super T,? super Throwable> a) {
561 +                return f.whenCompleteAsync(a);
562 +            }
563 +        },
564 +
565 + //         REVERSE_DEFAULT_ASYNC {
566 + //             public <T,U> CompletableFuture<Void> runAfterBoth
567 + //                 (CompletableFuture<T> f, CompletableFuture<U> g, Runnable a) {
568 + //                 return f.runAfterBothAsync(g, a);
569 + //             }
570 + //             public <T,U> CompletableFuture<Void> thenAcceptBoth
571 + //                 (CompletableFuture<T> f,
572 + //                  CompletionStage<? extends U> g,
573 + //                  BiConsumer<? super T,? super U> a) {
574 + //                 return DEFAULT_ASYNC.thenAcceptBoth(f, g, a);
575 + //             }
576 + //         },
577 +
578 +        EXECUTOR {
579 +            public <T,U> CompletableFuture<Void> runAfterBoth
580 +                (CompletableFuture<T> f, CompletableFuture<U> g, Runnable a) {
581 +                return f.runAfterBothAsync(g, a, new ThreadExecutor());
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 f.thenAcceptBothAsync(g, a, new ThreadExecutor());
588 +            }
589 +            public <T,U,V> CompletableFuture<V> thenCombine
590 +                (CompletableFuture<T> f,
591 +                 CompletionStage<? extends U> g,
592 +                 BiFunction<? super T,? super U,? extends V> a) {
593 +                return f.thenCombineAsync(g, a, new ThreadExecutor());
594 +            }
595 +            public <T,U> CompletableFuture<U> applyToEither
596 +                (CompletableFuture<T> f,
597 +                 CompletionStage<? extends T> g,
598 +                 Function<? super T,U> a) {
599 +                return f.applyToEitherAsync(g, a, new ThreadExecutor());
600 +            }
601 +            public <T> CompletableFuture<Void> acceptEither
602 +                (CompletableFuture<T> f,
603 +                 CompletionStage<? extends T> g,
604 +                 Consumer<? super T> a) {
605 +                return f.acceptEitherAsync(g, a, new ThreadExecutor());
606 +            }
607 +            public <T> CompletableFuture<Void> runAfterEither
608 +                (CompletableFuture<T> f,
609 +                 CompletionStage<?> g,
610 +                 java.lang.Runnable a) {
611 +                return f.runAfterEitherAsync(g, a, new ThreadExecutor());
612 +            }
613 +            public <T,U> CompletableFuture<U> thenCompose
614 +                (CompletableFuture<T> f,
615 +                 Function<? super T,? extends CompletionStage<U>> a) {
616 +                return f.thenComposeAsync(a, new ThreadExecutor());
617 +            }
618 +            public <T> CompletableFuture<T> whenComplete
619 +                (CompletableFuture<T> f,
620 +                 BiConsumer<? super T,? super Throwable> a) {
621 +                return f.whenCompleteAsync(a, new ThreadExecutor());
622 +            }
623 +        };
624 +
625 +        public abstract <T,U> CompletableFuture<Void> runAfterBoth
626 +            (CompletableFuture<T> f, CompletableFuture<U> g, Runnable a);
627 +        public abstract <T,U> CompletableFuture<Void> thenAcceptBoth
628 +            (CompletableFuture<T> f,
629 +             CompletionStage<? extends U> g,
630 +             BiConsumer<? super T,? super U> a);
631 +        public abstract <T,U,V> CompletableFuture<V> thenCombine
632 +            (CompletableFuture<T> f,
633 +             CompletionStage<? extends U> g,
634 +             BiFunction<? super T,? super U,? extends V> a);
635 +        public abstract <T,U> CompletableFuture<U> applyToEither
636 +            (CompletableFuture<T> f,
637 +             CompletionStage<? extends T> g,
638 +             Function<? super T,U> a);
639 +        public abstract <T> CompletableFuture<Void> acceptEither
640 +            (CompletableFuture<T> f,
641 +             CompletionStage<? extends T> g,
642 +             Consumer<? super T> a);
643 +        public abstract <T> CompletableFuture<Void> runAfterEither
644 +            (CompletableFuture<T> f,
645 +             CompletionStage<?> g,
646 +             java.lang.Runnable a);
647 +        public abstract <T,U> CompletableFuture<U> thenCompose
648 +            (CompletableFuture<T> f,
649 +             Function<? super T,? extends CompletionStage<U>> a);
650 +        public abstract <T> CompletableFuture<T> whenComplete
651 +            (CompletableFuture<T> f,
652 +             BiConsumer<? super T,? super Throwable> a);
653 +
654 +
655 +    }
656 +
657 +    /**
658       * exceptionally action completes with function value on source
659       * exception; otherwise with source value
660       */
# Line 654 | Line 904 | public class CompletableFutureTest exten
904          CompletableFuture<Void> g = f.thenAccept(r);
905          f.complete(one);
906          checkCompletedNormally(g, null);
907 <        assertEquals(r.value, 2);
907 >        assertEquals(r.value, (Integer) 2);
908      }
909  
910      /**
# Line 696 | Line 946 | public class CompletableFutureTest exten
946       * thenCombine result completes normally after normal completion
947       * of sources
948       */
949 <    public void testThenCombine() {
950 <        CompletableFuture<Integer> f, g, h;
951 <
952 <        f = new CompletableFuture<>();
953 <        g = new CompletableFuture<>();
954 <        h = f.thenCombine(g, subtract);
705 <        f.complete(3);
706 <        checkIncomplete(h);
707 <        g.complete(1);
708 <        checkCompletedNormally(h, 2);
949 >    public void testThenCombine_normalCompletion1() {
950 >        for (boolean createdIncomplete : new boolean[] { true, false })
951 >        for (boolean fFirst : new boolean[] { true, false })
952 >        for (ExecutionMode m : ExecutionMode.values())
953 >        for (Integer v1 : new Integer[] { 1, null })
954 >        for (Integer v2 : new Integer[] { 2, null }) {
955  
956 <        f = new CompletableFuture<>();
957 <        g = new CompletableFuture<>();
958 <        h = f.thenCombine(g, subtract);
959 <        g.complete(1);
960 <        checkIncomplete(h);
961 <        f.complete(3);
962 <        checkCompletedNormally(h, 2);
956 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
957 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
958 >        final SubtractFunction r = new SubtractFunction();
959 >        CompletableFuture<Integer> h = null;
960 >        if (createdIncomplete) h = m.thenCombine(f, g, r);
961 >
962 >        if (fFirst)
963 >            f.complete(v1);
964 >        else
965 >            g.complete(v2);
966 >        if (createdIncomplete) checkIncomplete(h);
967 >        assertEquals(r.invocationCount, 0);
968 >        if (!fFirst)
969 >            f.complete(v1);
970 >        else
971 >            g.complete(v2);
972 >        if (!createdIncomplete) h = m.thenCombine(f, g, r);
973  
974 <        f = new CompletableFuture<>();
975 <        g = new CompletableFuture<>();
976 <        g.complete(1);
977 <        f.complete(3);
978 <        h = f.thenCombine(g, subtract);
723 <        checkCompletedNormally(h, 2);
974 >        checkCompletedNormally(h, subtract(v1, v2));
975 >        checkCompletedNormally(f, v1);
976 >        checkCompletedNormally(g, v2);
977 >        assertEquals(r.invocationCount, 1);
978 >        }
979      }
980  
981      /**
982       * thenCombine result completes exceptionally after exceptional
983       * completion of either source
984       */
985 <    public void testThenCombine2() {
986 <        CompletableFuture<Integer> f, g, h;
985 >    public void testThenCombine_exceptionalCompletion1() {
986 >        for (ExecutionMode m : ExecutionMode.values())
987 >        for (Integer v1 : new Integer[] { 1, null }) {
988  
989 <        f = new CompletableFuture<>();
990 <        g = new CompletableFuture<>();
991 <        h = f.thenCombine(g, subtract);
992 <        f.completeExceptionally(new CFException());
989 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
990 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
991 >        final SubtractFunction r = new SubtractFunction();
992 >        final CompletableFuture<Integer> h = m.thenCombine(f, g, r);
993 >        final CFException ex = new CFException();
994 >
995 >        f.completeExceptionally(ex);
996          checkIncomplete(h);
997 <        g.complete(1);
739 <        checkCompletedWithWrappedCFException(h);
997 >        g.complete(v1);
998  
999 <        f = new CompletableFuture<>();
1000 <        g = new CompletableFuture<>();
1001 <        h = f.thenCombine(g, subtract);
1002 <        g.completeExceptionally(new CFException());
999 >        checkCompletedWithWrappedCFException(h, ex);
1000 >        checkCompletedWithWrappedCFException(f, ex);
1001 >        assertEquals(r.invocationCount, 0);
1002 >        checkCompletedNormally(g, v1);
1003 >        }
1004 >    }
1005 >
1006 >    public void testThenCombine_exceptionalCompletion2() {
1007 >        for (ExecutionMode m : ExecutionMode.values())
1008 >        for (Integer v1 : new Integer[] { 1, null }) {
1009 >
1010 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
1011 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
1012 >        final SubtractFunction r = new SubtractFunction();
1013 >        final CompletableFuture<Integer> h = m.thenCombine(f, g, r);
1014 >        final CFException ex = new CFException();
1015 >
1016 >        g.completeExceptionally(ex);
1017          checkIncomplete(h);
1018 <        f.complete(3);
747 <        checkCompletedWithWrappedCFException(h);
1018 >        f.complete(v1);
1019  
1020 <        f = new CompletableFuture<>();
1021 <        g = new CompletableFuture<>();
1022 <        f.complete(3);
1023 <        g.completeExceptionally(new CFException());
1024 <        h = f.thenCombine(g, subtract);
1025 <        checkCompletedWithWrappedCFException(h);
1020 >        checkCompletedWithWrappedCFException(h, ex);
1021 >        checkCompletedWithWrappedCFException(g, ex);
1022 >        assertEquals(r.invocationCount, 0);
1023 >        checkCompletedNormally(f, v1);
1024 >        }
1025 >    }
1026  
1027 <        f = new CompletableFuture<>();
1028 <        g = new CompletableFuture<>();
1029 <        f.completeExceptionally(new CFException());
1030 <        g.complete(3);
1031 <        h = f.thenCombine(g, subtract);
1032 <        checkCompletedWithWrappedCFException(h);
1027 >    public void testThenCombine_exceptionalCompletion3() {
1028 >        for (ExecutionMode m : ExecutionMode.values())
1029 >        for (Integer v1 : new Integer[] { 1, null }) {
1030 >
1031 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
1032 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
1033 >        final SubtractFunction r = new SubtractFunction();
1034 >        final CFException ex = new CFException();
1035 >
1036 >        g.completeExceptionally(ex);
1037 >        f.complete(v1);
1038 >        final CompletableFuture<Integer> h = m.thenCombine(f, g, r);
1039 >
1040 >        checkCompletedWithWrappedCFException(h, ex);
1041 >        checkCompletedWithWrappedCFException(g, ex);
1042 >        assertEquals(r.invocationCount, 0);
1043 >        checkCompletedNormally(f, v1);
1044 >        }
1045 >    }
1046 >
1047 >    public void testThenCombine_exceptionalCompletion4() {
1048 >        for (ExecutionMode m : ExecutionMode.values())
1049 >        for (Integer v1 : new Integer[] { 1, null }) {
1050 >
1051 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
1052 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
1053 >        final SubtractFunction r = new SubtractFunction();
1054 >        final CFException ex = new CFException();
1055 >
1056 >        f.completeExceptionally(ex);
1057 >        g.complete(v1);
1058 >        final CompletableFuture<Integer> h = m.thenCombine(f, g, r);
1059 >
1060 >        checkCompletedWithWrappedCFException(h, ex);
1061 >        checkCompletedWithWrappedCFException(f, ex);
1062 >        assertEquals(r.invocationCount, 0);
1063 >        checkCompletedNormally(g, v1);
1064 >        }
1065      }
1066  
1067      /**
1068       * thenCombine result completes exceptionally if action does
1069       */
1070 <    public void testThenCombine3() {
1071 <        CompletableFuture<Integer> f = new CompletableFuture<>();
1072 <        CompletableFuture<Integer> f2 = new CompletableFuture<>();
1073 <        FailingBiFunction r = new FailingBiFunction();
1074 <        CompletableFuture<Integer> g = f.thenCombine(f2, r);
1075 <        f.complete(one);
1076 <        checkIncomplete(g);
1077 <        assertFalse(r.ran);
1078 <        f2.complete(two);
1079 <        checkCompletedWithWrappedCFException(g);
1080 <        assertTrue(r.ran);
1070 >    public void testThenCombine_actionFailed1() {
1071 >        for (ExecutionMode m : ExecutionMode.values())
1072 >        for (Integer v1 : new Integer[] { 1, null })
1073 >        for (Integer v2 : new Integer[] { 2, null }) {
1074 >
1075 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
1076 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
1077 >        final FailingBiFunction r = new FailingBiFunction();
1078 >        final CompletableFuture<Integer> h = m.thenCombine(f, g, r);
1079 >
1080 >        f.complete(v1);
1081 >        checkIncomplete(h);
1082 >        g.complete(v2);
1083 >
1084 >        checkCompletedWithWrappedCFException(h);
1085 >        checkCompletedNormally(f, v1);
1086 >        checkCompletedNormally(g, v2);
1087 >        }
1088 >    }
1089 >
1090 >    public void testThenCombine_actionFailed2() {
1091 >        for (ExecutionMode m : ExecutionMode.values())
1092 >        for (Integer v1 : new Integer[] { 1, null })
1093 >        for (Integer v2 : new Integer[] { 2, null }) {
1094 >
1095 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
1096 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
1097 >        final FailingBiFunction r = new FailingBiFunction();
1098 >        final CompletableFuture<Integer> h = m.thenCombine(f, g, r);
1099 >
1100 >        g.complete(v2);
1101 >        checkIncomplete(h);
1102 >        f.complete(v1);
1103 >
1104 >        checkCompletedWithWrappedCFException(h);
1105 >        checkCompletedNormally(f, v1);
1106 >        checkCompletedNormally(g, v2);
1107 >        }
1108      }
1109  
1110      /**
1111       * thenCombine result completes exceptionally if either source cancelled
1112       */
1113 <    public void testThenCombine4() {
1114 <        CompletableFuture<Integer> f, g, h;
1113 >    public void testThenCombine_sourceCancelled1() {
1114 >        for (ExecutionMode m : ExecutionMode.values())
1115 >        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
1116 >        for (Integer v1 : new Integer[] { 1, null }) {
1117  
1118 <        f = new CompletableFuture<>();
1119 <        g = new CompletableFuture<>();
1120 <        h = f.thenCombine(g, subtract);
1121 <        assertTrue(f.cancel(true));
1118 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
1119 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
1120 >        final SubtractFunction r = new SubtractFunction();
1121 >        final CompletableFuture<Integer> h = m.thenCombine(f, g, r);
1122 >
1123 >        assertTrue(f.cancel(mayInterruptIfRunning));
1124          checkIncomplete(h);
1125 <        g.complete(1);
1125 >        g.complete(v1);
1126 >
1127          checkCompletedWithWrappedCancellationException(h);
1128 +        checkCancelled(f);
1129 +        assertEquals(r.invocationCount, 0);
1130 +        checkCompletedNormally(g, v1);
1131 +        }
1132 +    }
1133  
1134 <        f = new CompletableFuture<>();
1135 <        g = new CompletableFuture<>();
1136 <        h = f.thenCombine(g, subtract);
1137 <        assertTrue(g.cancel(true));
1134 >    public void testThenCombine_sourceCancelled2() {
1135 >        for (ExecutionMode m : ExecutionMode.values())
1136 >        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
1137 >        for (Integer v1 : new Integer[] { 1, null }) {
1138 >
1139 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
1140 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
1141 >        final SubtractFunction r = new SubtractFunction();
1142 >        final CompletableFuture<Integer> h = m.thenCombine(f, g, r);
1143 >
1144 >        assertTrue(g.cancel(mayInterruptIfRunning));
1145          checkIncomplete(h);
1146 <        f.complete(3);
1146 >        f.complete(v1);
1147 >
1148          checkCompletedWithWrappedCancellationException(h);
1149 +        checkCancelled(g);
1150 +        assertEquals(r.invocationCount, 0);
1151 +        checkCompletedNormally(f, v1);
1152 +        }
1153 +    }
1154 +
1155 +    public void testThenCombine_sourceCancelled3() {
1156 +        for (ExecutionMode m : ExecutionMode.values())
1157 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
1158 +        for (Integer v1 : new Integer[] { 1, null }) {
1159 +
1160 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1161 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1162 +        final SubtractFunction r = new SubtractFunction();
1163 +
1164 +        assertTrue(g.cancel(mayInterruptIfRunning));
1165 +        f.complete(v1);
1166 +        final CompletableFuture<Integer> h = m.thenCombine(f, g, r);
1167  
802        f = new CompletableFuture<>();
803        g = new CompletableFuture<>();
804        assertTrue(f.cancel(true));
805        assertTrue(g.cancel(true));
806        h = f.thenCombine(g, subtract);
1168          checkCompletedWithWrappedCancellationException(h);
1169 +        checkCancelled(g);
1170 +        assertEquals(r.invocationCount, 0);
1171 +        checkCompletedNormally(f, v1);
1172 +        }
1173 +    }
1174 +
1175 +    public void testThenCombine_sourceCancelled4() {
1176 +        for (ExecutionMode m : ExecutionMode.values())
1177 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
1178 +        for (Integer v1 : new Integer[] { 1, null }) {
1179 +
1180 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1181 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1182 +        final SubtractFunction r = new SubtractFunction();
1183 +
1184 +        assertTrue(f.cancel(mayInterruptIfRunning));
1185 +        g.complete(v1);
1186 +        final CompletableFuture<Integer> h = m.thenCombine(f, g, r);
1187 +
1188 +        checkCompletedWithWrappedCancellationException(h);
1189 +        checkCancelled(f);
1190 +        assertEquals(r.invocationCount, 0);
1191 +        checkCompletedNormally(g, v1);
1192 +        }
1193      }
1194  
1195      /**
1196       * thenAcceptBoth result completes normally after normal
1197       * completion of sources
1198       */
1199 <    public void testThenAcceptBoth() {
1200 <        CompletableFuture<Integer> f, g;
1201 <        CompletableFuture<Void> h;
1202 <        SubtractAction r;
1199 >    public void testThenAcceptBoth_normalCompletion1() {
1200 >        for (ExecutionMode m : ExecutionMode.values())
1201 >        for (Integer v1 : new Integer[] { 1, null })
1202 >        for (Integer v2 : new Integer[] { 2, null }) {
1203  
1204 <        f = new CompletableFuture<>();
1205 <        g = new CompletableFuture<>();
1206 <        h = f.thenAcceptBoth(g, r = new SubtractAction());
1207 <        f.complete(3);
1204 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
1205 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
1206 >        final SubtractAction r = new SubtractAction();
1207 >        final CompletableFuture<Void> h = m.thenAcceptBoth(f, g, r);
1208 >
1209 >        f.complete(v1);
1210          checkIncomplete(h);
1211 <        g.complete(1);
1211 >        assertFalse(r.ran());
1212 >        g.complete(v2);
1213 >
1214          checkCompletedNormally(h, null);
1215 <        assertEquals(r.value, 2);
1215 >        assertEquals(r.value, subtract(v1, v2));
1216 >        checkCompletedNormally(f, v1);
1217 >        checkCompletedNormally(g, v2);
1218 >        }
1219 >    }
1220  
1221 <        f = new CompletableFuture<>();
1222 <        g = new CompletableFuture<>();
1223 <        h = f.thenAcceptBoth(g, r = new SubtractAction());
1224 <        g.complete(1);
1221 >    public void testThenAcceptBoth_normalCompletion2() {
1222 >        for (ExecutionMode m : ExecutionMode.values())
1223 >        for (Integer v1 : new Integer[] { 1, null })
1224 >        for (Integer v2 : new Integer[] { 2, null }) {
1225 >
1226 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
1227 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
1228 >        final SubtractAction r = new SubtractAction();
1229 >        final CompletableFuture<Void> h = m.thenAcceptBoth(f, g, r);
1230 >
1231 >        g.complete(v2);
1232          checkIncomplete(h);
1233 <        f.complete(3);
1233 >        assertFalse(r.ran());
1234 >        f.complete(v1);
1235 >
1236          checkCompletedNormally(h, null);
1237 <        assertEquals(r.value, 2);
1237 >        assertEquals(r.value, subtract(v1, v2));
1238 >        checkCompletedNormally(f, v1);
1239 >        checkCompletedNormally(g, v2);
1240 >        }
1241 >    }
1242 >
1243 >    public void testThenAcceptBoth_normalCompletion3() {
1244 >        for (ExecutionMode m : ExecutionMode.values())
1245 >        for (Integer v1 : new Integer[] { 1, null })
1246 >        for (Integer v2 : new Integer[] { 2, null }) {
1247 >
1248 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
1249 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
1250 >        final SubtractAction r = new SubtractAction();
1251 >
1252 >        g.complete(v2);
1253 >        f.complete(v1);
1254 >        final CompletableFuture<Void> h = m.thenAcceptBoth(f, g, r);
1255  
837        f = new CompletableFuture<>();
838        g = new CompletableFuture<>();
839        g.complete(1);
840        f.complete(3);
841        h = f.thenAcceptBoth(g, r = new SubtractAction());
1256          checkCompletedNormally(h, null);
1257 <        assertEquals(r.value, 2);
1257 >        assertEquals(r.value, subtract(v1, v2));
1258 >        checkCompletedNormally(f, v1);
1259 >        checkCompletedNormally(g, v2);
1260 >        }
1261 >    }
1262 >
1263 >    public void testThenAcceptBoth_normalCompletion4() {
1264 >        for (ExecutionMode m : ExecutionMode.values())
1265 >        for (Integer v1 : new Integer[] { 1, null })
1266 >        for (Integer v2 : new Integer[] { 2, null }) {
1267 >
1268 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
1269 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
1270 >        final SubtractAction r = new SubtractAction();
1271 >
1272 >        f.complete(v1);
1273 >        g.complete(v2);
1274 >        final CompletableFuture<Void> h = m.thenAcceptBoth(f, g, r);
1275 >
1276 >        checkCompletedNormally(h, null);
1277 >        assertEquals(r.value, subtract(v1, v2));
1278 >        checkCompletedNormally(f, v1);
1279 >        checkCompletedNormally(g, v2);
1280 >        }
1281      }
1282  
1283      /**
1284       * thenAcceptBoth result completes exceptionally after exceptional
1285       * completion of either source
1286       */
1287 <    public void testThenAcceptBoth2() {
1288 <        CompletableFuture<Integer> f, g;
1289 <        CompletableFuture<Void> h;
853 <        SubtractAction r;
1287 >    public void testThenAcceptBoth_exceptionalCompletion1() {
1288 >        for (ExecutionMode m : ExecutionMode.values())
1289 >        for (Integer v1 : new Integer[] { 1, null }) {
1290  
1291 <        f = new CompletableFuture<>();
1292 <        g = new CompletableFuture<>();
1293 <        h = f.thenAcceptBoth(g, r = new SubtractAction());
1294 <        f.completeExceptionally(new CFException());
1291 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
1292 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
1293 >        final SubtractAction r = new SubtractAction();
1294 >        final CompletableFuture<Void> h = m.thenAcceptBoth(f, g, r);
1295 >        final CFException ex = new CFException();
1296 >
1297 >        f.completeExceptionally(ex);
1298          checkIncomplete(h);
1299 <        g.complete(1);
861 <        checkCompletedWithWrappedCFException(h);
1299 >        g.complete(v1);
1300  
1301 <        f = new CompletableFuture<>();
1302 <        g = new CompletableFuture<>();
1303 <        h = f.thenAcceptBoth(g, r = new SubtractAction());
1304 <        g.completeExceptionally(new CFException());
1301 >        checkCompletedWithWrappedCFException(h, ex);
1302 >        checkCompletedWithWrappedCFException(f, ex);
1303 >        assertEquals(r.invocationCount, 0);
1304 >        checkCompletedNormally(g, v1);
1305 >        }
1306 >    }
1307 >
1308 >    public void testThenAcceptBoth_exceptionalCompletion2() {
1309 >        for (ExecutionMode m : ExecutionMode.values())
1310 >        for (Integer v1 : new Integer[] { 1, null }) {
1311 >
1312 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
1313 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
1314 >        final SubtractAction r = new SubtractAction();
1315 >        final CompletableFuture<Void> h = m.thenAcceptBoth(f, g, r);
1316 >        final CFException ex = new CFException();
1317 >
1318 >        g.completeExceptionally(ex);
1319          checkIncomplete(h);
1320 <        f.complete(3);
869 <        checkCompletedWithWrappedCFException(h);
1320 >        f.complete(v1);
1321  
1322 <        f = new CompletableFuture<>();
1323 <        g = new CompletableFuture<>();
1324 <        f.complete(3);
1325 <        g.completeExceptionally(new CFException());
1326 <        h = f.thenAcceptBoth(g, r = new SubtractAction());
1327 <        checkCompletedWithWrappedCFException(h);
1322 >        checkCompletedWithWrappedCFException(h, ex);
1323 >        checkCompletedWithWrappedCFException(g, ex);
1324 >        assertEquals(r.invocationCount, 0);
1325 >        checkCompletedNormally(f, v1);
1326 >        }
1327 >    }
1328  
1329 <        f = new CompletableFuture<>();
1330 <        g = new CompletableFuture<>();
1331 <        f.completeExceptionally(new CFException());
1332 <        g.complete(3);
1333 <        h = f.thenAcceptBoth(g, r = new SubtractAction());
1334 <        checkCompletedWithWrappedCFException(h);
1329 >    public void testThenAcceptBoth_exceptionalCompletion3() {
1330 >        for (ExecutionMode m : ExecutionMode.values())
1331 >        for (Integer v1 : new Integer[] { 1, null }) {
1332 >
1333 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
1334 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
1335 >        final SubtractAction r = new SubtractAction();
1336 >        final CFException ex = new CFException();
1337 >
1338 >        g.completeExceptionally(ex);
1339 >        f.complete(v1);
1340 >        final CompletableFuture<Void> h = m.thenAcceptBoth(f, g, r);
1341 >
1342 >        checkCompletedWithWrappedCFException(h, ex);
1343 >        checkCompletedWithWrappedCFException(g, ex);
1344 >        assertEquals(r.invocationCount, 0);
1345 >        checkCompletedNormally(f, v1);
1346 >        }
1347 >    }
1348 >
1349 >    public void testThenAcceptBoth_exceptionalCompletion4() {
1350 >        for (ExecutionMode m : ExecutionMode.values())
1351 >        for (Integer v1 : new Integer[] { 1, null }) {
1352 >
1353 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
1354 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
1355 >        final SubtractAction r = new SubtractAction();
1356 >        final CFException ex = new CFException();
1357 >
1358 >        f.completeExceptionally(ex);
1359 >        g.complete(v1);
1360 >        final CompletableFuture<Void> h = m.thenAcceptBoth(f, g, r);
1361 >
1362 >        checkCompletedWithWrappedCFException(h, ex);
1363 >        checkCompletedWithWrappedCFException(f, ex);
1364 >        assertFalse(r.ran());
1365 >        checkCompletedNormally(g, v1);
1366 >        }
1367      }
1368  
1369      /**
1370       * thenAcceptBoth result completes exceptionally if action does
1371       */
1372 <    public void testThenAcceptBoth3() {
1373 <        CompletableFuture<Integer> f, g;
1374 <        CompletableFuture<Void> h;
1375 <        FailingBiConsumer r;
1372 >    public void testThenAcceptBoth_actionFailed1() {
1373 >        for (ExecutionMode m : ExecutionMode.values())
1374 >        for (Integer v1 : new Integer[] { 1, null })
1375 >        for (Integer v2 : new Integer[] { 2, null }) {
1376  
1377 <        f = new CompletableFuture<>();
1378 <        g = new CompletableFuture<>();
1379 <        h = f.thenAcceptBoth(g, r = new FailingBiConsumer());
1380 <        f.complete(3);
1377 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
1378 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
1379 >        final FailingBiConsumer r = new FailingBiConsumer();
1380 >        final CompletableFuture<Void> h = m.thenAcceptBoth(f, g, r);
1381 >
1382 >        f.complete(v1);
1383          checkIncomplete(h);
1384 <        g.complete(1);
1384 >        g.complete(v2);
1385 >
1386          checkCompletedWithWrappedCFException(h);
1387 +        checkCompletedNormally(f, v1);
1388 +        checkCompletedNormally(g, v2);
1389 +        }
1390 +    }
1391 +
1392 +    public void testThenAcceptBoth_actionFailed2() {
1393 +        for (ExecutionMode m : ExecutionMode.values())
1394 +        for (Integer v1 : new Integer[] { 1, null })
1395 +        for (Integer v2 : new Integer[] { 2, null }) {
1396 +
1397 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1398 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1399 +        final FailingBiConsumer r = new FailingBiConsumer();
1400 +        final CompletableFuture<Void> h = m.thenAcceptBoth(f, g, r);
1401 +
1402 +        g.complete(v2);
1403 +        checkIncomplete(h);
1404 +        f.complete(v1);
1405  
902        f = new CompletableFuture<>();
903        g = new CompletableFuture<>();
904        f.complete(3);
905        g.complete(1);
906        h = f.thenAcceptBoth(g, r = new FailingBiConsumer());
1406          checkCompletedWithWrappedCFException(h);
1407 +        checkCompletedNormally(f, v1);
1408 +        checkCompletedNormally(g, v2);
1409 +        }
1410      }
1411  
1412      /**
1413       * thenAcceptBoth result completes exceptionally if either source cancelled
1414       */
1415 <    public void testThenAcceptBoth4() {
1416 <        CompletableFuture<Integer> f, g;
1417 <        CompletableFuture<Void> h;
1418 <        SubtractAction r;
1415 >    public void testThenAcceptBoth_sourceCancelled1() {
1416 >        for (ExecutionMode m : ExecutionMode.values())
1417 >        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
1418 >        for (Integer v1 : new Integer[] { 1, null }) {
1419  
1420 <        f = new CompletableFuture<>();
1421 <        g = new CompletableFuture<>();
1422 <        h = f.thenAcceptBoth(g, r = new SubtractAction());
1423 <        assertTrue(f.cancel(true));
1420 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
1421 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
1422 >        final SubtractAction r = new SubtractAction();
1423 >        final CompletableFuture<Void> h = m.thenAcceptBoth(f, g, r);
1424 >
1425 >        assertTrue(f.cancel(mayInterruptIfRunning));
1426          checkIncomplete(h);
1427 <        g.complete(1);
1427 >        g.complete(v1);
1428 >
1429          checkCompletedWithWrappedCancellationException(h);
1430 +        checkCancelled(f);
1431 +        assertEquals(r.invocationCount, 0);
1432 +        checkCompletedNormally(g, v1);
1433 +        }
1434 +    }
1435  
1436 <        f = new CompletableFuture<>();
1437 <        g = new CompletableFuture<>();
1438 <        h = f.thenAcceptBoth(g, r = new SubtractAction());
1439 <        assertTrue(g.cancel(true));
1436 >    public void testThenAcceptBoth_sourceCancelled2() {
1437 >        for (ExecutionMode m : ExecutionMode.values())
1438 >        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
1439 >        for (Integer v1 : new Integer[] { 1, null }) {
1440 >
1441 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
1442 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
1443 >        final SubtractAction r = new SubtractAction();
1444 >        final CompletableFuture<Void> h = m.thenAcceptBoth(f, g, r);
1445 >
1446 >        assertTrue(g.cancel(mayInterruptIfRunning));
1447          checkIncomplete(h);
1448 <        f.complete(3);
1448 >        f.complete(v1);
1449 >
1450          checkCompletedWithWrappedCancellationException(h);
1451 +        checkCancelled(g);
1452 +        assertEquals(r.invocationCount, 0);
1453 +        checkCompletedNormally(f, v1);
1454 +        }
1455 +    }
1456 +
1457 +    public void testThenAcceptBoth_sourceCancelled3() {
1458 +        for (ExecutionMode m : ExecutionMode.values())
1459 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
1460 +        for (Integer v1 : new Integer[] { 1, null }) {
1461 +
1462 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1463 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1464 +        final SubtractAction r = new SubtractAction();
1465 +
1466 +        assertTrue(g.cancel(mayInterruptIfRunning));
1467 +        f.complete(v1);
1468 +        final CompletableFuture<Void> h = m.thenAcceptBoth(f, g, r);
1469  
934        f = new CompletableFuture<>();
935        g = new CompletableFuture<>();
936        f.complete(3);
937        assertTrue(g.cancel(true));
938        h = f.thenAcceptBoth(g, r = new SubtractAction());
1470          checkCompletedWithWrappedCancellationException(h);
1471 +        checkCancelled(g);
1472 +        assertEquals(r.invocationCount, 0);
1473 +        checkCompletedNormally(f, v1);
1474 +        }
1475 +    }
1476 +
1477 +    public void testThenAcceptBoth_sourceCancelled4() {
1478 +        for (ExecutionMode m : ExecutionMode.values())
1479 +        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
1480 +        for (Integer v1 : new Integer[] { 1, null }) {
1481 +
1482 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
1483 +        final CompletableFuture<Integer> g = new CompletableFuture<>();
1484 +        final SubtractAction r = new SubtractAction();
1485 +
1486 +        assertTrue(f.cancel(mayInterruptIfRunning));
1487 +        g.complete(v1);
1488 +        final CompletableFuture<Void> h = m.thenAcceptBoth(f, g, r);
1489  
941        f = new CompletableFuture<>();
942        g = new CompletableFuture<>();
943        assertTrue(f.cancel(true));
944        g.complete(3);
945        h = f.thenAcceptBoth(g, r = new SubtractAction());
1490          checkCompletedWithWrappedCancellationException(h);
1491 +        checkCancelled(f);
1492 +        assertEquals(r.invocationCount, 0);
1493 +        checkCompletedNormally(g, v1);
1494 +        }
1495      }
1496  
1497      /**
# Line 951 | Line 1499 | public class CompletableFutureTest exten
1499       * completion of sources
1500       */
1501      public void testRunAfterBoth_normalCompletion1() {
1502 +        for (ExecutionMode m : ExecutionMode.values())
1503          for (Integer v1 : new Integer[] { 1, null })
1504          for (Integer v2 : new Integer[] { 2, null }) {
1505  
1506          final CompletableFuture<Integer> f = new CompletableFuture<>();
1507          final CompletableFuture<Integer> g = new CompletableFuture<>();
1508          final Noop r = new Noop();
1509 <        final CompletableFuture<Void> h = f.runAfterBoth(g, r);
1509 >        final CompletableFuture<Void> h = m.runAfterBoth(f, g, r);
1510  
1511          f.complete(v1);
1512          checkIncomplete(h);
# Line 965 | Line 1514 | public class CompletableFutureTest exten
1514          g.complete(v2);
1515  
1516          checkCompletedNormally(h, null);
1517 <        assertTrue(r.ran);
1517 >        assertEquals(r.invocationCount, 1);
1518          checkCompletedNormally(f, v1);
1519          checkCompletedNormally(g, v2);
1520          }
1521      }
1522  
1523      public void testRunAfterBoth_normalCompletion2() {
1524 +        for (ExecutionMode m : ExecutionMode.values())
1525          for (Integer v1 : new Integer[] { 1, null })
1526          for (Integer v2 : new Integer[] { 2, null }) {
1527  
1528          final CompletableFuture<Integer> f = new CompletableFuture<>();
1529          final CompletableFuture<Integer> g = new CompletableFuture<>();
1530          final Noop r = new Noop();
1531 <        final CompletableFuture<Void> h = f.runAfterBoth(g, r);
1531 >        final CompletableFuture<Void> h = m.runAfterBoth(f, g, r);
1532  
1533          g.complete(v2);
1534          checkIncomplete(h);
# Line 986 | Line 1536 | public class CompletableFutureTest exten
1536          f.complete(v1);
1537  
1538          checkCompletedNormally(h, null);
1539 <        assertTrue(r.ran);
1539 >        assertEquals(r.invocationCount, 1);
1540          checkCompletedNormally(f, v1);
1541          checkCompletedNormally(g, v2);
1542          }
1543      }
1544  
1545      public void testRunAfterBoth_normalCompletion3() {
1546 +        for (ExecutionMode m : ExecutionMode.values())
1547          for (Integer v1 : new Integer[] { 1, null })
1548          for (Integer v2 : new Integer[] { 2, null }) {
1549  
# Line 1002 | Line 1553 | public class CompletableFutureTest exten
1553  
1554          g.complete(v2);
1555          f.complete(v1);
1556 <        final CompletableFuture<Void> h = f.runAfterBoth(g, r);
1556 >        final CompletableFuture<Void> h = m.runAfterBoth(f, g, r);
1557  
1558          checkCompletedNormally(h, null);
1559          assertTrue(r.ran);
# Line 1012 | Line 1563 | public class CompletableFutureTest exten
1563      }
1564  
1565      public void testRunAfterBoth_normalCompletion4() {
1566 +        for (ExecutionMode m : ExecutionMode.values())
1567          for (Integer v1 : new Integer[] { 1, null })
1568          for (Integer v2 : new Integer[] { 2, null }) {
1569  
# Line 1021 | Line 1573 | public class CompletableFutureTest exten
1573  
1574          f.complete(v1);
1575          g.complete(v2);
1576 <        final CompletableFuture<Void> h = f.runAfterBoth(g, r);
1576 >        final CompletableFuture<Void> h = m.runAfterBoth(f, g, r);
1577  
1578          checkCompletedNormally(h, null);
1579 <        assertTrue(r.ran);
1579 >        assertEquals(r.invocationCount, 1);
1580          checkCompletedNormally(f, v1);
1581          checkCompletedNormally(g, v2);
1582          }
# Line 1035 | Line 1587 | public class CompletableFutureTest exten
1587       * completion of either source
1588       */
1589      public void testRunAfterBoth_exceptionalCompletion1() {
1590 +        for (ExecutionMode m : ExecutionMode.values())
1591          for (Integer v1 : new Integer[] { 1, null }) {
1592  
1593          final CompletableFuture<Integer> f = new CompletableFuture<>();
1594          final CompletableFuture<Integer> g = new CompletableFuture<>();
1595          final Noop r = new Noop();
1596 <        final CompletableFuture<Void> h = f.runAfterBoth(g, r);
1596 >        final CompletableFuture<Void> h = m.runAfterBoth(f, g, r);
1597          final CFException ex = new CFException();
1598  
1599          f.completeExceptionally(ex);
# Line 1049 | Line 1602 | public class CompletableFutureTest exten
1602  
1603          checkCompletedWithWrappedCFException(h, ex);
1604          checkCompletedWithWrappedCFException(f, ex);
1605 <        assertFalse(r.ran);
1605 >        assertEquals(r.invocationCount, 0);
1606          checkCompletedNormally(g, v1);
1607          }
1608      }
1609  
1610      public void testRunAfterBoth_exceptionalCompletion2() {
1611 +        for (ExecutionMode m : ExecutionMode.values())
1612          for (Integer v1 : new Integer[] { 1, null }) {
1613  
1614          final CompletableFuture<Integer> f = new CompletableFuture<>();
1615          final CompletableFuture<Integer> g = new CompletableFuture<>();
1616          final Noop r = new Noop();
1617 <        final CompletableFuture<Void> h = f.runAfterBoth(g, r);
1617 >        final CompletableFuture<Void> h = m.runAfterBoth(f, g, r);
1618          final CFException ex = new CFException();
1619  
1620          g.completeExceptionally(ex);
# Line 1069 | Line 1623 | public class CompletableFutureTest exten
1623  
1624          checkCompletedWithWrappedCFException(h, ex);
1625          checkCompletedWithWrappedCFException(g, ex);
1626 <        assertFalse(r.ran);
1626 >        assertEquals(r.invocationCount, 0);
1627          checkCompletedNormally(f, v1);
1628          }
1629      }
1630  
1631      public void testRunAfterBoth_exceptionalCompletion3() {
1632 +        for (ExecutionMode m : ExecutionMode.values())
1633          for (Integer v1 : new Integer[] { 1, null }) {
1634  
1635          final CompletableFuture<Integer> f = new CompletableFuture<>();
# Line 1084 | Line 1639 | public class CompletableFutureTest exten
1639  
1640          g.completeExceptionally(ex);
1641          f.complete(v1);
1642 <        final CompletableFuture<Void> h = f.runAfterBoth(g, r);
1642 >        final CompletableFuture<Void> h = m.runAfterBoth(f, g, r);
1643  
1644          checkCompletedWithWrappedCFException(h, ex);
1645          checkCompletedWithWrappedCFException(g, ex);
1646 <        assertFalse(r.ran);
1646 >        assertEquals(r.invocationCount, 0);
1647          checkCompletedNormally(f, v1);
1648          }
1649      }
1650  
1651      public void testRunAfterBoth_exceptionalCompletion4() {
1652 +        for (ExecutionMode m : ExecutionMode.values())
1653          for (Integer v1 : new Integer[] { 1, null }) {
1654  
1655          final CompletableFuture<Integer> f = new CompletableFuture<>();
# Line 1103 | Line 1659 | public class CompletableFutureTest exten
1659  
1660          f.completeExceptionally(ex);
1661          g.complete(v1);
1662 <        final CompletableFuture<Void> h = f.runAfterBoth(g, r);
1662 >        final CompletableFuture<Void> h = m.runAfterBoth(f, g, r);
1663  
1664          checkCompletedWithWrappedCFException(h, ex);
1665          checkCompletedWithWrappedCFException(f, ex);
1666 <        assertFalse(r.ran);
1666 >        assertEquals(r.invocationCount, 0);
1667          checkCompletedNormally(g, v1);
1668          }
1669      }
# Line 1116 | Line 1672 | public class CompletableFutureTest exten
1672       * runAfterBoth result completes exceptionally if action does
1673       */
1674      public void testRunAfterBoth_actionFailed1() {
1675 +        for (ExecutionMode m : ExecutionMode.values())
1676          for (Integer v1 : new Integer[] { 1, null })
1677          for (Integer v2 : new Integer[] { 2, null }) {
1678  
1679          final CompletableFuture<Integer> f = new CompletableFuture<>();
1680          final CompletableFuture<Integer> g = new CompletableFuture<>();
1681          final FailingNoop r = new FailingNoop();
1682 <        final CompletableFuture<Void> h = f.runAfterBoth(g, r);
1682 >        final CompletableFuture<Void> h = m.runAfterBoth(f, g, r);
1683  
1684          f.complete(v1);
1685          checkIncomplete(h);
# Line 1135 | Line 1692 | public class CompletableFutureTest exten
1692      }
1693  
1694      public void testRunAfterBoth_actionFailed2() {
1695 +        for (ExecutionMode m : ExecutionMode.values())
1696          for (Integer v1 : new Integer[] { 1, null })
1697          for (Integer v2 : new Integer[] { 2, null }) {
1698  
1699          final CompletableFuture<Integer> f = new CompletableFuture<>();
1700          final CompletableFuture<Integer> g = new CompletableFuture<>();
1701          final FailingNoop r = new FailingNoop();
1702 <        final CompletableFuture<Void> h = f.runAfterBoth(g, r);
1702 >        final CompletableFuture<Void> h = m.runAfterBoth(f, g, r);
1703  
1704          g.complete(v2);
1705          checkIncomplete(h);
# Line 1157 | Line 1715 | public class CompletableFutureTest exten
1715       * runAfterBoth result completes exceptionally if either source cancelled
1716       */
1717      public void testRunAfterBoth_sourceCancelled1() {
1718 +        for (ExecutionMode m : ExecutionMode.values())
1719          for (boolean mayInterruptIfRunning : new boolean[] { true, false })
1720          for (Integer v1 : new Integer[] { 1, null }) {
1721  
1722          final CompletableFuture<Integer> f = new CompletableFuture<>();
1723          final CompletableFuture<Integer> g = new CompletableFuture<>();
1724          final Noop r = new Noop();
1725 <        final CompletableFuture<Void> h = f.runAfterBoth(g, r);
1725 >        final CompletableFuture<Void> h = m.runAfterBoth(f, g, r);
1726  
1727          assertTrue(f.cancel(mayInterruptIfRunning));
1728          checkIncomplete(h);
# Line 1171 | Line 1730 | public class CompletableFutureTest exten
1730  
1731          checkCompletedWithWrappedCancellationException(h);
1732          checkCancelled(f);
1733 <        assertFalse(r.ran);
1733 >        assertEquals(r.invocationCount, 0);
1734          checkCompletedNormally(g, v1);
1735          }
1736      }
1737  
1738      public void testRunAfterBoth_sourceCancelled2() {
1739 +        for (ExecutionMode m : ExecutionMode.values())
1740          for (boolean mayInterruptIfRunning : new boolean[] { true, false })
1741          for (Integer v1 : new Integer[] { 1, null }) {
1742  
1743          final CompletableFuture<Integer> f = new CompletableFuture<>();
1744          final CompletableFuture<Integer> g = new CompletableFuture<>();
1745          final Noop r = new Noop();
1746 <        final CompletableFuture<Void> h = f.runAfterBoth(g, r);
1746 >        final CompletableFuture<Void> h = m.runAfterBoth(f, g, r);
1747  
1748          assertTrue(g.cancel(mayInterruptIfRunning));
1749          checkIncomplete(h);
# Line 1191 | Line 1751 | public class CompletableFutureTest exten
1751  
1752          checkCompletedWithWrappedCancellationException(h);
1753          checkCancelled(g);
1754 <        assertFalse(r.ran);
1754 >        assertEquals(r.invocationCount, 0);
1755          checkCompletedNormally(f, v1);
1756          }
1757      }
1758  
1759      public void testRunAfterBoth_sourceCancelled3() {
1760 +        for (ExecutionMode m : ExecutionMode.values())
1761          for (boolean mayInterruptIfRunning : new boolean[] { true, false })
1762          for (Integer v1 : new Integer[] { 1, null }) {
1763  
# Line 1206 | Line 1767 | public class CompletableFutureTest exten
1767  
1768          assertTrue(g.cancel(mayInterruptIfRunning));
1769          f.complete(v1);
1770 <        final CompletableFuture<Void> h = f.runAfterBoth(g, r);
1770 >        final CompletableFuture<Void> h = m.runAfterBoth(f, g, r);
1771  
1772          checkCompletedWithWrappedCancellationException(h);
1773          checkCancelled(g);
1774 <        assertFalse(r.ran);
1774 >        assertEquals(r.invocationCount, 0);
1775          checkCompletedNormally(f, v1);
1776          }
1777      }
1778  
1779      public void testRunAfterBoth_sourceCancelled4() {
1780 +        for (ExecutionMode m : ExecutionMode.values())
1781          for (boolean mayInterruptIfRunning : new boolean[] { true, false })
1782          for (Integer v1 : new Integer[] { 1, null }) {
1783  
# Line 1225 | Line 1787 | public class CompletableFutureTest exten
1787  
1788          assertTrue(f.cancel(mayInterruptIfRunning));
1789          g.complete(v1);
1790 <        final CompletableFuture<Void> h = f.runAfterBoth(g, r);
1790 >        final CompletableFuture<Void> h = m.runAfterBoth(f, g, r);
1791  
1792          checkCompletedWithWrappedCancellationException(h);
1793          checkCancelled(f);
1794 <        assertFalse(r.ran);
1794 >        assertEquals(r.invocationCount, 0);
1795          checkCompletedNormally(g, v1);
1796          }
1797      }
# Line 1238 | Line 1800 | public class CompletableFutureTest exten
1800       * applyToEither result completes normally after normal completion
1801       * of either source
1802       */
1803 <    public void testApplyToEither() {
1804 <        CompletableFuture<Integer> f = new CompletableFuture<>();
1805 <        CompletableFuture<Integer> f2 = new CompletableFuture<>();
1806 <        CompletableFuture<Integer> g = f.applyToEither(f2, inc);
1245 <        f.complete(one);
1246 <        checkCompletedNormally(g, two);
1247 <        f2.complete(one);
1248 <        checkCompletedNormally(g, two);
1803 >    public void testApplyToEither_normalCompletion1() {
1804 >        for (ExecutionMode m : ExecutionMode.values())
1805 >        for (Integer v1 : new Integer[] { 1, null })
1806 >        for (Integer v2 : new Integer[] { 2, null }) {
1807  
1808 <        f = new CompletableFuture<>();
1809 <        f.complete(one);
1810 <        f2 = new CompletableFuture<>();
1811 <        g = f.applyToEither(f2, inc);
1812 <        checkCompletedNormally(g, two);
1808 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
1809 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
1810 >        final IncFunction r = new IncFunction();
1811 >        final CompletableFuture<Integer> h = m.applyToEither(f, g, r);
1812 >
1813 >        f.complete(v1);
1814 >        checkCompletedNormally(h, inc(v1));
1815 >        g.complete(v2);
1816 >
1817 >        checkCompletedNormally(f, v1);
1818 >        checkCompletedNormally(g, v2);
1819 >        checkCompletedNormally(h, inc(v1));
1820 >        }
1821 >    }
1822 >
1823 >    public void testApplyToEither_normalCompletion2() {
1824 >        for (ExecutionMode m : ExecutionMode.values())
1825 >        for (Integer v1 : new Integer[] { 1, null })
1826 >        for (Integer v2 : new Integer[] { 2, null }) {
1827 >
1828 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
1829 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
1830 >        final IncFunction r = new IncFunction();
1831 >        final CompletableFuture<Integer> h = m.applyToEither(f, g, r);
1832 >
1833 >        g.complete(v2);
1834 >        checkCompletedNormally(h, inc(v2));
1835 >        f.complete(v1);
1836 >
1837 >        checkCompletedNormally(f, v1);
1838 >        checkCompletedNormally(g, v2);
1839 >        checkCompletedNormally(h, inc(v2));
1840 >        }
1841 >    }
1842 >    public void testApplyToEither_normalCompletion3() {
1843 >        for (ExecutionMode m : ExecutionMode.values())
1844 >        for (Integer v1 : new Integer[] { 1, null })
1845 >        for (Integer v2 : new Integer[] { 2, null }) {
1846 >
1847 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
1848 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
1849 >        final IncFunction r = new IncFunction();
1850 >
1851 >        f.complete(v1);
1852 >        g.complete(v2);
1853 >        final CompletableFuture<Integer> h = m.applyToEither(f, g, r);
1854 >
1855 >        checkCompletedNormally(f, v1);
1856 >        checkCompletedNormally(g, v2);
1857 >
1858 >        // unspecified behavior
1859 >        assertTrue(Objects.equals(h.join(), inc(v1)) ||
1860 >                   Objects.equals(h.join(), inc(v2)));
1861 >        assertEquals(r.invocationCount, 1);
1862 >        }
1863      }
1864  
1865      /**
1866       * applyToEither result completes exceptionally after exceptional
1867       * completion of either source
1868       */
1869 <    public void testApplyToEither2() {
1870 <        CompletableFuture<Integer> f = new CompletableFuture<>();
1871 <        CompletableFuture<Integer> f2 = new CompletableFuture<>();
1264 <        CompletableFuture<Integer> g = f.applyToEither(f2, inc);
1265 <        f.completeExceptionally(new CFException());
1266 <        f2.complete(one);
1267 <        checkCompletedWithWrappedCFException(g);
1869 >    public void testApplyToEither_exceptionalCompletion1() {
1870 >        for (ExecutionMode m : ExecutionMode.values())
1871 >        for (Integer v1 : new Integer[] { 1, null }) {
1872  
1873 <        f = new CompletableFuture<>();
1874 <        f2 = new CompletableFuture<>();
1875 <        f2.completeExceptionally(new CFException());
1876 <        g = f.applyToEither(f2, inc);
1877 <        checkCompletedWithWrappedCFException(g);
1873 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
1874 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
1875 >        final IncFunction r = new IncFunction();
1876 >        final CompletableFuture<Integer> h = m.applyToEither(f, g, r);
1877 >        final CFException ex = new CFException();
1878 >
1879 >        f.completeExceptionally(ex);
1880 >        checkCompletedWithWrappedCFException(h, ex);
1881 >        g.complete(v1);
1882 >
1883 >        assertEquals(r.invocationCount, 0);
1884 >        checkCompletedNormally(g, v1);
1885 >        checkCompletedWithWrappedCFException(f, ex);
1886 >        checkCompletedWithWrappedCFException(h, ex);
1887 >        }
1888 >    }
1889 >
1890 >    public void testApplyToEither_exceptionalCompletion2() {
1891 >        for (ExecutionMode m : ExecutionMode.values())
1892 >        for (Integer v1 : new Integer[] { 1, null }) {
1893 >
1894 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
1895 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
1896 >        final IncFunction r = new IncFunction();
1897 >        final CompletableFuture<Integer> h = m.applyToEither(f, g, r);
1898 >        final CFException ex = new CFException();
1899 >
1900 >        g.completeExceptionally(ex);
1901 >        checkCompletedWithWrappedCFException(h, ex);
1902 >        f.complete(v1);
1903 >
1904 >        assertEquals(r.invocationCount, 0);
1905 >        checkCompletedNormally(f, v1);
1906 >        checkCompletedWithWrappedCFException(g, ex);
1907 >        checkCompletedWithWrappedCFException(h, ex);
1908 >        }
1909 >    }
1910 >
1911 >    public void testApplyToEither_exceptionalCompletion3() {
1912 >        for (ExecutionMode m : ExecutionMode.values())
1913 >        for (Integer v1 : new Integer[] { 1, null }) {
1914 >
1915 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
1916 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
1917 >        final IncFunction r = new IncFunction();
1918 >        final CFException ex = new CFException();
1919 >
1920 >        g.completeExceptionally(ex);
1921 >        f.complete(v1);
1922 >        final CompletableFuture<Integer> h = m.applyToEither(f, g, r);
1923 >
1924 >        // unspecified behavior
1925 >        Integer v;
1926 >        try {
1927 >            assertEquals(h.join(), inc(v1));
1928 >            assertEquals(r.invocationCount, 1);
1929 >        } catch (CompletionException ok) {
1930 >            checkCompletedWithWrappedCFException(h, ex);
1931 >            assertEquals(r.invocationCount, 0);
1932 >        }
1933 >
1934 >        checkCompletedWithWrappedCFException(g, ex);
1935 >        checkCompletedNormally(f, v1);
1936 >        }
1937 >    }
1938 >
1939 >    public void testApplyToEither_exceptionalCompletion4() {
1940 >        for (ExecutionMode m : ExecutionMode.values())
1941 >        for (Integer v1 : new Integer[] { 1, null }) {
1942 >
1943 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
1944 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
1945 >        final IncFunction r = new IncFunction();
1946 >        final CFException ex = new CFException();
1947 >
1948 >        f.completeExceptionally(ex);
1949 >        g.complete(v1);
1950 >        final CompletableFuture<Integer> h = m.applyToEither(f, g, r);
1951 >
1952 >        // unspecified behavior
1953 >        Integer v;
1954 >        try {
1955 >            assertEquals(h.join(), inc(v1));
1956 >            assertEquals(r.invocationCount, 1);
1957 >        } catch (CompletionException ok) {
1958 >            checkCompletedWithWrappedCFException(h, ex);
1959 >            assertEquals(r.invocationCount, 0);
1960 >        }
1961 >
1962 >        checkCompletedWithWrappedCFException(f, ex);
1963 >        checkCompletedNormally(g, v1);
1964 >        }
1965      }
1966  
1967      /**
1968       * applyToEither result completes exceptionally if action does
1969       */
1970 <    public void testApplyToEither3() {
1971 <        CompletableFuture<Integer> f = new CompletableFuture<>();
1972 <        CompletableFuture<Integer> f2 = new CompletableFuture<>();
1973 <        FailingFunction r = new FailingFunction();
1974 <        CompletableFuture<Integer> g = f.applyToEither(f2, r);
1975 <        f2.complete(two);
1976 <        checkCompletedWithWrappedCFException(g);
1970 >    public void testApplyToEither_actionFailed1() {
1971 >        for (ExecutionMode m : ExecutionMode.values())
1972 >        for (Integer v1 : new Integer[] { 1, null })
1973 >        for (Integer v2 : new Integer[] { 2, null }) {
1974 >
1975 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
1976 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
1977 >        final FailingFunction r = new FailingFunction();
1978 >        final CompletableFuture<Integer> h = m.applyToEither(f, g, r);
1979 >
1980 >        f.complete(v1);
1981 >        checkCompletedWithWrappedCFException(h);
1982 >        g.complete(v2);
1983 >        checkCompletedNormally(f, v1);
1984 >        checkCompletedNormally(g, v2);
1985 >        }
1986 >    }
1987 >
1988 >    public void testApplyToEither_actionFailed2() {
1989 >        for (ExecutionMode m : ExecutionMode.values())
1990 >        for (Integer v1 : new Integer[] { 1, null })
1991 >        for (Integer v2 : new Integer[] { 2, null }) {
1992 >
1993 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
1994 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
1995 >        final FailingFunction r = new FailingFunction();
1996 >        final CompletableFuture<Integer> h = m.applyToEither(f, g, r);
1997 >
1998 >        g.complete(v2);
1999 >        checkCompletedWithWrappedCFException(h);
2000 >        f.complete(v1);
2001 >        checkCompletedNormally(f, v1);
2002 >        checkCompletedNormally(g, v2);
2003 >        }
2004      }
2005  
2006      /**
2007       * applyToEither result completes exceptionally if either source cancelled
2008       */
2009 <    public void testApplyToEither4() {
2010 <        CompletableFuture<Integer> f = new CompletableFuture<>();
2011 <        CompletableFuture<Integer> f2 = new CompletableFuture<>();
2012 <        CompletableFuture<Integer> g = f.applyToEither(f2, inc);
2013 <        assertTrue(f.cancel(true));
2014 <        checkCompletedWithWrappedCancellationException(g);
2015 <        f = new CompletableFuture<>();
2016 <        f2 = new CompletableFuture<>();
2017 <        assertTrue(f2.cancel(true));
2018 <        checkCompletedWithWrappedCancellationException(g);
2009 >    public void testApplyToEither_sourceCancelled1() {
2010 >        for (ExecutionMode m : ExecutionMode.values())
2011 >        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
2012 >        for (Integer v1 : new Integer[] { 1, null }) {
2013 >
2014 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
2015 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
2016 >        final IncFunction r = new IncFunction();
2017 >        final CompletableFuture<Integer> h = m.applyToEither(f, g, r);
2018 >
2019 >        assertTrue(f.cancel(mayInterruptIfRunning));
2020 >        checkCompletedWithWrappedCancellationException(h);
2021 >        g.complete(v1);
2022 >
2023 >        checkCancelled(f);
2024 >        assertEquals(r.invocationCount, 0);
2025 >        checkCompletedNormally(g, v1);
2026 >        checkCompletedWithWrappedCancellationException(h);
2027 >        }
2028 >    }
2029 >
2030 >    public void testApplyToEither_sourceCancelled2() {
2031 >        for (ExecutionMode m : ExecutionMode.values())
2032 >        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
2033 >        for (Integer v1 : new Integer[] { 1, null }) {
2034 >
2035 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
2036 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
2037 >        final IncFunction r = new IncFunction();
2038 >        final CompletableFuture<Integer> h = m.applyToEither(f, g, r);
2039 >
2040 >        assertTrue(g.cancel(mayInterruptIfRunning));
2041 >        checkCompletedWithWrappedCancellationException(h);
2042 >        f.complete(v1);
2043 >
2044 >        checkCancelled(g);
2045 >        assertEquals(r.invocationCount, 0);
2046 >        checkCompletedNormally(f, v1);
2047 >        checkCompletedWithWrappedCancellationException(h);
2048 >        }
2049 >    }
2050 >
2051 >    public void testApplyToEither_sourceCancelled3() {
2052 >        for (ExecutionMode m : ExecutionMode.values())
2053 >        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
2054 >        for (Integer v1 : new Integer[] { 1, null }) {
2055 >
2056 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
2057 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
2058 >        final IncFunction r = new IncFunction();
2059 >
2060 >        assertTrue(g.cancel(mayInterruptIfRunning));
2061 >        f.complete(v1);
2062 >        final CompletableFuture<Integer> h = m.applyToEither(f, g, r);
2063 >
2064 >        // unspecified behavior
2065 >        Integer v;
2066 >        try {
2067 >            assertEquals(h.join(), inc(v1));
2068 >            assertEquals(r.invocationCount, 1);
2069 >        } catch (CompletionException ok) {
2070 >            checkCompletedWithWrappedCancellationException(h);
2071 >            assertEquals(r.invocationCount, 0);
2072 >        }
2073 >
2074 >        checkCancelled(g);
2075 >        checkCompletedNormally(f, v1);
2076 >        }
2077 >    }
2078 >
2079 >    public void testApplyToEither_sourceCancelled4() {
2080 >        for (ExecutionMode m : ExecutionMode.values())
2081 >        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
2082 >        for (Integer v1 : new Integer[] { 1, null }) {
2083 >
2084 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
2085 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
2086 >        final IncFunction r = new IncFunction();
2087 >
2088 >        assertTrue(f.cancel(mayInterruptIfRunning));
2089 >        g.complete(v1);
2090 >        final CompletableFuture<Integer> h = m.applyToEither(f, g, r);
2091 >
2092 >        // unspecified behavior
2093 >        Integer v;
2094 >        try {
2095 >            assertEquals(h.join(), inc(v1));
2096 >            assertEquals(r.invocationCount, 1);
2097 >        } catch (CompletionException ok) {
2098 >            checkCompletedWithWrappedCancellationException(h);
2099 >            assertEquals(r.invocationCount, 0);
2100 >        }
2101 >
2102 >        checkCancelled(f);
2103 >        checkCompletedNormally(g, v1);
2104 >        }
2105      }
2106  
2107      /**
2108       * acceptEither result completes normally after normal completion
2109       * of either source
2110       */
2111 <    public void testAcceptEither() {
2112 <        CompletableFuture<Integer> f = new CompletableFuture<>();
2113 <        CompletableFuture<Integer> f2 = new CompletableFuture<>();
2114 <        IncAction r = new IncAction();
1311 <        CompletableFuture<Void> g = f.acceptEither(f2, r);
1312 <        f.complete(one);
1313 <        checkCompletedNormally(g, null);
1314 <        f2.complete(one);
1315 <        checkCompletedNormally(g, null);
1316 <        assertEquals(r.value, 2);
2111 >    public void testAcceptEither_normalCompletion1() {
2112 >        for (ExecutionMode m : ExecutionMode.values())
2113 >        for (Integer v1 : new Integer[] { 1, null })
2114 >        for (Integer v2 : new Integer[] { 2, null }) {
2115  
2116 <        r = new IncAction();
2117 <        f = new CompletableFuture<>();
2118 <        f.complete(one);
2119 <        f2 = new CompletableFuture<>();
2120 <        g = f.acceptEither(f2, r);
2121 <        checkCompletedNormally(g, null);
2122 <        assertEquals(r.value, 2);
2116 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
2117 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
2118 >        final IncAction r = new IncAction();
2119 >        final CompletableFuture<Void> h = m.acceptEither(f, g, r);
2120 >
2121 >        f.complete(v1);
2122 >        checkCompletedNormally(h, null);
2123 >        assertEquals(r.value, inc(v1));
2124 >        g.complete(v2);
2125 >
2126 >        checkCompletedNormally(f, v1);
2127 >        checkCompletedNormally(g, v2);
2128 >        checkCompletedNormally(h, null);
2129 >        }
2130 >    }
2131 >
2132 >    public void testAcceptEither_normalCompletion2() {
2133 >        for (ExecutionMode m : ExecutionMode.values())
2134 >        for (Integer v1 : new Integer[] { 1, null })
2135 >        for (Integer v2 : new Integer[] { 2, null }) {
2136 >
2137 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
2138 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
2139 >        final IncAction r = new IncAction();
2140 >        final CompletableFuture<Void> h = m.acceptEither(f, g, r);
2141 >
2142 >        g.complete(v2);
2143 >        checkCompletedNormally(h, null);
2144 >        assertEquals(r.value, inc(v2));
2145 >        f.complete(v1);
2146 >
2147 >        checkCompletedNormally(f, v1);
2148 >        checkCompletedNormally(g, v2);
2149 >        checkCompletedNormally(h, null);
2150 >        }
2151 >    }
2152 >    public void testAcceptEither_normalCompletion3() {
2153 >        for (ExecutionMode m : ExecutionMode.values())
2154 >        for (Integer v1 : new Integer[] { 1, null })
2155 >        for (Integer v2 : new Integer[] { 2, null }) {
2156 >
2157 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
2158 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
2159 >        final IncAction r = new IncAction();
2160 >
2161 >        f.complete(v1);
2162 >        g.complete(v2);
2163 >        final CompletableFuture<Void> h = m.acceptEither(f, g, r);
2164 >
2165 >        checkCompletedNormally(h, null);
2166 >        checkCompletedNormally(f, v1);
2167 >        checkCompletedNormally(g, v2);
2168 >
2169 >        // unspecified behavior
2170 >        assertTrue(Objects.equals(r.value, inc(v1)) ||
2171 >                   Objects.equals(r.value, inc(v2)));
2172 >        }
2173      }
2174  
2175      /**
2176       * acceptEither result completes exceptionally after exceptional
2177       * completion of either source
2178       */
2179 <    public void testAcceptEither2() {
2180 <        CompletableFuture<Integer> f = new CompletableFuture<>();
2181 <        CompletableFuture<Integer> f2 = new CompletableFuture<>();
1334 <        IncAction r = new IncAction();
1335 <        CompletableFuture<Void> g = f.acceptEither(f2, r);
1336 <        f.completeExceptionally(new CFException());
1337 <        f2.complete(one);
1338 <        checkCompletedWithWrappedCFException(g);
2179 >    public void testAcceptEither_exceptionalCompletion1() {
2180 >        for (ExecutionMode m : ExecutionMode.values())
2181 >        for (Integer v1 : new Integer[] { 1, null }) {
2182  
2183 <        r = new IncAction();
2184 <        f = new CompletableFuture<>();
2185 <        f2 = new CompletableFuture<>();
2186 <        f2.completeExceptionally(new CFException());
2187 <        g = f.acceptEither(f2, r);
2188 <        checkCompletedWithWrappedCFException(g);
2183 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
2184 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
2185 >        final IncAction r = new IncAction();
2186 >        final CompletableFuture<Void> h = m.acceptEither(f, g, r);
2187 >        final CFException ex = new CFException();
2188 >
2189 >        f.completeExceptionally(ex);
2190 >        checkCompletedWithWrappedCFException(h, ex);
2191 >        g.complete(v1);
2192 >
2193 >        assertEquals(r.invocationCount, 0);
2194 >        checkCompletedNormally(g, v1);
2195 >        checkCompletedWithWrappedCFException(f, ex);
2196 >        checkCompletedWithWrappedCFException(h, ex);
2197 >        }
2198 >    }
2199 >
2200 >    public void testAcceptEither_exceptionalCompletion2() {
2201 >        for (ExecutionMode m : ExecutionMode.values())
2202 >        for (Integer v1 : new Integer[] { 1, null }) {
2203 >
2204 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
2205 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
2206 >        final IncAction r = new IncAction();
2207 >        final CompletableFuture<Void> h = m.acceptEither(f, g, r);
2208 >        final CFException ex = new CFException();
2209 >
2210 >        g.completeExceptionally(ex);
2211 >        checkCompletedWithWrappedCFException(h, ex);
2212 >        f.complete(v1);
2213 >
2214 >        assertEquals(r.invocationCount, 0);
2215 >        checkCompletedNormally(f, v1);
2216 >        checkCompletedWithWrappedCFException(g, ex);
2217 >        checkCompletedWithWrappedCFException(h, ex);
2218 >        }
2219 >    }
2220 >
2221 >    public void testAcceptEither_exceptionalCompletion3() {
2222 >        for (ExecutionMode m : ExecutionMode.values())
2223 >        for (Integer v1 : new Integer[] { 1, null }) {
2224 >
2225 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
2226 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
2227 >        final IncAction r = new IncAction();
2228 >        final CFException ex = new CFException();
2229 >
2230 >        g.completeExceptionally(ex);
2231 >        f.complete(v1);
2232 >        final CompletableFuture<Void> h = m.acceptEither(f, g, r);
2233 >
2234 >        // unspecified behavior
2235 >        Integer v;
2236 >        try {
2237 >            assertEquals(h.join(), null);
2238 >            assertEquals(r.invocationCount, 1);
2239 >            assertEquals(inc(v1), r.value);
2240 >        } catch (CompletionException ok) {
2241 >            checkCompletedWithWrappedCFException(h, ex);
2242 >            assertEquals(r.invocationCount, 0);
2243 >        }
2244 >
2245 >        checkCompletedWithWrappedCFException(g, ex);
2246 >        checkCompletedNormally(f, v1);
2247 >        }
2248 >    }
2249 >
2250 >    public void testAcceptEither_exceptionalCompletion4() {
2251 >        for (ExecutionMode m : ExecutionMode.values())
2252 >        for (Integer v1 : new Integer[] { 1, null }) {
2253 >
2254 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
2255 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
2256 >        final IncAction r = new IncAction();
2257 >        final CFException ex = new CFException();
2258 >
2259 >        f.completeExceptionally(ex);
2260 >        g.complete(v1);
2261 >        final CompletableFuture<Void> h = m.acceptEither(f, g, r);
2262 >
2263 >        // unspecified behavior
2264 >        Integer v;
2265 >        try {
2266 >            assertEquals(h.join(), null);
2267 >            assertEquals(r.invocationCount, 1);
2268 >            assertEquals(inc(v1), r.value);
2269 >        } catch (CompletionException ok) {
2270 >            checkCompletedWithWrappedCFException(h, ex);
2271 >            assertEquals(r.invocationCount, 0);
2272 >        }
2273 >
2274 >        checkCompletedWithWrappedCFException(f, ex);
2275 >        checkCompletedNormally(g, v1);
2276 >        }
2277      }
2278  
2279      /**
2280       * acceptEither result completes exceptionally if action does
2281       */
2282 <    public void testAcceptEither3() {
2283 <        CompletableFuture<Integer> f = new CompletableFuture<>();
2284 <        CompletableFuture<Integer> f2 = new CompletableFuture<>();
2285 <        FailingConsumer r = new FailingConsumer();
2286 <        CompletableFuture<Void> g = f.acceptEither(f2, r);
2287 <        f2.complete(two);
2288 <        checkCompletedWithWrappedCFException(g);
2282 >    public void testAcceptEither_actionFailed1() {
2283 >        for (ExecutionMode m : ExecutionMode.values())
2284 >        for (Integer v1 : new Integer[] { 1, null })
2285 >        for (Integer v2 : new Integer[] { 2, null }) {
2286 >
2287 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
2288 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
2289 >        final FailingConsumer r = new FailingConsumer();
2290 >        final CompletableFuture<Void> h = m.acceptEither(f, g, r);
2291 >
2292 >        f.complete(v1);
2293 >        checkCompletedWithWrappedCFException(h);
2294 >        g.complete(v2);
2295 >        checkCompletedNormally(f, v1);
2296 >        checkCompletedNormally(g, v2);
2297 >        }
2298 >    }
2299 >
2300 >    public void testAcceptEither_actionFailed2() {
2301 >        for (ExecutionMode m : ExecutionMode.values())
2302 >        for (Integer v1 : new Integer[] { 1, null })
2303 >        for (Integer v2 : new Integer[] { 2, null }) {
2304 >
2305 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
2306 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
2307 >        final FailingConsumer r = new FailingConsumer();
2308 >        final CompletableFuture<Void> h = m.acceptEither(f, g, r);
2309 >
2310 >        g.complete(v2);
2311 >        checkCompletedWithWrappedCFException(h);
2312 >        f.complete(v1);
2313 >        checkCompletedNormally(f, v1);
2314 >        checkCompletedNormally(g, v2);
2315 >        }
2316      }
2317  
2318      /**
2319       * acceptEither result completes exceptionally if either source cancelled
2320       */
2321 <    public void testAcceptEither4() {
2322 <        CompletableFuture<Integer> f = new CompletableFuture<>();
2323 <        CompletableFuture<Integer> f2 = new CompletableFuture<>();
2324 <        IncAction r = new IncAction();
2325 <        CompletableFuture<Void> g = f.acceptEither(f2, r);
2326 <        assertTrue(f.cancel(true));
2327 <        checkCompletedWithWrappedCancellationException(g);
2328 <        f = new CompletableFuture<>();
2329 <        f2 = new CompletableFuture<>();
2330 <        assertTrue(f2.cancel(true));
2331 <        checkCompletedWithWrappedCancellationException(g);
2321 >    public void testAcceptEither_sourceCancelled1() {
2322 >        for (ExecutionMode m : ExecutionMode.values())
2323 >        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
2324 >        for (Integer v1 : new Integer[] { 1, null }) {
2325 >
2326 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
2327 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
2328 >        final IncAction r = new IncAction();
2329 >        final CompletableFuture<Void> h = m.acceptEither(f, g, r);
2330 >
2331 >        assertTrue(f.cancel(mayInterruptIfRunning));
2332 >        checkCompletedWithWrappedCancellationException(h);
2333 >        g.complete(v1);
2334 >
2335 >        checkCancelled(f);
2336 >        assertEquals(r.invocationCount, 0);
2337 >        checkCompletedNormally(g, v1);
2338 >        checkCompletedWithWrappedCancellationException(h);
2339 >        }
2340 >    }
2341 >
2342 >    public void testAcceptEither_sourceCancelled2() {
2343 >        for (ExecutionMode m : ExecutionMode.values())
2344 >        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
2345 >        for (Integer v1 : new Integer[] { 1, null }) {
2346 >
2347 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
2348 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
2349 >        final IncAction r = new IncAction();
2350 >        final CompletableFuture<Void> h = m.acceptEither(f, g, r);
2351 >
2352 >        assertTrue(g.cancel(mayInterruptIfRunning));
2353 >        checkCompletedWithWrappedCancellationException(h);
2354 >        f.complete(v1);
2355 >
2356 >        checkCancelled(g);
2357 >        assertEquals(r.invocationCount, 0);
2358 >        checkCompletedNormally(f, v1);
2359 >        checkCompletedWithWrappedCancellationException(h);
2360 >        }
2361 >    }
2362 >
2363 >    public void testAcceptEither_sourceCancelled3() {
2364 >        for (ExecutionMode m : ExecutionMode.values())
2365 >        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
2366 >        for (Integer v1 : new Integer[] { 1, null }) {
2367 >
2368 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
2369 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
2370 >        final IncAction r = new IncAction();
2371 >
2372 >        assertTrue(g.cancel(mayInterruptIfRunning));
2373 >        f.complete(v1);
2374 >        final CompletableFuture<Void> h = m.acceptEither(f, g, r);
2375 >
2376 >        // unspecified behavior
2377 >        Integer v;
2378 >        try {
2379 >            assertEquals(h.join(), null);
2380 >            assertEquals(r.invocationCount, 1);
2381 >            assertEquals(inc(v1), r.value);
2382 >        } catch (CompletionException ok) {
2383 >            checkCompletedWithWrappedCancellationException(h);
2384 >            assertEquals(r.invocationCount, 0);
2385 >        }
2386 >
2387 >        checkCancelled(g);
2388 >        checkCompletedNormally(f, v1);
2389 >        }
2390 >    }
2391 >
2392 >    public void testAcceptEither_sourceCancelled4() {
2393 >        for (ExecutionMode m : ExecutionMode.values())
2394 >        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
2395 >        for (Integer v1 : new Integer[] { 1, null }) {
2396 >
2397 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
2398 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
2399 >        final IncAction r = new IncAction();
2400 >
2401 >        assertTrue(f.cancel(mayInterruptIfRunning));
2402 >        g.complete(v1);
2403 >        final CompletableFuture<Void> h = m.acceptEither(f, g, r);
2404 >
2405 >        // unspecified behavior
2406 >        Integer v;
2407 >        try {
2408 >            assertEquals(h.join(), null);
2409 >            assertEquals(r.invocationCount, 1);
2410 >            assertEquals(inc(v1), r.value);
2411 >        } catch (CompletionException ok) {
2412 >            checkCompletedWithWrappedCancellationException(h);
2413 >            assertEquals(r.invocationCount, 0);
2414 >        }
2415 >
2416 >        checkCancelled(f);
2417 >        checkCompletedNormally(g, v1);
2418 >        }
2419      }
2420  
2421      /**
2422       * runAfterEither result completes normally after normal completion
2423       * of either source
2424       */
2425 <    public void testRunAfterEither() {
2426 <        CompletableFuture<Integer> f = new CompletableFuture<>();
2427 <        CompletableFuture<Integer> f2 = new CompletableFuture<>();
2428 <        Noop r = new Noop();
1384 <        CompletableFuture<Void> g = f.runAfterEither(f2, r);
1385 <        f.complete(one);
1386 <        checkCompletedNormally(g, null);
1387 <        f2.complete(one);
1388 <        checkCompletedNormally(g, null);
1389 <        assertTrue(r.ran);
2425 >    public void testRunAfterEither_normalCompletion1() {
2426 >        for (ExecutionMode m : ExecutionMode.values())
2427 >        for (Integer v1 : new Integer[] { 1, null })
2428 >        for (Integer v2 : new Integer[] { 2, null }) {
2429  
2430 <        r = new Noop();
2431 <        f = new CompletableFuture<>();
2432 <        f.complete(one);
2433 <        f2 = new CompletableFuture<>();
2434 <        g = f.runAfterEither(f2, r);
2435 <        checkCompletedNormally(g, null);
2436 <        assertTrue(r.ran);
2430 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
2431 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
2432 >        final Noop r = new Noop();
2433 >        final CompletableFuture<Void> h = m.runAfterEither(f, g, r);
2434 >
2435 >        f.complete(v1);
2436 >        checkCompletedNormally(h, null);
2437 >        assertEquals(r.invocationCount, 1);
2438 >        g.complete(v2);
2439 >
2440 >        checkCompletedNormally(f, v1);
2441 >        checkCompletedNormally(g, v2);
2442 >        checkCompletedNormally(h, null);
2443 >        assertEquals(r.invocationCount, 1);
2444 >        }
2445 >    }
2446 >
2447 >    public void testRunAfterEither_normalCompletion2() {
2448 >        for (ExecutionMode m : ExecutionMode.values())
2449 >        for (Integer v1 : new Integer[] { 1, null })
2450 >        for (Integer v2 : new Integer[] { 2, null }) {
2451 >
2452 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
2453 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
2454 >        final Noop r = new Noop();
2455 >        final CompletableFuture<Void> h = m.runAfterEither(f, g, r);
2456 >
2457 >        g.complete(v2);
2458 >        checkCompletedNormally(h, null);
2459 >        assertEquals(r.invocationCount, 1);
2460 >        f.complete(v1);
2461 >
2462 >        checkCompletedNormally(f, v1);
2463 >        checkCompletedNormally(g, v2);
2464 >        checkCompletedNormally(h, null);
2465 >        assertEquals(r.invocationCount, 1);
2466 >        }
2467 >    }
2468 >    public void testRunAfterEither_normalCompletion3() {
2469 >        for (ExecutionMode m : ExecutionMode.values())
2470 >        for (Integer v1 : new Integer[] { 1, null })
2471 >        for (Integer v2 : new Integer[] { 2, null }) {
2472 >
2473 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
2474 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
2475 >        final Noop r = new Noop();
2476 >
2477 >        f.complete(v1);
2478 >        g.complete(v2);
2479 >        final CompletableFuture<Void> h = m.runAfterEither(f, g, r);
2480 >
2481 >        checkCompletedNormally(h, null);
2482 >        checkCompletedNormally(f, v1);
2483 >        checkCompletedNormally(g, v2);
2484 >        assertEquals(r.invocationCount, 1);
2485 >        }
2486      }
2487  
2488      /**
2489       * runAfterEither result completes exceptionally after exceptional
2490       * completion of either source
2491       */
2492 <    public void testRunAfterEither2() {
2493 <        CompletableFuture<Integer> f = new CompletableFuture<>();
2494 <        CompletableFuture<Integer> f2 = new CompletableFuture<>();
1407 <        Noop r = new Noop();
1408 <        CompletableFuture<Void> g = f.runAfterEither(f2, r);
1409 <        f.completeExceptionally(new CFException());
1410 <        f2.complete(one);
1411 <        checkCompletedWithWrappedCFException(g);
2492 >    public void testRunAfterEither_exceptionalCompletion1() {
2493 >        for (ExecutionMode m : ExecutionMode.values())
2494 >        for (Integer v1 : new Integer[] { 1, null }) {
2495  
2496 <        r = new Noop();
2497 <        f = new CompletableFuture<>();
2498 <        f2 = new CompletableFuture<>();
2499 <        f2.completeExceptionally(new CFException());
2500 <        g = f.runAfterEither(f2, r);
2501 <        checkCompletedWithWrappedCFException(g);
2496 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
2497 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
2498 >        final Noop r = new Noop();
2499 >        final CompletableFuture<Void> h = m.runAfterEither(f, g, r);
2500 >        final CFException ex = new CFException();
2501 >
2502 >        f.completeExceptionally(ex);
2503 >        checkCompletedWithWrappedCFException(h, ex);
2504 >        g.complete(v1);
2505 >
2506 >        assertEquals(r.invocationCount, 0);
2507 >        checkCompletedNormally(g, v1);
2508 >        checkCompletedWithWrappedCFException(f, ex);
2509 >        checkCompletedWithWrappedCFException(h, ex);
2510 >        }
2511 >    }
2512 >
2513 >    public void testRunAfterEither_exceptionalCompletion2() {
2514 >        for (ExecutionMode m : ExecutionMode.values())
2515 >        for (Integer v1 : new Integer[] { 1, null }) {
2516 >
2517 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
2518 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
2519 >        final Noop r = new Noop();
2520 >        final CompletableFuture<Void> h = m.runAfterEither(f, g, r);
2521 >        final CFException ex = new CFException();
2522 >
2523 >        g.completeExceptionally(ex);
2524 >        checkCompletedWithWrappedCFException(h, ex);
2525 >        f.complete(v1);
2526 >
2527 >        assertEquals(r.invocationCount, 0);
2528 >        checkCompletedNormally(f, v1);
2529 >        checkCompletedWithWrappedCFException(g, ex);
2530 >        checkCompletedWithWrappedCFException(h, ex);
2531 >        }
2532 >    }
2533 >
2534 >    public void testRunAfterEither_exceptionalCompletion3() {
2535 >        for (ExecutionMode m : ExecutionMode.values())
2536 >        for (Integer v1 : new Integer[] { 1, null }) {
2537 >
2538 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
2539 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
2540 >        final Noop r = new Noop();
2541 >        final CFException ex = new CFException();
2542 >
2543 >        g.completeExceptionally(ex);
2544 >        f.complete(v1);
2545 >        final CompletableFuture<Void> h = m.runAfterEither(f, g, r);
2546 >
2547 >        // unspecified behavior
2548 >        Integer v;
2549 >        try {
2550 >            assertEquals(h.join(), null);
2551 >            assertEquals(r.invocationCount, 1);
2552 >        } catch (CompletionException ok) {
2553 >            checkCompletedWithWrappedCFException(h, ex);
2554 >            assertEquals(r.invocationCount, 0);
2555 >        }
2556 >
2557 >        checkCompletedWithWrappedCFException(g, ex);
2558 >        checkCompletedNormally(f, v1);
2559 >        }
2560 >    }
2561 >
2562 >    public void testRunAfterEither_exceptionalCompletion4() {
2563 >        for (ExecutionMode m : ExecutionMode.values())
2564 >        for (Integer v1 : new Integer[] { 1, null }) {
2565 >
2566 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
2567 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
2568 >        final Noop r = new Noop();
2569 >        final CFException ex = new CFException();
2570 >
2571 >        f.completeExceptionally(ex);
2572 >        g.complete(v1);
2573 >        final CompletableFuture<Void> h = m.runAfterEither(f, g, r);
2574 >
2575 >        // unspecified behavior
2576 >        Integer v;
2577 >        try {
2578 >            assertEquals(h.join(), null);
2579 >            assertEquals(r.invocationCount, 1);
2580 >        } catch (CompletionException ok) {
2581 >            checkCompletedWithWrappedCFException(h, ex);
2582 >            assertEquals(r.invocationCount, 0);
2583 >        }
2584 >
2585 >        checkCompletedWithWrappedCFException(f, ex);
2586 >        checkCompletedNormally(g, v1);
2587 >        }
2588      }
2589  
2590      /**
2591       * runAfterEither result completes exceptionally if action does
2592       */
2593 <    public void testRunAfterEither3() {
2594 <        CompletableFuture<Integer> f = new CompletableFuture<>();
2595 <        CompletableFuture<Integer> f2 = new CompletableFuture<>();
2596 <        FailingNoop r = new FailingNoop();
2597 <        CompletableFuture<Void> g = f.runAfterEither(f2, r);
2598 <        f2.complete(two);
2599 <        checkCompletedWithWrappedCFException(g);
2593 >    public void testRunAfterEither_actionFailed1() {
2594 >        for (ExecutionMode m : ExecutionMode.values())
2595 >        for (Integer v1 : new Integer[] { 1, null })
2596 >        for (Integer v2 : new Integer[] { 2, null }) {
2597 >
2598 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
2599 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
2600 >        final FailingNoop r = new FailingNoop();
2601 >        final CompletableFuture<Void> h = m.runAfterEither(f, g, r);
2602 >
2603 >        f.complete(v1);
2604 >        checkCompletedWithWrappedCFException(h);
2605 >        g.complete(v2);
2606 >        checkCompletedNormally(f, v1);
2607 >        checkCompletedNormally(g, v2);
2608 >        }
2609 >    }
2610 >
2611 >    public void testRunAfterEither_actionFailed2() {
2612 >        for (ExecutionMode m : ExecutionMode.values())
2613 >        for (Integer v1 : new Integer[] { 1, null })
2614 >        for (Integer v2 : new Integer[] { 2, null }) {
2615 >
2616 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
2617 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
2618 >        final FailingNoop r = new FailingNoop();
2619 >        final CompletableFuture<Void> h = m.runAfterEither(f, g, r);
2620 >
2621 >        g.complete(v2);
2622 >        checkCompletedWithWrappedCFException(h);
2623 >        f.complete(v1);
2624 >        checkCompletedNormally(f, v1);
2625 >        checkCompletedNormally(g, v2);
2626 >        }
2627      }
2628  
2629      /**
2630       * runAfterEither result completes exceptionally if either source cancelled
2631       */
2632 <    public void testRunAfterEither4() {
2633 <        CompletableFuture<Integer> f = new CompletableFuture<>();
2634 <        CompletableFuture<Integer> f2 = new CompletableFuture<>();
2635 <        Noop r = new Noop();
2636 <        CompletableFuture<Void> g = f.runAfterEither(f2, r);
2637 <        assertTrue(f.cancel(true));
2638 <        checkCompletedWithWrappedCancellationException(g);
2639 <        f = new CompletableFuture<>();
2640 <        f2 = new CompletableFuture<>();
2641 <        assertTrue(f2.cancel(true));
2642 <        checkCompletedWithWrappedCancellationException(g);
2632 >    public void testRunAfterEither_sourceCancelled1() {
2633 >        for (ExecutionMode m : ExecutionMode.values())
2634 >        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
2635 >        for (Integer v1 : new Integer[] { 1, null }) {
2636 >
2637 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
2638 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
2639 >        final Noop r = new Noop();
2640 >        final CompletableFuture<Void> h = m.runAfterEither(f, g, r);
2641 >
2642 >        assertTrue(f.cancel(mayInterruptIfRunning));
2643 >        checkCompletedWithWrappedCancellationException(h);
2644 >        g.complete(v1);
2645 >
2646 >        checkCancelled(f);
2647 >        assertEquals(r.invocationCount, 0);
2648 >        checkCompletedNormally(g, v1);
2649 >        checkCompletedWithWrappedCancellationException(h);
2650 >        }
2651 >    }
2652 >
2653 >    public void testRunAfterEither_sourceCancelled2() {
2654 >        for (ExecutionMode m : ExecutionMode.values())
2655 >        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
2656 >        for (Integer v1 : new Integer[] { 1, null }) {
2657 >
2658 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
2659 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
2660 >        final Noop r = new Noop();
2661 >        final CompletableFuture<Void> h = m.runAfterEither(f, g, r);
2662 >
2663 >        assertTrue(g.cancel(mayInterruptIfRunning));
2664 >        checkCompletedWithWrappedCancellationException(h);
2665 >        f.complete(v1);
2666 >
2667 >        checkCancelled(g);
2668 >        assertEquals(r.invocationCount, 0);
2669 >        checkCompletedNormally(f, v1);
2670 >        checkCompletedWithWrappedCancellationException(h);
2671 >        }
2672 >    }
2673 >
2674 >    public void testRunAfterEither_sourceCancelled3() {
2675 >        for (ExecutionMode m : ExecutionMode.values())
2676 >        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
2677 >        for (Integer v1 : new Integer[] { 1, null }) {
2678 >
2679 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
2680 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
2681 >        final Noop r = new Noop();
2682 >
2683 >        assertTrue(g.cancel(mayInterruptIfRunning));
2684 >        f.complete(v1);
2685 >        final CompletableFuture<Void> h = m.runAfterEither(f, g, r);
2686 >
2687 >        // unspecified behavior
2688 >        Integer v;
2689 >        try {
2690 >            assertEquals(h.join(), null);
2691 >            assertEquals(r.invocationCount, 1);
2692 >        } catch (CompletionException ok) {
2693 >            checkCompletedWithWrappedCancellationException(h);
2694 >            assertEquals(r.invocationCount, 0);
2695 >        }
2696 >
2697 >        checkCancelled(g);
2698 >        checkCompletedNormally(f, v1);
2699 >        }
2700 >    }
2701 >
2702 >    public void testRunAfterEither_sourceCancelled4() {
2703 >        for (ExecutionMode m : ExecutionMode.values())
2704 >        for (boolean mayInterruptIfRunning : new boolean[] { true, false })
2705 >        for (Integer v1 : new Integer[] { 1, null }) {
2706 >
2707 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
2708 >        final CompletableFuture<Integer> g = new CompletableFuture<>();
2709 >        final Noop r = new Noop();
2710 >
2711 >        assertTrue(f.cancel(mayInterruptIfRunning));
2712 >        g.complete(v1);
2713 >        final CompletableFuture<Void> h = m.runAfterEither(f, g, r);
2714 >
2715 >        // unspecified behavior
2716 >        Integer v;
2717 >        try {
2718 >            assertEquals(h.join(), null);
2719 >            assertEquals(r.invocationCount, 1);
2720 >        } catch (CompletionException ok) {
2721 >            checkCompletedWithWrappedCancellationException(h);
2722 >            assertEquals(r.invocationCount, 0);
2723 >        }
2724 >
2725 >        checkCancelled(f);
2726 >        checkCompletedNormally(g, v1);
2727 >        }
2728      }
2729  
2730      /**
# Line 1631 | Line 2912 | public class CompletableFutureTest exten
2912          CompletableFuture<Void> g = f.thenAcceptAsync(r);
2913          f.complete(one);
2914          checkCompletedNormally(g, null);
2915 <        assertEquals(r.value, 2);
2915 >        assertEquals(r.value, (Integer) 2);
2916      }
2917  
2918      /**
# Line 1669 | Line 2950 | public class CompletableFutureTest exten
2950      }
2951  
2952      /**
1672     * thenCombineAsync result completes normally after normal
1673     * completion of sources
1674     */
1675    public void testThenCombineAsync() {
1676        CompletableFuture<Integer> f, g, h;
1677
1678        f = new CompletableFuture<>();
1679        g = new CompletableFuture<>();
1680        h = f.thenCombineAsync(g, subtract);
1681        f.complete(3);
1682        checkIncomplete(h);
1683        g.complete(1);
1684        checkCompletedNormally(h, 2);
1685
1686        f = new CompletableFuture<>();
1687        g = new CompletableFuture<>();
1688        h = f.thenCombineAsync(g, subtract);
1689        g.complete(1);
1690        checkIncomplete(h);
1691        f.complete(3);
1692        checkCompletedNormally(h, 2);
1693
1694        f = new CompletableFuture<>();
1695        g = new CompletableFuture<>();
1696        g.complete(1);
1697        f.complete(3);
1698        h = f.thenCombineAsync(g, subtract);
1699        checkCompletedNormally(h, 2);
1700    }
1701
1702    /**
1703     * thenCombineAsync result completes exceptionally after exceptional
1704     * completion of either source
1705     */
1706    public void testThenCombineAsync2() {
1707        CompletableFuture<Integer> f, g, h;
1708
1709        f = new CompletableFuture<>();
1710        g = new CompletableFuture<>();
1711        h = f.thenCombineAsync(g, subtract);
1712        f.completeExceptionally(new CFException());
1713        checkIncomplete(h);
1714        g.complete(1);
1715        checkCompletedWithWrappedCFException(h);
1716
1717        f = new CompletableFuture<>();
1718        g = new CompletableFuture<>();
1719        h = f.thenCombineAsync(g, subtract);
1720        g.completeExceptionally(new CFException());
1721        checkIncomplete(h);
1722        f.complete(3);
1723        checkCompletedWithWrappedCFException(h);
1724
1725        f = new CompletableFuture<>();
1726        g = new CompletableFuture<>();
1727        g.completeExceptionally(new CFException());
1728        f.complete(3);
1729        h = f.thenCombineAsync(g, subtract);
1730        checkCompletedWithWrappedCFException(h);
1731    }
1732
1733    /**
1734     * thenCombineAsync result completes exceptionally if action does
1735     */
1736    public void testThenCombineAsync3() {
1737        CompletableFuture<Integer> f = new CompletableFuture<>();
1738        CompletableFuture<Integer> f2 = new CompletableFuture<>();
1739        FailingBiFunction r = new FailingBiFunction();
1740        CompletableFuture<Integer> g = f.thenCombineAsync(f2, r);
1741        f.complete(one);
1742        checkIncomplete(g);
1743        assertFalse(r.ran);
1744        f2.complete(two);
1745        checkCompletedWithWrappedCFException(g);
1746        assertTrue(r.ran);
1747    }
1748
1749    /**
1750     * thenCombineAsync result completes exceptionally if either source cancelled
1751     */
1752    public void testThenCombineAsync4() {
1753        CompletableFuture<Integer> f, g, h;
1754
1755        f = new CompletableFuture<>();
1756        g = new CompletableFuture<>();
1757        h = f.thenCombineAsync(g, subtract);
1758        assertTrue(f.cancel(true));
1759        checkIncomplete(h);
1760        g.complete(1);
1761        checkCompletedWithWrappedCancellationException(h);
1762
1763        f = new CompletableFuture<>();
1764        g = new CompletableFuture<>();
1765        h = f.thenCombineAsync(g, subtract);
1766        assertTrue(g.cancel(true));
1767        checkIncomplete(h);
1768        f.complete(3);
1769        checkCompletedWithWrappedCancellationException(h);
1770
1771        f = new CompletableFuture<>();
1772        g = new CompletableFuture<>();
1773        g.complete(3);
1774        assertTrue(f.cancel(true));
1775        h = f.thenCombineAsync(g, subtract);
1776        checkCompletedWithWrappedCancellationException(h);
1777
1778        f = new CompletableFuture<>();
1779        g = new CompletableFuture<>();
1780        f.complete(3);
1781        assertTrue(g.cancel(true));
1782        h = f.thenCombineAsync(g, subtract);
1783        checkCompletedWithWrappedCancellationException(h);
1784    }
1785
1786    /**
1787     * thenAcceptBothAsync result completes normally after normal
1788     * completion of sources
1789     */
1790    public void testThenAcceptBothAsync() {
1791        CompletableFuture<Integer> f, g;
1792        CompletableFuture<Void> h;
1793        SubtractAction r;
1794
1795        f = new CompletableFuture<>();
1796        g = new CompletableFuture<>();
1797        h = f.thenAcceptBothAsync(g, r = new SubtractAction());
1798        f.complete(3);
1799        checkIncomplete(h);
1800        g.complete(1);
1801        checkCompletedNormally(h, null);
1802        assertEquals(r.value, 2);
1803
1804        f = new CompletableFuture<>();
1805        g = new CompletableFuture<>();
1806        h = f.thenAcceptBothAsync(g, r = new SubtractAction());
1807        g.complete(1);
1808        checkIncomplete(h);
1809        f.complete(3);
1810        checkCompletedNormally(h, null);
1811        assertEquals(r.value, 2);
1812
1813        f = new CompletableFuture<>();
1814        g = new CompletableFuture<>();
1815        g.complete(1);
1816        f.complete(3);
1817        h = f.thenAcceptBothAsync(g, r = new SubtractAction());
1818        checkCompletedNormally(h, null);
1819        assertEquals(r.value, 2);
1820    }
1821
1822    /**
1823     * thenAcceptBothAsync result completes exceptionally after exceptional
1824     * completion of source
1825     */
1826    public void testThenAcceptBothAsync2() {
1827        CompletableFuture<Integer> f, g;
1828        CompletableFuture<Void> h;
1829        SubtractAction r;
1830
1831        f = new CompletableFuture<>();
1832        g = new CompletableFuture<>();
1833        h = f.thenAcceptBothAsync(g, r = new SubtractAction());
1834        f.completeExceptionally(new CFException());
1835        checkIncomplete(h);
1836        g.complete(1);
1837        checkCompletedWithWrappedCFException(h);
1838
1839        f = new CompletableFuture<>();
1840        g = new CompletableFuture<>();
1841        h = f.thenAcceptBothAsync(g, r = new SubtractAction());
1842        g.completeExceptionally(new CFException());
1843        checkIncomplete(h);
1844        f.complete(3);
1845        checkCompletedWithWrappedCFException(h);
1846
1847        f = new CompletableFuture<>();
1848        g = new CompletableFuture<>();
1849        f.complete(3);
1850        g.completeExceptionally(new CFException());
1851        h = f.thenAcceptBothAsync(g, r = new SubtractAction());
1852        checkCompletedWithWrappedCFException(h);
1853
1854        f = new CompletableFuture<>();
1855        g = new CompletableFuture<>();
1856        f.completeExceptionally(new CFException());
1857        g.complete(3);
1858        h = f.thenAcceptBothAsync(g, r = new SubtractAction());
1859        checkCompletedWithWrappedCFException(h);
1860    }
1861
1862    /**
1863     * thenAcceptBothAsync result completes exceptionally if action does
1864     */
1865    public void testThenAcceptBothAsync3() {
1866        CompletableFuture<Integer> f, g;
1867        CompletableFuture<Void> h;
1868        FailingBiConsumer r;
1869
1870        f = new CompletableFuture<>();
1871        g = new CompletableFuture<>();
1872        h = f.thenAcceptBothAsync(g, r = new FailingBiConsumer());
1873        f.complete(3);
1874        checkIncomplete(h);
1875        g.complete(1);
1876        checkCompletedWithWrappedCFException(h);
1877
1878        f = new CompletableFuture<>();
1879        g = new CompletableFuture<>();
1880        f.complete(3);
1881        g.complete(1);
1882        h = f.thenAcceptBothAsync(g, r = new FailingBiConsumer());
1883        checkCompletedWithWrappedCFException(h);
1884    }
1885
1886    /**
1887     * thenAcceptBothAsync result completes exceptionally if either source cancelled
1888     */
1889    public void testThenAcceptBothAsync4() {
1890        CompletableFuture<Integer> f, g;
1891        CompletableFuture<Void> h;
1892        SubtractAction r;
1893
1894        f = new CompletableFuture<>();
1895        g = new CompletableFuture<>();
1896        h = f.thenAcceptBothAsync(g, r = new SubtractAction());
1897        assertTrue(f.cancel(true));
1898        checkIncomplete(h);
1899        g.complete(1);
1900        checkCompletedWithWrappedCancellationException(h);
1901
1902        f = new CompletableFuture<>();
1903        g = new CompletableFuture<>();
1904        h = f.thenAcceptBothAsync(g, r = new SubtractAction());
1905        assertTrue(g.cancel(true));
1906        checkIncomplete(h);
1907        f.complete(3);
1908        checkCompletedWithWrappedCancellationException(h);
1909
1910        f = new CompletableFuture<>();
1911        g = new CompletableFuture<>();
1912        f.complete(3);
1913        assertTrue(g.cancel(true));
1914        h = f.thenAcceptBothAsync(g, r = new SubtractAction());
1915        checkCompletedWithWrappedCancellationException(h);
1916
1917        f = new CompletableFuture<>();
1918        g = new CompletableFuture<>();
1919        assertTrue(f.cancel(true));
1920        g.complete(3);
1921        h = f.thenAcceptBothAsync(g, r = new SubtractAction());
1922        checkCompletedWithWrappedCancellationException(h);
1923    }
1924
1925    /**
1926     * runAfterBothAsync result completes normally after normal
1927     * completion of sources
1928     */
1929    public void testRunAfterBothAsync() {
1930        CompletableFuture<Integer> f = new CompletableFuture<>();
1931        CompletableFuture<Integer> f2 = new CompletableFuture<>();
1932        Noop r = new Noop();
1933        CompletableFuture<Void> g = f.runAfterBothAsync(f2, r);
1934        f.complete(one);
1935        checkIncomplete(g);
1936        f2.complete(two);
1937        checkCompletedNormally(g, null);
1938        assertTrue(r.ran);
1939    }
1940
1941    /**
1942     * runAfterBothAsync result completes exceptionally after exceptional
1943     * completion of source
1944     */
1945    public void testRunAfterBothAsync2() {
1946        CompletableFuture<Integer> f = new CompletableFuture<>();
1947        CompletableFuture<Integer> f2 = new CompletableFuture<>();
1948        Noop r = new Noop();
1949        CompletableFuture<Void> g = f.runAfterBothAsync(f2, r);
1950        f.completeExceptionally(new CFException());
1951        f2.complete(two);
1952        checkCompletedWithWrappedCFException(g);
1953
1954        r = new Noop();
1955        f = new CompletableFuture<>();
1956        f2 = new CompletableFuture<>();
1957        g = f.runAfterBothAsync(f2, r);
1958        f.complete(one);
1959        f2.completeExceptionally(new CFException());
1960        checkCompletedWithWrappedCFException(g);
1961    }
1962
1963    /**
1964     * runAfterBothAsync result completes exceptionally if action does
1965     */
1966    public void testRunAfterBothAsync3() {
1967        CompletableFuture<Integer> f = new CompletableFuture<>();
1968        CompletableFuture<Integer> f2 = new CompletableFuture<>();
1969        FailingNoop r = new FailingNoop();
1970        CompletableFuture<Void> g = f.runAfterBothAsync(f2, r);
1971        f.complete(one);
1972        checkIncomplete(g);
1973        f2.complete(two);
1974        checkCompletedWithWrappedCFException(g);
1975    }
1976
1977    /**
1978     * runAfterBothAsync result completes exceptionally if either source cancelled
1979     */
1980    public void testRunAfterBothAsync4() {
1981        CompletableFuture<Integer> f = new CompletableFuture<>();
1982        CompletableFuture<Integer> f2 = new CompletableFuture<>();
1983        Noop r = new Noop();
1984        CompletableFuture<Void> g = f.runAfterBothAsync(f2, r);
1985        assertTrue(f.cancel(true));
1986        f2.complete(two);
1987        checkCompletedWithWrappedCancellationException(g);
1988
1989        r = new Noop();
1990        f = new CompletableFuture<>();
1991        f2 = new CompletableFuture<>();
1992        g = f.runAfterBothAsync(f2, r);
1993        f.complete(one);
1994        assertTrue(f2.cancel(true));
1995        checkCompletedWithWrappedCancellationException(g);
1996    }
1997
1998    /**
1999     * applyToEitherAsync result completes normally after normal
2000     * completion of sources
2001     */
2002    public void testApplyToEitherAsync() {
2003        CompletableFuture<Integer> f = new CompletableFuture<>();
2004        CompletableFuture<Integer> f2 = new CompletableFuture<>();
2005        CompletableFuture<Integer> g = f.applyToEitherAsync(f2, inc);
2006        f.complete(one);
2007        checkCompletedNormally(g, two);
2008
2009        f = new CompletableFuture<>();
2010        f.complete(one);
2011        f2 = new CompletableFuture<>();
2012        g = f.applyToEitherAsync(f2, inc);
2013        checkCompletedNormally(g, two);
2014    }
2015
2016    /**
2017     * applyToEitherAsync result completes exceptionally after exceptional
2018     * completion of source
2019     */
2020    public void testApplyToEitherAsync2() {
2021        CompletableFuture<Integer> f = new CompletableFuture<>();
2022        CompletableFuture<Integer> f2 = new CompletableFuture<>();
2023        CompletableFuture<Integer> g = f.applyToEitherAsync(f2, inc);
2024        f.completeExceptionally(new CFException());
2025        checkCompletedWithWrappedCFException(g);
2026
2027        f = new CompletableFuture<>();
2028        f2 = new CompletableFuture<>();
2029        f2.completeExceptionally(new CFException());
2030        g = f.applyToEitherAsync(f2, inc);
2031        f.complete(one);
2032        checkCompletedWithWrappedCFException(g);
2033    }
2034
2035    /**
2036     * applyToEitherAsync result completes exceptionally if action does
2037     */
2038    public void testApplyToEitherAsync3() {
2039        CompletableFuture<Integer> f = new CompletableFuture<>();
2040        CompletableFuture<Integer> f2 = new CompletableFuture<>();
2041        FailingFunction r = new FailingFunction();
2042        CompletableFuture<Integer> g = f.applyToEitherAsync(f2, r);
2043        f.complete(one);
2044        checkCompletedWithWrappedCFException(g);
2045    }
2046
2047    /**
2048     * applyToEitherAsync result completes exceptionally if either source cancelled
2049     */
2050    public void testApplyToEitherAsync4() {
2051        CompletableFuture<Integer> f = new CompletableFuture<>();
2052        CompletableFuture<Integer> f2 = new CompletableFuture<>();
2053        CompletableFuture<Integer> g = f.applyToEitherAsync(f2, inc);
2054        assertTrue(f.cancel(true));
2055        checkCompletedWithWrappedCancellationException(g);
2056
2057        f = new CompletableFuture<>();
2058        f2 = new CompletableFuture<>();
2059        assertTrue(f2.cancel(true));
2060        g = f.applyToEitherAsync(f2, inc);
2061        checkCompletedWithWrappedCancellationException(g);
2062    }
2063
2064    /**
2065     * acceptEitherAsync result completes normally after normal
2066     * completion of sources
2067     */
2068    public void testAcceptEitherAsync() {
2069        CompletableFuture<Integer> f = new CompletableFuture<>();
2070        CompletableFuture<Integer> f2 = new CompletableFuture<>();
2071        IncAction r = new IncAction();
2072        CompletableFuture<Void> g = f.acceptEitherAsync(f2, r);
2073        f.complete(one);
2074        checkCompletedNormally(g, null);
2075        assertEquals(r.value, 2);
2076
2077        r = new IncAction();
2078        f = new CompletableFuture<>();
2079        f.complete(one);
2080        f2 = new CompletableFuture<>();
2081        g = f.acceptEitherAsync(f2, r);
2082        checkCompletedNormally(g, null);
2083        assertEquals(r.value, 2);
2084    }
2085
2086    /**
2087     * acceptEitherAsync result completes exceptionally after exceptional
2088     * completion of source
2089     */
2090    public void testAcceptEitherAsync2() {
2091        CompletableFuture<Integer> f = new CompletableFuture<>();
2092        CompletableFuture<Integer> f2 = new CompletableFuture<>();
2093        IncAction r = new IncAction();
2094        CompletableFuture<Void> g = f.acceptEitherAsync(f2, r);
2095        f.completeExceptionally(new CFException());
2096        checkCompletedWithWrappedCFException(g);
2097
2098        r = new IncAction();
2099        f = new CompletableFuture<>();
2100        f2 = new CompletableFuture<>();
2101        f2.completeExceptionally(new CFException());
2102        g = f.acceptEitherAsync(f2, r);
2103        f.complete(one);
2104        checkCompletedWithWrappedCFException(g);
2105    }
2106
2107    /**
2108     * acceptEitherAsync result completes exceptionally if action does
2109     */
2110    public void testAcceptEitherAsync3() {
2111        CompletableFuture<Integer> f = new CompletableFuture<>();
2112        CompletableFuture<Integer> f2 = new CompletableFuture<>();
2113        FailingConsumer r = new FailingConsumer();
2114        CompletableFuture<Void> g = f.acceptEitherAsync(f2, r);
2115        f.complete(one);
2116        checkCompletedWithWrappedCFException(g);
2117    }
2118
2119    /**
2120     * acceptEitherAsync result completes exceptionally if either
2121     * source cancelled
2122     */
2123    public void testAcceptEitherAsync4() {
2124        CompletableFuture<Integer> f = new CompletableFuture<>();
2125        CompletableFuture<Integer> f2 = new CompletableFuture<>();
2126        IncAction r = new IncAction();
2127        CompletableFuture<Void> g = f.acceptEitherAsync(f2, r);
2128        assertTrue(f.cancel(true));
2129        checkCompletedWithWrappedCancellationException(g);
2130
2131        r = new IncAction();
2132        f = new CompletableFuture<>();
2133        f2 = new CompletableFuture<>();
2134        assertTrue(f2.cancel(true));
2135        g = f.acceptEitherAsync(f2, r);
2136        checkCompletedWithWrappedCancellationException(g);
2137    }
2138
2139    /**
2140     * runAfterEitherAsync result completes normally after normal
2141     * completion of sources
2142     */
2143    public void testRunAfterEitherAsync() {
2144        CompletableFuture<Integer> f = new CompletableFuture<>();
2145        CompletableFuture<Integer> f2 = new CompletableFuture<>();
2146        Noop r = new Noop();
2147        CompletableFuture<Void> g = f.runAfterEitherAsync(f2, r);
2148        f.complete(one);
2149        checkCompletedNormally(g, null);
2150        assertTrue(r.ran);
2151
2152        r = new Noop();
2153        f = new CompletableFuture<>();
2154        f.complete(one);
2155        f2 = new CompletableFuture<>();
2156        g = f.runAfterEitherAsync(f2, r);
2157        checkCompletedNormally(g, null);
2158        assertTrue(r.ran);
2159    }
2160
2161    /**
2162     * runAfterEitherAsync result completes exceptionally after exceptional
2163     * completion of source
2164     */
2165    public void testRunAfterEitherAsync2() {
2166        CompletableFuture<Integer> f = new CompletableFuture<>();
2167        CompletableFuture<Integer> f2 = new CompletableFuture<>();
2168        Noop r = new Noop();
2169        CompletableFuture<Void> g = f.runAfterEitherAsync(f2, r);
2170        f.completeExceptionally(new CFException());
2171        checkCompletedWithWrappedCFException(g);
2172
2173        r = new Noop();
2174        f = new CompletableFuture<>();
2175        f2 = new CompletableFuture<>();
2176        f2.completeExceptionally(new CFException());
2177        g = f.runAfterEitherAsync(f2, r);
2178        f.complete(one);
2179        checkCompletedWithWrappedCFException(g);
2180    }
2181
2182    /**
2183     * runAfterEitherAsync result completes exceptionally if action does
2184     */
2185    public void testRunAfterEitherAsync3() {
2186        CompletableFuture<Integer> f = new CompletableFuture<>();
2187        CompletableFuture<Integer> f2 = new CompletableFuture<>();
2188        FailingNoop r = new FailingNoop();
2189        CompletableFuture<Void> g = f.runAfterEitherAsync(f2, r);
2190        f.complete(one);
2191        checkCompletedWithWrappedCFException(g);
2192    }
2193
2194    /**
2195     * runAfterEitherAsync result completes exceptionally if either
2196     * source cancelled
2197     */
2198    public void testRunAfterEitherAsync4() {
2199        CompletableFuture<Integer> f = new CompletableFuture<>();
2200        CompletableFuture<Integer> f2 = new CompletableFuture<>();
2201        Noop r = new Noop();
2202        CompletableFuture<Void> g = f.runAfterEitherAsync(f2, r);
2203        assertTrue(f.cancel(true));
2204        checkCompletedWithWrappedCancellationException(g);
2205
2206        r = new Noop();
2207        f = new CompletableFuture<>();
2208        f2 = new CompletableFuture<>();
2209        assertTrue(f2.cancel(true));
2210        g = f.runAfterEitherAsync(f2, r);
2211        checkCompletedWithWrappedCancellationException(g);
2212    }
2213
2214    /**
2953       * thenComposeAsync result completes normally after normal
2954       * completion of source
2955       */
# Line 2397 | Line 3135 | public class CompletableFutureTest exten
3135          CompletableFuture<Void> g = f.thenAcceptAsync(r, new ThreadExecutor());
3136          f.complete(one);
3137          checkCompletedNormally(g, null);
3138 <        assertEquals(r.value, 2);
3138 >        assertEquals(r.value, (Integer) 2);
3139      }
3140  
3141      /**
# Line 2435 | Line 3173 | public class CompletableFutureTest exten
3173      }
3174  
3175      /**
2438     * thenCombineAsync result completes normally after normal
2439     * completion of sources
2440     */
2441    public void testThenCombineAsyncE() {
2442        CompletableFuture<Integer> f, g, h;
2443        ThreadExecutor e = new ThreadExecutor();
2444        int count = 0;
2445
2446        f = new CompletableFuture<>();
2447        g = new CompletableFuture<>();
2448        h = f.thenCombineAsync(g, subtract, e);
2449        f.complete(3);
2450        checkIncomplete(h);
2451        g.complete(1);
2452        checkCompletedNormally(h, 2);
2453        assertEquals(++count, e.count.get());
2454
2455        f = new CompletableFuture<>();
2456        g = new CompletableFuture<>();
2457        h = f.thenCombineAsync(g, subtract, e);
2458        g.complete(1);
2459        checkIncomplete(h);
2460        f.complete(3);
2461        checkCompletedNormally(h, 2);
2462        assertEquals(++count, e.count.get());
2463
2464        f = new CompletableFuture<>();
2465        g = new CompletableFuture<>();
2466        g.complete(1);
2467        f.complete(3);
2468        h = f.thenCombineAsync(g, subtract, e);
2469        checkCompletedNormally(h, 2);
2470        assertEquals(++count, e.count.get());
2471    }
2472
2473    /**
2474     * thenCombineAsync result completes exceptionally after exceptional
2475     * completion of either source
2476     */
2477    public void testThenCombineAsync2E() {
2478        CompletableFuture<Integer> f, g, h;
2479        ThreadExecutor e = new ThreadExecutor();
2480        int count = 0;
2481
2482        f = new CompletableFuture<>();
2483        g = new CompletableFuture<>();
2484        h = f.thenCombineAsync(g, subtract, e);
2485        f.completeExceptionally(new CFException());
2486        checkIncomplete(h);
2487        g.complete(1);
2488        checkCompletedWithWrappedCFException(h);
2489
2490        f = new CompletableFuture<>();
2491        g = new CompletableFuture<>();
2492        h = f.thenCombineAsync(g, subtract, e);
2493        g.completeExceptionally(new CFException());
2494        checkIncomplete(h);
2495        f.complete(3);
2496        checkCompletedWithWrappedCFException(h);
2497
2498        f = new CompletableFuture<>();
2499        g = new CompletableFuture<>();
2500        g.completeExceptionally(new CFException());
2501        h = f.thenCombineAsync(g, subtract, e);
2502        checkIncomplete(h);
2503        f.complete(3);
2504        checkCompletedWithWrappedCFException(h);
2505
2506        assertEquals(0, e.count.get());
2507    }
2508
2509    /**
2510     * thenCombineAsync result completes exceptionally if action does
2511     */
2512    public void testThenCombineAsync3E() {
2513        CompletableFuture<Integer> f = new CompletableFuture<>();
2514        CompletableFuture<Integer> f2 = new CompletableFuture<>();
2515        FailingBiFunction r = new FailingBiFunction();
2516        CompletableFuture<Integer> g = f.thenCombineAsync(f2, r, new ThreadExecutor());
2517        f.complete(one);
2518        checkIncomplete(g);
2519        assertFalse(r.ran);
2520        f2.complete(two);
2521        checkCompletedWithWrappedCFException(g);
2522        assertTrue(r.ran);
2523    }
2524
2525    /**
2526     * thenCombineAsync result completes exceptionally if either source cancelled
2527     */
2528    public void testThenCombineAsync4E() {
2529        CompletableFuture<Integer> f, g, h;
2530        ThreadExecutor e = new ThreadExecutor();
2531
2532        f = new CompletableFuture<>();
2533        g = new CompletableFuture<>();
2534        h = f.thenCombineAsync(g, subtract, e);
2535        assertTrue(f.cancel(true));
2536        checkIncomplete(h);
2537        g.complete(1);
2538        checkCompletedWithWrappedCancellationException(h);
2539
2540        f = new CompletableFuture<>();
2541        g = new CompletableFuture<>();
2542        h = f.thenCombineAsync(g, subtract, e);
2543        assertTrue(g.cancel(true));
2544        checkIncomplete(h);
2545        f.complete(3);
2546        checkCompletedWithWrappedCancellationException(h);
2547
2548        f = new CompletableFuture<>();
2549        g = new CompletableFuture<>();
2550        assertTrue(g.cancel(true));
2551        h = f.thenCombineAsync(g, subtract, e);
2552        checkIncomplete(h);
2553        f.complete(3);
2554        checkCompletedWithWrappedCancellationException(h);
2555
2556        f = new CompletableFuture<>();
2557        g = new CompletableFuture<>();
2558        assertTrue(f.cancel(true));
2559        assertTrue(g.cancel(true));
2560        h = f.thenCombineAsync(g, subtract, e);
2561        checkCompletedWithWrappedCancellationException(h);
2562
2563        assertEquals(0, e.count.get());
2564    }
2565
2566    /**
2567     * thenAcceptBothAsync result completes normally after normal
2568     * completion of sources
2569     */
2570    public void testThenAcceptBothAsyncE() {
2571        CompletableFuture<Integer> f, g;
2572        CompletableFuture<Void> h;
2573        SubtractAction r;
2574        ThreadExecutor e = new ThreadExecutor();
2575
2576        f = new CompletableFuture<>();
2577        g = new CompletableFuture<>();
2578        h = f.thenAcceptBothAsync(g, r = new SubtractAction(), e);
2579        f.complete(3);
2580        checkIncomplete(h);
2581        g.complete(1);
2582        checkCompletedNormally(h, null);
2583        assertEquals(r.value, 2);
2584
2585        f = new CompletableFuture<>();
2586        g = new CompletableFuture<>();
2587        h = f.thenAcceptBothAsync(g, r = new SubtractAction(), e);
2588        g.complete(1);
2589        checkIncomplete(h);
2590        f.complete(3);
2591        checkCompletedNormally(h, null);
2592        assertEquals(r.value, 2);
2593
2594        f = new CompletableFuture<>();
2595        g = new CompletableFuture<>();
2596        g.complete(1);
2597        f.complete(3);
2598        h = f.thenAcceptBothAsync(g, r = new SubtractAction(), e);
2599        checkCompletedNormally(h, null);
2600        assertEquals(r.value, 2);
2601
2602        assertEquals(3, e.count.get());
2603    }
2604
2605    /**
2606     * thenAcceptBothAsync result completes exceptionally after exceptional
2607     * completion of source
2608     */
2609    public void testThenAcceptBothAsync2E() {
2610        CompletableFuture<Integer> f, g;
2611        CompletableFuture<Void> h;
2612        SubtractAction r;
2613        ThreadExecutor e = new ThreadExecutor();
2614
2615        f = new CompletableFuture<>();
2616        g = new CompletableFuture<>();
2617        h = f.thenAcceptBothAsync(g, r = new SubtractAction(), e);
2618        f.completeExceptionally(new CFException());
2619        checkIncomplete(h);
2620        g.complete(1);
2621        checkCompletedWithWrappedCFException(h);
2622
2623        f = new CompletableFuture<>();
2624        g = new CompletableFuture<>();
2625        h = f.thenAcceptBothAsync(g, r = new SubtractAction(), e);
2626        g.completeExceptionally(new CFException());
2627        checkIncomplete(h);
2628        f.complete(3);
2629        checkCompletedWithWrappedCFException(h);
2630
2631        f = new CompletableFuture<>();
2632        g = new CompletableFuture<>();
2633        f.complete(3);
2634        g.completeExceptionally(new CFException());
2635        h = f.thenAcceptBothAsync(g, r = new SubtractAction(), e);
2636        checkCompletedWithWrappedCFException(h);
2637
2638        f = new CompletableFuture<>();
2639        g = new CompletableFuture<>();
2640        f.completeExceptionally(new CFException());
2641        g.complete(3);
2642        h = f.thenAcceptBothAsync(g, r = new SubtractAction(), e);
2643        checkCompletedWithWrappedCFException(h);
2644
2645        assertEquals(0, e.count.get());
2646    }
2647
2648    /**
2649     * thenAcceptBothAsync result completes exceptionally if action does
2650     */
2651    public void testThenAcceptBothAsync3E() {
2652        CompletableFuture<Integer> f, g;
2653        CompletableFuture<Void> h;
2654        FailingBiConsumer r;
2655        ThreadExecutor e = new ThreadExecutor();
2656
2657        f = new CompletableFuture<>();
2658        g = new CompletableFuture<>();
2659        h = f.thenAcceptBothAsync(g, r = new FailingBiConsumer(), e);
2660        f.complete(3);
2661        checkIncomplete(h);
2662        g.complete(1);
2663        checkCompletedWithWrappedCFException(h);
2664
2665        f = new CompletableFuture<>();
2666        g = new CompletableFuture<>();
2667        f.complete(3);
2668        g.complete(1);
2669        h = f.thenAcceptBothAsync(g, r = new FailingBiConsumer(), e);
2670        checkCompletedWithWrappedCFException(h);
2671
2672        assertEquals(2, e.count.get());
2673    }
2674
2675    /**
2676     * thenAcceptBothAsync result completes exceptionally if either source cancelled
2677     */
2678    public void testThenAcceptBothAsync4E() {
2679        CompletableFuture<Integer> f, g;
2680        CompletableFuture<Void> h;
2681        SubtractAction r;
2682        ThreadExecutor e = new ThreadExecutor();
2683
2684        f = new CompletableFuture<>();
2685        g = new CompletableFuture<>();
2686        h = f.thenAcceptBothAsync(g, r = new SubtractAction(), e);
2687        assertTrue(f.cancel(true));
2688        checkIncomplete(h);
2689        g.complete(1);
2690        checkCompletedWithWrappedCancellationException(h);
2691
2692        f = new CompletableFuture<>();
2693        g = new CompletableFuture<>();
2694        h = f.thenAcceptBothAsync(g, r = new SubtractAction(), e);
2695        assertTrue(g.cancel(true));
2696        checkIncomplete(h);
2697        f.complete(3);
2698        checkCompletedWithWrappedCancellationException(h);
2699
2700        f = new CompletableFuture<>();
2701        g = new CompletableFuture<>();
2702        f.complete(3);
2703        assertTrue(g.cancel(true));
2704        h = f.thenAcceptBothAsync(g, r = new SubtractAction(), e);
2705        checkCompletedWithWrappedCancellationException(h);
2706
2707        f = new CompletableFuture<>();
2708        g = new CompletableFuture<>();
2709        assertTrue(f.cancel(true));
2710        g.complete(3);
2711        h = f.thenAcceptBothAsync(g, r = new SubtractAction(), e);
2712        checkCompletedWithWrappedCancellationException(h);
2713
2714        assertEquals(0, e.count.get());
2715    }
2716
2717    /**
2718     * runAfterBothAsync result completes normally after normal
2719     * completion of sources
2720     */
2721    public void testRunAfterBothAsyncE() {
2722        CompletableFuture<Integer> f = new CompletableFuture<>();
2723        CompletableFuture<Integer> f2 = new CompletableFuture<>();
2724        Noop r = new Noop();
2725        CompletableFuture<Void> g = f.runAfterBothAsync(f2, r, new ThreadExecutor());
2726        f.complete(one);
2727        checkIncomplete(g);
2728        f2.complete(two);
2729        checkCompletedNormally(g, null);
2730        assertTrue(r.ran);
2731    }
2732
2733    /**
2734     * runAfterBothAsync result completes exceptionally after exceptional
2735     * completion of source
2736     */
2737    public void testRunAfterBothAsync2E() {
2738        CompletableFuture<Integer> f = new CompletableFuture<>();
2739        CompletableFuture<Integer> f2 = new CompletableFuture<>();
2740        Noop r = new Noop();
2741        CompletableFuture<Void> g = f.runAfterBothAsync(f2, r, new ThreadExecutor());
2742        f.completeExceptionally(new CFException());
2743        f2.complete(two);
2744        checkCompletedWithWrappedCFException(g);
2745
2746        r = new Noop();
2747        f = new CompletableFuture<>();
2748        f2 = new CompletableFuture<>();
2749        g = f.runAfterBothAsync(f2, r, new ThreadExecutor());
2750        f.complete(one);
2751        f2.completeExceptionally(new CFException());
2752        checkCompletedWithWrappedCFException(g);
2753    }
2754
2755    /**
2756     * runAfterBothAsync result completes exceptionally if action does
2757     */
2758    public void testRunAfterBothAsync3E() {
2759        CompletableFuture<Integer> f = new CompletableFuture<>();
2760        CompletableFuture<Integer> f2 = new CompletableFuture<>();
2761        FailingNoop r = new FailingNoop();
2762        CompletableFuture<Void> g = f.runAfterBothAsync(f2, r, new ThreadExecutor());
2763        f.complete(one);
2764        checkIncomplete(g);
2765        f2.complete(two);
2766        checkCompletedWithWrappedCFException(g);
2767    }
2768
2769    /**
2770     * runAfterBothAsync result completes exceptionally if either source cancelled
2771     */
2772    public void testRunAfterBothAsync4E() {
2773        CompletableFuture<Integer> f = new CompletableFuture<>();
2774        CompletableFuture<Integer> f2 = new CompletableFuture<>();
2775        Noop r = new Noop();
2776        CompletableFuture<Void> g = f.runAfterBothAsync(f2, r, new ThreadExecutor());
2777        assertTrue(f.cancel(true));
2778        f2.complete(two);
2779        checkCompletedWithWrappedCancellationException(g);
2780
2781        r = new Noop();
2782        f = new CompletableFuture<>();
2783        f2 = new CompletableFuture<>();
2784        g = f.runAfterBothAsync(f2, r, new ThreadExecutor());
2785        f.complete(one);
2786        assertTrue(f2.cancel(true));
2787        checkCompletedWithWrappedCancellationException(g);
2788    }
2789
2790    /**
2791     * applyToEitherAsync result completes normally after normal
2792     * completion of sources
2793     */
2794    public void testApplyToEitherAsyncE() {
2795        CompletableFuture<Integer> f = new CompletableFuture<>();
2796        CompletableFuture<Integer> f2 = new CompletableFuture<>();
2797        CompletableFuture<Integer> g = f.applyToEitherAsync(f2, inc, new ThreadExecutor());
2798        f.complete(one);
2799        checkCompletedNormally(g, two);
2800
2801        f = new CompletableFuture<>();
2802        f.complete(one);
2803        f2 = new CompletableFuture<>();
2804        g = f.applyToEitherAsync(f2, inc, new ThreadExecutor());
2805        checkCompletedNormally(g, two);
2806    }
2807
2808    /**
2809     * applyToEitherAsync result completes exceptionally after exceptional
2810     * completion of source
2811     */
2812    public void testApplyToEitherAsync2E() {
2813        CompletableFuture<Integer> f = new CompletableFuture<>();
2814        CompletableFuture<Integer> f2 = new CompletableFuture<>();
2815        CompletableFuture<Integer> g = f.applyToEitherAsync(f2, inc, new ThreadExecutor());
2816        f.completeExceptionally(new CFException());
2817        checkCompletedWithWrappedCFException(g);
2818
2819        f = new CompletableFuture<>();
2820        f2 = new CompletableFuture<>();
2821        f2.completeExceptionally(new CFException());
2822        g = f.applyToEitherAsync(f2, inc, new ThreadExecutor());
2823        f.complete(one);
2824        checkCompletedWithWrappedCFException(g);
2825    }
2826
2827    /**
2828     * applyToEitherAsync result completes exceptionally if action does
2829     */
2830    public void testApplyToEitherAsync3E() {
2831        CompletableFuture<Integer> f = new CompletableFuture<>();
2832        CompletableFuture<Integer> f2 = new CompletableFuture<>();
2833        FailingFunction r = new FailingFunction();
2834        CompletableFuture<Integer> g = f.applyToEitherAsync(f2, r, new ThreadExecutor());
2835        f.complete(one);
2836        checkCompletedWithWrappedCFException(g);
2837    }
2838
2839    /**
2840     * applyToEitherAsync result completes exceptionally if either source cancelled
2841     */
2842    public void testApplyToEitherAsync4E() {
2843        CompletableFuture<Integer> f = new CompletableFuture<>();
2844        CompletableFuture<Integer> f2 = new CompletableFuture<>();
2845        CompletableFuture<Integer> g = f.applyToEitherAsync(f2, inc, new ThreadExecutor());
2846        assertTrue(f.cancel(true));
2847        checkCompletedWithWrappedCancellationException(g);
2848
2849        f = new CompletableFuture<>();
2850        f2 = new CompletableFuture<>();
2851        assertTrue(f2.cancel(true));
2852        g = f.applyToEitherAsync(f2, inc, new ThreadExecutor());
2853        checkCompletedWithWrappedCancellationException(g);
2854    }
2855
2856    /**
2857     * acceptEitherAsync result completes normally after normal
2858     * completion of sources
2859     */
2860    public void testAcceptEitherAsyncE() {
2861        CompletableFuture<Integer> f = new CompletableFuture<>();
2862        CompletableFuture<Integer> f2 = new CompletableFuture<>();
2863        IncAction r = new IncAction();
2864        CompletableFuture<Void> g = f.acceptEitherAsync(f2, r, new ThreadExecutor());
2865        f.complete(one);
2866        checkCompletedNormally(g, null);
2867        assertEquals(r.value, 2);
2868
2869        r = new IncAction();
2870        f = new CompletableFuture<>();
2871        f.complete(one);
2872        f2 = new CompletableFuture<>();
2873        g = f.acceptEitherAsync(f2, r, new ThreadExecutor());
2874        checkCompletedNormally(g, null);
2875        assertEquals(r.value, 2);
2876    }
2877
2878    /**
2879     * acceptEitherAsync result completes exceptionally after exceptional
2880     * completion of source
2881     */
2882    public void testAcceptEitherAsync2E() {
2883        CompletableFuture<Integer> f = new CompletableFuture<>();
2884        CompletableFuture<Integer> f2 = new CompletableFuture<>();
2885        IncAction r = new IncAction();
2886        CompletableFuture<Void> g = f.acceptEitherAsync(f2, r, new ThreadExecutor());
2887        f.completeExceptionally(new CFException());
2888        checkCompletedWithWrappedCFException(g);
2889
2890        r = new IncAction();
2891        f = new CompletableFuture<>();
2892        f2 = new CompletableFuture<>();
2893        f2.completeExceptionally(new CFException());
2894        g = f.acceptEitherAsync(f2, r, new ThreadExecutor());
2895        f.complete(one);
2896        checkCompletedWithWrappedCFException(g);
2897    }
2898
2899    /**
2900     * acceptEitherAsync result completes exceptionally if action does
2901     */
2902    public void testAcceptEitherAsync3E() {
2903        CompletableFuture<Integer> f = new CompletableFuture<>();
2904        CompletableFuture<Integer> f2 = new CompletableFuture<>();
2905        FailingConsumer r = new FailingConsumer();
2906        CompletableFuture<Void> g = f.acceptEitherAsync(f2, r, new ThreadExecutor());
2907        f.complete(one);
2908        checkCompletedWithWrappedCFException(g);
2909    }
2910
2911    /**
2912     * acceptEitherAsync result completes exceptionally if either
2913     * source cancelled
2914     */
2915    public void testAcceptEitherAsync4E() {
2916        CompletableFuture<Integer> f = new CompletableFuture<>();
2917        CompletableFuture<Integer> f2 = new CompletableFuture<>();
2918        IncAction r = new IncAction();
2919        CompletableFuture<Void> g = f.acceptEitherAsync(f2, r, new ThreadExecutor());
2920        assertTrue(f.cancel(true));
2921        checkCompletedWithWrappedCancellationException(g);
2922
2923        r = new IncAction();
2924        f = new CompletableFuture<>();
2925        f2 = new CompletableFuture<>();
2926        assertTrue(f2.cancel(true));
2927        g = f.acceptEitherAsync(f2, r, new ThreadExecutor());
2928        checkCompletedWithWrappedCancellationException(g);
2929    }
2930
2931    /**
2932     * runAfterEitherAsync result completes normally after normal
2933     * completion of sources
2934     */
2935    public void testRunAfterEitherAsyncE() {
2936        CompletableFuture<Integer> f = new CompletableFuture<>();
2937        CompletableFuture<Integer> f2 = new CompletableFuture<>();
2938        Noop r = new Noop();
2939        CompletableFuture<Void> g = f.runAfterEitherAsync(f2, r, new ThreadExecutor());
2940        f.complete(one);
2941        checkCompletedNormally(g, null);
2942        assertTrue(r.ran);
2943
2944        r = new Noop();
2945        f = new CompletableFuture<>();
2946        f.complete(one);
2947        f2 = new CompletableFuture<>();
2948        g = f.runAfterEitherAsync(f2, r, new ThreadExecutor());
2949        checkCompletedNormally(g, null);
2950        assertTrue(r.ran);
2951    }
2952
2953    /**
2954     * runAfterEitherAsync result completes exceptionally after exceptional
2955     * completion of source
2956     */
2957    public void testRunAfterEitherAsync2E() {
2958        CompletableFuture<Integer> f = new CompletableFuture<>();
2959        CompletableFuture<Integer> f2 = new CompletableFuture<>();
2960        Noop r = new Noop();
2961        CompletableFuture<Void> g = f.runAfterEitherAsync(f2, r, new ThreadExecutor());
2962        f.completeExceptionally(new CFException());
2963        checkCompletedWithWrappedCFException(g);
2964
2965        r = new Noop();
2966        f = new CompletableFuture<>();
2967        f2 = new CompletableFuture<>();
2968        f2.completeExceptionally(new CFException());
2969        g = f.runAfterEitherAsync(f2, r, new ThreadExecutor());
2970        f.complete(one);
2971        checkCompletedWithWrappedCFException(g);
2972    }
2973
2974    /**
2975     * runAfterEitherAsync result completes exceptionally if action does
2976     */
2977    public void testRunAfterEitherAsync3E() {
2978        CompletableFuture<Integer> f = new CompletableFuture<>();
2979        CompletableFuture<Integer> f2 = new CompletableFuture<>();
2980        FailingNoop r = new FailingNoop();
2981        CompletableFuture<Void> g = f.runAfterEitherAsync(f2, r, new ThreadExecutor());
2982        f.complete(one);
2983        checkCompletedWithWrappedCFException(g);
2984    }
2985
2986    /**
2987     * runAfterEitherAsync result completes exceptionally if either
2988     * source cancelled
2989     */
2990    public void testRunAfterEitherAsync4E() {
2991        CompletableFuture<Integer> f = new CompletableFuture<>();
2992        CompletableFuture<Integer> f2 = new CompletableFuture<>();
2993        Noop r = new Noop();
2994        CompletableFuture<Void> g = f.runAfterEitherAsync(f2, r, new ThreadExecutor());
2995        assertTrue(f.cancel(true));
2996        checkCompletedWithWrappedCancellationException(g);
2997
2998        r = new Noop();
2999        f = new CompletableFuture<>();
3000        f2 = new CompletableFuture<>();
3001        assertTrue(f2.cancel(true));
3002        g = f.runAfterEitherAsync(f2, r, new ThreadExecutor());
3003        checkCompletedWithWrappedCancellationException(g);
3004    }
3005
3006    /**
3176       * thenComposeAsync result completes normally after normal
3177       * completion of source
3178       */
# Line 3247 | Line 3416 | public class CompletableFutureTest exten
3416       * whenComplete action executes on normal completion, propagating
3417       * source result.
3418       */
3419 <    public void testWhenComplete1() {
3419 >    public void testWhenComplete_normalCompletion1() {
3420 >        for (ExecutionMode m : ExecutionMode.values())
3421 >        for (Integer v1 : new Integer[] { 1, null }) {
3422 >
3423          final AtomicInteger a = new AtomicInteger();
3424 <        CompletableFuture<Integer> f = new CompletableFuture<>();
3425 <        CompletableFuture<Integer> g =
3426 <            f.whenComplete((Integer x, Throwable t) -> a.getAndIncrement());
3427 <        f.complete(three);
3428 <        checkCompletedNormally(f, three);
3429 <        checkCompletedNormally(g, three);
3424 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
3425 >        final CompletableFuture<Integer> g =
3426 >            m.whenComplete(f,
3427 >                           (Integer x, Throwable t) -> {
3428 >                               threadAssertSame(x, v1);
3429 >                               threadAssertNull(t);
3430 >                               a.getAndIncrement();
3431 >                           });
3432 >        f.complete(v1);
3433 >        checkCompletedNormally(f, v1);
3434 >        checkCompletedNormally(g, v1);
3435          assertEquals(a.get(), 1);
3436 +        }
3437      }
3438  
3439      /**
3440       * whenComplete action executes on exceptional completion, propagating
3441       * source result.
3442       */
3443 <    public void testWhenComplete2() {
3443 >    public void testWhenComplete_exceptionalCompletion() {
3444 >        for (ExecutionMode m : ExecutionMode.values())
3445 >        for (Integer v1 : new Integer[] { 1, null }) {
3446 >
3447          final AtomicInteger a = new AtomicInteger();
3448 <        CompletableFuture<Integer> f = new CompletableFuture<>();
3449 <        CompletableFuture<Integer> g =
3450 <            f.whenComplete((Integer x, Throwable t) -> a.getAndIncrement());
3451 <        f.completeExceptionally(new CFException());
3452 <        assertTrue(f.isCompletedExceptionally());
3453 <        assertTrue(g.isCompletedExceptionally());
3448 >        final CFException ex = new CFException();
3449 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
3450 >        final CompletableFuture<Integer> g = m.whenComplete
3451 >            (f,
3452 >             (Integer x, Throwable t) -> {
3453 >                threadAssertNull(x);
3454 >                threadAssertSame(t, ex);
3455 >                a.getAndIncrement();
3456 >            });
3457 >        f.completeExceptionally(ex);
3458 >        checkCompletedWithWrappedCFException(f, ex);
3459 >        checkCompletedWithWrappedCFException(g, ex);
3460          assertEquals(a.get(), 1);
3461 +        }
3462      }
3463  
3464      /**
3465       * If a whenComplete action throws an exception when triggered by
3466       * a normal completion, it completes exceptionally
3467       */
3468 <    public void testWhenComplete3() {
3469 <        CompletableFuture<Integer> f = new CompletableFuture<>();
3470 <        CompletableFuture<Integer> g =
3283 <            f.whenComplete((Integer x, Throwable t) ->
3284 <                           { throw new CFException(); } );
3285 <        f.complete(three);
3286 <        checkCompletedNormally(f, three);
3287 <        assertTrue(g.isCompletedExceptionally());
3288 <        checkCompletedWithWrappedCFException(g);
3289 <    }
3290 <
3291 <    /**
3292 <     * whenCompleteAsync action executes on normal completion, propagating
3293 <     * source result.
3294 <     */
3295 <    public void testWhenCompleteAsync1() {
3296 <        final AtomicInteger a = new AtomicInteger();
3297 <        CompletableFuture<Integer> f = new CompletableFuture<>();
3298 <        CompletableFuture<Integer> g =
3299 <            f.whenCompleteAsync((Integer x, Throwable t) -> a.getAndIncrement());
3300 <        f.complete(three);
3301 <        checkCompletedNormally(f, three);
3302 <        checkCompletedNormally(g, three);
3303 <        assertEquals(a.get(), 1);
3304 <    }
3305 <
3306 <    /**
3307 <     * whenCompleteAsync action executes on exceptional completion, propagating
3308 <     * source result.
3309 <     */
3310 <    public void testWhenCompleteAsync2() {
3311 <        final AtomicInteger a = new AtomicInteger();
3312 <        CompletableFuture<Integer> f = new CompletableFuture<>();
3313 <        CompletableFuture<Integer> g =
3314 <            f.whenCompleteAsync((Integer x, Throwable t) -> a.getAndIncrement());
3315 <        f.completeExceptionally(new CFException());
3316 <        checkCompletedWithWrappedCFException(f);
3317 <        checkCompletedWithWrappedCFException(g);
3318 <    }
3319 <
3320 <    /**
3321 <     * If a whenCompleteAsync action throws an exception when
3322 <     * triggered by a normal completion, it completes exceptionally
3323 <     */
3324 <    public void testWhenCompleteAsync3() {
3325 <        CompletableFuture<Integer> f = new CompletableFuture<>();
3326 <        CompletableFuture<Integer> g =
3327 <            f.whenCompleteAsync((Integer x, Throwable t) ->
3328 <                           { throw new CFException(); } );
3329 <        f.complete(three);
3330 <        checkCompletedNormally(f, three);
3331 <        checkCompletedWithWrappedCFException(g);
3332 <    }
3468 >    public void testWhenComplete_actionFailed() {
3469 >        for (ExecutionMode m : ExecutionMode.values())
3470 >        for (Integer v1 : new Integer[] { 1, null }) {
3471  
3472 <    /**
3473 <     * whenCompleteAsync action executes on normal completion, propagating
3474 <     * source result.
3475 <     */
3476 <    public void testWhenCompleteAsync1e() {
3477 <        final AtomicInteger a = new AtomicInteger();
3478 <        ThreadExecutor exec = new ThreadExecutor();
3479 <        CompletableFuture<Integer> f = new CompletableFuture<>();
3480 <        CompletableFuture<Integer> g =
3481 <            f.whenCompleteAsync((Integer x, Throwable t) -> a.getAndIncrement(),
3482 <                                exec);
3483 <        f.complete(three);
3484 <        checkCompletedNormally(f, three);
3347 <        checkCompletedNormally(g, three);
3348 <        assertEquals(a.get(), 1);
3472 >        final CFException ex = new CFException();
3473 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
3474 >        final CompletableFuture<Integer> g = m.whenComplete
3475 >            (f,
3476 >             (Integer x, Throwable t) -> {
3477 >                threadAssertSame(x, v1);
3478 >                threadAssertNull(t);
3479 >                throw ex;
3480 >            });
3481 >        f.complete(v1);
3482 >        checkCompletedNormally(f, v1);
3483 >        checkCompletedWithWrappedCFException(g, ex);
3484 >        }
3485      }
3486  
3487      /**
3488 <     * whenCompleteAsync action executes on exceptional completion, propagating
3489 <     * source result.
3488 >     * If a whenComplete action throws an exception when triggered by
3489 >     * a source completion that also throws an exception, the source
3490 >     * exception takes precedence.
3491       */
3492 <    public void testWhenCompleteAsync2e() {
3493 <        final AtomicInteger a = new AtomicInteger();
3494 <        ThreadExecutor exec = new ThreadExecutor();
3358 <        CompletableFuture<Integer> f = new CompletableFuture<>();
3359 <        CompletableFuture<Integer> g =
3360 <            f.whenCompleteAsync((Integer x, Throwable t) -> a.getAndIncrement(),
3361 <                                exec);
3362 <        f.completeExceptionally(new CFException());
3363 <        checkCompletedWithWrappedCFException(f);
3364 <        checkCompletedWithWrappedCFException(g);
3365 <    }
3492 >    public void testWhenComplete_actionFailedSourceFailed() {
3493 >        for (ExecutionMode m : ExecutionMode.values())
3494 >        for (Integer v1 : new Integer[] { 1, null }) {
3495  
3496 <    /**
3497 <     * If a whenCompleteAsync action throws an exception when triggered
3498 <     * by a normal completion, it completes exceptionally
3499 <     */
3500 <    public void testWhenCompleteAsync3e() {
3501 <        ThreadExecutor exec = new ThreadExecutor();
3502 <        CompletableFuture<Integer> f = new CompletableFuture<>();
3503 <        CompletableFuture<Integer> g =
3504 <            f.whenCompleteAsync((Integer x, Throwable t) ->
3505 <                                { throw new CFException(); },
3506 <                                exec);
3507 <        f.complete(three);
3508 <        checkCompletedNormally(f, three);
3509 <        checkCompletedWithWrappedCFException(g);
3496 >        final CFException ex1 = new CFException();
3497 >        final CFException ex2 = new CFException();
3498 >        final CompletableFuture<Integer> f = new CompletableFuture<>();
3499 >        final CompletableFuture<Integer> g = m.whenComplete
3500 >            (f,
3501 >             (Integer x, Throwable t) -> {
3502 >                threadAssertSame(t, ex1);
3503 >                threadAssertNull(x);
3504 >                throw ex2;
3505 >            });
3506 >        f.completeExceptionally(ex1);
3507 >        checkCompletedWithWrappedCFException(f, ex1);
3508 >        checkCompletedWithWrappedCFException(g, ex1);
3509 >        }
3510      }
3511  
3512      /**

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines