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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines