ThreadPoolExecutorSubclassTest.java revision ed4f365789d43b1961657195df223a19bf4ef20f
1/*
2 * Written by Doug Lea with assistance from members of JCP JSR-166
3 * Expert Group and released to the public domain, as explained at
4 * http://creativecommons.org/publicdomain/zero/1.0/
5 * Other contributors include Andrew Wright, Jeffrey Hayes,
6 * Pat Fisher, Mike Judd.
7 */
8
9package jsr166;
10
11import static java.util.concurrent.TimeUnit.MILLISECONDS;
12
13import java.util.ArrayList;
14import java.util.List;
15import java.util.concurrent.ArrayBlockingQueue;
16import java.util.concurrent.BlockingQueue;
17import java.util.concurrent.Callable;
18import java.util.concurrent.CountDownLatch;
19import java.util.concurrent.ExecutionException;
20import java.util.concurrent.Executors;
21import java.util.concurrent.ExecutorService;
22import java.util.concurrent.Future;
23import java.util.concurrent.FutureTask;
24import java.util.concurrent.LinkedBlockingQueue;
25import java.util.concurrent.RejectedExecutionException;
26import java.util.concurrent.RejectedExecutionHandler;
27import java.util.concurrent.RunnableFuture;
28import java.util.concurrent.SynchronousQueue;
29import java.util.concurrent.ThreadFactory;
30import java.util.concurrent.ThreadPoolExecutor;
31import java.util.concurrent.TimeoutException;
32import java.util.concurrent.TimeUnit;
33import java.util.concurrent.locks.Condition;
34import java.util.concurrent.locks.ReentrantLock;
35
36import junit.framework.Test;
37import junit.framework.TestSuite;
38
39public 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;
59        CustomTask(Callable<V> c) {
60            if (c == null) throw new NullPointerException();
61            callable = c;
62        }
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        }
68        public boolean isDone() {
69            lock.lock(); try { return done; } finally { lock.unlock() ; }
70        }
71        public boolean isCancelled() {
72            lock.lock(); try { return cancelled; } finally { lock.unlock() ; }
73        }
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        }
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        }
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        }
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 {
145        protected <V> RunnableFuture<V> newTaskFor(Callable<V> c) {
146            return new CustomTask<V>(c);
147        }
148        protected <V> RunnableFuture<V> newTaskFor(Runnable r, V v) {
149            return new CustomTask<V>(r, v);
150        }
151
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        }
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
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        }
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
194        public CustomTPE() {
195            super(1, 1, LONG_DELAY_MS, MILLISECONDS, new SynchronousQueue<Runnable>());
196        }
197        protected void beforeExecute(Thread t, Runnable r) {
198            beforeCalled.countDown();
199        }
200        protected void afterExecute(Runnable r, Throwable t) {
201            afterCalled.countDown();
202        }
203        protected void terminated() {
204            terminatedCalled.countDown();
205        }
206
207        public boolean beforeCalled() {
208            return beforeCalled.getCount() == 0;
209        }
210        public boolean afterCalled() {
211            return afterCalled.getCount() == 0;
212        }
213        public boolean terminatedCalled() {
214            return terminatedCalled.getCount() == 0;
215        }
216    }
217
218    static class FailingThreadFactory implements ThreadFactory {
219        int calls = 0;
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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);
1792            assertTrue(p.getPoolSize() >= 1);
1793        } finally {
1794            joinPool(p);
1795        }
1796    }
1797
1798}
1799