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.AccessControlContext;
     14 import java.security.AccessControlException;
     15 import java.security.AccessController;
     16 import java.security.PrivilegedAction;
     17 import java.security.PrivilegedExceptionAction;
     18 import java.util.ArrayList;
     19 import java.util.List;
     20 import java.util.concurrent.Callable;
     21 import java.util.concurrent.CountDownLatch;
     22 import java.util.concurrent.Executors;
     23 import java.util.concurrent.ExecutorService;
     24 import java.util.concurrent.Future;
     25 import java.util.concurrent.ScheduledExecutorService;
     26 import java.util.concurrent.ThreadPoolExecutor;
     27 
     28 import junit.framework.Test;
     29 import junit.framework.TestSuite;
     30 
     31 public class ExecutorsTest extends JSR166TestCase {
     32     // android-note: Removed because the CTS runner does a bad job of
     33     // retrying tests that have suite() declarations.
     34     //
     35     // public static void main(String[] args) {
     36     //     main(suite(), args);
     37     // }
     38     // public static Test suite() {
     39     //     return new TestSuite(ExecutorsTest.class);
     40     // }
     41 
     42     /**
     43      * A newCachedThreadPool can execute runnables
     44      */
     45     public void testNewCachedThreadPool1() {
     46         final ExecutorService e = Executors.newCachedThreadPool();
     47         try (PoolCleaner cleaner = cleaner(e)) {
     48             e.execute(new NoOpRunnable());
     49             e.execute(new NoOpRunnable());
     50             e.execute(new NoOpRunnable());
     51         }
     52     }
     53 
     54     /**
     55      * A newCachedThreadPool with given ThreadFactory can execute runnables
     56      */
     57     public void testNewCachedThreadPool2() {
     58         final ExecutorService e = Executors.newCachedThreadPool(new SimpleThreadFactory());
     59         try (PoolCleaner cleaner = cleaner(e)) {
     60             e.execute(new NoOpRunnable());
     61             e.execute(new NoOpRunnable());
     62             e.execute(new NoOpRunnable());
     63         }
     64     }
     65 
     66     /**
     67      * A newCachedThreadPool with null ThreadFactory throws NPE
     68      */
     69     public void testNewCachedThreadPool3() {
     70         try {
     71             ExecutorService e = Executors.newCachedThreadPool(null);
     72             shouldThrow();
     73         } catch (NullPointerException success) {}
     74     }
     75 
     76     /**
     77      * A new SingleThreadExecutor can execute runnables
     78      */
     79     public void testNewSingleThreadExecutor1() {
     80         final ExecutorService e = Executors.newSingleThreadExecutor();
     81         try (PoolCleaner cleaner = cleaner(e)) {
     82             e.execute(new NoOpRunnable());
     83             e.execute(new NoOpRunnable());
     84             e.execute(new NoOpRunnable());
     85         }
     86     }
     87 
     88     /**
     89      * A new SingleThreadExecutor with given ThreadFactory can execute runnables
     90      */
     91     public void testNewSingleThreadExecutor2() {
     92         final ExecutorService e = Executors.newSingleThreadExecutor(new SimpleThreadFactory());
     93         try (PoolCleaner cleaner = cleaner(e)) {
     94             e.execute(new NoOpRunnable());
     95             e.execute(new NoOpRunnable());
     96             e.execute(new NoOpRunnable());
     97         }
     98     }
     99 
    100     /**
    101      * A new SingleThreadExecutor with null ThreadFactory throws NPE
    102      */
    103     public void testNewSingleThreadExecutor3() {
    104         try {
    105             ExecutorService e = Executors.newSingleThreadExecutor(null);
    106             shouldThrow();
    107         } catch (NullPointerException success) {}
    108     }
    109 
    110     /**
    111      * A new SingleThreadExecutor cannot be casted to concrete implementation
    112      */
    113     public void testCastNewSingleThreadExecutor() {
    114         final ExecutorService e = Executors.newSingleThreadExecutor();
    115         try (PoolCleaner cleaner = cleaner(e)) {
    116             try {
    117                 ThreadPoolExecutor tpe = (ThreadPoolExecutor)e;
    118                 shouldThrow();
    119             } catch (ClassCastException success) {}
    120         }
    121     }
    122 
    123     /**
    124      * A new newFixedThreadPool can execute runnables
    125      */
    126     public void testNewFixedThreadPool1() {
    127         final ExecutorService e = Executors.newFixedThreadPool(2);
    128         try (PoolCleaner cleaner = cleaner(e)) {
    129             e.execute(new NoOpRunnable());
    130             e.execute(new NoOpRunnable());
    131             e.execute(new NoOpRunnable());
    132         }
    133     }
    134 
    135     /**
    136      * A new newFixedThreadPool with given ThreadFactory can execute runnables
    137      */
    138     public void testNewFixedThreadPool2() {
    139         final ExecutorService e = Executors.newFixedThreadPool(2, new SimpleThreadFactory());
    140         try (PoolCleaner cleaner = cleaner(e)) {
    141             e.execute(new NoOpRunnable());
    142             e.execute(new NoOpRunnable());
    143             e.execute(new NoOpRunnable());
    144         }
    145     }
    146 
    147     /**
    148      * A new newFixedThreadPool with null ThreadFactory throws NPE
    149      */
    150     public void testNewFixedThreadPool3() {
    151         try {
    152             ExecutorService e = Executors.newFixedThreadPool(2, null);
    153             shouldThrow();
    154         } catch (NullPointerException success) {}
    155     }
    156 
    157     /**
    158      * A new newFixedThreadPool with 0 threads throws IAE
    159      */
    160     public void testNewFixedThreadPool4() {
    161         try {
    162             ExecutorService e = Executors.newFixedThreadPool(0);
    163             shouldThrow();
    164         } catch (IllegalArgumentException success) {}
    165     }
    166 
    167     /**
    168      * An unconfigurable newFixedThreadPool can execute runnables
    169      */
    170     public void testUnconfigurableExecutorService() {
    171         final ExecutorService e = Executors.unconfigurableExecutorService(Executors.newFixedThreadPool(2));
    172         try (PoolCleaner cleaner = cleaner(e)) {
    173             e.execute(new NoOpRunnable());
    174             e.execute(new NoOpRunnable());
    175             e.execute(new NoOpRunnable());
    176         }
    177     }
    178 
    179     /**
    180      * unconfigurableExecutorService(null) throws NPE
    181      */
    182     public void testUnconfigurableExecutorServiceNPE() {
    183         try {
    184             ExecutorService e = Executors.unconfigurableExecutorService(null);
    185             shouldThrow();
    186         } catch (NullPointerException success) {}
    187     }
    188 
    189     /**
    190      * unconfigurableScheduledExecutorService(null) throws NPE
    191      */
    192     public void testUnconfigurableScheduledExecutorServiceNPE() {
    193         try {
    194             ExecutorService e = Executors.unconfigurableScheduledExecutorService(null);
    195             shouldThrow();
    196         } catch (NullPointerException success) {}
    197     }
    198 
    199     /**
    200      * a newSingleThreadScheduledExecutor successfully runs delayed task
    201      */
    202     public void testNewSingleThreadScheduledExecutor() throws Exception {
    203         final ScheduledExecutorService p = Executors.newSingleThreadScheduledExecutor();
    204         try (PoolCleaner cleaner = cleaner(p)) {
    205             final CountDownLatch proceed = new CountDownLatch(1);
    206             final Runnable task = new CheckedRunnable() {
    207                 public void realRun() {
    208                     await(proceed);
    209                 }};
    210             long startTime = System.nanoTime();
    211             Future f = p.schedule(Executors.callable(task, Boolean.TRUE),
    212                                   timeoutMillis(), MILLISECONDS);
    213             assertFalse(f.isDone());
    214             proceed.countDown();
    215             assertSame(Boolean.TRUE, f.get(LONG_DELAY_MS, MILLISECONDS));
    216             assertSame(Boolean.TRUE, f.get());
    217             assertTrue(f.isDone());
    218             assertFalse(f.isCancelled());
    219             assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
    220         }
    221     }
    222 
    223     /**
    224      * a newScheduledThreadPool successfully runs delayed task
    225      */
    226     public void testNewScheduledThreadPool() throws Exception {
    227         final ScheduledExecutorService p = Executors.newScheduledThreadPool(2);
    228         try (PoolCleaner cleaner = cleaner(p)) {
    229             final CountDownLatch proceed = new CountDownLatch(1);
    230             final Runnable task = new CheckedRunnable() {
    231                 public void realRun() {
    232                     await(proceed);
    233                 }};
    234             long startTime = System.nanoTime();
    235             Future f = p.schedule(Executors.callable(task, Boolean.TRUE),
    236                                   timeoutMillis(), MILLISECONDS);
    237             assertFalse(f.isDone());
    238             proceed.countDown();
    239             assertSame(Boolean.TRUE, f.get(LONG_DELAY_MS, MILLISECONDS));
    240             assertSame(Boolean.TRUE, f.get());
    241             assertTrue(f.isDone());
    242             assertFalse(f.isCancelled());
    243             assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
    244         }
    245     }
    246 
    247     /**
    248      * an unconfigurable newScheduledThreadPool successfully runs delayed task
    249      */
    250     public void testUnconfigurableScheduledExecutorService() throws Exception {
    251         final ScheduledExecutorService p =
    252             Executors.unconfigurableScheduledExecutorService
    253             (Executors.newScheduledThreadPool(2));
    254         try (PoolCleaner cleaner = cleaner(p)) {
    255             final CountDownLatch proceed = new CountDownLatch(1);
    256             final Runnable task = new CheckedRunnable() {
    257                 public void realRun() {
    258                     await(proceed);
    259                 }};
    260             long startTime = System.nanoTime();
    261             Future f = p.schedule(Executors.callable(task, Boolean.TRUE),
    262                                   timeoutMillis(), MILLISECONDS);
    263             assertFalse(f.isDone());
    264             proceed.countDown();
    265             assertSame(Boolean.TRUE, f.get(LONG_DELAY_MS, MILLISECONDS));
    266             assertSame(Boolean.TRUE, f.get());
    267             assertTrue(f.isDone());
    268             assertFalse(f.isCancelled());
    269             assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
    270         }
    271     }
    272 
    273     /**
    274      * Future.get on submitted tasks will time out if they compute too long.
    275      */
    276     public void testTimedCallable() throws Exception {
    277         final ExecutorService[] executors = {
    278             Executors.newSingleThreadExecutor(),
    279             Executors.newCachedThreadPool(),
    280             Executors.newFixedThreadPool(2),
    281             Executors.newScheduledThreadPool(2),
    282         };
    283 
    284         final Runnable sleeper = new CheckedInterruptedRunnable() {
    285             public void realRun() throws InterruptedException {
    286                 delay(LONG_DELAY_MS);
    287             }};
    288 
    289         List<Thread> threads = new ArrayList<Thread>();
    290         for (final ExecutorService executor : executors) {
    291             threads.add(newStartedThread(new CheckedRunnable() {
    292                 public void realRun() {
    293                     Future future = executor.submit(sleeper);
    294                     assertFutureTimesOut(future);
    295                 }}));
    296         }
    297         for (Thread thread : threads)
    298             awaitTermination(thread);
    299         for (ExecutorService executor : executors)
    300             joinPool(executor);
    301     }
    302 
    303     /**
    304      * ThreadPoolExecutor using defaultThreadFactory has
    305      * specified group, priority, daemon status, and name
    306      */
    307     public void testDefaultThreadFactory() throws Exception {
    308         final ThreadGroup egroup = Thread.currentThread().getThreadGroup();
    309         final CountDownLatch done = new CountDownLatch(1);
    310         Runnable r = new CheckedRunnable() {
    311             public void realRun() {
    312                 try {
    313                     Thread current = Thread.currentThread();
    314                     assertTrue(!current.isDaemon());
    315                     assertTrue(current.getPriority() <= Thread.NORM_PRIORITY);
    316                     ThreadGroup g = current.getThreadGroup();
    317                     SecurityManager s = System.getSecurityManager();
    318                     if (s != null)
    319                         assertTrue(g == s.getThreadGroup());
    320                     else
    321                         assertTrue(g == egroup);
    322                     String name = current.getName();
    323                     assertTrue(name.endsWith("thread-1"));
    324                 } catch (SecurityException ok) {
    325                     // Also pass if not allowed to change setting
    326                 }
    327                 done.countDown();
    328             }};
    329         ExecutorService e = Executors.newSingleThreadExecutor(Executors.defaultThreadFactory());
    330         try (PoolCleaner cleaner = cleaner(e)) {
    331             e.execute(r);
    332             await(done);
    333         }
    334     }
    335 
    336     /**
    337      * ThreadPoolExecutor using privilegedThreadFactory has
    338      * specified group, priority, daemon status, name,
    339      * access control context and context class loader
    340      */
    341     public void testPrivilegedThreadFactory() throws Exception {
    342         final CountDownLatch done = new CountDownLatch(1);
    343         Runnable r = new CheckedRunnable() {
    344             public void realRun() throws Exception {
    345                 final ThreadGroup egroup = Thread.currentThread().getThreadGroup();
    346                 final ClassLoader thisccl = Thread.currentThread().getContextClassLoader();
    347                 // android-note: Removed unsupported access controller check.
    348                 // final AccessControlContext thisacc = AccessController.getContext();
    349                 Runnable r = new CheckedRunnable() {
    350                     public void realRun() {
    351                         Thread current = Thread.currentThread();
    352                         assertTrue(!current.isDaemon());
    353                         assertTrue(current.getPriority() <= Thread.NORM_PRIORITY);
    354                         ThreadGroup g = current.getThreadGroup();
    355                         SecurityManager s = System.getSecurityManager();
    356                         if (s != null)
    357                             assertTrue(g == s.getThreadGroup());
    358                         else
    359                             assertTrue(g == egroup);
    360                         String name = current.getName();
    361                         assertTrue(name.endsWith("thread-1"));
    362                         assertSame(thisccl, current.getContextClassLoader());
    363                         //assertEquals(thisacc, AccessController.getContext());
    364                         done.countDown();
    365                     }};
    366                 ExecutorService e = Executors.newSingleThreadExecutor(Executors.privilegedThreadFactory());
    367                 try (PoolCleaner cleaner = cleaner(e)) {
    368                     e.execute(r);
    369                     await(done);
    370                 }
    371             }};
    372 
    373         runWithPermissions(r,
    374                            new RuntimePermission("getClassLoader"),
    375                            new RuntimePermission("setContextClassLoader"),
    376                            new RuntimePermission("modifyThread"));
    377     }
    378 
    379     boolean haveCCLPermissions() {
    380         SecurityManager sm = System.getSecurityManager();
    381         if (sm != null) {
    382             try {
    383                 sm.checkPermission(new RuntimePermission("setContextClassLoader"));
    384                 sm.checkPermission(new RuntimePermission("getClassLoader"));
    385             } catch (AccessControlException e) {
    386                 return false;
    387             }
    388         }
    389         return true;
    390     }
    391 
    392     void checkCCL() {
    393         SecurityManager sm = System.getSecurityManager();
    394         if (sm != null) {
    395             sm.checkPermission(new RuntimePermission("setContextClassLoader"));
    396             sm.checkPermission(new RuntimePermission("getClassLoader"));
    397         }
    398     }
    399 
    400     class CheckCCL implements Callable<Object> {
    401         public Object call() {
    402             checkCCL();
    403             return null;
    404         }
    405     }
    406 
    407     /**
    408      * Without class loader permissions, creating
    409      * privilegedCallableUsingCurrentClassLoader throws ACE
    410      */
    411     public void testCreatePrivilegedCallableUsingCCLWithNoPrivs() {
    412         Runnable r = new CheckedRunnable() {
    413             public void realRun() throws Exception {
    414                 if (System.getSecurityManager() == null)
    415                     return;
    416                 try {
    417                     Executors.privilegedCallableUsingCurrentClassLoader(new NoOpCallable());
    418                     shouldThrow();
    419                 } catch (AccessControlException success) {}
    420             }};
    421 
    422         runWithoutPermissions(r);
    423     }
    424 
    425     /**
    426      * With class loader permissions, calling
    427      * privilegedCallableUsingCurrentClassLoader does not throw ACE
    428      */
    429     public void testPrivilegedCallableUsingCCLWithPrivs() throws Exception {
    430         Runnable r = new CheckedRunnable() {
    431             public void realRun() throws Exception {
    432                 Executors.privilegedCallableUsingCurrentClassLoader
    433                     (new NoOpCallable())
    434                     .call();
    435             }};
    436 
    437         runWithPermissions(r,
    438                            new RuntimePermission("getClassLoader"),
    439                            new RuntimePermission("setContextClassLoader"));
    440     }
    441 
    442     /**
    443      * Without permissions, calling privilegedCallable throws ACE
    444      */
    445     public void testPrivilegedCallableWithNoPrivs() throws Exception {
    446         // Avoid classloader-related SecurityExceptions in swingui.TestRunner
    447         Executors.privilegedCallable(new CheckCCL());
    448 
    449         Runnable r = new CheckedRunnable() {
    450             public void realRun() throws Exception {
    451                 if (System.getSecurityManager() == null)
    452                     return;
    453                 Callable task = Executors.privilegedCallable(new CheckCCL());
    454                 try {
    455                     task.call();
    456                     shouldThrow();
    457                 } catch (AccessControlException success) {}
    458             }};
    459 
    460         runWithoutPermissions(r);
    461 
    462         // It seems rather difficult to test that the
    463         // AccessControlContext of the privilegedCallable is used
    464         // instead of its caller.  Below is a failed attempt to do
    465         // that, which does not work because the AccessController
    466         // cannot capture the internal state of the current Policy.
    467         // It would be much more work to differentiate based on,
    468         // e.g. CodeSource.
    469 
    470 //         final AccessControlContext[] noprivAcc = new AccessControlContext[1];
    471 //         final Callable[] task = new Callable[1];
    472 
    473 //         runWithPermissions
    474 //             (new CheckedRunnable() {
    475 //                 public void realRun() {
    476 //                     if (System.getSecurityManager() == null)
    477 //                         return;
    478 //                     noprivAcc[0] = AccessController.getContext();
    479 //                     task[0] = Executors.privilegedCallable(new CheckCCL());
    480 //                     try {
    481 //                         AccessController.doPrivileged(new PrivilegedAction<Void>() {
    482 //                                                           public Void run() {
    483 //                                                               checkCCL();
    484 //                                                               return null;
    485 //                                                           }}, noprivAcc[0]);
    486 //                         shouldThrow();
    487 //                     } catch (AccessControlException success) {}
    488 //                 }});
    489 
    490 //         runWithPermissions
    491 //             (new CheckedRunnable() {
    492 //                 public void realRun() throws Exception {
    493 //                     if (System.getSecurityManager() == null)
    494 //                         return;
    495 //                     // Verify that we have an underprivileged ACC
    496 //                     try {
    497 //                         AccessController.doPrivileged(new PrivilegedAction<Void>() {
    498 //                                                           public Void run() {
    499 //                                                               checkCCL();
    500 //                                                               return null;
    501 //                                                           }}, noprivAcc[0]);
    502 //                         shouldThrow();
    503 //                     } catch (AccessControlException success) {}
    504 
    505 //                     try {
    506 //                         task[0].call();
    507 //                         shouldThrow();
    508 //                     } catch (AccessControlException success) {}
    509 //                 }},
    510 //              new RuntimePermission("getClassLoader"),
    511 //              new RuntimePermission("setContextClassLoader"));
    512     }
    513 
    514     /**
    515      * With permissions, calling privilegedCallable succeeds
    516      */
    517     public void testPrivilegedCallableWithPrivs() throws Exception {
    518         Runnable r = new CheckedRunnable() {
    519             public void realRun() throws Exception {
    520                 Executors.privilegedCallable(new CheckCCL()).call();
    521             }};
    522 
    523         runWithPermissions(r,
    524                            new RuntimePermission("getClassLoader"),
    525                            new RuntimePermission("setContextClassLoader"));
    526     }
    527 
    528     /**
    529      * callable(Runnable) returns null when called
    530      */
    531     public void testCallable1() throws Exception {
    532         Callable c = Executors.callable(new NoOpRunnable());
    533         assertNull(c.call());
    534     }
    535 
    536     /**
    537      * callable(Runnable, result) returns result when called
    538      */
    539     public void testCallable2() throws Exception {
    540         Callable c = Executors.callable(new NoOpRunnable(), one);
    541         assertSame(one, c.call());
    542     }
    543 
    544     /**
    545      * callable(PrivilegedAction) returns its result when called
    546      */
    547     public void testCallable3() throws Exception {
    548         Callable c = Executors.callable(new PrivilegedAction() {
    549                 public Object run() { return one; }});
    550         assertSame(one, c.call());
    551     }
    552 
    553     /**
    554      * callable(PrivilegedExceptionAction) returns its result when called
    555      */
    556     public void testCallable4() throws Exception {
    557         Callable c = Executors.callable(new PrivilegedExceptionAction() {
    558                 public Object run() { return one; }});
    559         assertSame(one, c.call());
    560     }
    561 
    562     /**
    563      * callable(null Runnable) throws NPE
    564      */
    565     public void testCallableNPE1() {
    566         try {
    567             Callable c = Executors.callable((Runnable) null);
    568             shouldThrow();
    569         } catch (NullPointerException success) {}
    570     }
    571 
    572     /**
    573      * callable(null, result) throws NPE
    574      */
    575     public void testCallableNPE2() {
    576         try {
    577             Callable c = Executors.callable((Runnable) null, one);
    578             shouldThrow();
    579         } catch (NullPointerException success) {}
    580     }
    581 
    582     /**
    583      * callable(null PrivilegedAction) throws NPE
    584      */
    585     public void testCallableNPE3() {
    586         try {
    587             Callable c = Executors.callable((PrivilegedAction) null);
    588             shouldThrow();
    589         } catch (NullPointerException success) {}
    590     }
    591 
    592     /**
    593      * callable(null PrivilegedExceptionAction) throws NPE
    594      */
    595     public void testCallableNPE4() {
    596         try {
    597             Callable c = Executors.callable((PrivilegedExceptionAction) null);
    598             shouldThrow();
    599         } catch (NullPointerException success) {}
    600     }
    601 
    602 }
    603