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  */
      6 
      7 package jsr166;
      8 
      9 import junit.framework.*;
     10 import java.util.*;
     11 import java.util.concurrent.*;
     12 import static java.util.concurrent.TimeUnit.MILLISECONDS;
     13 import java.util.concurrent.atomic.AtomicInteger;
     14 
     15 public class ScheduledExecutorSubclassTest extends JSR166TestCase {
     16 
     17     static class CustomTask<V> implements RunnableScheduledFuture<V> {
     18         RunnableScheduledFuture<V> task;
     19         volatile boolean ran;
     20         CustomTask(RunnableScheduledFuture<V> t) { task = t; }
     21         public boolean isPeriodic() { return task.isPeriodic(); }
     22         public void run() {
     23             ran = true;
     24             task.run();
     25         }
     26         public long getDelay(TimeUnit unit) { return task.getDelay(unit); }
     27         public int compareTo(Delayed t) {
     28             return task.compareTo(((CustomTask)t).task);
     29         }
     30         public boolean cancel(boolean mayInterruptIfRunning) {
     31             return task.cancel(mayInterruptIfRunning);
     32         }
     33         public boolean isCancelled() { return task.isCancelled(); }
     34         public boolean isDone() { return task.isDone(); }
     35         public V get() throws InterruptedException, ExecutionException {
     36             V v = task.get();
     37             assertTrue(ran);
     38             return v;
     39         }
     40         public V get(long time, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
     41             V v = task.get(time, unit);
     42             assertTrue(ran);
     43             return v;
     44         }
     45     }
     46 
     47     public class CustomExecutor extends ScheduledThreadPoolExecutor {
     48 
     49         protected <V> RunnableScheduledFuture<V> decorateTask(Runnable r, RunnableScheduledFuture<V> task) {
     50             return new CustomTask<V>(task);
     51         }
     52 
     53         protected <V> RunnableScheduledFuture<V> decorateTask(Callable<V> c, RunnableScheduledFuture<V> task) {
     54             return new CustomTask<V>(task);
     55         }
     56         CustomExecutor(int corePoolSize) { super(corePoolSize); }
     57         CustomExecutor(int corePoolSize, RejectedExecutionHandler handler) {
     58             super(corePoolSize, handler);
     59         }
     60 
     61         CustomExecutor(int corePoolSize, ThreadFactory threadFactory) {
     62             super(corePoolSize, threadFactory);
     63         }
     64         CustomExecutor(int corePoolSize, ThreadFactory threadFactory,
     65                        RejectedExecutionHandler handler) {
     66             super(corePoolSize, threadFactory, handler);
     67         }
     68 
     69     }
     70 
     71     /**
     72      * execute successfully executes a runnable
     73      */
     74     public void testExecute() throws InterruptedException {
     75         CustomExecutor p = new CustomExecutor(1);
     76         final CountDownLatch done = new CountDownLatch(1);
     77         final Runnable task = new CheckedRunnable() {
     78             public void realRun() {
     79                 done.countDown();
     80             }};
     81         try {
     82             p.execute(task);
     83             assertTrue(done.await(SMALL_DELAY_MS, MILLISECONDS));
     84         } finally {
     85             joinPool(p);
     86         }
     87     }
     88 
     89     /**
     90      * delayed schedule of callable successfully executes after delay
     91      */
     92     public void testSchedule1() throws Exception {
     93         CustomExecutor p = new CustomExecutor(1);
     94         final long startTime = System.nanoTime();
     95         final CountDownLatch done = new CountDownLatch(1);
     96         try {
     97             Callable task = new CheckedCallable<Boolean>() {
     98                 public Boolean realCall() {
     99                     done.countDown();
    100                     assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
    101                     return Boolean.TRUE;
    102                 }};
    103             Future f = p.schedule(task, timeoutMillis(), MILLISECONDS);
    104             assertSame(Boolean.TRUE, f.get());
    105             assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
    106             assertTrue(done.await(0L, MILLISECONDS));
    107         } finally {
    108             joinPool(p);
    109         }
    110     }
    111 
    112     /**
    113      * delayed schedule of runnable successfully executes after delay
    114      */
    115     public void testSchedule3() throws Exception {
    116         CustomExecutor p = new CustomExecutor(1);
    117         final long startTime = System.nanoTime();
    118         final CountDownLatch done = new CountDownLatch(1);
    119         try {
    120             Runnable task = new CheckedRunnable() {
    121                 public void realRun() {
    122                     done.countDown();
    123                     assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
    124                 }};
    125             Future f = p.schedule(task, timeoutMillis(), MILLISECONDS);
    126             await(done);
    127             assertNull(f.get(LONG_DELAY_MS, MILLISECONDS));
    128             assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
    129         } finally {
    130             joinPool(p);
    131         }
    132     }
    133 
    134     /**
    135      * scheduleAtFixedRate executes runnable after given initial delay
    136      */
    137     public void testSchedule4() throws InterruptedException {
    138         CustomExecutor p = new CustomExecutor(1);
    139         final long startTime = System.nanoTime();
    140         final CountDownLatch done = new CountDownLatch(1);
    141         try {
    142             Runnable task = new CheckedRunnable() {
    143                 public void realRun() {
    144                     done.countDown();
    145                     assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
    146                 }};
    147             ScheduledFuture f =
    148                 p.scheduleAtFixedRate(task, timeoutMillis(),
    149                                       LONG_DELAY_MS, MILLISECONDS);
    150             await(done);
    151             assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
    152             f.cancel(true);
    153         } finally {
    154             joinPool(p);
    155         }
    156     }
    157 
    158     /**
    159      * scheduleWithFixedDelay executes runnable after given initial delay
    160      */
    161     public void testSchedule5() throws InterruptedException {
    162         CustomExecutor p = new CustomExecutor(1);
    163         final long startTime = System.nanoTime();
    164         final CountDownLatch done = new CountDownLatch(1);
    165         try {
    166             Runnable task = new CheckedRunnable() {
    167                 public void realRun() {
    168                     done.countDown();
    169                     assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
    170                 }};
    171             ScheduledFuture f =
    172                 p.scheduleWithFixedDelay(task, timeoutMillis(),
    173                                          LONG_DELAY_MS, MILLISECONDS);
    174             await(done);
    175             assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
    176             f.cancel(true);
    177         } finally {
    178             joinPool(p);
    179         }
    180     }
    181 
    182     static class RunnableCounter implements Runnable {
    183         AtomicInteger count = new AtomicInteger(0);
    184         public void run() { count.getAndIncrement(); }
    185     }
    186 
    187     /**
    188      * scheduleAtFixedRate executes series of tasks at given rate
    189      */
    190     public void testFixedRateSequence() throws InterruptedException {
    191         CustomExecutor p = new CustomExecutor(1);
    192         RunnableCounter counter = new RunnableCounter();
    193         ScheduledFuture h =
    194             p.scheduleAtFixedRate(counter, 0, 1, MILLISECONDS);
    195         delay(SMALL_DELAY_MS);
    196         h.cancel(true);
    197         int c = counter.count.get();
    198         // By time scaling conventions, we must have at least
    199         // an execution per SHORT delay, but no more than one SHORT more
    200         assertTrue(c >= SMALL_DELAY_MS / SHORT_DELAY_MS);
    201         assertTrue(c <= SMALL_DELAY_MS + SHORT_DELAY_MS);
    202         joinPool(p);
    203     }
    204 
    205     /**
    206      * scheduleWithFixedDelay executes series of tasks with given period
    207      */
    208     public void testFixedDelaySequence() throws InterruptedException {
    209         CustomExecutor p = new CustomExecutor(1);
    210         RunnableCounter counter = new RunnableCounter();
    211         ScheduledFuture h =
    212             p.scheduleWithFixedDelay(counter, 0, 1, MILLISECONDS);
    213         delay(SMALL_DELAY_MS);
    214         h.cancel(true);
    215         int c = counter.count.get();
    216         assertTrue(c >= SMALL_DELAY_MS / SHORT_DELAY_MS);
    217         assertTrue(c <= SMALL_DELAY_MS + SHORT_DELAY_MS);
    218         joinPool(p);
    219     }
    220 
    221     /**
    222      * execute(null) throws NPE
    223      */
    224     public void testExecuteNull() throws InterruptedException {
    225         CustomExecutor se = new CustomExecutor(1);
    226         try {
    227             se.execute(null);
    228             shouldThrow();
    229         } catch (NullPointerException success) {}
    230         joinPool(se);
    231     }
    232 
    233     /**
    234      * schedule(null) throws NPE
    235      */
    236     public void testScheduleNull() throws InterruptedException {
    237         CustomExecutor se = new CustomExecutor(1);
    238         try {
    239             TrackedCallable callable = null;
    240             Future f = se.schedule(callable, SHORT_DELAY_MS, MILLISECONDS);
    241             shouldThrow();
    242         } catch (NullPointerException success) {}
    243         joinPool(se);
    244     }
    245 
    246     /**
    247      * execute throws RejectedExecutionException if shutdown
    248      */
    249     public void testSchedule1_RejectedExecutionException() {
    250         CustomExecutor se = new CustomExecutor(1);
    251         try {
    252             se.shutdown();
    253             se.schedule(new NoOpRunnable(),
    254                         MEDIUM_DELAY_MS, MILLISECONDS);
    255             shouldThrow();
    256         } catch (RejectedExecutionException success) {
    257         } catch (SecurityException ok) {
    258         }
    259 
    260         joinPool(se);
    261     }
    262 
    263     /**
    264      * schedule throws RejectedExecutionException if shutdown
    265      */
    266     public void testSchedule2_RejectedExecutionException() {
    267         CustomExecutor se = new CustomExecutor(1);
    268         try {
    269             se.shutdown();
    270             se.schedule(new NoOpCallable(),
    271                         MEDIUM_DELAY_MS, MILLISECONDS);
    272             shouldThrow();
    273         } catch (RejectedExecutionException success) {
    274         } catch (SecurityException ok) {
    275         }
    276         joinPool(se);
    277     }
    278 
    279     /**
    280      * schedule callable throws RejectedExecutionException if shutdown
    281      */
    282     public void testSchedule3_RejectedExecutionException() {
    283         CustomExecutor se = new CustomExecutor(1);
    284         try {
    285             se.shutdown();
    286             se.schedule(new NoOpCallable(),
    287                         MEDIUM_DELAY_MS, MILLISECONDS);
    288             shouldThrow();
    289         } catch (RejectedExecutionException success) {
    290         } catch (SecurityException ok) {
    291         }
    292         joinPool(se);
    293     }
    294 
    295     /**
    296      * scheduleAtFixedRate throws RejectedExecutionException if shutdown
    297      */
    298     public void testScheduleAtFixedRate1_RejectedExecutionException() {
    299         CustomExecutor se = new CustomExecutor(1);
    300         try {
    301             se.shutdown();
    302             se.scheduleAtFixedRate(new NoOpRunnable(),
    303                                    MEDIUM_DELAY_MS, MEDIUM_DELAY_MS, MILLISECONDS);
    304             shouldThrow();
    305         } catch (RejectedExecutionException success) {
    306         } catch (SecurityException ok) {
    307         }
    308         joinPool(se);
    309     }
    310 
    311     /**
    312      * scheduleWithFixedDelay throws RejectedExecutionException if shutdown
    313      */
    314     public void testScheduleWithFixedDelay1_RejectedExecutionException() {
    315         CustomExecutor se = new CustomExecutor(1);
    316         try {
    317             se.shutdown();
    318             se.scheduleWithFixedDelay(new NoOpRunnable(),
    319                                       MEDIUM_DELAY_MS, MEDIUM_DELAY_MS, MILLISECONDS);
    320             shouldThrow();
    321         } catch (RejectedExecutionException success) {
    322         } catch (SecurityException ok) {
    323         }
    324         joinPool(se);
    325     }
    326 
    327     /**
    328      * getActiveCount increases but doesn't overestimate, when a
    329      * thread becomes active
    330      */
    331     public void testGetActiveCount() throws InterruptedException {
    332         final ThreadPoolExecutor p = new CustomExecutor(2);
    333         final CountDownLatch threadStarted = new CountDownLatch(1);
    334         final CountDownLatch done = new CountDownLatch(1);
    335         try {
    336             assertEquals(0, p.getActiveCount());
    337             p.execute(new CheckedRunnable() {
    338                 public void realRun() throws InterruptedException {
    339                     threadStarted.countDown();
    340                     assertEquals(1, p.getActiveCount());
    341                     done.await();
    342                 }});
    343             assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
    344             assertEquals(1, p.getActiveCount());
    345         } finally {
    346             done.countDown();
    347             joinPool(p);
    348         }
    349     }
    350 
    351     /**
    352      * getCompletedTaskCount increases, but doesn't overestimate,
    353      * when tasks complete
    354      */
    355     public void testGetCompletedTaskCount() throws InterruptedException {
    356         final ThreadPoolExecutor p = new CustomExecutor(2);
    357         final CountDownLatch threadStarted = new CountDownLatch(1);
    358         final CountDownLatch threadProceed = new CountDownLatch(1);
    359         final CountDownLatch threadDone = new CountDownLatch(1);
    360         try {
    361             assertEquals(0, p.getCompletedTaskCount());
    362             p.execute(new CheckedRunnable() {
    363                 public void realRun() throws InterruptedException {
    364                     threadStarted.countDown();
    365                     assertEquals(0, p.getCompletedTaskCount());
    366                     threadProceed.await();
    367                     threadDone.countDown();
    368                 }});
    369             await(threadStarted);
    370             assertEquals(0, p.getCompletedTaskCount());
    371             threadProceed.countDown();
    372             threadDone.await();
    373             long startTime = System.nanoTime();
    374             while (p.getCompletedTaskCount() != 1) {
    375                 if (millisElapsedSince(startTime) > LONG_DELAY_MS)
    376                     fail("timed out");
    377                 Thread.yield();
    378             }
    379         } finally {
    380             joinPool(p);
    381         }
    382     }
    383 
    384     /**
    385      * getCorePoolSize returns size given in constructor if not otherwise set
    386      */
    387     public void testGetCorePoolSize() {
    388         CustomExecutor p = new CustomExecutor(1);
    389         assertEquals(1, p.getCorePoolSize());
    390         joinPool(p);
    391     }
    392 
    393     /**
    394      * getLargestPoolSize increases, but doesn't overestimate, when
    395      * multiple threads active
    396      */
    397     public void testGetLargestPoolSize() throws InterruptedException {
    398         final int THREADS = 3;
    399         final ThreadPoolExecutor p = new CustomExecutor(THREADS);
    400         final CountDownLatch threadsStarted = new CountDownLatch(THREADS);
    401         final CountDownLatch done = new CountDownLatch(1);
    402         try {
    403             assertEquals(0, p.getLargestPoolSize());
    404             for (int i = 0; i < THREADS; i++)
    405                 p.execute(new CheckedRunnable() {
    406                     public void realRun() throws InterruptedException {
    407                         threadsStarted.countDown();
    408                         done.await();
    409                         assertEquals(THREADS, p.getLargestPoolSize());
    410                     }});
    411             assertTrue(threadsStarted.await(SMALL_DELAY_MS, MILLISECONDS));
    412             assertEquals(THREADS, p.getLargestPoolSize());
    413         } finally {
    414             done.countDown();
    415             joinPool(p);
    416             assertEquals(THREADS, p.getLargestPoolSize());
    417         }
    418     }
    419 
    420     /**
    421      * getPoolSize increases, but doesn't overestimate, when threads
    422      * become active
    423      */
    424     public void testGetPoolSize() throws InterruptedException {
    425         final ThreadPoolExecutor p = new CustomExecutor(1);
    426         final CountDownLatch threadStarted = new CountDownLatch(1);
    427         final CountDownLatch done = new CountDownLatch(1);
    428         try {
    429             assertEquals(0, p.getPoolSize());
    430             p.execute(new CheckedRunnable() {
    431                 public void realRun() throws InterruptedException {
    432                     threadStarted.countDown();
    433                     assertEquals(1, p.getPoolSize());
    434                     done.await();
    435                 }});
    436             assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
    437             assertEquals(1, p.getPoolSize());
    438         } finally {
    439             done.countDown();
    440             joinPool(p);
    441         }
    442     }
    443 
    444     /**
    445      * getTaskCount increases, but doesn't overestimate, when tasks
    446      * submitted
    447      */
    448     public void testGetTaskCount() throws InterruptedException {
    449         final ThreadPoolExecutor p = new CustomExecutor(1);
    450         final CountDownLatch threadStarted = new CountDownLatch(1);
    451         final CountDownLatch done = new CountDownLatch(1);
    452         final int TASKS = 5;
    453         try {
    454             assertEquals(0, p.getTaskCount());
    455             for (int i = 0; i < TASKS; i++)
    456                 p.execute(new CheckedRunnable() {
    457                     public void realRun() throws InterruptedException {
    458                         threadStarted.countDown();
    459                         done.await();
    460                     }});
    461             assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
    462             assertEquals(TASKS, p.getTaskCount());
    463         } finally {
    464             done.countDown();
    465             joinPool(p);
    466         }
    467     }
    468 
    469     /**
    470      * getThreadFactory returns factory in constructor if not set
    471      */
    472     public void testGetThreadFactory() {
    473         ThreadFactory tf = new SimpleThreadFactory();
    474         CustomExecutor p = new CustomExecutor(1, tf);
    475         assertSame(tf, p.getThreadFactory());
    476         joinPool(p);
    477     }
    478 
    479     /**
    480      * setThreadFactory sets the thread factory returned by getThreadFactory
    481      */
    482     public void testSetThreadFactory() {
    483         ThreadFactory tf = new SimpleThreadFactory();
    484         CustomExecutor p = new CustomExecutor(1);
    485         p.setThreadFactory(tf);
    486         assertSame(tf, p.getThreadFactory());
    487         joinPool(p);
    488     }
    489 
    490     /**
    491      * setThreadFactory(null) throws NPE
    492      */
    493     public void testSetThreadFactoryNull() {
    494         CustomExecutor p = new CustomExecutor(1);
    495         try {
    496             p.setThreadFactory(null);
    497             shouldThrow();
    498         } catch (NullPointerException success) {
    499         } finally {
    500             joinPool(p);
    501         }
    502     }
    503 
    504     /**
    505      * isShutdown is false before shutdown, true after
    506      */
    507     public void testIsShutdown() {
    508         CustomExecutor p = new CustomExecutor(1);
    509         try {
    510             assertFalse(p.isShutdown());
    511         }
    512         finally {
    513             try { p.shutdown(); } catch (SecurityException ok) { return; }
    514         }
    515         assertTrue(p.isShutdown());
    516     }
    517 
    518     /**
    519      * isTerminated is false before termination, true after
    520      */
    521     public void testIsTerminated() throws InterruptedException {
    522         final ThreadPoolExecutor p = new CustomExecutor(1);
    523         final CountDownLatch threadStarted = new CountDownLatch(1);
    524         final CountDownLatch done = new CountDownLatch(1);
    525         assertFalse(p.isTerminated());
    526         try {
    527             p.execute(new CheckedRunnable() {
    528                 public void realRun() throws InterruptedException {
    529                     assertFalse(p.isTerminated());
    530                     threadStarted.countDown();
    531                     done.await();
    532                 }});
    533             assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
    534             assertFalse(p.isTerminating());
    535             done.countDown();
    536         } finally {
    537             try { p.shutdown(); } catch (SecurityException ok) { return; }
    538         }
    539         assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
    540         assertTrue(p.isTerminated());
    541     }
    542 
    543     /**
    544      * isTerminating is not true when running or when terminated
    545      */
    546     public void testIsTerminating() throws InterruptedException {
    547         final ThreadPoolExecutor p = new CustomExecutor(1);
    548         final CountDownLatch threadStarted = new CountDownLatch(1);
    549         final CountDownLatch done = new CountDownLatch(1);
    550         try {
    551             assertFalse(p.isTerminating());
    552             p.execute(new CheckedRunnable() {
    553                 public void realRun() throws InterruptedException {
    554                     assertFalse(p.isTerminating());
    555                     threadStarted.countDown();
    556                     done.await();
    557                 }});
    558             assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
    559             assertFalse(p.isTerminating());
    560             done.countDown();
    561         } finally {
    562             try { p.shutdown(); } catch (SecurityException ok) { return; }
    563         }
    564         assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
    565         assertTrue(p.isTerminated());
    566         assertFalse(p.isTerminating());
    567     }
    568 
    569     /**
    570      * getQueue returns the work queue, which contains queued tasks
    571      */
    572     public void testGetQueue() throws InterruptedException {
    573         ScheduledThreadPoolExecutor p = new CustomExecutor(1);
    574         final CountDownLatch threadStarted = new CountDownLatch(1);
    575         final CountDownLatch done = new CountDownLatch(1);
    576         try {
    577             ScheduledFuture[] tasks = new ScheduledFuture[5];
    578             for (int i = 0; i < tasks.length; i++) {
    579                 Runnable r = new CheckedRunnable() {
    580                     public void realRun() throws InterruptedException {
    581                         threadStarted.countDown();
    582                         done.await();
    583                     }};
    584                 tasks[i] = p.schedule(r, 1, MILLISECONDS);
    585             }
    586             assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
    587             BlockingQueue<Runnable> q = p.getQueue();
    588             assertTrue(q.contains(tasks[tasks.length - 1]));
    589             assertFalse(q.contains(tasks[0]));
    590         } finally {
    591             done.countDown();
    592             joinPool(p);
    593         }
    594     }
    595 
    596     /**
    597      * remove(task) removes queued task, and fails to remove active task
    598      */
    599     public void testRemove() throws InterruptedException {
    600         final ScheduledThreadPoolExecutor p = new CustomExecutor(1);
    601         ScheduledFuture[] tasks = new ScheduledFuture[5];
    602         final CountDownLatch threadStarted = new CountDownLatch(1);
    603         final CountDownLatch done = new CountDownLatch(1);
    604         try {
    605             for (int i = 0; i < tasks.length; i++) {
    606                 Runnable r = new CheckedRunnable() {
    607                     public void realRun() throws InterruptedException {
    608                         threadStarted.countDown();
    609                         done.await();
    610                     }};
    611                 tasks[i] = p.schedule(r, 1, MILLISECONDS);
    612             }
    613             assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
    614             BlockingQueue<Runnable> q = p.getQueue();
    615             assertFalse(p.remove((Runnable)tasks[0]));
    616             assertTrue(q.contains((Runnable)tasks[4]));
    617             assertTrue(q.contains((Runnable)tasks[3]));
    618             assertTrue(p.remove((Runnable)tasks[4]));
    619             assertFalse(p.remove((Runnable)tasks[4]));
    620             assertFalse(q.contains((Runnable)tasks[4]));
    621             assertTrue(q.contains((Runnable)tasks[3]));
    622             assertTrue(p.remove((Runnable)tasks[3]));
    623             assertFalse(q.contains((Runnable)tasks[3]));
    624         } finally {
    625             done.countDown();
    626             joinPool(p);
    627         }
    628     }
    629 
    630     /**
    631      * purge removes cancelled tasks from the queue
    632      */
    633     public void testPurge() throws InterruptedException {
    634         CustomExecutor p = new CustomExecutor(1);
    635         ScheduledFuture[] tasks = new ScheduledFuture[5];
    636         for (int i = 0; i < tasks.length; i++)
    637             tasks[i] = p.schedule(new SmallPossiblyInterruptedRunnable(),
    638                                   LONG_DELAY_MS, MILLISECONDS);
    639         try {
    640             int max = tasks.length;
    641             if (tasks[4].cancel(true)) --max;
    642             if (tasks[3].cancel(true)) --max;
    643             // There must eventually be an interference-free point at
    644             // which purge will not fail. (At worst, when queue is empty.)
    645             long startTime = System.nanoTime();
    646             do {
    647                 p.purge();
    648                 long count = p.getTaskCount();
    649                 if (count == max)
    650                     return;
    651             } while (millisElapsedSince(startTime) < MEDIUM_DELAY_MS);
    652             fail("Purge failed to remove cancelled tasks");
    653         } finally {
    654             for (ScheduledFuture task : tasks)
    655                 task.cancel(true);
    656             joinPool(p);
    657         }
    658     }
    659 
    660     /**
    661      * shutdownNow returns a list containing tasks that were not run
    662      */
    663     public void testShutdownNow() {
    664         CustomExecutor p = new CustomExecutor(1);
    665         for (int i = 0; i < 5; i++)
    666             p.schedule(new SmallPossiblyInterruptedRunnable(),
    667                        LONG_DELAY_MS, MILLISECONDS);
    668         try {
    669             List<Runnable> l = p.shutdownNow();
    670             assertTrue(p.isShutdown());
    671             assertEquals(5, l.size());
    672         } catch (SecurityException ok) {
    673             // Allowed in case test doesn't have privs
    674         } finally {
    675             joinPool(p);
    676         }
    677     }
    678 
    679     /**
    680      * In default setting, shutdown cancels periodic but not delayed
    681      * tasks at shutdown
    682      */
    683     public void testShutdown1() throws InterruptedException {
    684         CustomExecutor p = new CustomExecutor(1);
    685         assertTrue(p.getExecuteExistingDelayedTasksAfterShutdownPolicy());
    686         assertFalse(p.getContinueExistingPeriodicTasksAfterShutdownPolicy());
    687 
    688         ScheduledFuture[] tasks = new ScheduledFuture[5];
    689         for (int i = 0; i < tasks.length; i++)
    690             tasks[i] = p.schedule(new NoOpRunnable(),
    691                                   SHORT_DELAY_MS, MILLISECONDS);
    692         try { p.shutdown(); } catch (SecurityException ok) { return; }
    693         BlockingQueue<Runnable> q = p.getQueue();
    694         for (ScheduledFuture task : tasks) {
    695             assertFalse(task.isDone());
    696             assertFalse(task.isCancelled());
    697             assertTrue(q.contains(task));
    698         }
    699         assertTrue(p.isShutdown());
    700         assertTrue(p.awaitTermination(SMALL_DELAY_MS, MILLISECONDS));
    701         assertTrue(p.isTerminated());
    702         for (ScheduledFuture task : tasks) {
    703             assertTrue(task.isDone());
    704             assertFalse(task.isCancelled());
    705         }
    706     }
    707 
    708     /**
    709      * If setExecuteExistingDelayedTasksAfterShutdownPolicy is false,
    710      * delayed tasks are cancelled at shutdown
    711      */
    712     public void testShutdown2() throws InterruptedException {
    713         CustomExecutor p = new CustomExecutor(1);
    714         p.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
    715         assertFalse(p.getExecuteExistingDelayedTasksAfterShutdownPolicy());
    716         assertFalse(p.getContinueExistingPeriodicTasksAfterShutdownPolicy());
    717         ScheduledFuture[] tasks = new ScheduledFuture[5];
    718         for (int i = 0; i < tasks.length; i++)
    719             tasks[i] = p.schedule(new NoOpRunnable(),
    720                                   SHORT_DELAY_MS, MILLISECONDS);
    721         BlockingQueue q = p.getQueue();
    722         assertEquals(tasks.length, q.size());
    723         try { p.shutdown(); } catch (SecurityException ok) { return; }
    724         assertTrue(p.isShutdown());
    725         assertTrue(q.isEmpty());
    726         assertTrue(p.awaitTermination(SMALL_DELAY_MS, MILLISECONDS));
    727         assertTrue(p.isTerminated());
    728         for (ScheduledFuture task : tasks) {
    729             assertTrue(task.isDone());
    730             assertTrue(task.isCancelled());
    731         }
    732     }
    733 
    734     /**
    735      * If setContinueExistingPeriodicTasksAfterShutdownPolicy is set false,
    736      * periodic tasks are cancelled at shutdown
    737      */
    738     public void testShutdown3() throws InterruptedException {
    739         CustomExecutor p = new CustomExecutor(1);
    740         assertTrue(p.getExecuteExistingDelayedTasksAfterShutdownPolicy());
    741         assertFalse(p.getContinueExistingPeriodicTasksAfterShutdownPolicy());
    742         p.setContinueExistingPeriodicTasksAfterShutdownPolicy(false);
    743         assertTrue(p.getExecuteExistingDelayedTasksAfterShutdownPolicy());
    744         assertFalse(p.getContinueExistingPeriodicTasksAfterShutdownPolicy());
    745         long initialDelay = LONG_DELAY_MS;
    746         ScheduledFuture task =
    747             p.scheduleAtFixedRate(new NoOpRunnable(), initialDelay,
    748                                   5, MILLISECONDS);
    749         try { p.shutdown(); } catch (SecurityException ok) { return; }
    750         assertTrue(p.isShutdown());
    751         assertTrue(p.getQueue().isEmpty());
    752         assertTrue(task.isDone());
    753         assertTrue(task.isCancelled());
    754         joinPool(p);
    755     }
    756 
    757     /**
    758      * if setContinueExistingPeriodicTasksAfterShutdownPolicy is true,
    759      * periodic tasks are not cancelled at shutdown
    760      */
    761     public void testShutdown4() throws InterruptedException {
    762         CustomExecutor p = new CustomExecutor(1);
    763         final CountDownLatch counter = new CountDownLatch(2);
    764         try {
    765             p.setContinueExistingPeriodicTasksAfterShutdownPolicy(true);
    766             assertTrue(p.getExecuteExistingDelayedTasksAfterShutdownPolicy());
    767             assertTrue(p.getContinueExistingPeriodicTasksAfterShutdownPolicy());
    768             final Runnable r = new CheckedRunnable() {
    769                 public void realRun() {
    770                     counter.countDown();
    771                 }};
    772             ScheduledFuture task =
    773                 p.scheduleAtFixedRate(r, 1, 1, MILLISECONDS);
    774             assertFalse(task.isDone());
    775             assertFalse(task.isCancelled());
    776             try { p.shutdown(); } catch (SecurityException ok) { return; }
    777             assertFalse(task.isCancelled());
    778             assertFalse(p.isTerminated());
    779             assertTrue(p.isShutdown());
    780             assertTrue(counter.await(SMALL_DELAY_MS, MILLISECONDS));
    781             assertFalse(task.isCancelled());
    782             assertTrue(task.cancel(false));
    783             assertTrue(task.isDone());
    784             assertTrue(task.isCancelled());
    785             assertTrue(p.awaitTermination(SMALL_DELAY_MS, MILLISECONDS));
    786             assertTrue(p.isTerminated());
    787         }
    788         finally {
    789             joinPool(p);
    790         }
    791     }
    792 
    793     /**
    794      * completed submit of callable returns result
    795      */
    796     public void testSubmitCallable() throws Exception {
    797         ExecutorService e = new CustomExecutor(2);
    798         try {
    799             Future<String> future = e.submit(new StringTask());
    800             String result = future.get();
    801             assertSame(TEST_STRING, result);
    802         } finally {
    803             joinPool(e);
    804         }
    805     }
    806 
    807     /**
    808      * completed submit of runnable returns successfully
    809      */
    810     public void testSubmitRunnable() throws Exception {
    811         ExecutorService e = new CustomExecutor(2);
    812         try {
    813             Future<?> future = e.submit(new NoOpRunnable());
    814             future.get();
    815             assertTrue(future.isDone());
    816         } finally {
    817             joinPool(e);
    818         }
    819     }
    820 
    821     /**
    822      * completed submit of (runnable, result) returns result
    823      */
    824     public void testSubmitRunnable2() throws Exception {
    825         ExecutorService e = new CustomExecutor(2);
    826         try {
    827             Future<String> future = e.submit(new NoOpRunnable(), TEST_STRING);
    828             String result = future.get();
    829             assertSame(TEST_STRING, result);
    830         } finally {
    831             joinPool(e);
    832         }
    833     }
    834 
    835     /**
    836      * invokeAny(null) throws NPE
    837      */
    838     public void testInvokeAny1() throws Exception {
    839         ExecutorService e = new CustomExecutor(2);
    840         try {
    841             e.invokeAny(null);
    842             shouldThrow();
    843         } catch (NullPointerException success) {
    844         } finally {
    845             joinPool(e);
    846         }
    847     }
    848 
    849     /**
    850      * invokeAny(empty collection) throws IAE
    851      */
    852     public void testInvokeAny2() throws Exception {
    853         ExecutorService e = new CustomExecutor(2);
    854         try {
    855             e.invokeAny(new ArrayList<Callable<String>>());
    856             shouldThrow();
    857         } catch (IllegalArgumentException success) {
    858         } finally {
    859             joinPool(e);
    860         }
    861     }
    862 
    863     /**
    864      * invokeAny(c) throws NPE if c has null elements
    865      */
    866     public void testInvokeAny3() throws Exception {
    867         CountDownLatch latch = new CountDownLatch(1);
    868         ExecutorService e = new CustomExecutor(2);
    869         List<Callable<String>> l = new ArrayList<Callable<String>>();
    870         l.add(latchAwaitingStringTask(latch));
    871         l.add(null);
    872         try {
    873             e.invokeAny(l);
    874             shouldThrow();
    875         } catch (NullPointerException success) {
    876         } finally {
    877             latch.countDown();
    878             joinPool(e);
    879         }
    880     }
    881 
    882     /**
    883      * invokeAny(c) throws ExecutionException if no task completes
    884      */
    885     public void testInvokeAny4() throws Exception {
    886         ExecutorService e = new CustomExecutor(2);
    887         List<Callable<String>> l = new ArrayList<Callable<String>>();
    888         l.add(new NPETask());
    889         try {
    890             e.invokeAny(l);
    891             shouldThrow();
    892         } catch (ExecutionException success) {
    893             assertTrue(success.getCause() instanceof NullPointerException);
    894         } finally {
    895             joinPool(e);
    896         }
    897     }
    898 
    899     /**
    900      * invokeAny(c) returns result of some task
    901      */
    902     public void testInvokeAny5() throws Exception {
    903         ExecutorService e = new CustomExecutor(2);
    904         try {
    905             List<Callable<String>> l = new ArrayList<Callable<String>>();
    906             l.add(new StringTask());
    907             l.add(new StringTask());
    908             String result = e.invokeAny(l);
    909             assertSame(TEST_STRING, result);
    910         } finally {
    911             joinPool(e);
    912         }
    913     }
    914 
    915     /**
    916      * invokeAll(null) throws NPE
    917      */
    918     public void testInvokeAll1() throws Exception {
    919         ExecutorService e = new CustomExecutor(2);
    920         try {
    921             e.invokeAll(null);
    922             shouldThrow();
    923         } catch (NullPointerException success) {
    924         } finally {
    925             joinPool(e);
    926         }
    927     }
    928 
    929     /**
    930      * invokeAll(empty collection) returns empty collection
    931      */
    932     public void testInvokeAll2() throws Exception {
    933         ExecutorService e = new CustomExecutor(2);
    934         try {
    935             List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>());
    936             assertTrue(r.isEmpty());
    937         } finally {
    938             joinPool(e);
    939         }
    940     }
    941 
    942     /**
    943      * invokeAll(c) throws NPE if c has null elements
    944      */
    945     public void testInvokeAll3() throws Exception {
    946         ExecutorService e = new CustomExecutor(2);
    947         List<Callable<String>> l = new ArrayList<Callable<String>>();
    948         l.add(new StringTask());
    949         l.add(null);
    950         try {
    951             e.invokeAll(l);
    952             shouldThrow();
    953         } catch (NullPointerException success) {
    954         } finally {
    955             joinPool(e);
    956         }
    957     }
    958 
    959     /**
    960      * get of invokeAll(c) throws exception on failed task
    961      */
    962     public void testInvokeAll4() throws Exception {
    963         ExecutorService e = new CustomExecutor(2);
    964         List<Callable<String>> l = new ArrayList<Callable<String>>();
    965         l.add(new NPETask());
    966         List<Future<String>> futures = e.invokeAll(l);
    967         assertEquals(1, futures.size());
    968         try {
    969             futures.get(0).get();
    970             shouldThrow();
    971         } catch (ExecutionException success) {
    972             assertTrue(success.getCause() instanceof NullPointerException);
    973         } finally {
    974             joinPool(e);
    975         }
    976     }
    977 
    978     /**
    979      * invokeAll(c) returns results of all completed tasks
    980      */
    981     public void testInvokeAll5() throws Exception {
    982         ExecutorService e = new CustomExecutor(2);
    983         try {
    984             List<Callable<String>> l = new ArrayList<Callable<String>>();
    985             l.add(new StringTask());
    986             l.add(new StringTask());
    987             List<Future<String>> futures = e.invokeAll(l);
    988             assertEquals(2, futures.size());
    989             for (Future<String> future : futures)
    990                 assertSame(TEST_STRING, future.get());
    991         } finally {
    992             joinPool(e);
    993         }
    994     }
    995 
    996     /**
    997      * timed invokeAny(null) throws NPE
    998      */
    999     public void testTimedInvokeAny1() throws Exception {
   1000         ExecutorService e = new CustomExecutor(2);
   1001         try {
   1002             e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS);
   1003             shouldThrow();
   1004         } catch (NullPointerException success) {
   1005         } finally {
   1006             joinPool(e);
   1007         }
   1008     }
   1009 
   1010     /**
   1011      * timed invokeAny(,,null) throws NPE
   1012      */
   1013     public void testTimedInvokeAnyNullTimeUnit() throws Exception {
   1014         ExecutorService e = new CustomExecutor(2);
   1015         List<Callable<String>> l = new ArrayList<Callable<String>>();
   1016         l.add(new StringTask());
   1017         try {
   1018             e.invokeAny(l, MEDIUM_DELAY_MS, null);
   1019             shouldThrow();
   1020         } catch (NullPointerException success) {
   1021         } finally {
   1022             joinPool(e);
   1023         }
   1024     }
   1025 
   1026     /**
   1027      * timed invokeAny(empty collection) throws IAE
   1028      */
   1029     public void testTimedInvokeAny2() throws Exception {
   1030         ExecutorService e = new CustomExecutor(2);
   1031         try {
   1032             e.invokeAny(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);
   1033             shouldThrow();
   1034         } catch (IllegalArgumentException success) {
   1035         } finally {
   1036             joinPool(e);
   1037         }
   1038     }
   1039 
   1040     /**
   1041      * timed invokeAny(c) throws NPE if c has null elements
   1042      */
   1043     public void testTimedInvokeAny3() throws Exception {
   1044         CountDownLatch latch = new CountDownLatch(1);
   1045         ExecutorService e = new CustomExecutor(2);
   1046         List<Callable<String>> l = new ArrayList<Callable<String>>();
   1047         l.add(latchAwaitingStringTask(latch));
   1048         l.add(null);
   1049         try {
   1050             e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
   1051             shouldThrow();
   1052         } catch (NullPointerException success) {
   1053         } finally {
   1054             latch.countDown();
   1055             joinPool(e);
   1056         }
   1057     }
   1058 
   1059     /**
   1060      * timed invokeAny(c) throws ExecutionException if no task completes
   1061      */
   1062     public void testTimedInvokeAny4() throws Exception {
   1063         ExecutorService e = new CustomExecutor(2);
   1064         List<Callable<String>> l = new ArrayList<Callable<String>>();
   1065         l.add(new NPETask());
   1066         try {
   1067             e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
   1068             shouldThrow();
   1069         } catch (ExecutionException success) {
   1070             assertTrue(success.getCause() instanceof NullPointerException);
   1071         } finally {
   1072             joinPool(e);
   1073         }
   1074     }
   1075 
   1076     /**
   1077      * timed invokeAny(c) returns result of some task
   1078      */
   1079     public void testTimedInvokeAny5() throws Exception {
   1080         ExecutorService e = new CustomExecutor(2);
   1081         try {
   1082             List<Callable<String>> l = new ArrayList<Callable<String>>();
   1083             l.add(new StringTask());
   1084             l.add(new StringTask());
   1085             String result = e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
   1086             assertSame(TEST_STRING, result);
   1087         } finally {
   1088             joinPool(e);
   1089         }
   1090     }
   1091 
   1092     /**
   1093      * timed invokeAll(null) throws NPE
   1094      */
   1095     public void testTimedInvokeAll1() throws Exception {
   1096         ExecutorService e = new CustomExecutor(2);
   1097         try {
   1098             e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS);
   1099             shouldThrow();
   1100         } catch (NullPointerException success) {
   1101         } finally {
   1102             joinPool(e);
   1103         }
   1104     }
   1105 
   1106     /**
   1107      * timed invokeAll(,,null) throws NPE
   1108      */
   1109     public void testTimedInvokeAllNullTimeUnit() throws Exception {
   1110         ExecutorService e = new CustomExecutor(2);
   1111         List<Callable<String>> l = new ArrayList<Callable<String>>();
   1112         l.add(new StringTask());
   1113         try {
   1114             e.invokeAll(l, MEDIUM_DELAY_MS, null);
   1115             shouldThrow();
   1116         } catch (NullPointerException success) {
   1117         } finally {
   1118             joinPool(e);
   1119         }
   1120     }
   1121 
   1122     /**
   1123      * timed invokeAll(empty collection) returns empty collection
   1124      */
   1125     public void testTimedInvokeAll2() throws Exception {
   1126         ExecutorService e = new CustomExecutor(2);
   1127         try {
   1128             List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);
   1129             assertTrue(r.isEmpty());
   1130         } finally {
   1131             joinPool(e);
   1132         }
   1133     }
   1134 
   1135     /**
   1136      * timed invokeAll(c) throws NPE if c has null elements
   1137      */
   1138     public void testTimedInvokeAll3() throws Exception {
   1139         ExecutorService e = new CustomExecutor(2);
   1140         List<Callable<String>> l = new ArrayList<Callable<String>>();
   1141         l.add(new StringTask());
   1142         l.add(null);
   1143         try {
   1144             e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
   1145             shouldThrow();
   1146         } catch (NullPointerException success) {
   1147         } finally {
   1148             joinPool(e);
   1149         }
   1150     }
   1151 
   1152     /**
   1153      * get of element of invokeAll(c) throws exception on failed task
   1154      */
   1155     public void testTimedInvokeAll4() throws Exception {
   1156         ExecutorService e = new CustomExecutor(2);
   1157         List<Callable<String>> l = new ArrayList<Callable<String>>();
   1158         l.add(new NPETask());
   1159         List<Future<String>> futures =
   1160             e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
   1161         assertEquals(1, futures.size());
   1162         try {
   1163             futures.get(0).get();
   1164             shouldThrow();
   1165         } catch (ExecutionException success) {
   1166             assertTrue(success.getCause() instanceof NullPointerException);
   1167         } finally {
   1168             joinPool(e);
   1169         }
   1170     }
   1171 
   1172     /**
   1173      * timed invokeAll(c) returns results of all completed tasks
   1174      */
   1175     public void testTimedInvokeAll5() throws Exception {
   1176         ExecutorService e = new CustomExecutor(2);
   1177         try {
   1178             List<Callable<String>> l = new ArrayList<Callable<String>>();
   1179             l.add(new StringTask());
   1180             l.add(new StringTask());
   1181             List<Future<String>> futures =
   1182                 e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
   1183             assertEquals(2, futures.size());
   1184             for (Future<String> future : futures)
   1185                 assertSame(TEST_STRING, future.get());
   1186         } finally {
   1187             joinPool(e);
   1188         }
   1189     }
   1190 
   1191     /**
   1192      * timed invokeAll(c) cancels tasks not completed by timeout
   1193      */
   1194     public void testTimedInvokeAll6() throws Exception {
   1195         ExecutorService e = new CustomExecutor(2);
   1196         try {
   1197             List<Callable<String>> l = new ArrayList<Callable<String>>();
   1198             l.add(new StringTask());
   1199             l.add(Executors.callable(new MediumPossiblyInterruptedRunnable(), TEST_STRING));
   1200             l.add(new StringTask());
   1201             List<Future<String>> futures =
   1202                 e.invokeAll(l, SHORT_DELAY_MS, MILLISECONDS);
   1203             assertEquals(l.size(), futures.size());
   1204             for (Future future : futures)
   1205                 assertTrue(future.isDone());
   1206             assertFalse(futures.get(0).isCancelled());
   1207             assertTrue(futures.get(1).isCancelled());
   1208         } finally {
   1209             joinPool(e);
   1210         }
   1211     }
   1212 
   1213 }
   1214