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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines