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 static java.util.concurrent.TimeUnit.MILLISECONDS;
     12 
     13 import java.security.PrivilegedAction;
     14 import java.security.PrivilegedExceptionAction;
     15 import java.util.ArrayList;
     16 import java.util.Collections;
     17 import java.util.List;
     18 import java.util.concurrent.AbstractExecutorService;
     19 import java.util.concurrent.ArrayBlockingQueue;
     20 import java.util.concurrent.Callable;
     21 import java.util.concurrent.CancellationException;
     22 import java.util.concurrent.CountDownLatch;
     23 import java.util.concurrent.ExecutionException;
     24 import java.util.concurrent.Executors;
     25 import java.util.concurrent.ExecutorService;
     26 import java.util.concurrent.Future;
     27 import java.util.concurrent.ThreadPoolExecutor;
     28 import java.util.concurrent.TimeUnit;
     29 import java.util.concurrent.atomic.AtomicBoolean;
     30 
     31 import junit.framework.Test;
     32 import junit.framework.TestSuite;
     33 
     34 public class AbstractExecutorServiceTest extends JSR166TestCase {
     35     // android-note: Removed because the CTS runner does a bad job of
     36     // retrying tests that have suite() declarations.
     37     //
     38     // public static void main(String[] args) {
     39     //     main(suite(), args);
     40     // }
     41     // public static Test suite() {
     42     //     return new TestSuite(AbstractExecutorServiceTest.class);
     43     // }
     44 
     45     /**
     46      * A no-frills implementation of AbstractExecutorService, designed
     47      * to test the submit methods only.
     48      */
     49     static class DirectExecutorService extends AbstractExecutorService {
     50         public void execute(Runnable r) { r.run(); }
     51         public void shutdown() { shutdown = true; }
     52         public List<Runnable> shutdownNow() {
     53             shutdown = true;
     54             return Collections.EMPTY_LIST;
     55         }
     56         public boolean isShutdown() { return shutdown; }
     57         public boolean isTerminated() { return isShutdown(); }
     58         public boolean awaitTermination(long timeout, TimeUnit unit) {
     59             return isShutdown();
     60         }
     61         private volatile boolean shutdown = false;
     62     }
     63 
     64     /**
     65      * execute(runnable) runs it to completion
     66      */
     67     public void testExecuteRunnable() throws Exception {
     68         ExecutorService e = new DirectExecutorService();
     69         final AtomicBoolean done = new AtomicBoolean(false);
     70         Future<?> future = e.submit(new CheckedRunnable() {
     71             public void realRun() {
     72                 done.set(true);
     73             }});
     74         assertNull(future.get());
     75         assertNull(future.get(0, MILLISECONDS));
     76         assertTrue(done.get());
     77         assertTrue(future.isDone());
     78         assertFalse(future.isCancelled());
     79     }
     80 
     81     /**
     82      * Completed submit(callable) returns result
     83      */
     84     public void testSubmitCallable() throws Exception {
     85         ExecutorService e = new DirectExecutorService();
     86         Future<String> future = e.submit(new StringTask());
     87         String result = future.get();
     88         assertSame(TEST_STRING, result);
     89     }
     90 
     91     /**
     92      * Completed submit(runnable) returns successfully
     93      */
     94     public void testSubmitRunnable() throws Exception {
     95         ExecutorService e = new DirectExecutorService();
     96         Future<?> future = e.submit(new NoOpRunnable());
     97         future.get();
     98         assertTrue(future.isDone());
     99     }
    100 
    101     /**
    102      * Completed submit(runnable, result) returns result
    103      */
    104     public void testSubmitRunnable2() throws Exception {
    105         ExecutorService e = new DirectExecutorService();
    106         Future<String> future = e.submit(new NoOpRunnable(), TEST_STRING);
    107         String result = future.get();
    108         assertSame(TEST_STRING, result);
    109     }
    110 
    111     /**
    112      * A submitted privileged action runs to completion
    113      */
    114     public void testSubmitPrivilegedAction() throws Exception {
    115         Runnable r = new CheckedRunnable() {
    116             public void realRun() throws Exception {
    117                 ExecutorService e = new DirectExecutorService();
    118                 Future future = e.submit(Executors.callable(new PrivilegedAction() {
    119                     public Object run() {
    120                         return TEST_STRING;
    121                     }}));
    122 
    123                 assertSame(TEST_STRING, future.get());
    124             }};
    125 
    126         runWithPermissions(r,
    127                            new RuntimePermission("getClassLoader"),
    128                            new RuntimePermission("setContextClassLoader"),
    129                            new RuntimePermission("modifyThread"));
    130     }
    131 
    132     /**
    133      * A submitted privileged exception action runs to completion
    134      */
    135     public void testSubmitPrivilegedExceptionAction() throws Exception {
    136         Runnable r = new CheckedRunnable() {
    137             public void realRun() throws Exception {
    138                 ExecutorService e = new DirectExecutorService();
    139                 Future future = e.submit(Executors.callable(new PrivilegedExceptionAction() {
    140                     public Object run() {
    141                         return TEST_STRING;
    142                     }}));
    143 
    144                 assertSame(TEST_STRING, future.get());
    145             }};
    146 
    147         runWithPermissions(r);
    148     }
    149 
    150     /**
    151      * A submitted failed privileged exception action reports exception
    152      */
    153     public void testSubmitFailedPrivilegedExceptionAction() throws Exception {
    154         Runnable r = new CheckedRunnable() {
    155             public void realRun() throws Exception {
    156                 ExecutorService e = new DirectExecutorService();
    157                 Future future = e.submit(Executors.callable(new PrivilegedExceptionAction() {
    158                     public Object run() throws Exception {
    159                         throw new IndexOutOfBoundsException();
    160                     }}));
    161 
    162                 try {
    163                     future.get();
    164                     shouldThrow();
    165                 } catch (ExecutionException success) {
    166                     assertTrue(success.getCause() instanceof IndexOutOfBoundsException);
    167                 }}};
    168 
    169         runWithPermissions(r);
    170     }
    171 
    172     /**
    173      * execute(null runnable) throws NPE
    174      */
    175     public void testExecuteNullRunnable() {
    176         ExecutorService e = new DirectExecutorService();
    177         try {
    178             e.submit((Runnable) null);
    179             shouldThrow();
    180         } catch (NullPointerException success) {}
    181     }
    182 
    183     /**
    184      * submit(null callable) throws NPE
    185      */
    186     public void testSubmitNullCallable() {
    187         ExecutorService e = new DirectExecutorService();
    188         try {
    189             e.submit((Callable) null);
    190             shouldThrow();
    191         } catch (NullPointerException success) {}
    192     }
    193 
    194     /**
    195      * submit(callable).get() throws InterruptedException if interrupted
    196      */
    197     public void testInterruptedSubmit() throws InterruptedException {
    198         final CountDownLatch submitted    = new CountDownLatch(1);
    199         final CountDownLatch quittingTime = new CountDownLatch(1);
    200         final Callable<Void> awaiter = new CheckedCallable<Void>() {
    201             public Void realCall() throws InterruptedException {
    202                 assertTrue(quittingTime.await(2*LONG_DELAY_MS, MILLISECONDS));
    203                 return null;
    204             }};
    205         final ExecutorService p
    206             = new ThreadPoolExecutor(1,1,60, TimeUnit.SECONDS,
    207                                      new ArrayBlockingQueue<Runnable>(10));
    208         try (PoolCleaner cleaner = cleaner(p, quittingTime)) {
    209             Thread t = newStartedThread(new CheckedInterruptedRunnable() {
    210                 public void realRun() throws Exception {
    211                     Future<Void> future = p.submit(awaiter);
    212                     submitted.countDown();
    213                     future.get();
    214                 }});
    215 
    216             await(submitted);
    217             t.interrupt();
    218             awaitTermination(t);
    219         }
    220     }
    221 
    222     /**
    223      * get of submit(callable) throws ExecutionException if callable
    224      * throws exception
    225      */
    226     public void testSubmitEE() throws InterruptedException {
    227         final ThreadPoolExecutor p =
    228             new ThreadPoolExecutor(1, 1,
    229                                    60, TimeUnit.SECONDS,
    230                                    new ArrayBlockingQueue<Runnable>(10));
    231         try (PoolCleaner cleaner = cleaner(p)) {
    232             Callable c = new Callable() {
    233                 public Object call() { throw new ArithmeticException(); }};
    234             try {
    235                 p.submit(c).get();
    236                 shouldThrow();
    237             } catch (ExecutionException success) {
    238                 assertTrue(success.getCause() instanceof ArithmeticException);
    239             }
    240         }
    241     }
    242 
    243     /**
    244      * invokeAny(null) throws NPE
    245      */
    246     public void testInvokeAny1() throws Exception {
    247         final ExecutorService e = new DirectExecutorService();
    248         try (PoolCleaner cleaner = cleaner(e)) {
    249             try {
    250                 e.invokeAny(null);
    251                 shouldThrow();
    252             } catch (NullPointerException success) {}
    253         }
    254     }
    255 
    256     /**
    257      * invokeAny(empty collection) throws IAE
    258      */
    259     public void testInvokeAny2() throws Exception {
    260         final ExecutorService e = new DirectExecutorService();
    261         try (PoolCleaner cleaner = cleaner(e)) {
    262             try {
    263                 e.invokeAny(new ArrayList<Callable<String>>());
    264                 shouldThrow();
    265             } catch (IllegalArgumentException success) {}
    266         }
    267     }
    268 
    269     /**
    270      * invokeAny(c) throws NPE if c has null elements
    271      */
    272     public void testInvokeAny3() throws Exception {
    273         final ExecutorService e = new DirectExecutorService();
    274         try (PoolCleaner cleaner = cleaner(e)) {
    275             List<Callable<Long>> l = new ArrayList<Callable<Long>>();
    276             l.add(new Callable<Long>() {
    277                       public Long call() { throw new ArithmeticException(); }});
    278             l.add(null);
    279             try {
    280                 e.invokeAny(l);
    281                 shouldThrow();
    282             } catch (NullPointerException success) {}
    283         }
    284     }
    285 
    286     /**
    287      * invokeAny(c) throws ExecutionException if no task in c completes
    288      */
    289     public void testInvokeAny4() throws InterruptedException {
    290         final ExecutorService e = new DirectExecutorService();
    291         try (PoolCleaner cleaner = cleaner(e)) {
    292             List<Callable<String>> l = new ArrayList<Callable<String>>();
    293             l.add(new NPETask());
    294             try {
    295                 e.invokeAny(l);
    296                 shouldThrow();
    297             } catch (ExecutionException success) {
    298                 assertTrue(success.getCause() instanceof NullPointerException);
    299             }
    300         }
    301     }
    302 
    303     /**
    304      * invokeAny(c) returns result of some task in c if at least one completes
    305      */
    306     public void testInvokeAny5() throws Exception {
    307         final ExecutorService e = new DirectExecutorService();
    308         try (PoolCleaner cleaner = cleaner(e)) {
    309             List<Callable<String>> l = new ArrayList<Callable<String>>();
    310             l.add(new StringTask());
    311             l.add(new StringTask());
    312             String result = e.invokeAny(l);
    313             assertSame(TEST_STRING, result);
    314         }
    315     }
    316 
    317     /**
    318      * invokeAll(null) throws NPE
    319      */
    320     public void testInvokeAll1() throws InterruptedException {
    321         final ExecutorService e = new DirectExecutorService();
    322         try (PoolCleaner cleaner = cleaner(e)) {
    323             try {
    324                 e.invokeAll(null);
    325                 shouldThrow();
    326             } catch (NullPointerException success) {}
    327         }
    328     }
    329 
    330     /**
    331      * invokeAll(empty collection) returns empty collection
    332      */
    333     public void testInvokeAll2() throws InterruptedException {
    334         final ExecutorService e = new DirectExecutorService();
    335         try (PoolCleaner cleaner = cleaner(e)) {
    336             List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>());
    337             assertTrue(r.isEmpty());
    338         }
    339     }
    340 
    341     /**
    342      * invokeAll(c) throws NPE if c has null elements
    343      */
    344     public void testInvokeAll3() throws InterruptedException {
    345         final ExecutorService e = new DirectExecutorService();
    346         try (PoolCleaner cleaner = cleaner(e)) {
    347             List<Callable<String>> l = new ArrayList<Callable<String>>();
    348             l.add(new StringTask());
    349             l.add(null);
    350             try {
    351                 e.invokeAll(l);
    352                 shouldThrow();
    353             } catch (NullPointerException success) {}
    354         }
    355     }
    356 
    357     /**
    358      * get of returned element of invokeAll(c) throws exception on failed task
    359      */
    360     public void testInvokeAll4() throws Exception {
    361         final ExecutorService e = new DirectExecutorService();
    362         try (PoolCleaner cleaner = cleaner(e)) {
    363             List<Callable<String>> l = new ArrayList<Callable<String>>();
    364             l.add(new NPETask());
    365             List<Future<String>> futures = e.invokeAll(l);
    366             assertEquals(1, futures.size());
    367             try {
    368                 futures.get(0).get();
    369                 shouldThrow();
    370             } catch (ExecutionException success) {
    371                 assertTrue(success.getCause() instanceof NullPointerException);
    372             }
    373         }
    374     }
    375 
    376     /**
    377      * invokeAll(c) returns results of all completed tasks in c
    378      */
    379     public void testInvokeAll5() throws Exception {
    380         final ExecutorService e = new DirectExecutorService();
    381         try (PoolCleaner cleaner = cleaner(e)) {
    382             List<Callable<String>> l = new ArrayList<Callable<String>>();
    383             l.add(new StringTask());
    384             l.add(new StringTask());
    385             List<Future<String>> futures = e.invokeAll(l);
    386             assertEquals(2, futures.size());
    387             for (Future<String> future : futures)
    388                 assertSame(TEST_STRING, future.get());
    389         }
    390     }
    391 
    392     /**
    393      * timed invokeAny(null) throws NPE
    394      */
    395     public void testTimedInvokeAny1() throws Exception {
    396         final ExecutorService e = new DirectExecutorService();
    397         try (PoolCleaner cleaner = cleaner(e)) {
    398             try {
    399                 e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS);
    400                 shouldThrow();
    401             } catch (NullPointerException success) {}
    402         }
    403     }
    404 
    405     /**
    406      * timed invokeAny(null time unit) throws NPE
    407      */
    408     public void testTimedInvokeAnyNullTimeUnit() throws Exception {
    409         final ExecutorService e = new DirectExecutorService();
    410         try (PoolCleaner cleaner = cleaner(e)) {
    411             List<Callable<String>> l = new ArrayList<Callable<String>>();
    412             l.add(new StringTask());
    413             try {
    414                 e.invokeAny(l, MEDIUM_DELAY_MS, null);
    415                 shouldThrow();
    416             } catch (NullPointerException success) {}
    417         }
    418     }
    419 
    420     /**
    421      * timed invokeAny(empty collection) throws IAE
    422      */
    423     public void testTimedInvokeAny2() throws Exception {
    424         final ExecutorService e = new DirectExecutorService();
    425         try (PoolCleaner cleaner = cleaner(e)) {
    426             try {
    427                 e.invokeAny(new ArrayList<Callable<String>>(),
    428                             MEDIUM_DELAY_MS, MILLISECONDS);
    429                 shouldThrow();
    430             } catch (IllegalArgumentException success) {}
    431         }
    432     }
    433 
    434     /**
    435      * timed invokeAny(c) throws NPE if c has null elements
    436      */
    437     public void testTimedInvokeAny3() throws Exception {
    438         final ExecutorService e = new DirectExecutorService();
    439         try (PoolCleaner cleaner = cleaner(e)) {
    440             List<Callable<Long>> l = new ArrayList<Callable<Long>>();
    441             l.add(new Callable<Long>() {
    442                       public Long call() { throw new ArithmeticException(); }});
    443             l.add(null);
    444             try {
    445                 e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
    446                 shouldThrow();
    447             } catch (NullPointerException success) {}
    448         }
    449     }
    450 
    451     /**
    452      * timed invokeAny(c) throws ExecutionException if no task completes
    453      */
    454     public void testTimedInvokeAny4() throws Exception {
    455         final ExecutorService e = new DirectExecutorService();
    456         try (PoolCleaner cleaner = cleaner(e)) {
    457             long startTime = System.nanoTime();
    458             List<Callable<String>> l = new ArrayList<Callable<String>>();
    459             l.add(new NPETask());
    460             try {
    461                 e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
    462                 shouldThrow();
    463             } catch (ExecutionException success) {
    464                 assertTrue(success.getCause() instanceof NullPointerException);
    465             }
    466             assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
    467         }
    468     }
    469 
    470     /**
    471      * timed invokeAny(c) returns result of some task in c
    472      */
    473     public void testTimedInvokeAny5() throws Exception {
    474         final ExecutorService e = new DirectExecutorService();
    475         try (PoolCleaner cleaner = cleaner(e)) {
    476             long startTime = System.nanoTime();
    477             List<Callable<String>> l = new ArrayList<Callable<String>>();
    478             l.add(new StringTask());
    479             l.add(new StringTask());
    480             String result = e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
    481             assertSame(TEST_STRING, result);
    482             assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
    483         }
    484     }
    485 
    486     /**
    487      * timed invokeAll(null) throws NPE
    488      */
    489     public void testTimedInvokeAll1() throws InterruptedException {
    490         final ExecutorService e = new DirectExecutorService();
    491         try (PoolCleaner cleaner = cleaner(e)) {
    492             try {
    493                 e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS);
    494                 shouldThrow();
    495             } catch (NullPointerException success) {}
    496         }
    497     }
    498 
    499     /**
    500      * timed invokeAll(null time unit) throws NPE
    501      */
    502     public void testTimedInvokeAllNullTimeUnit() throws InterruptedException {
    503         final ExecutorService e = new DirectExecutorService();
    504         try (PoolCleaner cleaner = cleaner(e)) {
    505             List<Callable<String>> l = new ArrayList<Callable<String>>();
    506             l.add(new StringTask());
    507             try {
    508                 e.invokeAll(l, MEDIUM_DELAY_MS, null);
    509                 shouldThrow();
    510             } catch (NullPointerException success) {}
    511         }
    512     }
    513 
    514     /**
    515      * timed invokeAll(empty collection) returns empty collection
    516      */
    517     public void testTimedInvokeAll2() throws InterruptedException {
    518         final ExecutorService e = new DirectExecutorService();
    519         try (PoolCleaner cleaner = cleaner(e)) {
    520             List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);
    521             assertTrue(r.isEmpty());
    522         }
    523     }
    524 
    525     /**
    526      * timed invokeAll(c) throws NPE if c has null elements
    527      */
    528     public void testTimedInvokeAll3() throws InterruptedException {
    529         final ExecutorService e = new DirectExecutorService();
    530         try (PoolCleaner cleaner = cleaner(e)) {
    531             List<Callable<String>> l = new ArrayList<Callable<String>>();
    532             l.add(new StringTask());
    533             l.add(null);
    534             try {
    535                 e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
    536                 shouldThrow();
    537             } catch (NullPointerException success) {}
    538         }
    539     }
    540 
    541     /**
    542      * get of returned element of invokeAll(c) throws exception on failed task
    543      */
    544     public void testTimedInvokeAll4() throws Exception {
    545         final ExecutorService e = new DirectExecutorService();
    546         try (PoolCleaner cleaner = cleaner(e)) {
    547             List<Callable<String>> l = new ArrayList<Callable<String>>();
    548             l.add(new NPETask());
    549             List<Future<String>> futures =
    550                 e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS);
    551             assertEquals(1, futures.size());
    552             try {
    553                 futures.get(0).get();
    554                 shouldThrow();
    555             } catch (ExecutionException success) {
    556                 assertTrue(success.getCause() instanceof NullPointerException);
    557             }
    558         }
    559     }
    560 
    561     /**
    562      * timed invokeAll(c) returns results of all completed tasks in c
    563      */
    564     public void testTimedInvokeAll5() throws Exception {
    565         final ExecutorService e = new DirectExecutorService();
    566         try (PoolCleaner cleaner = cleaner(e)) {
    567             List<Callable<String>> l = new ArrayList<Callable<String>>();
    568             l.add(new StringTask());
    569             l.add(new StringTask());
    570             List<Future<String>> futures =
    571                 e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS);
    572             assertEquals(2, futures.size());
    573             for (Future<String> future : futures)
    574                 assertSame(TEST_STRING, future.get());
    575         }
    576     }
    577 
    578     /**
    579      * timed invokeAll cancels tasks not completed by timeout
    580      */
    581     public void testTimedInvokeAll6() throws Exception {
    582         final ExecutorService e = new DirectExecutorService();
    583         try (PoolCleaner cleaner = cleaner(e)) {
    584             for (long timeout = timeoutMillis();;) {
    585                 List<Callable<String>> tasks = new ArrayList<>();
    586                 tasks.add(new StringTask("0"));
    587                 tasks.add(Executors.callable(possiblyInterruptedRunnable(timeout),
    588                                              TEST_STRING));
    589                 tasks.add(new StringTask("2"));
    590                 long startTime = System.nanoTime();
    591                 List<Future<String>> futures =
    592                     e.invokeAll(tasks, timeout, MILLISECONDS);
    593                 assertEquals(tasks.size(), futures.size());
    594                 assertTrue(millisElapsedSince(startTime) >= timeout);
    595                 for (Future future : futures)
    596                     assertTrue(future.isDone());
    597                 try {
    598                     assertEquals("0", futures.get(0).get());
    599                     assertEquals(TEST_STRING, futures.get(1).get());
    600                 } catch (CancellationException retryWithLongerTimeout) {
    601                     // unusual delay before starting second task
    602                     timeout *= 2;
    603                     if (timeout >= LONG_DELAY_MS / 2)
    604                         fail("expected exactly one task to be cancelled");
    605                     continue;
    606                 }
    607                 assertTrue(futures.get(2).isCancelled());
    608                 break;
    609             }
    610         }
    611     }
    612 
    613 }
    614