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 */
6
7package jsr166;
8
9import static java.util.concurrent.TimeUnit.MILLISECONDS;
10import static java.util.concurrent.TimeUnit.NANOSECONDS;
11
12import java.security.PrivilegedAction;
13import java.security.PrivilegedExceptionAction;
14import java.util.ArrayList;
15import java.util.Collection;
16import java.util.List;
17import java.util.concurrent.Callable;
18import java.util.concurrent.CountDownLatch;
19import java.util.concurrent.ExecutionException;
20import java.util.concurrent.Executors;
21import java.util.concurrent.ExecutorService;
22import java.util.concurrent.ForkJoinPool;
23import java.util.concurrent.ForkJoinTask;
24import java.util.concurrent.ForkJoinWorkerThread;
25import java.util.concurrent.Future;
26import java.util.concurrent.RecursiveTask;
27import java.util.concurrent.RejectedExecutionException;
28import java.util.concurrent.atomic.AtomicBoolean;
29import java.util.concurrent.locks.ReentrantLock;
30
31import junit.framework.AssertionFailedError;
32import junit.framework.Test;
33import junit.framework.TestSuite;
34
35public class ForkJoinPoolTest extends JSR166TestCase {
36    // android-note: Removed because the CTS runner does a bad job of
37    // retrying tests that have suite() declarations.
38    //
39    // public static void main(String[] args) {
40    //     main(suite(), args);
41    // }
42    // public static Test suite() {
43    //     return new TestSuite(...);
44    // }
45
46    /*
47     * Testing coverage notes:
48     *
49     * 1. shutdown and related methods are tested via super.joinPool.
50     *
51     * 2. newTaskFor and adapters are tested in submit/invoke tests
52     *
53     * 3. We cannot portably test monitoring methods such as
54     * getStealCount() since they rely ultimately on random task
55     * stealing that may cause tasks not to be stolen/propagated
56     * across threads, especially on uniprocessors.
57     *
58     * 4. There are no independently testable ForkJoinWorkerThread
59     * methods, but they are covered here and in task tests.
60     */
61
62    // Some classes to test extension and factory methods
63
64    static class MyHandler implements Thread.UncaughtExceptionHandler {
65        volatile int catches = 0;
66        public void uncaughtException(Thread t, Throwable e) {
67            ++catches;
68        }
69    }
70
71    // to test handlers
72    static class FailingFJWSubclass extends ForkJoinWorkerThread {
73        public FailingFJWSubclass(ForkJoinPool p) { super(p) ; }
74        protected void onStart() { super.onStart(); throw new Error(); }
75    }
76
77    static class FailingThreadFactory
78            implements ForkJoinPool.ForkJoinWorkerThreadFactory {
79        volatile int calls = 0;
80        public ForkJoinWorkerThread newThread(ForkJoinPool p) {
81            if (++calls > 1) return null;
82            return new FailingFJWSubclass(p);
83        }
84    }
85
86    static class SubFJP extends ForkJoinPool { // to expose protected
87        SubFJP() { super(1); }
88        public int drainTasksTo(Collection<? super ForkJoinTask<?>> c) {
89            return super.drainTasksTo(c);
90        }
91        public ForkJoinTask<?> pollSubmission() {
92            return super.pollSubmission();
93        }
94    }
95
96    static class ManagedLocker implements ForkJoinPool.ManagedBlocker {
97        final ReentrantLock lock;
98        boolean hasLock = false;
99        ManagedLocker(ReentrantLock lock) { this.lock = lock; }
100        public boolean block() {
101            if (!hasLock)
102                lock.lock();
103            return true;
104        }
105        public boolean isReleasable() {
106            return hasLock || (hasLock = lock.tryLock());
107        }
108    }
109
110    // A simple recursive task for testing
111    static final class FibTask extends RecursiveTask<Integer> {
112        final int number;
113        FibTask(int n) { number = n; }
114        protected Integer compute() {
115            int n = number;
116            if (n <= 1)
117                return n;
118            FibTask f1 = new FibTask(n - 1);
119            f1.fork();
120            return (new FibTask(n - 2)).compute() + f1.join();
121        }
122    }
123
124    // A failing task for testing
125    static final class FailingTask extends ForkJoinTask<Void> {
126        public final Void getRawResult() { return null; }
127        protected final void setRawResult(Void mustBeNull) { }
128        protected final boolean exec() { throw new Error(); }
129        FailingTask() {}
130    }
131
132    // Fib needlessly using locking to test ManagedBlockers
133    static final class LockingFibTask extends RecursiveTask<Integer> {
134        final int number;
135        final ManagedLocker locker;
136        final ReentrantLock lock;
137        LockingFibTask(int n, ManagedLocker locker, ReentrantLock lock) {
138            number = n;
139            this.locker = locker;
140            this.lock = lock;
141        }
142        protected Integer compute() {
143            int n;
144            LockingFibTask f1 = null;
145            LockingFibTask f2 = null;
146            locker.block();
147            n = number;
148            if (n > 1) {
149                f1 = new LockingFibTask(n - 1, locker, lock);
150                f2 = new LockingFibTask(n - 2, locker, lock);
151            }
152            lock.unlock();
153            if (n <= 1)
154                return n;
155            else {
156                f1.fork();
157                return f2.compute() + f1.join();
158            }
159        }
160    }
161
162    /**
163     * Successfully constructed pool reports default factory,
164     * parallelism and async mode policies, no active threads or
165     * tasks, and quiescent running state.
166     */
167    public void testDefaultInitialState() {
168        ForkJoinPool p = new ForkJoinPool(1);
169        try {
170            assertSame(ForkJoinPool.defaultForkJoinWorkerThreadFactory,
171                       p.getFactory());
172            assertFalse(p.getAsyncMode());
173            assertEquals(0, p.getActiveThreadCount());
174            assertEquals(0, p.getStealCount());
175            assertEquals(0, p.getQueuedTaskCount());
176            assertEquals(0, p.getQueuedSubmissionCount());
177            assertFalse(p.hasQueuedSubmissions());
178            assertFalse(p.isShutdown());
179            assertFalse(p.isTerminating());
180            assertFalse(p.isTerminated());
181        } finally {
182            joinPool(p);
183        }
184    }
185
186    /**
187     * Constructor throws if size argument is less than zero
188     */
189    public void testConstructor1() {
190        try {
191            new ForkJoinPool(-1);
192            shouldThrow();
193        } catch (IllegalArgumentException success) {}
194    }
195
196    /**
197     * Constructor throws if factory argument is null
198     */
199    public void testConstructor2() {
200        try {
201            new ForkJoinPool(1, null, null, false);
202            shouldThrow();
203        } catch (NullPointerException success) {}
204    }
205
206    /**
207     * getParallelism returns size set in constructor
208     */
209    public void testGetParallelism() {
210        ForkJoinPool p = new ForkJoinPool(1);
211        try {
212            assertEquals(1, p.getParallelism());
213        } finally {
214            joinPool(p);
215        }
216    }
217
218    /**
219     * getPoolSize returns number of started workers.
220     */
221    public void testGetPoolSize() {
222        ForkJoinPool p = new ForkJoinPool(1);
223        try {
224            assertEquals(0, p.getActiveThreadCount());
225            Future<String> future = p.submit(new StringTask());
226            assertEquals(1, p.getPoolSize());
227        } finally {
228            joinPool(p);
229        }
230    }
231
232    /**
233     * awaitTermination on a non-shutdown pool times out
234     */
235    public void testAwaitTermination_timesOut() throws InterruptedException {
236        ForkJoinPool p = new ForkJoinPool(1);
237        assertFalse(p.isTerminated());
238        assertFalse(p.awaitTermination(Long.MIN_VALUE, NANOSECONDS));
239        assertFalse(p.awaitTermination(Long.MIN_VALUE, MILLISECONDS));
240        assertFalse(p.awaitTermination(-1L, NANOSECONDS));
241        assertFalse(p.awaitTermination(-1L, MILLISECONDS));
242        assertFalse(p.awaitTermination(0L, NANOSECONDS));
243        assertFalse(p.awaitTermination(0L, MILLISECONDS));
244        long timeoutNanos = 999999L;
245        long startTime = System.nanoTime();
246        assertFalse(p.awaitTermination(timeoutNanos, NANOSECONDS));
247        assertTrue(System.nanoTime() - startTime >= timeoutNanos);
248        assertFalse(p.isTerminated());
249        startTime = System.nanoTime();
250        long timeoutMillis = timeoutMillis();
251        assertFalse(p.awaitTermination(timeoutMillis, MILLISECONDS));
252        assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
253        assertFalse(p.isTerminated());
254        p.shutdown();
255        assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
256        assertTrue(p.isTerminated());
257    }
258
259    /**
260     * setUncaughtExceptionHandler changes handler for uncaught exceptions.
261     *
262     * Additionally tests: Overriding ForkJoinWorkerThread.onStart
263     * performs its defined action
264     */
265    public void testSetUncaughtExceptionHandler() throws InterruptedException {
266        final CountDownLatch uehInvoked = new CountDownLatch(1);
267        final Thread.UncaughtExceptionHandler eh =
268            new Thread.UncaughtExceptionHandler() {
269                public void uncaughtException(Thread t, Throwable e) {
270                    uehInvoked.countDown();
271                }};
272        ForkJoinPool p = new ForkJoinPool(1, new FailingThreadFactory(),
273                                          eh, false);
274        try {
275            assertSame(eh, p.getUncaughtExceptionHandler());
276            try {
277                p.execute(new FibTask(8));
278                assertTrue(uehInvoked.await(MEDIUM_DELAY_MS, MILLISECONDS));
279            } catch (RejectedExecutionException ok) {
280            }
281        } finally {
282            p.shutdownNow(); // failure might have prevented processing task
283            joinPool(p);
284        }
285    }
286
287    /**
288     * After invoking a single task, isQuiescent eventually becomes
289     * true, at which time queues are empty, threads are not active,
290     * the task has completed successfully, and construction
291     * parameters continue to hold
292     */
293    public void testIsQuiescent() throws Exception {
294        ForkJoinPool p = new ForkJoinPool(2);
295        try {
296            assertTrue(p.isQuiescent());
297            long startTime = System.nanoTime();
298            FibTask f = new FibTask(20);
299            p.invoke(f);
300            assertSame(ForkJoinPool.defaultForkJoinWorkerThreadFactory,
301                       p.getFactory());
302            while (! p.isQuiescent()) {
303                if (millisElapsedSince(startTime) > LONG_DELAY_MS)
304                    throw new AssertionFailedError("timed out");
305                assertFalse(p.getAsyncMode());
306                assertFalse(p.isShutdown());
307                assertFalse(p.isTerminating());
308                assertFalse(p.isTerminated());
309                Thread.yield();
310            }
311
312            assertTrue(p.isQuiescent());
313            assertFalse(p.getAsyncMode());
314            assertEquals(0, p.getActiveThreadCount());
315            assertEquals(0, p.getQueuedTaskCount());
316            assertEquals(0, p.getQueuedSubmissionCount());
317            assertFalse(p.hasQueuedSubmissions());
318            assertFalse(p.isShutdown());
319            assertFalse(p.isTerminating());
320            assertFalse(p.isTerminated());
321            assertTrue(f.isDone());
322            assertEquals(6765, (int) f.get());
323        } finally {
324            joinPool(p);
325        }
326    }
327
328    /**
329     * Completed submit(ForkJoinTask) returns result
330     */
331    public void testSubmitForkJoinTask() throws Throwable {
332        ForkJoinPool p = new ForkJoinPool(1);
333        try {
334            ForkJoinTask<Integer> f = p.submit(new FibTask(8));
335            assertEquals(21, (int) f.get());
336        } finally {
337            joinPool(p);
338        }
339    }
340
341    /**
342     * A task submitted after shutdown is rejected
343     */
344    public void testSubmitAfterShutdown() {
345        ForkJoinPool p = new ForkJoinPool(1);
346        try {
347            p.shutdown();
348            assertTrue(p.isShutdown());
349            try {
350                ForkJoinTask<Integer> f = p.submit(new FibTask(8));
351                shouldThrow();
352            } catch (RejectedExecutionException success) {}
353        } finally {
354            joinPool(p);
355        }
356    }
357
358    /**
359     * Pool maintains parallelism when using ManagedBlocker
360     */
361    public void testBlockingForkJoinTask() throws Throwable {
362        ForkJoinPool p = new ForkJoinPool(4);
363        try {
364            ReentrantLock lock = new ReentrantLock();
365            ManagedLocker locker = new ManagedLocker(lock);
366            ForkJoinTask<Integer> f = new LockingFibTask(20, locker, lock);
367            p.execute(f);
368            assertEquals(6765, (int) f.get());
369        } finally {
370            p.shutdownNow(); // don't wait out shutdown
371        }
372    }
373
374    /**
375     * pollSubmission returns unexecuted submitted task, if present
376     */
377    public void testPollSubmission() {
378        final CountDownLatch done = new CountDownLatch(1);
379        SubFJP p = new SubFJP();
380        try {
381            ForkJoinTask a = p.submit(awaiter(done));
382            ForkJoinTask b = p.submit(awaiter(done));
383            ForkJoinTask c = p.submit(awaiter(done));
384            ForkJoinTask r = p.pollSubmission();
385            assertTrue(r == a || r == b || r == c);
386            assertFalse(r.isDone());
387        } finally {
388            done.countDown();
389            joinPool(p);
390        }
391    }
392
393    /**
394     * drainTasksTo transfers unexecuted submitted tasks, if present
395     */
396    public void testDrainTasksTo() {
397        final CountDownLatch done = new CountDownLatch(1);
398        SubFJP p = new SubFJP();
399        try {
400            ForkJoinTask a = p.submit(awaiter(done));
401            ForkJoinTask b = p.submit(awaiter(done));
402            ForkJoinTask c = p.submit(awaiter(done));
403            ArrayList<ForkJoinTask> al = new ArrayList();
404            p.drainTasksTo(al);
405            assertTrue(al.size() > 0);
406            for (ForkJoinTask r : al) {
407                assertTrue(r == a || r == b || r == c);
408                assertFalse(r.isDone());
409            }
410        } finally {
411            done.countDown();
412            joinPool(p);
413        }
414    }
415
416    // FJ Versions of AbstractExecutorService tests
417
418    /**
419     * execute(runnable) runs it to completion
420     */
421    public void testExecuteRunnable() throws Throwable {
422        ExecutorService e = new ForkJoinPool(1);
423        try {
424            final AtomicBoolean done = new AtomicBoolean(false);
425            Future<?> future = e.submit(new CheckedRunnable() {
426                public void realRun() {
427                    done.set(true);
428                }});
429            assertNull(future.get());
430            assertNull(future.get(0, MILLISECONDS));
431            assertTrue(done.get());
432            assertTrue(future.isDone());
433            assertFalse(future.isCancelled());
434        } finally {
435            joinPool(e);
436        }
437    }
438
439    /**
440     * Completed submit(callable) returns result
441     */
442    public void testSubmitCallable() throws Throwable {
443        ExecutorService e = new ForkJoinPool(1);
444        try {
445            Future<String> future = e.submit(new StringTask());
446            assertSame(TEST_STRING, future.get());
447            assertTrue(future.isDone());
448            assertFalse(future.isCancelled());
449        } finally {
450            joinPool(e);
451        }
452    }
453
454    /**
455     * Completed submit(runnable) returns successfully
456     */
457    public void testSubmitRunnable() throws Throwable {
458        ExecutorService e = new ForkJoinPool(1);
459        try {
460            Future<?> future = e.submit(new NoOpRunnable());
461            assertNull(future.get());
462            assertTrue(future.isDone());
463            assertFalse(future.isCancelled());
464        } finally {
465            joinPool(e);
466        }
467    }
468
469    /**
470     * Completed submit(runnable, result) returns result
471     */
472    public void testSubmitRunnable2() throws Throwable {
473        ExecutorService e = new ForkJoinPool(1);
474        try {
475            Future<String> future = e.submit(new NoOpRunnable(), TEST_STRING);
476            assertSame(TEST_STRING, future.get());
477            assertTrue(future.isDone());
478            assertFalse(future.isCancelled());
479        } finally {
480            joinPool(e);
481        }
482    }
483
484    /**
485     * A submitted privileged action runs to completion
486     */
487    public void testSubmitPrivilegedAction() throws Exception {
488        final Callable callable = Executors.callable(new PrivilegedAction() {
489                public Object run() { return TEST_STRING; }});
490        Runnable r = new CheckedRunnable() {
491        public void realRun() throws Exception {
492            ExecutorService e = new ForkJoinPool(1);
493            try {
494                Future future = e.submit(callable);
495                assertSame(TEST_STRING, future.get());
496            } finally {
497                joinPool(e);
498            }
499        }};
500
501        runWithPermissions(r, new RuntimePermission("modifyThread"));
502    }
503
504    /**
505     * A submitted privileged exception action runs to completion
506     */
507    public void testSubmitPrivilegedExceptionAction() throws Exception {
508        final Callable callable =
509            Executors.callable(new PrivilegedExceptionAction() {
510                public Object run() { return TEST_STRING; }});
511        Runnable r = new CheckedRunnable() {
512        public void realRun() throws Exception {
513            ExecutorService e = new ForkJoinPool(1);
514            try {
515                Future future = e.submit(callable);
516                assertSame(TEST_STRING, future.get());
517            } finally {
518                joinPool(e);
519            }
520        }};
521
522        runWithPermissions(r, new RuntimePermission("modifyThread"));
523    }
524
525    /**
526     * A submitted failed privileged exception action reports exception
527     */
528    public void testSubmitFailedPrivilegedExceptionAction() throws Exception {
529        final Callable callable =
530            Executors.callable(new PrivilegedExceptionAction() {
531                public Object run() { throw new IndexOutOfBoundsException(); }});
532        Runnable r = new CheckedRunnable() {
533        public void realRun() throws Exception {
534            ExecutorService e = new ForkJoinPool(1);
535            try {
536                Future future = e.submit(callable);
537                try {
538                    future.get();
539                    shouldThrow();
540                } catch (ExecutionException success) {
541                    assertTrue(success.getCause() instanceof IndexOutOfBoundsException);
542                }
543            } finally {
544                joinPool(e);
545            }
546        }};
547
548        runWithPermissions(r, new RuntimePermission("modifyThread"));
549    }
550
551    /**
552     * execute(null runnable) throws NullPointerException
553     */
554    public void testExecuteNullRunnable() {
555        ExecutorService e = new ForkJoinPool(1);
556        try {
557            Future<?> future = e.submit((Runnable) null);
558            shouldThrow();
559        } catch (NullPointerException success) {
560        } finally {
561            joinPool(e);
562        }
563    }
564
565    /**
566     * submit(null callable) throws NullPointerException
567     */
568    public void testSubmitNullCallable() {
569        ExecutorService e = new ForkJoinPool(1);
570        try {
571            Future<String> future = e.submit((Callable) null);
572            shouldThrow();
573        } catch (NullPointerException success) {
574        } finally {
575            joinPool(e);
576        }
577    }
578
579    /**
580     * submit(callable).get() throws InterruptedException if interrupted
581     */
582    public void testInterruptedSubmit() throws InterruptedException {
583        final CountDownLatch submitted    = new CountDownLatch(1);
584        final CountDownLatch quittingTime = new CountDownLatch(1);
585        final ExecutorService p = new ForkJoinPool(1);
586        final Callable<Void> awaiter = new CheckedCallable<Void>() {
587            public Void realCall() throws InterruptedException {
588                assertTrue(quittingTime.await(MEDIUM_DELAY_MS, MILLISECONDS));
589                return null;
590            }};
591        try {
592            Thread t = new Thread(new CheckedInterruptedRunnable() {
593                public void realRun() throws Exception {
594                    Future<Void> future = p.submit(awaiter);
595                    submitted.countDown();
596                    future.get();
597                }});
598            t.start();
599            assertTrue(submitted.await(MEDIUM_DELAY_MS, MILLISECONDS));
600            t.interrupt();
601            t.join();
602        } finally {
603            quittingTime.countDown();
604            joinPool(p);
605        }
606    }
607
608    /**
609     * get of submit(callable) throws ExecutionException if callable
610     * throws exception
611     */
612    public void testSubmitEE() throws Throwable {
613        ForkJoinPool p = new ForkJoinPool(1);
614        try {
615            p.submit(new Callable() {
616                public Object call() { throw new ArithmeticException(); }})
617                .get();
618            shouldThrow();
619        } catch (ExecutionException success) {
620            assertTrue(success.getCause() instanceof ArithmeticException);
621        } finally {
622            joinPool(p);
623        }
624    }
625
626    /**
627     * invokeAny(null) throws NullPointerException
628     */
629    public void testInvokeAny1() throws Throwable {
630        ExecutorService e = new ForkJoinPool(1);
631        try {
632            e.invokeAny(null);
633            shouldThrow();
634        } catch (NullPointerException success) {
635        } finally {
636            joinPool(e);
637        }
638    }
639
640    /**
641     * invokeAny(empty collection) throws IllegalArgumentException
642     */
643    public void testInvokeAny2() throws Throwable {
644        ExecutorService e = new ForkJoinPool(1);
645        try {
646            e.invokeAny(new ArrayList<Callable<String>>());
647            shouldThrow();
648        } catch (IllegalArgumentException success) {
649        } finally {
650            joinPool(e);
651        }
652    }
653
654    /**
655     * invokeAny(c) throws NullPointerException if c has a single null element
656     */
657    public void testInvokeAny3() throws Throwable {
658        ExecutorService e = new ForkJoinPool(1);
659        List<Callable<String>> l = new ArrayList<Callable<String>>();
660        l.add(null);
661        try {
662            e.invokeAny(l);
663            shouldThrow();
664        } catch (NullPointerException success) {
665        } finally {
666            joinPool(e);
667        }
668    }
669
670    /**
671     * invokeAny(c) throws NullPointerException if c has null elements
672     */
673    public void testInvokeAny4() throws Throwable {
674        CountDownLatch latch = new CountDownLatch(1);
675        ExecutorService e = new ForkJoinPool(1);
676        List<Callable<String>> l = new ArrayList<Callable<String>>();
677        l.add(latchAwaitingStringTask(latch));
678        l.add(null);
679        try {
680            e.invokeAny(l);
681            shouldThrow();
682        } catch (NullPointerException success) {
683        } finally {
684            latch.countDown();
685            joinPool(e);
686        }
687    }
688
689    /**
690     * invokeAny(c) throws ExecutionException if no task in c completes
691     */
692    public void testInvokeAny5() throws Throwable {
693        ExecutorService e = new ForkJoinPool(1);
694        List<Callable<String>> l = new ArrayList<Callable<String>>();
695        l.add(new NPETask());
696        try {
697            e.invokeAny(l);
698            shouldThrow();
699        } catch (ExecutionException success) {
700            assertTrue(success.getCause() instanceof NullPointerException);
701        } finally {
702            joinPool(e);
703        }
704    }
705
706    /**
707     * invokeAny(c) returns result of some task in c if at least one completes
708     */
709    public void testInvokeAny6() throws Throwable {
710        ExecutorService e = new ForkJoinPool(1);
711        try {
712            List<Callable<String>> l = new ArrayList<Callable<String>>();
713            l.add(new StringTask());
714            l.add(new StringTask());
715            String result = e.invokeAny(l);
716            assertSame(TEST_STRING, result);
717        } finally {
718            joinPool(e);
719        }
720    }
721
722    /**
723     * invokeAll(null) throws NullPointerException
724     */
725    public void testInvokeAll1() throws Throwable {
726        ExecutorService e = new ForkJoinPool(1);
727        try {
728            e.invokeAll(null);
729            shouldThrow();
730        } catch (NullPointerException success) {
731        } finally {
732            joinPool(e);
733        }
734    }
735
736    /**
737     * invokeAll(empty collection) returns empty collection
738     */
739    public void testInvokeAll2() throws InterruptedException {
740        ExecutorService e = new ForkJoinPool(1);
741        try {
742            List<Future<String>> r
743                = e.invokeAll(new ArrayList<Callable<String>>());
744            assertTrue(r.isEmpty());
745        } finally {
746            joinPool(e);
747        }
748    }
749
750    /**
751     * invokeAll(c) throws NullPointerException if c has null elements
752     */
753    public void testInvokeAll3() throws InterruptedException {
754        ExecutorService e = new ForkJoinPool(1);
755        List<Callable<String>> l = new ArrayList<Callable<String>>();
756        l.add(new StringTask());
757        l.add(null);
758        try {
759            e.invokeAll(l);
760            shouldThrow();
761        } catch (NullPointerException success) {
762        } finally {
763            joinPool(e);
764        }
765    }
766
767    /**
768     * get of returned element of invokeAll(c) throws
769     * ExecutionException on failed task
770     */
771    public void testInvokeAll4() throws Throwable {
772        ExecutorService e = new ForkJoinPool(1);
773        List<Callable<String>> l = new ArrayList<Callable<String>>();
774        l.add(new NPETask());
775        List<Future<String>> futures = e.invokeAll(l);
776        assertEquals(1, futures.size());
777        try {
778            futures.get(0).get();
779            shouldThrow();
780        } catch (ExecutionException success) {
781            assertTrue(success.getCause() instanceof NullPointerException);
782        } finally {
783            joinPool(e);
784        }
785    }
786
787    /**
788     * invokeAll(c) returns results of all completed tasks in c
789     */
790    public void testInvokeAll5() throws Throwable {
791        ExecutorService e = new ForkJoinPool(1);
792        try {
793            List<Callable<String>> l = new ArrayList<Callable<String>>();
794            l.add(new StringTask());
795            l.add(new StringTask());
796            List<Future<String>> futures = e.invokeAll(l);
797            assertEquals(2, futures.size());
798            for (Future<String> future : futures)
799                assertSame(TEST_STRING, future.get());
800        } finally {
801            joinPool(e);
802        }
803    }
804
805    /**
806     * timed invokeAny(null) throws NullPointerException
807     */
808    public void testTimedInvokeAny1() throws Throwable {
809        ExecutorService e = new ForkJoinPool(1);
810        try {
811            e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS);
812            shouldThrow();
813        } catch (NullPointerException success) {
814        } finally {
815            joinPool(e);
816        }
817    }
818
819    /**
820     * timed invokeAny(null time unit) throws NullPointerException
821     */
822    public void testTimedInvokeAnyNullTimeUnit() throws Throwable {
823        ExecutorService e = new ForkJoinPool(1);
824        List<Callable<String>> l = new ArrayList<Callable<String>>();
825        l.add(new StringTask());
826        try {
827            e.invokeAny(l, MEDIUM_DELAY_MS, null);
828            shouldThrow();
829        } catch (NullPointerException success) {
830        } finally {
831            joinPool(e);
832        }
833    }
834
835    /**
836     * timed invokeAny(empty collection) throws IllegalArgumentException
837     */
838    public void testTimedInvokeAny2() throws Throwable {
839        ExecutorService e = new ForkJoinPool(1);
840        try {
841            e.invokeAny(new ArrayList<Callable<String>>(),
842                        MEDIUM_DELAY_MS, MILLISECONDS);
843            shouldThrow();
844        } catch (IllegalArgumentException success) {
845        } finally {
846            joinPool(e);
847        }
848    }
849
850    /**
851     * timed invokeAny(c) throws NullPointerException if c has null elements
852     */
853    public void testTimedInvokeAny3() throws Throwable {
854        CountDownLatch latch = new CountDownLatch(1);
855        ExecutorService e = new ForkJoinPool(1);
856        List<Callable<String>> l = new ArrayList<Callable<String>>();
857        l.add(latchAwaitingStringTask(latch));
858        l.add(null);
859        try {
860            e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
861            shouldThrow();
862        } catch (NullPointerException success) {
863        } finally {
864            latch.countDown();
865            joinPool(e);
866        }
867    }
868
869    /**
870     * timed invokeAny(c) throws ExecutionException if no task completes
871     */
872    public void testTimedInvokeAny4() throws Throwable {
873        ExecutorService e = new ForkJoinPool(1);
874        List<Callable<String>> l = new ArrayList<Callable<String>>();
875        l.add(new NPETask());
876        try {
877            e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
878            shouldThrow();
879        } catch (ExecutionException success) {
880            assertTrue(success.getCause() instanceof NullPointerException);
881        } finally {
882            joinPool(e);
883        }
884    }
885
886    /**
887     * timed invokeAny(c) returns result of some task in c
888     */
889    public void testTimedInvokeAny5() throws Throwable {
890        ExecutorService e = new ForkJoinPool(1);
891        try {
892            List<Callable<String>> l = new ArrayList<Callable<String>>();
893            l.add(new StringTask());
894            l.add(new StringTask());
895            String result = e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
896            assertSame(TEST_STRING, result);
897        } finally {
898            joinPool(e);
899        }
900    }
901
902    /**
903     * timed invokeAll(null) throws NullPointerException
904     */
905    public void testTimedInvokeAll1() throws Throwable {
906        ExecutorService e = new ForkJoinPool(1);
907        try {
908            e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS);
909            shouldThrow();
910        } catch (NullPointerException success) {
911        } finally {
912            joinPool(e);
913        }
914    }
915
916    /**
917     * timed invokeAll(null time unit) throws NullPointerException
918     */
919    public void testTimedInvokeAllNullTimeUnit() throws Throwable {
920        ExecutorService e = new ForkJoinPool(1);
921        List<Callable<String>> l = new ArrayList<Callable<String>>();
922        l.add(new StringTask());
923        try {
924            e.invokeAll(l, MEDIUM_DELAY_MS, null);
925            shouldThrow();
926        } catch (NullPointerException success) {
927        } finally {
928            joinPool(e);
929        }
930    }
931
932    /**
933     * timed invokeAll(empty collection) returns empty collection
934     */
935    public void testTimedInvokeAll2() throws InterruptedException {
936        ExecutorService e = new ForkJoinPool(1);
937        try {
938            List<Future<String>> r
939                = e.invokeAll(new ArrayList<Callable<String>>(),
940                              MEDIUM_DELAY_MS, MILLISECONDS);
941            assertTrue(r.isEmpty());
942        } finally {
943            joinPool(e);
944        }
945    }
946
947    /**
948     * timed invokeAll(c) throws NullPointerException if c has null elements
949     */
950    public void testTimedInvokeAll3() throws InterruptedException {
951        ExecutorService e = new ForkJoinPool(1);
952        List<Callable<String>> l = new ArrayList<Callable<String>>();
953        l.add(new StringTask());
954        l.add(null);
955        try {
956            e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
957            shouldThrow();
958        } catch (NullPointerException success) {
959        } finally {
960            joinPool(e);
961        }
962    }
963
964    /**
965     * get of returned element of invokeAll(c) throws exception on failed task
966     */
967    public void testTimedInvokeAll4() throws Throwable {
968        ExecutorService e = new ForkJoinPool(1);
969        List<Callable<String>> l = new ArrayList<Callable<String>>();
970        l.add(new NPETask());
971        List<Future<String>> futures
972            = e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
973        assertEquals(1, futures.size());
974        try {
975            futures.get(0).get();
976            shouldThrow();
977        } catch (ExecutionException success) {
978            assertTrue(success.getCause() instanceof NullPointerException);
979        } finally {
980            joinPool(e);
981        }
982    }
983
984    /**
985     * timed invokeAll(c) returns results of all completed tasks in c
986     */
987    public void testTimedInvokeAll5() throws Throwable {
988        ExecutorService e = new ForkJoinPool(1);
989        try {
990            List<Callable<String>> l = new ArrayList<Callable<String>>();
991            l.add(new StringTask());
992            l.add(new StringTask());
993            List<Future<String>> futures
994                = e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
995            assertEquals(2, futures.size());
996            for (Future<String> future : futures)
997                assertSame(TEST_STRING, future.get());
998        } finally {
999            joinPool(e);
1000        }
1001    }
1002
1003}
1004