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