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