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