| /* | 
 |  * 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/publicdomain/zero/1.0/ | 
 |  * Other contributors include Andrew Wright, Jeffrey Hayes, | 
 |  * Pat Fisher, Mike Judd. | 
 |  */ | 
 |  | 
 | package jsr166; | 
 |  | 
 | import static java.util.concurrent.TimeUnit.MILLISECONDS; | 
 |  | 
 | import java.security.PrivilegedAction; | 
 | import java.security.PrivilegedExceptionAction; | 
 | import java.util.ArrayList; | 
 | import java.util.Collections; | 
 | import java.util.List; | 
 | import java.util.concurrent.AbstractExecutorService; | 
 | import java.util.concurrent.ArrayBlockingQueue; | 
 | import java.util.concurrent.Callable; | 
 | import java.util.concurrent.CancellationException; | 
 | import java.util.concurrent.CountDownLatch; | 
 | import java.util.concurrent.ExecutionException; | 
 | import java.util.concurrent.Executors; | 
 | import java.util.concurrent.ExecutorService; | 
 | import java.util.concurrent.Future; | 
 | import java.util.concurrent.ThreadPoolExecutor; | 
 | import java.util.concurrent.TimeUnit; | 
 | import java.util.concurrent.atomic.AtomicBoolean; | 
 |  | 
 | import junit.framework.Test; | 
 | import junit.framework.TestSuite; | 
 |  | 
 | public class AbstractExecutorServiceTest extends JSR166TestCase { | 
 |     // android-note: Removed because the CTS runner does a bad job of | 
 |     // retrying tests that have suite() declarations. | 
 |     // | 
 |     // public static void main(String[] args) { | 
 |     //     main(suite(), args); | 
 |     // } | 
 |     // public static Test suite() { | 
 |     //     return new TestSuite(AbstractExecutorServiceTest.class); | 
 |     // } | 
 |  | 
 |     /** | 
 |      * A no-frills implementation of AbstractExecutorService, designed | 
 |      * to test the submit methods only. | 
 |      */ | 
 |     static class DirectExecutorService extends AbstractExecutorService { | 
 |         public void execute(Runnable r) { r.run(); } | 
 |         public void shutdown() { shutdown = true; } | 
 |         public List<Runnable> shutdownNow() { | 
 |             shutdown = true; | 
 |             return Collections.EMPTY_LIST; | 
 |         } | 
 |         public boolean isShutdown() { return shutdown; } | 
 |         public boolean isTerminated() { return isShutdown(); } | 
 |         public boolean awaitTermination(long timeout, TimeUnit unit) { | 
 |             return isShutdown(); | 
 |         } | 
 |         private volatile boolean shutdown = false; | 
 |     } | 
 |  | 
 |     /** | 
 |      * execute(runnable) runs it to completion | 
 |      */ | 
 |     public void testExecuteRunnable() throws Exception { | 
 |         ExecutorService e = new DirectExecutorService(); | 
 |         final AtomicBoolean done = new AtomicBoolean(false); | 
 |         Future<?> future = e.submit(new CheckedRunnable() { | 
 |             public void realRun() { | 
 |                 done.set(true); | 
 |             }}); | 
 |         assertNull(future.get()); | 
 |         assertNull(future.get(0, MILLISECONDS)); | 
 |         assertTrue(done.get()); | 
 |         assertTrue(future.isDone()); | 
 |         assertFalse(future.isCancelled()); | 
 |     } | 
 |  | 
 |     /** | 
 |      * Completed submit(callable) returns result | 
 |      */ | 
 |     public void testSubmitCallable() throws Exception { | 
 |         ExecutorService e = new DirectExecutorService(); | 
 |         Future<String> 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()); | 
 |     } | 
 |  | 
 |     /** | 
 |      * Completed submit(runnable, result) returns result | 
 |      */ | 
 |     public void testSubmitRunnable2() throws Exception { | 
 |         ExecutorService e = new DirectExecutorService(); | 
 |         Future<String> future = e.submit(new NoOpRunnable(), TEST_STRING); | 
 |         String result = future.get(); | 
 |         assertSame(TEST_STRING, result); | 
 |     } | 
 |  | 
 |     /** | 
 |      * A submitted privileged action runs to completion | 
 |      */ | 
 |     public void testSubmitPrivilegedAction() throws Exception { | 
 |         Runnable r = new CheckedRunnable() { | 
 |             public void realRun() throws Exception { | 
 |                 ExecutorService e = new DirectExecutorService(); | 
 |                 Future future = e.submit(Executors.callable(new PrivilegedAction() { | 
 |                     public Object run() { | 
 |                         return TEST_STRING; | 
 |                     }})); | 
 |  | 
 |                 assertSame(TEST_STRING, future.get()); | 
 |             }}; | 
 |  | 
 |         runWithPermissions(r, | 
 |                            new RuntimePermission("getClassLoader"), | 
 |                            new RuntimePermission("setContextClassLoader"), | 
 |                            new RuntimePermission("modifyThread")); | 
 |     } | 
 |  | 
 |     /** | 
 |      * A submitted privileged exception action runs to completion | 
 |      */ | 
 |     public void testSubmitPrivilegedExceptionAction() throws Exception { | 
 |         Runnable r = new CheckedRunnable() { | 
 |             public void realRun() throws Exception { | 
 |                 ExecutorService e = new DirectExecutorService(); | 
 |                 Future future = e.submit(Executors.callable(new PrivilegedExceptionAction() { | 
 |                     public Object run() { | 
 |                         return TEST_STRING; | 
 |                     }})); | 
 |  | 
 |                 assertSame(TEST_STRING, future.get()); | 
 |             }}; | 
 |  | 
 |         runWithPermissions(r); | 
 |     } | 
 |  | 
 |     /** | 
 |      * A submitted failed privileged exception action reports exception | 
 |      */ | 
 |     public void testSubmitFailedPrivilegedExceptionAction() throws Exception { | 
 |         Runnable r = new CheckedRunnable() { | 
 |             public void realRun() throws Exception { | 
 |                 ExecutorService e = new DirectExecutorService(); | 
 |                 Future future = e.submit(Executors.callable(new PrivilegedExceptionAction() { | 
 |                     public Object run() throws Exception { | 
 |                         throw new IndexOutOfBoundsException(); | 
 |                     }})); | 
 |  | 
 |                 try { | 
 |                     future.get(); | 
 |                     shouldThrow(); | 
 |                 } catch (ExecutionException success) { | 
 |                     assertTrue(success.getCause() instanceof IndexOutOfBoundsException); | 
 |                 }}}; | 
 |  | 
 |         runWithPermissions(r); | 
 |     } | 
 |  | 
 |     /** | 
 |      * execute(null runnable) throws NPE | 
 |      */ | 
 |     public void testExecuteNullRunnable() { | 
 |         ExecutorService e = new DirectExecutorService(); | 
 |         try { | 
 |             e.submit((Runnable) null); | 
 |             shouldThrow(); | 
 |         } catch (NullPointerException success) {} | 
 |     } | 
 |  | 
 |     /** | 
 |      * submit(null callable) throws NPE | 
 |      */ | 
 |     public void testSubmitNullCallable() { | 
 |         ExecutorService e = new DirectExecutorService(); | 
 |         try { | 
 |             e.submit((Callable) null); | 
 |             shouldThrow(); | 
 |         } catch (NullPointerException success) {} | 
 |     } | 
 |  | 
 |     /** | 
 |      * submit(callable).get() throws InterruptedException if interrupted | 
 |      */ | 
 |     public void testInterruptedSubmit() throws InterruptedException { | 
 |         final CountDownLatch submitted    = new CountDownLatch(1); | 
 |         final CountDownLatch quittingTime = new CountDownLatch(1); | 
 |         final Callable<Void> awaiter = new CheckedCallable<Void>() { | 
 |             public Void realCall() throws InterruptedException { | 
 |                 assertTrue(quittingTime.await(2*LONG_DELAY_MS, MILLISECONDS)); | 
 |                 return null; | 
 |             }}; | 
 |         final ExecutorService p | 
 |             = new ThreadPoolExecutor(1,1,60, TimeUnit.SECONDS, | 
 |                                      new ArrayBlockingQueue<Runnable>(10)); | 
 |         try (PoolCleaner cleaner = cleaner(p, quittingTime)) { | 
 |             Thread t = newStartedThread(new CheckedInterruptedRunnable() { | 
 |                 public void realRun() throws Exception { | 
 |                     Future<Void> future = p.submit(awaiter); | 
 |                     submitted.countDown(); | 
 |                     future.get(); | 
 |                 }}); | 
 |  | 
 |             await(submitted); | 
 |             t.interrupt(); | 
 |             awaitTermination(t); | 
 |         } | 
 |     } | 
 |  | 
 |     /** | 
 |      * get of submit(callable) throws ExecutionException if callable | 
 |      * throws exception | 
 |      */ | 
 |     public void testSubmitEE() throws InterruptedException { | 
 |         final ThreadPoolExecutor p = | 
 |             new ThreadPoolExecutor(1, 1, | 
 |                                    60, TimeUnit.SECONDS, | 
 |                                    new ArrayBlockingQueue<Runnable>(10)); | 
 |         try (PoolCleaner cleaner = cleaner(p)) { | 
 |             Callable c = new Callable() { | 
 |                 public Object call() { throw new ArithmeticException(); }}; | 
 |             try { | 
 |                 p.submit(c).get(); | 
 |                 shouldThrow(); | 
 |             } catch (ExecutionException success) { | 
 |                 assertTrue(success.getCause() instanceof ArithmeticException); | 
 |             } | 
 |         } | 
 |     } | 
 |  | 
 |     /** | 
 |      * invokeAny(null) throws NPE | 
 |      */ | 
 |     public void testInvokeAny1() throws Exception { | 
 |         final ExecutorService e = new DirectExecutorService(); | 
 |         try (PoolCleaner cleaner = cleaner(e)) { | 
 |             try { | 
 |                 e.invokeAny(null); | 
 |                 shouldThrow(); | 
 |             } catch (NullPointerException success) {} | 
 |         } | 
 |     } | 
 |  | 
 |     /** | 
 |      * invokeAny(empty collection) throws IAE | 
 |      */ | 
 |     public void testInvokeAny2() throws Exception { | 
 |         final ExecutorService e = new DirectExecutorService(); | 
 |         try (PoolCleaner cleaner = cleaner(e)) { | 
 |             try { | 
 |                 e.invokeAny(new ArrayList<Callable<String>>()); | 
 |                 shouldThrow(); | 
 |             } catch (IllegalArgumentException success) {} | 
 |         } | 
 |     } | 
 |  | 
 |     /** | 
 |      * invokeAny(c) throws NPE if c has null elements | 
 |      */ | 
 |     public void testInvokeAny3() throws Exception { | 
 |         final ExecutorService e = new DirectExecutorService(); | 
 |         try (PoolCleaner cleaner = cleaner(e)) { | 
 |             List<Callable<Long>> l = new ArrayList<Callable<Long>>(); | 
 |             l.add(new Callable<Long>() { | 
 |                       public Long call() { throw new ArithmeticException(); }}); | 
 |             l.add(null); | 
 |             try { | 
 |                 e.invokeAny(l); | 
 |                 shouldThrow(); | 
 |             } catch (NullPointerException success) {} | 
 |         } | 
 |     } | 
 |  | 
 |     /** | 
 |      * invokeAny(c) throws ExecutionException if no task in c completes | 
 |      */ | 
 |     public void testInvokeAny4() throws InterruptedException { | 
 |         final ExecutorService e = new DirectExecutorService(); | 
 |         try (PoolCleaner cleaner = cleaner(e)) { | 
 |             List<Callable<String>> l = new ArrayList<Callable<String>>(); | 
 |             l.add(new NPETask()); | 
 |             try { | 
 |                 e.invokeAny(l); | 
 |                 shouldThrow(); | 
 |             } catch (ExecutionException success) { | 
 |                 assertTrue(success.getCause() instanceof NullPointerException); | 
 |             } | 
 |         } | 
 |     } | 
 |  | 
 |     /** | 
 |      * invokeAny(c) returns result of some task in c if at least one completes | 
 |      */ | 
 |     public void testInvokeAny5() throws Exception { | 
 |         final ExecutorService e = new DirectExecutorService(); | 
 |         try (PoolCleaner cleaner = cleaner(e)) { | 
 |             List<Callable<String>> l = new ArrayList<Callable<String>>(); | 
 |             l.add(new StringTask()); | 
 |             l.add(new StringTask()); | 
 |             String result = e.invokeAny(l); | 
 |             assertSame(TEST_STRING, result); | 
 |         } | 
 |     } | 
 |  | 
 |     /** | 
 |      * invokeAll(null) throws NPE | 
 |      */ | 
 |     public void testInvokeAll1() throws InterruptedException { | 
 |         final ExecutorService e = new DirectExecutorService(); | 
 |         try (PoolCleaner cleaner = cleaner(e)) { | 
 |             try { | 
 |                 e.invokeAll(null); | 
 |                 shouldThrow(); | 
 |             } catch (NullPointerException success) {} | 
 |         } | 
 |     } | 
 |  | 
 |     /** | 
 |      * invokeAll(empty collection) returns empty collection | 
 |      */ | 
 |     public void testInvokeAll2() throws InterruptedException { | 
 |         final ExecutorService e = new DirectExecutorService(); | 
 |         try (PoolCleaner cleaner = cleaner(e)) { | 
 |             List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>()); | 
 |             assertTrue(r.isEmpty()); | 
 |         } | 
 |     } | 
 |  | 
 |     /** | 
 |      * invokeAll(c) throws NPE if c has null elements | 
 |      */ | 
 |     public void testInvokeAll3() throws InterruptedException { | 
 |         final ExecutorService e = new DirectExecutorService(); | 
 |         try (PoolCleaner cleaner = cleaner(e)) { | 
 |             List<Callable<String>> l = new ArrayList<Callable<String>>(); | 
 |             l.add(new StringTask()); | 
 |             l.add(null); | 
 |             try { | 
 |                 e.invokeAll(l); | 
 |                 shouldThrow(); | 
 |             } catch (NullPointerException success) {} | 
 |         } | 
 |     } | 
 |  | 
 |     /** | 
 |      * get of returned element of invokeAll(c) throws exception on failed task | 
 |      */ | 
 |     public void testInvokeAll4() throws Exception { | 
 |         final ExecutorService e = new DirectExecutorService(); | 
 |         try (PoolCleaner cleaner = cleaner(e)) { | 
 |             List<Callable<String>> l = new ArrayList<Callable<String>>(); | 
 |             l.add(new NPETask()); | 
 |             List<Future<String>> futures = e.invokeAll(l); | 
 |             assertEquals(1, futures.size()); | 
 |             try { | 
 |                 futures.get(0).get(); | 
 |                 shouldThrow(); | 
 |             } catch (ExecutionException success) { | 
 |                 assertTrue(success.getCause() instanceof NullPointerException); | 
 |             } | 
 |         } | 
 |     } | 
 |  | 
 |     /** | 
 |      * invokeAll(c) returns results of all completed tasks in c | 
 |      */ | 
 |     public void testInvokeAll5() throws Exception { | 
 |         final ExecutorService e = new DirectExecutorService(); | 
 |         try (PoolCleaner cleaner = cleaner(e)) { | 
 |             List<Callable<String>> l = new ArrayList<Callable<String>>(); | 
 |             l.add(new StringTask()); | 
 |             l.add(new StringTask()); | 
 |             List<Future<String>> futures = e.invokeAll(l); | 
 |             assertEquals(2, futures.size()); | 
 |             for (Future<String> future : futures) | 
 |                 assertSame(TEST_STRING, future.get()); | 
 |         } | 
 |     } | 
 |  | 
 |     /** | 
 |      * timed invokeAny(null) throws NPE | 
 |      */ | 
 |     public void testTimedInvokeAny1() throws Exception { | 
 |         final ExecutorService e = new DirectExecutorService(); | 
 |         try (PoolCleaner cleaner = cleaner(e)) { | 
 |             try { | 
 |                 e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS); | 
 |                 shouldThrow(); | 
 |             } catch (NullPointerException success) {} | 
 |         } | 
 |     } | 
 |  | 
 |     /** | 
 |      * timed invokeAny(null time unit) throws NPE | 
 |      */ | 
 |     public void testTimedInvokeAnyNullTimeUnit() throws Exception { | 
 |         final ExecutorService e = new DirectExecutorService(); | 
 |         try (PoolCleaner cleaner = cleaner(e)) { | 
 |             List<Callable<String>> l = new ArrayList<Callable<String>>(); | 
 |             l.add(new StringTask()); | 
 |             try { | 
 |                 e.invokeAny(l, MEDIUM_DELAY_MS, null); | 
 |                 shouldThrow(); | 
 |             } catch (NullPointerException success) {} | 
 |         } | 
 |     } | 
 |  | 
 |     /** | 
 |      * timed invokeAny(empty collection) throws IAE | 
 |      */ | 
 |     public void testTimedInvokeAny2() throws Exception { | 
 |         final ExecutorService e = new DirectExecutorService(); | 
 |         try (PoolCleaner cleaner = cleaner(e)) { | 
 |             try { | 
 |                 e.invokeAny(new ArrayList<Callable<String>>(), | 
 |                             MEDIUM_DELAY_MS, MILLISECONDS); | 
 |                 shouldThrow(); | 
 |             } catch (IllegalArgumentException success) {} | 
 |         } | 
 |     } | 
 |  | 
 |     /** | 
 |      * timed invokeAny(c) throws NPE if c has null elements | 
 |      */ | 
 |     public void testTimedInvokeAny3() throws Exception { | 
 |         final ExecutorService e = new DirectExecutorService(); | 
 |         try (PoolCleaner cleaner = cleaner(e)) { | 
 |             List<Callable<Long>> l = new ArrayList<Callable<Long>>(); | 
 |             l.add(new Callable<Long>() { | 
 |                       public Long call() { throw new ArithmeticException(); }}); | 
 |             l.add(null); | 
 |             try { | 
 |                 e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS); | 
 |                 shouldThrow(); | 
 |             } catch (NullPointerException success) {} | 
 |         } | 
 |     } | 
 |  | 
 |     /** | 
 |      * timed invokeAny(c) throws ExecutionException if no task completes | 
 |      */ | 
 |     public void testTimedInvokeAny4() throws Exception { | 
 |         final ExecutorService e = new DirectExecutorService(); | 
 |         try (PoolCleaner cleaner = cleaner(e)) { | 
 |             long startTime = System.nanoTime(); | 
 |             List<Callable<String>> l = new ArrayList<Callable<String>>(); | 
 |             l.add(new NPETask()); | 
 |             try { | 
 |                 e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS); | 
 |                 shouldThrow(); | 
 |             } catch (ExecutionException success) { | 
 |                 assertTrue(success.getCause() instanceof NullPointerException); | 
 |             } | 
 |             assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); | 
 |         } | 
 |     } | 
 |  | 
 |     /** | 
 |      * timed invokeAny(c) returns result of some task in c | 
 |      */ | 
 |     public void testTimedInvokeAny5() throws Exception { | 
 |         final ExecutorService e = new DirectExecutorService(); | 
 |         try (PoolCleaner cleaner = cleaner(e)) { | 
 |             long startTime = System.nanoTime(); | 
 |             List<Callable<String>> l = new ArrayList<Callable<String>>(); | 
 |             l.add(new StringTask()); | 
 |             l.add(new StringTask()); | 
 |             String result = e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS); | 
 |             assertSame(TEST_STRING, result); | 
 |             assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); | 
 |         } | 
 |     } | 
 |  | 
 |     /** | 
 |      * timed invokeAll(null) throws NPE | 
 |      */ | 
 |     public void testTimedInvokeAll1() throws InterruptedException { | 
 |         final ExecutorService e = new DirectExecutorService(); | 
 |         try (PoolCleaner cleaner = cleaner(e)) { | 
 |             try { | 
 |                 e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS); | 
 |                 shouldThrow(); | 
 |             } catch (NullPointerException success) {} | 
 |         } | 
 |     } | 
 |  | 
 |     /** | 
 |      * timed invokeAll(null time unit) throws NPE | 
 |      */ | 
 |     public void testTimedInvokeAllNullTimeUnit() throws InterruptedException { | 
 |         final ExecutorService e = new DirectExecutorService(); | 
 |         try (PoolCleaner cleaner = cleaner(e)) { | 
 |             List<Callable<String>> l = new ArrayList<Callable<String>>(); | 
 |             l.add(new StringTask()); | 
 |             try { | 
 |                 e.invokeAll(l, MEDIUM_DELAY_MS, null); | 
 |                 shouldThrow(); | 
 |             } catch (NullPointerException success) {} | 
 |         } | 
 |     } | 
 |  | 
 |     /** | 
 |      * timed invokeAll(empty collection) returns empty collection | 
 |      */ | 
 |     public void testTimedInvokeAll2() throws InterruptedException { | 
 |         final ExecutorService e = new DirectExecutorService(); | 
 |         try (PoolCleaner cleaner = cleaner(e)) { | 
 |             List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS); | 
 |             assertTrue(r.isEmpty()); | 
 |         } | 
 |     } | 
 |  | 
 |     /** | 
 |      * timed invokeAll(c) throws NPE if c has null elements | 
 |      */ | 
 |     public void testTimedInvokeAll3() throws InterruptedException { | 
 |         final ExecutorService e = new DirectExecutorService(); | 
 |         try (PoolCleaner cleaner = cleaner(e)) { | 
 |             List<Callable<String>> l = new ArrayList<Callable<String>>(); | 
 |             l.add(new StringTask()); | 
 |             l.add(null); | 
 |             try { | 
 |                 e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS); | 
 |                 shouldThrow(); | 
 |             } catch (NullPointerException success) {} | 
 |         } | 
 |     } | 
 |  | 
 |     /** | 
 |      * get of returned element of invokeAll(c) throws exception on failed task | 
 |      */ | 
 |     public void testTimedInvokeAll4() throws Exception { | 
 |         final ExecutorService e = new DirectExecutorService(); | 
 |         try (PoolCleaner cleaner = cleaner(e)) { | 
 |             List<Callable<String>> l = new ArrayList<Callable<String>>(); | 
 |             l.add(new NPETask()); | 
 |             List<Future<String>> futures = | 
 |                 e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS); | 
 |             assertEquals(1, futures.size()); | 
 |             try { | 
 |                 futures.get(0).get(); | 
 |                 shouldThrow(); | 
 |             } catch (ExecutionException success) { | 
 |                 assertTrue(success.getCause() instanceof NullPointerException); | 
 |             } | 
 |         } | 
 |     } | 
 |  | 
 |     /** | 
 |      * timed invokeAll(c) returns results of all completed tasks in c | 
 |      */ | 
 |     public void testTimedInvokeAll5() throws Exception { | 
 |         final ExecutorService e = new DirectExecutorService(); | 
 |         try (PoolCleaner cleaner = cleaner(e)) { | 
 |             List<Callable<String>> l = new ArrayList<Callable<String>>(); | 
 |             l.add(new StringTask()); | 
 |             l.add(new StringTask()); | 
 |             List<Future<String>> futures = | 
 |                 e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS); | 
 |             assertEquals(2, futures.size()); | 
 |             for (Future<String> future : futures) | 
 |                 assertSame(TEST_STRING, future.get()); | 
 |         } | 
 |     } | 
 |  | 
 |     /** | 
 |      * timed invokeAll cancels tasks not completed by timeout | 
 |      */ | 
 |     public void testTimedInvokeAll6() throws Exception { | 
 |         final ExecutorService e = new DirectExecutorService(); | 
 |         try (PoolCleaner cleaner = cleaner(e)) { | 
 |             for (long timeout = timeoutMillis();;) { | 
 |                 List<Callable<String>> tasks = new ArrayList<>(); | 
 |                 tasks.add(new StringTask("0")); | 
 |                 tasks.add(Executors.callable(possiblyInterruptedRunnable(timeout), | 
 |                                              TEST_STRING)); | 
 |                 tasks.add(new StringTask("2")); | 
 |                 long startTime = System.nanoTime(); | 
 |                 List<Future<String>> futures = | 
 |                     e.invokeAll(tasks, timeout, MILLISECONDS); | 
 |                 assertEquals(tasks.size(), futures.size()); | 
 |                 assertTrue(millisElapsedSince(startTime) >= timeout); | 
 |                 for (Future future : futures) | 
 |                     assertTrue(future.isDone()); | 
 |                 try { | 
 |                     assertEquals("0", futures.get(0).get()); | 
 |                     assertEquals(TEST_STRING, futures.get(1).get()); | 
 |                 } catch (CancellationException retryWithLongerTimeout) { | 
 |                     // unusual delay before starting second task | 
 |                     timeout *= 2; | 
 |                     if (timeout >= LONG_DELAY_MS / 2) | 
 |                         fail("expected exactly one task to be cancelled"); | 
 |                     continue; | 
 |                 } | 
 |                 assertTrue(futures.get(2).isCancelled()); | 
 |                 break; | 
 |             } | 
 |         } | 
 |     } | 
 |  | 
 | } |