--- jsr166/src/test/tck/AbstractExecutorServiceTest.java 2003/12/19 20:38:55 1.4 +++ jsr166/src/test/tck/AbstractExecutorServiceTest.java 2009/12/01 22:51:44 1.22 @@ -1,28 +1,30 @@ /* - * Written by members of JCP JSR-166 Expert Group and released to the - * public domain. Use, modify, and redistribute this code in any way - * without acknowledgement. Other contributors include Andrew Wright, - * Jeffrey Hayes, Pat Fischer, Mike Judd. + * 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 static java.util.concurrent.TimeUnit.MILLISECONDS; import java.math.BigInteger; import java.security.*; -public class AbstractExecutorServiceTest extends JSR166TestCase{ +public class AbstractExecutorServiceTest extends JSR166TestCase { public static void main(String[] args) { junit.textui.TestRunner.run (suite()); } public static Test suite() { - return new TestSuite(ExecutorsTest.class); + return new TestSuite(AbstractExecutorServiceTest.class); } - /** + /** * A no-frills implementation of AbstractExecutorService, designed - * to test the submit/invoke methods only. + * to test the submit methods only. */ static class DirectExecutorService extends AbstractExecutorService { public void execute(Runnable r) { r.run(); } @@ -34,135 +36,139 @@ public class AbstractExecutorServiceTest private volatile boolean shutdown = false; } - private static final String TEST_STRING = "a test string"; - - private static class StringTask implements Callable { - public String call() { return TEST_STRING; } + /** + * execute(runnable) runs it to completion + */ + public void testExecuteRunnable() throws Exception { + ExecutorService e = new DirectExecutorService(); + TrackedShortRunnable task = new TrackedShortRunnable(); + assertFalse(task.done); + Future future = e.submit(task); + future.get(); + assertTrue(task.done); } + /** - * execute of runnable runs it to completion + * Completed submit(callable) returns result */ - public void testExecuteRunnable() { - try { - ExecutorService e = new DirectExecutorService(); - TrackedShortRunnable task = new TrackedShortRunnable(); - assertFalse(task.done); - Future future = e.submit(task); - future.get(); - assertTrue(task.done); - } - catch (ExecutionException ex) { - unexpectedException(); - } - catch (InterruptedException ex) { - unexpectedException(); - } + public void testSubmitCallable() throws Exception { + ExecutorService e = new DirectExecutorService(); + Future future = e.submit(new StringTask()); + String result = future.get(); + assertSame(TEST_STRING, result); } + /** + * Completed submit(runnable) returns successfully + */ + public void testSubmitRunnable() throws Exception { + ExecutorService e = new DirectExecutorService(); + Future future = e.submit(new NoOpRunnable()); + future.get(); + assertTrue(future.isDone()); + } /** - * execute of a callable runs it to completion + * Completed submit(runnable, result) returns result */ - public void testExecuteCallable() { - try { - ExecutorService e = new DirectExecutorService(); - Future future = e.submit(new StringTask()); - String result = future.get(); - assertSame(TEST_STRING, result); - } - catch (ExecutionException ex) { - unexpectedException(); - } - catch (InterruptedException ex) { - unexpectedException(); - } + public void testSubmitRunnable2() throws Exception { + ExecutorService e = new DirectExecutorService(); + Future future = e.submit(new NoOpRunnable(), TEST_STRING); + String result = future.get(); + assertSame(TEST_STRING, result); } /** - * execute of a privileged action runs it to completion + * A submitted privileged action to completion */ - public void testExecutePrivilegedAction() { - Policy savedPolicy = Policy.getPolicy(); - AdjustablePolicy policy = new AdjustablePolicy(); - policy.addPermission(new RuntimePermission("getContextClassLoader")); - policy.addPermission(new RuntimePermission("setContextClassLoader")); - Policy.setPolicy(policy); + public void testSubmitPrivilegedAction() throws Exception { + 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 { ExecutorService e = new DirectExecutorService(); - Future future = e.submit(new PrivilegedAction() { + Future future = e.submit(Executors.callable(new PrivilegedAction() { public Object run() { return TEST_STRING; - }}); + }})); Object result = future.get(); assertSame(TEST_STRING, result); } - catch (ExecutionException ex) { - unexpectedException(); - } - catch (InterruptedException ex) { - unexpectedException(); - } finally { - Policy.setPolicy(savedPolicy); + try { + Policy.setPolicy(savedPolicy); + } catch (AccessControlException ok) { + return; + } } } /** - * execute of a privileged exception action runs it to completion + * A submitted a privileged exception action runs to completion */ - public void testExecutePrivilegedExceptionAction() { - Policy savedPolicy = Policy.getPolicy(); - AdjustablePolicy policy = new AdjustablePolicy(); - policy.addPermission(new RuntimePermission("getContextClassLoader")); - policy.addPermission(new RuntimePermission("setContextClassLoader")); - Policy.setPolicy(policy); + public void testSubmitPrivilegedExceptionAction() throws Exception { + 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 { ExecutorService e = new DirectExecutorService(); - Future future = e.submit(new PrivilegedExceptionAction() { + Future future = e.submit(Executors.callable(new PrivilegedExceptionAction() { public Object run() { return TEST_STRING; - }}); + }})); Object result = future.get(); assertSame(TEST_STRING, result); } - catch (ExecutionException ex) { - unexpectedException(); - } - catch (InterruptedException ex) { - unexpectedException(); - } finally { Policy.setPolicy(savedPolicy); } } /** - * execute of a failed privileged exception action reports exception + * A submitted failed privileged exception action reports exception */ - public void testExecuteFailedPrivilegedExceptionAction() { - Policy savedPolicy = Policy.getPolicy(); - AdjustablePolicy policy = new AdjustablePolicy(); - policy.addPermission(new RuntimePermission("getContextClassLoader")); - policy.addPermission(new RuntimePermission("setContextClassLoader")); - Policy.setPolicy(policy); + public void testSubmitFailedPrivilegedExceptionAction() throws Exception { + 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 { ExecutorService e = new DirectExecutorService(); - Future future = e.submit(new PrivilegedExceptionAction() { + Future future = e.submit(Executors.callable(new PrivilegedExceptionAction() { public Object run() throws Exception { throw new IndexOutOfBoundsException(); - }}); + }})); - Object result = future.get(); + future.get(); shouldThrow(); - } - catch (ExecutionException success) { - } - catch (InterruptedException ex) { - unexpectedException(); + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof IndexOutOfBoundsException); } finally { Policy.setPolicy(savedPolicy); @@ -170,209 +176,527 @@ public class AbstractExecutorServiceTest } /** - * invoke of a callable runs it to completion + * execute(null runnable) throws NPE */ - public void testInvokeCallable() { + public void testExecuteNullRunnable() { try { ExecutorService e = new DirectExecutorService(); - String result = e.invoke(new StringTask()); - - assertSame(TEST_STRING, result); - } - catch (ExecutionException ex) { - unexpectedException(); - } - catch (InterruptedException ex) { - unexpectedException(); - } + e.submit((Runnable) null); + shouldThrow(); + } catch (NullPointerException success) {} } + /** - * execute with a null runnable throws NPE + * submit(null callable) throws NPE */ - public void testExecuteNullRunnable() { + public void testSubmitNullCallable() { try { ExecutorService e = new DirectExecutorService(); - TrackedShortRunnable task = null; - Future future = e.submit(task); + e.submit((Callable) null); shouldThrow(); + } catch (NullPointerException success) {} + } + + /** + * submit(runnable) throws RejectedExecutionException if + * executor is saturated. + */ + public void testExecute1() { + ThreadPoolExecutor p = + new ThreadPoolExecutor(1, 1, + 60, TimeUnit.SECONDS, + new ArrayBlockingQueue(1)); + try { + for (int i = 0; i < 2; ++i) + p.submit(new MediumRunnable()); + for (int i = 0; i < 2; ++i) { + try { + p.submit(new MediumRunnable()); + shouldThrow(); + } catch (RejectedExecutionException success) {} + } + } finally { + joinPool(p); } - catch (NullPointerException success) { - } - catch (Exception ex) { - unexpectedException(); + } + + /** + * submit(callable) throws RejectedExecutionException + * if executor is saturated. + */ + public void testExecute2() { + ThreadPoolExecutor p = + new ThreadPoolExecutor(1, 1, + 60, TimeUnit.SECONDS, + new ArrayBlockingQueue(1)); + try { + for (int i = 0; i < 2; ++i) + p.submit(new MediumRunnable()); + for (int i = 0; i < 2; ++i) { + try { + p.submit(new SmallCallable()); + shouldThrow(); + } catch (RejectedExecutionException success) {} + } + } finally { + joinPool(p); } } /** - * execute of a null callable throws NPE + * Blocking on submit(callable) throws InterruptedException if + * caller interrupted. + */ + public void testInterruptedSubmit() throws InterruptedException { + final ThreadPoolExecutor p = new ThreadPoolExecutor(1,1,60, TimeUnit.SECONDS, new ArrayBlockingQueue(10)); + Thread t = new Thread(new CheckedInterruptedRunnable() { + public void realRun() throws Exception { + p.submit(new CheckedCallable() { + public Object realCall() + throws InterruptedException { + Thread.sleep(SMALL_DELAY_MS); + return null; + }}).get(); + }}); + + t.start(); + Thread.sleep(SHORT_DELAY_MS); + t.interrupt(); + joinPool(p); + } + + /** + * get of submitted callable throws InterruptedException if callable + * interrupted */ - public void testExecuteNullCallable() { + public void testSubmitIE() throws InterruptedException { + final ThreadPoolExecutor p = + new ThreadPoolExecutor(1, 1, + 60, TimeUnit.SECONDS, + new ArrayBlockingQueue(10)); + + Thread t = new Thread(new CheckedInterruptedRunnable() { + public void realRun() throws Exception { + p.submit(new SmallCallable()).get(); + }}); + + t.start(); + Thread.sleep(SHORT_DELAY_MS); + t.interrupt(); + t.join(); + joinPool(p); + } + + /** + * get of submit(callable) throws ExecutionException if callable + * throws exception + */ + public void testSubmitEE() throws InterruptedException { + ThreadPoolExecutor p = + new ThreadPoolExecutor(1, 1, + 60, TimeUnit.SECONDS, + new ArrayBlockingQueue(10)); + + Callable c = new Callable() { + public Object call() { return 5/0; }}; + try { - ExecutorService e = new DirectExecutorService(); - StringTask t = null; - Future future = e.submit(t); + p.submit(c).get(); shouldThrow(); + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof ArithmeticException); } - catch (NullPointerException success) { + joinPool(p); + } + + /** + * invokeAny(null) throws NPE + */ + public void testInvokeAny1() + throws InterruptedException, ExecutionException { + ExecutorService e = new DirectExecutorService(); + try { + e.invokeAny(null); + shouldThrow(); + } catch (NullPointerException success) { + } finally { + joinPool(e); } - catch (Exception ex) { - unexpectedException(); + } + + /** + * invokeAny(empty collection) throws IAE + */ + public void testInvokeAny2() + throws InterruptedException, ExecutionException { + ExecutorService e = new DirectExecutorService(); + try { + e.invokeAny(new ArrayList>()); + shouldThrow(); + } catch (IllegalArgumentException success) { + } finally { + joinPool(e); } } /** - * invoke of a null callable throws NPE + * invokeAny(c) throws NPE if c has null elements */ - public void testInvokeNullCallable() { + public void testInvokeAny3() throws Exception { + ExecutorService e = new DirectExecutorService(); + List> l = new ArrayList>(); + l.add(new Callable() { + public Integer call() { return 5/0; }}); + l.add(null); try { - ExecutorService e = new DirectExecutorService(); - StringTask t = null; - String result = e.invoke(t); + e.invokeAny(l); shouldThrow(); + } catch (NullPointerException success) { + } finally { + joinPool(e); } - catch (NullPointerException success) { + } + + /** + * invokeAny(c) throws ExecutionException if no task in c completes + */ + public void testInvokeAny4() throws InterruptedException { + ExecutorService e = new DirectExecutorService(); + List> l = new ArrayList>(); + l.add(new NPETask()); + try { + e.invokeAny(l); + shouldThrow(); + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof NullPointerException); + } finally { + joinPool(e); } - catch (Exception ex) { - unexpectedException(); + } + + /** + * invokeAny(c) returns result of some task in c if at least one completes + */ + public void testInvokeAny5() throws Exception { + ExecutorService e = new DirectExecutorService(); + try { + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(new StringTask()); + String result = e.invokeAny(l); + assertSame(TEST_STRING, result); + } finally { + joinPool(e); } } /** - * execute(Executor, Runnable) throws RejectedExecutionException - * if saturated. + * invokeAll(null) throws NPE */ - public void testExecute1() { - ThreadPoolExecutor p = new ThreadPoolExecutor(1,1, SHORT_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue(1)); + public void testInvokeAll1() throws InterruptedException { + ExecutorService e = new DirectExecutorService(); try { + e.invokeAll(null); + shouldThrow(); + } catch (NullPointerException success) { + } finally { + joinPool(e); + } + } - for(int i = 0; i < 5; ++i){ - p.submit(new MediumRunnable()); - } + /** + * invokeAll(empty collection) returns empty collection + */ + public void testInvokeAll2() throws InterruptedException { + ExecutorService e = new DirectExecutorService(); + try { + List> r = e.invokeAll(new ArrayList>()); + assertTrue(r.isEmpty()); + } finally { + joinPool(e); + } + } + + /** + * invokeAll(c) throws NPE if c has null elements + */ + public void testInvokeAll3() throws InterruptedException { + ExecutorService e = new DirectExecutorService(); + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(null); + try { + e.invokeAll(l); shouldThrow(); - } catch(RejectedExecutionException success){} - joinPool(p); + } catch (NullPointerException success) { + } finally { + joinPool(e); + } } /** - * execute(Executor, Callable)throws RejectedExecutionException - * if saturated. + * get of returned element of invokeAll(c) throws exception on failed task */ - public void testExecute2() { - ThreadPoolExecutor p = new ThreadPoolExecutor(1,1, SHORT_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue(1)); + public void testInvokeAll4() throws Exception { + ExecutorService e = new DirectExecutorService(); try { - for(int i = 0; i < 5; ++i) { - p.submit(new SmallCallable()); + List> l = new ArrayList>(); + l.add(new NPETask()); + List> futures = e.invokeAll(l); + assertEquals(1, futures.size()); + try { + futures.get(0).get(); + shouldThrow(); + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof NullPointerException); } - shouldThrow(); - } catch(RejectedExecutionException e){} - joinPool(p); + } finally { + joinPool(e); + } + } + + /** + * invokeAll(c) returns results of all completed tasks in c + */ + public void testInvokeAll5() throws Exception { + ExecutorService e = new DirectExecutorService(); + try { + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(new StringTask()); + List> futures = e.invokeAll(l); + assertEquals(2, futures.size()); + for (Future future : futures) + assertSame(TEST_STRING, future.get()); + } finally { + joinPool(e); + } } /** - * invoke(Executor, Callable) throws InterruptedException if - * caller interrupted. + * timed invokeAny(null) throws NPE */ - public void testInterruptedInvoke() { - final ThreadPoolExecutor p = new ThreadPoolExecutor(1,1,SHORT_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue(10)); - Thread t = new Thread(new Runnable() { - public void run() { - try { - p.invoke(new Callable() { - public Object call() { - try { - Thread.sleep(MEDIUM_DELAY_MS); - shouldThrow(); - } catch(InterruptedException e){ - } - return null; - } - }); - } catch(InterruptedException success){ - } catch(Exception e) { - unexpectedException(); - } - - } - }); - try { - t.start(); - Thread.sleep(SHORT_DELAY_MS); - t.interrupt(); - } catch(Exception e){ - unexpectedException(); + public void testTimedInvokeAny1() throws Exception { + ExecutorService e = new DirectExecutorService(); + try { + e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (NullPointerException success) { + } finally { + joinPool(e); } - joinPool(p); } /** - * invoke(Executor, Callable) throws InterruptedException if - * callable throws exception + * timed invokeAny(null time unit) throws NPE */ - public void testInvoke5() { - final ThreadPoolExecutor p = new ThreadPoolExecutor(1,1,SHORT_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue(10)); + public void testTimedInvokeAnyNullTimeUnit() throws Exception { + ExecutorService e = new DirectExecutorService(); + List> l = new ArrayList>(); + l.add(new StringTask()); + try { + e.invokeAny(l, MEDIUM_DELAY_MS, null); + shouldThrow(); + } catch (NullPointerException success) { + } finally { + joinPool(e); + } + } - final Callable c = new Callable() { - public Object call() { - try { - p.invoke(new SmallCallable()); - shouldThrow(); - } catch(InterruptedException e){} - catch(RejectedExecutionException e2){} - catch(ExecutionException e3){} - return Boolean.TRUE; - } - }; + /** + * timed invokeAny(empty collection) throws IAE + */ + public void testTimedInvokeAny2() throws Exception { + ExecutorService e = new DirectExecutorService(); + try { + e.invokeAny(new ArrayList>(), MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (IllegalArgumentException success) { + } finally { + joinPool(e); + } + } + /** + * timed invokeAny(c) throws NPE if c has null elements + */ + public void testTimedInvokeAny3() throws Exception { + ExecutorService e = new DirectExecutorService(); + List> l = new ArrayList>(); + l.add(new Callable() { + public Integer call() { return 5/0; }}); + l.add(null); + try { + e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (NullPointerException success) { + } finally { + joinPool(e); + } + } + + /** + * timed invokeAny(c) throws ExecutionException if no task completes + */ + public void testTimedInvokeAny4() throws Exception { + ExecutorService e = new DirectExecutorService(); + List> l = new ArrayList>(); + l.add(new NPETask()); + try { + e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof NullPointerException); + } finally { + joinPool(e); + } + } + /** + * timed invokeAny(c) returns result of some task in c + */ + public void testTimedInvokeAny5() throws Exception { + ExecutorService e = new DirectExecutorService(); + try { + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(new StringTask()); + String result = e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS); + assertSame(TEST_STRING, result); + } finally { + joinPool(e); + } + } - Thread t = new Thread(new Runnable() { - public void run() { - try { - c.call(); - } catch(Exception e){} - } - }); - try { - t.start(); - Thread.sleep(SHORT_DELAY_MS); - t.interrupt(); - t.join(); - } catch(InterruptedException e){ - unexpectedException(); + /** + * timed invokeAll(null) throws NPE + */ + public void testTimedInvokeAll1() throws InterruptedException { + ExecutorService e = new DirectExecutorService(); + try { + e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (NullPointerException success) { + } finally { + joinPool(e); } + } - joinPool(p); + /** + * timed invokeAll(null time unit) throws NPE + */ + public void testTimedInvokeAllNullTimeUnit() throws InterruptedException { + ExecutorService e = new DirectExecutorService(); + List> l = new ArrayList>(); + l.add(new StringTask()); + try { + e.invokeAll(l, MEDIUM_DELAY_MS, null); + shouldThrow(); + } catch (NullPointerException success) { + } finally { + joinPool(e); + } } /** - * invoke(Executor, Callable) will throw ExecutionException - * if callable throws exception + * timed invokeAll(empty collection) returns empty collection */ - public void testInvoke6() { - ThreadPoolExecutor p = new ThreadPoolExecutor(1,1,SHORT_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue(10)); + public void testTimedInvokeAll2() throws InterruptedException { + ExecutorService e = new DirectExecutorService(); + try { + List> r = e.invokeAll(new ArrayList>(), MEDIUM_DELAY_MS, MILLISECONDS); + assertTrue(r.isEmpty()); + } finally { + joinPool(e); + } + } + /** + * timed invokeAll(c) throws NPE if c has null elements + */ + public void testTimedInvokeAll3() throws InterruptedException { + ExecutorService e = new DirectExecutorService(); + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(null); try { - Callable c = new Callable() { - public Object call() { - int i = 5/0; - return Boolean.TRUE; - } - }; + e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS); + shouldThrow(); + } catch (NullPointerException success) { + } finally { + joinPool(e); + } + } - for(int i =0; i < 5; i++){ - p.invoke(c); + /** + * get of returned element of invokeAll(c) throws exception on failed task + */ + public void testTimedInvokeAll4() throws Exception { + ExecutorService e = new DirectExecutorService(); + try { + List> l = new ArrayList>(); + l.add(new NPETask()); + List> futures = + e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS); + assertEquals(1, futures.size()); + try { + futures.get(0).get(); + shouldThrow(); + } catch (ExecutionException success) { + assertTrue(success.getCause() instanceof NullPointerException); } + } finally { + joinPool(e); + } + } - shouldThrow(); + /** + * timed invokeAll(c) returns results of all completed tasks in c + */ + public void testTimedInvokeAll5() throws Exception { + ExecutorService e = new DirectExecutorService(); + try { + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(new StringTask()); + List> futures = + e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS); + assertEquals(2, futures.size()); + for (Future future : futures) + assertSame(TEST_STRING, future.get()); + } finally { + joinPool(e); } - catch(ExecutionException success){ - } catch(Exception e) { - unexpectedException(); + } + + /** + * timed invokeAll cancels tasks not completed by timeout + */ + public void testTimedInvokeAll6() throws InterruptedException { + ExecutorService e = new DirectExecutorService(); + try { + List> l = new ArrayList>(); + l.add(new StringTask()); + l.add(Executors.callable(new MediumPossiblyInterruptedRunnable(), TEST_STRING)); + l.add(new StringTask()); + List> futures = + e.invokeAll(l, SMALL_DELAY_MS, MILLISECONDS); + assertEquals(3, futures.size()); + Iterator> it = futures.iterator(); + Future f1 = it.next(); + Future f2 = it.next(); + Future f3 = it.next(); + assertTrue(f1.isDone()); + assertFalse(f1.isCancelled()); + assertTrue(f2.isDone()); + assertTrue(f3.isDone()); + assertTrue(f3.isCancelled()); + } finally { + joinPool(e); } - joinPool(p); } }