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.SECONDS;
10
11import java.util.HashSet;
12import java.util.concurrent.CancellationException;
13import java.util.concurrent.ExecutionException;
14import java.util.concurrent.ForkJoinPool;
15import java.util.concurrent.ForkJoinTask;
16import java.util.concurrent.RecursiveTask;
17import java.util.concurrent.TimeoutException;
18
19import junit.framework.Test;
20import junit.framework.TestSuite;
21
22public class RecursiveTaskTest extends JSR166TestCase {
23
24    // android-note: Removed because the CTS runner does a bad job of
25    // retrying tests that have suite() declarations.
26    //
27    // public static void main(String[] args) {
28    //     main(suite(), args);
29    // }
30    // public static Test suite() {
31    //     return new TestSuite(RecursiveTaskTest.class);
32    // }
33
34    private static ForkJoinPool mainPool() {
35        return new ForkJoinPool();
36    }
37
38    private static ForkJoinPool singletonPool() {
39        return new ForkJoinPool(1);
40    }
41
42    private static ForkJoinPool asyncSingletonPool() {
43        return new ForkJoinPool(1,
44                                ForkJoinPool.defaultForkJoinWorkerThreadFactory,
45                                null, true);
46    }
47
48    private <T> T testInvokeOnPool(ForkJoinPool pool, RecursiveTask<T> a) {
49        try (PoolCleaner cleaner = cleaner(pool)) {
50            checkNotDone(a);
51
52            T result = pool.invoke(a);
53
54            checkCompletedNormally(a, result);
55            return result;
56        }
57    }
58
59    void checkNotDone(RecursiveTask a) {
60        assertFalse(a.isDone());
61        assertFalse(a.isCompletedNormally());
62        assertFalse(a.isCompletedAbnormally());
63        assertFalse(a.isCancelled());
64        assertNull(a.getException());
65        assertNull(a.getRawResult());
66
67        if (! ForkJoinTask.inForkJoinPool()) {
68            Thread.currentThread().interrupt();
69            try {
70                a.get();
71                shouldThrow();
72            } catch (InterruptedException success) {
73            } catch (Throwable fail) { threadUnexpectedException(fail); }
74
75            Thread.currentThread().interrupt();
76            try {
77                a.get(5L, SECONDS);
78                shouldThrow();
79            } catch (InterruptedException success) {
80            } catch (Throwable fail) { threadUnexpectedException(fail); }
81        }
82
83        try {
84            a.get(0L, SECONDS);
85            shouldThrow();
86        } catch (TimeoutException success) {
87        } catch (Throwable fail) { threadUnexpectedException(fail); }
88    }
89
90    <T> void checkCompletedNormally(RecursiveTask<T> a, T expected) {
91        assertTrue(a.isDone());
92        assertFalse(a.isCancelled());
93        assertTrue(a.isCompletedNormally());
94        assertFalse(a.isCompletedAbnormally());
95        assertNull(a.getException());
96        assertSame(expected, a.getRawResult());
97        assertSame(expected, a.join());
98        assertFalse(a.cancel(false));
99        assertFalse(a.cancel(true));
100        try {
101            assertSame(expected, a.get());
102        } catch (Throwable fail) { threadUnexpectedException(fail); }
103        try {
104            assertSame(expected, a.get(5L, SECONDS));
105        } catch (Throwable fail) { threadUnexpectedException(fail); }
106    }
107
108    /**
109     * Waits for the task to complete, and checks that when it does,
110     * it will have an Integer result equals to the given int.
111     */
112    void checkCompletesNormally(RecursiveTask<Integer> a, int expected) {
113        Integer r = a.join();
114        assertEquals(expected, (int) r);
115        checkCompletedNormally(a, r);
116    }
117
118    /**
119     * Like checkCompletesNormally, but verifies that the task has
120     * already completed.
121     */
122    void checkCompletedNormally(RecursiveTask<Integer> a, int expected) {
123        Integer r = a.getRawResult();
124        assertEquals(expected, (int) r);
125        checkCompletedNormally(a, r);
126    }
127
128    void checkCancelled(RecursiveTask a) {
129        assertTrue(a.isDone());
130        assertTrue(a.isCancelled());
131        assertFalse(a.isCompletedNormally());
132        assertTrue(a.isCompletedAbnormally());
133        assertTrue(a.getException() instanceof CancellationException);
134        assertNull(a.getRawResult());
135
136        try {
137            a.join();
138            shouldThrow();
139        } catch (CancellationException success) {
140        } catch (Throwable fail) { threadUnexpectedException(fail); }
141
142        try {
143            a.get();
144            shouldThrow();
145        } catch (CancellationException success) {
146        } catch (Throwable fail) { threadUnexpectedException(fail); }
147
148        try {
149            a.get(5L, SECONDS);
150            shouldThrow();
151        } catch (CancellationException success) {
152        } catch (Throwable fail) { threadUnexpectedException(fail); }
153    }
154
155    void checkCompletedAbnormally(RecursiveTask a, Throwable t) {
156        assertTrue(a.isDone());
157        assertFalse(a.isCancelled());
158        assertFalse(a.isCompletedNormally());
159        assertTrue(a.isCompletedAbnormally());
160        assertSame(t.getClass(), a.getException().getClass());
161        assertNull(a.getRawResult());
162        assertFalse(a.cancel(false));
163        assertFalse(a.cancel(true));
164
165        try {
166            a.join();
167            shouldThrow();
168        } catch (Throwable expected) {
169            assertSame(t.getClass(), expected.getClass());
170        }
171
172        try {
173            a.get();
174            shouldThrow();
175        } catch (ExecutionException success) {
176            assertSame(t.getClass(), success.getCause().getClass());
177        } catch (Throwable fail) { threadUnexpectedException(fail); }
178
179        try {
180            a.get(5L, SECONDS);
181            shouldThrow();
182        } catch (ExecutionException success) {
183            assertSame(t.getClass(), success.getCause().getClass());
184        } catch (Throwable fail) { threadUnexpectedException(fail); }
185    }
186
187    public static final class FJException extends RuntimeException {
188        public FJException() { super(); }
189    }
190
191    // An invalid return value for Fib
192    static final Integer NoResult = Integer.valueOf(-17);
193
194    // A simple recursive task for testing
195    final class FibTask extends CheckedRecursiveTask<Integer> {
196        final int number;
197        FibTask(int n) { number = n; }
198        public Integer realCompute() {
199            int n = number;
200            if (n <= 1)
201                return n;
202            FibTask f1 = new FibTask(n - 1);
203            f1.fork();
204            return (new FibTask(n - 2)).compute() + f1.join();
205        }
206
207        public void publicSetRawResult(Integer result) {
208            setRawResult(result);
209        }
210    }
211
212    // A recursive action failing in base case
213    final class FailingFibTask extends RecursiveTask<Integer> {
214        final int number;
215        int result;
216        FailingFibTask(int n) { number = n; }
217        public Integer compute() {
218            int n = number;
219            if (n <= 1)
220                throw new FJException();
221            FailingFibTask f1 = new FailingFibTask(n - 1);
222            f1.fork();
223            return (new FibTask(n - 2)).compute() + f1.join();
224        }
225    }
226
227    /**
228     * invoke returns value when task completes normally.
229     * isCompletedAbnormally and isCancelled return false for normally
230     * completed tasks. getRawResult of a completed non-null task
231     * returns value;
232     */
233    public void testInvoke() {
234        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
235            public Integer realCompute() {
236                FibTask f = new FibTask(8);
237                Integer r = f.invoke();
238                assertEquals(21, (int) r);
239                checkCompletedNormally(f, r);
240                return r;
241            }};
242        assertEquals(21, (int) testInvokeOnPool(mainPool(), a));
243    }
244
245    /**
246     * quietlyInvoke task returns when task completes normally.
247     * isCompletedAbnormally and isCancelled return false for normally
248     * completed tasks
249     */
250    public void testQuietlyInvoke() {
251        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
252            public Integer realCompute() {
253                FibTask f = new FibTask(8);
254                f.quietlyInvoke();
255                checkCompletedNormally(f, 21);
256                return NoResult;
257            }};
258        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
259    }
260
261    /**
262     * join of a forked task returns when task completes
263     */
264    public void testForkJoin() {
265        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
266            public Integer realCompute() {
267                FibTask f = new FibTask(8);
268                assertSame(f, f.fork());
269                Integer r = f.join();
270                assertEquals(21, (int) r);
271                checkCompletedNormally(f, r);
272                return r;
273            }};
274        assertEquals(21, (int) testInvokeOnPool(mainPool(), a));
275    }
276
277    /**
278     * get of a forked task returns when task completes
279     */
280    public void testForkGet() {
281        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
282            public Integer realCompute() throws Exception {
283                FibTask f = new FibTask(8);
284                assertSame(f, f.fork());
285                Integer r = f.get();
286                assertEquals(21, (int) r);
287                checkCompletedNormally(f, r);
288                return r;
289            }};
290        assertEquals(21, (int) testInvokeOnPool(mainPool(), a));
291    }
292
293    /**
294     * timed get of a forked task returns when task completes
295     */
296    public void testForkTimedGet() {
297        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
298            public Integer realCompute() throws Exception {
299                FibTask f = new FibTask(8);
300                assertSame(f, f.fork());
301                Integer r = f.get(5L, SECONDS);
302                assertEquals(21, (int) r);
303                checkCompletedNormally(f, r);
304                return r;
305            }};
306        assertEquals(21, (int) testInvokeOnPool(mainPool(), a));
307    }
308
309    /**
310     * quietlyJoin of a forked task returns when task completes
311     */
312    public void testForkQuietlyJoin() {
313        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
314            public Integer realCompute() {
315                FibTask f = new FibTask(8);
316                assertSame(f, f.fork());
317                f.quietlyJoin();
318                Integer r = f.getRawResult();
319                assertEquals(21, (int) r);
320                checkCompletedNormally(f, r);
321                return r;
322            }};
323        assertEquals(21, (int) testInvokeOnPool(mainPool(), a));
324    }
325
326    /**
327     * helpQuiesce returns when tasks are complete.
328     * getQueuedTaskCount returns 0 when quiescent
329     */
330    public void testForkHelpQuiesce() {
331        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
332            public Integer realCompute() {
333                FibTask f = new FibTask(8);
334                assertSame(f, f.fork());
335                helpQuiesce();
336                while (!f.isDone()) // wait out race
337                    ;
338                assertEquals(0, getQueuedTaskCount());
339                checkCompletedNormally(f, 21);
340                return NoResult;
341            }};
342        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
343    }
344
345    /**
346     * invoke task throws exception when task completes abnormally
347     */
348    public void testAbnormalInvoke() {
349        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
350            public Integer realCompute() {
351                FailingFibTask f = new FailingFibTask(8);
352                try {
353                    f.invoke();
354                    shouldThrow();
355                } catch (FJException success) {
356                    checkCompletedAbnormally(f, success);
357                }
358                return NoResult;
359            }};
360        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
361    }
362
363    /**
364     * quietlyInvoke task returns when task completes abnormally
365     */
366    public void testAbnormalQuietlyInvoke() {
367        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
368            public Integer realCompute() {
369                FailingFibTask f = new FailingFibTask(8);
370                f.quietlyInvoke();
371                assertTrue(f.getException() instanceof FJException);
372                checkCompletedAbnormally(f, f.getException());
373                return NoResult;
374            }};
375        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
376    }
377
378    /**
379     * join of a forked task throws exception when task completes abnormally
380     */
381    public void testAbnormalForkJoin() {
382        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
383            public Integer realCompute() {
384                FailingFibTask f = new FailingFibTask(8);
385                assertSame(f, f.fork());
386                try {
387                    Integer r = f.join();
388                    shouldThrow();
389                } catch (FJException success) {
390                    checkCompletedAbnormally(f, success);
391                }
392                return NoResult;
393            }};
394        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
395    }
396
397    /**
398     * get of a forked task throws exception when task completes abnormally
399     */
400    public void testAbnormalForkGet() {
401        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
402            public Integer realCompute() throws Exception {
403                FailingFibTask f = new FailingFibTask(8);
404                assertSame(f, f.fork());
405                try {
406                    Integer r = f.get();
407                    shouldThrow();
408                } catch (ExecutionException success) {
409                    Throwable cause = success.getCause();
410                    assertTrue(cause instanceof FJException);
411                    checkCompletedAbnormally(f, cause);
412                }
413                return NoResult;
414            }};
415        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
416    }
417
418    /**
419     * timed get of a forked task throws exception when task completes abnormally
420     */
421    public void testAbnormalForkTimedGet() {
422        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
423            public Integer realCompute() throws Exception {
424                FailingFibTask f = new FailingFibTask(8);
425                assertSame(f, f.fork());
426                try {
427                    Integer r = f.get(5L, SECONDS);
428                    shouldThrow();
429                } catch (ExecutionException success) {
430                    Throwable cause = success.getCause();
431                    assertTrue(cause instanceof FJException);
432                    checkCompletedAbnormally(f, cause);
433                }
434                return NoResult;
435            }};
436        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
437    }
438
439    /**
440     * quietlyJoin of a forked task returns when task completes abnormally
441     */
442    public void testAbnormalForkQuietlyJoin() {
443        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
444            public Integer realCompute() {
445                FailingFibTask f = new FailingFibTask(8);
446                assertSame(f, f.fork());
447                f.quietlyJoin();
448                assertTrue(f.getException() instanceof FJException);
449                checkCompletedAbnormally(f, f.getException());
450                return NoResult;
451            }};
452        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
453    }
454
455    /**
456     * invoke task throws exception when task cancelled
457     */
458    public void testCancelledInvoke() {
459        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
460            public Integer realCompute() {
461                FibTask f = new FibTask(8);
462                assertTrue(f.cancel(true));
463                try {
464                    Integer r = f.invoke();
465                    shouldThrow();
466                } catch (CancellationException success) {
467                    checkCancelled(f);
468                }
469                return NoResult;
470            }};
471        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
472    }
473
474    /**
475     * join of a forked task throws exception when task cancelled
476     */
477    public void testCancelledForkJoin() {
478        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
479            public Integer realCompute() {
480                FibTask f = new FibTask(8);
481                assertTrue(f.cancel(true));
482                assertSame(f, f.fork());
483                try {
484                    Integer r = f.join();
485                    shouldThrow();
486                } catch (CancellationException success) {
487                    checkCancelled(f);
488                }
489                return NoResult;
490            }};
491        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
492    }
493
494    /**
495     * get of a forked task throws exception when task cancelled
496     */
497    public void testCancelledForkGet() {
498        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
499            public Integer realCompute() throws Exception {
500                FibTask f = new FibTask(8);
501                assertTrue(f.cancel(true));
502                assertSame(f, f.fork());
503                try {
504                    Integer r = f.get();
505                    shouldThrow();
506                } catch (CancellationException success) {
507                    checkCancelled(f);
508                }
509                return NoResult;
510            }};
511        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
512    }
513
514    /**
515     * timed get of a forked task throws exception when task cancelled
516     */
517    public void testCancelledForkTimedGet() {
518        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
519            public Integer realCompute() throws Exception {
520                FibTask f = new FibTask(8);
521                assertTrue(f.cancel(true));
522                assertSame(f, f.fork());
523                try {
524                    Integer r = f.get(5L, SECONDS);
525                    shouldThrow();
526                } catch (CancellationException success) {
527                    checkCancelled(f);
528                }
529                return NoResult;
530            }};
531        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
532    }
533
534    /**
535     * quietlyJoin of a forked task returns when task cancelled
536     */
537    public void testCancelledForkQuietlyJoin() {
538        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
539            public Integer realCompute() {
540                FibTask f = new FibTask(8);
541                assertTrue(f.cancel(true));
542                assertSame(f, f.fork());
543                f.quietlyJoin();
544                checkCancelled(f);
545                return NoResult;
546            }};
547        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
548    }
549
550    /**
551     * getPool of executing task returns its pool
552     */
553    public void testGetPool() {
554        final ForkJoinPool mainPool = mainPool();
555        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
556            public Integer realCompute() {
557                assertSame(mainPool, getPool());
558                return NoResult;
559            }};
560        assertSame(NoResult, testInvokeOnPool(mainPool, a));
561    }
562
563    /**
564     * getPool of non-FJ task returns null
565     */
566    public void testGetPool2() {
567        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
568            public Integer realCompute() {
569                assertNull(getPool());
570                return NoResult;
571            }};
572        assertSame(NoResult, a.invoke());
573    }
574
575    /**
576     * inForkJoinPool of executing task returns true
577     */
578    public void testInForkJoinPool() {
579        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
580            public Integer realCompute() {
581                assertTrue(inForkJoinPool());
582                return NoResult;
583            }};
584        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
585    }
586
587    /**
588     * inForkJoinPool of non-FJ task returns false
589     */
590    public void testInForkJoinPool2() {
591        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
592            public Integer realCompute() {
593                assertFalse(inForkJoinPool());
594                return NoResult;
595            }};
596        assertSame(NoResult, a.invoke());
597    }
598
599    /**
600     * The value set by setRawResult is returned by getRawResult
601     */
602    public void testSetRawResult() {
603        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
604            public Integer realCompute() {
605                setRawResult(NoResult);
606                assertSame(NoResult, getRawResult());
607                return NoResult;
608            }
609        };
610        assertSame(NoResult, a.invoke());
611    }
612
613    /**
614     * A reinitialized normally completed task may be re-invoked
615     */
616    public void testReinitialize() {
617        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
618            public Integer realCompute() {
619                FibTask f = new FibTask(8);
620                checkNotDone(f);
621
622                for (int i = 0; i < 3; i++) {
623                    Integer r = f.invoke();
624                    assertEquals(21, (int) r);
625                    checkCompletedNormally(f, r);
626                    f.reinitialize();
627                    f.publicSetRawResult(null);
628                    checkNotDone(f);
629                }
630                return NoResult;
631            }};
632        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
633    }
634
635    /**
636     * A reinitialized abnormally completed task may be re-invoked
637     */
638    public void testReinitializeAbnormal() {
639        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
640            public Integer realCompute() {
641                FailingFibTask f = new FailingFibTask(8);
642                checkNotDone(f);
643
644                for (int i = 0; i < 3; i++) {
645                    try {
646                        f.invoke();
647                        shouldThrow();
648                    } catch (FJException success) {
649                        checkCompletedAbnormally(f, success);
650                    }
651                    f.reinitialize();
652                    checkNotDone(f);
653                }
654                return NoResult;
655            }};
656        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
657    }
658
659    /**
660     * invoke task throws exception after invoking completeExceptionally
661     */
662    public void testCompleteExceptionally() {
663        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
664            public Integer realCompute() {
665                FibTask f = new FibTask(8);
666                f.completeExceptionally(new FJException());
667                try {
668                    Integer r = f.invoke();
669                    shouldThrow();
670                } catch (FJException success) {
671                    checkCompletedAbnormally(f, success);
672                }
673                return NoResult;
674            }};
675        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
676    }
677
678    /**
679     * invoke task suppresses execution invoking complete
680     */
681    public void testComplete() {
682        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
683            public Integer realCompute() {
684                FibTask f = new FibTask(8);
685                f.complete(NoResult);
686                Integer r = f.invoke();
687                assertSame(NoResult, r);
688                checkCompletedNormally(f, NoResult);
689                return r;
690            }};
691        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
692    }
693
694    /**
695     * invokeAll(t1, t2) invokes all task arguments
696     */
697    public void testInvokeAll2() {
698        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
699            public Integer realCompute() {
700                FibTask f = new FibTask(8);
701                FibTask g = new FibTask(9);
702                invokeAll(f, g);
703                checkCompletedNormally(f, 21);
704                checkCompletedNormally(g, 34);
705                return NoResult;
706            }};
707        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
708    }
709
710    /**
711     * invokeAll(tasks) with 1 argument invokes task
712     */
713    public void testInvokeAll1() {
714        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
715            public Integer realCompute() {
716                FibTask f = new FibTask(8);
717                invokeAll(f);
718                checkCompletedNormally(f, 21);
719                return NoResult;
720            }};
721        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
722    }
723
724    /**
725     * invokeAll(tasks) with > 2 argument invokes tasks
726     */
727    public void testInvokeAll3() {
728        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
729            public Integer realCompute() {
730                FibTask f = new FibTask(8);
731                FibTask g = new FibTask(9);
732                FibTask h = new FibTask(7);
733                invokeAll(f, g, h);
734                assertTrue(f.isDone());
735                assertTrue(g.isDone());
736                assertTrue(h.isDone());
737                checkCompletedNormally(f, 21);
738                checkCompletedNormally(g, 34);
739                checkCompletedNormally(h, 13);
740                return NoResult;
741            }};
742        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
743    }
744
745    /**
746     * invokeAll(collection) invokes all tasks in the collection
747     */
748    public void testInvokeAllCollection() {
749        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
750            public Integer realCompute() {
751                FibTask f = new FibTask(8);
752                FibTask g = new FibTask(9);
753                FibTask h = new FibTask(7);
754                HashSet set = new HashSet();
755                set.add(f);
756                set.add(g);
757                set.add(h);
758                invokeAll(set);
759                assertTrue(f.isDone());
760                assertTrue(g.isDone());
761                assertTrue(h.isDone());
762                checkCompletedNormally(f, 21);
763                checkCompletedNormally(g, 34);
764                checkCompletedNormally(h, 13);
765                return NoResult;
766            }};
767        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
768    }
769
770    /**
771     * invokeAll(tasks) with any null task throws NPE
772     */
773    public void testInvokeAllNPE() {
774        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
775            public Integer realCompute() {
776                FibTask f = new FibTask(8);
777                FibTask g = new FibTask(9);
778                FibTask h = null;
779                try {
780                    invokeAll(f, g, h);
781                    shouldThrow();
782                } catch (NullPointerException success) {}
783                return NoResult;
784            }};
785        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
786    }
787
788    /**
789     * invokeAll(t1, t2) throw exception if any task does
790     */
791    public void testAbnormalInvokeAll2() {
792        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
793            public Integer realCompute() {
794                FibTask f = new FibTask(8);
795                FailingFibTask g = new FailingFibTask(9);
796                try {
797                    invokeAll(f, g);
798                    shouldThrow();
799                } catch (FJException success) {
800                    checkCompletedAbnormally(g, success);
801                }
802                return NoResult;
803            }};
804        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
805    }
806
807    /**
808     * invokeAll(tasks) with 1 argument throws exception if task does
809     */
810    public void testAbnormalInvokeAll1() {
811        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
812            public Integer realCompute() {
813                FailingFibTask g = new FailingFibTask(9);
814                try {
815                    invokeAll(g);
816                    shouldThrow();
817                } catch (FJException success) {
818                    checkCompletedAbnormally(g, success);
819                }
820                return NoResult;
821            }};
822        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
823    }
824
825    /**
826     * invokeAll(tasks) with > 2 argument throws exception if any task does
827     */
828    public void testAbnormalInvokeAll3() {
829        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
830            public Integer realCompute() {
831                FibTask f = new FibTask(8);
832                FailingFibTask g = new FailingFibTask(9);
833                FibTask h = new FibTask(7);
834                try {
835                    invokeAll(f, g, h);
836                    shouldThrow();
837                } catch (FJException success) {
838                    checkCompletedAbnormally(g, success);
839                }
840                return NoResult;
841            }};
842        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
843    }
844
845    /**
846     * invokeAll(collection) throws exception if any task does
847     */
848    public void testAbnormalInvokeAllCollection() {
849        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
850            public Integer realCompute() {
851                FailingFibTask f = new FailingFibTask(8);
852                FibTask g = new FibTask(9);
853                FibTask h = new FibTask(7);
854                HashSet set = new HashSet();
855                set.add(f);
856                set.add(g);
857                set.add(h);
858                try {
859                    invokeAll(set);
860                    shouldThrow();
861                } catch (FJException success) {
862                    checkCompletedAbnormally(f, success);
863                }
864                return NoResult;
865            }};
866        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
867    }
868
869    /**
870     * tryUnfork returns true for most recent unexecuted task,
871     * and suppresses execution
872     */
873    public void testTryUnfork() {
874        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
875            public Integer realCompute() {
876                FibTask g = new FibTask(9);
877                assertSame(g, g.fork());
878                FibTask f = new FibTask(8);
879                assertSame(f, f.fork());
880                assertTrue(f.tryUnfork());
881                helpQuiesce();
882                checkNotDone(f);
883                checkCompletedNormally(g, 34);
884                return NoResult;
885            }};
886        assertSame(NoResult, testInvokeOnPool(singletonPool(), a));
887    }
888
889    /**
890     * getSurplusQueuedTaskCount returns > 0 when
891     * there are more tasks than threads
892     */
893    public void testGetSurplusQueuedTaskCount() {
894        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
895            public Integer realCompute() {
896                FibTask h = new FibTask(7);
897                assertSame(h, h.fork());
898                FibTask g = new FibTask(9);
899                assertSame(g, g.fork());
900                FibTask f = new FibTask(8);
901                assertSame(f, f.fork());
902                assertTrue(getSurplusQueuedTaskCount() > 0);
903                helpQuiesce();
904                assertEquals(0, getSurplusQueuedTaskCount());
905                checkCompletedNormally(f, 21);
906                checkCompletedNormally(g, 34);
907                checkCompletedNormally(h, 13);
908                return NoResult;
909            }};
910        assertSame(NoResult, testInvokeOnPool(singletonPool(), a));
911    }
912
913    /**
914     * peekNextLocalTask returns most recent unexecuted task.
915     */
916    public void testPeekNextLocalTask() {
917        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
918            public Integer realCompute() {
919                FibTask g = new FibTask(9);
920                assertSame(g, g.fork());
921                FibTask f = new FibTask(8);
922                assertSame(f, f.fork());
923                assertSame(f, peekNextLocalTask());
924                checkCompletesNormally(f, 21);
925                helpQuiesce();
926                checkCompletedNormally(g, 34);
927                return NoResult;
928            }};
929        assertSame(NoResult, testInvokeOnPool(singletonPool(), a));
930    }
931
932    /**
933     * pollNextLocalTask returns most recent unexecuted task
934     * without executing it
935     */
936    public void testPollNextLocalTask() {
937        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
938            public Integer realCompute() {
939                FibTask g = new FibTask(9);
940                assertSame(g, g.fork());
941                FibTask f = new FibTask(8);
942                assertSame(f, f.fork());
943                assertSame(f, pollNextLocalTask());
944                helpQuiesce();
945                checkNotDone(f);
946                checkCompletedNormally(g, 34);
947                return NoResult;
948            }};
949        assertSame(NoResult, testInvokeOnPool(singletonPool(), a));
950    }
951
952    /**
953     * pollTask returns an unexecuted task without executing it
954     */
955    public void testPollTask() {
956        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
957            public Integer realCompute() {
958                FibTask g = new FibTask(9);
959                assertSame(g, g.fork());
960                FibTask f = new FibTask(8);
961                assertSame(f, f.fork());
962                assertSame(f, pollTask());
963                helpQuiesce();
964                checkNotDone(f);
965                checkCompletedNormally(g, 34);
966                return NoResult;
967            }};
968        assertSame(NoResult, testInvokeOnPool(singletonPool(), a));
969    }
970
971    /**
972     * peekNextLocalTask returns least recent unexecuted task in async mode
973     */
974    public void testPeekNextLocalTaskAsync() {
975        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
976            public Integer realCompute() {
977                FibTask g = new FibTask(9);
978                assertSame(g, g.fork());
979                FibTask f = new FibTask(8);
980                assertSame(f, f.fork());
981                assertSame(g, peekNextLocalTask());
982                assertEquals(21, (int) f.join());
983                helpQuiesce();
984                checkCompletedNormally(f, 21);
985                checkCompletedNormally(g, 34);
986                return NoResult;
987            }};
988        assertSame(NoResult, testInvokeOnPool(asyncSingletonPool(), a));
989    }
990
991    /**
992     * pollNextLocalTask returns least recent unexecuted task without
993     * executing it, in async mode
994     */
995    public void testPollNextLocalTaskAsync() {
996        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
997            public Integer realCompute() {
998                FibTask g = new FibTask(9);
999                assertSame(g, g.fork());
1000                FibTask f = new FibTask(8);
1001                assertSame(f, f.fork());
1002                assertSame(g, pollNextLocalTask());
1003                helpQuiesce();
1004                checkCompletedNormally(f, 21);
1005                checkNotDone(g);
1006                return NoResult;
1007            }};
1008        assertSame(NoResult, testInvokeOnPool(asyncSingletonPool(), a));
1009    }
1010
1011    /**
1012     * pollTask returns an unexecuted task without executing it, in
1013     * async mode
1014     */
1015    public void testPollTaskAsync() {
1016        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
1017            public Integer realCompute() {
1018                FibTask g = new FibTask(9);
1019                assertSame(g, g.fork());
1020                FibTask f = new FibTask(8);
1021                assertSame(f, f.fork());
1022                assertSame(g, pollTask());
1023                helpQuiesce();
1024                checkCompletedNormally(f, 21);
1025                checkNotDone(g);
1026                return NoResult;
1027            }};
1028        assertSame(NoResult, testInvokeOnPool(asyncSingletonPool(), a));
1029    }
1030
1031}
1032