blob: a7d217d83f8292599bbf2f7b5f717a8ebee1f458 [file] [log] [blame]
/*
* 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) {
}
}
}