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.43 by jsr166, Sat Oct 3 00:37: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;
# Line 16 | Line 19 | import java.util.concurrent.Cancellation
19   import java.util.concurrent.CountDownLatch;
20   import java.util.concurrent.Delayed;
21   import java.util.concurrent.ExecutionException;
19 import java.util.concurrent.Executors;
22   import java.util.concurrent.ExecutorService;
23   import java.util.concurrent.Future;
24   import java.util.concurrent.RejectedExecutionException;
# Line 25 | 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 42 | 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 99 | 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();
107 <            }};
108 <        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));
111 <        } finally {
112 <            joinPool(p);
114 >            await(done);
115          }
116      }
117  
# Line 117 | Line 119 | public class ScheduledExecutorSubclassTe
119       * delayed schedule of callable successfully executes after delay
120       */
121      public void testSchedule1() throws Exception {
120        CustomExecutor p = new CustomExecutor(1);
121        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 130 | Line 132 | public class ScheduledExecutorSubclassTe
132              Future f = p.schedule(task, timeoutMillis(), MILLISECONDS);
133              assertSame(Boolean.TRUE, f.get());
134              assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
133            assertTrue(done.await(0L, MILLISECONDS));
134        } finally {
135            joinPool(p);
135          }
136      }
137  
# Line 140 | 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 153 | Line 152 | public class ScheduledExecutorSubclassTe
152              await(done);
153              assertNull(f.get(LONG_DELAY_MS, MILLISECONDS));
154              assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
156        } finally {
157            joinPool(p);
155          }
156      }
157  
# Line 162 | 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 177 | Line 174 | public class ScheduledExecutorSubclassTe
174              await(done);
175              assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
176              f.cancel(true);
180        } finally {
181            joinPool(p);
177          }
178      }
179  
# Line 186 | 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 201 | Line 196 | public class ScheduledExecutorSubclassTe
196              await(done);
197              assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
198              f.cancel(true);
204        } finally {
205            joinPool(p);
199          }
200      }
201  
# Line 212 | 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");
237 <        } finally {
238 <            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");
265 <        } finally {
266 <            joinPool(p);
278 >            fail("unexpected execution rate");
279          }
280      }
281  
# Line 271 | 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          }
308
309        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          }
325        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          }
341        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          }
357        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          }
373        joinPool(se);
387      }
388  
389      /**
# Line 378 | Line 391 | public class ScheduledExecutorSubclassTe
391       * thread becomes active
392       */
393      public void testGetActiveCount() throws InterruptedException {
381        final ThreadPoolExecutor p = new CustomExecutor(2);
382        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());
394        } finally {
395            done.countDown();
396            joinPool(p);
407          }
408      }
409  
# Line 403 | 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              }
428        } finally {
429            joinPool(p);
438          }
439      }
440  
# Line 434 | 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 445 | Line 454 | public class ScheduledExecutorSubclassTe
454       */
455      public void testGetLargestPoolSize() throws InterruptedException {
456          final int THREADS = 3;
448        final ThreadPoolExecutor p = new CustomExecutor(THREADS);
449        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));
461 <            assertEquals(THREADS, p.getLargestPoolSize());
462 <        } finally {
463 <            done.countDown();
464 <            joinPool(p);
469 >            await(threadsStarted);
470              assertEquals(THREADS, p.getLargestPoolSize());
471          }
472 +        assertEquals(THREADS, p.getLargestPoolSize());
473      }
474  
475      /**
# Line 471 | Line 477 | public class ScheduledExecutorSubclassTe
477       * become active
478       */
479      public void testGetPoolSize() throws InterruptedException {
474        final ThreadPoolExecutor p = new CustomExecutor(1);
475        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());
487        } finally {
488            done.countDown();
489            joinPool(p);
493          }
494      }
495  
# Line 495 | Line 498 | public class ScheduledExecutorSubclassTe
498       * submitted
499       */
500      public void testGetTaskCount() throws InterruptedException {
501 <        final ThreadPoolExecutor p = new CustomExecutor(1);
499 <        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 {
513 <            done.countDown();
514 <            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 {
549 <            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 554 | 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());
560        }
561        finally {
575              try { p.shutdown(); } catch (SecurityException ok) { return; }
576 +            assertTrue(p.isShutdown());
577          }
564        assertTrue(p.isShutdown());
578      }
579  
580      /**
581       * isTerminated is false before termination, true after
582       */
583      public void testIsTerminated() throws InterruptedException {
571        final ThreadPoolExecutor p = new CustomExecutor(1);
572        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();
585        } finally {
598              try { p.shutdown(); } catch (SecurityException ok) { return; }
599 +            assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
600 +            assertTrue(p.isTerminated());
601          }
588        assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
589        assertTrue(p.isTerminated());
602      }
603  
604      /**
605       * isTerminating is not true when running or when terminated
606       */
607      public void testIsTerminating() throws InterruptedException {
596        final ThreadPoolExecutor p = new CustomExecutor(1);
597        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();
610        } 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          }
613        assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
614        assertTrue(p.isTerminated());
615        assertFalse(p.isTerminating());
627      }
628  
629      /**
630       * getQueue returns the work queue, which contains queued tasks
631       */
632      public void testGetQueue() throws InterruptedException {
622        ScheduledThreadPoolExecutor p = new CustomExecutor(1);
623        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]));
639        } finally {
640            done.countDown();
641            joinPool(p);
650          }
651      }
652  
# Line 646 | Line 654 | public class ScheduledExecutorSubclassTe
654       * remove(task) removes queued task, and fails to remove active task
655       */
656      public void testRemove() throws InterruptedException {
649        final ScheduledThreadPoolExecutor p = new CustomExecutor(1);
650        ScheduledFuture[] tasks = new ScheduledFuture[5];
651        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 670 | 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]));
673        } finally {
674            done.countDown();
675            joinPool(p);
681          }
682      }
683  
# Line 680 | 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 697 | 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");
702        } finally {
703            for (ScheduledFuture task : tasks)
704                task.cancel(true);
705            joinPool(p);
710          }
711      }
712  
# Line 715 | Line 719 | public class ScheduledExecutorSubclassTe
719          final int count = 5;
720          final AtomicInteger ran = new AtomicInteger(0);
721          final CustomExecutor p = new CustomExecutor(poolSize);
722 <        CountDownLatch threadsStarted = new CountDownLatch(poolSize);
722 >        final CountDownLatch threadsStarted = new CountDownLatch(poolSize);
723          Runnable waiter = new CheckedRunnable() { public void realRun() {
724              threadsStarted.countDown();
725              try {
# Line 725 | Line 729 | public class ScheduledExecutorSubclassTe
729          }};
730          for (int i = 0; i < count; i++)
731              p.execute(waiter);
732 <        assertTrue(threadsStarted.await(LONG_DELAY_MS, MILLISECONDS));
732 >        await(threadsStarted);
733          assertEquals(poolSize, p.getActiveCount());
734          assertEquals(0, p.getCompletedTaskCount());
735          final List<Runnable> queuedTasks;
# Line 748 | Line 752 | public class ScheduledExecutorSubclassTe
752       * and those tasks are drained from the queue
753       */
754      public void testShutdownNow_delayedTasks() throws InterruptedException {
755 <        CustomExecutor p = new CustomExecutor(1);
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();
# Line 786 | Line 790 | public class ScheduledExecutorSubclassTe
790       * - setContinueExistingPeriodicTasksAfterShutdownPolicy
791       */
792      public void testShutdown_cancellation() throws Exception {
793 <        Boolean[] allBooleans = { null, Boolean.FALSE, Boolean.TRUE };
790 <        for (Boolean policy : allBooleans)
791 <    {
792 <        final int poolSize = 2;
793 >        final int poolSize = 4;
794          final CustomExecutor p = new CustomExecutor(poolSize);
795 <        final boolean effectiveDelayedPolicy = (policy != Boolean.FALSE);
796 <        final boolean effectivePeriodicPolicy = (policy == Boolean.TRUE);
797 <        final boolean effectiveRemovePolicy = (policy == Boolean.TRUE);
798 <        if (policy != null) {
799 <            p.setExecuteExistingDelayedTasksAfterShutdownPolicy(policy);
800 <            p.setContinueExistingPeriodicTasksAfterShutdownPolicy(policy);
801 <            p.setRemoveOnCancelPolicy(policy);
802 <        }
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 <        // Strategy: Wedge the pool with poolSize "blocker" threads
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 CountDownLatch periodicLatch1 = new CountDownLatch(2);
813 <        final CountDownLatch periodicLatch2 = new CountDownLatch(2);
814 <        Runnable task = new CheckedRunnable() { public void realRun()
815 <                                                    throws InterruptedException {
816 <            poolBlocked.countDown();
817 <            assertTrue(unblock.await(LONG_DELAY_MS, MILLISECONDS));
818 <            ran.getAndIncrement();
819 <        }};
820 <        List<Future<?>> blockers = new ArrayList<>();
821 <        List<Future<?>> periodics = new ArrayList<>();
822 <        List<Future<?>> delayeds = new ArrayList<>();
823 <        for (int i = 0; i < poolSize; i++)
824 <            blockers.add(p.submit(task));
825 <        assertTrue(poolBlocked.await(LONG_DELAY_MS, MILLISECONDS));
826 <
827 <        periodics.add(p.scheduleAtFixedRate(countDowner(periodicLatch1),
828 <                                            1, 1, MILLISECONDS));
829 <        periodics.add(p.scheduleWithFixedDelay(countDowner(periodicLatch2),
830 <                                               1, 1, MILLISECONDS));
831 <        delayeds.add(p.schedule(task, 1, MILLISECONDS));
834 >        final RuntimeException exception = new RuntimeException();
835  
836 <        assertTrue(p.getQueue().containsAll(periodics));
837 <        assertTrue(p.getQueue().containsAll(delayeds));
838 <        try { p.shutdown(); } catch (SecurityException ok) { return; }
839 <        assertTrue(p.isShutdown());
840 <        assertFalse(p.isTerminated());
841 <        for (Future<?> periodic : periodics) {
842 <            assertTrue(effectivePeriodicPolicy ^ periodic.isCancelled());
840 <            assertTrue(effectivePeriodicPolicy ^ periodic.isDone());
841 <        }
842 <        for (Future<?> delayed : delayeds) {
843 <            assertTrue(effectiveDelayedPolicy ^ delayed.isCancelled());
844 <            assertTrue(effectiveDelayedPolicy ^ delayed.isDone());
845 <        }
846 <        if (testImplementationDetails) {
847 <            assertEquals(effectivePeriodicPolicy,
848 <                         p.getQueue().containsAll(periodics));
849 <            assertEquals(effectiveDelayedPolicy,
850 <                         p.getQueue().containsAll(delayeds));
851 <        }
852 <        // Release all pool threads
853 <        unblock.countDown();
854 <
855 <        for (Future<?> delayed : delayeds) {
856 <            if (effectiveDelayedPolicy) {
857 <                assertNull(delayed.get());
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          }
845 <        if (effectivePeriodicPolicy) {
846 <            assertTrue(periodicLatch1.await(LONG_DELAY_MS, MILLISECONDS));
847 <            assertTrue(periodicLatch2.await(LONG_DELAY_MS, MILLISECONDS));
848 <            for (Future<?> periodic : periodics) {
849 <                assertTrue(periodic.cancel(false));
850 <                assertTrue(periodic.isCancelled());
851 <                assertTrue(periodic.isDone());
845 >
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.isTerminating());
896 +        assertFalse(p.isTerminated());
897 +
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 <        assertEquals(2 + (effectiveDelayedPolicy ? 1 : 0), ran.get());
942 <    }}
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);
883        } finally {
884            joinPool(e);
982          }
983      }
984  
# Line 889 | 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());
897        } finally {
898            joinPool(e);
994          }
995      }
996  
# Line 903 | 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);
911        } finally {
912            joinPool(e);
1006          }
1007      }
1008  
# Line 917 | 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 {
926 <            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 {
940 <            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 945 | 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();
959            joinPool(e);
1050          }
1051      }
1052  
# Line 964 | 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 981 | 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);
991        } finally {
992            joinPool(e);
1081          }
1082      }
1083  
# Line 997 | 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 {
1006 <            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());
1018        } finally {
1019            joinPool(e);
1107          }
1108      }
1109  
# Line 1024 | 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 {
1036 <            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 1041 | 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 1060 | 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());
1072        } finally {
1073            joinPool(e);
1158          }
1159      }
1160  
# Line 1078 | 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 {
1087 <            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 1092 | 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 {
1103 <            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 1123 | 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();
1136            joinPool(e);
1219          }
1220      }
1221  
# Line 1141 | 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 1158 | 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 {
1169 <            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 {
1183 <            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 {
1199 <            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());
1211        } finally {
1212            joinPool(e);
1296          }
1297      }
1298  
# Line 1217 | 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 {
1229 <            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 1234 | 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 1254 | 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 =
# Line 1264 | Line 1346 | public class ScheduledExecutorSubclassTe
1346              assertEquals(2, futures.size());
1347              for (Future<String> future : futures)
1348                  assertSame(TEST_STRING, future.get());
1267        } finally {
1268            joinPool(e);
1349          }
1350      }
1351  
# Line 1273 | 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 <            for (long timeout = timeoutMillis();;) {
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(Executors.callable(new LongPossiblyInterruptedRunnable(), TEST_STRING));
1367 >                tasks.add(waiter);
1368                  tasks.add(new StringTask("2"));
1369                  long startTime = System.nanoTime();
1370                  List<Future<String>> futures =
1371 <                    e.invokeAll(tasks, timeout, MILLISECONDS);
1371 >                    p.invokeAll(tasks, timeout, MILLISECONDS);
1372                  assertEquals(tasks.size(), futures.size());
1373                  assertTrue(millisElapsedSince(startTime) >= timeout);
1374                  for (Future future : futures)
# Line 1298 | Line 1384 | public class ScheduledExecutorSubclassTe
1384                          fail("expected exactly one task to be cancelled");
1385                  }
1386              }
1301        } finally {
1302            joinPool(e);
1387          }
1388      }
1389  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines