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