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