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 
9 package jsr166;
10 
11 import static java.util.concurrent.TimeUnit.MILLISECONDS;
12 import static java.util.concurrent.TimeUnit.SECONDS;
13 
14 import java.util.ArrayList;
15 import java.util.List;
16 import java.util.concurrent.ArrayBlockingQueue;
17 import java.util.concurrent.BlockingQueue;
18 import java.util.concurrent.Callable;
19 import java.util.concurrent.CancellationException;
20 import java.util.concurrent.CountDownLatch;
21 import java.util.concurrent.ExecutionException;
22 import java.util.concurrent.Executors;
23 import java.util.concurrent.ExecutorService;
24 import java.util.concurrent.Future;
25 import java.util.concurrent.FutureTask;
26 import java.util.concurrent.LinkedBlockingQueue;
27 import java.util.concurrent.RejectedExecutionException;
28 import java.util.concurrent.RejectedExecutionHandler;
29 import java.util.concurrent.RunnableFuture;
30 import java.util.concurrent.SynchronousQueue;
31 import java.util.concurrent.ThreadFactory;
32 import java.util.concurrent.ThreadPoolExecutor;
33 import java.util.concurrent.TimeoutException;
34 import java.util.concurrent.TimeUnit;
35 import java.util.concurrent.atomic.AtomicInteger;
36 import java.util.concurrent.locks.Condition;
37 import java.util.concurrent.locks.ReentrantLock;
38 
39 import junit.framework.Test;
40 import junit.framework.TestSuite;
41 
42 public 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;
CustomTask(Callable<V> c)62         CustomTask(Callable<V> c) {
63             if (c == null) throw new NullPointerException();
64             callable = c;
65         }
CustomTask(final Runnable r, final V res)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         }
isDone()71         public boolean isDone() {
72             lock.lock(); try { return done; } finally { lock.unlock() ; }
73         }
isCancelled()74         public boolean isCancelled() {
75             lock.lock(); try { return cancelled; } finally { lock.unlock() ; }
76         }
cancel(boolean mayInterrupt)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         }
run()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         }
get()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         }
get(long timeout, TimeUnit unit)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 {
newTaskFor(Callable<V> c)153         protected <V> RunnableFuture<V> newTaskFor(Callable<V> c) {
154             return new CustomTask<V>(c);
155         }
newTaskFor(Runnable r, V v)156         protected <V> RunnableFuture<V> newTaskFor(Runnable r, V v) {
157             return new CustomTask<V>(r, v);
158         }
159 
CustomTPE(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue)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         }
CustomTPE(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory)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 
CustomTPE(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler)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         }
CustomTPE(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)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 
CustomTPE()202         public CustomTPE() {
203             super(1, 1, LONG_DELAY_MS, MILLISECONDS, new SynchronousQueue<Runnable>());
204         }
beforeExecute(Thread t, Runnable r)205         protected void beforeExecute(Thread t, Runnable r) {
206             beforeCalled.countDown();
207         }
afterExecute(Runnable r, Throwable t)208         protected void afterExecute(Runnable r, Throwable t) {
209             afterCalled.countDown();
210         }
terminated()211         protected void terminated() {
212             terminatedCalled.countDown();
213         }
214 
beforeCalled()215         public boolean beforeCalled() {
216             return beforeCalled.getCount() == 0;
217         }
afterCalled()218         public boolean afterCalled() {
219             return afterCalled.getCount() == 0;
220         }
terminatedCalled()221         public boolean terminatedCalled() {
222             return terminatedCalled.getCount() == 0;
223         }
224     }
225 
226     static class FailingThreadFactory implements ThreadFactory {
227         int calls = 0;
newThread(Runnable r)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      */
testExecute()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      */
testGetActiveCount()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      */
testPrestartCoreThread()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      */
testPrestartAllCoreThreads()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      */
testGetCompletedTaskCount()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      */
testGetCorePoolSize()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      */
testGetKeepAliveTime()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      */
testGetThreadFactory()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      */
testSetThreadFactory()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      */
testSetThreadFactoryNull()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      */
testGetRejectedExecutionHandler()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      */
testSetRejectedExecutionHandler()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      */
testSetRejectedExecutionHandlerNull()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      */
testGetLargestPoolSize()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      */
testGetMaximumPoolSize()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      */
testGetPoolSize()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      */
testGetTaskCount()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      */
testIsShutdown()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      */
testIsTerminated()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      */
testIsTerminating()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      */
testGetQueue()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      */
testRemove()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      */
testPurge()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      */
testShutdownNow()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      */
testConstructor1()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      */
testConstructor2()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      */
testConstructor3()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      */
testConstructor4()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      */
testConstructor5()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      */
testConstructorNullPointerException()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      */
testConstructor6()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      */
testConstructor7()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      */
testConstructor8()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      */
testConstructor9()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      */
testConstructor10()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      */
testConstructorNullPointerException2()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      */
testConstructorNullPointerException3()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      */
testConstructor11()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      */
testConstructor12()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      */
testConstructor13()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      */
testConstructor14()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      */
testConstructor15()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      */
testConstructorNullPointerException4()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      */
testConstructorNullPointerException5()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      */
testConstructor16()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      */
testConstructor17()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      */
testConstructor18()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      */
testConstructor19()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      */
testConstructor20()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      */
testConstructorNullPointerException6()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      */
testConstructorNullPointerException7()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      */
testConstructorNullPointerException8()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      */
testSaturatedExecute()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      */
testSaturatedExecute2()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      */
testSaturatedExecute3()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      */
testSaturatedExecute4()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      */
testRejectedExecutionExceptionOnShutdown()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      */
testCallerRunsOnShutdown()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      */
testDiscardOnShutdown()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      */
testDiscardOldestOnShutdown()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      */
testExecuteNull()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      */
testCorePoolSizeIllegalArgumentException()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      */
testMaximumPoolSizeIllegalArgumentException()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      */
testMaximumPoolSizeIllegalArgumentException2()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      */
testKeepAliveTimeIllegalArgumentException()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      */
testTerminated()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      */
testBeforeAfter()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      */
testSubmitCallable()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      */
testSubmitRunnable()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      */
testSubmitRunnable2()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      */
testInvokeAny1()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      */
testInvokeAny2()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      */
testInvokeAny3()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      */
testInvokeAny4()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      */
testInvokeAny5()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      */
testInvokeAll1()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      */
testInvokeAll2()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      */
testInvokeAll3()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      */
testInvokeAll4()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      */
testInvokeAll5()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      */
testTimedInvokeAny1()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      */
testTimedInvokeAnyNullTimeUnit()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      */
testTimedInvokeAny2()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      */
testTimedInvokeAny3()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      */
testTimedInvokeAny4()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