ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/ScheduledExecutorSubclassTest.java
(Generate patch)

Comparing jsr166/src/test/tck/ScheduledExecutorSubclassTest.java (file contents):
Revision 1.35 by jsr166, Sat Apr 25 04:55:31 2015 UTC vs.
Revision 1.68 by jsr166, Mon May 29 22:44:27 2017 UTC

# Line 5 | Line 5
5   */
6  
7   import static java.util.concurrent.TimeUnit.MILLISECONDS;
8 + import static java.util.concurrent.TimeUnit.NANOSECONDS;
9 + import static java.util.concurrent.TimeUnit.SECONDS;
10  
11   import java.util.ArrayList;
12 + import java.util.Collection;
13 + import java.util.Collections;
14 + import java.util.HashSet;
15   import java.util.List;
16   import java.util.concurrent.BlockingQueue;
17   import java.util.concurrent.Callable;
18 + import java.util.concurrent.CancellationException;
19   import java.util.concurrent.CountDownLatch;
20   import java.util.concurrent.Delayed;
21   import java.util.concurrent.ExecutionException;
16 import java.util.concurrent.Executors;
22   import java.util.concurrent.ExecutorService;
23   import java.util.concurrent.Future;
24   import java.util.concurrent.RejectedExecutionException;
# Line 22 | Line 27 | import java.util.concurrent.RunnableSche
27   import java.util.concurrent.ScheduledFuture;
28   import java.util.concurrent.ScheduledThreadPoolExecutor;
29   import java.util.concurrent.ThreadFactory;
30 + import java.util.concurrent.ThreadLocalRandom;
31   import java.util.concurrent.ThreadPoolExecutor;
32   import java.util.concurrent.TimeoutException;
33   import java.util.concurrent.TimeUnit;
34 + import java.util.concurrent.atomic.AtomicBoolean;
35   import java.util.concurrent.atomic.AtomicInteger;
36 + import java.util.concurrent.atomic.AtomicLong;
37 + import java.util.stream.Stream;
38  
39   import junit.framework.Test;
40   import junit.framework.TestSuite;
# Line 39 | Line 48 | public class ScheduledExecutorSubclassTe
48      }
49  
50      static class CustomTask<V> implements RunnableScheduledFuture<V> {
51 <        RunnableScheduledFuture<V> task;
51 >        private final RunnableScheduledFuture<V> task;
52          volatile boolean ran;
53 <        CustomTask(RunnableScheduledFuture<V> t) { task = t; }
53 >        CustomTask(RunnableScheduledFuture<V> task) { this.task = task; }
54          public boolean isPeriodic() { return task.isPeriodic(); }
55          public void run() {
56              ran = true;
# Line 96 | Line 105 | public class ScheduledExecutorSubclassTe
105       * execute successfully executes a runnable
106       */
107      public void testExecute() throws InterruptedException {
108 <        CustomExecutor p = new CustomExecutor(1);
109 <        final CountDownLatch done = new CountDownLatch(1);
110 <        final Runnable task = new CheckedRunnable() {
111 <            public void realRun() {
112 <                done.countDown();
104 <            }};
105 <        try {
108 >        final CustomExecutor p = new CustomExecutor(1);
109 >        try (PoolCleaner cleaner = cleaner(p)) {
110 >            final CountDownLatch done = new CountDownLatch(1);
111 >            final Runnable task = new CheckedRunnable() {
112 >                public void realRun() { done.countDown(); }};
113              p.execute(task);
114 <            assertTrue(done.await(SMALL_DELAY_MS, MILLISECONDS));
108 <        } finally {
109 <            joinPool(p);
114 >            await(done);
115          }
116      }
117  
# Line 114 | Line 119 | public class ScheduledExecutorSubclassTe
119       * delayed schedule of callable successfully executes after delay
120       */
121      public void testSchedule1() throws Exception {
117        CustomExecutor p = new CustomExecutor(1);
118        final long startTime = System.nanoTime();
122          final CountDownLatch done = new CountDownLatch(1);
123 <        try {
123 >        final CustomExecutor p = new CustomExecutor(1);
124 >        try (PoolCleaner cleaner = cleaner(p, done)) {
125 >            final long startTime = System.nanoTime();
126              Callable task = new CheckedCallable<Boolean>() {
127                  public Boolean realCall() {
128                      done.countDown();
# Line 127 | Line 132 | public class ScheduledExecutorSubclassTe
132              Future f = p.schedule(task, timeoutMillis(), MILLISECONDS);
133              assertSame(Boolean.TRUE, f.get());
134              assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
130            assertTrue(done.await(0L, MILLISECONDS));
131        } finally {
132            joinPool(p);
135          }
136      }
137  
# Line 137 | Line 139 | public class ScheduledExecutorSubclassTe
139       * delayed schedule of runnable successfully executes after delay
140       */
141      public void testSchedule3() throws Exception {
142 <        CustomExecutor p = new CustomExecutor(1);
143 <        final long startTime = System.nanoTime();
144 <        final CountDownLatch done = new CountDownLatch(1);
145 <        try {
142 >        final CustomExecutor p = new CustomExecutor(1);
143 >        try (PoolCleaner cleaner = cleaner(p)) {
144 >            final long startTime = System.nanoTime();
145 >            final CountDownLatch done = new CountDownLatch(1);
146              Runnable task = new CheckedRunnable() {
147                  public void realRun() {
148                      done.countDown();
# Line 150 | Line 152 | public class ScheduledExecutorSubclassTe
152              await(done);
153              assertNull(f.get(LONG_DELAY_MS, MILLISECONDS));
154              assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
153        } finally {
154            joinPool(p);
155          }
156      }
157  
# Line 159 | Line 159 | public class ScheduledExecutorSubclassTe
159       * scheduleAtFixedRate executes runnable after given initial delay
160       */
161      public void testSchedule4() throws InterruptedException {
162 <        CustomExecutor p = new CustomExecutor(1);
163 <        final long startTime = System.nanoTime();
164 <        final CountDownLatch done = new CountDownLatch(1);
165 <        try {
162 >        final CustomExecutor p = new CustomExecutor(1);
163 >        try (PoolCleaner cleaner = cleaner(p)) {
164 >            final long startTime = System.nanoTime();
165 >            final CountDownLatch done = new CountDownLatch(1);
166              Runnable task = new CheckedRunnable() {
167                  public void realRun() {
168                      done.countDown();
# Line 174 | Line 174 | public class ScheduledExecutorSubclassTe
174              await(done);
175              assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
176              f.cancel(true);
177        } finally {
178            joinPool(p);
177          }
178      }
179  
# Line 183 | Line 181 | public class ScheduledExecutorSubclassTe
181       * scheduleWithFixedDelay executes runnable after given initial delay
182       */
183      public void testSchedule5() throws InterruptedException {
184 <        CustomExecutor p = new CustomExecutor(1);
185 <        final long startTime = System.nanoTime();
186 <        final CountDownLatch done = new CountDownLatch(1);
187 <        try {
184 >        final CustomExecutor p = new CustomExecutor(1);
185 >        try (PoolCleaner cleaner = cleaner(p)) {
186 >            final long startTime = System.nanoTime();
187 >            final CountDownLatch done = new CountDownLatch(1);
188              Runnable task = new CheckedRunnable() {
189                  public void realRun() {
190                      done.countDown();
# Line 198 | Line 196 | public class ScheduledExecutorSubclassTe
196              await(done);
197              assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
198              f.cancel(true);
201        } finally {
202            joinPool(p);
199          }
200      }
201  
# Line 209 | Line 205 | public class ScheduledExecutorSubclassTe
205      }
206  
207      /**
208 <     * scheduleAtFixedRate executes series of tasks at given rate
208 >     * scheduleAtFixedRate executes series of tasks at given rate.
209 >     * Eventually, it must hold that:
210 >     *   cycles - 1 <= elapsedMillis/delay < cycles
211       */
212      public void testFixedRateSequence() throws InterruptedException {
213 <        CustomExecutor p = new CustomExecutor(1);
214 <        try {
213 >        final CustomExecutor p = new CustomExecutor(1);
214 >        try (PoolCleaner cleaner = cleaner(p)) {
215              for (int delay = 1; delay <= LONG_DELAY_MS; delay *= 3) {
216 <                long startTime = System.nanoTime();
217 <                int cycles = 10;
216 >                final long startTime = System.nanoTime();
217 >                final int cycles = 8;
218                  final CountDownLatch done = new CountDownLatch(cycles);
219 <                Runnable task = new CheckedRunnable() {
219 >                final Runnable task = new CheckedRunnable() {
220                      public void realRun() { done.countDown(); }};
221 <                ScheduledFuture h =
221 >                final ScheduledFuture periodicTask =
222                      p.scheduleAtFixedRate(task, 0, delay, MILLISECONDS);
223 <                done.await();
224 <                h.cancel(true);
225 <                double normalizedTime =
226 <                    (double) millisElapsedSince(startTime) / delay;
227 <                if (normalizedTime >= cycles - 1 &&
228 <                    normalizedTime <= cycles)
223 >                final int totalDelayMillis = (cycles - 1) * delay;
224 >                await(done, totalDelayMillis + LONG_DELAY_MS);
225 >                periodicTask.cancel(true);
226 >                final long elapsedMillis = millisElapsedSince(startTime);
227 >                assertTrue(elapsedMillis >= totalDelayMillis);
228 >                if (elapsedMillis <= cycles * delay)
229                      return;
230 +                // else retry with longer delay
231              }
232 <            throw new AssertionError("unexpected execution rate");
234 <        } finally {
235 <            joinPool(p);
232 >            fail("unexpected execution rate");
233          }
234      }
235  
236      /**
237 <     * scheduleWithFixedDelay executes series of tasks with given period
237 >     * scheduleWithFixedDelay executes series of tasks with given period.
238 >     * Eventually, it must hold that each task starts at least delay and at
239 >     * most 2 * delay after the termination of the previous task.
240       */
241      public void testFixedDelaySequence() throws InterruptedException {
242 <        CustomExecutor p = new CustomExecutor(1);
243 <        try {
242 >        final CustomExecutor p = new CustomExecutor(1);
243 >        try (PoolCleaner cleaner = cleaner(p)) {
244              for (int delay = 1; delay <= LONG_DELAY_MS; delay *= 3) {
245 <                long startTime = System.nanoTime();
246 <                int cycles = 10;
245 >                final long startTime = System.nanoTime();
246 >                final AtomicLong previous = new AtomicLong(startTime);
247 >                final AtomicBoolean tryLongerDelay = new AtomicBoolean(false);
248 >                final int cycles = 8;
249                  final CountDownLatch done = new CountDownLatch(cycles);
250 <                Runnable task = new CheckedRunnable() {
251 <                    public void realRun() { done.countDown(); }};
252 <                ScheduledFuture h =
250 >                final int d = delay;
251 >                final Runnable task = new CheckedRunnable() {
252 >                    public void realRun() {
253 >                        long now = System.nanoTime();
254 >                        long elapsedMillis
255 >                            = NANOSECONDS.toMillis(now - previous.get());
256 >                        if (done.getCount() == cycles) { // first execution
257 >                            if (elapsedMillis >= d)
258 >                                tryLongerDelay.set(true);
259 >                        } else {
260 >                            assertTrue(elapsedMillis >= d);
261 >                            if (elapsedMillis >= 2 * d)
262 >                                tryLongerDelay.set(true);
263 >                        }
264 >                        previous.set(now);
265 >                        done.countDown();
266 >                    }};
267 >                final ScheduledFuture periodicTask =
268                      p.scheduleWithFixedDelay(task, 0, delay, MILLISECONDS);
269 <                done.await();
270 <                h.cancel(true);
271 <                double normalizedTime =
272 <                    (double) millisElapsedSince(startTime) / delay;
273 <                if (normalizedTime >= cycles - 1 &&
274 <                    normalizedTime <= cycles)
269 >                final int totalDelayMillis = (cycles - 1) * delay;
270 >                await(done, totalDelayMillis + cycles * LONG_DELAY_MS);
271 >                periodicTask.cancel(true);
272 >                final long elapsedMillis = millisElapsedSince(startTime);
273 >                assertTrue(elapsedMillis >= totalDelayMillis);
274 >                if (!tryLongerDelay.get())
275                      return;
276 +                // else retry with longer delay
277              }
278 <            throw new AssertionError("unexpected execution rate");
262 <        } finally {
263 <            joinPool(p);
278 >            fail("unexpected execution rate");
279          }
280      }
281  
# Line 268 | Line 283 | public class ScheduledExecutorSubclassTe
283       * execute(null) throws NPE
284       */
285      public void testExecuteNull() throws InterruptedException {
286 <        CustomExecutor se = new CustomExecutor(1);
287 <        try {
288 <            se.execute(null);
289 <            shouldThrow();
290 <        } catch (NullPointerException success) {}
291 <        joinPool(se);
286 >        final CustomExecutor p = new CustomExecutor(1);
287 >        try (PoolCleaner cleaner = cleaner(p)) {
288 >            try {
289 >                p.execute(null);
290 >                shouldThrow();
291 >            } catch (NullPointerException success) {}
292 >        }
293      }
294  
295      /**
296       * schedule(null) throws NPE
297       */
298      public void testScheduleNull() throws InterruptedException {
299 <        CustomExecutor se = new CustomExecutor(1);
300 <        try {
301 <            TrackedCallable callable = null;
302 <            Future f = se.schedule(callable, SHORT_DELAY_MS, MILLISECONDS);
303 <            shouldThrow();
304 <        } catch (NullPointerException success) {}
305 <        joinPool(se);
299 >        final CustomExecutor p = new CustomExecutor(1);
300 >        try (PoolCleaner cleaner = cleaner(p)) {
301 >            try {
302 >                Future f = p.schedule((Callable)null,
303 >                                      randomTimeout(), randomTimeUnit());
304 >                shouldThrow();
305 >            } catch (NullPointerException success) {}
306 >        }
307      }
308  
309      /**
310       * execute throws RejectedExecutionException if shutdown
311       */
312      public void testSchedule1_RejectedExecutionException() {
313 <        CustomExecutor se = new CustomExecutor(1);
314 <        try {
315 <            se.shutdown();
316 <            se.schedule(new NoOpRunnable(),
317 <                        MEDIUM_DELAY_MS, MILLISECONDS);
318 <            shouldThrow();
319 <        } catch (RejectedExecutionException success) {
320 <        } catch (SecurityException ok) {
313 >        final CustomExecutor p = new CustomExecutor(1);
314 >        try (PoolCleaner cleaner = cleaner(p)) {
315 >            try {
316 >                p.shutdown();
317 >                p.schedule(new NoOpRunnable(),
318 >                           randomTimeout(), randomTimeUnit());
319 >                shouldThrow();
320 >            } catch (RejectedExecutionException success) {
321 >            } catch (SecurityException ok) {}
322          }
305
306        joinPool(se);
323      }
324  
325      /**
326       * schedule throws RejectedExecutionException if shutdown
327       */
328      public void testSchedule2_RejectedExecutionException() {
329 <        CustomExecutor se = new CustomExecutor(1);
330 <        try {
331 <            se.shutdown();
332 <            se.schedule(new NoOpCallable(),
333 <                        MEDIUM_DELAY_MS, MILLISECONDS);
334 <            shouldThrow();
335 <        } catch (RejectedExecutionException success) {
336 <        } catch (SecurityException ok) {
329 >        final CustomExecutor p = new CustomExecutor(1);
330 >        try (PoolCleaner cleaner = cleaner(p)) {
331 >            try {
332 >                p.shutdown();
333 >                p.schedule(new NoOpCallable(),
334 >                           randomTimeout(), randomTimeUnit());
335 >                shouldThrow();
336 >            } catch (RejectedExecutionException success) {
337 >            } catch (SecurityException ok) {}
338          }
322        joinPool(se);
339      }
340  
341      /**
342       * schedule callable throws RejectedExecutionException if shutdown
343       */
344      public void testSchedule3_RejectedExecutionException() {
345 <        CustomExecutor se = new CustomExecutor(1);
346 <        try {
347 <            se.shutdown();
348 <            se.schedule(new NoOpCallable(),
349 <                        MEDIUM_DELAY_MS, MILLISECONDS);
350 <            shouldThrow();
351 <        } catch (RejectedExecutionException success) {
352 <        } catch (SecurityException ok) {
345 >        final CustomExecutor p = new CustomExecutor(1);
346 >        try (PoolCleaner cleaner = cleaner(p)) {
347 >            try {
348 >                p.shutdown();
349 >                p.schedule(new NoOpCallable(),
350 >                           randomTimeout(), randomTimeUnit());
351 >                shouldThrow();
352 >            } catch (RejectedExecutionException success) {
353 >            } catch (SecurityException ok) {}
354          }
338        joinPool(se);
355      }
356  
357      /**
358       * scheduleAtFixedRate throws RejectedExecutionException if shutdown
359       */
360      public void testScheduleAtFixedRate1_RejectedExecutionException() {
361 <        CustomExecutor se = new CustomExecutor(1);
362 <        try {
363 <            se.shutdown();
364 <            se.scheduleAtFixedRate(new NoOpRunnable(),
365 <                                   MEDIUM_DELAY_MS, MEDIUM_DELAY_MS, MILLISECONDS);
366 <            shouldThrow();
367 <        } catch (RejectedExecutionException success) {
368 <        } catch (SecurityException ok) {
361 >        final CustomExecutor p = new CustomExecutor(1);
362 >        try (PoolCleaner cleaner = cleaner(p)) {
363 >            try {
364 >                p.shutdown();
365 >                p.scheduleAtFixedRate(new NoOpRunnable(),
366 >                                      MEDIUM_DELAY_MS, MEDIUM_DELAY_MS, MILLISECONDS);
367 >                shouldThrow();
368 >            } catch (RejectedExecutionException success) {
369 >            } catch (SecurityException ok) {}
370          }
354        joinPool(se);
371      }
372  
373      /**
374       * scheduleWithFixedDelay throws RejectedExecutionException if shutdown
375       */
376      public void testScheduleWithFixedDelay1_RejectedExecutionException() {
377 <        CustomExecutor se = new CustomExecutor(1);
378 <        try {
379 <            se.shutdown();
380 <            se.scheduleWithFixedDelay(new NoOpRunnable(),
381 <                                      MEDIUM_DELAY_MS, MEDIUM_DELAY_MS, MILLISECONDS);
382 <            shouldThrow();
383 <        } catch (RejectedExecutionException success) {
384 <        } catch (SecurityException ok) {
377 >        final CustomExecutor p = new CustomExecutor(1);
378 >        try (PoolCleaner cleaner = cleaner(p)) {
379 >            try {
380 >                p.shutdown();
381 >                p.scheduleWithFixedDelay(new NoOpRunnable(),
382 >                                         MEDIUM_DELAY_MS, MEDIUM_DELAY_MS, MILLISECONDS);
383 >                shouldThrow();
384 >            } catch (RejectedExecutionException success) {
385 >            } catch (SecurityException ok) {}
386          }
370        joinPool(se);
387      }
388  
389      /**
# Line 375 | Line 391 | public class ScheduledExecutorSubclassTe
391       * thread becomes active
392       */
393      public void testGetActiveCount() throws InterruptedException {
378        final ThreadPoolExecutor p = new CustomExecutor(2);
379        final CountDownLatch threadStarted = new CountDownLatch(1);
394          final CountDownLatch done = new CountDownLatch(1);
395 <        try {
395 >        final ThreadPoolExecutor p = new CustomExecutor(2);
396 >        try (PoolCleaner cleaner = cleaner(p, done)) {
397 >            final CountDownLatch threadStarted = new CountDownLatch(1);
398              assertEquals(0, p.getActiveCount());
399              p.execute(new CheckedRunnable() {
400                  public void realRun() throws InterruptedException {
401                      threadStarted.countDown();
402                      assertEquals(1, p.getActiveCount());
403 <                    done.await();
403 >                    await(done);
404                  }});
405 <            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
405 >            await(threadStarted);
406              assertEquals(1, p.getActiveCount());
391        } finally {
392            done.countDown();
393            joinPool(p);
407          }
408      }
409  
# Line 400 | Line 413 | public class ScheduledExecutorSubclassTe
413       */
414      public void testGetCompletedTaskCount() throws InterruptedException {
415          final ThreadPoolExecutor p = new CustomExecutor(2);
416 <        final CountDownLatch threadStarted = new CountDownLatch(1);
417 <        final CountDownLatch threadProceed = new CountDownLatch(1);
418 <        final CountDownLatch threadDone = new CountDownLatch(1);
419 <        try {
416 >        try (PoolCleaner cleaner = cleaner(p)) {
417 >            final CountDownLatch threadStarted = new CountDownLatch(1);
418 >            final CountDownLatch threadProceed = new CountDownLatch(1);
419 >            final CountDownLatch threadDone = new CountDownLatch(1);
420              assertEquals(0, p.getCompletedTaskCount());
421              p.execute(new CheckedRunnable() {
422                  public void realRun() throws InterruptedException {
423                      threadStarted.countDown();
424                      assertEquals(0, p.getCompletedTaskCount());
425 <                    threadProceed.await();
425 >                    await(threadProceed);
426                      threadDone.countDown();
427                  }});
428              await(threadStarted);
429              assertEquals(0, p.getCompletedTaskCount());
430              threadProceed.countDown();
431 <            threadDone.await();
431 >            await(threadDone);
432              long startTime = System.nanoTime();
433              while (p.getCompletedTaskCount() != 1) {
434                  if (millisElapsedSince(startTime) > LONG_DELAY_MS)
435                      fail("timed out");
436                  Thread.yield();
437              }
425        } finally {
426            joinPool(p);
438          }
439      }
440  
# Line 431 | Line 442 | public class ScheduledExecutorSubclassTe
442       * getCorePoolSize returns size given in constructor if not otherwise set
443       */
444      public void testGetCorePoolSize() {
445 <        CustomExecutor p = new CustomExecutor(1);
446 <        assertEquals(1, p.getCorePoolSize());
447 <        joinPool(p);
445 >        final CustomExecutor p = new CustomExecutor(1);
446 >        try (PoolCleaner cleaner = cleaner(p)) {
447 >            assertEquals(1, p.getCorePoolSize());
448 >        }
449      }
450  
451      /**
# Line 442 | Line 454 | public class ScheduledExecutorSubclassTe
454       */
455      public void testGetLargestPoolSize() throws InterruptedException {
456          final int THREADS = 3;
445        final ThreadPoolExecutor p = new CustomExecutor(THREADS);
446        final CountDownLatch threadsStarted = new CountDownLatch(THREADS);
457          final CountDownLatch done = new CountDownLatch(1);
458 <        try {
458 >        final ThreadPoolExecutor p = new CustomExecutor(THREADS);
459 >        try (PoolCleaner cleaner = cleaner(p, done)) {
460 >            final CountDownLatch threadsStarted = new CountDownLatch(THREADS);
461              assertEquals(0, p.getLargestPoolSize());
462              for (int i = 0; i < THREADS; i++)
463                  p.execute(new CheckedRunnable() {
464                      public void realRun() throws InterruptedException {
465                          threadsStarted.countDown();
466 <                        done.await();
466 >                        await(done);
467                          assertEquals(THREADS, p.getLargestPoolSize());
468                      }});
469 <            assertTrue(threadsStarted.await(SMALL_DELAY_MS, MILLISECONDS));
458 <            assertEquals(THREADS, p.getLargestPoolSize());
459 <        } finally {
460 <            done.countDown();
461 <            joinPool(p);
469 >            await(threadsStarted);
470              assertEquals(THREADS, p.getLargestPoolSize());
471          }
472 +        assertEquals(THREADS, p.getLargestPoolSize());
473      }
474  
475      /**
# Line 468 | Line 477 | public class ScheduledExecutorSubclassTe
477       * become active
478       */
479      public void testGetPoolSize() throws InterruptedException {
471        final ThreadPoolExecutor p = new CustomExecutor(1);
472        final CountDownLatch threadStarted = new CountDownLatch(1);
480          final CountDownLatch done = new CountDownLatch(1);
481 <        try {
481 >        final ThreadPoolExecutor p = new CustomExecutor(1);
482 >        try (PoolCleaner cleaner = cleaner(p, done)) {
483 >            final CountDownLatch threadStarted = new CountDownLatch(1);
484              assertEquals(0, p.getPoolSize());
485              p.execute(new CheckedRunnable() {
486                  public void realRun() throws InterruptedException {
487                      threadStarted.countDown();
488                      assertEquals(1, p.getPoolSize());
489 <                    done.await();
489 >                    await(done);
490                  }});
491 <            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
491 >            await(threadStarted);
492              assertEquals(1, p.getPoolSize());
484        } finally {
485            done.countDown();
486            joinPool(p);
493          }
494      }
495  
# Line 492 | Line 498 | public class ScheduledExecutorSubclassTe
498       * submitted
499       */
500      public void testGetTaskCount() throws InterruptedException {
501 <        final ThreadPoolExecutor p = new CustomExecutor(1);
496 <        final CountDownLatch threadStarted = new CountDownLatch(1);
501 >        final int TASKS = 3;
502          final CountDownLatch done = new CountDownLatch(1);
503 <        final int TASKS = 5;
504 <        try {
503 >        final ThreadPoolExecutor p = new CustomExecutor(1);
504 >        try (PoolCleaner cleaner = cleaner(p, done)) {
505 >            final CountDownLatch threadStarted = new CountDownLatch(1);
506              assertEquals(0, p.getTaskCount());
507 <            for (int i = 0; i < TASKS; i++)
507 >            assertEquals(0, p.getCompletedTaskCount());
508 >            p.execute(new CheckedRunnable() {
509 >                public void realRun() throws InterruptedException {
510 >                    threadStarted.countDown();
511 >                    await(done);
512 >                }});
513 >            await(threadStarted);
514 >            assertEquals(1, p.getTaskCount());
515 >            assertEquals(0, p.getCompletedTaskCount());
516 >            for (int i = 0; i < TASKS; i++) {
517 >                assertEquals(1 + i, p.getTaskCount());
518                  p.execute(new CheckedRunnable() {
519                      public void realRun() throws InterruptedException {
520                          threadStarted.countDown();
521 <                        done.await();
521 >                        assertEquals(1 + TASKS, p.getTaskCount());
522 >                        await(done);
523                      }});
524 <            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
525 <            assertEquals(TASKS, p.getTaskCount());
526 <        } finally {
510 <            done.countDown();
511 <            joinPool(p);
524 >            }
525 >            assertEquals(1 + TASKS, p.getTaskCount());
526 >            assertEquals(0, p.getCompletedTaskCount());
527          }
528 +        assertEquals(1 + TASKS, p.getTaskCount());
529 +        assertEquals(1 + TASKS, p.getCompletedTaskCount());
530      }
531  
532      /**
533       * getThreadFactory returns factory in constructor if not set
534       */
535      public void testGetThreadFactory() {
536 <        ThreadFactory tf = new SimpleThreadFactory();
537 <        CustomExecutor p = new CustomExecutor(1, tf);
538 <        assertSame(tf, p.getThreadFactory());
539 <        joinPool(p);
536 >        final ThreadFactory threadFactory = new SimpleThreadFactory();
537 >        final CustomExecutor p = new CustomExecutor(1, threadFactory);
538 >        try (PoolCleaner cleaner = cleaner(p)) {
539 >            assertSame(threadFactory, p.getThreadFactory());
540 >        }
541      }
542  
543      /**
544       * setThreadFactory sets the thread factory returned by getThreadFactory
545       */
546      public void testSetThreadFactory() {
547 <        ThreadFactory tf = new SimpleThreadFactory();
548 <        CustomExecutor p = new CustomExecutor(1);
549 <        p.setThreadFactory(tf);
550 <        assertSame(tf, p.getThreadFactory());
551 <        joinPool(p);
547 >        final ThreadFactory threadFactory = new SimpleThreadFactory();
548 >        final CustomExecutor p = new CustomExecutor(1);
549 >        try (PoolCleaner cleaner = cleaner(p)) {
550 >            p.setThreadFactory(threadFactory);
551 >            assertSame(threadFactory, p.getThreadFactory());
552 >        }
553      }
554  
555      /**
556       * setThreadFactory(null) throws NPE
557       */
558      public void testSetThreadFactoryNull() {
559 <        CustomExecutor p = new CustomExecutor(1);
560 <        try {
561 <            p.setThreadFactory(null);
562 <            shouldThrow();
563 <        } catch (NullPointerException success) {
564 <        } finally {
546 <            joinPool(p);
559 >        final CustomExecutor p = new CustomExecutor(1);
560 >        try (PoolCleaner cleaner = cleaner(p)) {
561 >            try {
562 >                p.setThreadFactory(null);
563 >                shouldThrow();
564 >            } catch (NullPointerException success) {}
565          }
566      }
567  
# Line 551 | Line 569 | public class ScheduledExecutorSubclassTe
569       * isShutdown is false before shutdown, true after
570       */
571      public void testIsShutdown() {
572 <        CustomExecutor p = new CustomExecutor(1);
573 <        try {
572 >        final CustomExecutor p = new CustomExecutor(1);
573 >        try (PoolCleaner cleaner = cleaner(p)) {
574              assertFalse(p.isShutdown());
557        }
558        finally {
575              try { p.shutdown(); } catch (SecurityException ok) { return; }
576 +            assertTrue(p.isShutdown());
577          }
561        assertTrue(p.isShutdown());
578      }
579  
580      /**
581       * isTerminated is false before termination, true after
582       */
583      public void testIsTerminated() throws InterruptedException {
568        final ThreadPoolExecutor p = new CustomExecutor(1);
569        final CountDownLatch threadStarted = new CountDownLatch(1);
584          final CountDownLatch done = new CountDownLatch(1);
585 <        assertFalse(p.isTerminated());
586 <        try {
585 >        final ThreadPoolExecutor p = new CustomExecutor(1);
586 >        try (PoolCleaner cleaner = cleaner(p)) {
587 >            final CountDownLatch threadStarted = new CountDownLatch(1);
588              p.execute(new CheckedRunnable() {
589                  public void realRun() throws InterruptedException {
590                      assertFalse(p.isTerminated());
591                      threadStarted.countDown();
592 <                    done.await();
592 >                    await(done);
593                  }});
594 <            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
594 >            await(threadStarted);
595 >            assertFalse(p.isTerminated());
596              assertFalse(p.isTerminating());
597              done.countDown();
582        } finally {
598              try { p.shutdown(); } catch (SecurityException ok) { return; }
599 +            assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
600 +            assertTrue(p.isTerminated());
601          }
585        assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
586        assertTrue(p.isTerminated());
602      }
603  
604      /**
605       * isTerminating is not true when running or when terminated
606       */
607      public void testIsTerminating() throws InterruptedException {
593        final ThreadPoolExecutor p = new CustomExecutor(1);
594        final CountDownLatch threadStarted = new CountDownLatch(1);
608          final CountDownLatch done = new CountDownLatch(1);
609 <        try {
609 >        final ThreadPoolExecutor p = new CustomExecutor(1);
610 >        try (PoolCleaner cleaner = cleaner(p)) {
611 >            final CountDownLatch threadStarted = new CountDownLatch(1);
612              assertFalse(p.isTerminating());
613              p.execute(new CheckedRunnable() {
614                  public void realRun() throws InterruptedException {
615                      assertFalse(p.isTerminating());
616                      threadStarted.countDown();
617 <                    done.await();
617 >                    await(done);
618                  }});
619 <            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
619 >            await(threadStarted);
620              assertFalse(p.isTerminating());
621              done.countDown();
607        } finally {
622              try { p.shutdown(); } catch (SecurityException ok) { return; }
623 +            assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
624 +            assertTrue(p.isTerminated());
625 +            assertFalse(p.isTerminating());
626          }
610        assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
611        assertTrue(p.isTerminated());
612        assertFalse(p.isTerminating());
627      }
628  
629      /**
630       * getQueue returns the work queue, which contains queued tasks
631       */
632      public void testGetQueue() throws InterruptedException {
619        ScheduledThreadPoolExecutor p = new CustomExecutor(1);
620        final CountDownLatch threadStarted = new CountDownLatch(1);
633          final CountDownLatch done = new CountDownLatch(1);
634 <        try {
634 >        final ScheduledThreadPoolExecutor p = new CustomExecutor(1);
635 >        try (PoolCleaner cleaner = cleaner(p, done)) {
636 >            final CountDownLatch threadStarted = new CountDownLatch(1);
637              ScheduledFuture[] tasks = new ScheduledFuture[5];
638              for (int i = 0; i < tasks.length; i++) {
639                  Runnable r = new CheckedRunnable() {
640                      public void realRun() throws InterruptedException {
641                          threadStarted.countDown();
642 <                        done.await();
642 >                        await(done);
643                      }};
644                  tasks[i] = p.schedule(r, 1, MILLISECONDS);
645              }
646 <            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
646 >            await(threadStarted);
647              BlockingQueue<Runnable> q = p.getQueue();
648              assertTrue(q.contains(tasks[tasks.length - 1]));
649              assertFalse(q.contains(tasks[0]));
636        } finally {
637            done.countDown();
638            joinPool(p);
650          }
651      }
652  
# Line 643 | Line 654 | public class ScheduledExecutorSubclassTe
654       * remove(task) removes queued task, and fails to remove active task
655       */
656      public void testRemove() throws InterruptedException {
646        final ScheduledThreadPoolExecutor p = new CustomExecutor(1);
647        ScheduledFuture[] tasks = new ScheduledFuture[5];
648        final CountDownLatch threadStarted = new CountDownLatch(1);
657          final CountDownLatch done = new CountDownLatch(1);
658 <        try {
658 >        final ScheduledThreadPoolExecutor p = new CustomExecutor(1);
659 >        try (PoolCleaner cleaner = cleaner(p, done)) {
660 >            ScheduledFuture[] tasks = new ScheduledFuture[5];
661 >            final CountDownLatch threadStarted = new CountDownLatch(1);
662              for (int i = 0; i < tasks.length; i++) {
663                  Runnable r = new CheckedRunnable() {
664                      public void realRun() throws InterruptedException {
665                          threadStarted.countDown();
666 <                        done.await();
666 >                        await(done);
667                      }};
668                  tasks[i] = p.schedule(r, 1, MILLISECONDS);
669              }
670 <            assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
670 >            await(threadStarted);
671              BlockingQueue<Runnable> q = p.getQueue();
672              assertFalse(p.remove((Runnable)tasks[0]));
673              assertTrue(q.contains((Runnable)tasks[4]));
# Line 667 | Line 678 | public class ScheduledExecutorSubclassTe
678              assertTrue(q.contains((Runnable)tasks[3]));
679              assertTrue(p.remove((Runnable)tasks[3]));
680              assertFalse(q.contains((Runnable)tasks[3]));
670        } finally {
671            done.countDown();
672            joinPool(p);
681          }
682      }
683  
# Line 677 | Line 685 | public class ScheduledExecutorSubclassTe
685       * purge removes cancelled tasks from the queue
686       */
687      public void testPurge() throws InterruptedException {
688 <        CustomExecutor p = new CustomExecutor(1);
689 <        ScheduledFuture[] tasks = new ScheduledFuture[5];
690 <        for (int i = 0; i < tasks.length; i++)
691 <            tasks[i] = p.schedule(new SmallPossiblyInterruptedRunnable(),
692 <                                  LONG_DELAY_MS, MILLISECONDS);
693 <        try {
688 >        final ScheduledFuture[] tasks = new ScheduledFuture[5];
689 >        final Runnable releaser = new Runnable() { public void run() {
690 >            for (ScheduledFuture task : tasks)
691 >                if (task != null) task.cancel(true); }};
692 >        final CustomExecutor p = new CustomExecutor(1);
693 >        try (PoolCleaner cleaner = cleaner(p, releaser)) {
694 >            for (int i = 0; i < tasks.length; i++)
695 >                tasks[i] = p.schedule(new SmallPossiblyInterruptedRunnable(),
696 >                                      LONG_DELAY_MS, MILLISECONDS);
697              int max = tasks.length;
698              if (tasks[4].cancel(true)) --max;
699              if (tasks[3].cancel(true)) --max;
# Line 694 | Line 705 | public class ScheduledExecutorSubclassTe
705                  long count = p.getTaskCount();
706                  if (count == max)
707                      return;
708 <            } while (millisElapsedSince(startTime) < MEDIUM_DELAY_MS);
708 >            } while (millisElapsedSince(startTime) < LONG_DELAY_MS);
709              fail("Purge failed to remove cancelled tasks");
699        } finally {
700            for (ScheduledFuture task : tasks)
701                task.cancel(true);
702            joinPool(p);
710          }
711      }
712  
713      /**
714 <     * shutdownNow returns a list containing tasks that were not run
714 >     * shutdownNow returns a list containing tasks that were not run,
715 >     * and those tasks are drained from the queue
716       */
717 <    public void testShutdownNow() {
718 <        CustomExecutor p = new CustomExecutor(1);
719 <        for (int i = 0; i < 5; i++)
720 <            p.schedule(new SmallPossiblyInterruptedRunnable(),
721 <                       LONG_DELAY_MS, MILLISECONDS);
717 >    public void testShutdownNow() throws InterruptedException {
718 >        final int poolSize = 2;
719 >        final int count = 5;
720 >        final AtomicInteger ran = new AtomicInteger(0);
721 >        final CustomExecutor p = new CustomExecutor(poolSize);
722 >        final CountDownLatch threadsStarted = new CountDownLatch(poolSize);
723 >        Runnable waiter = new CheckedRunnable() { public void realRun() {
724 >            threadsStarted.countDown();
725 >            try {
726 >                MILLISECONDS.sleep(2 * LONG_DELAY_MS);
727 >            } catch (InterruptedException success) {}
728 >            ran.getAndIncrement();
729 >        }};
730 >        for (int i = 0; i < count; i++)
731 >            p.execute(waiter);
732 >        await(threadsStarted);
733 >        assertEquals(poolSize, p.getActiveCount());
734 >        assertEquals(0, p.getCompletedTaskCount());
735 >        final List<Runnable> queuedTasks;
736          try {
737 <            List<Runnable> l = p.shutdownNow();
716 <            assertTrue(p.isShutdown());
717 <            assertEquals(5, l.size());
737 >            queuedTasks = p.shutdownNow();
738          } catch (SecurityException ok) {
739 <            // Allowed in case test doesn't have privs
720 <        } finally {
721 <            joinPool(p);
739 >            return; // Allowed in case test doesn't have privs
740          }
741 +        assertTrue(p.isShutdown());
742 +        assertTrue(p.getQueue().isEmpty());
743 +        assertEquals(count - poolSize, queuedTasks.size());
744 +        assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
745 +        assertTrue(p.isTerminated());
746 +        assertEquals(poolSize, ran.get());
747 +        assertEquals(poolSize, p.getCompletedTaskCount());
748      }
749  
750      /**
751 <     * In default setting, shutdown cancels periodic but not delayed
752 <     * tasks at shutdown
751 >     * shutdownNow returns a list containing tasks that were not run,
752 >     * and those tasks are drained from the queue
753       */
754 <    public void testShutdown1() throws InterruptedException {
755 <        CustomExecutor p = new CustomExecutor(1);
756 <        assertTrue(p.getExecuteExistingDelayedTasksAfterShutdownPolicy());
757 <        assertFalse(p.getContinueExistingPeriodicTasksAfterShutdownPolicy());
758 <
759 <        ScheduledFuture[] tasks = new ScheduledFuture[5];
760 <        for (int i = 0; i < tasks.length; i++)
761 <            tasks[i] = p.schedule(new NoOpRunnable(),
762 <                                  SHORT_DELAY_MS, MILLISECONDS);
763 <        try { p.shutdown(); } catch (SecurityException ok) { return; }
764 <        BlockingQueue<Runnable> q = p.getQueue();
765 <        for (ScheduledFuture task : tasks) {
766 <            assertFalse(task.isDone());
767 <            assertFalse(task.isCancelled());
768 <            assertTrue(q.contains(task));
754 >    public void testShutdownNow_delayedTasks() throws InterruptedException {
755 >        final CustomExecutor p = new CustomExecutor(1);
756 >        List<ScheduledFuture> tasks = new ArrayList<>();
757 >        for (int i = 0; i < 3; i++) {
758 >            Runnable r = new NoOpRunnable();
759 >            tasks.add(p.schedule(r, 9, SECONDS));
760 >            tasks.add(p.scheduleAtFixedRate(r, 9, 9, SECONDS));
761 >            tasks.add(p.scheduleWithFixedDelay(r, 9, 9, SECONDS));
762 >        }
763 >        if (testImplementationDetails)
764 >            assertEquals(new HashSet(tasks), new HashSet(p.getQueue()));
765 >        final List<Runnable> queuedTasks;
766 >        try {
767 >            queuedTasks = p.shutdownNow();
768 >        } catch (SecurityException ok) {
769 >            return; // Allowed in case test doesn't have privs
770          }
771          assertTrue(p.isShutdown());
772 <        assertTrue(p.awaitTermination(SMALL_DELAY_MS, MILLISECONDS));
773 <        assertTrue(p.isTerminated());
772 >        assertTrue(p.getQueue().isEmpty());
773 >        if (testImplementationDetails)
774 >            assertEquals(new HashSet(tasks), new HashSet(queuedTasks));
775 >        assertEquals(tasks.size(), queuedTasks.size());
776          for (ScheduledFuture task : tasks) {
777 <            assertTrue(task.isDone());
777 >            assertFalse(((CustomTask)task).ran);
778 >            assertFalse(task.isDone());
779              assertFalse(task.isCancelled());
780          }
781 +        assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
782 +        assertTrue(p.isTerminated());
783      }
784  
785      /**
786 <     * If setExecuteExistingDelayedTasksAfterShutdownPolicy is false,
787 <     * delayed tasks are cancelled at shutdown
788 <     */
789 <    public void testShutdown2() throws InterruptedException {
790 <        CustomExecutor p = new CustomExecutor(1);
791 <        p.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
792 <        assertFalse(p.getExecuteExistingDelayedTasksAfterShutdownPolicy());
793 <        assertFalse(p.getContinueExistingPeriodicTasksAfterShutdownPolicy());
794 <        ScheduledFuture[] tasks = new ScheduledFuture[5];
795 <        for (int i = 0; i < tasks.length; i++)
796 <            tasks[i] = p.schedule(new NoOpRunnable(),
797 <                                  SHORT_DELAY_MS, MILLISECONDS);
798 <        BlockingQueue q = p.getQueue();
799 <        assertEquals(tasks.length, q.size());
800 <        try { p.shutdown(); } catch (SecurityException ok) { return; }
801 <        assertTrue(p.isShutdown());
802 <        assertTrue(q.isEmpty());
803 <        assertTrue(p.awaitTermination(SMALL_DELAY_MS, MILLISECONDS));
804 <        assertTrue(p.isTerminated());
805 <        for (ScheduledFuture task : tasks) {
806 <            assertTrue(task.isDone());
807 <            assertTrue(task.isCancelled());
786 >     * By default, periodic tasks are cancelled at shutdown.
787 >     * By default, delayed tasks keep running after shutdown.
788 >     * Check that changing the default values work:
789 >     * - setExecuteExistingDelayedTasksAfterShutdownPolicy
790 >     * - setContinueExistingPeriodicTasksAfterShutdownPolicy
791 >     */
792 >    public void testShutdown_cancellation() throws Exception {
793 >        final int poolSize = 4;
794 >        final CustomExecutor p = new CustomExecutor(poolSize);
795 >        final BlockingQueue<Runnable> q = p.getQueue();
796 >        final ThreadLocalRandom rnd = ThreadLocalRandom.current();
797 >        final long delay = rnd.nextInt(2);
798 >        final int rounds = rnd.nextInt(1, 3);
799 >        final boolean effectiveDelayedPolicy;
800 >        final boolean effectivePeriodicPolicy;
801 >        final boolean effectiveRemovePolicy;
802 >
803 >        if (rnd.nextBoolean())
804 >            p.setExecuteExistingDelayedTasksAfterShutdownPolicy(
805 >                effectiveDelayedPolicy = rnd.nextBoolean());
806 >        else
807 >            effectiveDelayedPolicy = true;
808 >        assertEquals(effectiveDelayedPolicy,
809 >                     p.getExecuteExistingDelayedTasksAfterShutdownPolicy());
810 >
811 >        if (rnd.nextBoolean())
812 >            p.setContinueExistingPeriodicTasksAfterShutdownPolicy(
813 >                effectivePeriodicPolicy = rnd.nextBoolean());
814 >        else
815 >            effectivePeriodicPolicy = false;
816 >        assertEquals(effectivePeriodicPolicy,
817 >                     p.getContinueExistingPeriodicTasksAfterShutdownPolicy());
818 >
819 >        if (rnd.nextBoolean())
820 >            p.setRemoveOnCancelPolicy(
821 >                effectiveRemovePolicy = rnd.nextBoolean());
822 >        else
823 >            effectiveRemovePolicy = false;
824 >        assertEquals(effectiveRemovePolicy,
825 >                     p.getRemoveOnCancelPolicy());
826 >
827 >        final boolean periodicTasksContinue = effectivePeriodicPolicy && rnd.nextBoolean();
828 >
829 >        // Strategy: Wedge the pool with one wave of "blocker" tasks,
830 >        // then add a second wave that waits in the queue until unblocked.
831 >        final AtomicInteger ran = new AtomicInteger(0);
832 >        final CountDownLatch poolBlocked = new CountDownLatch(poolSize);
833 >        final CountDownLatch unblock = new CountDownLatch(1);
834 >        final RuntimeException exception = new RuntimeException();
835 >
836 >        class Task implements Runnable {
837 >            public void run() {
838 >                try {
839 >                    ran.getAndIncrement();
840 >                    poolBlocked.countDown();
841 >                    await(unblock);
842 >                } catch (Throwable fail) { threadUnexpectedException(fail); }
843 >            }
844          }
778    }
845  
846 <    /**
847 <     * If setContinueExistingPeriodicTasksAfterShutdownPolicy is set false,
848 <     * periodic tasks are cancelled at shutdown
849 <     */
850 <    public void testShutdown3() throws InterruptedException {
851 <        CustomExecutor p = new CustomExecutor(1);
852 <        assertTrue(p.getExecuteExistingDelayedTasksAfterShutdownPolicy());
853 <        assertFalse(p.getContinueExistingPeriodicTasksAfterShutdownPolicy());
854 <        p.setContinueExistingPeriodicTasksAfterShutdownPolicy(false);
855 <        assertTrue(p.getExecuteExistingDelayedTasksAfterShutdownPolicy());
856 <        assertFalse(p.getContinueExistingPeriodicTasksAfterShutdownPolicy());
857 <        long initialDelay = LONG_DELAY_MS;
858 <        ScheduledFuture task =
859 <            p.scheduleAtFixedRate(new NoOpRunnable(), initialDelay,
860 <                                  5, MILLISECONDS);
846 >        class PeriodicTask extends Task {
847 >            PeriodicTask(int rounds) { this.rounds = rounds; }
848 >            int rounds;
849 >            public void run() {
850 >                if (--rounds == 0) super.run();
851 >                // throw exception to surely terminate this periodic task,
852 >                // but in a separate execution and in a detectable way.
853 >                if (rounds == -1) throw exception;
854 >            }
855 >        }
856 >
857 >        Runnable task = new Task();
858 >
859 >        List<Future<?>> immediates = new ArrayList<>();
860 >        List<Future<?>> delayeds   = new ArrayList<>();
861 >        List<Future<?>> periodics  = new ArrayList<>();
862 >
863 >        immediates.add(p.submit(task));
864 >        delayeds.add(p.schedule(task, delay, MILLISECONDS));
865 >        periodics.add(p.scheduleAtFixedRate(
866 >                          new PeriodicTask(rounds), delay, 1, MILLISECONDS));
867 >        periodics.add(p.scheduleWithFixedDelay(
868 >                          new PeriodicTask(rounds), delay, 1, MILLISECONDS));
869 >
870 >        await(poolBlocked);
871 >
872 >        assertEquals(poolSize, ran.get());
873 >        assertEquals(poolSize, p.getActiveCount());
874 >        assertTrue(q.isEmpty());
875 >
876 >        // Add second wave of tasks.
877 >        immediates.add(p.submit(task));
878 >        delayeds.add(p.schedule(task, effectiveDelayedPolicy ? delay : LONG_DELAY_MS, MILLISECONDS));
879 >        periodics.add(p.scheduleAtFixedRate(
880 >                          new PeriodicTask(rounds), delay, 1, MILLISECONDS));
881 >        periodics.add(p.scheduleWithFixedDelay(
882 >                          new PeriodicTask(rounds), delay, 1, MILLISECONDS));
883 >
884 >        assertEquals(poolSize, q.size());
885 >        assertEquals(poolSize, ran.get());
886 >
887 >        immediates.forEach(
888 >            f -> assertTrue(((ScheduledFuture)f).getDelay(NANOSECONDS) <= 0L));
889 >
890 >        Stream.of(immediates, delayeds, periodics).flatMap(c -> c.stream())
891 >            .forEach(f -> assertFalse(f.isDone()));
892 >
893          try { p.shutdown(); } catch (SecurityException ok) { return; }
894          assertTrue(p.isShutdown());
895 <        assertTrue(p.getQueue().isEmpty());
896 <        assertTrue(task.isDone());
799 <        assertTrue(task.isCancelled());
800 <        joinPool(p);
801 <    }
895 >        assertTrue(p.isTerminating());
896 >        assertFalse(p.isTerminated());
897  
898 <    /**
899 <     * if setContinueExistingPeriodicTasksAfterShutdownPolicy is true,
900 <     * periodic tasks are not cancelled at shutdown
901 <     */
902 <    public void testShutdown4() throws InterruptedException {
903 <        CustomExecutor p = new CustomExecutor(1);
904 <        final CountDownLatch counter = new CountDownLatch(2);
905 <        try {
906 <            p.setContinueExistingPeriodicTasksAfterShutdownPolicy(true);
907 <            assertTrue(p.getExecuteExistingDelayedTasksAfterShutdownPolicy());
908 <            assertTrue(p.getContinueExistingPeriodicTasksAfterShutdownPolicy());
909 <            final Runnable r = new CheckedRunnable() {
910 <                public void realRun() {
911 <                    counter.countDown();
912 <                }};
913 <            ScheduledFuture task =
914 <                p.scheduleAtFixedRate(r, 1, 1, MILLISECONDS);
915 <            assertFalse(task.isDone());
916 <            assertFalse(task.isCancelled());
917 <            try { p.shutdown(); } catch (SecurityException ok) { return; }
918 <            assertFalse(task.isCancelled());
919 <            assertFalse(p.isTerminated());
920 <            assertTrue(p.isShutdown());
921 <            assertTrue(counter.await(SMALL_DELAY_MS, MILLISECONDS));
922 <            assertFalse(task.isCancelled());
923 <            assertTrue(task.cancel(false));
924 <            assertTrue(task.isDone());
925 <            assertTrue(task.isCancelled());
926 <            assertTrue(p.awaitTermination(SMALL_DELAY_MS, MILLISECONDS));
927 <            assertTrue(p.isTerminated());
928 <        }
929 <        finally {
930 <            joinPool(p);
898 >        if (rnd.nextBoolean())
899 >            assertThrows(
900 >                RejectedExecutionException.class,
901 >                () -> p.submit(task),
902 >                () -> p.schedule(task, 1, SECONDS),
903 >                () -> p.scheduleAtFixedRate(
904 >                    new PeriodicTask(1), 1, 1, SECONDS),
905 >                () -> p.scheduleWithFixedDelay(
906 >                    new PeriodicTask(2), 1, 1, SECONDS));
907 >
908 >        assertTrue(q.contains(immediates.get(1)));
909 >        assertTrue(!effectiveDelayedPolicy
910 >                   ^ q.contains(delayeds.get(1)));
911 >        assertTrue(!effectivePeriodicPolicy
912 >                   ^ q.containsAll(periodics.subList(2, 4)));
913 >
914 >        immediates.forEach(f -> assertFalse(f.isDone()));
915 >
916 >        assertFalse(delayeds.get(0).isDone());
917 >        if (effectiveDelayedPolicy)
918 >            assertFalse(delayeds.get(1).isDone());
919 >        else
920 >            assertTrue(delayeds.get(1).isCancelled());
921 >
922 >        if (effectivePeriodicPolicy)
923 >            periodics.forEach(
924 >                f -> {
925 >                    assertFalse(f.isDone());
926 >                    if (!periodicTasksContinue) {
927 >                        assertTrue(f.cancel(false));
928 >                        assertTrue(f.isCancelled());
929 >                    }
930 >                });
931 >        else {
932 >            periodics.subList(0, 2).forEach(f -> assertFalse(f.isDone()));
933 >            periodics.subList(2, 4).forEach(f -> assertTrue(f.isCancelled()));
934          }
935 +
936 +        unblock.countDown();    // Release all pool threads
937 +
938 +        assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
939 +        assertFalse(p.isTerminating());
940 +        assertTrue(p.isTerminated());
941 +
942 +        assertTrue(q.isEmpty());
943 +
944 +        Stream.of(immediates, delayeds, periodics).flatMap(c -> c.stream())
945 +            .forEach(f -> assertTrue(f.isDone()));
946 +
947 +        for (Future<?> f : immediates) assertNull(f.get());
948 +
949 +        assertNull(delayeds.get(0).get());
950 +        if (effectiveDelayedPolicy)
951 +            assertNull(delayeds.get(1).get());
952 +        else
953 +            assertTrue(delayeds.get(1).isCancelled());
954 +
955 +        if (periodicTasksContinue)
956 +            periodics.forEach(
957 +                f -> {
958 +                    try { f.get(); }
959 +                    catch (ExecutionException success) {
960 +                        assertSame(exception, success.getCause());
961 +                    }
962 +                    catch (Throwable fail) { threadUnexpectedException(fail); }
963 +                });
964 +        else
965 +            periodics.forEach(f -> assertTrue(f.isCancelled()));
966 +
967 +        assertEquals(poolSize + 1
968 +                     + (effectiveDelayedPolicy ? 1 : 0)
969 +                     + (periodicTasksContinue ? 2 : 0),
970 +                     ran.get());
971      }
972  
973      /**
974       * completed submit of callable returns result
975       */
976      public void testSubmitCallable() throws Exception {
977 <        ExecutorService e = new CustomExecutor(2);
978 <        try {
977 >        final ExecutorService e = new CustomExecutor(2);
978 >        try (PoolCleaner cleaner = cleaner(e)) {
979              Future<String> future = e.submit(new StringTask());
980              String result = future.get();
981              assertSame(TEST_STRING, result);
848        } finally {
849            joinPool(e);
982          }
983      }
984  
# Line 854 | Line 986 | public class ScheduledExecutorSubclassTe
986       * completed submit of runnable returns successfully
987       */
988      public void testSubmitRunnable() throws Exception {
989 <        ExecutorService e = new CustomExecutor(2);
990 <        try {
989 >        final ExecutorService e = new CustomExecutor(2);
990 >        try (PoolCleaner cleaner = cleaner(e)) {
991              Future<?> future = e.submit(new NoOpRunnable());
992              future.get();
993              assertTrue(future.isDone());
862        } finally {
863            joinPool(e);
994          }
995      }
996  
# Line 868 | Line 998 | public class ScheduledExecutorSubclassTe
998       * completed submit of (runnable, result) returns result
999       */
1000      public void testSubmitRunnable2() throws Exception {
1001 <        ExecutorService e = new CustomExecutor(2);
1002 <        try {
1001 >        final ExecutorService e = new CustomExecutor(2);
1002 >        try (PoolCleaner cleaner = cleaner(e)) {
1003              Future<String> future = e.submit(new NoOpRunnable(), TEST_STRING);
1004              String result = future.get();
1005              assertSame(TEST_STRING, result);
876        } finally {
877            joinPool(e);
1006          }
1007      }
1008  
# Line 882 | Line 1010 | public class ScheduledExecutorSubclassTe
1010       * invokeAny(null) throws NPE
1011       */
1012      public void testInvokeAny1() throws Exception {
1013 <        ExecutorService e = new CustomExecutor(2);
1014 <        try {
1015 <            e.invokeAny(null);
1016 <            shouldThrow();
1017 <        } catch (NullPointerException success) {
1018 <        } finally {
891 <            joinPool(e);
1013 >        final ExecutorService e = new CustomExecutor(2);
1014 >        try (PoolCleaner cleaner = cleaner(e)) {
1015 >            try {
1016 >                e.invokeAny(null);
1017 >                shouldThrow();
1018 >            } catch (NullPointerException success) {}
1019          }
1020      }
1021  
1022      /**
1023 <     * invokeAny(empty collection) throws IAE
1023 >     * invokeAny(empty collection) throws IllegalArgumentException
1024       */
1025      public void testInvokeAny2() throws Exception {
1026 <        ExecutorService e = new CustomExecutor(2);
1027 <        try {
1028 <            e.invokeAny(new ArrayList<Callable<String>>());
1029 <            shouldThrow();
1030 <        } catch (IllegalArgumentException success) {
1031 <        } finally {
905 <            joinPool(e);
1026 >        final ExecutorService e = new CustomExecutor(2);
1027 >        try (PoolCleaner cleaner = cleaner(e)) {
1028 >            try {
1029 >                e.invokeAny(new ArrayList<Callable<String>>());
1030 >                shouldThrow();
1031 >            } catch (IllegalArgumentException success) {}
1032          }
1033      }
1034  
# Line 910 | Line 1036 | public class ScheduledExecutorSubclassTe
1036       * invokeAny(c) throws NPE if c has null elements
1037       */
1038      public void testInvokeAny3() throws Exception {
1039 <        CountDownLatch latch = new CountDownLatch(1);
1040 <        ExecutorService e = new CustomExecutor(2);
1041 <        List<Callable<String>> l = new ArrayList<Callable<String>>();
1042 <        l.add(latchAwaitingStringTask(latch));
1043 <        l.add(null);
1044 <        try {
1045 <            e.invokeAny(l);
1046 <            shouldThrow();
1047 <        } catch (NullPointerException success) {
1048 <        } finally {
1039 >        final CountDownLatch latch = new CountDownLatch(1);
1040 >        final ExecutorService e = new CustomExecutor(2);
1041 >        try (PoolCleaner cleaner = cleaner(e)) {
1042 >            List<Callable<String>> l = new ArrayList<>();
1043 >            l.add(latchAwaitingStringTask(latch));
1044 >            l.add(null);
1045 >            try {
1046 >                e.invokeAny(l);
1047 >                shouldThrow();
1048 >            } catch (NullPointerException success) {}
1049              latch.countDown();
924            joinPool(e);
1050          }
1051      }
1052  
# Line 929 | Line 1054 | public class ScheduledExecutorSubclassTe
1054       * invokeAny(c) throws ExecutionException if no task completes
1055       */
1056      public void testInvokeAny4() throws Exception {
1057 <        ExecutorService e = new CustomExecutor(2);
1058 <        List<Callable<String>> l = new ArrayList<Callable<String>>();
1059 <        l.add(new NPETask());
1060 <        try {
1061 <            e.invokeAny(l);
1062 <            shouldThrow();
1063 <        } catch (ExecutionException success) {
1064 <            assertTrue(success.getCause() instanceof NullPointerException);
1065 <        } finally {
1066 <            joinPool(e);
1057 >        final ExecutorService e = new CustomExecutor(2);
1058 >        try (PoolCleaner cleaner = cleaner(e)) {
1059 >            List<Callable<String>> l = new ArrayList<>();
1060 >            l.add(new NPETask());
1061 >            try {
1062 >                e.invokeAny(l);
1063 >                shouldThrow();
1064 >            } catch (ExecutionException success) {
1065 >                assertTrue(success.getCause() instanceof NullPointerException);
1066 >            }
1067          }
1068      }
1069  
# Line 946 | Line 1071 | public class ScheduledExecutorSubclassTe
1071       * invokeAny(c) returns result of some task
1072       */
1073      public void testInvokeAny5() throws Exception {
1074 <        ExecutorService e = new CustomExecutor(2);
1075 <        try {
1076 <            List<Callable<String>> l = new ArrayList<Callable<String>>();
1074 >        final ExecutorService e = new CustomExecutor(2);
1075 >        try (PoolCleaner cleaner = cleaner(e)) {
1076 >            List<Callable<String>> l = new ArrayList<>();
1077              l.add(new StringTask());
1078              l.add(new StringTask());
1079              String result = e.invokeAny(l);
1080              assertSame(TEST_STRING, result);
956        } finally {
957            joinPool(e);
1081          }
1082      }
1083  
# Line 962 | Line 1085 | public class ScheduledExecutorSubclassTe
1085       * invokeAll(null) throws NPE
1086       */
1087      public void testInvokeAll1() throws Exception {
1088 <        ExecutorService e = new CustomExecutor(2);
1089 <        try {
1090 <            e.invokeAll(null);
1091 <            shouldThrow();
1092 <        } catch (NullPointerException success) {
1093 <        } finally {
971 <            joinPool(e);
1088 >        final ExecutorService e = new CustomExecutor(2);
1089 >        try (PoolCleaner cleaner = cleaner(e)) {
1090 >            try {
1091 >                e.invokeAll(null);
1092 >                shouldThrow();
1093 >            } catch (NullPointerException success) {}
1094          }
1095      }
1096  
1097      /**
1098 <     * invokeAll(empty collection) returns empty collection
1098 >     * invokeAll(empty collection) returns empty list
1099       */
1100      public void testInvokeAll2() throws Exception {
1101 <        ExecutorService e = new CustomExecutor(2);
1102 <        try {
1103 <            List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>());
1101 >        final ExecutorService e = new CustomExecutor(2);
1102 >        final Collection<Callable<String>> emptyCollection
1103 >            = Collections.emptyList();
1104 >        try (PoolCleaner cleaner = cleaner(e)) {
1105 >            List<Future<String>> r = e.invokeAll(emptyCollection);
1106              assertTrue(r.isEmpty());
983        } finally {
984            joinPool(e);
1107          }
1108      }
1109  
# Line 989 | Line 1111 | public class ScheduledExecutorSubclassTe
1111       * invokeAll(c) throws NPE if c has null elements
1112       */
1113      public void testInvokeAll3() throws Exception {
1114 <        ExecutorService e = new CustomExecutor(2);
1115 <        List<Callable<String>> l = new ArrayList<Callable<String>>();
1116 <        l.add(new StringTask());
1117 <        l.add(null);
1118 <        try {
1119 <            e.invokeAll(l);
1120 <            shouldThrow();
1121 <        } catch (NullPointerException success) {
1122 <        } finally {
1001 <            joinPool(e);
1114 >        final ExecutorService e = new CustomExecutor(2);
1115 >        try (PoolCleaner cleaner = cleaner(e)) {
1116 >            List<Callable<String>> l = new ArrayList<>();
1117 >            l.add(new StringTask());
1118 >            l.add(null);
1119 >            try {
1120 >                e.invokeAll(l);
1121 >                shouldThrow();
1122 >            } catch (NullPointerException success) {}
1123          }
1124      }
1125  
# Line 1006 | Line 1127 | public class ScheduledExecutorSubclassTe
1127       * get of invokeAll(c) throws exception on failed task
1128       */
1129      public void testInvokeAll4() throws Exception {
1130 <        ExecutorService e = new CustomExecutor(2);
1131 <        List<Callable<String>> l = new ArrayList<Callable<String>>();
1132 <        l.add(new NPETask());
1133 <        List<Future<String>> futures = e.invokeAll(l);
1134 <        assertEquals(1, futures.size());
1135 <        try {
1136 <            futures.get(0).get();
1137 <            shouldThrow();
1138 <        } catch (ExecutionException success) {
1139 <            assertTrue(success.getCause() instanceof NullPointerException);
1140 <        } finally {
1141 <            joinPool(e);
1130 >        final ExecutorService e = new CustomExecutor(2);
1131 >        try (PoolCleaner cleaner = cleaner(e)) {
1132 >            List<Callable<String>> l = new ArrayList<>();
1133 >            l.add(new NPETask());
1134 >            List<Future<String>> futures = e.invokeAll(l);
1135 >            assertEquals(1, futures.size());
1136 >            try {
1137 >                futures.get(0).get();
1138 >                shouldThrow();
1139 >            } catch (ExecutionException success) {
1140 >                assertTrue(success.getCause() instanceof NullPointerException);
1141 >            }
1142          }
1143      }
1144  
# Line 1025 | Line 1146 | public class ScheduledExecutorSubclassTe
1146       * invokeAll(c) returns results of all completed tasks
1147       */
1148      public void testInvokeAll5() throws Exception {
1149 <        ExecutorService e = new CustomExecutor(2);
1150 <        try {
1151 <            List<Callable<String>> l = new ArrayList<Callable<String>>();
1149 >        final ExecutorService e = new CustomExecutor(2);
1150 >        try (PoolCleaner cleaner = cleaner(e)) {
1151 >            List<Callable<String>> l = new ArrayList<>();
1152              l.add(new StringTask());
1153              l.add(new StringTask());
1154              List<Future<String>> futures = e.invokeAll(l);
1155              assertEquals(2, futures.size());
1156              for (Future<String> future : futures)
1157                  assertSame(TEST_STRING, future.get());
1037        } finally {
1038            joinPool(e);
1158          }
1159      }
1160  
# Line 1043 | Line 1162 | public class ScheduledExecutorSubclassTe
1162       * timed invokeAny(null) throws NPE
1163       */
1164      public void testTimedInvokeAny1() throws Exception {
1165 <        ExecutorService e = new CustomExecutor(2);
1166 <        try {
1167 <            e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS);
1168 <            shouldThrow();
1169 <        } catch (NullPointerException success) {
1170 <        } finally {
1052 <            joinPool(e);
1165 >        final ExecutorService e = new CustomExecutor(2);
1166 >        try (PoolCleaner cleaner = cleaner(e)) {
1167 >            try {
1168 >                e.invokeAny(null, randomTimeout(), randomTimeUnit());
1169 >                shouldThrow();
1170 >            } catch (NullPointerException success) {}
1171          }
1172      }
1173  
# Line 1057 | Line 1175 | public class ScheduledExecutorSubclassTe
1175       * timed invokeAny(,,null) throws NPE
1176       */
1177      public void testTimedInvokeAnyNullTimeUnit() throws Exception {
1178 <        ExecutorService e = new CustomExecutor(2);
1179 <        List<Callable<String>> l = new ArrayList<Callable<String>>();
1180 <        l.add(new StringTask());
1181 <        try {
1182 <            e.invokeAny(l, MEDIUM_DELAY_MS, null);
1183 <            shouldThrow();
1184 <        } catch (NullPointerException success) {
1185 <        } finally {
1068 <            joinPool(e);
1178 >        final ExecutorService e = new CustomExecutor(2);
1179 >        try (PoolCleaner cleaner = cleaner(e)) {
1180 >            List<Callable<String>> l = new ArrayList<>();
1181 >            l.add(new StringTask());
1182 >            try {
1183 >                e.invokeAny(l, randomTimeout(), null);
1184 >                shouldThrow();
1185 >            } catch (NullPointerException success) {}
1186          }
1187      }
1188  
1189      /**
1190 <     * timed invokeAny(empty collection) throws IAE
1190 >     * timed invokeAny(empty collection) throws IllegalArgumentException
1191       */
1192      public void testTimedInvokeAny2() throws Exception {
1193 <        ExecutorService e = new CustomExecutor(2);
1194 <        try {
1195 <            e.invokeAny(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);
1196 <            shouldThrow();
1197 <        } catch (IllegalArgumentException success) {
1198 <        } finally {
1199 <            joinPool(e);
1193 >        final ExecutorService e = new CustomExecutor(2);
1194 >        final Collection<Callable<String>> emptyCollection
1195 >            = Collections.emptyList();
1196 >        try (PoolCleaner cleaner = cleaner(e)) {
1197 >            try {
1198 >                e.invokeAny(emptyCollection, randomTimeout(), randomTimeUnit());
1199 >                shouldThrow();
1200 >            } catch (IllegalArgumentException success) {}
1201          }
1202      }
1203  
# Line 1088 | Line 1206 | public class ScheduledExecutorSubclassTe
1206       */
1207      public void testTimedInvokeAny3() throws Exception {
1208          CountDownLatch latch = new CountDownLatch(1);
1209 <        ExecutorService e = new CustomExecutor(2);
1210 <        List<Callable<String>> l = new ArrayList<Callable<String>>();
1211 <        l.add(latchAwaitingStringTask(latch));
1212 <        l.add(null);
1213 <        try {
1214 <            e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
1215 <            shouldThrow();
1216 <        } catch (NullPointerException success) {
1217 <        } finally {
1209 >        final ExecutorService e = new CustomExecutor(2);
1210 >        try (PoolCleaner cleaner = cleaner(e)) {
1211 >            List<Callable<String>> l = new ArrayList<>();
1212 >            l.add(latchAwaitingStringTask(latch));
1213 >            l.add(null);
1214 >            try {
1215 >                e.invokeAny(l, randomTimeout(), randomTimeUnit());
1216 >                shouldThrow();
1217 >            } catch (NullPointerException success) {}
1218              latch.countDown();
1101            joinPool(e);
1219          }
1220      }
1221  
# Line 1106 | Line 1223 | public class ScheduledExecutorSubclassTe
1223       * timed invokeAny(c) throws ExecutionException if no task completes
1224       */
1225      public void testTimedInvokeAny4() throws Exception {
1226 <        ExecutorService e = new CustomExecutor(2);
1227 <        List<Callable<String>> l = new ArrayList<Callable<String>>();
1228 <        l.add(new NPETask());
1229 <        try {
1230 <            e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
1231 <            shouldThrow();
1232 <        } catch (ExecutionException success) {
1233 <            assertTrue(success.getCause() instanceof NullPointerException);
1234 <        } finally {
1235 <            joinPool(e);
1226 >        final ExecutorService e = new CustomExecutor(2);
1227 >        try (PoolCleaner cleaner = cleaner(e)) {
1228 >            long startTime = System.nanoTime();
1229 >            List<Callable<String>> l = new ArrayList<>();
1230 >            l.add(new NPETask());
1231 >            try {
1232 >                e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
1233 >                shouldThrow();
1234 >            } catch (ExecutionException success) {
1235 >                assertTrue(success.getCause() instanceof NullPointerException);
1236 >            }
1237 >            assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
1238          }
1239      }
1240  
# Line 1123 | Line 1242 | public class ScheduledExecutorSubclassTe
1242       * timed invokeAny(c) returns result of some task
1243       */
1244      public void testTimedInvokeAny5() throws Exception {
1245 <        ExecutorService e = new CustomExecutor(2);
1246 <        try {
1247 <            List<Callable<String>> l = new ArrayList<Callable<String>>();
1245 >        final ExecutorService e = new CustomExecutor(2);
1246 >        try (PoolCleaner cleaner = cleaner(e)) {
1247 >            long startTime = System.nanoTime();
1248 >            List<Callable<String>> l = new ArrayList<>();
1249              l.add(new StringTask());
1250              l.add(new StringTask());
1251 <            String result = e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
1251 >            String result = e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
1252              assertSame(TEST_STRING, result);
1253 <        } finally {
1134 <            joinPool(e);
1253 >            assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
1254          }
1255      }
1256  
1257      /**
1258 <     * timed invokeAll(null) throws NPE
1258 >     * timed invokeAll(null) throws NullPointerException
1259       */
1260      public void testTimedInvokeAll1() throws Exception {
1261 <        ExecutorService e = new CustomExecutor(2);
1262 <        try {
1263 <            e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS);
1264 <            shouldThrow();
1265 <        } catch (NullPointerException success) {
1266 <        } finally {
1148 <            joinPool(e);
1261 >        final ExecutorService e = new CustomExecutor(2);
1262 >        try (PoolCleaner cleaner = cleaner(e)) {
1263 >            try {
1264 >                e.invokeAll(null, randomTimeout(), randomTimeUnit());
1265 >                shouldThrow();
1266 >            } catch (NullPointerException success) {}
1267          }
1268      }
1269  
1270      /**
1271 <     * timed invokeAll(,,null) throws NPE
1271 >     * timed invokeAll(,,null) throws NullPointerException
1272       */
1273      public void testTimedInvokeAllNullTimeUnit() throws Exception {
1274 <        ExecutorService e = new CustomExecutor(2);
1275 <        List<Callable<String>> l = new ArrayList<Callable<String>>();
1276 <        l.add(new StringTask());
1277 <        try {
1278 <            e.invokeAll(l, MEDIUM_DELAY_MS, null);
1279 <            shouldThrow();
1280 <        } catch (NullPointerException success) {
1281 <        } finally {
1164 <            joinPool(e);
1274 >        final ExecutorService e = new CustomExecutor(2);
1275 >        try (PoolCleaner cleaner = cleaner(e)) {
1276 >            List<Callable<String>> l = new ArrayList<>();
1277 >            l.add(new StringTask());
1278 >            try {
1279 >                e.invokeAll(l, randomTimeout(), null);
1280 >                shouldThrow();
1281 >            } catch (NullPointerException success) {}
1282          }
1283      }
1284  
1285      /**
1286 <     * timed invokeAll(empty collection) returns empty collection
1286 >     * timed invokeAll(empty collection) returns empty list
1287       */
1288      public void testTimedInvokeAll2() throws Exception {
1289 <        ExecutorService e = new CustomExecutor(2);
1290 <        try {
1291 <            List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);
1289 >        final ExecutorService e = new CustomExecutor(2);
1290 >        final Collection<Callable<String>> emptyCollection
1291 >            = Collections.emptyList();
1292 >        try (PoolCleaner cleaner = cleaner(e)) {
1293 >            List<Future<String>> r =
1294 >                e.invokeAll(emptyCollection, randomTimeout(), randomTimeUnit());
1295              assertTrue(r.isEmpty());
1176        } finally {
1177            joinPool(e);
1296          }
1297      }
1298  
# Line 1182 | Line 1300 | public class ScheduledExecutorSubclassTe
1300       * timed invokeAll(c) throws NPE if c has null elements
1301       */
1302      public void testTimedInvokeAll3() throws Exception {
1303 <        ExecutorService e = new CustomExecutor(2);
1304 <        List<Callable<String>> l = new ArrayList<Callable<String>>();
1305 <        l.add(new StringTask());
1306 <        l.add(null);
1307 <        try {
1308 <            e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
1309 <            shouldThrow();
1310 <        } catch (NullPointerException success) {
1311 <        } finally {
1194 <            joinPool(e);
1303 >        final ExecutorService e = new CustomExecutor(2);
1304 >        try (PoolCleaner cleaner = cleaner(e)) {
1305 >            List<Callable<String>> l = new ArrayList<>();
1306 >            l.add(new StringTask());
1307 >            l.add(null);
1308 >            try {
1309 >                e.invokeAll(l, randomTimeout(), randomTimeUnit());
1310 >                shouldThrow();
1311 >            } catch (NullPointerException success) {}
1312          }
1313      }
1314  
# Line 1199 | Line 1316 | public class ScheduledExecutorSubclassTe
1316       * get of element of invokeAll(c) throws exception on failed task
1317       */
1318      public void testTimedInvokeAll4() throws Exception {
1319 <        ExecutorService e = new CustomExecutor(2);
1320 <        List<Callable<String>> l = new ArrayList<Callable<String>>();
1321 <        l.add(new NPETask());
1322 <        List<Future<String>> futures =
1323 <            e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
1324 <        assertEquals(1, futures.size());
1325 <        try {
1326 <            futures.get(0).get();
1327 <            shouldThrow();
1328 <        } catch (ExecutionException success) {
1329 <            assertTrue(success.getCause() instanceof NullPointerException);
1330 <        } finally {
1331 <            joinPool(e);
1319 >        final ExecutorService e = new CustomExecutor(2);
1320 >        final Collection<Callable<String>> c = new ArrayList<>();
1321 >        c.add(new NPETask());
1322 >        try (PoolCleaner cleaner = cleaner(e)) {
1323 >            List<Future<String>> futures =
1324 >                e.invokeAll(c, LONG_DELAY_MS, MILLISECONDS);
1325 >            assertEquals(1, futures.size());
1326 >            try {
1327 >                futures.get(0).get();
1328 >                shouldThrow();
1329 >            } catch (ExecutionException success) {
1330 >                assertTrue(success.getCause() instanceof NullPointerException);
1331 >            }
1332          }
1333      }
1334  
# Line 1219 | Line 1336 | public class ScheduledExecutorSubclassTe
1336       * timed invokeAll(c) returns results of all completed tasks
1337       */
1338      public void testTimedInvokeAll5() throws Exception {
1339 <        ExecutorService e = new CustomExecutor(2);
1340 <        try {
1341 <            List<Callable<String>> l = new ArrayList<Callable<String>>();
1339 >        final ExecutorService e = new CustomExecutor(2);
1340 >        try (PoolCleaner cleaner = cleaner(e)) {
1341 >            List<Callable<String>> l = new ArrayList<>();
1342              l.add(new StringTask());
1343              l.add(new StringTask());
1344              List<Future<String>> futures =
1345 <                e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
1345 >                e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS);
1346              assertEquals(2, futures.size());
1347              for (Future<String> future : futures)
1348                  assertSame(TEST_STRING, future.get());
1232        } finally {
1233            joinPool(e);
1349          }
1350      }
1351  
# Line 1238 | Line 1353 | public class ScheduledExecutorSubclassTe
1353       * timed invokeAll(c) cancels tasks not completed by timeout
1354       */
1355      public void testTimedInvokeAll6() throws Exception {
1356 <        ExecutorService e = new CustomExecutor(2);
1357 <        try {
1358 <            List<Callable<String>> l = new ArrayList<Callable<String>>();
1359 <            l.add(new StringTask());
1360 <            l.add(Executors.callable(new MediumPossiblyInterruptedRunnable(), TEST_STRING));
1361 <            l.add(new StringTask());
1362 <            List<Future<String>> futures =
1363 <                e.invokeAll(l, SHORT_DELAY_MS, MILLISECONDS);
1364 <            assertEquals(l.size(), futures.size());
1365 <            for (Future future : futures)
1366 <                assertTrue(future.isDone());
1367 <            assertFalse(futures.get(0).isCancelled());
1368 <            assertTrue(futures.get(1).isCancelled());
1369 <        } finally {
1370 <            joinPool(e);
1356 >        for (long timeout = timeoutMillis();;) {
1357 >            final CountDownLatch done = new CountDownLatch(1);
1358 >            final Callable<String> waiter = new CheckedCallable<String>() {
1359 >                public String realCall() {
1360 >                    try { done.await(LONG_DELAY_MS, MILLISECONDS); }
1361 >                    catch (InterruptedException ok) {}
1362 >                    return "1"; }};
1363 >            final ExecutorService p = new CustomExecutor(2);
1364 >            try (PoolCleaner cleaner = cleaner(p, done)) {
1365 >                List<Callable<String>> tasks = new ArrayList<>();
1366 >                tasks.add(new StringTask("0"));
1367 >                tasks.add(waiter);
1368 >                tasks.add(new StringTask("2"));
1369 >                long startTime = System.nanoTime();
1370 >                List<Future<String>> futures =
1371 >                    p.invokeAll(tasks, timeout, MILLISECONDS);
1372 >                assertEquals(tasks.size(), futures.size());
1373 >                assertTrue(millisElapsedSince(startTime) >= timeout);
1374 >                for (Future future : futures)
1375 >                    assertTrue(future.isDone());
1376 >                assertTrue(futures.get(1).isCancelled());
1377 >                try {
1378 >                    assertEquals("0", futures.get(0).get());
1379 >                    assertEquals("2", futures.get(2).get());
1380 >                    break;
1381 >                } catch (CancellationException retryWithLongerTimeout) {
1382 >                    timeout *= 2;
1383 >                    if (timeout >= LONG_DELAY_MS / 2)
1384 >                        fail("expected exactly one task to be cancelled");
1385 >                }
1386 >            }
1387          }
1388      }
1389  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines