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.47 by jsr166, Mon Oct 5 20:45:41 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 105 | Line 111 | public class ScheduledExecutorSubclassTe
111              final Runnable task = new CheckedRunnable() {
112                  public void realRun() { done.countDown(); }};
113              p.execute(task);
114 <            assertTrue(done.await(LONG_DELAY_MS, MILLISECONDS));
114 >            await(done);
115          }
116      }
117  
# Line 113 | Line 119 | public class ScheduledExecutorSubclassTe
119       * delayed schedule of callable successfully executes after delay
120       */
121      public void testSchedule1() throws Exception {
122 +        final CountDownLatch done = new CountDownLatch(1);
123          final CustomExecutor p = new CustomExecutor(1);
124 <        try (PoolCleaner cleaner = cleaner(p)) {
124 >        try (PoolCleaner cleaner = cleaner(p, done)) {
125              final long startTime = System.nanoTime();
119            final CountDownLatch done = new CountDownLatch(1);
126              Callable task = new CheckedCallable<Boolean>() {
127                  public Boolean realCall() {
128                      done.countDown();
# Line 126 | Line 132 | public class ScheduledExecutorSubclassTe
132              Future f = p.schedule(task, timeoutMillis(), MILLISECONDS);
133              assertSame(Boolean.TRUE, f.get());
134              assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
129            assertTrue(done.await(0L, MILLISECONDS));
135          }
136      }
137  
# Line 200 | 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          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");
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          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");
278 >            fail("unexpected execution rate");
279          }
280      }
281  
# Line 271 | Line 299 | public class ScheduledExecutorSubclassTe
299          final CustomExecutor p = new CustomExecutor(1);
300          try (PoolCleaner cleaner = cleaner(p)) {
301              try {
302 <                TrackedCallable callable = null;
303 <                Future f = p.schedule(callable, SHORT_DELAY_MS, MILLISECONDS);
302 >                Future f = p.schedule((Callable)null,
303 >                                      randomTimeout(), randomTimeUnit());
304                  shouldThrow();
305              } catch (NullPointerException success) {}
306          }
# Line 287 | Line 315 | public class ScheduledExecutorSubclassTe
315              try {
316                  p.shutdown();
317                  p.schedule(new NoOpRunnable(),
318 <                           MEDIUM_DELAY_MS, MILLISECONDS);
318 >                           randomTimeout(), randomTimeUnit());
319                  shouldThrow();
320              } catch (RejectedExecutionException success) {
321              } catch (SecurityException ok) {}
# Line 303 | Line 331 | public class ScheduledExecutorSubclassTe
331              try {
332                  p.shutdown();
333                  p.schedule(new NoOpCallable(),
334 <                           MEDIUM_DELAY_MS, MILLISECONDS);
334 >                           randomTimeout(), randomTimeUnit());
335                  shouldThrow();
336              } catch (RejectedExecutionException success) {
337              } catch (SecurityException ok) {}
# Line 319 | Line 347 | public class ScheduledExecutorSubclassTe
347              try {
348                  p.shutdown();
349                  p.schedule(new NoOpCallable(),
350 <                           MEDIUM_DELAY_MS, MILLISECONDS);
350 >                           randomTimeout(), randomTimeUnit());
351                  shouldThrow();
352              } catch (RejectedExecutionException success) {
353              } catch (SecurityException ok) {}
# Line 363 | Line 391 | public class ScheduledExecutorSubclassTe
391       * thread becomes active
392       */
393      public void testGetActiveCount() throws InterruptedException {
394 +        final CountDownLatch done = new CountDownLatch(1);
395          final ThreadPoolExecutor p = new CustomExecutor(2);
396 <        try (PoolCleaner cleaner = cleaner(p)) {
396 >        try (PoolCleaner cleaner = cleaner(p, done)) {
397              final CountDownLatch threadStarted = new CountDownLatch(1);
369            final CountDownLatch done = 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(MEDIUM_DELAY_MS, MILLISECONDS));
405 >            await(threadStarted);
406              assertEquals(1, p.getActiveCount());
379            done.countDown();
407          }
408      }
409  
# Line 395 | Line 422 | public class ScheduledExecutorSubclassTe
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)
# Line 427 | Line 454 | public class ScheduledExecutorSubclassTe
454       */
455      public void testGetLargestPoolSize() throws InterruptedException {
456          final int THREADS = 3;
457 +        final CountDownLatch done = new CountDownLatch(1);
458          final ThreadPoolExecutor p = new CustomExecutor(THREADS);
459 <        try (PoolCleaner cleaner = cleaner(p)) {
459 >        try (PoolCleaner cleaner = cleaner(p, done)) {
460              final CountDownLatch threadsStarted = new CountDownLatch(THREADS);
433            final CountDownLatch done = new CountDownLatch(1);
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(MEDIUM_DELAY_MS, MILLISECONDS));
469 >            await(threadsStarted);
470              assertEquals(THREADS, p.getLargestPoolSize());
444            done.countDown();
471          }
472          assertEquals(THREADS, p.getLargestPoolSize());
473      }
# Line 451 | Line 477 | public class ScheduledExecutorSubclassTe
477       * become active
478       */
479      public void testGetPoolSize() throws InterruptedException {
480 +        final CountDownLatch done = new CountDownLatch(1);
481          final ThreadPoolExecutor p = new CustomExecutor(1);
482 <        try (PoolCleaner cleaner = cleaner(p)) {
482 >        try (PoolCleaner cleaner = cleaner(p, done)) {
483              final CountDownLatch threadStarted = new CountDownLatch(1);
457            final CountDownLatch done = 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(MEDIUM_DELAY_MS, MILLISECONDS));
491 >            await(threadStarted);
492              assertEquals(1, p.getPoolSize());
467            done.countDown();
493          }
494      }
495  
# Line 473 | Line 498 | public class ScheduledExecutorSubclassTe
498       * submitted
499       */
500      public void testGetTaskCount() throws InterruptedException {
501 +        final int TASKS = 3;
502 +        final CountDownLatch done = new CountDownLatch(1);
503          final ThreadPoolExecutor p = new CustomExecutor(1);
504 <        try (PoolCleaner cleaner = cleaner(p)) {
504 >        try (PoolCleaner cleaner = cleaner(p, done)) {
505              final CountDownLatch threadStarted = new CountDownLatch(1);
479            final CountDownLatch done = new CountDownLatch(1);
480            final int TASKS = 5;
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(MEDIUM_DELAY_MS, MILLISECONDS));
525 <            assertEquals(TASKS, p.getTaskCount());
526 <            done.countDown();
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      /**
# Line 543 | Line 581 | public class ScheduledExecutorSubclassTe
581       * isTerminated is false before termination, true after
582       */
583      public void testIsTerminated() throws InterruptedException {
584 +        final CountDownLatch done = new CountDownLatch(1);
585          final ThreadPoolExecutor p = new CustomExecutor(1);
586          try (PoolCleaner cleaner = cleaner(p)) {
587              final CountDownLatch threadStarted = new CountDownLatch(1);
549            final CountDownLatch done = new CountDownLatch(1);
550            assertFalse(p.isTerminated());
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(MEDIUM_DELAY_MS, MILLISECONDS));
594 >            await(threadStarted);
595 >            assertFalse(p.isTerminated());
596              assertFalse(p.isTerminating());
597              done.countDown();
598              try { p.shutdown(); } catch (SecurityException ok) { return; }
# Line 567 | Line 605 | public class ScheduledExecutorSubclassTe
605       * isTerminating is not true when running or when terminated
606       */
607      public void testIsTerminating() throws InterruptedException {
608 +        final CountDownLatch done = new CountDownLatch(1);
609          final ThreadPoolExecutor p = new CustomExecutor(1);
610          try (PoolCleaner cleaner = cleaner(p)) {
611              final CountDownLatch threadStarted = new CountDownLatch(1);
573            final CountDownLatch done = 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(MEDIUM_DELAY_MS, MILLISECONDS));
619 >            await(threadStarted);
620              assertFalse(p.isTerminating());
621              done.countDown();
622              try { p.shutdown(); } catch (SecurityException ok) { return; }
# Line 592 | Line 630 | public class ScheduledExecutorSubclassTe
630       * getQueue returns the work queue, which contains queued tasks
631       */
632      public void testGetQueue() throws InterruptedException {
633 +        final CountDownLatch done = new CountDownLatch(1);
634          final ScheduledThreadPoolExecutor p = new CustomExecutor(1);
635 <        try (PoolCleaner cleaner = cleaner(p)) {
635 >        try (PoolCleaner cleaner = cleaner(p, done)) {
636              final CountDownLatch threadStarted = new CountDownLatch(1);
598            final CountDownLatch done = 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(MEDIUM_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]));
612            done.countDown();
650          }
651      }
652  
# Line 617 | Line 654 | public class ScheduledExecutorSubclassTe
654       * remove(task) removes queued task, and fails to remove active task
655       */
656      public void testRemove() throws InterruptedException {
657 +        final CountDownLatch done = new CountDownLatch(1);
658          final ScheduledThreadPoolExecutor p = new CustomExecutor(1);
659 <        try (PoolCleaner cleaner = cleaner(p)) {
659 >        try (PoolCleaner cleaner = cleaner(p, done)) {
660              ScheduledFuture[] tasks = new ScheduledFuture[5];
661              final CountDownLatch threadStarted = new CountDownLatch(1);
624            final CountDownLatch done = 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(MEDIUM_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 641 | 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]));
644            done.countDown();
681          }
682      }
683  
# Line 649 | Line 685 | public class ScheduledExecutorSubclassTe
685       * purge removes cancelled tasks from the queue
686       */
687      public void testPurge() throws InterruptedException {
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 <        ScheduledFuture[] tasks = new ScheduledFuture[5];
694 <        for (int i = 0; i < tasks.length; i++)
695 <            tasks[i] = p.schedule(new SmallPossiblyInterruptedRunnable(),
696 <                                  LONG_DELAY_MS, MILLISECONDS);
657 <        try {
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 666 | 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");
671        } finally {
672            for (ScheduledFuture task : tasks)
673                task.cancel(true);
674            joinPool(p);
710          }
711      }
712  
# Line 694 | 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 755 | Line 790 | public class ScheduledExecutorSubclassTe
790       * - setContinueExistingPeriodicTasksAfterShutdownPolicy
791       */
792      public void testShutdown_cancellation() throws Exception {
793 <        Boolean[] allBooleans = { null, Boolean.FALSE, Boolean.TRUE };
759 <        for (Boolean policy : allBooleans)
760 <    {
761 <        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);
782 <        final CountDownLatch periodicLatch2 = new CountDownLatch(2);
783 <        Runnable task = new CheckedRunnable() { public void realRun()
784 <                                                    throws InterruptedException {
785 <            poolBlocked.countDown();
786 <            assertTrue(unblock.await(LONG_DELAY_MS, MILLISECONDS));
787 <            ran.getAndIncrement();
788 <        }};
789 <        List<Future<?>> blockers = new ArrayList<>();
790 <        List<Future<?>> periodics = new ArrayList<>();
791 <        List<Future<?>> delayeds = new ArrayList<>();
792 <        for (int i = 0; i < poolSize; i++)
793 <            blockers.add(p.submit(task));
794 <        assertTrue(poolBlocked.await(LONG_DELAY_MS, MILLISECONDS));
795 <
796 <        periodics.add(p.scheduleAtFixedRate(countDowner(periodicLatch1),
797 <                                            1, 1, MILLISECONDS));
798 <        periodics.add(p.scheduleWithFixedDelay(countDowner(periodicLatch2),
799 <                                               1, 1, MILLISECONDS));
800 <        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());
809 <            assertTrue(effectivePeriodicPolicy ^ periodic.isDone());
810 <        }
811 <        for (Future<?> delayed : delayeds) {
812 <            assertTrue(effectiveDelayedPolicy ^ delayed.isCancelled());
813 <            assertTrue(effectiveDelayedPolicy ^ delayed.isDone());
814 <        }
815 <        if (testImplementationDetails) {
816 <            assertEquals(effectivePeriodicPolicy,
817 <                         p.getQueue().containsAll(periodics));
818 <            assertEquals(effectiveDelayedPolicy,
819 <                         p.getQueue().containsAll(delayeds));
820 <        }
821 <        // Release all pool threads
822 <        unblock.countDown();
823 <
824 <        for (Future<?> delayed : delayeds) {
825 <            if (effectiveDelayedPolicy) {
826 <                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
# Line 890 | Line 1020 | public class ScheduledExecutorSubclassTe
1020      }
1021  
1022      /**
1023 <     * invokeAny(empty collection) throws IAE
1023 >     * invokeAny(empty collection) throws IllegalArgumentException
1024       */
1025      public void testInvokeAny2() throws Exception {
1026          final ExecutorService e = new CustomExecutor(2);
# Line 909 | Line 1039 | public class ScheduledExecutorSubclassTe
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<Callable<String>>();
1042 >            List<Callable<String>> l = new ArrayList<>();
1043              l.add(latchAwaitingStringTask(latch));
1044              l.add(null);
1045              try {
# Line 926 | Line 1056 | public class ScheduledExecutorSubclassTe
1056      public void testInvokeAny4() throws Exception {
1057          final ExecutorService e = new CustomExecutor(2);
1058          try (PoolCleaner cleaner = cleaner(e)) {
1059 <            List<Callable<String>> l = new ArrayList<Callable<String>>();
1059 >            List<Callable<String>> l = new ArrayList<>();
1060              l.add(new NPETask());
1061              try {
1062                  e.invokeAny(l);
# Line 943 | Line 1073 | public class ScheduledExecutorSubclassTe
1073      public void testInvokeAny5() throws Exception {
1074          final ExecutorService e = new CustomExecutor(2);
1075          try (PoolCleaner cleaner = cleaner(e)) {
1076 <            List<Callable<String>> l = new ArrayList<Callable<String>>();
1076 >            List<Callable<String>> l = new ArrayList<>();
1077              l.add(new StringTask());
1078              l.add(new StringTask());
1079              String result = e.invokeAny(l);
# Line 965 | Line 1095 | public class ScheduledExecutorSubclassTe
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          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(new ArrayList<Callable<String>>());
1105 >            List<Future<String>> r = e.invokeAll(emptyCollection);
1106              assertTrue(r.isEmpty());
1107          }
1108      }
# Line 981 | Line 1113 | public class ScheduledExecutorSubclassTe
1113      public void testInvokeAll3() throws Exception {
1114          final ExecutorService e = new CustomExecutor(2);
1115          try (PoolCleaner cleaner = cleaner(e)) {
1116 <            List<Callable<String>> l = new ArrayList<Callable<String>>();
1116 >            List<Callable<String>> l = new ArrayList<>();
1117              l.add(new StringTask());
1118              l.add(null);
1119              try {
# Line 997 | Line 1129 | public class ScheduledExecutorSubclassTe
1129      public void testInvokeAll4() throws Exception {
1130          final ExecutorService e = new CustomExecutor(2);
1131          try (PoolCleaner cleaner = cleaner(e)) {
1132 <            List<Callable<String>> l = new ArrayList<Callable<String>>();
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());
# Line 1016 | Line 1148 | public class ScheduledExecutorSubclassTe
1148      public void testInvokeAll5() throws Exception {
1149          final ExecutorService e = new CustomExecutor(2);
1150          try (PoolCleaner cleaner = cleaner(e)) {
1151 <            List<Callable<String>> l = new ArrayList<Callable<String>>();
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);
# Line 1033 | Line 1165 | public class ScheduledExecutorSubclassTe
1165          final ExecutorService e = new CustomExecutor(2);
1166          try (PoolCleaner cleaner = cleaner(e)) {
1167              try {
1168 <                e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS);
1168 >                e.invokeAny(null, randomTimeout(), randomTimeUnit());
1169                  shouldThrow();
1170              } catch (NullPointerException success) {}
1171          }
# Line 1045 | Line 1177 | public class ScheduledExecutorSubclassTe
1177      public void testTimedInvokeAnyNullTimeUnit() throws Exception {
1178          final ExecutorService e = new CustomExecutor(2);
1179          try (PoolCleaner cleaner = cleaner(e)) {
1180 <            List<Callable<String>> l = new ArrayList<Callable<String>>();
1180 >            List<Callable<String>> l = new ArrayList<>();
1181              l.add(new StringTask());
1182              try {
1183 <                e.invokeAny(l, MEDIUM_DELAY_MS, null);
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          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(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);
1198 >                e.invokeAny(emptyCollection, randomTimeout(), randomTimeUnit());
1199                  shouldThrow();
1200              } catch (IllegalArgumentException success) {}
1201          }
# Line 1074 | Line 1208 | public class ScheduledExecutorSubclassTe
1208          CountDownLatch latch = new CountDownLatch(1);
1209          final ExecutorService e = new CustomExecutor(2);
1210          try (PoolCleaner cleaner = cleaner(e)) {
1211 <            List<Callable<String>> l = new ArrayList<Callable<String>>();
1211 >            List<Callable<String>> l = new ArrayList<>();
1212              l.add(latchAwaitingStringTask(latch));
1213              l.add(null);
1214              try {
1215 <                e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
1215 >                e.invokeAny(l, randomTimeout(), randomTimeUnit());
1216                  shouldThrow();
1217              } catch (NullPointerException success) {}
1218              latch.countDown();
# Line 1091 | Line 1225 | public class ScheduledExecutorSubclassTe
1225      public void testTimedInvokeAny4() throws Exception {
1226          final ExecutorService e = new CustomExecutor(2);
1227          try (PoolCleaner cleaner = cleaner(e)) {
1228 <            List<Callable<String>> l = new ArrayList<Callable<String>>();
1228 >            long startTime = System.nanoTime();
1229 >            List<Callable<String>> l = new ArrayList<>();
1230              l.add(new NPETask());
1231              try {
1232 <                e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
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 1108 | Line 1244 | public class ScheduledExecutorSubclassTe
1244      public void testTimedInvokeAny5() throws Exception {
1245          final ExecutorService e = new CustomExecutor(2);
1246          try (PoolCleaner cleaner = cleaner(e)) {
1247 <            List<Callable<String>> l = new ArrayList<Callable<String>>();
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 +            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          final ExecutorService e = new CustomExecutor(2);
1262          try (PoolCleaner cleaner = cleaner(e)) {
1263              try {
1264 <                e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS);
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          final ExecutorService e = new CustomExecutor(2);
1275          try (PoolCleaner cleaner = cleaner(e)) {
1276 <            List<Callable<String>> l = new ArrayList<Callable<String>>();
1276 >            List<Callable<String>> l = new ArrayList<>();
1277              l.add(new StringTask());
1278              try {
1279 <                e.invokeAll(l, MEDIUM_DELAY_MS, null);
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          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 = e.invokeAll(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);
1293 >            List<Future<String>> r =
1294 >                e.invokeAll(emptyCollection, randomTimeout(), randomTimeUnit());
1295              assertTrue(r.isEmpty());
1296          }
1297      }
# Line 1161 | Line 1302 | public class ScheduledExecutorSubclassTe
1302      public void testTimedInvokeAll3() throws Exception {
1303          final ExecutorService e = new CustomExecutor(2);
1304          try (PoolCleaner cleaner = cleaner(e)) {
1305 <            List<Callable<String>> l = new ArrayList<Callable<String>>();
1305 >            List<Callable<String>> l = new ArrayList<>();
1306              l.add(new StringTask());
1307              l.add(null);
1308              try {
1309 <                e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
1309 >                e.invokeAll(l, randomTimeout(), randomTimeUnit());
1310                  shouldThrow();
1311              } catch (NullPointerException success) {}
1312          }
# Line 1176 | Line 1317 | public class ScheduledExecutorSubclassTe
1317       */
1318      public void testTimedInvokeAll4() throws Exception {
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)) {
1180            List<Callable<String>> l = new ArrayList<Callable<String>>();
1181            l.add(new NPETask());
1323              List<Future<String>> futures =
1324 <                e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
1324 >                e.invokeAll(c, LONG_DELAY_MS, MILLISECONDS);
1325              assertEquals(1, futures.size());
1326              try {
1327                  futures.get(0).get();
# Line 1197 | Line 1338 | public class ScheduledExecutorSubclassTe
1338      public void testTimedInvokeAll5() throws Exception {
1339          final ExecutorService e = new CustomExecutor(2);
1340          try (PoolCleaner cleaner = cleaner(e)) {
1341 <            List<Callable<String>> l = new ArrayList<Callable<String>>();
1341 >            List<Callable<String>> l = new ArrayList<>();
1342              l.add(new StringTask());
1343              l.add(new StringTask());
1344              List<Future<String>> futures =
# Line 1212 | Line 1353 | public class ScheduledExecutorSubclassTe
1353       * timed invokeAll(c) cancels tasks not completed by timeout
1354       */
1355      public void testTimedInvokeAll6() throws Exception {
1356 <        final ExecutorService e = new CustomExecutor(2);
1357 <        try (PoolCleaner cleaner = cleaner(e)) {
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)

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines