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.SECONDS;
13
14import java.util.ArrayList;
15import java.util.List;
16import java.util.concurrent.ArrayBlockingQueue;
17import java.util.concurrent.BlockingQueue;
18import java.util.concurrent.Callable;
19import java.util.concurrent.CancellationException;
20import java.util.concurrent.CountDownLatch;
21import java.util.concurrent.ExecutionException;
22import java.util.concurrent.Executors;
23import java.util.concurrent.ExecutorService;
24import java.util.concurrent.Future;
25import java.util.concurrent.FutureTask;
26import java.util.concurrent.LinkedBlockingQueue;
27import java.util.concurrent.RejectedExecutionException;
28import java.util.concurrent.RejectedExecutionHandler;
29import java.util.concurrent.RunnableFuture;
30import java.util.concurrent.SynchronousQueue;
31import java.util.concurrent.ThreadFactory;
32import java.util.concurrent.ThreadPoolExecutor;
33import java.util.concurrent.TimeoutException;
34import java.util.concurrent.TimeUnit;
35import java.util.concurrent.atomic.AtomicInteger;
36import java.util.concurrent.locks.Condition;
37import java.util.concurrent.locks.ReentrantLock;
38
39import junit.framework.Test;
40import junit.framework.TestSuite;
41
42public class ThreadPoolExecutorSubclassTest extends JSR166TestCase {
43    // android-note: Removed because the CTS runner does a bad job of
44    // retrying tests that have suite() declarations.
45    //
46    // public static void main(String[] args) {
47    //     main(suite(), args);
48    // }
49    // public static Test suite() {
50    //     return new TestSuite(ThreadPoolExecutorSubclassTest.class);
51    // }
52
53    static class CustomTask<V> implements RunnableFuture<V> {
54        final Callable<V> callable;
55        final ReentrantLock lock = new ReentrantLock();
56        final Condition cond = lock.newCondition();
57        boolean done;
58        boolean cancelled;
59        V result;
60        Thread thread;
61        Exception exception;
62        CustomTask(Callable<V> c) {
63            if (c == null) throw new NullPointerException();
64            callable = c;
65        }
66        CustomTask(final Runnable r, final V res) {
67            if (r == null) throw new NullPointerException();
68            callable = new Callable<V>() {
69                public V call() throws Exception { r.run(); return res; }};
70        }
71        public boolean isDone() {
72            lock.lock(); try { return done; } finally { lock.unlock() ; }
73        }
74        public boolean isCancelled() {
75            lock.lock(); try { return cancelled; } finally { lock.unlock() ; }
76        }
77        public boolean cancel(boolean mayInterrupt) {
78            lock.lock();
79            try {
80                if (!done) {
81                    cancelled = true;
82                    done = true;
83                    if (mayInterrupt && thread != null)
84                        thread.interrupt();
85                    return true;
86                }
87                return false;
88            }
89            finally { lock.unlock() ; }
90        }
91        public void run() {
92            lock.lock();
93            try {
94                if (done)
95                    return;
96                thread = Thread.currentThread();
97            }
98            finally { lock.unlock() ; }
99            V v = null;
100            Exception e = null;
101            try {
102                v = callable.call();
103            }
104            catch (Exception ex) {
105                e = ex;
106            }
107            lock.lock();
108            try {
109                if (!done) {
110                    result = v;
111                    exception = e;
112                    done = true;
113                    thread = null;
114                    cond.signalAll();
115                }
116            }
117            finally { lock.unlock(); }
118        }
119        public V get() throws InterruptedException, ExecutionException {
120            lock.lock();
121            try {
122                while (!done)
123                    cond.await();
124                if (cancelled)
125                    throw new CancellationException();
126                if (exception != null)
127                    throw new ExecutionException(exception);
128                return result;
129            }
130            finally { lock.unlock(); }
131        }
132        public V get(long timeout, TimeUnit unit)
133            throws InterruptedException, ExecutionException, TimeoutException {
134            long nanos = unit.toNanos(timeout);
135            lock.lock();
136            try {
137                while (!done) {
138                    if (nanos <= 0L)
139                        throw new TimeoutException();
140                    nanos = cond.awaitNanos(nanos);
141                }
142                if (cancelled)
143                    throw new CancellationException();
144                if (exception != null)
145                    throw new ExecutionException(exception);
146                return result;
147            }
148            finally { lock.unlock(); }
149        }
150    }
151
152    static class CustomTPE extends ThreadPoolExecutor {
153        protected <V> RunnableFuture<V> newTaskFor(Callable<V> c) {
154            return new CustomTask<V>(c);
155        }
156        protected <V> RunnableFuture<V> newTaskFor(Runnable r, V v) {
157            return new CustomTask<V>(r, v);
158        }
159
160        CustomTPE(int corePoolSize,
161                  int maximumPoolSize,
162                  long keepAliveTime,
163                  TimeUnit unit,
164                  BlockingQueue<Runnable> workQueue) {
165            super(corePoolSize, maximumPoolSize, keepAliveTime, unit,
166                  workQueue);
167        }
168        CustomTPE(int corePoolSize,
169                  int maximumPoolSize,
170                  long keepAliveTime,
171                  TimeUnit unit,
172                  BlockingQueue<Runnable> workQueue,
173                  ThreadFactory threadFactory) {
174        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
175             threadFactory);
176        }
177
178        CustomTPE(int corePoolSize,
179                  int maximumPoolSize,
180                  long keepAliveTime,
181                  TimeUnit unit,
182                  BlockingQueue<Runnable> workQueue,
183                  RejectedExecutionHandler handler) {
184        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
185              handler);
186        }
187        CustomTPE(int corePoolSize,
188                  int maximumPoolSize,
189                  long keepAliveTime,
190                  TimeUnit unit,
191                  BlockingQueue<Runnable> workQueue,
192                  ThreadFactory threadFactory,
193                  RejectedExecutionHandler handler) {
194            super(corePoolSize, maximumPoolSize, keepAliveTime, unit,
195              workQueue, threadFactory, handler);
196        }
197
198        final CountDownLatch beforeCalled = new CountDownLatch(1);
199        final CountDownLatch afterCalled = new CountDownLatch(1);
200        final CountDownLatch terminatedCalled = new CountDownLatch(1);
201
202        public CustomTPE() {
203            super(1, 1, LONG_DELAY_MS, MILLISECONDS, new SynchronousQueue<Runnable>());
204        }
205        protected void beforeExecute(Thread t, Runnable r) {
206            beforeCalled.countDown();
207        }
208        protected void afterExecute(Runnable r, Throwable t) {
209            afterCalled.countDown();
210        }
211        protected void terminated() {
212            terminatedCalled.countDown();
213        }
214
215        public boolean beforeCalled() {
216            return beforeCalled.getCount() == 0;
217        }
218        public boolean afterCalled() {
219            return afterCalled.getCount() == 0;
220        }
221        public boolean terminatedCalled() {
222            return terminatedCalled.getCount() == 0;
223        }
224    }
225
226    static class FailingThreadFactory implements ThreadFactory {
227        int calls = 0;
228        public Thread newThread(Runnable r) {
229            if (++calls > 1) return null;
230            return new Thread(r);
231        }
232    }
233
234    /**
235     * execute successfully executes a runnable
236     */
237    public void testExecute() throws InterruptedException {
238        final ThreadPoolExecutor p =
239            new CustomTPE(1, 1,
240                          2 * LONG_DELAY_MS, MILLISECONDS,
241                          new ArrayBlockingQueue<Runnable>(10));
242        try (PoolCleaner cleaner = cleaner(p)) {
243            final CountDownLatch done = new CountDownLatch(1);
244            final Runnable task = new CheckedRunnable() {
245                public void realRun() { done.countDown(); }};
246            p.execute(task);
247            assertTrue(done.await(LONG_DELAY_MS, MILLISECONDS));
248        }
249    }
250
251    /**
252     * getActiveCount increases but doesn't overestimate, when a
253     * thread becomes active
254     */
255    public void testGetActiveCount() throws InterruptedException {
256        final CountDownLatch done = new CountDownLatch(1);
257        final ThreadPoolExecutor p =
258            new CustomTPE(2, 2,
259                          LONG_DELAY_MS, MILLISECONDS,
260                          new ArrayBlockingQueue<Runnable>(10));
261        try (PoolCleaner cleaner = cleaner(p, done)) {
262            final CountDownLatch threadStarted = new CountDownLatch(1);
263            assertEquals(0, p.getActiveCount());
264            p.execute(new CheckedRunnable() {
265                public void realRun() throws InterruptedException {
266                    threadStarted.countDown();
267                    assertEquals(1, p.getActiveCount());
268                    await(done);
269                }});
270            await(threadStarted);
271            assertEquals(1, p.getActiveCount());
272        }
273    }
274
275    /**
276     * prestartCoreThread starts a thread if under corePoolSize, else doesn't
277     */
278    public void testPrestartCoreThread() {
279        final ThreadPoolExecutor p =
280            new CustomTPE(2, 6,
281                          LONG_DELAY_MS, MILLISECONDS,
282                          new ArrayBlockingQueue<Runnable>(10));
283        try (PoolCleaner cleaner = cleaner(p)) {
284            assertEquals(0, p.getPoolSize());
285            assertTrue(p.prestartCoreThread());
286            assertEquals(1, p.getPoolSize());
287            assertTrue(p.prestartCoreThread());
288            assertEquals(2, p.getPoolSize());
289            assertFalse(p.prestartCoreThread());
290            assertEquals(2, p.getPoolSize());
291            p.setCorePoolSize(4);
292            assertTrue(p.prestartCoreThread());
293            assertEquals(3, p.getPoolSize());
294            assertTrue(p.prestartCoreThread());
295            assertEquals(4, p.getPoolSize());
296            assertFalse(p.prestartCoreThread());
297            assertEquals(4, p.getPoolSize());
298        }
299    }
300
301    /**
302     * prestartAllCoreThreads starts all corePoolSize threads
303     */
304    public void testPrestartAllCoreThreads() {
305        final ThreadPoolExecutor p =
306            new CustomTPE(2, 6,
307                          LONG_DELAY_MS, MILLISECONDS,
308                          new ArrayBlockingQueue<Runnable>(10));
309        try (PoolCleaner cleaner = cleaner(p)) {
310            assertEquals(0, p.getPoolSize());
311            p.prestartAllCoreThreads();
312            assertEquals(2, p.getPoolSize());
313            p.prestartAllCoreThreads();
314            assertEquals(2, p.getPoolSize());
315            p.setCorePoolSize(4);
316            p.prestartAllCoreThreads();
317            assertEquals(4, p.getPoolSize());
318            p.prestartAllCoreThreads();
319            assertEquals(4, p.getPoolSize());
320        }
321    }
322
323    /**
324     * getCompletedTaskCount increases, but doesn't overestimate,
325     * when tasks complete
326     */
327    public void testGetCompletedTaskCount() throws InterruptedException {
328        final ThreadPoolExecutor p =
329            new CustomTPE(2, 2,
330                          LONG_DELAY_MS, MILLISECONDS,
331                          new ArrayBlockingQueue<Runnable>(10));
332        try (PoolCleaner cleaner = cleaner(p)) {
333            final CountDownLatch threadStarted = new CountDownLatch(1);
334            final CountDownLatch threadProceed = new CountDownLatch(1);
335            final CountDownLatch threadDone = new CountDownLatch(1);
336            assertEquals(0, p.getCompletedTaskCount());
337            p.execute(new CheckedRunnable() {
338                public void realRun() throws InterruptedException {
339                    threadStarted.countDown();
340                    assertEquals(0, p.getCompletedTaskCount());
341                    threadProceed.await();
342                    threadDone.countDown();
343                }});
344            await(threadStarted);
345            assertEquals(0, p.getCompletedTaskCount());
346            threadProceed.countDown();
347            threadDone.await();
348            long startTime = System.nanoTime();
349            while (p.getCompletedTaskCount() != 1) {
350                if (millisElapsedSince(startTime) > LONG_DELAY_MS)
351                    fail("timed out");
352                Thread.yield();
353            }
354        }
355    }
356
357    /**
358     * getCorePoolSize returns size given in constructor if not otherwise set
359     */
360    public void testGetCorePoolSize() {
361        final ThreadPoolExecutor p =
362            new CustomTPE(1, 1,
363                          LONG_DELAY_MS, MILLISECONDS,
364                          new ArrayBlockingQueue<Runnable>(10));
365        try (PoolCleaner cleaner = cleaner(p)) {
366            assertEquals(1, p.getCorePoolSize());
367        }
368    }
369
370    /**
371     * getKeepAliveTime returns value given in constructor if not otherwise set
372     */
373    public void testGetKeepAliveTime() {
374        final ThreadPoolExecutor p =
375            new CustomTPE(2, 2,
376                          1000, MILLISECONDS,
377                          new ArrayBlockingQueue<Runnable>(10));
378        try (PoolCleaner cleaner = cleaner(p)) {
379            assertEquals(1, p.getKeepAliveTime(SECONDS));
380        }
381    }
382
383    /**
384     * getThreadFactory returns factory in constructor if not set
385     */
386    public void testGetThreadFactory() {
387        final ThreadFactory threadFactory = new SimpleThreadFactory();
388        final ThreadPoolExecutor p =
389            new CustomTPE(1, 2,
390                          LONG_DELAY_MS, MILLISECONDS,
391                          new ArrayBlockingQueue<Runnable>(10),
392                          threadFactory,
393                          new NoOpREHandler());
394        try (PoolCleaner cleaner = cleaner(p)) {
395            assertSame(threadFactory, p.getThreadFactory());
396        }
397    }
398
399    /**
400     * setThreadFactory sets the thread factory returned by getThreadFactory
401     */
402    public void testSetThreadFactory() {
403        final ThreadPoolExecutor p =
404            new CustomTPE(1, 2,
405                          LONG_DELAY_MS, MILLISECONDS,
406                          new ArrayBlockingQueue<Runnable>(10));
407        try (PoolCleaner cleaner = cleaner(p)) {
408            ThreadFactory threadFactory = new SimpleThreadFactory();
409            p.setThreadFactory(threadFactory);
410            assertSame(threadFactory, p.getThreadFactory());
411        }
412    }
413
414    /**
415     * setThreadFactory(null) throws NPE
416     */
417    public void testSetThreadFactoryNull() {
418        final ThreadPoolExecutor p =
419            new CustomTPE(1, 2,
420                          LONG_DELAY_MS, MILLISECONDS,
421                          new ArrayBlockingQueue<Runnable>(10));
422        try (PoolCleaner cleaner = cleaner(p)) {
423            try {
424                p.setThreadFactory(null);
425                shouldThrow();
426            } catch (NullPointerException success) {}
427        }
428    }
429
430    /**
431     * getRejectedExecutionHandler returns handler in constructor if not set
432     */
433    public void testGetRejectedExecutionHandler() {
434        final RejectedExecutionHandler handler = new NoOpREHandler();
435        final ThreadPoolExecutor p =
436            new CustomTPE(1, 2,
437                          LONG_DELAY_MS, MILLISECONDS,
438                          new ArrayBlockingQueue<Runnable>(10),
439                          handler);
440        try (PoolCleaner cleaner = cleaner(p)) {
441            assertSame(handler, p.getRejectedExecutionHandler());
442        }
443    }
444
445    /**
446     * setRejectedExecutionHandler sets the handler returned by
447     * getRejectedExecutionHandler
448     */
449    public void testSetRejectedExecutionHandler() {
450        final ThreadPoolExecutor p =
451            new CustomTPE(1, 2,
452                          LONG_DELAY_MS, MILLISECONDS,
453                          new ArrayBlockingQueue<Runnable>(10));
454        try (PoolCleaner cleaner = cleaner(p)) {
455            RejectedExecutionHandler handler = new NoOpREHandler();
456            p.setRejectedExecutionHandler(handler);
457            assertSame(handler, p.getRejectedExecutionHandler());
458        }
459    }
460
461    /**
462     * setRejectedExecutionHandler(null) throws NPE
463     */
464    public void testSetRejectedExecutionHandlerNull() {
465        final ThreadPoolExecutor p =
466            new CustomTPE(1, 2,
467                          LONG_DELAY_MS, MILLISECONDS,
468                          new ArrayBlockingQueue<Runnable>(10));
469        try (PoolCleaner cleaner = cleaner(p)) {
470            try {
471                p.setRejectedExecutionHandler(null);
472                shouldThrow();
473            } catch (NullPointerException success) {}
474        }
475    }
476
477    /**
478     * getLargestPoolSize increases, but doesn't overestimate, when
479     * multiple threads active
480     */
481    public void testGetLargestPoolSize() throws InterruptedException {
482        final int THREADS = 3;
483        final CountDownLatch done = new CountDownLatch(1);
484        final ThreadPoolExecutor p =
485            new CustomTPE(THREADS, THREADS,
486                          LONG_DELAY_MS, MILLISECONDS,
487                          new ArrayBlockingQueue<Runnable>(10));
488        try (PoolCleaner cleaner = cleaner(p, done)) {
489            assertEquals(0, p.getLargestPoolSize());
490            final CountDownLatch threadsStarted = new CountDownLatch(THREADS);
491            for (int i = 0; i < THREADS; i++)
492                p.execute(new CheckedRunnable() {
493                    public void realRun() throws InterruptedException {
494                        threadsStarted.countDown();
495                        await(done);
496                        assertEquals(THREADS, p.getLargestPoolSize());
497                    }});
498            await(threadsStarted);
499            assertEquals(THREADS, p.getLargestPoolSize());
500        }
501        assertEquals(THREADS, p.getLargestPoolSize());
502    }
503
504    /**
505     * getMaximumPoolSize returns value given in constructor if not
506     * otherwise set
507     */
508    public void testGetMaximumPoolSize() {
509        final ThreadPoolExecutor p =
510            new CustomTPE(2, 3,
511                          LONG_DELAY_MS, MILLISECONDS,
512                          new ArrayBlockingQueue<Runnable>(10));
513        try (PoolCleaner cleaner = cleaner(p)) {
514            assertEquals(3, p.getMaximumPoolSize());
515            p.setMaximumPoolSize(5);
516            assertEquals(5, p.getMaximumPoolSize());
517            p.setMaximumPoolSize(4);
518            assertEquals(4, p.getMaximumPoolSize());
519        }
520    }
521
522    /**
523     * getPoolSize increases, but doesn't overestimate, when threads
524     * become active
525     */
526    public void testGetPoolSize() throws InterruptedException {
527        final CountDownLatch done = new CountDownLatch(1);
528        final ThreadPoolExecutor p =
529            new CustomTPE(1, 1,
530                          LONG_DELAY_MS, MILLISECONDS,
531                          new ArrayBlockingQueue<Runnable>(10));
532        try (PoolCleaner cleaner = cleaner(p, done)) {
533            assertEquals(0, p.getPoolSize());
534            final CountDownLatch threadStarted = new CountDownLatch(1);
535            p.execute(new CheckedRunnable() {
536                public void realRun() throws InterruptedException {
537                    threadStarted.countDown();
538                    assertEquals(1, p.getPoolSize());
539                    await(done);
540                }});
541            await(threadStarted);
542            assertEquals(1, p.getPoolSize());
543        }
544    }
545
546    /**
547     * getTaskCount increases, but doesn't overestimate, when tasks submitted
548     */
549    public void testGetTaskCount() throws InterruptedException {
550        final int TASKS = 3;
551        final CountDownLatch done = new CountDownLatch(1);
552        final ThreadPoolExecutor p =
553            new CustomTPE(1, 1,
554                          LONG_DELAY_MS, MILLISECONDS,
555                          new ArrayBlockingQueue<Runnable>(10));
556        try (PoolCleaner cleaner = cleaner(p, done)) {
557            final CountDownLatch threadStarted = new CountDownLatch(1);
558            assertEquals(0, p.getTaskCount());
559            assertEquals(0, p.getCompletedTaskCount());
560            p.execute(new CheckedRunnable() {
561                public void realRun() throws InterruptedException {
562                    threadStarted.countDown();
563                    await(done);
564                }});
565            await(threadStarted);
566            assertEquals(1, p.getTaskCount());
567            assertEquals(0, p.getCompletedTaskCount());
568            for (int i = 0; i < TASKS; i++) {
569                assertEquals(1 + i, p.getTaskCount());
570                p.execute(new CheckedRunnable() {
571                    public void realRun() throws InterruptedException {
572                        threadStarted.countDown();
573                        assertEquals(1 + TASKS, p.getTaskCount());
574                        await(done);
575                    }});
576            }
577            assertEquals(1 + TASKS, p.getTaskCount());
578            assertEquals(0, p.getCompletedTaskCount());
579        }
580        assertEquals(1 + TASKS, p.getTaskCount());
581        assertEquals(1 + TASKS, p.getCompletedTaskCount());
582    }
583
584    /**
585     * isShutdown is false before shutdown, true after
586     */
587    public void testIsShutdown() {
588        final ThreadPoolExecutor p =
589            new CustomTPE(1, 1,
590                          LONG_DELAY_MS, MILLISECONDS,
591                          new ArrayBlockingQueue<Runnable>(10));
592        try (PoolCleaner cleaner = cleaner(p)) {
593            assertFalse(p.isShutdown());
594            try { p.shutdown(); } catch (SecurityException ok) { return; }
595            assertTrue(p.isShutdown());
596        }
597    }
598
599    /**
600     * isTerminated is false before termination, true after
601     */
602    public void testIsTerminated() throws InterruptedException {
603        final ThreadPoolExecutor p =
604            new CustomTPE(1, 1,
605                          LONG_DELAY_MS, MILLISECONDS,
606                          new ArrayBlockingQueue<Runnable>(10));
607        try (PoolCleaner cleaner = cleaner(p)) {
608            final CountDownLatch threadStarted = new CountDownLatch(1);
609            final CountDownLatch done = new CountDownLatch(1);
610            assertFalse(p.isTerminating());
611            p.execute(new CheckedRunnable() {
612                public void realRun() throws InterruptedException {
613                    assertFalse(p.isTerminating());
614                    threadStarted.countDown();
615                    await(done);
616                }});
617            await(threadStarted);
618            assertFalse(p.isTerminating());
619            done.countDown();
620            try { p.shutdown(); } catch (SecurityException ok) { return; }
621            assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
622            assertTrue(p.isTerminated());
623            assertFalse(p.isTerminating());
624        }
625    }
626
627    /**
628     * isTerminating is not true when running or when terminated
629     */
630    public void testIsTerminating() throws InterruptedException {
631        final ThreadPoolExecutor p =
632            new CustomTPE(1, 1,
633                          LONG_DELAY_MS, MILLISECONDS,
634                          new ArrayBlockingQueue<Runnable>(10));
635        try (PoolCleaner cleaner = cleaner(p)) {
636            final CountDownLatch threadStarted = new CountDownLatch(1);
637            final CountDownLatch done = new CountDownLatch(1);
638            assertFalse(p.isTerminating());
639            p.execute(new CheckedRunnable() {
640                public void realRun() throws InterruptedException {
641                    assertFalse(p.isTerminating());
642                    threadStarted.countDown();
643                    await(done);
644                }});
645            await(threadStarted);
646            assertFalse(p.isTerminating());
647            done.countDown();
648            try { p.shutdown(); } catch (SecurityException ok) { return; }
649            assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
650            assertTrue(p.isTerminated());
651            assertFalse(p.isTerminating());
652        }
653    }
654
655    /**
656     * getQueue returns the work queue, which contains queued tasks
657     */
658    public void testGetQueue() throws InterruptedException {
659        final CountDownLatch done = new CountDownLatch(1);
660        final BlockingQueue<Runnable> q = new ArrayBlockingQueue<Runnable>(10);
661        final ThreadPoolExecutor p =
662            new CustomTPE(1, 1,
663                          LONG_DELAY_MS, MILLISECONDS,
664                          q);
665        try (PoolCleaner cleaner = cleaner(p, done)) {
666            final CountDownLatch threadStarted = new CountDownLatch(1);
667            FutureTask[] tasks = new FutureTask[5];
668            for (int i = 0; i < tasks.length; i++) {
669                Callable task = new CheckedCallable<Boolean>() {
670                    public Boolean realCall() throws InterruptedException {
671                        threadStarted.countDown();
672                        assertSame(q, p.getQueue());
673                        await(done);
674                        return Boolean.TRUE;
675                    }};
676                tasks[i] = new FutureTask(task);
677                p.execute(tasks[i]);
678            }
679            await(threadStarted);
680            assertSame(q, p.getQueue());
681            assertFalse(q.contains(tasks[0]));
682            assertTrue(q.contains(tasks[tasks.length - 1]));
683            assertEquals(tasks.length - 1, q.size());
684        }
685    }
686
687    /**
688     * remove(task) removes queued task, and fails to remove active task
689     */
690    public void testRemove() throws InterruptedException {
691        final CountDownLatch done = new CountDownLatch(1);
692        BlockingQueue<Runnable> q = new ArrayBlockingQueue<Runnable>(10);
693        final ThreadPoolExecutor p =
694            new CustomTPE(1, 1,
695                          LONG_DELAY_MS, MILLISECONDS,
696                          q);
697        try (PoolCleaner cleaner = cleaner(p, done)) {
698            Runnable[] tasks = new Runnable[6];
699            final CountDownLatch threadStarted = new CountDownLatch(1);
700            for (int i = 0; i < tasks.length; i++) {
701                tasks[i] = new CheckedRunnable() {
702                    public void realRun() throws InterruptedException {
703                        threadStarted.countDown();
704                        await(done);
705                    }};
706                p.execute(tasks[i]);
707            }
708            await(threadStarted);
709            assertFalse(p.remove(tasks[0]));
710            assertTrue(q.contains(tasks[4]));
711            assertTrue(q.contains(tasks[3]));
712            assertTrue(p.remove(tasks[4]));
713            assertFalse(p.remove(tasks[4]));
714            assertFalse(q.contains(tasks[4]));
715            assertTrue(q.contains(tasks[3]));
716            assertTrue(p.remove(tasks[3]));
717            assertFalse(q.contains(tasks[3]));
718        }
719    }
720
721    /**
722     * purge removes cancelled tasks from the queue
723     */
724    public void testPurge() throws InterruptedException {
725        final CountDownLatch threadStarted = new CountDownLatch(1);
726        final CountDownLatch done = new CountDownLatch(1);
727        final BlockingQueue<Runnable> q = new ArrayBlockingQueue<Runnable>(10);
728        final ThreadPoolExecutor p =
729            new CustomTPE(1, 1,
730                          LONG_DELAY_MS, MILLISECONDS,
731                          q);
732        try (PoolCleaner cleaner = cleaner(p, done)) {
733            FutureTask[] tasks = new FutureTask[5];
734            for (int i = 0; i < tasks.length; i++) {
735                Callable task = new CheckedCallable<Boolean>() {
736                    public Boolean realCall() throws InterruptedException {
737                        threadStarted.countDown();
738                        await(done);
739                        return Boolean.TRUE;
740                    }};
741                tasks[i] = new FutureTask(task);
742                p.execute(tasks[i]);
743            }
744            await(threadStarted);
745            assertEquals(tasks.length, p.getTaskCount());
746            assertEquals(tasks.length - 1, q.size());
747            assertEquals(1L, p.getActiveCount());
748            assertEquals(0L, p.getCompletedTaskCount());
749            tasks[4].cancel(true);
750            tasks[3].cancel(false);
751            p.purge();
752            assertEquals(tasks.length - 3, q.size());
753            assertEquals(tasks.length - 2, p.getTaskCount());
754            p.purge();         // Nothing to do
755            assertEquals(tasks.length - 3, q.size());
756            assertEquals(tasks.length - 2, p.getTaskCount());
757        }
758    }
759
760    /**
761     * shutdownNow returns a list containing tasks that were not run,
762     * and those tasks are drained from the queue
763     */
764    public void testShutdownNow() throws InterruptedException {
765        final int poolSize = 2;
766        final int count = 5;
767        final AtomicInteger ran = new AtomicInteger(0);
768        final ThreadPoolExecutor p =
769            new CustomTPE(poolSize, poolSize,
770                          LONG_DELAY_MS, MILLISECONDS,
771                          new ArrayBlockingQueue<Runnable>(10));
772        final CountDownLatch threadsStarted = new CountDownLatch(poolSize);
773        Runnable waiter = new CheckedRunnable() { public void realRun() {
774            threadsStarted.countDown();
775            try {
776                MILLISECONDS.sleep(2 * LONG_DELAY_MS);
777            } catch (InterruptedException success) {}
778            ran.getAndIncrement();
779        }};
780        for (int i = 0; i < count; i++)
781            p.execute(waiter);
782        await(threadsStarted);
783        assertEquals(poolSize, p.getActiveCount());
784        assertEquals(0, p.getCompletedTaskCount());
785        final List<Runnable> queuedTasks;
786        try {
787            queuedTasks = p.shutdownNow();
788        } catch (SecurityException ok) {
789            return; // Allowed in case test doesn't have privs
790        }
791        assertTrue(p.isShutdown());
792        assertTrue(p.getQueue().isEmpty());
793        assertEquals(count - poolSize, queuedTasks.size());
794        assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
795        assertTrue(p.isTerminated());
796        assertEquals(poolSize, ran.get());
797        assertEquals(poolSize, p.getCompletedTaskCount());
798    }
799
800    // Exception Tests
801
802    /**
803     * Constructor throws if corePoolSize argument is less than zero
804     */
805    public void testConstructor1() {
806        try {
807            new CustomTPE(-1, 1, 1L, SECONDS,
808                          new ArrayBlockingQueue<Runnable>(10));
809            shouldThrow();
810        } catch (IllegalArgumentException success) {}
811    }
812
813    /**
814     * Constructor throws if maximumPoolSize is less than zero
815     */
816    public void testConstructor2() {
817        try {
818            new CustomTPE(1, -1, 1L, SECONDS,
819                          new ArrayBlockingQueue<Runnable>(10));
820            shouldThrow();
821        } catch (IllegalArgumentException success) {}
822    }
823
824    /**
825     * Constructor throws if maximumPoolSize is equal to zero
826     */
827    public void testConstructor3() {
828        try {
829            new CustomTPE(1, 0, 1L, SECONDS,
830                          new ArrayBlockingQueue<Runnable>(10));
831            shouldThrow();
832        } catch (IllegalArgumentException success) {}
833    }
834
835    /**
836     * Constructor throws if keepAliveTime is less than zero
837     */
838    public void testConstructor4() {
839        try {
840            new CustomTPE(1, 2, -1L, SECONDS,
841                          new ArrayBlockingQueue<Runnable>(10));
842            shouldThrow();
843        } catch (IllegalArgumentException success) {}
844    }
845
846    /**
847     * Constructor throws if corePoolSize is greater than the maximumPoolSize
848     */
849    public void testConstructor5() {
850        try {
851            new CustomTPE(2, 1, 1L, SECONDS,
852                          new ArrayBlockingQueue<Runnable>(10));
853            shouldThrow();
854        } catch (IllegalArgumentException success) {}
855    }
856
857    /**
858     * Constructor throws if workQueue is set to null
859     */
860    public void testConstructorNullPointerException() {
861        try {
862            new CustomTPE(1, 2, 1L, SECONDS, null);
863            shouldThrow();
864        } catch (NullPointerException success) {}
865    }
866
867    /**
868     * Constructor throws if corePoolSize argument is less than zero
869     */
870    public void testConstructor6() {
871        try {
872            new CustomTPE(-1, 1, 1L, SECONDS,
873                          new ArrayBlockingQueue<Runnable>(10),
874                          new SimpleThreadFactory());
875            shouldThrow();
876        } catch (IllegalArgumentException success) {}
877    }
878
879    /**
880     * Constructor throws if maximumPoolSize is less than zero
881     */
882    public void testConstructor7() {
883        try {
884            new CustomTPE(1,-1, 1L, SECONDS,
885                          new ArrayBlockingQueue<Runnable>(10),
886                          new SimpleThreadFactory());
887            shouldThrow();
888        } catch (IllegalArgumentException success) {}
889    }
890
891    /**
892     * Constructor throws if maximumPoolSize is equal to zero
893     */
894    public void testConstructor8() {
895        try {
896            new CustomTPE(1, 0, 1L, SECONDS,
897                          new ArrayBlockingQueue<Runnable>(10),
898                          new SimpleThreadFactory());
899            shouldThrow();
900        } catch (IllegalArgumentException success) {}
901    }
902
903    /**
904     * Constructor throws if keepAliveTime is less than zero
905     */
906    public void testConstructor9() {
907        try {
908            new CustomTPE(1, 2, -1L, SECONDS,
909                          new ArrayBlockingQueue<Runnable>(10),
910                          new SimpleThreadFactory());
911            shouldThrow();
912        } catch (IllegalArgumentException success) {}
913    }
914
915    /**
916     * Constructor throws if corePoolSize is greater than the maximumPoolSize
917     */
918    public void testConstructor10() {
919        try {
920            new CustomTPE(2, 1, 1L, SECONDS,
921                          new ArrayBlockingQueue<Runnable>(10),
922                          new SimpleThreadFactory());
923            shouldThrow();
924        } catch (IllegalArgumentException success) {}
925    }
926
927    /**
928     * Constructor throws if workQueue is set to null
929     */
930    public void testConstructorNullPointerException2() {
931        try {
932            new CustomTPE(1, 2, 1L, SECONDS, null, new SimpleThreadFactory());
933            shouldThrow();
934        } catch (NullPointerException success) {}
935    }
936
937    /**
938     * Constructor throws if threadFactory is set to null
939     */
940    public void testConstructorNullPointerException3() {
941        try {
942            new CustomTPE(1, 2, 1L, SECONDS,
943                          new ArrayBlockingQueue<Runnable>(10),
944                          (ThreadFactory) null);
945            shouldThrow();
946        } catch (NullPointerException success) {}
947    }
948
949    /**
950     * Constructor throws if corePoolSize argument is less than zero
951     */
952    public void testConstructor11() {
953        try {
954            new CustomTPE(-1, 1, 1L, SECONDS,
955                          new ArrayBlockingQueue<Runnable>(10),
956                          new NoOpREHandler());
957            shouldThrow();
958        } catch (IllegalArgumentException success) {}
959    }
960
961    /**
962     * Constructor throws if maximumPoolSize is less than zero
963     */
964    public void testConstructor12() {
965        try {
966            new CustomTPE(1, -1, 1L, SECONDS,
967                          new ArrayBlockingQueue<Runnable>(10),
968                          new NoOpREHandler());
969            shouldThrow();
970        } catch (IllegalArgumentException success) {}
971    }
972
973    /**
974     * Constructor throws if maximumPoolSize is equal to zero
975     */
976    public void testConstructor13() {
977        try {
978            new CustomTPE(1, 0, 1L, SECONDS,
979                          new ArrayBlockingQueue<Runnable>(10),
980                          new NoOpREHandler());
981            shouldThrow();
982        } catch (IllegalArgumentException success) {}
983    }
984
985    /**
986     * Constructor throws if keepAliveTime is less than zero
987     */
988    public void testConstructor14() {
989        try {
990            new CustomTPE(1, 2, -1L, SECONDS,
991                          new ArrayBlockingQueue<Runnable>(10),
992                          new NoOpREHandler());
993            shouldThrow();
994        } catch (IllegalArgumentException success) {}
995    }
996
997    /**
998     * Constructor throws if corePoolSize is greater than the maximumPoolSize
999     */
1000    public void testConstructor15() {
1001        try {
1002            new CustomTPE(2, 1, 1L, SECONDS,
1003                          new ArrayBlockingQueue<Runnable>(10),
1004                          new NoOpREHandler());
1005            shouldThrow();
1006        } catch (IllegalArgumentException success) {}
1007    }
1008
1009    /**
1010     * Constructor throws if workQueue is set to null
1011     */
1012    public void testConstructorNullPointerException4() {
1013        try {
1014            new CustomTPE(1, 2, 1L, SECONDS,
1015                          null,
1016                          new NoOpREHandler());
1017            shouldThrow();
1018        } catch (NullPointerException success) {}
1019    }
1020
1021    /**
1022     * Constructor throws if handler is set to null
1023     */
1024    public void testConstructorNullPointerException5() {
1025        try {
1026            new CustomTPE(1, 2, 1L, SECONDS,
1027                          new ArrayBlockingQueue<Runnable>(10),
1028                          (RejectedExecutionHandler) null);
1029            shouldThrow();
1030        } catch (NullPointerException success) {}
1031    }
1032
1033    /**
1034     * Constructor throws if corePoolSize argument is less than zero
1035     */
1036    public void testConstructor16() {
1037        try {
1038            new CustomTPE(-1, 1, 1L, SECONDS,
1039                          new ArrayBlockingQueue<Runnable>(10),
1040                          new SimpleThreadFactory(),
1041                          new NoOpREHandler());
1042            shouldThrow();
1043        } catch (IllegalArgumentException success) {}
1044    }
1045
1046    /**
1047     * Constructor throws if maximumPoolSize is less than zero
1048     */
1049    public void testConstructor17() {
1050        try {
1051            new CustomTPE(1, -1, 1L, SECONDS,
1052                          new ArrayBlockingQueue<Runnable>(10),
1053                          new SimpleThreadFactory(),
1054                          new NoOpREHandler());
1055            shouldThrow();
1056        } catch (IllegalArgumentException success) {}
1057    }
1058
1059    /**
1060     * Constructor throws if maximumPoolSize is equal to zero
1061     */
1062    public void testConstructor18() {
1063        try {
1064            new CustomTPE(1, 0, 1L, SECONDS,
1065                          new ArrayBlockingQueue<Runnable>(10),
1066                          new SimpleThreadFactory(),
1067                          new NoOpREHandler());
1068            shouldThrow();
1069        } catch (IllegalArgumentException success) {}
1070    }
1071
1072    /**
1073     * Constructor throws if keepAliveTime is less than zero
1074     */
1075    public void testConstructor19() {
1076        try {
1077            new CustomTPE(1, 2, -1L, SECONDS,
1078                          new ArrayBlockingQueue<Runnable>(10),
1079                          new SimpleThreadFactory(),
1080                          new NoOpREHandler());
1081            shouldThrow();
1082        } catch (IllegalArgumentException success) {}
1083    }
1084
1085    /**
1086     * Constructor throws if corePoolSize is greater than the maximumPoolSize
1087     */
1088    public void testConstructor20() {
1089        try {
1090            new CustomTPE(2, 1, 1L, SECONDS,
1091                          new ArrayBlockingQueue<Runnable>(10),
1092                          new SimpleThreadFactory(),
1093                          new NoOpREHandler());
1094            shouldThrow();
1095        } catch (IllegalArgumentException success) {}
1096    }
1097
1098    /**
1099     * Constructor throws if workQueue is null
1100     */
1101    public void testConstructorNullPointerException6() {
1102        try {
1103            new CustomTPE(1, 2, 1L, SECONDS,
1104                          null,
1105                          new SimpleThreadFactory(),
1106                          new NoOpREHandler());
1107            shouldThrow();
1108        } catch (NullPointerException success) {}
1109    }
1110
1111    /**
1112     * Constructor throws if handler is null
1113     */
1114    public void testConstructorNullPointerException7() {
1115        try {
1116            new CustomTPE(1, 2, 1L, SECONDS,
1117                          new ArrayBlockingQueue<Runnable>(10),
1118                          new SimpleThreadFactory(),
1119                          (RejectedExecutionHandler) null);
1120            shouldThrow();
1121        } catch (NullPointerException success) {}
1122    }
1123
1124    /**
1125     * Constructor throws if ThreadFactory is null
1126     */
1127    public void testConstructorNullPointerException8() {
1128        try {
1129            new CustomTPE(1, 2, 1L, SECONDS,
1130                          new ArrayBlockingQueue<Runnable>(10),
1131                          (ThreadFactory) null,
1132                          new NoOpREHandler());
1133            shouldThrow();
1134        } catch (NullPointerException success) {}
1135    }
1136
1137    /**
1138     * execute throws RejectedExecutionException if saturated.
1139     */
1140    public void testSaturatedExecute() {
1141        final CountDownLatch done = new CountDownLatch(1);
1142        final ThreadPoolExecutor p =
1143            new CustomTPE(1, 1,
1144                          LONG_DELAY_MS, MILLISECONDS,
1145                          new ArrayBlockingQueue<Runnable>(1));
1146        try (PoolCleaner cleaner = cleaner(p, done)) {
1147            Runnable task = new CheckedRunnable() {
1148                public void realRun() throws InterruptedException {
1149                    await(done);
1150                }};
1151            for (int i = 0; i < 2; ++i)
1152                p.execute(task);
1153            for (int i = 0; i < 2; ++i) {
1154                try {
1155                    p.execute(task);
1156                    shouldThrow();
1157                } catch (RejectedExecutionException success) {}
1158                assertTrue(p.getTaskCount() <= 2);
1159            }
1160        }
1161    }
1162
1163    /**
1164     * executor using CallerRunsPolicy runs task if saturated.
1165     */
1166    public void testSaturatedExecute2() {
1167        final CountDownLatch done = new CountDownLatch(1);
1168        final ThreadPoolExecutor p =
1169            new CustomTPE(1, 1,
1170                          LONG_DELAY_MS, MILLISECONDS,
1171                          new ArrayBlockingQueue<Runnable>(1),
1172                          new CustomTPE.CallerRunsPolicy());
1173        try (PoolCleaner cleaner = cleaner(p, done)) {
1174            Runnable blocker = new CheckedRunnable() {
1175                public void realRun() throws InterruptedException {
1176                    await(done);
1177                }};
1178            p.execute(blocker);
1179            TrackedNoOpRunnable[] tasks = new TrackedNoOpRunnable[5];
1180            for (int i = 0; i < tasks.length; i++)
1181                tasks[i] = new TrackedNoOpRunnable();
1182            for (int i = 0; i < tasks.length; i++)
1183                p.execute(tasks[i]);
1184            for (int i = 1; i < tasks.length; i++)
1185                assertTrue(tasks[i].done);
1186            assertFalse(tasks[0].done); // waiting in queue
1187        }
1188    }
1189
1190    /**
1191     * executor using DiscardPolicy drops task if saturated.
1192     */
1193    public void testSaturatedExecute3() {
1194        final TrackedNoOpRunnable[] tasks = new TrackedNoOpRunnable[5];
1195        for (int i = 0; i < tasks.length; ++i)
1196            tasks[i] = new TrackedNoOpRunnable();
1197        final CountDownLatch done = new CountDownLatch(1);
1198        final ThreadPoolExecutor p =
1199            new CustomTPE(1, 1,
1200                          LONG_DELAY_MS, MILLISECONDS,
1201                          new ArrayBlockingQueue<Runnable>(1),
1202                          new CustomTPE.DiscardPolicy());
1203        try (PoolCleaner cleaner = cleaner(p, done)) {
1204            p.execute(awaiter(done));
1205
1206            for (TrackedNoOpRunnable task : tasks)
1207                p.execute(task);
1208            for (int i = 1; i < tasks.length; i++)
1209                assertFalse(tasks[i].done);
1210        }
1211        for (int i = 1; i < tasks.length; i++)
1212            assertFalse(tasks[i].done);
1213        assertTrue(tasks[0].done); // was waiting in queue
1214    }
1215
1216    /**
1217     * executor using DiscardOldestPolicy drops oldest task if saturated.
1218     */
1219    public void testSaturatedExecute4() {
1220        final CountDownLatch done = new CountDownLatch(1);
1221        LatchAwaiter r1 = awaiter(done);
1222        LatchAwaiter r2 = awaiter(done);
1223        LatchAwaiter r3 = awaiter(done);
1224        final ThreadPoolExecutor p =
1225            new CustomTPE(1, 1,
1226                          LONG_DELAY_MS, MILLISECONDS,
1227                          new ArrayBlockingQueue<Runnable>(1),
1228                          new CustomTPE.DiscardOldestPolicy());
1229        try (PoolCleaner cleaner = cleaner(p, done)) {
1230            assertEquals(LatchAwaiter.NEW, r1.state);
1231            assertEquals(LatchAwaiter.NEW, r2.state);
1232            assertEquals(LatchAwaiter.NEW, r3.state);
1233            p.execute(r1);
1234            p.execute(r2);
1235            assertTrue(p.getQueue().contains(r2));
1236            p.execute(r3);
1237            assertFalse(p.getQueue().contains(r2));
1238            assertTrue(p.getQueue().contains(r3));
1239        }
1240        assertEquals(LatchAwaiter.DONE, r1.state);
1241        assertEquals(LatchAwaiter.NEW, r2.state);
1242        assertEquals(LatchAwaiter.DONE, r3.state);
1243    }
1244
1245    /**
1246     * execute throws RejectedExecutionException if shutdown
1247     */
1248    public void testRejectedExecutionExceptionOnShutdown() {
1249        final ThreadPoolExecutor p =
1250            new CustomTPE(1, 1,
1251                          LONG_DELAY_MS, MILLISECONDS,
1252                          new ArrayBlockingQueue<Runnable>(1));
1253        try { p.shutdown(); } catch (SecurityException ok) { return; }
1254        try (PoolCleaner cleaner = cleaner(p)) {
1255            try {
1256                p.execute(new NoOpRunnable());
1257                shouldThrow();
1258            } catch (RejectedExecutionException success) {}
1259        }
1260    }
1261
1262    /**
1263     * execute using CallerRunsPolicy drops task on shutdown
1264     */
1265    public void testCallerRunsOnShutdown() {
1266        final ThreadPoolExecutor p =
1267            new CustomTPE(1, 1,
1268                          LONG_DELAY_MS, MILLISECONDS,
1269                          new ArrayBlockingQueue<Runnable>(1),
1270                          new CustomTPE.CallerRunsPolicy());
1271        try { p.shutdown(); } catch (SecurityException ok) { return; }
1272        try (PoolCleaner cleaner = cleaner(p)) {
1273            TrackedNoOpRunnable r = new TrackedNoOpRunnable();
1274            p.execute(r);
1275            assertFalse(r.done);
1276        }
1277    }
1278
1279    /**
1280     * execute using DiscardPolicy drops task on shutdown
1281     */
1282    public void testDiscardOnShutdown() {
1283        final ThreadPoolExecutor p =
1284            new CustomTPE(1, 1,
1285                          LONG_DELAY_MS, MILLISECONDS,
1286                          new ArrayBlockingQueue<Runnable>(1),
1287                          new CustomTPE.DiscardPolicy());
1288        try { p.shutdown(); } catch (SecurityException ok) { return; }
1289        try (PoolCleaner cleaner = cleaner(p)) {
1290            TrackedNoOpRunnable r = new TrackedNoOpRunnable();
1291            p.execute(r);
1292            assertFalse(r.done);
1293        }
1294    }
1295
1296    /**
1297     * execute using DiscardOldestPolicy drops task on shutdown
1298     */
1299    public void testDiscardOldestOnShutdown() {
1300        final ThreadPoolExecutor p =
1301            new CustomTPE(1, 1,
1302                          LONG_DELAY_MS, MILLISECONDS,
1303                          new ArrayBlockingQueue<Runnable>(1),
1304                          new CustomTPE.DiscardOldestPolicy());
1305
1306        try { p.shutdown(); } catch (SecurityException ok) { return; }
1307        try (PoolCleaner cleaner = cleaner(p)) {
1308            TrackedNoOpRunnable r = new TrackedNoOpRunnable();
1309            p.execute(r);
1310            assertFalse(r.done);
1311        }
1312    }
1313
1314    /**
1315     * execute(null) throws NPE
1316     */
1317    public void testExecuteNull() {
1318        final ThreadPoolExecutor p =
1319            new CustomTPE(1, 2,
1320                          1L, SECONDS,
1321                          new ArrayBlockingQueue<Runnable>(10));
1322        try (PoolCleaner cleaner = cleaner(p)) {
1323            try {
1324                p.execute(null);
1325                shouldThrow();
1326            } catch (NullPointerException success) {}
1327        }
1328    }
1329
1330    /**
1331     * setCorePoolSize of negative value throws IllegalArgumentException
1332     */
1333    public void testCorePoolSizeIllegalArgumentException() {
1334        final ThreadPoolExecutor p =
1335            new CustomTPE(1, 2,
1336                          LONG_DELAY_MS, MILLISECONDS,
1337                          new ArrayBlockingQueue<Runnable>(10));
1338        try (PoolCleaner cleaner = cleaner(p)) {
1339            try {
1340                p.setCorePoolSize(-1);
1341                shouldThrow();
1342            } catch (IllegalArgumentException success) {}
1343        }
1344    }
1345
1346    /**
1347     * setMaximumPoolSize(int) throws IllegalArgumentException
1348     * if given a value less the core pool size
1349     */
1350    public void testMaximumPoolSizeIllegalArgumentException() {
1351        final ThreadPoolExecutor p =
1352            new CustomTPE(2, 3,
1353                          LONG_DELAY_MS, MILLISECONDS,
1354                          new ArrayBlockingQueue<Runnable>(10));
1355        try (PoolCleaner cleaner = cleaner(p)) {
1356            try {
1357                p.setMaximumPoolSize(1);
1358                shouldThrow();
1359            } catch (IllegalArgumentException success) {}
1360        }
1361    }
1362
1363    /**
1364     * setMaximumPoolSize throws IllegalArgumentException
1365     * if given a negative value
1366     */
1367    public void testMaximumPoolSizeIllegalArgumentException2() {
1368        final ThreadPoolExecutor p =
1369            new CustomTPE(2, 3,
1370                          LONG_DELAY_MS,
1371                          MILLISECONDS,new ArrayBlockingQueue<Runnable>(10));
1372        try (PoolCleaner cleaner = cleaner(p)) {
1373            try {
1374                p.setMaximumPoolSize(-1);
1375                shouldThrow();
1376            } catch (IllegalArgumentException success) {}
1377        }
1378    }
1379
1380    /**
1381     * setKeepAliveTime throws IllegalArgumentException
1382     * when given a negative value
1383     */
1384    public void testKeepAliveTimeIllegalArgumentException() {
1385        final ThreadPoolExecutor p =
1386            new CustomTPE(2, 3,
1387                          LONG_DELAY_MS, MILLISECONDS,
1388                          new ArrayBlockingQueue<Runnable>(10));
1389        try (PoolCleaner cleaner = cleaner(p)) {
1390            try {
1391                p.setKeepAliveTime(-1, MILLISECONDS);
1392                shouldThrow();
1393            } catch (IllegalArgumentException success) {}
1394        }
1395    }
1396
1397    /**
1398     * terminated() is called on termination
1399     */
1400    public void testTerminated() {
1401        CustomTPE p = new CustomTPE();
1402        try (PoolCleaner cleaner = cleaner(p)) {
1403            try { p.shutdown(); } catch (SecurityException ok) { return; }
1404            assertTrue(p.terminatedCalled());
1405            assertTrue(p.isShutdown());
1406        }
1407    }
1408
1409    /**
1410     * beforeExecute and afterExecute are called when executing task
1411     */
1412    public void testBeforeAfter() throws InterruptedException {
1413        CustomTPE p = new CustomTPE();
1414        try (PoolCleaner cleaner = cleaner(p)) {
1415            final CountDownLatch done = new CountDownLatch(1);
1416            p.execute(new CheckedRunnable() {
1417                public void realRun() {
1418                    done.countDown();
1419                }});
1420            await(p.afterCalled);
1421            assertEquals(0, done.getCount());
1422            assertTrue(p.afterCalled());
1423            assertTrue(p.beforeCalled());
1424        }
1425    }
1426
1427    /**
1428     * completed submit of callable returns result
1429     */
1430    public void testSubmitCallable() throws Exception {
1431        final ExecutorService e =
1432            new CustomTPE(2, 2,
1433                          LONG_DELAY_MS, MILLISECONDS,
1434                          new ArrayBlockingQueue<Runnable>(10));
1435        try (PoolCleaner cleaner = cleaner(e)) {
1436            Future<String> future = e.submit(new StringTask());
1437            String result = future.get();
1438            assertSame(TEST_STRING, result);
1439        }
1440    }
1441
1442    /**
1443     * completed submit of runnable returns successfully
1444     */
1445    public void testSubmitRunnable() throws Exception {
1446        final ExecutorService e =
1447            new CustomTPE(2, 2,
1448                          LONG_DELAY_MS, MILLISECONDS,
1449                          new ArrayBlockingQueue<Runnable>(10));
1450        try (PoolCleaner cleaner = cleaner(e)) {
1451            Future<?> future = e.submit(new NoOpRunnable());
1452            future.get();
1453            assertTrue(future.isDone());
1454        }
1455    }
1456
1457    /**
1458     * completed submit of (runnable, result) returns result
1459     */
1460    public void testSubmitRunnable2() throws Exception {
1461        final ExecutorService e =
1462            new CustomTPE(2, 2,
1463                          LONG_DELAY_MS, MILLISECONDS,
1464                          new ArrayBlockingQueue<Runnable>(10));
1465        try (PoolCleaner cleaner = cleaner(e)) {
1466            Future<String> future = e.submit(new NoOpRunnable(), TEST_STRING);
1467            String result = future.get();
1468            assertSame(TEST_STRING, result);
1469        }
1470    }
1471
1472    /**
1473     * invokeAny(null) throws NPE
1474     */
1475    public void testInvokeAny1() throws Exception {
1476        final ExecutorService e =
1477            new CustomTPE(2, 2,
1478                          LONG_DELAY_MS, MILLISECONDS,
1479                          new ArrayBlockingQueue<Runnable>(10));
1480        try (PoolCleaner cleaner = cleaner(e)) {
1481            try {
1482                e.invokeAny(null);
1483                shouldThrow();
1484            } catch (NullPointerException success) {}
1485        }
1486    }
1487
1488    /**
1489     * invokeAny(empty collection) throws IAE
1490     */
1491    public void testInvokeAny2() throws Exception {
1492        final ExecutorService e =
1493            new CustomTPE(2, 2,
1494                          LONG_DELAY_MS, MILLISECONDS,
1495                          new ArrayBlockingQueue<Runnable>(10));
1496        try (PoolCleaner cleaner = cleaner(e)) {
1497            try {
1498                e.invokeAny(new ArrayList<Callable<String>>());
1499                shouldThrow();
1500            } catch (IllegalArgumentException success) {}
1501        }
1502    }
1503
1504    /**
1505     * invokeAny(c) throws NPE if c has null elements
1506     */
1507    public void testInvokeAny3() throws Exception {
1508        CountDownLatch latch = new CountDownLatch(1);
1509        final ExecutorService e =
1510            new CustomTPE(2, 2,
1511                          LONG_DELAY_MS, MILLISECONDS,
1512                          new ArrayBlockingQueue<Runnable>(10));
1513        try (PoolCleaner cleaner = cleaner(e)) {
1514            List<Callable<String>> l = new ArrayList<Callable<String>>();
1515            l.add(latchAwaitingStringTask(latch));
1516            l.add(null);
1517            try {
1518                e.invokeAny(l);
1519                shouldThrow();
1520            } catch (NullPointerException success) {}
1521            latch.countDown();
1522        }
1523    }
1524
1525    /**
1526     * invokeAny(c) throws ExecutionException if no task completes
1527     */
1528    public void testInvokeAny4() throws Exception {
1529        final ExecutorService e =
1530            new CustomTPE(2, 2,
1531                          LONG_DELAY_MS, MILLISECONDS,
1532                          new ArrayBlockingQueue<Runnable>(10));
1533        try (PoolCleaner cleaner = cleaner(e)) {
1534            List<Callable<String>> l = new ArrayList<Callable<String>>();
1535            l.add(new NPETask());
1536            try {
1537                e.invokeAny(l);
1538                shouldThrow();
1539            } catch (ExecutionException success) {
1540                assertTrue(success.getCause() instanceof NullPointerException);
1541            }
1542        }
1543    }
1544
1545    /**
1546     * invokeAny(c) returns result of some task
1547     */
1548    public void testInvokeAny5() throws Exception {
1549        final ExecutorService e =
1550            new CustomTPE(2, 2,
1551                          LONG_DELAY_MS, MILLISECONDS,
1552                          new ArrayBlockingQueue<Runnable>(10));
1553        try (PoolCleaner cleaner = cleaner(e)) {
1554            List<Callable<String>> l = new ArrayList<Callable<String>>();
1555            l.add(new StringTask());
1556            l.add(new StringTask());
1557            String result = e.invokeAny(l);
1558            assertSame(TEST_STRING, result);
1559        }
1560    }
1561
1562    /**
1563     * invokeAll(null) throws NPE
1564     */
1565    public void testInvokeAll1() throws Exception {
1566        final ExecutorService e =
1567            new CustomTPE(2, 2,
1568                          LONG_DELAY_MS, MILLISECONDS,
1569                          new ArrayBlockingQueue<Runnable>(10));
1570        try (PoolCleaner cleaner = cleaner(e)) {
1571            try {
1572                e.invokeAll(null);
1573                shouldThrow();
1574            } catch (NullPointerException success) {}
1575        }
1576    }
1577
1578    /**
1579     * invokeAll(empty collection) returns empty collection
1580     */
1581    public void testInvokeAll2() throws Exception {
1582        final ExecutorService e =
1583            new CustomTPE(2, 2,
1584                          LONG_DELAY_MS, MILLISECONDS,
1585                          new ArrayBlockingQueue<Runnable>(10));
1586        try (PoolCleaner cleaner = cleaner(e)) {
1587            List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>());
1588            assertTrue(r.isEmpty());
1589        }
1590    }
1591
1592    /**
1593     * invokeAll(c) throws NPE if c has null elements
1594     */
1595    public void testInvokeAll3() throws Exception {
1596        final ExecutorService e =
1597            new CustomTPE(2, 2,
1598                          LONG_DELAY_MS, MILLISECONDS,
1599                          new ArrayBlockingQueue<Runnable>(10));
1600        try (PoolCleaner cleaner = cleaner(e)) {
1601            List<Callable<String>> l = new ArrayList<Callable<String>>();
1602            l.add(new StringTask());
1603            l.add(null);
1604            try {
1605                e.invokeAll(l);
1606                shouldThrow();
1607            } catch (NullPointerException success) {}
1608        }
1609    }
1610
1611    /**
1612     * get of element of invokeAll(c) throws exception on failed task
1613     */
1614    public void testInvokeAll4() throws Exception {
1615        final ExecutorService e =
1616            new CustomTPE(2, 2,
1617                          LONG_DELAY_MS, MILLISECONDS,
1618                          new ArrayBlockingQueue<Runnable>(10));
1619        try (PoolCleaner cleaner = cleaner(e)) {
1620            List<Callable<String>> l = new ArrayList<Callable<String>>();
1621            l.add(new NPETask());
1622            List<Future<String>> futures = e.invokeAll(l);
1623            assertEquals(1, futures.size());
1624            try {
1625                futures.get(0).get();
1626                shouldThrow();
1627            } catch (ExecutionException success) {
1628                assertTrue(success.getCause() instanceof NullPointerException);
1629            }
1630        }
1631    }
1632
1633    /**
1634     * invokeAll(c) returns results of all completed tasks
1635     */
1636    public void testInvokeAll5() throws Exception {
1637        final ExecutorService e =
1638            new CustomTPE(2, 2,
1639                          LONG_DELAY_MS, MILLISECONDS,
1640                          new ArrayBlockingQueue<Runnable>(10));
1641        try (PoolCleaner cleaner = cleaner(e)) {
1642            List<Callable<String>> l = new ArrayList<Callable<String>>();
1643            l.add(new StringTask());
1644            l.add(new StringTask());
1645            List<Future<String>> futures = e.invokeAll(l);
1646            assertEquals(2, futures.size());
1647            for (Future<String> future : futures)
1648                assertSame(TEST_STRING, future.get());
1649        }
1650    }
1651
1652    /**
1653     * timed invokeAny(null) throws NPE
1654     */
1655    public void testTimedInvokeAny1() throws Exception {
1656        final ExecutorService e =
1657            new CustomTPE(2, 2,
1658                          LONG_DELAY_MS, MILLISECONDS,
1659                          new ArrayBlockingQueue<Runnable>(10));
1660        try (PoolCleaner cleaner = cleaner(e)) {
1661            try {
1662                e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS);
1663                shouldThrow();
1664            } catch (NullPointerException success) {}
1665        }
1666    }
1667
1668    /**
1669     * timed invokeAny(,,null) throws NPE
1670     */
1671    public void testTimedInvokeAnyNullTimeUnit() throws Exception {
1672        final ExecutorService e =
1673            new CustomTPE(2, 2,
1674                          LONG_DELAY_MS, MILLISECONDS,
1675                          new ArrayBlockingQueue<Runnable>(10));
1676        try (PoolCleaner cleaner = cleaner(e)) {
1677            List<Callable<String>> l = new ArrayList<Callable<String>>();
1678            l.add(new StringTask());
1679            try {
1680                e.invokeAny(l, MEDIUM_DELAY_MS, null);
1681                shouldThrow();
1682            } catch (NullPointerException success) {}
1683        }
1684    }
1685
1686    /**
1687     * timed invokeAny(empty collection) throws IAE
1688     */
1689    public void testTimedInvokeAny2() throws Exception {
1690        final ExecutorService e =
1691            new CustomTPE(2, 2,
1692                          LONG_DELAY_MS, MILLISECONDS,
1693                          new ArrayBlockingQueue<Runnable>(10));
1694        try (PoolCleaner cleaner = cleaner(e)) {
1695            try {
1696                e.invokeAny(new ArrayList<Callable<String>>(),
1697                            MEDIUM_DELAY_MS, MILLISECONDS);
1698                shouldThrow();
1699            } catch (IllegalArgumentException success) {}
1700        }
1701    }
1702
1703    /**
1704     * timed invokeAny(c) throws NPE if c has null elements
1705     */
1706    public void testTimedInvokeAny3() throws Exception {
1707        CountDownLatch latch = new CountDownLatch(1);
1708        final ExecutorService e =
1709            new CustomTPE(2, 2,
1710                          LONG_DELAY_MS, MILLISECONDS,
1711                          new ArrayBlockingQueue<Runnable>(10));
1712        try (PoolCleaner cleaner = cleaner(e)) {
1713            List<Callable<String>> l = new ArrayList<Callable<String>>();
1714            l.add(latchAwaitingStringTask(latch));
1715            l.add(null);
1716            try {
1717                e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
1718                shouldThrow();
1719            } catch (NullPointerException success) {}
1720            latch.countDown();
1721        }
1722    }
1723
1724    /**
1725     * timed invokeAny(c) throws ExecutionException if no task completes
1726     */
1727    public void testTimedInvokeAny4() throws Exception {
1728        final ExecutorService e =
1729            new CustomTPE(2, 2,
1730                          LONG_DELAY_MS, MILLISECONDS,
1731                          new ArrayBlockingQueue<Runnable>(10));
1732        try (PoolCleaner cleaner = cleaner(e)) {
1733            long startTime = System.nanoTime();
1734            List<Callable<String>> l = new ArrayList<Callable<String>>();
1735            l.add(new NPETask());
1736            try {
1737                e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
1738                shouldThrow();
1739            } catch (ExecutionException success) {
1740                assertTrue(success.getCause() instanceof NullPointerException);
1741            }
1742            assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
1743        }
1744    }
1745
1746    /**
1747     * timed invokeAny(c) returns result of some task
1748     */
1749    public void testTimedInvokeAny5() throws Exception {
1750        final ExecutorService e =
1751            new CustomTPE(2, 2,
1752                          LONG_DELAY_MS, MILLISECONDS,
1753                          new ArrayBlockingQueue<Runnable>(10));
1754        try (PoolCleaner cleaner = cleaner(e)) {
1755            long startTime = System.nanoTime();
1756            List<Callable<String>> l = new ArrayList<Callable<String>>();
1757            l.add(new StringTask());
1758            l.add(new StringTask());
1759            String result = e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
1760            assertSame(TEST_STRING, result);
1761            assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
1762        }
1763    }
1764
1765    /**
1766     * timed invokeAll(null) throws NPE
1767     */
1768    public void testTimedInvokeAll1() throws Exception {
1769        final ExecutorService e =
1770            new CustomTPE(2, 2,
1771                          LONG_DELAY_MS, MILLISECONDS,
1772                          new ArrayBlockingQueue<Runnable>(10));
1773        try (PoolCleaner cleaner = cleaner(e)) {
1774            try {
1775                e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS);
1776                shouldThrow();
1777            } catch (NullPointerException success) {}
1778        }
1779    }
1780
1781    /**
1782     * timed invokeAll(,,null) throws NPE
1783     */
1784    public void testTimedInvokeAllNullTimeUnit() throws Exception {
1785        final ExecutorService e =
1786            new CustomTPE(2, 2,
1787                          LONG_DELAY_MS, MILLISECONDS,
1788                          new ArrayBlockingQueue<Runnable>(10));
1789        try (PoolCleaner cleaner = cleaner(e)) {
1790            List<Callable<String>> l = new ArrayList<Callable<String>>();
1791            l.add(new StringTask());
1792            try {
1793                e.invokeAll(l, MEDIUM_DELAY_MS, null);
1794                shouldThrow();
1795            } catch (NullPointerException success) {}
1796        }
1797    }
1798
1799    /**
1800     * timed invokeAll(empty collection) returns empty collection
1801     */
1802    public void testTimedInvokeAll2() throws Exception {
1803        final ExecutorService e =
1804            new CustomTPE(2, 2,
1805                          LONG_DELAY_MS, MILLISECONDS,
1806                          new ArrayBlockingQueue<Runnable>(10));
1807        try (PoolCleaner cleaner = cleaner(e)) {
1808            List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>(),
1809                                                 MEDIUM_DELAY_MS, MILLISECONDS);
1810            assertTrue(r.isEmpty());
1811        }
1812    }
1813
1814    /**
1815     * timed invokeAll(c) throws NPE if c has null elements
1816     */
1817    public void testTimedInvokeAll3() throws Exception {
1818        final ExecutorService e =
1819            new CustomTPE(2, 2,
1820                          LONG_DELAY_MS, MILLISECONDS,
1821                          new ArrayBlockingQueue<Runnable>(10));
1822        try (PoolCleaner cleaner = cleaner(e)) {
1823            List<Callable<String>> l = new ArrayList<Callable<String>>();
1824            l.add(new StringTask());
1825            l.add(null);
1826            try {
1827                e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
1828                shouldThrow();
1829            } catch (NullPointerException success) {}
1830        }
1831    }
1832
1833    /**
1834     * get of element of invokeAll(c) throws exception on failed task
1835     */
1836    public void testTimedInvokeAll4() throws Exception {
1837        final ExecutorService e =
1838            new CustomTPE(2, 2,
1839                          LONG_DELAY_MS, MILLISECONDS,
1840                          new ArrayBlockingQueue<Runnable>(10));
1841        try (PoolCleaner cleaner = cleaner(e)) {
1842            List<Callable<String>> l = new ArrayList<Callable<String>>();
1843            l.add(new NPETask());
1844            List<Future<String>> futures =
1845                e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS);
1846            assertEquals(1, futures.size());
1847            try {
1848                futures.get(0).get();
1849                shouldThrow();
1850            } catch (ExecutionException success) {
1851                assertTrue(success.getCause() instanceof NullPointerException);
1852            }
1853        }
1854    }
1855
1856    /**
1857     * timed invokeAll(c) returns results of all completed tasks
1858     */
1859    public void testTimedInvokeAll5() throws Exception {
1860        final ExecutorService e =
1861            new CustomTPE(2, 2,
1862                          LONG_DELAY_MS, MILLISECONDS,
1863                          new ArrayBlockingQueue<Runnable>(10));
1864        try (PoolCleaner cleaner = cleaner(e)) {
1865            List<Callable<String>> l = new ArrayList<Callable<String>>();
1866            l.add(new StringTask());
1867            l.add(new StringTask());
1868            List<Future<String>> futures =
1869                e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS);
1870            assertEquals(2, futures.size());
1871            for (Future<String> future : futures)
1872                assertSame(TEST_STRING, future.get());
1873        }
1874    }
1875
1876    /**
1877     * timed invokeAll(c) cancels tasks not completed by timeout
1878     */
1879    public void testTimedInvokeAll6() throws Exception {
1880        for (long timeout = timeoutMillis();;) {
1881            final CountDownLatch done = new CountDownLatch(1);
1882            final Callable<String> waiter = new CheckedCallable<String>() {
1883                public String realCall() {
1884                    try { done.await(LONG_DELAY_MS, MILLISECONDS); }
1885                    catch (InterruptedException ok) {}
1886                    return "1"; }};
1887            final ExecutorService p =
1888                new CustomTPE(2, 2,
1889                              LONG_DELAY_MS, MILLISECONDS,
1890                              new ArrayBlockingQueue<Runnable>(10));
1891            try (PoolCleaner cleaner = cleaner(p, done)) {
1892                List<Callable<String>> tasks = new ArrayList<>();
1893                tasks.add(new StringTask("0"));
1894                tasks.add(waiter);
1895                tasks.add(new StringTask("2"));
1896                long startTime = System.nanoTime();
1897                List<Future<String>> futures =
1898                    p.invokeAll(tasks, timeout, MILLISECONDS);
1899                assertEquals(tasks.size(), futures.size());
1900                assertTrue(millisElapsedSince(startTime) >= timeout);
1901                for (Future future : futures)
1902                    assertTrue(future.isDone());
1903                assertTrue(futures.get(1).isCancelled());
1904                try {
1905                    assertEquals("0", futures.get(0).get());
1906                    assertEquals("2", futures.get(2).get());
1907                    break;
1908                } catch (CancellationException retryWithLongerTimeout) {
1909                    timeout *= 2;
1910                    if (timeout >= LONG_DELAY_MS / 2)
1911                        fail("expected exactly one task to be cancelled");
1912                }
1913            }
1914        }
1915    }
1916
1917    /**
1918     * Execution continues if there is at least one thread even if
1919     * thread factory fails to create more
1920     */
1921    public void testFailingThreadFactory() throws InterruptedException {
1922        final ExecutorService e =
1923            new CustomTPE(100, 100,
1924                          LONG_DELAY_MS, MILLISECONDS,
1925                          new LinkedBlockingQueue<Runnable>(),
1926                          new FailingThreadFactory());
1927        try (PoolCleaner cleaner = cleaner(e)) {
1928            final int TASKS = 100;
1929            final CountDownLatch done = new CountDownLatch(TASKS);
1930            for (int k = 0; k < TASKS; ++k)
1931                e.execute(new CheckedRunnable() {
1932                    public void realRun() {
1933                        done.countDown();
1934                    }});
1935            assertTrue(done.await(LONG_DELAY_MS, MILLISECONDS));
1936        }
1937    }
1938
1939    /**
1940     * allowsCoreThreadTimeOut is by default false.
1941     */
1942    public void testAllowsCoreThreadTimeOut() {
1943        final ThreadPoolExecutor p =
1944            new CustomTPE(2, 2,
1945                          1000, MILLISECONDS,
1946                          new ArrayBlockingQueue<Runnable>(10));
1947        try (PoolCleaner cleaner = cleaner(p)) {
1948            assertFalse(p.allowsCoreThreadTimeOut());
1949        }
1950    }
1951
1952    /**
1953     * allowCoreThreadTimeOut(true) causes idle threads to time out
1954     */
1955    public void testAllowCoreThreadTimeOut_true() throws Exception {
1956        long keepAliveTime = timeoutMillis();
1957        final ThreadPoolExecutor p =
1958            new CustomTPE(2, 10,
1959                          keepAliveTime, MILLISECONDS,
1960                          new ArrayBlockingQueue<Runnable>(10));
1961        try (PoolCleaner cleaner = cleaner(p)) {
1962            final CountDownLatch threadStarted = new CountDownLatch(1);
1963            p.allowCoreThreadTimeOut(true);
1964            p.execute(new CheckedRunnable() {
1965                public void realRun() {
1966                    threadStarted.countDown();
1967                    assertEquals(1, p.getPoolSize());
1968                }});
1969            await(threadStarted);
1970            delay(keepAliveTime);
1971            long startTime = System.nanoTime();
1972            while (p.getPoolSize() > 0
1973                   && millisElapsedSince(startTime) < LONG_DELAY_MS)
1974                Thread.yield();
1975            assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
1976            assertEquals(0, p.getPoolSize());
1977        }
1978    }
1979
1980    /**
1981     * allowCoreThreadTimeOut(false) causes idle threads not to time out
1982     */
1983    public void testAllowCoreThreadTimeOut_false() throws Exception {
1984        long keepAliveTime = timeoutMillis();
1985        final ThreadPoolExecutor p =
1986            new CustomTPE(2, 10,
1987                          keepAliveTime, MILLISECONDS,
1988                          new ArrayBlockingQueue<Runnable>(10));
1989        try (PoolCleaner cleaner = cleaner(p)) {
1990            final CountDownLatch threadStarted = new CountDownLatch(1);
1991            p.allowCoreThreadTimeOut(false);
1992            p.execute(new CheckedRunnable() {
1993                public void realRun() throws InterruptedException {
1994                    threadStarted.countDown();
1995                    assertTrue(p.getPoolSize() >= 1);
1996                }});
1997            delay(2 * keepAliveTime);
1998            assertTrue(p.getPoolSize() >= 1);
1999        }
2000    }
2001
2002    /**
2003     * get(cancelled task) throws CancellationException
2004     * (in part, a test of CustomTPE itself)
2005     */
2006    public void testGet_cancelled() throws Exception {
2007        final CountDownLatch done = new CountDownLatch(1);
2008        final ExecutorService e =
2009            new CustomTPE(1, 1,
2010                          LONG_DELAY_MS, MILLISECONDS,
2011                          new LinkedBlockingQueue<Runnable>());
2012        try (PoolCleaner cleaner = cleaner(e, done)) {
2013            final CountDownLatch blockerStarted = new CountDownLatch(1);
2014            final List<Future<?>> futures = new ArrayList<>();
2015            for (int i = 0; i < 2; i++) {
2016                Runnable r = new CheckedRunnable() { public void realRun()
2017                                                         throws Throwable {
2018                    blockerStarted.countDown();
2019                    assertTrue(done.await(2 * LONG_DELAY_MS, MILLISECONDS));
2020                }};
2021                futures.add(e.submit(r));
2022            }
2023            await(blockerStarted);
2024            for (Future<?> future : futures) future.cancel(false);
2025            for (Future<?> future : futures) {
2026                try {
2027                    future.get();
2028                    shouldThrow();
2029                } catch (CancellationException success) {}
2030                try {
2031                    future.get(LONG_DELAY_MS, MILLISECONDS);
2032                    shouldThrow();
2033                } catch (CancellationException success) {}
2034                assertTrue(future.isCancelled());
2035                assertTrue(future.isDone());
2036            }
2037        }
2038    }
2039
2040}
2041