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.106 by jsr166, Thu Sep 3 17:01:22 2015 UTC vs.
Revision 1.124 by jsr166, Thu Sep 10 17:51:37 2015 UTC

# Line 8 | Line 8
8   import static java.util.concurrent.TimeUnit.MILLISECONDS;
9   import static java.util.concurrent.TimeUnit.SECONDS;
10  
11 + import java.lang.reflect.Method;
12 + import java.lang.reflect.Modifier;
13 +
14 + import java.util.stream.Collectors;
15 + import java.util.stream.Stream;
16 +
17   import java.util.ArrayList;
18 + import java.util.Arrays;
19   import java.util.List;
20   import java.util.Objects;
21 + import java.util.Set;
22   import java.util.concurrent.Callable;
23   import java.util.concurrent.CancellationException;
24   import java.util.concurrent.CompletableFuture;
# Line 28 | Line 36 | import java.util.function.BiConsumer;
36   import java.util.function.BiFunction;
37   import java.util.function.Consumer;
38   import java.util.function.Function;
39 + import java.util.function.Predicate;
40   import java.util.function.Supplier;
41  
42   import junit.framework.Test;
# Line 77 | Line 86 | public class CompletableFutureTest exten
86          assertTrue(f.toString().contains("[Completed normally]"));
87      }
88  
89 <    void checkCompletedWithWrappedCFException(CompletableFuture<?> f) {
90 <        long startTime = System.nanoTime();
91 <        long timeoutMillis = LONG_DELAY_MS;
92 <        try {
93 <            f.get(timeoutMillis, MILLISECONDS);
94 <            shouldThrow();
95 <        } catch (ExecutionException success) {
96 <            assertTrue(success.getCause() instanceof CFException);
97 <        } catch (Throwable fail) { threadUnexpectedException(fail); }
98 <        assertTrue(millisElapsedSince(startTime) < timeoutMillis/2);
99 <
100 <        try {
101 <            f.join();
102 <            shouldThrow();
103 <        } catch (CompletionException success) {
104 <            assertTrue(success.getCause() instanceof CFException);
105 <        }
97 <        try {
98 <            f.getNow(null);
99 <            shouldThrow();
100 <        } catch (CompletionException success) {
101 <            assertTrue(success.getCause() instanceof CFException);
89 >    /**
90 >     * Returns the "raw" internal exceptional completion of f,
91 >     * without any additional wrapping with CompletionException.
92 >     */
93 >    <U> Throwable exceptionalCompletion(CompletableFuture<U> f) {
94 >        // handle (and whenComplete) can distinguish between "direct"
95 >        // and "wrapped" exceptional completion
96 >        return f.handle((U u, Throwable t) -> t).join();
97 >    }
98 >
99 >    void checkCompletedExceptionally(CompletableFuture<?> f,
100 >                                     boolean wrapped,
101 >                                     Consumer<Throwable> checker) {
102 >        Throwable cause = exceptionalCompletion(f);
103 >        if (wrapped) {
104 >            assertTrue(cause instanceof CompletionException);
105 >            cause = cause.getCause();
106          }
107 <        try {
104 <            f.get();
105 <            shouldThrow();
106 <        } catch (ExecutionException success) {
107 <            assertTrue(success.getCause() instanceof CFException);
108 <        } catch (Throwable fail) { threadUnexpectedException(fail); }
109 <        assertTrue(f.isDone());
110 <        assertFalse(f.isCancelled());
111 <        assertTrue(f.toString().contains("[Completed exceptionally]"));
112 <    }
107 >        checker.accept(cause);
108  
114    <U> void checkCompletedExceptionallyWithRootCause(CompletableFuture<U> f,
115                                                      Throwable ex) {
109          long startTime = System.nanoTime();
117        long timeoutMillis = LONG_DELAY_MS;
110          try {
111 <            f.get(timeoutMillis, MILLISECONDS);
111 >            f.get(LONG_DELAY_MS, MILLISECONDS);
112              shouldThrow();
113          } catch (ExecutionException success) {
114 <            assertSame(ex, success.getCause());
114 >            assertSame(cause, success.getCause());
115          } catch (Throwable fail) { threadUnexpectedException(fail); }
116 <        assertTrue(millisElapsedSince(startTime) < timeoutMillis/2);
116 >        assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS / 2);
117  
118          try {
119              f.join();
120              shouldThrow();
121          } catch (CompletionException success) {
122 <            assertSame(ex, success.getCause());
123 <        }
122 >            assertSame(cause, success.getCause());
123 >        } catch (Throwable fail) { threadUnexpectedException(fail); }
124 >
125          try {
126              f.getNow(null);
127              shouldThrow();
128          } catch (CompletionException success) {
129 <            assertSame(ex, success.getCause());
130 <        }
129 >            assertSame(cause, success.getCause());
130 >        } catch (Throwable fail) { threadUnexpectedException(fail); }
131 >
132          try {
133              f.get();
134              shouldThrow();
135          } catch (ExecutionException success) {
136 <            assertSame(ex, success.getCause());
136 >            assertSame(cause, success.getCause());
137          } catch (Throwable fail) { threadUnexpectedException(fail); }
138  
145        assertTrue(f.isDone());
139          assertFalse(f.isCancelled());
140 +        assertTrue(f.isDone());
141 +        assertTrue(f.isCompletedExceptionally());
142          assertTrue(f.toString().contains("[Completed exceptionally]"));
143      }
144  
145 <    <U> void checkCompletedExceptionallyWithTimeout(CompletableFuture<U> f) {
146 <        long startTime = System.nanoTime();
147 <        long timeoutMillis = LONG_DELAY_MS;
148 <        try {
154 <            f.get(timeoutMillis, MILLISECONDS);
155 <            shouldThrow();
156 <        } catch (ExecutionException ex) {
157 <            assertTrue(ex.getCause() instanceof TimeoutException);
158 <        } catch (Throwable fail) { threadUnexpectedException(fail); }
159 <        assertTrue(millisElapsedSince(startTime) < timeoutMillis/2);
160 <
161 <        try {
162 <            f.join();
163 <            shouldThrow();
164 <        } catch (Throwable ex) {
165 <            assertTrue(ex.getCause() instanceof TimeoutException);
166 <        }
167 <
168 <        try {
169 <            f.getNow(null);
170 <            shouldThrow();
171 <        } catch (Throwable ex) {
172 <            assertTrue(ex.getCause() instanceof TimeoutException);
173 <        }
145 >    void checkCompletedWithWrappedCFException(CompletableFuture<?> f) {
146 >        checkCompletedExceptionally(f, true,
147 >            (t) -> assertTrue(t instanceof CFException));
148 >    }
149  
150 <        try {
151 <            f.get();
152 <            shouldThrow();
153 <        } catch (ExecutionException ex) {
179 <            assertTrue(ex.getCause() instanceof TimeoutException);
180 <        } catch (Throwable fail) { threadUnexpectedException(fail); }
150 >    void checkCompletedWithWrappedCancellationException(CompletableFuture<?> f) {
151 >        checkCompletedExceptionally(f, true,
152 >            (t) -> assertTrue(t instanceof CancellationException));
153 >    }
154  
155 <        assertTrue(f.isDone());
156 <        assertFalse(f.isCancelled());
157 <        assertTrue(f.toString().contains("[Completed exceptionally]"));
155 >    void checkCompletedWithTimeoutException(CompletableFuture<?> f) {
156 >        checkCompletedExceptionally(f, false,
157 >            (t) -> assertTrue(t instanceof TimeoutException));
158      }
159  
160 <    <U> void checkCompletedWithWrappedException(CompletableFuture<U> f,
161 <                                                Throwable ex) {
162 <        checkCompletedExceptionallyWithRootCause(f, ex);
190 <        try {
191 <            CompletableFuture<Throwable> spy = f.handle
192 <                ((U u, Throwable t) -> t);
193 <            assertTrue(spy.join() instanceof CompletionException);
194 <            assertSame(ex, spy.join().getCause());
195 <        } catch (Throwable fail) { threadUnexpectedException(fail); }
160 >    void checkCompletedWithWrappedException(CompletableFuture<?> f,
161 >                                            Throwable ex) {
162 >        checkCompletedExceptionally(f, true, (t) -> assertSame(t, ex));
163      }
164  
165 <    <U> void checkCompletedExceptionally(CompletableFuture<U> f, Throwable ex) {
166 <        checkCompletedExceptionallyWithRootCause(f, ex);
200 <        try {
201 <            CompletableFuture<Throwable> spy = f.handle
202 <                ((U u, Throwable t) -> t);
203 <            assertSame(ex, spy.join());
204 <        } catch (Throwable fail) { threadUnexpectedException(fail); }
165 >    void checkCompletedExceptionally(CompletableFuture<?> f, Throwable ex) {
166 >        checkCompletedExceptionally(f, false, (t) -> assertSame(t, ex));
167      }
168  
169      void checkCancelled(CompletableFuture<?> f) {
170          long startTime = System.nanoTime();
209        long timeoutMillis = LONG_DELAY_MS;
171          try {
172 <            f.get(timeoutMillis, MILLISECONDS);
172 >            f.get(LONG_DELAY_MS, MILLISECONDS);
173              shouldThrow();
174          } catch (CancellationException success) {
175          } catch (Throwable fail) { threadUnexpectedException(fail); }
176 <        assertTrue(millisElapsedSince(startTime) < timeoutMillis/2);
176 >        assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS / 2);
177  
178          try {
179              f.join();
# Line 227 | Line 188 | public class CompletableFutureTest exten
188              shouldThrow();
189          } catch (CancellationException success) {
190          } catch (Throwable fail) { threadUnexpectedException(fail); }
230        assertTrue(f.isDone());
231        assertTrue(f.isCompletedExceptionally());
232        assertTrue(f.isCancelled());
233        assertTrue(f.toString().contains("[Completed exceptionally]"));
234    }
191  
192 <    void checkCompletedWithWrappedCancellationException(CompletableFuture<?> f) {
237 <        long startTime = System.nanoTime();
238 <        long timeoutMillis = LONG_DELAY_MS;
239 <        try {
240 <            f.get(timeoutMillis, MILLISECONDS);
241 <            shouldThrow();
242 <        } catch (ExecutionException success) {
243 <            assertTrue(success.getCause() instanceof CancellationException);
244 <        } catch (Throwable fail) { threadUnexpectedException(fail); }
245 <        assertTrue(millisElapsedSince(startTime) < timeoutMillis/2);
192 >        assertTrue(exceptionalCompletion(f) instanceof CancellationException);
193  
247        try {
248            f.join();
249            shouldThrow();
250        } catch (CompletionException success) {
251            assertTrue(success.getCause() instanceof CancellationException);
252        }
253        try {
254            f.getNow(null);
255            shouldThrow();
256        } catch (CompletionException success) {
257            assertTrue(success.getCause() instanceof CancellationException);
258        }
259        try {
260            f.get();
261            shouldThrow();
262        } catch (ExecutionException success) {
263            assertTrue(success.getCause() instanceof CancellationException);
264        } catch (Throwable fail) { threadUnexpectedException(fail); }
194          assertTrue(f.isDone());
266        assertFalse(f.isCancelled());
195          assertTrue(f.isCompletedExceptionally());
196 +        assertTrue(f.isCancelled());
197          assertTrue(f.toString().contains("[Completed exceptionally]"));
198      }
199  
# Line 3142 | Line 3071 | public class CompletableFutureTest exten
3071              for (int i = 0; i < k; i++) {
3072                  checkIncomplete(f);
3073                  checkIncomplete(CompletableFuture.allOf(fs));
3074 <                if (i != k/2) {
3074 >                if (i != k / 2) {
3075                      fs[i].complete(i);
3076                      checkCompletedNormally(fs[i], i);
3077                  } else {
# Line 3333 | Line 3262 | public class CompletableFutureTest exten
3262              () -> f.exceptionally(null),
3263  
3264              () -> f.handle(null),
3265 +
3266              () -> CompletableFuture.allOf((CompletableFuture<?>)null),
3267              () -> CompletableFuture.allOf((CompletableFuture<?>[])null),
3268              () -> CompletableFuture.allOf(f, null),
# Line 3344 | Line 3274 | public class CompletableFutureTest exten
3274              () -> CompletableFuture.anyOf(null, f),
3275  
3276              () -> f.obtrudeException(null),
3277 +
3278 +            () -> CompletableFuture.delayedExecutor(1L, SECONDS, null),
3279 +            () -> CompletableFuture.delayedExecutor(1L, null, new ThreadExecutor()),
3280 +            () -> CompletableFuture.delayedExecutor(1L, null),
3281 +
3282 +            () -> f.orTimeout(1L, null),
3283 +            () -> f.completeOnTimeout(42, 1L, null),
3284 +
3285 +            () -> CompletableFuture.failedFuture(null),
3286 +            () -> CompletableFuture.failedStage(null),
3287          };
3288  
3289          assertThrows(NullPointerException.class, throwingActions);
# Line 3364 | Line 3304 | public class CompletableFutureTest exten
3304       * newIncompleteFuture returns an incomplete CompletableFuture
3305       */
3306      public void testNewIncompleteFuture() {
3307 +        for (Integer v1 : new Integer[] { 1, null })
3308 +    {
3309          CompletableFuture<Integer> f = new CompletableFuture<>();
3310          CompletableFuture<Integer> g = f.newIncompleteFuture();
3311          checkIncomplete(f);
3312          checkIncomplete(g);
3313 <    }
3313 >        f.complete(v1);
3314 >        checkCompletedNormally(f, v1);
3315 >        checkIncomplete(g);
3316 >        g.complete(v1);
3317 >        checkCompletedNormally(g, v1);
3318 >        assertSame(g.getClass(), CompletableFuture.class);
3319 >    }}
3320  
3321      /**
3322       * completedStage returns a completed CompletionStage
3323       */
3324      public void testCompletedStage() {
3325 <        AtomicInteger x = new AtomicInteger();
3325 >        AtomicInteger x = new AtomicInteger(0);
3326          AtomicReference<Throwable> r = new AtomicReference<Throwable>();
3327          CompletionStage<Integer> f = CompletableFuture.completedStage(1);
3328          f.whenComplete((v, e) -> {if (e != null) r.set(e); else x.set(v);});
# Line 3384 | Line 3332 | public class CompletableFutureTest exten
3332  
3333      /**
3334       * defaultExecutor by default returns the commonPool if
3335 <     * it supports at least one thread.
3335 >     * it supports more than one thread.
3336       */
3337      public void testDefaultExecutor() {
3338          CompletableFuture<Integer> f = new CompletableFuture<>();
3339          Executor e = f.defaultExecutor();
3340 <        Executor c =  ForkJoinPool.commonPool();
3340 >        Executor c = ForkJoinPool.commonPool();
3341          if (ForkJoinPool.getCommonPoolParallelism() > 1)
3342              assertSame(e, c);
3343 +        else
3344 +            assertNotSame(e, c);
3345      }
3346  
3347      /**
# Line 3401 | Line 3351 | public class CompletableFutureTest exten
3351      public void testFailedFuture() {
3352          CFException ex = new CFException();
3353          CompletableFuture<Integer> f = CompletableFuture.failedFuture(ex);
3354 <        checkCompletedExceptionallyWithRootCause(f, ex);
3354 >        checkCompletedExceptionally(f, ex);
3355      }
3356  
3357      /**
3358       * failedFuture(null) throws NPE
3359       */
3360 <    public void testFailedFuture2() {
3360 >    public void testFailedFuture_null() {
3361          try {
3362              CompletableFuture<Integer> f = CompletableFuture.failedFuture(null);
3363              shouldThrow();
# Line 3440 | Line 3390 | public class CompletableFutureTest exten
3390          CFException ex = new CFException();
3391          f.completeExceptionally(ex);
3392          checkCompletedExceptionally(f, ex);
3393 <        checkCompletedWithWrappedCFException(g);
3393 >        checkCompletedWithWrappedException(g, ex);
3394      }
3395  
3396      /**
# Line 3450 | Line 3400 | public class CompletableFutureTest exten
3400      public void testMinimalCompletionStage() {
3401          CompletableFuture<Integer> f = new CompletableFuture<>();
3402          CompletionStage<Integer> g = f.minimalCompletionStage();
3403 <        AtomicInteger x = new AtomicInteger();
3403 >        AtomicInteger x = new AtomicInteger(0);
3404          AtomicReference<Throwable> r = new AtomicReference<Throwable>();
3405          checkIncomplete(f);
3406          g.whenComplete((v, e) -> {if (e != null) r.set(e); else x.set(v);});
# Line 3467 | Line 3417 | public class CompletableFutureTest exten
3417      public void testMinimalCompletionStage2() {
3418          CompletableFuture<Integer> f = new CompletableFuture<>();
3419          CompletionStage<Integer> g = f.minimalCompletionStage();
3420 <        AtomicInteger x = new AtomicInteger();
3420 >        AtomicInteger x = new AtomicInteger(0);
3421          AtomicReference<Throwable> r = new AtomicReference<Throwable>();
3422          g.whenComplete((v, e) -> {if (e != null) r.set(e); else x.set(v);});
3423          checkIncomplete(f);
# Line 3479 | Line 3429 | public class CompletableFutureTest exten
3429      }
3430  
3431      /**
3432 <     * failedStage returns a Completionstage completed
3432 >     * failedStage returns a CompletionStage completed
3433       * exceptionally with the given Exception
3434       */
3435      public void testFailedStage() {
3436          CFException ex = new CFException();
3437          CompletionStage<Integer> f = CompletableFuture.failedStage(ex);
3438 <        AtomicInteger x = new AtomicInteger();
3438 >        AtomicInteger x = new AtomicInteger(0);
3439          AtomicReference<Throwable> r = new AtomicReference<Throwable>();
3440          f.whenComplete((v, e) -> {if (e != null) r.set(e); else x.set(v);});
3441          assertEquals(x.get(), 0);
3442 <        assertEquals(r.get().getCause(), ex);
3442 >        assertEquals(r.get(), ex);
3443      }
3444  
3445      /**
3446       * completeAsync completes with value of given supplier
3447       */
3448      public void testCompleteAsync() {
3449 +        for (Integer v1 : new Integer[] { 1, null })
3450 +    {
3451          CompletableFuture<Integer> f = new CompletableFuture<>();
3452 <        f.completeAsync(() -> 1);
3452 >        f.completeAsync(() -> v1);
3453          f.join();
3454 <        checkCompletedNormally(f, 1);
3455 <    }
3454 >        checkCompletedNormally(f, v1);
3455 >    }}
3456  
3457      /**
3458       * completeAsync completes exceptionally if given supplier throws
# Line 3512 | Line 3464 | public class CompletableFutureTest exten
3464          try {
3465              f.join();
3466              shouldThrow();
3467 <        } catch (Exception success) {}
3468 <        checkCompletedWithWrappedCFException(f);
3467 >        } catch (CompletionException success) {}
3468 >        checkCompletedWithWrappedException(f, ex);
3469      }
3470  
3471      /**
3472       * completeAsync with given executor completes with value of given supplier
3473       */
3474      public void testCompleteAsync3() {
3475 +        for (Integer v1 : new Integer[] { 1, null })
3476 +    {
3477          CompletableFuture<Integer> f = new CompletableFuture<>();
3478 <        f.completeAsync(() -> 1, new ThreadExecutor());
3479 <        f.join();
3480 <        checkCompletedNormally(f, 1);
3481 <    }
3478 >        ThreadExecutor executor = new ThreadExecutor();
3479 >        f.completeAsync(() -> v1, executor);
3480 >        assertSame(v1, f.join());
3481 >        checkCompletedNormally(f, v1);
3482 >        assertEquals(1, executor.count.get());
3483 >    }}
3484  
3485      /**
3486       * completeAsync with given executor completes exceptionally if
# Line 3533 | Line 3489 | public class CompletableFutureTest exten
3489      public void testCompleteAsync4() {
3490          CompletableFuture<Integer> f = new CompletableFuture<>();
3491          CFException ex = new CFException();
3492 <        f.completeAsync(() -> {if (true) throw ex; return 1;}, new ThreadExecutor());
3492 >        ThreadExecutor executor = new ThreadExecutor();
3493 >        f.completeAsync(() -> {if (true) throw ex; return 1;}, executor);
3494          try {
3495              f.join();
3496              shouldThrow();
3497 <        } catch (Exception success) {}
3498 <        checkCompletedWithWrappedCFException(f);
3497 >        } catch (CompletionException success) {}
3498 >        checkCompletedWithWrappedException(f, ex);
3499 >        assertEquals(1, executor.count.get());
3500      }
3501  
3502      /**
3503       * orTimeout completes with TimeoutException if not complete
3504       */
3505 <    public void testOrTimeout() {
3505 >    public void testOrTimeout_timesOut() {
3506 >        long timeoutMillis = timeoutMillis();
3507          CompletableFuture<Integer> f = new CompletableFuture<>();
3508 <        f.orTimeout(SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
3509 <        checkCompletedExceptionallyWithTimeout(f);
3508 >        long startTime = System.nanoTime();
3509 >        f.orTimeout(timeoutMillis, MILLISECONDS);
3510 >        checkCompletedWithTimeoutException(f);
3511 >        assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
3512      }
3513  
3514      /**
3515       * orTimeout completes normally if completed before timeout
3516       */
3517 <    public void testOrTimeout2() {
3517 >    public void testOrTimeout_completed() {
3518 >        for (Integer v1 : new Integer[] { 1, null })
3519 >    {
3520          CompletableFuture<Integer> f = new CompletableFuture<>();
3521 <        f.complete(1);
3522 <        f.orTimeout(SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
3523 <        checkCompletedNormally(f, 1);
3524 <    }
3521 >        CompletableFuture<Integer> g = new CompletableFuture<>();
3522 >        long startTime = System.nanoTime();
3523 >        f.complete(v1);
3524 >        f.orTimeout(LONG_DELAY_MS, MILLISECONDS);
3525 >        g.orTimeout(LONG_DELAY_MS, MILLISECONDS);
3526 >        g.complete(v1);
3527 >        checkCompletedNormally(f, v1);
3528 >        checkCompletedNormally(g, v1);
3529 >        assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS / 2);
3530 >    }}
3531  
3532      /**
3533       * completeOnTimeout completes with given value if not complete
3534       */
3535 <    public void testCompleteOnTimeout() {
3535 >    public void testCompleteOnTimeout_timesOut() {
3536 >        testInParallel(() -> testCompleteOnTimeout_timesOut(42),
3537 >                       () -> testCompleteOnTimeout_timesOut(null));
3538 >    }
3539 >
3540 >    public void testCompleteOnTimeout_timesOut(Integer v) {
3541 >        long timeoutMillis = timeoutMillis();
3542          CompletableFuture<Integer> f = new CompletableFuture<>();
3543 <        f.completeOnTimeout(-1, SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
3544 <        f.join();
3545 <        checkCompletedNormally(f, -1);
3543 >        long startTime = System.nanoTime();
3544 >        f.completeOnTimeout(v, timeoutMillis, MILLISECONDS);
3545 >        assertSame(v, f.join());
3546 >        assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
3547 >        f.complete(99);         // should have no effect
3548 >        checkCompletedNormally(f, v);
3549      }
3550  
3551      /**
3552       * completeOnTimeout has no effect if completed within timeout
3553       */
3554 <    public void testCompleteOnTimeout2() {
3554 >    public void testCompleteOnTimeout_completed() {
3555 >        for (Integer v1 : new Integer[] { 1, null })
3556 >    {
3557          CompletableFuture<Integer> f = new CompletableFuture<>();
3558 <        f.complete(1);
3559 <        f.completeOnTimeout(-1, SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
3560 <        checkCompletedNormally(f, 1);
3561 <    }
3558 >        CompletableFuture<Integer> g = new CompletableFuture<>();
3559 >        long startTime = System.nanoTime();
3560 >        f.complete(v1);
3561 >        f.completeOnTimeout(-1, LONG_DELAY_MS, MILLISECONDS);
3562 >        g.completeOnTimeout(-1, LONG_DELAY_MS, MILLISECONDS);
3563 >        g.complete(v1);
3564 >        checkCompletedNormally(f, v1);
3565 >        checkCompletedNormally(g, v1);
3566 >        assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS / 2);
3567 >    }}
3568  
3569      /**
3570       * delayedExecutor returns an executor that delays submission
3571       */
3572      public void testDelayedExecutor() {
3573 <        long timeoutMillis = SMALL_DELAY_MS;
3574 <        Executor d = CompletableFuture.delayedExecutor(timeoutMillis,
3575 <                                                       MILLISECONDS);
3573 >        testInParallel(() -> testDelayedExecutor(null, null),
3574 >                       () -> testDelayedExecutor(null, 1),
3575 >                       () -> testDelayedExecutor(new ThreadExecutor(), 1),
3576 >                       () -> testDelayedExecutor(new ThreadExecutor(), 1));
3577 >    }
3578 >
3579 >    public void testDelayedExecutor(Executor executor, Integer v) throws Exception {
3580 >        long timeoutMillis = timeoutMillis();
3581 >        // Use an "unreasonably long" long timeout to catch lingering threads
3582 >        long longTimeoutMillis = 1000 * 60 * 60 * 24;
3583 >        final Executor delayer, longDelayer;
3584 >        if (executor == null) {
3585 >            delayer = CompletableFuture.delayedExecutor(timeoutMillis, MILLISECONDS);
3586 >            longDelayer = CompletableFuture.delayedExecutor(longTimeoutMillis, MILLISECONDS);
3587 >        } else {
3588 >            delayer = CompletableFuture.delayedExecutor(timeoutMillis, MILLISECONDS, executor);
3589 >            longDelayer = CompletableFuture.delayedExecutor(longTimeoutMillis, MILLISECONDS, executor);
3590 >        }
3591          long startTime = System.nanoTime();
3592 <        CompletableFuture<Integer> f = CompletableFuture.supplyAsync(() -> 1, d);
3593 <        assertNull(f.getNow(null));
3594 <        try {
3595 <            f.get(LONG_DELAY_MS, MILLISECONDS);
3596 <        } catch (Throwable fail) { threadUnexpectedException(fail); }
3597 <        assertTrue(millisElapsedSince(startTime) > timeoutMillis/2);
3598 <        checkCompletedNormally(f, 1);
3599 <    }
3592 >        CompletableFuture<Integer> f =
3593 >            CompletableFuture.supplyAsync(() -> v, delayer);
3594 >        CompletableFuture<Integer> g =
3595 >            CompletableFuture.supplyAsync(() -> v, longDelayer);
3596 >
3597 >        assertNull(g.getNow(null));
3598 >
3599 >        assertSame(v, f.get(LONG_DELAY_MS, MILLISECONDS));
3600 >        long millisElapsed = millisElapsedSince(startTime);
3601 >        assertTrue(millisElapsed >= timeoutMillis);
3602 >        assertTrue(millisElapsed < LONG_DELAY_MS / 2);
3603  
3604 <    /**
3605 <     * delayedExecutor for a given executor returns an executor that
3606 <     * delays submission
3607 <     */
3604 <    public void testDelayedExecutor2() {
3605 <        long timeoutMillis = SMALL_DELAY_MS;
3606 <        Executor d = CompletableFuture.delayedExecutor(timeoutMillis,
3607 <                                                       MILLISECONDS,
3608 <                                                       new ThreadExecutor());
3609 <        long startTime = System.nanoTime();
3610 <        CompletableFuture<Integer> f = CompletableFuture.supplyAsync(() -> 1, d);
3611 <        assertNull(f.getNow(null));
3612 <        try {
3613 <            f.get(LONG_DELAY_MS, MILLISECONDS);
3614 <        } catch (Throwable fail) { threadUnexpectedException(fail); }
3615 <        assertTrue(millisElapsedSince(startTime) > timeoutMillis/2);
3616 <        checkCompletedNormally(f, 1);
3604 >        checkCompletedNormally(f, v);
3605 >
3606 >        checkIncomplete(g);
3607 >        assertTrue(g.cancel(true));
3608      }
3609  
3610      //--- tests of implementation details; not part of official tck ---
# Line 3706 | Line 3697 | public class CompletableFutureTest exten
3697          }
3698      }}
3699  
3700 +    /**
3701 +     * Minimal completion stages throw UOE for all non-CompletionStage methods
3702 +     */
3703 +    public void testMinimalCompletionStage_minimality() {
3704 +        if (!testImplementationDetails) return;
3705 +        Function<Method, String> toSignature =
3706 +            (method) -> method.getName() + Arrays.toString(method.getParameterTypes());
3707 +        Predicate<Method> isNotStatic =
3708 +            (method) -> (method.getModifiers() & Modifier.STATIC) == 0;
3709 +        List<Method> minimalMethods =
3710 +            Stream.of(Object.class, CompletionStage.class)
3711 +            .map((klazz) -> Stream.of(klazz.getMethods()))
3712 +            .reduce(Stream::concat)
3713 +            .orElseGet(Stream::empty)
3714 +            .filter(isNotStatic)
3715 +            .collect(Collectors.toList());
3716 +        // Methods from CompletableFuture permitted NOT to throw UOE
3717 +        String[] signatureWhitelist = {
3718 +            "newIncompleteFuture[]",
3719 +            "defaultExecutor[]",
3720 +            "minimalCompletionStage[]",
3721 +            "copy[]",
3722 +        };
3723 +        Set<String> permittedMethodSignatures =
3724 +            Stream.concat(minimalMethods.stream().map(toSignature),
3725 +                          Stream.of(signatureWhitelist))
3726 +            .collect(Collectors.toSet());
3727 +        List<Method> allMethods = Stream.of(CompletableFuture.class.getMethods())
3728 +            .filter(isNotStatic)
3729 +            .filter((method) -> !permittedMethodSignatures.contains(toSignature.apply(method)))
3730 +            .collect(Collectors.toList());
3731 +
3732 +        CompletionStage<Integer> minimalStage =
3733 +            new CompletableFuture<Integer>().minimalCompletionStage();
3734 +
3735 +        List<Method> bugs = new ArrayList<>();
3736 +        for (Method method : allMethods) {
3737 +            Class<?>[] parameterTypes = method.getParameterTypes();
3738 +            Object[] args = new Object[parameterTypes.length];
3739 +            // Manufacture boxed primitives for primitive params
3740 +            for (int i = 0; i < args.length; i++) {
3741 +                Class<?> type = parameterTypes[i];
3742 +                if (parameterTypes[i] == boolean.class)
3743 +                    args[i] = false;
3744 +                else if (parameterTypes[i] == int.class)
3745 +                    args[i] = 0;
3746 +                else if (parameterTypes[i] == long.class)
3747 +                    args[i] = 0L;
3748 +            }
3749 +            try {
3750 +                method.invoke(minimalStage, args);
3751 +                bugs.add(method);
3752 +            }
3753 +            catch (java.lang.reflect.InvocationTargetException expected) {
3754 +                if (! (expected.getCause() instanceof UnsupportedOperationException)) {
3755 +                    bugs.add(method);
3756 +                    // expected.getCause().printStackTrace();
3757 +                }
3758 +            }
3759 +            catch (ReflectiveOperationException bad) { throw new Error(bad); }
3760 +        }
3761 +        if (!bugs.isEmpty())
3762 +            throw new Error("Methods did not throw UOE: " + bugs.toString());
3763 +    }
3764 +
3765 + //     static <U> U join(CompletionStage<U> stage) {
3766 + //         CompletableFuture<U> f = new CompletableFuture<>();
3767 + //         stage.whenComplete((v, ex) -> {
3768 + //             if (ex != null) f.completeExceptionally(ex); else f.complete(v);
3769 + //         });
3770 + //         return f.join();
3771 + //     }
3772 +
3773 + //     static <U> boolean isDone(CompletionStage<U> stage) {
3774 + //         CompletableFuture<U> f = new CompletableFuture<>();
3775 + //         stage.whenComplete((v, ex) -> {
3776 + //             if (ex != null) f.completeExceptionally(ex); else f.complete(v);
3777 + //         });
3778 + //         return f.isDone();
3779 + //     }
3780 +
3781 + //     static <U> U join2(CompletionStage<U> stage) {
3782 + //         return stage.toCompletableFuture().copy().join();
3783 + //     }
3784 +
3785 + //     static <U> boolean isDone2(CompletionStage<U> stage) {
3786 + //         return stage.toCompletableFuture().copy().isDone();
3787 + //     }
3788 +
3789   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines