| /* |
| * Written by Doug Lea with assistance from members of JCP JSR-166 |
| * Expert Group and released to the public domain, as explained at |
| * http://creativecommons.org/licenses/publicdomain |
| * Other contributors include Andrew Wright, Jeffrey Hayes, |
| * Pat Fisher, Mike Judd. |
| */ |
| |
| |
| import junit.framework.*; |
| import java.util.*; |
| import java.util.concurrent.*; |
| import java.math.BigInteger; |
| import java.security.*; |
| |
| public class ExecutorsTest extends JSR166TestCase{ |
| public static void main(String[] args) { |
| junit.textui.TestRunner.run (suite()); |
| } |
| public static Test suite() { |
| return new TestSuite(ExecutorsTest.class); |
| } |
| |
| static class TimedCallable<T> implements Callable<T> { |
| private final ExecutorService exec; |
| private final Callable<T> func; |
| private final long msecs; |
| |
| TimedCallable(ExecutorService exec, Callable<T> func, long msecs) { |
| this.exec = exec; |
| this.func = func; |
| this.msecs = msecs; |
| } |
| |
| public T call() throws Exception { |
| Future<T> ftask = exec.submit(func); |
| try { |
| return ftask.get(msecs, TimeUnit.MILLISECONDS); |
| } finally { |
| ftask.cancel(true); |
| } |
| } |
| } |
| |
| |
| private static class Fib implements Callable<BigInteger> { |
| private final BigInteger n; |
| Fib(long n) { |
| if (n < 0) throw new IllegalArgumentException("need non-negative arg, but got " + n); |
| this.n = BigInteger.valueOf(n); |
| } |
| public BigInteger call() { |
| BigInteger f1 = BigInteger.ONE; |
| BigInteger f2 = f1; |
| for (BigInteger i = BigInteger.ZERO; i.compareTo(n) < 0; i = i.add(BigInteger.ONE)) { |
| BigInteger t = f1.add(f2); |
| f1 = f2; |
| f2 = t; |
| } |
| return f1; |
| } |
| }; |
| |
| /** |
| * A newCachedThreadPool can execute runnables |
| */ |
| public void testNewCachedThreadPool1() { |
| ExecutorService e = Executors.newCachedThreadPool(); |
| e.execute(new NoOpRunnable()); |
| e.execute(new NoOpRunnable()); |
| e.execute(new NoOpRunnable()); |
| joinPool(e); |
| } |
| |
| /** |
| * A newCachedThreadPool with given ThreadFactory can execute runnables |
| */ |
| public void testNewCachedThreadPool2() { |
| ExecutorService e = Executors.newCachedThreadPool(new SimpleThreadFactory()); |
| e.execute(new NoOpRunnable()); |
| e.execute(new NoOpRunnable()); |
| e.execute(new NoOpRunnable()); |
| joinPool(e); |
| } |
| |
| /** |
| * A newCachedThreadPool with null ThreadFactory throws NPE |
| */ |
| public void testNewCachedThreadPool3() { |
| try { |
| ExecutorService e = Executors.newCachedThreadPool(null); |
| shouldThrow(); |
| } |
| catch(NullPointerException success) { |
| } |
| } |
| |
| |
| /** |
| * A new SingleThreadExecutor can execute runnables |
| */ |
| public void testNewSingleThreadExecutor1() { |
| ExecutorService e = Executors.newSingleThreadExecutor(); |
| e.execute(new NoOpRunnable()); |
| e.execute(new NoOpRunnable()); |
| e.execute(new NoOpRunnable()); |
| joinPool(e); |
| } |
| |
| /** |
| * A new SingleThreadExecutor with given ThreadFactory can execute runnables |
| */ |
| public void testNewSingleThreadExecutor2() { |
| ExecutorService e = Executors.newSingleThreadExecutor(new SimpleThreadFactory()); |
| e.execute(new NoOpRunnable()); |
| e.execute(new NoOpRunnable()); |
| e.execute(new NoOpRunnable()); |
| joinPool(e); |
| } |
| |
| /** |
| * A new SingleThreadExecutor with null ThreadFactory throws NPE |
| */ |
| public void testNewSingleThreadExecutor3() { |
| try { |
| ExecutorService e = Executors.newSingleThreadExecutor(null); |
| shouldThrow(); |
| } |
| catch(NullPointerException success) { |
| } |
| } |
| |
| /** |
| * A new SingleThreadExecutor cannot be casted to concrete implementation |
| */ |
| public void testCastNewSingleThreadExecutor() { |
| ExecutorService e = Executors.newSingleThreadExecutor(); |
| try { |
| ThreadPoolExecutor tpe = (ThreadPoolExecutor)e; |
| } catch (ClassCastException success) { |
| } finally { |
| joinPool(e); |
| } |
| } |
| |
| |
| /** |
| * A new newFixedThreadPool can execute runnables |
| */ |
| public void testNewFixedThreadPool1() { |
| ExecutorService e = Executors.newFixedThreadPool(2); |
| e.execute(new NoOpRunnable()); |
| e.execute(new NoOpRunnable()); |
| e.execute(new NoOpRunnable()); |
| joinPool(e); |
| } |
| |
| /** |
| * A new newFixedThreadPool with given ThreadFactory can execute runnables |
| */ |
| public void testNewFixedThreadPool2() { |
| ExecutorService e = Executors.newFixedThreadPool(2, new SimpleThreadFactory()); |
| e.execute(new NoOpRunnable()); |
| e.execute(new NoOpRunnable()); |
| e.execute(new NoOpRunnable()); |
| joinPool(e); |
| } |
| |
| /** |
| * A new newFixedThreadPool with null ThreadFactory throws NPE |
| */ |
| public void testNewFixedThreadPool3() { |
| try { |
| ExecutorService e = Executors.newFixedThreadPool(2, null); |
| shouldThrow(); |
| } |
| catch(NullPointerException success) { |
| } |
| } |
| |
| /** |
| * A new newFixedThreadPool with 0 threads throws IAE |
| */ |
| public void testNewFixedThreadPool4() { |
| try { |
| ExecutorService e = Executors.newFixedThreadPool(0); |
| shouldThrow(); |
| } |
| catch(IllegalArgumentException success) { |
| } |
| } |
| |
| |
| /** |
| * An unconfigurable newFixedThreadPool can execute runnables |
| */ |
| public void testunconfigurableExecutorService() { |
| ExecutorService e = Executors.unconfigurableExecutorService(Executors.newFixedThreadPool(2)); |
| e.execute(new NoOpRunnable()); |
| e.execute(new NoOpRunnable()); |
| e.execute(new NoOpRunnable()); |
| joinPool(e); |
| } |
| |
| /** |
| * unconfigurableExecutorService(null) throws NPE |
| */ |
| public void testunconfigurableExecutorServiceNPE() { |
| try { |
| ExecutorService e = Executors.unconfigurableExecutorService(null); |
| } |
| catch (NullPointerException success) { |
| } |
| } |
| |
| /** |
| * unconfigurableScheduledExecutorService(null) throws NPE |
| */ |
| public void testunconfigurableScheduledExecutorServiceNPE() { |
| try { |
| ExecutorService e = Executors.unconfigurableScheduledExecutorService(null); |
| } |
| catch (NullPointerException success) { |
| } |
| } |
| |
| |
| /** |
| * a newSingleThreadScheduledExecutor successfully runs delayed task |
| */ |
| public void testNewSingleThreadScheduledExecutor() { |
| try { |
| TrackedCallable callable = new TrackedCallable(); |
| ScheduledExecutorService p1 = Executors.newSingleThreadScheduledExecutor(); |
| Future f = p1.schedule(callable, SHORT_DELAY_MS, TimeUnit.MILLISECONDS); |
| assertFalse(callable.done); |
| Thread.sleep(MEDIUM_DELAY_MS); |
| assertTrue(callable.done); |
| assertEquals(Boolean.TRUE, f.get()); |
| joinPool(p1); |
| } catch(RejectedExecutionException e){} |
| catch(Exception e){ |
| e.printStackTrace(); |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * a newScheduledThreadPool successfully runs delayed task |
| */ |
| public void testnewScheduledThreadPool() { |
| try { |
| TrackedCallable callable = new TrackedCallable(); |
| ScheduledExecutorService p1 = Executors.newScheduledThreadPool(2); |
| Future f = p1.schedule(callable, SHORT_DELAY_MS, TimeUnit.MILLISECONDS); |
| assertFalse(callable.done); |
| Thread.sleep(MEDIUM_DELAY_MS); |
| assertTrue(callable.done); |
| assertEquals(Boolean.TRUE, f.get()); |
| joinPool(p1); |
| } catch(RejectedExecutionException e){} |
| catch(Exception e){ |
| e.printStackTrace(); |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * an unconfigurable newScheduledThreadPool successfully runs delayed task |
| */ |
| public void testunconfigurableScheduledExecutorService() { |
| try { |
| TrackedCallable callable = new TrackedCallable(); |
| ScheduledExecutorService p1 = Executors.unconfigurableScheduledExecutorService(Executors.newScheduledThreadPool(2)); |
| Future f = p1.schedule(callable, SHORT_DELAY_MS, TimeUnit.MILLISECONDS); |
| assertFalse(callable.done); |
| Thread.sleep(MEDIUM_DELAY_MS); |
| assertTrue(callable.done); |
| assertEquals(Boolean.TRUE, f.get()); |
| joinPool(p1); |
| } catch(RejectedExecutionException e){} |
| catch(Exception e){ |
| e.printStackTrace(); |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * timeouts from execute will time out if they compute too long. |
| */ |
| public void testTimedCallable() { |
| int N = 10000; |
| ExecutorService executor = Executors.newSingleThreadExecutor(); |
| List<Callable<BigInteger>> tasks = new ArrayList<Callable<BigInteger>>(N); |
| try { |
| long startTime = System.currentTimeMillis(); |
| |
| long i = 0; |
| while (tasks.size() < N) { |
| tasks.add(new TimedCallable<BigInteger>(executor, new Fib(i), 1)); |
| i += 10; |
| } |
| |
| int iters = 0; |
| BigInteger sum = BigInteger.ZERO; |
| for (Iterator<Callable<BigInteger>> it = tasks.iterator(); it.hasNext();) { |
| try { |
| ++iters; |
| sum = sum.add(it.next().call()); |
| } |
| catch (TimeoutException success) { |
| assertTrue(iters > 0); |
| return; |
| } |
| catch (Exception e) { |
| unexpectedException(); |
| } |
| } |
| // if by chance we didn't ever time out, total time must be small |
| long elapsed = System.currentTimeMillis() - startTime; |
| assertTrue(elapsed < N); |
| } |
| finally { |
| joinPool(executor); |
| } |
| } |
| |
| |
| /** |
| * ThreadPoolExecutor using defaultThreadFactory has |
| * specified group, priority, daemon status, and name |
| */ |
| public void testDefaultThreadFactory() { |
| final ThreadGroup egroup = Thread.currentThread().getThreadGroup(); |
| Runnable r = new Runnable() { |
| public void run() { |
| try { |
| Thread current = Thread.currentThread(); |
| threadAssertTrue(!current.isDaemon()); |
| threadAssertTrue(current.getPriority() <= Thread.NORM_PRIORITY); |
| ThreadGroup g = current.getThreadGroup(); |
| SecurityManager s = System.getSecurityManager(); |
| if (s != null) |
| threadAssertTrue(g == s.getThreadGroup()); |
| else |
| threadAssertTrue(g == egroup); |
| String name = current.getName(); |
| threadAssertTrue(name.endsWith("thread-1")); |
| } catch (SecurityException ok) { |
| // Also pass if not allowed to change setting |
| } |
| } |
| }; |
| ExecutorService e = Executors.newSingleThreadExecutor(Executors.defaultThreadFactory()); |
| |
| e.execute(r); |
| try { |
| e.shutdown(); |
| } catch(SecurityException ok) { |
| } |
| |
| try { |
| Thread.sleep(SHORT_DELAY_MS); |
| } catch (Exception eX) { |
| unexpectedException(); |
| } finally { |
| joinPool(e); |
| } |
| } |
| |
| /** |
| * ThreadPoolExecutor using privilegedThreadFactory has |
| * specified group, priority, daemon status, name, |
| * access control context and context class loader |
| */ |
| public void testPrivilegedThreadFactory() { |
| Policy savedPolicy = null; |
| try { |
| savedPolicy = Policy.getPolicy(); |
| AdjustablePolicy policy = new AdjustablePolicy(); |
| policy.addPermission(new RuntimePermission("getContextClassLoader")); |
| policy.addPermission(new RuntimePermission("setContextClassLoader")); |
| Policy.setPolicy(policy); |
| } catch (AccessControlException ok) { |
| return; |
| } |
| final ThreadGroup egroup = Thread.currentThread().getThreadGroup(); |
| final ClassLoader thisccl = Thread.currentThread().getContextClassLoader(); |
| final AccessControlContext thisacc = AccessController.getContext(); |
| Runnable r = new Runnable() { |
| public void run() { |
| try { |
| Thread current = Thread.currentThread(); |
| threadAssertTrue(!current.isDaemon()); |
| threadAssertTrue(current.getPriority() <= Thread.NORM_PRIORITY); |
| ThreadGroup g = current.getThreadGroup(); |
| SecurityManager s = System.getSecurityManager(); |
| if (s != null) |
| threadAssertTrue(g == s.getThreadGroup()); |
| else |
| threadAssertTrue(g == egroup); |
| String name = current.getName(); |
| threadAssertTrue(name.endsWith("thread-1")); |
| threadAssertTrue(thisccl == current.getContextClassLoader()); |
| threadAssertTrue(thisacc.equals(AccessController.getContext())); |
| } catch(SecurityException ok) { |
| // Also pass if not allowed to change settings |
| } |
| } |
| }; |
| ExecutorService e = Executors.newSingleThreadExecutor(Executors.privilegedThreadFactory()); |
| |
| Policy.setPolicy(savedPolicy); |
| e.execute(r); |
| try { |
| e.shutdown(); |
| } catch(SecurityException ok) { |
| } |
| try { |
| Thread.sleep(SHORT_DELAY_MS); |
| } catch (Exception ex) { |
| unexpectedException(); |
| } finally { |
| joinPool(e); |
| } |
| |
| } |
| |
| void checkCCL() { |
| AccessController.getContext().checkPermission(new RuntimePermission("getContextClassLoader")); |
| } |
| |
| class CheckCCL implements Callable<Object> { |
| public Object call() { |
| checkCCL(); |
| return null; |
| } |
| } |
| |
| |
| /** |
| * Without class loader permissions, creating |
| * privilegedCallableUsingCurrentClassLoader throws ACE |
| */ |
| public void testCreatePrivilegedCallableUsingCCLWithNoPrivs() { |
| Policy savedPolicy = null; |
| try { |
| savedPolicy = Policy.getPolicy(); |
| AdjustablePolicy policy = new AdjustablePolicy(); |
| Policy.setPolicy(policy); |
| } catch (AccessControlException ok) { |
| return; |
| } |
| |
| // Check if program still has too many permissions to run test |
| try { |
| checkCCL(); |
| // too many privileges to test; so return |
| Policy.setPolicy(savedPolicy); |
| return; |
| } catch(AccessControlException ok) { |
| } |
| |
| try { |
| Callable task = Executors.privilegedCallableUsingCurrentClassLoader(new NoOpCallable()); |
| shouldThrow(); |
| } catch(AccessControlException success) { |
| } catch(Exception ex) { |
| unexpectedException(); |
| } |
| finally { |
| Policy.setPolicy(savedPolicy); |
| } |
| } |
| |
| /** |
| * With class loader permissions, calling |
| * privilegedCallableUsingCurrentClassLoader does not throw ACE |
| */ |
| public void testprivilegedCallableUsingCCLWithPrivs() { |
| Policy savedPolicy = null; |
| try { |
| savedPolicy = Policy.getPolicy(); |
| AdjustablePolicy policy = new AdjustablePolicy(); |
| policy.addPermission(new RuntimePermission("getContextClassLoader")); |
| policy.addPermission(new RuntimePermission("setContextClassLoader")); |
| Policy.setPolicy(policy); |
| } catch (AccessControlException ok) { |
| return; |
| } |
| |
| try { |
| Callable task = Executors.privilegedCallableUsingCurrentClassLoader(new NoOpCallable()); |
| task.call(); |
| } catch(Exception ex) { |
| unexpectedException(); |
| } |
| finally { |
| Policy.setPolicy(savedPolicy); |
| } |
| } |
| |
| /** |
| * Without permissions, calling privilegedCallable throws ACE |
| */ |
| public void testprivilegedCallableWithNoPrivs() { |
| Callable task; |
| Policy savedPolicy = null; |
| AdjustablePolicy policy = null; |
| AccessControlContext noprivAcc = null; |
| try { |
| savedPolicy = Policy.getPolicy(); |
| policy = new AdjustablePolicy(); |
| Policy.setPolicy(policy); |
| noprivAcc = AccessController.getContext(); |
| task = Executors.privilegedCallable(new CheckCCL()); |
| Policy.setPolicy(savedPolicy); |
| } catch (AccessControlException ok) { |
| return; // program has too few permissions to set up test |
| } |
| |
| // Make sure that program doesn't have too many permissions |
| try { |
| AccessController.doPrivileged(new PrivilegedAction() { |
| public Object run() { |
| checkCCL(); |
| return null; |
| }}, noprivAcc); |
| // too many permissions; skip test |
| return; |
| } catch(AccessControlException ok) { |
| } |
| |
| try { |
| task.call(); |
| shouldThrow(); |
| } catch(AccessControlException success) { |
| } catch(Exception ex) { |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * With permissions, calling privilegedCallable succeeds |
| */ |
| public void testprivilegedCallableWithPrivs() { |
| Policy savedPolicy = null; |
| try { |
| savedPolicy = Policy.getPolicy(); |
| AdjustablePolicy policy = new AdjustablePolicy(); |
| policy.addPermission(new RuntimePermission("getContextClassLoader")); |
| policy.addPermission(new RuntimePermission("setContextClassLoader")); |
| Policy.setPolicy(policy); |
| } catch (AccessControlException ok) { |
| return; |
| } |
| |
| Callable task = Executors.privilegedCallable(new CheckCCL()); |
| try { |
| task.call(); |
| } catch(Exception ex) { |
| unexpectedException(); |
| } finally { |
| Policy.setPolicy(savedPolicy); |
| } |
| } |
| |
| /** |
| * callable(Runnable) returns null when called |
| */ |
| public void testCallable1() { |
| try { |
| Callable c = Executors.callable(new NoOpRunnable()); |
| assertNull(c.call()); |
| } catch(Exception ex) { |
| unexpectedException(); |
| } |
| |
| } |
| |
| /** |
| * callable(Runnable, result) returns result when called |
| */ |
| public void testCallable2() { |
| try { |
| Callable c = Executors.callable(new NoOpRunnable(), one); |
| assertEquals(one, c.call()); |
| } catch(Exception ex) { |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * callable(PrivilegedAction) returns its result when called |
| */ |
| public void testCallable3() { |
| try { |
| Callable c = Executors.callable(new PrivilegedAction() { |
| public Object run() { return one; }}); |
| assertEquals(one, c.call()); |
| } catch(Exception ex) { |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * callable(PrivilegedExceptionAction) returns its result when called |
| */ |
| public void testCallable4() { |
| try { |
| Callable c = Executors.callable(new PrivilegedExceptionAction() { |
| public Object run() { return one; }}); |
| assertEquals(one, c.call()); |
| } catch(Exception ex) { |
| unexpectedException(); |
| } |
| } |
| |
| |
| /** |
| * callable(null Runnable) throws NPE |
| */ |
| public void testCallableNPE1() { |
| try { |
| Runnable r = null; |
| Callable c = Executors.callable(r); |
| } catch (NullPointerException success) { |
| } |
| } |
| |
| /** |
| * callable(null, result) throws NPE |
| */ |
| public void testCallableNPE2() { |
| try { |
| Runnable r = null; |
| Callable c = Executors.callable(r, one); |
| } catch (NullPointerException success) { |
| } |
| } |
| |
| /** |
| * callable(null PrivilegedAction) throws NPE |
| */ |
| public void testCallableNPE3() { |
| try { |
| PrivilegedAction r = null; |
| Callable c = Executors.callable(r); |
| } catch (NullPointerException success) { |
| } |
| } |
| |
| /** |
| * callable(null PrivilegedExceptionAction) throws NPE |
| */ |
| public void testCallableNPE4() { |
| try { |
| PrivilegedExceptionAction r = null; |
| Callable c = Executors.callable(r); |
| } catch (NullPointerException success) { |
| } |
| } |
| |
| |
| } |