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.172 by jsr166, Thu Sep 15 00:32:45 2016 UTC vs.
Revision 1.207 by jsr166, Sun Sep 23 02:06:28 2018 UTC

# Line 41 | Line 41 | import java.util.function.Function;
41   import java.util.function.Predicate;
42   import java.util.function.Supplier;
43  
44 import junit.framework.AssertionFailedError;
44   import junit.framework.Test;
45   import junit.framework.TestSuite;
46  
# Line 59 | Line 58 | public class CompletableFutureTest exten
58      void checkIncomplete(CompletableFuture<?> f) {
59          assertFalse(f.isDone());
60          assertFalse(f.isCancelled());
61 <        assertTrue(f.toString().contains("Not completed"));
61 >        assertTrue(f.toString().matches(".*\\[.*Not completed.*\\]"));
62 >
63 >        Object result = null;
64          try {
65 <            assertNull(f.getNow(null));
65 >            result = f.getNow(null);
66          } catch (Throwable fail) { threadUnexpectedException(fail); }
67 +        assertNull(result);
68 +
69          try {
70 <            f.get(0L, SECONDS);
70 >            f.get(randomExpiredTimeout(), randomTimeUnit());
71              shouldThrow();
72          }
73          catch (TimeoutException success) {}
74          catch (Throwable fail) { threadUnexpectedException(fail); }
75      }
76  
77 <    <T> void checkCompletedNormally(CompletableFuture<T> f, T value) {
78 <        checkTimedGet(f, value);
77 >    <T> void checkCompletedNormally(CompletableFuture<T> f, T expectedValue) {
78 >        checkTimedGet(f, expectedValue);
79  
80 +        assertEquals(expectedValue, f.join());
81 +        assertEquals(expectedValue, f.getNow(null));
82 +
83 +        T result = null;
84          try {
85 <            assertEquals(value, f.join());
79 <        } catch (Throwable fail) { threadUnexpectedException(fail); }
80 <        try {
81 <            assertEquals(value, f.getNow(null));
82 <        } catch (Throwable fail) { threadUnexpectedException(fail); }
83 <        try {
84 <            assertEquals(value, f.get());
85 >            result = f.get();
86          } catch (Throwable fail) { threadUnexpectedException(fail); }
87 +        assertEquals(expectedValue, result);
88 +
89          assertTrue(f.isDone());
90          assertFalse(f.isCancelled());
91          assertFalse(f.isCompletedExceptionally());
92 <        assertTrue(f.toString().contains("[Completed normally]"));
92 >        assertTrue(f.toString().matches(".*\\[.*Completed normally.*\\]"));
93      }
94  
95      /**
96       * Returns the "raw" internal exceptional completion of f,
97       * without any additional wrapping with CompletionException.
98       */
99 <    <U> Throwable exceptionalCompletion(CompletableFuture<U> f) {
100 <        // handle (and whenComplete) can distinguish between "direct"
101 <        // and "wrapped" exceptional completion
102 <        return f.handle((U u, Throwable t) -> t).join();
99 >    Throwable exceptionalCompletion(CompletableFuture<?> f) {
100 >        // handle (and whenComplete and exceptionally) can distinguish
101 >        // between "direct" and "wrapped" exceptional completion
102 >        return f.handle((u, t) -> t).join();
103      }
104  
105      void checkCompletedExceptionally(CompletableFuture<?> f,
# Line 142 | Line 145 | public class CompletableFutureTest exten
145          assertFalse(f.isCancelled());
146          assertTrue(f.isDone());
147          assertTrue(f.isCompletedExceptionally());
148 <        assertTrue(f.toString().contains("[Completed exceptionally]"));
148 >        assertTrue(f.toString().matches(".*\\[.*Completed exceptionally.*\\]"));
149      }
150  
151      void checkCompletedWithWrappedCFException(CompletableFuture<?> f) {
152          checkCompletedExceptionally(f, true,
153 <            (t) -> assertTrue(t instanceof CFException));
153 >            t -> assertTrue(t instanceof CFException));
154      }
155  
156      void checkCompletedWithWrappedCancellationException(CompletableFuture<?> f) {
157          checkCompletedExceptionally(f, true,
158 <            (t) -> assertTrue(t instanceof CancellationException));
158 >            t -> assertTrue(t instanceof CancellationException));
159      }
160  
161      void checkCompletedWithTimeoutException(CompletableFuture<?> f) {
162          checkCompletedExceptionally(f, false,
163 <            (t) -> assertTrue(t instanceof TimeoutException));
163 >            t -> assertTrue(t instanceof TimeoutException));
164      }
165  
166      void checkCompletedWithWrappedException(CompletableFuture<?> f,
167                                              Throwable ex) {
168 <        checkCompletedExceptionally(f, true, (t) -> assertSame(t, ex));
168 >        checkCompletedExceptionally(f, true, t -> assertSame(t, ex));
169      }
170  
171      void checkCompletedExceptionally(CompletableFuture<?> f, Throwable ex) {
172 <        checkCompletedExceptionally(f, false, (t) -> assertSame(t, ex));
172 >        checkCompletedExceptionally(f, false, t -> assertSame(t, ex));
173      }
174  
175      void checkCancelled(CompletableFuture<?> f) {
# Line 197 | Line 200 | public class CompletableFutureTest exten
200          assertTrue(f.isDone());
201          assertTrue(f.isCompletedExceptionally());
202          assertTrue(f.isCancelled());
203 <        assertTrue(f.toString().contains("[Completed exceptionally]"));
203 >        assertTrue(f.toString().matches(".*\\[.*Completed exceptionally.*\\]"));
204      }
205  
206      /**
# Line 296 | Line 299 | public class CompletableFutureTest exten
299          }
300  
301          f = new CompletableFuture<>();
302 <        f.completeExceptionally(ex = new CFException());
302 >        f.completeExceptionally(new CFException());
303          f.obtrudeValue(v1);
304          checkCompletedNormally(f, v1);
305          f.obtrudeException(ex = new CFException());
# Line 333 | Line 336 | public class CompletableFutureTest exten
336      /**
337       * toString indicates current completion state
338       */
339 <    public void testToString() {
340 <        CompletableFuture<String> f;
341 <
342 <        f = new CompletableFuture<String>();
343 <        assertTrue(f.toString().contains("[Not completed]"));
339 >    public void testToString_incomplete() {
340 >        CompletableFuture<String> f = new CompletableFuture<>();
341 >        assertTrue(f.toString().matches(".*\\[.*Not completed.*\\]"));
342 >        if (testImplementationDetails)
343 >            assertEquals(identityString(f) + "[Not completed]",
344 >                         f.toString());
345 >    }
346  
347 +    public void testToString_normal() {
348 +        CompletableFuture<String> f = new CompletableFuture<>();
349          assertTrue(f.complete("foo"));
350 <        assertTrue(f.toString().contains("[Completed normally]"));
350 >        assertTrue(f.toString().matches(".*\\[.*Completed normally.*\\]"));
351 >        if (testImplementationDetails)
352 >            assertEquals(identityString(f) + "[Completed normally]",
353 >                         f.toString());
354 >    }
355  
356 <        f = new CompletableFuture<String>();
356 >    public void testToString_exception() {
357 >        CompletableFuture<String> f = new CompletableFuture<>();
358          assertTrue(f.completeExceptionally(new IndexOutOfBoundsException()));
359 <        assertTrue(f.toString().contains("[Completed exceptionally]"));
359 >        assertTrue(f.toString().matches(".*\\[.*Completed exceptionally.*\\]"));
360 >        if (testImplementationDetails)
361 >            assertTrue(f.toString().startsWith(
362 >                               identityString(f) + "[Completed exceptionally: "));
363 >    }
364  
365 +    public void testToString_cancelled() {
366          for (boolean mayInterruptIfRunning : new boolean[] { true, false }) {
367 <            f = new CompletableFuture<String>();
367 >            CompletableFuture<String> f = new CompletableFuture<>();
368              assertTrue(f.cancel(mayInterruptIfRunning));
369 <            assertTrue(f.toString().contains("[Completed exceptionally]"));
369 >            assertTrue(f.toString().matches(".*\\[.*Completed exceptionally.*\\]"));
370 >            if (testImplementationDetails)
371 >                assertTrue(f.toString().startsWith(
372 >                                   identityString(f) + "[Completed exceptionally: "));
373          }
374      }
375  
# Line 531 | Line 551 | public class CompletableFutureTest exten
551          public CompletableFuture<Integer> apply(Integer x) {
552              invoked();
553              value = x;
554 <            CompletableFuture<Integer> f = new CompletableFuture<>();
555 <            assertTrue(f.complete(inc(x)));
556 <            return f;
554 >            return CompletableFuture.completedFuture(inc(x));
555 >        }
556 >    }
557 >
558 >    static class FailingExceptionalCompletableFutureFunction extends CheckedAction
559 >        implements Function<Throwable, CompletableFuture<Integer>>
560 >    {
561 >        final CFException ex;
562 >        FailingExceptionalCompletableFutureFunction(ExecutionMode m) { super(m); ex = new CFException(); }
563 >        public CompletableFuture<Integer> apply(Throwable x) {
564 >            invoked();
565 >            throw ex;
566 >        }
567 >    }
568 >
569 >    static class ExceptionalCompletableFutureFunction extends CheckedAction
570 >        implements Function<Throwable, CompletionStage<Integer>> {
571 >        final Integer value = 3;
572 >        ExceptionalCompletableFutureFunction(ExecutionMode m) { super(m); }
573 >        public CompletionStage<Integer> apply(Throwable x) {
574 >            invoked();
575 >            return CompletableFuture.completedFuture(value);
576          }
577      }
578  
# Line 652 | Line 691 | public class CompletableFutureTest exten
691                   Function<? super T,U> a) {
692                  return f.applyToEither(g, a);
693              }
694 +            public <T> CompletableFuture<T> exceptionally
695 +                (CompletableFuture<T> f,
696 +                 Function<Throwable, ? extends T> fn) {
697 +                return f.exceptionally(fn);
698 +            }
699 +            public <T> CompletableFuture<T> exceptionallyCompose
700 +                (CompletableFuture<T> f, Function<Throwable, ? extends CompletionStage<T>> fn) {
701 +                return f.exceptionallyCompose(fn);
702 +            }
703          },
656
704          ASYNC {
705              public void checkExecutionMode() {
706                  assertEquals(defaultExecutorIsCommonPool,
# Line 726 | Line 773 | public class CompletableFutureTest exten
773                   Function<? super T,U> a) {
774                  return f.applyToEitherAsync(g, a);
775              }
776 +            public <T> CompletableFuture<T> exceptionally
777 +                (CompletableFuture<T> f,
778 +                 Function<Throwable, ? extends T> fn) {
779 +                return f.exceptionallyAsync(fn);
780 +            }
781 +
782 +            public <T> CompletableFuture<T> exceptionallyCompose
783 +                (CompletableFuture<T> f, Function<Throwable, ? extends CompletionStage<T>> fn) {
784 +                return f.exceptionallyComposeAsync(fn);
785 +            }
786 +
787          },
788  
789          EXECUTOR {
# Line 799 | Line 857 | public class CompletableFutureTest exten
857                   Function<? super T,U> a) {
858                  return f.applyToEitherAsync(g, a, new ThreadExecutor());
859              }
860 +            public <T> CompletableFuture<T> exceptionally
861 +                (CompletableFuture<T> f,
862 +                 Function<Throwable, ? extends T> fn) {
863 +                return f.exceptionallyAsync(fn, new ThreadExecutor());
864 +            }
865 +            public <T> CompletableFuture<T> exceptionallyCompose
866 +                (CompletableFuture<T> f, Function<Throwable, ? extends CompletionStage<T>> fn) {
867 +                return f.exceptionallyComposeAsync(fn, new ThreadExecutor());
868 +            }
869 +
870          };
871  
872          public abstract void checkExecutionMode();
# Line 841 | Line 909 | public class CompletableFutureTest exten
909              (CompletableFuture<T> f,
910               CompletionStage<? extends T> g,
911               Function<? super T,U> a);
912 +        public abstract <T> CompletableFuture<T> exceptionally
913 +            (CompletableFuture<T> f,
914 +             Function<Throwable, ? extends T> fn);
915 +        public abstract <T> CompletableFuture<T> exceptionallyCompose
916 +            (CompletableFuture<T> f,
917 +             Function<Throwable, ? extends CompletionStage<T>> fn);
918      }
919  
920      /**
# Line 848 | Line 922 | public class CompletableFutureTest exten
922       * normally, and source result is propagated
923       */
924      public void testExceptionally_normalCompletion() {
925 +        for (ExecutionMode m : ExecutionMode.values())
926          for (boolean createIncomplete : new boolean[] { true, false })
927          for (Integer v1 : new Integer[] { 1, null })
928      {
854        final AtomicInteger a = new AtomicInteger(0);
929          final CompletableFuture<Integer> f = new CompletableFuture<>();
930          if (!createIncomplete) assertTrue(f.complete(v1));
931 <        final CompletableFuture<Integer> g = f.exceptionally
932 <            ((Throwable t) -> {
859 <                a.getAndIncrement();
931 >        final CompletableFuture<Integer> g = m.exceptionally
932 >            (f, (Throwable t) -> {
933                  threadFail("should not be called");
934                  return null;            // unreached
935              });
# Line 864 | Line 937 | public class CompletableFutureTest exten
937  
938          checkCompletedNormally(g, v1);
939          checkCompletedNormally(f, v1);
867        assertEquals(0, a.get());
940      }}
941  
942      /**
# Line 872 | Line 944 | public class CompletableFutureTest exten
944       * exception
945       */
946      public void testExceptionally_exceptionalCompletion() {
947 +        for (ExecutionMode m : ExecutionMode.values())
948          for (boolean createIncomplete : new boolean[] { true, false })
949          for (Integer v1 : new Integer[] { 1, null })
950      {
# Line 879 | Line 952 | public class CompletableFutureTest exten
952          final CFException ex = new CFException();
953          final CompletableFuture<Integer> f = new CompletableFuture<>();
954          if (!createIncomplete) f.completeExceptionally(ex);
955 <        final CompletableFuture<Integer> g = f.exceptionally
956 <            ((Throwable t) -> {
957 <                ExecutionMode.SYNC.checkExecutionMode();
955 >        final CompletableFuture<Integer> g = m.exceptionally
956 >            (f, (Throwable t) -> {
957 >                m.checkExecutionMode();
958                  threadAssertSame(t, ex);
959                  a.getAndIncrement();
960                  return v1;
# Line 897 | Line 970 | public class CompletableFutureTest exten
970       * exceptionally with that exception
971       */
972      public void testExceptionally_exceptionalCompletionActionFailed() {
973 +        for (ExecutionMode m : ExecutionMode.values())
974          for (boolean createIncomplete : new boolean[] { true, false })
975      {
976          final AtomicInteger a = new AtomicInteger(0);
# Line 904 | Line 978 | public class CompletableFutureTest exten
978          final CFException ex2 = new CFException();
979          final CompletableFuture<Integer> f = new CompletableFuture<>();
980          if (!createIncomplete) f.completeExceptionally(ex1);
981 <        final CompletableFuture<Integer> g = f.exceptionally
982 <            ((Throwable t) -> {
983 <                ExecutionMode.SYNC.checkExecutionMode();
981 >        final CompletableFuture<Integer> g = m.exceptionally
982 >            (f, (Throwable t) -> {
983 >                m.checkExecutionMode();
984                  threadAssertSame(t, ex1);
985                  a.getAndIncrement();
986                  throw ex2;
# Line 1242 | Line 1316 | public class CompletableFutureTest exten
1316          r.assertInvoked();
1317      }}
1318  
1319 +    @SuppressWarnings("FutureReturnValueIgnored")
1320      public void testRunAsync_rejectingExecutor() {
1321          CountingRejectingExecutor e = new CountingRejectingExecutor();
1322          try {
# Line 1288 | Line 1363 | public class CompletableFutureTest exten
1363          r.assertInvoked();
1364      }}
1365  
1366 +    @SuppressWarnings("FutureReturnValueIgnored")
1367      public void testSupplyAsync_rejectingExecutor() {
1368          CountingRejectingExecutor e = new CountingRejectingExecutor();
1369          try {
# Line 2562 | Line 2638 | public class CompletableFutureTest exten
2638  
2639          // unspecified behavior - both source completions available
2640          try {
2641 <            assertEquals(null, h0.join());
2641 >            assertNull(h0.join());
2642              rs[0].assertValue(v1);
2643          } catch (CompletionException ok) {
2644              checkCompletedWithWrappedException(h0, ex);
2645              rs[0].assertNotInvoked();
2646          }
2647          try {
2648 <            assertEquals(null, h1.join());
2648 >            assertNull(h1.join());
2649              rs[1].assertValue(v1);
2650          } catch (CompletionException ok) {
2651              checkCompletedWithWrappedException(h1, ex);
2652              rs[1].assertNotInvoked();
2653          }
2654          try {
2655 <            assertEquals(null, h2.join());
2655 >            assertNull(h2.join());
2656              rs[2].assertValue(v1);
2657          } catch (CompletionException ok) {
2658              checkCompletedWithWrappedException(h2, ex);
2659              rs[2].assertNotInvoked();
2660          }
2661          try {
2662 <            assertEquals(null, h3.join());
2662 >            assertNull(h3.join());
2663              rs[3].assertValue(v1);
2664          } catch (CompletionException ok) {
2665              checkCompletedWithWrappedException(h3, ex);
# Line 2822 | Line 2898 | public class CompletableFutureTest exten
2898  
2899          // unspecified behavior - both source completions available
2900          try {
2901 <            assertEquals(null, h0.join());
2901 >            assertNull(h0.join());
2902              rs[0].assertInvoked();
2903          } catch (CompletionException ok) {
2904              checkCompletedWithWrappedException(h0, ex);
2905              rs[0].assertNotInvoked();
2906          }
2907          try {
2908 <            assertEquals(null, h1.join());
2908 >            assertNull(h1.join());
2909              rs[1].assertInvoked();
2910          } catch (CompletionException ok) {
2911              checkCompletedWithWrappedException(h1, ex);
2912              rs[1].assertNotInvoked();
2913          }
2914          try {
2915 <            assertEquals(null, h2.join());
2915 >            assertNull(h2.join());
2916              rs[2].assertInvoked();
2917          } catch (CompletionException ok) {
2918              checkCompletedWithWrappedException(h2, ex);
2919              rs[2].assertNotInvoked();
2920          }
2921          try {
2922 <            assertEquals(null, h3.join());
2922 >            assertNull(h3.join());
2923              rs[3].assertInvoked();
2924          } catch (CompletionException ok) {
2925              checkCompletedWithWrappedException(h3, ex);
# Line 3075 | Line 3151 | public class CompletableFutureTest exten
3151          checkCompletedNormally(f, v1);
3152      }}
3153  
3154 +    /**
3155 +     * exceptionallyCompose result completes normally after normal
3156 +     * completion of source
3157 +     */
3158 +    public void testExceptionallyCompose_normalCompletion() {
3159 +        for (ExecutionMode m : ExecutionMode.values())
3160 +        for (boolean createIncomplete : new boolean[] { true, false })
3161 +        for (Integer v1 : new Integer[] { 1, null })
3162 +    {
3163 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
3164 +        final ExceptionalCompletableFutureFunction r =
3165 +            new ExceptionalCompletableFutureFunction(m);
3166 +        if (!createIncomplete) assertTrue(f.complete(v1));
3167 +        final CompletableFuture<Integer> g = m.exceptionallyCompose(f, r);
3168 +        if (createIncomplete) assertTrue(f.complete(v1));
3169 +
3170 +        checkCompletedNormally(f, v1);
3171 +        checkCompletedNormally(g, v1);
3172 +        r.assertNotInvoked();
3173 +    }}
3174 +
3175 +    /**
3176 +     * exceptionallyCompose result completes normally after exceptional
3177 +     * completion of source
3178 +     */
3179 +    public void testExceptionallyCompose_exceptionalCompletion() {
3180 +        for (ExecutionMode m : ExecutionMode.values())
3181 +        for (boolean createIncomplete : new boolean[] { true, false })
3182 +    {
3183 +        final CFException ex = new CFException();
3184 +        final ExceptionalCompletableFutureFunction r =
3185 +            new ExceptionalCompletableFutureFunction(m);
3186 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
3187 +        if (!createIncomplete) f.completeExceptionally(ex);
3188 +        final CompletableFuture<Integer> g = m.exceptionallyCompose(f, r);
3189 +        if (createIncomplete) f.completeExceptionally(ex);
3190 +
3191 +        checkCompletedExceptionally(f, ex);
3192 +        checkCompletedNormally(g, r.value);
3193 +        r.assertInvoked();
3194 +    }}
3195 +
3196 +    /**
3197 +     * exceptionallyCompose completes exceptionally on exception if action does
3198 +     */
3199 +    public void testExceptionallyCompose_actionFailed() {
3200 +        for (ExecutionMode m : ExecutionMode.values())
3201 +        for (boolean createIncomplete : new boolean[] { true, false })
3202 +        for (Integer v1 : new Integer[] { 1, null })
3203 +    {
3204 +        final CFException ex = new CFException();
3205 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
3206 +        final FailingExceptionalCompletableFutureFunction r
3207 +            = new FailingExceptionalCompletableFutureFunction(m);
3208 +        if (!createIncomplete) f.completeExceptionally(ex);
3209 +        final CompletableFuture<Integer> g = m.exceptionallyCompose(f, r);
3210 +        if (createIncomplete) f.completeExceptionally(ex);
3211 +
3212 +        checkCompletedExceptionally(f, ex);
3213 +        checkCompletedWithWrappedException(g, r.ex);
3214 +        r.assertInvoked();
3215 +    }}
3216 +
3217 +
3218      // other static methods
3219  
3220      /**
# Line 3238 | Line 3378 | public class CompletableFutureTest exten
3378      /**
3379       * Completion methods throw NullPointerException with null arguments
3380       */
3381 +    @SuppressWarnings("FutureReturnValueIgnored")
3382      public void testNPE() {
3383          CompletableFuture<Integer> f = new CompletableFuture<>();
3384          CompletableFuture<Integer> g = new CompletableFuture<>();
# Line 3257 | Line 3398 | public class CompletableFutureTest exten
3398  
3399              () -> f.thenApply(null),
3400              () -> f.thenApplyAsync(null),
3401 <            () -> f.thenApplyAsync((x) -> x, null),
3401 >            () -> f.thenApplyAsync(x -> x, null),
3402              () -> f.thenApplyAsync(null, exec),
3403  
3404              () -> f.thenAccept(null),
3405              () -> f.thenAcceptAsync(null),
3406 <            () -> f.thenAcceptAsync((x) -> {} , null),
3406 >            () -> f.thenAcceptAsync(x -> {} , null),
3407              () -> f.thenAcceptAsync(null, exec),
3408  
3409              () -> f.thenRun(null),
# Line 3297 | Line 3438 | public class CompletableFutureTest exten
3438              () -> f.applyToEither(g, null),
3439              () -> f.applyToEitherAsync(g, null),
3440              () -> f.applyToEitherAsync(g, null, exec),
3441 <            () -> f.applyToEither(nullFuture, (x) -> x),
3442 <            () -> f.applyToEitherAsync(nullFuture, (x) -> x),
3443 <            () -> f.applyToEitherAsync(nullFuture, (x) -> x, exec),
3444 <            () -> f.applyToEitherAsync(g, (x) -> x, null),
3441 >            () -> f.applyToEither(nullFuture, x -> x),
3442 >            () -> f.applyToEitherAsync(nullFuture, x -> x),
3443 >            () -> f.applyToEitherAsync(nullFuture, x -> x, exec),
3444 >            () -> f.applyToEitherAsync(g, x -> x, null),
3445  
3446              () -> f.acceptEither(g, null),
3447              () -> f.acceptEitherAsync(g, null),
3448              () -> f.acceptEitherAsync(g, null, exec),
3449 <            () -> f.acceptEither(nullFuture, (x) -> {}),
3450 <            () -> f.acceptEitherAsync(nullFuture, (x) -> {}),
3451 <            () -> f.acceptEitherAsync(nullFuture, (x) -> {}, exec),
3452 <            () -> f.acceptEitherAsync(g, (x) -> {}, null),
3449 >            () -> f.acceptEither(nullFuture, x -> {}),
3450 >            () -> f.acceptEitherAsync(nullFuture, x -> {}),
3451 >            () -> f.acceptEitherAsync(nullFuture, x -> {}, exec),
3452 >            () -> f.acceptEitherAsync(g, x -> {}, null),
3453  
3454              () -> f.runAfterEither(g, null),
3455              () -> f.runAfterEitherAsync(g, null),
# Line 3374 | Line 3515 | public class CompletableFutureTest exten
3515          for (CompletableFuture<Integer> src : srcs) {
3516              List<CompletableFuture<?>> fs = new ArrayList<>();
3517              fs.add(src.thenRunAsync(() -> {}, e));
3518 <            fs.add(src.thenAcceptAsync((z) -> {}, e));
3519 <            fs.add(src.thenApplyAsync((z) -> z, e));
3518 >            fs.add(src.thenAcceptAsync(z -> {}, e));
3519 >            fs.add(src.thenApplyAsync(z -> z, e));
3520  
3521              fs.add(src.thenCombineAsync(src, (x, y) -> x, e));
3522              fs.add(src.thenAcceptBothAsync(src, (x, y) -> {}, e));
3523              fs.add(src.runAfterBothAsync(src, () -> {}, e));
3524  
3525 <            fs.add(src.applyToEitherAsync(src, (z) -> z, e));
3526 <            fs.add(src.acceptEitherAsync(src, (z) -> {}, e));
3525 >            fs.add(src.applyToEitherAsync(src, z -> z, e));
3526 >            fs.add(src.acceptEitherAsync(src, z -> {}, e));
3527              fs.add(src.runAfterEitherAsync(src, () -> {}, e));
3528  
3529 <            fs.add(src.thenComposeAsync((z) -> null, e));
3529 >            fs.add(src.thenComposeAsync(z -> null, e));
3530              fs.add(src.whenCompleteAsync((z, t) -> {}, e));
3531              fs.add(src.handleAsync((z, t) -> null, e));
3532  
# Line 3418 | Line 3559 | public class CompletableFutureTest exten
3559          {
3560              List<CompletableFuture<?>> fs = new ArrayList<>();
3561  
3562 <            fs.add(complete.applyToEitherAsync(incomplete, (z) -> z, e));
3563 <            fs.add(incomplete.applyToEitherAsync(complete, (z) -> z, e));
3562 >            fs.add(complete.applyToEitherAsync(incomplete, z -> z, e));
3563 >            fs.add(incomplete.applyToEitherAsync(complete, z -> z, e));
3564  
3565 <            fs.add(complete.acceptEitherAsync(incomplete, (z) -> {}, e));
3566 <            fs.add(incomplete.acceptEitherAsync(complete, (z) -> {}, e));
3565 >            fs.add(complete.acceptEitherAsync(incomplete, z -> {}, e));
3566 >            fs.add(incomplete.acceptEitherAsync(complete, z -> {}, e));
3567  
3568              fs.add(complete.runAfterEitherAsync(incomplete, () -> {}, e));
3569              fs.add(incomplete.runAfterEitherAsync(complete, () -> {}, e));
# Line 3461 | Line 3602 | public class CompletableFutureTest exten
3602  
3603          List<CompletableFuture<?>> fs = new ArrayList<>();
3604          fs.add(incomplete.thenRunAsync(() -> {}, e));
3605 <        fs.add(incomplete.thenAcceptAsync((z) -> {}, e));
3606 <        fs.add(incomplete.thenApplyAsync((z) -> z, e));
3605 >        fs.add(incomplete.thenAcceptAsync(z -> {}, e));
3606 >        fs.add(incomplete.thenApplyAsync(z -> z, e));
3607  
3608          fs.add(incomplete.thenCombineAsync(incomplete, (x, y) -> x, e));
3609          fs.add(incomplete.thenAcceptBothAsync(incomplete, (x, y) -> {}, e));
3610          fs.add(incomplete.runAfterBothAsync(incomplete, () -> {}, e));
3611  
3612 <        fs.add(incomplete.applyToEitherAsync(incomplete, (z) -> z, e));
3613 <        fs.add(incomplete.acceptEitherAsync(incomplete, (z) -> {}, e));
3612 >        fs.add(incomplete.applyToEitherAsync(incomplete, z -> z, e));
3613 >        fs.add(incomplete.acceptEitherAsync(incomplete, z -> {}, e));
3614          fs.add(incomplete.runAfterEitherAsync(incomplete, () -> {}, e));
3615  
3616 <        fs.add(incomplete.thenComposeAsync((z) -> null, e));
3616 >        fs.add(incomplete.thenComposeAsync(z -> null, e));
3617          fs.add(incomplete.whenCompleteAsync((z, t) -> {}, e));
3618          fs.add(incomplete.handleAsync((z, t) -> null, e));
3619  
# Line 3532 | Line 3673 | public class CompletableFutureTest exten
3673       */
3674      public void testCompletedStage() {
3675          AtomicInteger x = new AtomicInteger(0);
3676 <        AtomicReference<Throwable> r = new AtomicReference<Throwable>();
3676 >        AtomicReference<Throwable> r = new AtomicReference<>();
3677          CompletionStage<Integer> f = CompletableFuture.completedStage(1);
3678          f.whenComplete((v, e) -> {if (e != null) r.set(e); else x.set(v);});
3679          assertEquals(x.get(), 1);
# Line 3577 | Line 3718 | public class CompletableFutureTest exten
3718       * copy returns a CompletableFuture that is completed normally,
3719       * with the same value, when source is.
3720       */
3721 <    public void testCopy() {
3721 >    public void testCopy_normalCompletion() {
3722 >        for (boolean createIncomplete : new boolean[] { true, false })
3723 >        for (Integer v1 : new Integer[] { 1, null })
3724 >    {
3725          CompletableFuture<Integer> f = new CompletableFuture<>();
3726 +        if (!createIncomplete) assertTrue(f.complete(v1));
3727          CompletableFuture<Integer> g = f.copy();
3728 <        checkIncomplete(f);
3729 <        checkIncomplete(g);
3730 <        f.complete(1);
3731 <        checkCompletedNormally(f, 1);
3732 <        checkCompletedNormally(g, 1);
3733 <    }
3728 >        if (createIncomplete) {
3729 >            checkIncomplete(f);
3730 >            checkIncomplete(g);
3731 >            assertTrue(f.complete(v1));
3732 >        }
3733 >        checkCompletedNormally(f, v1);
3734 >        checkCompletedNormally(g, v1);
3735 >    }}
3736  
3737      /**
3738       * copy returns a CompletableFuture that is completed exceptionally
3739       * when source is.
3740       */
3741 <    public void testCopy2() {
3741 >    public void testCopy_exceptionalCompletion() {
3742 >        for (boolean createIncomplete : new boolean[] { true, false })
3743 >    {
3744 >        CFException ex = new CFException();
3745          CompletableFuture<Integer> f = new CompletableFuture<>();
3746 +        if (!createIncomplete) f.completeExceptionally(ex);
3747          CompletableFuture<Integer> g = f.copy();
3748 <        checkIncomplete(f);
3749 <        checkIncomplete(g);
3750 <        CFException ex = new CFException();
3751 <        f.completeExceptionally(ex);
3748 >        if (createIncomplete) {
3749 >            checkIncomplete(f);
3750 >            checkIncomplete(g);
3751 >            f.completeExceptionally(ex);
3752 >        }
3753          checkCompletedExceptionally(f, ex);
3754          checkCompletedWithWrappedException(g, ex);
3755 +    }}
3756 +
3757 +    /**
3758 +     * Completion of a copy does not complete its source.
3759 +     */
3760 +    public void testCopy_oneWayPropagation() {
3761 +        CompletableFuture<Integer> f = new CompletableFuture<>();
3762 +        assertTrue(f.copy().complete(1));
3763 +        assertTrue(f.copy().complete(null));
3764 +        assertTrue(f.copy().cancel(true));
3765 +        assertTrue(f.copy().cancel(false));
3766 +        assertTrue(f.copy().completeExceptionally(new CFException()));
3767 +        checkIncomplete(f);
3768      }
3769  
3770      /**
# Line 3610 | Line 3775 | public class CompletableFutureTest exten
3775          CompletableFuture<Integer> f = new CompletableFuture<>();
3776          CompletionStage<Integer> g = f.minimalCompletionStage();
3777          AtomicInteger x = new AtomicInteger(0);
3778 <        AtomicReference<Throwable> r = new AtomicReference<Throwable>();
3778 >        AtomicReference<Throwable> r = new AtomicReference<>();
3779          checkIncomplete(f);
3780          g.whenComplete((v, e) -> {if (e != null) r.set(e); else x.set(v);});
3781          f.complete(1);
# Line 3627 | Line 3792 | public class CompletableFutureTest exten
3792          CompletableFuture<Integer> f = new CompletableFuture<>();
3793          CompletionStage<Integer> g = f.minimalCompletionStage();
3794          AtomicInteger x = new AtomicInteger(0);
3795 <        AtomicReference<Throwable> r = new AtomicReference<Throwable>();
3795 >        AtomicReference<Throwable> r = new AtomicReference<>();
3796          g.whenComplete((v, e) -> {if (e != null) r.set(e); else x.set(v);});
3797          checkIncomplete(f);
3798          CFException ex = new CFException();
# Line 3645 | Line 3810 | public class CompletableFutureTest exten
3810          CFException ex = new CFException();
3811          CompletionStage<Integer> f = CompletableFuture.failedStage(ex);
3812          AtomicInteger x = new AtomicInteger(0);
3813 <        AtomicReference<Throwable> r = new AtomicReference<Throwable>();
3813 >        AtomicReference<Throwable> r = new AtomicReference<>();
3814          f.whenComplete((v, e) -> {if (e != null) r.set(e); else x.set(v);});
3815          assertEquals(x.get(), 0);
3816          assertEquals(r.get(), ex);
# Line 3669 | Line 3834 | public class CompletableFutureTest exten
3834      public void testCompleteAsync2() {
3835          CompletableFuture<Integer> f = new CompletableFuture<>();
3836          CFException ex = new CFException();
3837 <        f.completeAsync(() -> {if (true) throw ex; return 1;});
3837 >        f.completeAsync(() -> { throw ex; });
3838          try {
3839              f.join();
3840              shouldThrow();
# Line 3699 | Line 3864 | public class CompletableFutureTest exten
3864          CompletableFuture<Integer> f = new CompletableFuture<>();
3865          CFException ex = new CFException();
3866          ThreadExecutor executor = new ThreadExecutor();
3867 <        f.completeAsync(() -> {if (true) throw ex; return 1;}, executor);
3867 >        f.completeAsync(() -> { throw ex; }, executor);
3868          try {
3869              f.join();
3870              shouldThrow();
# Line 3858 | Line 4023 | public class CompletableFutureTest exten
4023          List<Function<CompletableFuture<Integer>, CompletableFuture<?>>> funs
4024              = new ArrayList<>();
4025  
4026 <        funs.add((y) -> m.thenRun(y, noopRunnable));
4027 <        funs.add((y) -> m.thenAccept(y, noopConsumer));
4028 <        funs.add((y) -> m.thenApply(y, incFunction));
4029 <
4030 <        funs.add((y) -> m.runAfterEither(y, incomplete, noopRunnable));
4031 <        funs.add((y) -> m.acceptEither(y, incomplete, noopConsumer));
4032 <        funs.add((y) -> m.applyToEither(y, incomplete, incFunction));
4033 <
4034 <        funs.add((y) -> m.runAfterBoth(y, v42, noopRunnable));
4035 <        funs.add((y) -> m.runAfterBoth(v42, y, noopRunnable));
4036 <        funs.add((y) -> m.thenAcceptBoth(y, v42, new SubtractAction(m)));
4037 <        funs.add((y) -> m.thenAcceptBoth(v42, y, new SubtractAction(m)));
4038 <        funs.add((y) -> m.thenCombine(y, v42, new SubtractFunction(m)));
4039 <        funs.add((y) -> m.thenCombine(v42, y, new SubtractFunction(m)));
4040 <
4041 <        funs.add((y) -> m.whenComplete(y, (Integer r, Throwable t) -> {}));
4042 <
4043 <        funs.add((y) -> m.thenCompose(y, new CompletableFutureInc(m)));
4044 <
4045 <        funs.add((y) -> CompletableFuture.allOf(y));
4046 <        funs.add((y) -> CompletableFuture.allOf(y, v42));
4047 <        funs.add((y) -> CompletableFuture.allOf(v42, y));
4048 <        funs.add((y) -> CompletableFuture.anyOf(y));
4049 <        funs.add((y) -> CompletableFuture.anyOf(y, incomplete));
4050 <        funs.add((y) -> CompletableFuture.anyOf(incomplete, y));
4026 >        funs.add(y -> m.thenRun(y, noopRunnable));
4027 >        funs.add(y -> m.thenAccept(y, noopConsumer));
4028 >        funs.add(y -> m.thenApply(y, incFunction));
4029 >
4030 >        funs.add(y -> m.runAfterEither(y, incomplete, noopRunnable));
4031 >        funs.add(y -> m.acceptEither(y, incomplete, noopConsumer));
4032 >        funs.add(y -> m.applyToEither(y, incomplete, incFunction));
4033 >
4034 >        funs.add(y -> m.runAfterBoth(y, v42, noopRunnable));
4035 >        funs.add(y -> m.runAfterBoth(v42, y, noopRunnable));
4036 >        funs.add(y -> m.thenAcceptBoth(y, v42, new SubtractAction(m)));
4037 >        funs.add(y -> m.thenAcceptBoth(v42, y, new SubtractAction(m)));
4038 >        funs.add(y -> m.thenCombine(y, v42, new SubtractFunction(m)));
4039 >        funs.add(y -> m.thenCombine(v42, y, new SubtractFunction(m)));
4040 >
4041 >        funs.add(y -> m.whenComplete(y, (Integer r, Throwable t) -> {}));
4042 >
4043 >        funs.add(y -> m.thenCompose(y, new CompletableFutureInc(m)));
4044 >
4045 >        funs.add(y -> CompletableFuture.allOf(y));
4046 >        funs.add(y -> CompletableFuture.allOf(y, v42));
4047 >        funs.add(y -> CompletableFuture.allOf(v42, y));
4048 >        funs.add(y -> CompletableFuture.anyOf(y));
4049 >        funs.add(y -> CompletableFuture.anyOf(y, incomplete));
4050 >        funs.add(y -> CompletableFuture.anyOf(incomplete, y));
4051  
4052          for (Function<CompletableFuture<Integer>, CompletableFuture<?>>
4053                   fun : funs) {
# Line 3939 | Line 4104 | public class CompletableFutureTest exten
4104      public void testMinimalCompletionStage_minimality() {
4105          if (!testImplementationDetails) return;
4106          Function<Method, String> toSignature =
4107 <            (method) -> method.getName() + Arrays.toString(method.getParameterTypes());
4107 >            method -> method.getName() + Arrays.toString(method.getParameterTypes());
4108          Predicate<Method> isNotStatic =
4109 <            (method) -> (method.getModifiers() & Modifier.STATIC) == 0;
4109 >            method -> (method.getModifiers() & Modifier.STATIC) == 0;
4110          List<Method> minimalMethods =
4111              Stream.of(Object.class, CompletionStage.class)
4112 <            .flatMap((klazz) -> Stream.of(klazz.getMethods()))
4112 >            .flatMap(klazz -> Stream.of(klazz.getMethods()))
4113              .filter(isNotStatic)
4114              .collect(Collectors.toList());
4115          // Methods from CompletableFuture permitted NOT to throw UOE
# Line 3960 | Line 4125 | public class CompletableFutureTest exten
4125              .collect(Collectors.toSet());
4126          List<Method> allMethods = Stream.of(CompletableFuture.class.getMethods())
4127              .filter(isNotStatic)
4128 <            .filter((method) -> !permittedMethodSignatures.contains(toSignature.apply(method)))
4128 >            .filter(method -> !permittedMethodSignatures.contains(toSignature.apply(method)))
4129              .collect(Collectors.toList());
4130  
4131          List<CompletionStage<Integer>> stages = new ArrayList<>();
4132 <        stages.add(new CompletableFuture<Integer>().minimalCompletionStage());
4132 >        CompletionStage<Integer> min =
4133 >            new CompletableFuture<Integer>().minimalCompletionStage();
4134 >        stages.add(min);
4135 >        stages.add(min.thenApply(x -> x));
4136          stages.add(CompletableFuture.completedStage(1));
4137          stages.add(CompletableFuture.failedStage(new CFException()));
4138  
# Line 4000 | Line 4168 | public class CompletableFutureTest exten
4168              throw new Error("Methods did not throw UOE: " + bugs);
4169      }
4170  
4171 +    /**
4172 +     * minimalStage.toCompletableFuture() returns a CompletableFuture that
4173 +     * is completed normally, with the same value, when source is.
4174 +     */
4175 +    public void testMinimalCompletionStage_toCompletableFuture_normalCompletion() {
4176 +        for (boolean createIncomplete : new boolean[] { true, false })
4177 +        for (Integer v1 : new Integer[] { 1, null })
4178 +    {
4179 +        CompletableFuture<Integer> f = new CompletableFuture<>();
4180 +        CompletionStage<Integer> minimal = f.minimalCompletionStage();
4181 +        if (!createIncomplete) assertTrue(f.complete(v1));
4182 +        CompletableFuture<Integer> g = minimal.toCompletableFuture();
4183 +        if (createIncomplete) {
4184 +            checkIncomplete(f);
4185 +            checkIncomplete(g);
4186 +            assertTrue(f.complete(v1));
4187 +        }
4188 +        checkCompletedNormally(f, v1);
4189 +        checkCompletedNormally(g, v1);
4190 +    }}
4191 +
4192 +    /**
4193 +     * minimalStage.toCompletableFuture() returns a CompletableFuture that
4194 +     * is completed exceptionally when source is.
4195 +     */
4196 +    public void testMinimalCompletionStage_toCompletableFuture_exceptionalCompletion() {
4197 +        for (boolean createIncomplete : new boolean[] { true, false })
4198 +    {
4199 +        CFException ex = new CFException();
4200 +        CompletableFuture<Integer> f = new CompletableFuture<>();
4201 +        CompletionStage<Integer> minimal = f.minimalCompletionStage();
4202 +        if (!createIncomplete) f.completeExceptionally(ex);
4203 +        CompletableFuture<Integer> g = minimal.toCompletableFuture();
4204 +        if (createIncomplete) {
4205 +            checkIncomplete(f);
4206 +            checkIncomplete(g);
4207 +            f.completeExceptionally(ex);
4208 +        }
4209 +        checkCompletedExceptionally(f, ex);
4210 +        checkCompletedWithWrappedException(g, ex);
4211 +    }}
4212 +
4213 +    /**
4214 +     * minimalStage.toCompletableFuture() gives mutable CompletableFuture
4215 +     */
4216 +    public void testMinimalCompletionStage_toCompletableFuture_mutable() {
4217 +        for (Integer v1 : new Integer[] { 1, null })
4218 +    {
4219 +        CompletableFuture<Integer> f = new CompletableFuture<>();
4220 +        CompletionStage minimal = f.minimalCompletionStage();
4221 +        CompletableFuture<Integer> g = minimal.toCompletableFuture();
4222 +        assertTrue(g.complete(v1));
4223 +        checkCompletedNormally(g, v1);
4224 +        checkIncomplete(f);
4225 +        checkIncomplete(minimal.toCompletableFuture());
4226 +    }}
4227 +
4228 +    /**
4229 +     * minimalStage.toCompletableFuture().join() awaits completion
4230 +     */
4231 +    public void testMinimalCompletionStage_toCompletableFuture_join() throws Exception {
4232 +        for (boolean createIncomplete : new boolean[] { true, false })
4233 +        for (Integer v1 : new Integer[] { 1, null })
4234 +    {
4235 +        CompletableFuture<Integer> f = new CompletableFuture<>();
4236 +        if (!createIncomplete) assertTrue(f.complete(v1));
4237 +        CompletionStage<Integer> minimal = f.minimalCompletionStage();
4238 +        if (createIncomplete) assertTrue(f.complete(v1));
4239 +        assertEquals(v1, minimal.toCompletableFuture().join());
4240 +        assertEquals(v1, minimal.toCompletableFuture().get());
4241 +        checkCompletedNormally(minimal.toCompletableFuture(), v1);
4242 +    }}
4243 +
4244 +    /**
4245 +     * Completion of a toCompletableFuture copy of a minimal stage
4246 +     * does not complete its source.
4247 +     */
4248 +    public void testMinimalCompletionStage_toCompletableFuture_oneWayPropagation() {
4249 +        CompletableFuture<Integer> f = new CompletableFuture<>();
4250 +        CompletionStage<Integer> g = f.minimalCompletionStage();
4251 +        assertTrue(g.toCompletableFuture().complete(1));
4252 +        assertTrue(g.toCompletableFuture().complete(null));
4253 +        assertTrue(g.toCompletableFuture().cancel(true));
4254 +        assertTrue(g.toCompletableFuture().cancel(false));
4255 +        assertTrue(g.toCompletableFuture().completeExceptionally(new CFException()));
4256 +        checkIncomplete(g.toCompletableFuture());
4257 +        f.complete(1);
4258 +        checkCompletedNormally(g.toCompletableFuture(), 1);
4259 +    }
4260 +
4261 +    /** Demo utility method for external reliable toCompletableFuture */
4262 +    static <T> CompletableFuture<T> toCompletableFuture(CompletionStage<T> stage) {
4263 +        CompletableFuture<T> f = new CompletableFuture<>();
4264 +        stage.handle((T t, Throwable ex) -> {
4265 +                         if (ex != null) f.completeExceptionally(ex);
4266 +                         else f.complete(t);
4267 +                         return null;
4268 +                     });
4269 +        return f;
4270 +    }
4271 +
4272 +    /** Demo utility method to join a CompletionStage */
4273 +    static <T> T join(CompletionStage<T> stage) {
4274 +        return toCompletableFuture(stage).join();
4275 +    }
4276 +
4277 +    /**
4278 +     * Joining a minimal stage "by hand" works
4279 +     */
4280 +    public void testMinimalCompletionStage_join_by_hand() {
4281 +        for (boolean createIncomplete : new boolean[] { true, false })
4282 +        for (Integer v1 : new Integer[] { 1, null })
4283 +    {
4284 +        CompletableFuture<Integer> f = new CompletableFuture<>();
4285 +        CompletionStage<Integer> minimal = f.minimalCompletionStage();
4286 +        CompletableFuture<Integer> g = new CompletableFuture<>();
4287 +        if (!createIncomplete) assertTrue(f.complete(v1));
4288 +        minimal.thenAccept(x -> g.complete(x));
4289 +        if (createIncomplete) assertTrue(f.complete(v1));
4290 +        g.join();
4291 +        checkCompletedNormally(g, v1);
4292 +        checkCompletedNormally(f, v1);
4293 +        assertEquals(v1, join(minimal));
4294 +    }}
4295 +
4296      static class Monad {
4297          static class ZeroException extends RuntimeException {
4298              public ZeroException() { super("monadic zero"); }
# Line 4016 | Line 4309 | public class CompletableFutureTest exten
4309          static <T,U,V> Function<T, CompletableFuture<V>> compose
4310              (Function<T, CompletableFuture<U>> f,
4311               Function<U, CompletableFuture<V>> g) {
4312 <            return (x) -> f.apply(x).thenCompose(g);
4312 >            return x -> f.apply(x).thenCompose(g);
4313          }
4314  
4315          static void assertZero(CompletableFuture<?> f) {
4316              try {
4317                  f.getNow(null);
4318 <                throw new AssertionFailedError("should throw");
4318 >                throw new AssertionError("should throw");
4319              } catch (CompletionException success) {
4320                  assertTrue(success.getCause() instanceof ZeroException);
4321              }
# Line 4096 | Line 4389 | public class CompletableFutureTest exten
4389  
4390          // Some mutually non-commutative functions
4391          Function<Long, CompletableFuture<Long>> triple
4392 <            = (x) -> Monad.unit(3 * x);
4392 >            = x -> Monad.unit(3 * x);
4393          Function<Long, CompletableFuture<Long>> inc
4394 <            = (x) -> Monad.unit(x + 1);
4394 >            = x -> Monad.unit(x + 1);
4395  
4396          // unit is a right identity: m >>= unit === m
4397          Monad.assertFutureEquals(inc.apply(5L).thenCompose(unit),
# Line 4110 | Line 4403 | public class CompletableFutureTest exten
4403          // associativity: (m >>= f) >>= g === m >>= ( \x -> (f x >>= g) )
4404          Monad.assertFutureEquals(
4405              unit.apply(5L).thenCompose(inc).thenCompose(triple),
4406 <            unit.apply(5L).thenCompose((x) -> inc.apply(x).thenCompose(triple)));
4406 >            unit.apply(5L).thenCompose(x -> inc.apply(x).thenCompose(triple)));
4407  
4408          // The case for CompletableFuture as an additive monad is weaker...
4409  
# Line 4120 | Line 4413 | public class CompletableFutureTest exten
4413          // left zero: zero >>= f === zero
4414          Monad.assertZero(zero.thenCompose(inc));
4415          // right zero: f >>= (\x -> zero) === zero
4416 <        Monad.assertZero(inc.apply(5L).thenCompose((x) -> zero));
4416 >        Monad.assertZero(inc.apply(5L).thenCompose(x -> zero));
4417  
4418          // f plus zero === f
4419          Monad.assertFutureEquals(Monad.unit(5L),
# Line 4147 | Line 4440 | public class CompletableFutureTest exten
4440      }
4441  
4442      /** Test long recursive chains of CompletableFutures with cascading completions */
4443 +    @SuppressWarnings("FutureReturnValueIgnored")
4444      public void testRecursiveChains() throws Throwable {
4445          for (ExecutionMode m : ExecutionMode.values())
4446          for (boolean addDeadEnds : new boolean[] { true, false })
# Line 4171 | Line 4465 | public class CompletableFutureTest exten
4465       * A single CompletableFuture with many dependents.
4466       * A demo of scalability - runtime is O(n).
4467       */
4468 +    @SuppressWarnings("FutureReturnValueIgnored")
4469      public void testManyDependents() throws Throwable {
4470          final int n = expensiveTests ? 1_000_000 : 10;
4471          final CompletableFuture<Void> head = new CompletableFuture<>();
# Line 4178 | Line 4473 | public class CompletableFutureTest exten
4473          final AtomicInteger count = new AtomicInteger(0);
4474          for (int i = 0; i < n; i++) {
4475              head.thenRun(() -> count.getAndIncrement());
4476 <            head.thenAccept((x) -> count.getAndIncrement());
4477 <            head.thenApply((x) -> count.getAndIncrement());
4476 >            head.thenAccept(x -> count.getAndIncrement());
4477 >            head.thenApply(x -> count.getAndIncrement());
4478  
4479              head.runAfterBoth(complete, () -> count.getAndIncrement());
4480              head.thenAcceptBoth(complete, (x, y) -> count.getAndIncrement());
# Line 4189 | Line 4484 | public class CompletableFutureTest exten
4484              complete.thenCombine(head, (x, y) -> count.getAndIncrement());
4485  
4486              head.runAfterEither(new CompletableFuture<Void>(), () -> count.getAndIncrement());
4487 <            head.acceptEither(new CompletableFuture<Void>(), (x) -> count.getAndIncrement());
4488 <            head.applyToEither(new CompletableFuture<Void>(), (x) -> count.getAndIncrement());
4487 >            head.acceptEither(new CompletableFuture<Void>(), x -> count.getAndIncrement());
4488 >            head.applyToEither(new CompletableFuture<Void>(), x -> count.getAndIncrement());
4489              new CompletableFuture<Void>().runAfterEither(head, () -> count.getAndIncrement());
4490 <            new CompletableFuture<Void>().acceptEither(head, (x) -> count.getAndIncrement());
4491 <            new CompletableFuture<Void>().applyToEither(head, (x) -> count.getAndIncrement());
4490 >            new CompletableFuture<Void>().acceptEither(head, x -> count.getAndIncrement());
4491 >            new CompletableFuture<Void>().applyToEither(head, x -> count.getAndIncrement());
4492          }
4493          head.complete(null);
4494          assertEquals(5 * 3 * n, count.get());
4495      }
4496  
4497      /** ant -Dvmoptions=-Xmx8m -Djsr166.expensiveTests=true -Djsr166.tckTestClass=CompletableFutureTest tck */
4498 +    @SuppressWarnings("FutureReturnValueIgnored")
4499      public void testCoCompletionGarbageRetention() throws Throwable {
4500          final int n = expensiveTests ? 1_000_000 : 10;
4501          final CompletableFuture<Integer> incomplete = new CompletableFuture<>();
# Line 4210 | Line 4506 | public class CompletableFutureTest exten
4506              f.complete(null);
4507  
4508              f = new CompletableFuture<>();
4509 <            f.acceptEither(incomplete, (x) -> {});
4509 >            f.acceptEither(incomplete, x -> {});
4510              f.complete(null);
4511  
4512              f = new CompletableFuture<>();
4513 <            f.applyToEither(incomplete, (x) -> x);
4513 >            f.applyToEither(incomplete, x -> x);
4514              f.complete(null);
4515  
4516              f = new CompletableFuture<>();
4517 <            CompletableFuture.anyOf(new CompletableFuture<?>[] { f, incomplete });
4517 >            CompletableFuture.anyOf(f, incomplete);
4518              f.complete(null);
4519          }
4520  
# Line 4228 | Line 4524 | public class CompletableFutureTest exten
4524              f.complete(null);
4525  
4526              f = new CompletableFuture<>();
4527 <            incomplete.acceptEither(f, (x) -> {});
4527 >            incomplete.acceptEither(f, x -> {});
4528              f.complete(null);
4529  
4530              f = new CompletableFuture<>();
4531 <            incomplete.applyToEither(f, (x) -> x);
4531 >            incomplete.applyToEither(f, x -> x);
4532              f.complete(null);
4533  
4534              f = new CompletableFuture<>();
4535 <            CompletableFuture.anyOf(new CompletableFuture<?>[] { incomplete, f });
4535 >            CompletableFuture.anyOf(incomplete, f);
4536              f.complete(null);
4537          }
4538      }
# Line 4290 | Line 4586 | public class CompletableFutureTest exten
4586              assertTrue(neverCompleted.thenRun(() -> {}).cancel(true));
4587      }
4588  
4589 +    /**
4590 +     * Checks for garbage retention when MinimalStage.toCompletableFuture()
4591 +     * is invoked many times.
4592 +     * 8161600: Garbage retention when source CompletableFutures are never completed
4593 +     *
4594 +     * As of 2016-07, fails with OOME:
4595 +     * ant -Dvmoptions=-Xmx8m -Djsr166.expensiveTests=true -Djsr166.tckTestClass=CompletableFutureTest -Djsr166.methodFilter=testToCompletableFutureGarbageRetention tck
4596 +     */
4597 +    public void testToCompletableFutureGarbageRetention() throws Throwable {
4598 +        final int n = expensiveTests ? 900_000 : 10;
4599 +        CompletableFuture<Integer> neverCompleted = new CompletableFuture<>();
4600 +        CompletionStage minimal = neverCompleted.minimalCompletionStage();
4601 +        for (int i = 0; i < n; i++)
4602 +            assertTrue(minimal.toCompletableFuture().cancel(true));
4603 +    }
4604 +
4605   //     static <U> U join(CompletionStage<U> stage) {
4606   //         CompletableFuture<U> f = new CompletableFuture<>();
4607   //         stage.whenComplete((v, ex) -> {
# Line 4314 | Line 4626 | public class CompletableFutureTest exten
4626   //         return stage.toCompletableFuture().copy().isDone();
4627   //     }
4628  
4629 +    // For testing default implementations
4630 +    // Only non-default interface methods defined.
4631 +    static final class DelegatedCompletionStage<T> implements CompletionStage<T> {
4632 +        final CompletableFuture<T> cf;
4633 +        DelegatedCompletionStage(CompletableFuture<T> cf) { this.cf = cf; }
4634 +        public CompletableFuture<T> toCompletableFuture() {
4635 +            return cf; }
4636 +        public CompletionStage<Void> thenRun
4637 +            (Runnable action) {
4638 +            return cf.thenRun(action); }
4639 +        public CompletionStage<Void> thenRunAsync
4640 +            (Runnable action) {
4641 +            return cf.thenRunAsync(action); }
4642 +        public CompletionStage<Void> thenRunAsync
4643 +            (Runnable action,
4644 +             Executor executor) {
4645 +            return cf.thenRunAsync(action, executor); }
4646 +        public CompletionStage<Void> thenAccept
4647 +            (Consumer<? super T> action) {
4648 +            return cf.thenAccept(action); }
4649 +        public CompletionStage<Void> thenAcceptAsync
4650 +            (Consumer<? super T> action) {
4651 +            return cf.thenAcceptAsync(action); }
4652 +        public CompletionStage<Void> thenAcceptAsync
4653 +            (Consumer<? super T> action,
4654 +             Executor executor) {
4655 +            return cf.thenAcceptAsync(action, executor); }
4656 +        public <U> CompletionStage<U> thenApply
4657 +            (Function<? super T,? extends U> a) {
4658 +            return cf.thenApply(a); }
4659 +        public <U> CompletionStage<U> thenApplyAsync
4660 +            (Function<? super T,? extends U> fn) {
4661 +            return cf.thenApplyAsync(fn); }
4662 +        public <U> CompletionStage<U> thenApplyAsync
4663 +            (Function<? super T,? extends U> fn,
4664 +             Executor executor) {
4665 +            return cf.thenApplyAsync(fn, executor); }
4666 +        public <U,V> CompletionStage<V> thenCombine
4667 +            (CompletionStage<? extends U> other,
4668 +             BiFunction<? super T,? super U,? extends V> fn) {
4669 +            return cf.thenCombine(other, fn); }
4670 +        public <U,V> CompletionStage<V> thenCombineAsync
4671 +            (CompletionStage<? extends U> other,
4672 +             BiFunction<? super T,? super U,? extends V> fn) {
4673 +            return cf.thenCombineAsync(other, fn); }
4674 +        public <U,V> CompletionStage<V> thenCombineAsync
4675 +            (CompletionStage<? extends U> other,
4676 +             BiFunction<? super T,? super U,? extends V> fn,
4677 +             Executor executor) {
4678 +            return cf.thenCombineAsync(other, fn, executor); }
4679 +        public <U> CompletionStage<Void> thenAcceptBoth
4680 +            (CompletionStage<? extends U> other,
4681 +             BiConsumer<? super T, ? super U> action) {
4682 +            return cf.thenAcceptBoth(other, action); }
4683 +        public <U> CompletionStage<Void> thenAcceptBothAsync
4684 +            (CompletionStage<? extends U> other,
4685 +             BiConsumer<? super T, ? super U> action) {
4686 +            return cf.thenAcceptBothAsync(other, action); }
4687 +        public <U> CompletionStage<Void> thenAcceptBothAsync
4688 +            (CompletionStage<? extends U> other,
4689 +             BiConsumer<? super T, ? super U> action,
4690 +             Executor executor) {
4691 +            return cf.thenAcceptBothAsync(other, action, executor); }
4692 +        public CompletionStage<Void> runAfterBoth
4693 +            (CompletionStage<?> other,
4694 +             Runnable action) {
4695 +            return cf.runAfterBoth(other, action); }
4696 +        public CompletionStage<Void> runAfterBothAsync
4697 +            (CompletionStage<?> other,
4698 +             Runnable action) {
4699 +            return cf.runAfterBothAsync(other, action); }
4700 +        public CompletionStage<Void> runAfterBothAsync
4701 +            (CompletionStage<?> other,
4702 +             Runnable action,
4703 +             Executor executor) {
4704 +            return cf.runAfterBothAsync(other, action, executor); }
4705 +        public <U> CompletionStage<U> applyToEither
4706 +            (CompletionStage<? extends T> other,
4707 +             Function<? super T, U> fn) {
4708 +            return cf.applyToEither(other, fn); }
4709 +        public <U> CompletionStage<U> applyToEitherAsync
4710 +            (CompletionStage<? extends T> other,
4711 +             Function<? super T, U> fn) {
4712 +            return cf.applyToEitherAsync(other, fn); }
4713 +        public <U> CompletionStage<U> applyToEitherAsync
4714 +            (CompletionStage<? extends T> other,
4715 +             Function<? super T, U> fn,
4716 +             Executor executor) {
4717 +            return cf.applyToEitherAsync(other, fn, executor); }
4718 +        public CompletionStage<Void> acceptEither
4719 +            (CompletionStage<? extends T> other,
4720 +             Consumer<? super T> action) {
4721 +            return cf.acceptEither(other, action); }
4722 +        public CompletionStage<Void> acceptEitherAsync
4723 +            (CompletionStage<? extends T> other,
4724 +             Consumer<? super T> action) {
4725 +            return cf.acceptEitherAsync(other, action); }
4726 +        public CompletionStage<Void> acceptEitherAsync
4727 +            (CompletionStage<? extends T> other,
4728 +             Consumer<? super T> action,
4729 +             Executor executor) {
4730 +            return cf.acceptEitherAsync(other, action, executor); }
4731 +        public CompletionStage<Void> runAfterEither
4732 +            (CompletionStage<?> other,
4733 +             Runnable action) {
4734 +            return cf.runAfterEither(other, action); }
4735 +        public CompletionStage<Void> runAfterEitherAsync
4736 +            (CompletionStage<?> other,
4737 +             Runnable action) {
4738 +            return cf.runAfterEitherAsync(other, action); }
4739 +        public CompletionStage<Void> runAfterEitherAsync
4740 +            (CompletionStage<?> other,
4741 +             Runnable action,
4742 +             Executor executor) {
4743 +            return cf.runAfterEitherAsync(other, action, executor); }
4744 +        public <U> CompletionStage<U> thenCompose
4745 +            (Function<? super T, ? extends CompletionStage<U>> fn) {
4746 +            return cf.thenCompose(fn); }
4747 +        public <U> CompletionStage<U> thenComposeAsync
4748 +            (Function<? super T, ? extends CompletionStage<U>> fn) {
4749 +            return cf.thenComposeAsync(fn); }
4750 +        public <U> CompletionStage<U> thenComposeAsync
4751 +            (Function<? super T, ? extends CompletionStage<U>> fn,
4752 +             Executor executor) {
4753 +            return cf.thenComposeAsync(fn, executor); }
4754 +        public <U> CompletionStage<U> handle
4755 +            (BiFunction<? super T, Throwable, ? extends U> fn) {
4756 +            return cf.handle(fn); }
4757 +        public <U> CompletionStage<U> handleAsync
4758 +            (BiFunction<? super T, Throwable, ? extends U> fn) {
4759 +            return cf.handleAsync(fn); }
4760 +        public <U> CompletionStage<U> handleAsync
4761 +            (BiFunction<? super T, Throwable, ? extends U> fn,
4762 +             Executor executor) {
4763 +            return cf.handleAsync(fn, executor); }
4764 +        public CompletionStage<T> whenComplete
4765 +            (BiConsumer<? super T, ? super Throwable> action) {
4766 +            return cf.whenComplete(action); }
4767 +        public CompletionStage<T> whenCompleteAsync
4768 +            (BiConsumer<? super T, ? super Throwable> action) {
4769 +            return cf.whenCompleteAsync(action); }
4770 +        public CompletionStage<T> whenCompleteAsync
4771 +            (BiConsumer<? super T, ? super Throwable> action,
4772 +             Executor executor) {
4773 +            return cf.whenCompleteAsync(action, executor); }
4774 +        public CompletionStage<T> exceptionally
4775 +            (Function<Throwable, ? extends T> fn) {
4776 +            return cf.exceptionally(fn); }
4777 +    }
4778 +
4779 +    /**
4780 +     * default-implemented exceptionallyAsync action is not invoked when
4781 +     * source completes normally, and source result is propagated
4782 +     */
4783 +    public void testDefaultExceptionallyAsync_normalCompletion() {
4784 +        for (boolean createIncomplete : new boolean[] { true, false })
4785 +        for (Integer v1 : new Integer[] { 1, null })
4786 +    {
4787 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
4788 +        final DelegatedCompletionStage<Integer> d =
4789 +            new DelegatedCompletionStage<Integer>(f);
4790 +        if (!createIncomplete) assertTrue(f.complete(v1));
4791 +        final CompletionStage<Integer> g = d.exceptionallyAsync
4792 +            ((Throwable t) -> {
4793 +                threadFail("should not be called");
4794 +                return null;            // unreached
4795 +            });
4796 +        if (createIncomplete) assertTrue(f.complete(v1));
4797 +
4798 +        checkCompletedNormally(g.toCompletableFuture(), v1);
4799 +    }}
4800 +
4801 +    /**
4802 +     * default-implemented exceptionallyAsync action completes with
4803 +     * function value on source exception
4804 +     */
4805 +    public void testDefaultExceptionallyAsync_exceptionalCompletion() {
4806 +        for (boolean createIncomplete : new boolean[] { true, false })
4807 +        for (Integer v1 : new Integer[] { 1, null })
4808 +    {
4809 +        final AtomicInteger a = new AtomicInteger(0);
4810 +        final CFException ex = new CFException();
4811 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
4812 +        final DelegatedCompletionStage<Integer> d =
4813 +            new DelegatedCompletionStage<Integer>(f);
4814 +        if (!createIncomplete) f.completeExceptionally(ex);
4815 +        final CompletionStage<Integer> g = d.exceptionallyAsync
4816 +            ((Throwable t) -> {
4817 +                threadAssertSame(t, ex);
4818 +                a.getAndIncrement();
4819 +                return v1;
4820 +            });
4821 +        if (createIncomplete) f.completeExceptionally(ex);
4822 +
4823 +        checkCompletedNormally(g.toCompletableFuture(), v1);
4824 +        assertEquals(1, a.get());
4825 +    }}
4826 +
4827 +    /**
4828 +     * Under default implementation, if an "exceptionally action"
4829 +     * throws an exception, it completes exceptionally with that
4830 +     * exception
4831 +     */
4832 +    public void testDefaultExceptionallyAsync_exceptionalCompletionActionFailed() {
4833 +        for (boolean createIncomplete : new boolean[] { true, false })
4834 +    {
4835 +        final AtomicInteger a = new AtomicInteger(0);
4836 +        final CFException ex1 = new CFException();
4837 +        final CFException ex2 = new CFException();
4838 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
4839 +        final DelegatedCompletionStage<Integer> d =
4840 +            new DelegatedCompletionStage<Integer>(f);
4841 +        if (!createIncomplete) f.completeExceptionally(ex1);
4842 +        final CompletionStage<Integer> g = d.exceptionallyAsync
4843 +            ((Throwable t) -> {
4844 +                threadAssertSame(t, ex1);
4845 +                a.getAndIncrement();
4846 +                throw ex2;
4847 +            });
4848 +        if (createIncomplete) f.completeExceptionally(ex1);
4849 +
4850 +        checkCompletedWithWrappedException(g.toCompletableFuture(), ex2);
4851 +        checkCompletedExceptionally(f, ex1);
4852 +        checkCompletedExceptionally(d.toCompletableFuture(), ex1);
4853 +        assertEquals(1, a.get());
4854 +    }}
4855 +
4856 +    /**
4857 +     * default exceptionallyCompose result completes normally after normal
4858 +     * completion of source
4859 +     */
4860 +    public void testDefaultExceptionallyCompose_normalCompletion() {
4861 +        for (boolean createIncomplete : new boolean[] { true, false })
4862 +        for (Integer v1 : new Integer[] { 1, null })
4863 +    {
4864 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
4865 +        final ExceptionalCompletableFutureFunction r =
4866 +            new ExceptionalCompletableFutureFunction(ExecutionMode.SYNC);
4867 +        final DelegatedCompletionStage<Integer> d =
4868 +            new DelegatedCompletionStage<Integer>(f);
4869 +        if (!createIncomplete) assertTrue(f.complete(v1));
4870 +        final CompletionStage<Integer> g = d.exceptionallyCompose(r);
4871 +        if (createIncomplete) assertTrue(f.complete(v1));
4872 +
4873 +        checkCompletedNormally(f, v1);
4874 +        checkCompletedNormally(g.toCompletableFuture(), v1);
4875 +        r.assertNotInvoked();
4876 +    }}
4877 +
4878 +    /**
4879 +     * default-implemented exceptionallyCompose result completes
4880 +     * normally after exceptional completion of source
4881 +     */
4882 +    public void testDefaultExceptionallyCompose_exceptionalCompletion() {
4883 +        for (boolean createIncomplete : new boolean[] { true, false })
4884 +    {
4885 +        final CFException ex = new CFException();
4886 +        final ExceptionalCompletableFutureFunction r =
4887 +            new ExceptionalCompletableFutureFunction(ExecutionMode.SYNC);
4888 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
4889 +        final DelegatedCompletionStage<Integer> d =
4890 +            new DelegatedCompletionStage<Integer>(f);
4891 +        if (!createIncomplete) f.completeExceptionally(ex);
4892 +        final CompletionStage<Integer> g = d.exceptionallyCompose(r);
4893 +        if (createIncomplete) f.completeExceptionally(ex);
4894 +
4895 +        checkCompletedExceptionally(f, ex);
4896 +        checkCompletedNormally(g.toCompletableFuture(), r.value);
4897 +        r.assertInvoked();
4898 +    }}
4899 +
4900 +    /**
4901 +     * default-implemented exceptionallyCompose completes
4902 +     * exceptionally on exception if action does
4903 +     */
4904 +    public void testDefaultExceptionallyCompose_actionFailed() {
4905 +        for (boolean createIncomplete : new boolean[] { true, false })
4906 +        for (Integer v1 : new Integer[] { 1, null })
4907 +    {
4908 +        final CFException ex = new CFException();
4909 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
4910 +        final FailingExceptionalCompletableFutureFunction r
4911 +            = new FailingExceptionalCompletableFutureFunction(ExecutionMode.SYNC);
4912 +        final DelegatedCompletionStage<Integer> d =
4913 +            new DelegatedCompletionStage<Integer>(f);
4914 +        if (!createIncomplete) f.completeExceptionally(ex);
4915 +        final CompletionStage<Integer> g = d.exceptionallyCompose(r);
4916 +        if (createIncomplete) f.completeExceptionally(ex);
4917 +
4918 +        checkCompletedExceptionally(f, ex);
4919 +        checkCompletedWithWrappedException(g.toCompletableFuture(), r.ex);
4920 +        r.assertInvoked();
4921 +    }}
4922 +
4923 +    /**
4924 +     * default exceptionallyComposeAsync result completes normally after normal
4925 +     * completion of source
4926 +     */
4927 +    public void testDefaultExceptionallyComposeAsync_normalCompletion() {
4928 +        for (boolean createIncomplete : new boolean[] { true, false })
4929 +        for (Integer v1 : new Integer[] { 1, null })
4930 +    {
4931 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
4932 +        final ExceptionalCompletableFutureFunction r =
4933 +            new ExceptionalCompletableFutureFunction(ExecutionMode.ASYNC);
4934 +        final DelegatedCompletionStage<Integer> d =
4935 +            new DelegatedCompletionStage<Integer>(f);
4936 +        if (!createIncomplete) assertTrue(f.complete(v1));
4937 +        final CompletionStage<Integer> g = d.exceptionallyComposeAsync(r);
4938 +        if (createIncomplete) assertTrue(f.complete(v1));
4939 +
4940 +        checkCompletedNormally(f, v1);
4941 +        checkCompletedNormally(g.toCompletableFuture(), v1);
4942 +        r.assertNotInvoked();
4943 +    }}
4944 +
4945 +    /**
4946 +     * default-implemented exceptionallyComposeAsync result completes
4947 +     * normally after exceptional completion of source
4948 +     */
4949 +    public void testDefaultExceptionallyComposeAsync_exceptionalCompletion() {
4950 +        for (boolean createIncomplete : new boolean[] { true, false })
4951 +    {
4952 +        final CFException ex = new CFException();
4953 +        final ExceptionalCompletableFutureFunction r =
4954 +            new ExceptionalCompletableFutureFunction(ExecutionMode.ASYNC);
4955 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
4956 +        final DelegatedCompletionStage<Integer> d =
4957 +            new DelegatedCompletionStage<Integer>(f);
4958 +        if (!createIncomplete) f.completeExceptionally(ex);
4959 +        final CompletionStage<Integer> g = d.exceptionallyComposeAsync(r);
4960 +        if (createIncomplete) f.completeExceptionally(ex);
4961 +
4962 +        checkCompletedExceptionally(f, ex);
4963 +        checkCompletedNormally(g.toCompletableFuture(), r.value);
4964 +        r.assertInvoked();
4965 +    }}
4966 +
4967 +    /**
4968 +     * default-implemented exceptionallyComposeAsync completes
4969 +     * exceptionally on exception if action does
4970 +     */
4971 +    public void testDefaultExceptionallyComposeAsync_actionFailed() {
4972 +        for (boolean createIncomplete : new boolean[] { true, false })
4973 +        for (Integer v1 : new Integer[] { 1, null })
4974 +    {
4975 +        final CFException ex = new CFException();
4976 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
4977 +        final FailingExceptionalCompletableFutureFunction r
4978 +            = new FailingExceptionalCompletableFutureFunction(ExecutionMode.ASYNC);
4979 +        final DelegatedCompletionStage<Integer> d =
4980 +            new DelegatedCompletionStage<Integer>(f);
4981 +        if (!createIncomplete) f.completeExceptionally(ex);
4982 +        final CompletionStage<Integer> g = d.exceptionallyComposeAsync(r);
4983 +        if (createIncomplete) f.completeExceptionally(ex);
4984 +
4985 +        checkCompletedExceptionally(f, ex);
4986 +        checkCompletedWithWrappedException(g.toCompletableFuture(), r.ex);
4987 +        r.assertInvoked();
4988 +    }}
4989 +
4990 +
4991 +    /**
4992 +     * default exceptionallyComposeAsync result completes normally after normal
4993 +     * completion of source
4994 +     */
4995 +    public void testDefaultExceptionallyComposeAsyncExecutor_normalCompletion() {
4996 +        for (boolean createIncomplete : new boolean[] { true, false })
4997 +        for (Integer v1 : new Integer[] { 1, null })
4998 +    {
4999 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
5000 +        final ExceptionalCompletableFutureFunction r =
5001 +            new ExceptionalCompletableFutureFunction(ExecutionMode.EXECUTOR);
5002 +        final DelegatedCompletionStage<Integer> d =
5003 +            new DelegatedCompletionStage<Integer>(f);
5004 +        if (!createIncomplete) assertTrue(f.complete(v1));
5005 +        final CompletionStage<Integer> g = d.exceptionallyComposeAsync(r, new ThreadExecutor());
5006 +        if (createIncomplete) assertTrue(f.complete(v1));
5007 +
5008 +        checkCompletedNormally(f, v1);
5009 +        checkCompletedNormally(g.toCompletableFuture(), v1);
5010 +        r.assertNotInvoked();
5011 +    }}
5012 +
5013 +    /**
5014 +     * default-implemented exceptionallyComposeAsync result completes
5015 +     * normally after exceptional completion of source
5016 +     */
5017 +    public void testDefaultExceptionallyComposeAsyncExecutor_exceptionalCompletion() {
5018 +        for (boolean createIncomplete : new boolean[] { true, false })
5019 +    {
5020 +        final CFException ex = new CFException();
5021 +        final ExceptionalCompletableFutureFunction r =
5022 +            new ExceptionalCompletableFutureFunction(ExecutionMode.EXECUTOR);
5023 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
5024 +        final DelegatedCompletionStage<Integer> d =
5025 +            new DelegatedCompletionStage<Integer>(f);
5026 +        if (!createIncomplete) f.completeExceptionally(ex);
5027 +        final CompletionStage<Integer> g = d.exceptionallyComposeAsync(r, new ThreadExecutor());
5028 +        if (createIncomplete) f.completeExceptionally(ex);
5029 +
5030 +        checkCompletedExceptionally(f, ex);
5031 +        checkCompletedNormally(g.toCompletableFuture(), r.value);
5032 +        r.assertInvoked();
5033 +    }}
5034 +
5035 +    /**
5036 +     * default-implemented exceptionallyComposeAsync completes
5037 +     * exceptionally on exception if action does
5038 +     */
5039 +    public void testDefaultExceptionallyComposeAsyncExecutor_actionFailed() {
5040 +        for (boolean createIncomplete : new boolean[] { true, false })
5041 +        for (Integer v1 : new Integer[] { 1, null })
5042 +    {
5043 +        final CFException ex = new CFException();
5044 +        final CompletableFuture<Integer> f = new CompletableFuture<>();
5045 +        final FailingExceptionalCompletableFutureFunction r
5046 +            = new FailingExceptionalCompletableFutureFunction(ExecutionMode.EXECUTOR);
5047 +        final DelegatedCompletionStage<Integer> d =
5048 +            new DelegatedCompletionStage<Integer>(f);
5049 +        if (!createIncomplete) f.completeExceptionally(ex);
5050 +        final CompletionStage<Integer> g = d.exceptionallyComposeAsync(r, new ThreadExecutor());
5051 +        if (createIncomplete) f.completeExceptionally(ex);
5052 +
5053 +        checkCompletedExceptionally(f, ex);
5054 +        checkCompletedWithWrappedException(g.toCompletableFuture(), r.ex);
5055 +        r.assertInvoked();
5056 +    }}
5057 +
5058   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines