RecursiveTaskTest.java revision 17486:81e4e95b2288
1228753Smm/*
2228753Smm * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3228753Smm *
4228753Smm * This code is free software; you can redistribute it and/or modify it
5228753Smm * under the terms of the GNU General Public License version 2 only, as
6228753Smm * published by the Free Software Foundation.
7228753Smm *
8228753Smm * This code is distributed in the hope that it will be useful, but WITHOUT
9228753Smm * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10228753Smm * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
11228753Smm * version 2 for more details (a copy is included in the LICENSE file that
12228753Smm * accompanied this code).
13228753Smm *
14228753Smm * You should have received a copy of the GNU General Public License version
15228753Smm * 2 along with this work; if not, write to the Free Software Foundation,
16228753Smm * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17228753Smm *
18228753Smm * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19228753Smm * or visit www.oracle.com if you need additional information or have any
20228753Smm * questions.
21228753Smm */
22228753Smm
23228753Smm/*
24228753Smm * This file is available under and governed by the GNU General Public
25228753Smm * License version 2 only, as published by the Free Software Foundation.
26228753Smm * However, the following notice accompanied the original version of this
27228753Smm * file:
28228753Smm *
29228753Smm * Written by Doug Lea with assistance from members of JCP JSR-166
30228753Smm * Expert Group and released to the public domain, as explained at
31228753Smm * http://creativecommons.org/publicdomain/zero/1.0/
32228753Smm */
33228753Smm
34228753Smmimport static java.util.concurrent.TimeUnit.MILLISECONDS;
35228753Smm
36228753Smmimport java.util.HashSet;
37228753Smmimport java.util.concurrent.CancellationException;
38228753Smmimport java.util.concurrent.ExecutionException;
39228753Smmimport java.util.concurrent.ForkJoinPool;
40228753Smmimport java.util.concurrent.ForkJoinTask;
41228753Smmimport java.util.concurrent.RecursiveTask;
42228753Smmimport java.util.concurrent.TimeoutException;
43228753Smm
44228753Smmimport junit.framework.Test;
45228753Smmimport junit.framework.TestSuite;
46248616Smm
47228753Smmpublic class RecursiveTaskTest extends JSR166TestCase {
48228753Smm
49231200Smm    public static void main(String[] args) {
50228753Smm        main(suite(), args);
51228753Smm    }
52228753Smm    public static Test suite() {
53231200Smm        return new TestSuite(RecursiveTaskTest.class);
54231200Smm    }
55231200Smm
56231200Smm    private static ForkJoinPool mainPool() {
57231200Smm        return new ForkJoinPool();
58228753Smm    }
59228753Smm
60228753Smm    private static ForkJoinPool singletonPool() {
61231200Smm        return new ForkJoinPool(1);
62248616Smm    }
63248616Smm
64228753Smm    private static ForkJoinPool asyncSingletonPool() {
65228753Smm        return new ForkJoinPool(1,
66228753Smm                                ForkJoinPool.defaultForkJoinWorkerThreadFactory,
67228753Smm                                null, true);
68228753Smm    }
69248616Smm
70248616Smm    private <T> T testInvokeOnPool(ForkJoinPool pool, RecursiveTask<T> a) {
71248616Smm        try (PoolCleaner cleaner = cleaner(pool)) {
72228753Smm            checkNotDone(a);
73228753Smm
74228753Smm            T result = pool.invoke(a);
75228753Smm
76228753Smm            checkCompletedNormally(a, result);
77228753Smm            return result;
78228753Smm        }
79228753Smm    }
80228753Smm
81231200Smm    void checkNotDone(RecursiveTask a) {
82228753Smm        assertFalse(a.isDone());
83231200Smm        assertFalse(a.isCompletedNormally());
84231200Smm        assertFalse(a.isCompletedAbnormally());
85228753Smm        assertFalse(a.isCancelled());
86231200Smm        assertNull(a.getException());
87231200Smm        assertNull(a.getRawResult());
88248616Smm
89231200Smm        if (! ForkJoinTask.inForkJoinPool()) {
90231200Smm            Thread.currentThread().interrupt();
91248616Smm            try {
92228753Smm                a.get();
93228753Smm                shouldThrow();
94228753Smm            } catch (InterruptedException success) {
95231200Smm            } catch (Throwable fail) { threadUnexpectedException(fail); }
96228753Smm
97228753Smm            Thread.currentThread().interrupt();
98231200Smm            try {
99228753Smm                a.get(randomTimeout(), randomTimeUnit());
100228753Smm                shouldThrow();
101231200Smm            } catch (InterruptedException success) {
102231200Smm            } catch (Throwable fail) { threadUnexpectedException(fail); }
103231200Smm        }
104231200Smm
105231200Smm        try {
106231200Smm            a.get(randomExpiredTimeout(), randomTimeUnit());
107231200Smm            shouldThrow();
108228753Smm        } catch (TimeoutException success) {
109228753Smm        } catch (Throwable fail) { threadUnexpectedException(fail); }
110228753Smm    }
111231200Smm
112231200Smm    <T> void checkCompletedNormally(RecursiveTask<T> a, T expected) {
113231200Smm        assertTrue(a.isDone());
114231200Smm        assertFalse(a.isCancelled());
115231200Smm        assertTrue(a.isCompletedNormally());
116248616Smm        assertFalse(a.isCompletedAbnormally());
117231200Smm        assertNull(a.getException());
118248616Smm        assertSame(expected, a.getRawResult());
119248616Smm        assertSame(expected, a.join());
120228753Smm        assertFalse(a.cancel(false));
121248616Smm        assertFalse(a.cancel(true));
122248616Smm        try {
123248616Smm            assertSame(expected, a.get());
124248616Smm            assertSame(expected, a.get(randomTimeout(), randomTimeUnit()));
125248616Smm        } catch (Throwable fail) { threadUnexpectedException(fail); }
126248616Smm    }
127248616Smm
128248616Smm    /**
129248616Smm     * Waits for the task to complete, and checks that when it does,
130248616Smm     * it will have an Integer result equals to the given int.
131248616Smm     */
132248616Smm    void checkCompletesNormally(RecursiveTask<Integer> a, int expected) {
133228753Smm        Integer r = a.join();
134228753Smm        assertEquals(expected, (int) r);
135248616Smm        checkCompletedNormally(a, r);
136248616Smm    }
137248616Smm
138248616Smm    /**
139248616Smm     * Like checkCompletesNormally, but verifies that the task has
140248616Smm     * already completed.
141248616Smm     */
142248616Smm    void checkCompletedNormally(RecursiveTask<Integer> a, int expected) {
143248616Smm        Integer r = a.getRawResult();
144248616Smm        assertEquals(expected, (int) r);
145248616Smm        checkCompletedNormally(a, r);
146248616Smm    }
147248616Smm
148248616Smm    void checkCancelled(RecursiveTask a) {
149248616Smm        assertTrue(a.isDone());
150228753Smm        assertTrue(a.isCancelled());
151248616Smm        assertFalse(a.isCompletedNormally());
152248616Smm        assertTrue(a.isCompletedAbnormally());
153248616Smm        assertTrue(a.getException() instanceof CancellationException);
154248616Smm        assertNull(a.getRawResult());
155248616Smm
156248616Smm        try {
157248616Smm            a.join();
158248616Smm            shouldThrow();
159248616Smm        } catch (CancellationException success) {
160248616Smm        } catch (Throwable fail) { threadUnexpectedException(fail); }
161248616Smm
162248616Smm        try {
163248616Smm            a.get();
164248616Smm            shouldThrow();
165248616Smm        } catch (CancellationException success) {
166248616Smm        } catch (Throwable fail) { threadUnexpectedException(fail); }
167248616Smm
168248616Smm        try {
169248616Smm            a.get(randomTimeout(), randomTimeUnit());
170248616Smm            shouldThrow();
171248616Smm        } catch (CancellationException success) {
172248616Smm        } catch (Throwable fail) { threadUnexpectedException(fail); }
173248616Smm    }
174248616Smm
175248616Smm    void checkCompletedAbnormally(RecursiveTask a, Throwable t) {
176248616Smm        assertTrue(a.isDone());
177248616Smm        assertFalse(a.isCancelled());
178248616Smm        assertFalse(a.isCompletedNormally());
179228753Smm        assertTrue(a.isCompletedAbnormally());
180228753Smm        assertSame(t.getClass(), a.getException().getClass());
181228753Smm        assertNull(a.getRawResult());
182231200Smm        assertFalse(a.cancel(false));
183228753Smm        assertFalse(a.cancel(true));
184231200Smm
185228753Smm        try {
186228753Smm            a.join();
187231200Smm            shouldThrow();
188231200Smm        } catch (Throwable expected) {
189231200Smm            assertSame(t.getClass(), expected.getClass());
190228753Smm        }
191231200Smm
192238856Smm        try {
193238856Smm            a.get();
194248616Smm            shouldThrow();
195248616Smm        } catch (ExecutionException success) {
196238856Smm            assertSame(t.getClass(), success.getCause().getClass());
197238856Smm        } catch (Throwable fail) { threadUnexpectedException(fail); }
198238856Smm
199238856Smm        try {
200238856Smm            a.get(randomTimeout(), randomTimeUnit());
201238856Smm            shouldThrow();
202238856Smm        } catch (ExecutionException success) {
203231200Smm            assertSame(t.getClass(), success.getCause().getClass());
204231200Smm        } catch (Throwable fail) { threadUnexpectedException(fail); }
205231200Smm    }
206231200Smm
207231200Smm    public static final class FJException extends RuntimeException {
208231200Smm        public FJException() { super(); }
209231200Smm    }
210228753Smm
211228753Smm    /** An invalid return value for Fib. */
212231200Smm    static final Integer NoResult = Integer.valueOf(-17);
213231200Smm
214248616Smm    /** A simple recursive task for testing. */
215228753Smm    final class FibTask extends CheckedRecursiveTask<Integer> {
216228753Smm        final int number;
217231200Smm        FibTask(int n) { number = n; }
218231200Smm        public Integer realCompute() {
219231200Smm            int n = number;
220231200Smm            if (n <= 1)
221248616Smm                return n;
222248616Smm            FibTask f1 = new FibTask(n - 1);
223248616Smm            f1.fork();
224248616Smm            return (new FibTask(n - 2)).compute() + f1.join();
225248616Smm        }
226248616Smm
227248616Smm        public void publicSetRawResult(Integer result) {
228248616Smm            setRawResult(result);
229231200Smm        }
230231200Smm    }
231231200Smm
232231200Smm    /** A recursive action failing in base case. */
233228753Smm    final class FailingFibTask extends RecursiveTask<Integer> {
234231200Smm        final int number;
235228753Smm        int result;
236228753Smm        FailingFibTask(int n) { number = n; }
237231200Smm        public Integer compute() {
238231200Smm            int n = number;
239228753Smm            if (n <= 1)
240228753Smm                throw new FJException();
241228753Smm            FailingFibTask f1 = new FailingFibTask(n - 1);
242228753Smm            f1.fork();
243228753Smm            return (new FibTask(n - 2)).compute() + f1.join();
244228753Smm        }
245231200Smm    }
246231200Smm
247228753Smm    /**
248228753Smm     * invoke returns value when task completes normally.
249228753Smm     * isCompletedAbnormally and isCancelled return false for normally
250231200Smm     * completed tasks. getRawResult of a completed non-null task
251228753Smm     * returns value;
252228753Smm     */
253228753Smm    public void testInvoke() {
254228753Smm        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
255228753Smm            public Integer realCompute() {
256231200Smm                FibTask f = new FibTask(8);
257228753Smm                Integer r = f.invoke();
258228753Smm                assertEquals(21, (int) r);
259228753Smm                checkCompletedNormally(f, r);
260228753Smm                return r;
261248616Smm            }};
262248616Smm        assertEquals(21, (int) testInvokeOnPool(mainPool(), a));
263228753Smm    }
264228753Smm
265231200Smm    /**
266228753Smm     * quietlyInvoke task returns when task completes normally.
267228753Smm     * isCompletedAbnormally and isCancelled return false for normally
268228753Smm     * completed tasks
269228753Smm     */
270228753Smm    public void testQuietlyInvoke() {
271228753Smm        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
272228753Smm            public Integer realCompute() {
273228753Smm                FibTask f = new FibTask(8);
274228753Smm                f.quietlyInvoke();
275228753Smm                checkCompletedNormally(f, 21);
276228753Smm                return NoResult;
277228753Smm            }};
278231200Smm        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
279228753Smm    }
280228753Smm
281231200Smm    /**
282228753Smm     * join of a forked task returns when task completes
283228753Smm     */
284228753Smm    public void testForkJoin() {
285248616Smm        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
286231200Smm            public Integer realCompute() {
287228753Smm                FibTask f = new FibTask(8);
288228753Smm                assertSame(f, f.fork());
289231200Smm                Integer r = f.join();
290248616Smm                assertEquals(21, (int) r);
291231200Smm                checkCompletedNormally(f, r);
292228753Smm                return r;
293228753Smm            }};
294228753Smm        assertEquals(21, (int) testInvokeOnPool(mainPool(), a));
295228753Smm    }
296228753Smm
297228753Smm    /**
298228753Smm     * get of a forked task returns when task completes
299228753Smm     */
300228753Smm    public void testForkGet() {
301231200Smm        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
302228753Smm            public Integer realCompute() throws Exception {
303228753Smm                FibTask f = new FibTask(8);
304231200Smm                assertSame(f, f.fork());
305231200Smm                Integer r = f.get();
306228753Smm                assertEquals(21, (int) r);
307231200Smm                checkCompletedNormally(f, r);
308231200Smm                return r;
309231200Smm            }};
310231200Smm        assertEquals(21, (int) testInvokeOnPool(mainPool(), a));
311231200Smm    }
312231200Smm
313231200Smm    /**
314231200Smm     * timed get of a forked task returns when task completes
315231200Smm     */
316231200Smm    public void testForkTimedGet() {
317238856Smm        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
318238856Smm            public Integer realCompute() throws Exception {
319238856Smm                FibTask f = new FibTask(8);
320238856Smm                assertSame(f, f.fork());
321238856Smm                Integer r = f.get(LONG_DELAY_MS, MILLISECONDS);
322238856Smm                assertEquals(21, (int) r);
323238856Smm                checkCompletedNormally(f, r);
324238856Smm                return r;
325231200Smm            }};
326231200Smm        assertEquals(21, (int) testInvokeOnPool(mainPool(), a));
327228753Smm    }
328231200Smm
329231200Smm    /**
330231200Smm     * quietlyJoin of a forked task returns when task completes
331231200Smm     */
332231200Smm    public void testForkQuietlyJoin() {
333231200Smm        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
334231200Smm            public Integer realCompute() {
335228753Smm                FibTask f = new FibTask(8);
336231200Smm                assertSame(f, f.fork());
337231200Smm                f.quietlyJoin();
338228753Smm                Integer r = f.getRawResult();
339228753Smm                assertEquals(21, (int) r);
340228753Smm                checkCompletedNormally(f, r);
341228753Smm                return r;
342228753Smm            }};
343228753Smm        assertEquals(21, (int) testInvokeOnPool(mainPool(), a));
344228753Smm    }
345228753Smm
346228753Smm    /**
347228753Smm     * helpQuiesce returns when tasks are complete.
348231200Smm     * getQueuedTaskCount returns 0 when quiescent
349231200Smm     */
350228753Smm    public void testForkHelpQuiesce() {
351228753Smm        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
352228753Smm            public Integer realCompute() {
353228753Smm                FibTask f = new FibTask(8);
354231200Smm                assertSame(f, f.fork());
355231200Smm                helpQuiesce();
356231200Smm                while (!f.isDone()) // wait out race
357231200Smm                    ;
358231200Smm                assertEquals(0, getQueuedTaskCount());
359228753Smm                checkCompletedNormally(f, 21);
360231200Smm                return NoResult;
361248616Smm            }};
362248616Smm        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
363228753Smm    }
364228753Smm
365228753Smm    /**
366231200Smm     * invoke task throws exception when task completes abnormally
367228753Smm     */
368228753Smm    public void testAbnormalInvoke() {
369231200Smm        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
370228753Smm            public Integer realCompute() {
371228753Smm                FailingFibTask f = new FailingFibTask(8);
372228753Smm                try {
373228753Smm                    f.invoke();
374228753Smm                    shouldThrow();
375228753Smm                } catch (FJException success) {
376231200Smm                    checkCompletedAbnormally(f, success);
377228753Smm                }
378228753Smm                return NoResult;
379228753Smm            }};
380228753Smm        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
381228753Smm    }
382228753Smm
383228753Smm    /**
384228753Smm     * quietlyInvoke task returns when task completes abnormally
385228753Smm     */
386231200Smm    public void testAbnormalQuietlyInvoke() {
387228753Smm        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
388228753Smm            public Integer realCompute() {
389228753Smm                FailingFibTask f = new FailingFibTask(8);
390228753Smm                f.quietlyInvoke();
391228753Smm                assertTrue(f.getException() instanceof FJException);
392228753Smm                checkCompletedAbnormally(f, f.getException());
393228753Smm                return NoResult;
394228753Smm            }};
395248616Smm        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
396248616Smm    }
397248616Smm
398248616Smm    /**
399248616Smm     * join of a forked task throws exception when task completes abnormally
400248616Smm     */
401248616Smm    public void testAbnormalForkJoin() {
402248616Smm        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
403248616Smm            public Integer realCompute() {
404248616Smm                FailingFibTask f = new FailingFibTask(8);
405248616Smm                assertSame(f, f.fork());
406248616Smm                try {
407248616Smm                    Integer r = f.join();
408248616Smm                    shouldThrow();
409248616Smm                } catch (FJException success) {
410248616Smm                    checkCompletedAbnormally(f, success);
411248616Smm                }
412248616Smm                return NoResult;
413248616Smm            }};
414248616Smm        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
415248616Smm    }
416248616Smm
417248616Smm    /**
418248616Smm     * get of a forked task throws exception when task completes abnormally
419248616Smm     */
420248616Smm    public void testAbnormalForkGet() {
421248616Smm        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
422248616Smm            public Integer realCompute() throws Exception {
423248616Smm                FailingFibTask f = new FailingFibTask(8);
424248616Smm                assertSame(f, f.fork());
425248616Smm                try {
426248616Smm                    Integer r = f.get();
427248616Smm                    shouldThrow();
428248616Smm                } catch (ExecutionException success) {
429248616Smm                    Throwable cause = success.getCause();
430248616Smm                    assertTrue(cause instanceof FJException);
431248616Smm                    checkCompletedAbnormally(f, cause);
432248616Smm                }
433248616Smm                return NoResult;
434248616Smm            }};
435248616Smm        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
436248616Smm    }
437248616Smm
438248616Smm    /**
439248616Smm     * timed get of a forked task throws exception when task completes abnormally
440248616Smm     */
441248616Smm    public void testAbnormalForkTimedGet() {
442228753Smm        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
443            public Integer realCompute() throws Exception {
444                FailingFibTask f = new FailingFibTask(8);
445                assertSame(f, f.fork());
446                try {
447                    Integer r = f.get(LONG_DELAY_MS, MILLISECONDS);
448                    shouldThrow();
449                } catch (ExecutionException success) {
450                    Throwable cause = success.getCause();
451                    assertTrue(cause instanceof FJException);
452                    checkCompletedAbnormally(f, cause);
453                }
454                return NoResult;
455            }};
456        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
457    }
458
459    /**
460     * quietlyJoin of a forked task returns when task completes abnormally
461     */
462    public void testAbnormalForkQuietlyJoin() {
463        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
464            public Integer realCompute() {
465                FailingFibTask f = new FailingFibTask(8);
466                assertSame(f, f.fork());
467                f.quietlyJoin();
468                assertTrue(f.getException() instanceof FJException);
469                checkCompletedAbnormally(f, f.getException());
470                return NoResult;
471            }};
472        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
473    }
474
475    /**
476     * invoke task throws exception when task cancelled
477     */
478    public void testCancelledInvoke() {
479        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
480            public Integer realCompute() {
481                FibTask f = new FibTask(8);
482                assertTrue(f.cancel(true));
483                try {
484                    Integer r = f.invoke();
485                    shouldThrow();
486                } catch (CancellationException success) {
487                    checkCancelled(f);
488                }
489                return NoResult;
490            }};
491        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
492    }
493
494    /**
495     * join of a forked task throws exception when task cancelled
496     */
497    public void testCancelledForkJoin() {
498        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
499            public Integer realCompute() {
500                FibTask f = new FibTask(8);
501                assertTrue(f.cancel(true));
502                assertSame(f, f.fork());
503                try {
504                    Integer r = f.join();
505                    shouldThrow();
506                } catch (CancellationException success) {
507                    checkCancelled(f);
508                }
509                return NoResult;
510            }};
511        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
512    }
513
514    /**
515     * get of a forked task throws exception when task cancelled
516     */
517    public void testCancelledForkGet() {
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();
525                    shouldThrow();
526                } catch (CancellationException success) {
527                    checkCancelled(f);
528                }
529                return NoResult;
530            }};
531        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
532    }
533
534    /**
535     * timed get of a forked task throws exception when task cancelled
536     */
537    public void testCancelledForkTimedGet() {
538        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
539            public Integer realCompute() throws Exception {
540                FibTask f = new FibTask(8);
541                assertTrue(f.cancel(true));
542                assertSame(f, f.fork());
543                try {
544                    Integer r = f.get(LONG_DELAY_MS, MILLISECONDS);
545                    shouldThrow();
546                } catch (CancellationException success) {
547                    checkCancelled(f);
548                }
549                return NoResult;
550            }};
551        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
552    }
553
554    /**
555     * quietlyJoin of a forked task returns when task cancelled
556     */
557    public void testCancelledForkQuietlyJoin() {
558        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
559            public Integer realCompute() {
560                FibTask f = new FibTask(8);
561                assertTrue(f.cancel(true));
562                assertSame(f, f.fork());
563                f.quietlyJoin();
564                checkCancelled(f);
565                return NoResult;
566            }};
567        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
568    }
569
570    /**
571     * getPool of executing task returns its pool
572     */
573    public void testGetPool() {
574        final ForkJoinPool mainPool = mainPool();
575        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
576            public Integer realCompute() {
577                assertSame(mainPool, getPool());
578                return NoResult;
579            }};
580        assertSame(NoResult, testInvokeOnPool(mainPool, a));
581    }
582
583    /**
584     * getPool of non-FJ task returns null
585     */
586    public void testGetPool2() {
587        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
588            public Integer realCompute() {
589                assertNull(getPool());
590                return NoResult;
591            }};
592        assertSame(NoResult, a.invoke());
593    }
594
595    /**
596     * inForkJoinPool of executing task returns true
597     */
598    public void testInForkJoinPool() {
599        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
600            public Integer realCompute() {
601                assertTrue(inForkJoinPool());
602                return NoResult;
603            }};
604        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
605    }
606
607    /**
608     * inForkJoinPool of non-FJ task returns false
609     */
610    public void testInForkJoinPool2() {
611        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
612            public Integer realCompute() {
613                assertFalse(inForkJoinPool());
614                return NoResult;
615            }};
616        assertSame(NoResult, a.invoke());
617    }
618
619    /**
620     * The value set by setRawResult is returned by getRawResult
621     */
622    public void testSetRawResult() {
623        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
624            public Integer realCompute() {
625                setRawResult(NoResult);
626                assertSame(NoResult, getRawResult());
627                return NoResult;
628            }
629        };
630        assertSame(NoResult, a.invoke());
631    }
632
633    /**
634     * A reinitialized normally completed task may be re-invoked
635     */
636    public void testReinitialize() {
637        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
638            public Integer realCompute() {
639                FibTask f = new FibTask(8);
640                checkNotDone(f);
641
642                for (int i = 0; i < 3; i++) {
643                    Integer r = f.invoke();
644                    assertEquals(21, (int) r);
645                    checkCompletedNormally(f, r);
646                    f.reinitialize();
647                    f.publicSetRawResult(null);
648                    checkNotDone(f);
649                }
650                return NoResult;
651            }};
652        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
653    }
654
655    /**
656     * A reinitialized abnormally completed task may be re-invoked
657     */
658    public void testReinitializeAbnormal() {
659        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
660            public Integer realCompute() {
661                FailingFibTask f = new FailingFibTask(8);
662                checkNotDone(f);
663
664                for (int i = 0; i < 3; i++) {
665                    try {
666                        f.invoke();
667                        shouldThrow();
668                    } catch (FJException success) {
669                        checkCompletedAbnormally(f, success);
670                    }
671                    f.reinitialize();
672                    checkNotDone(f);
673                }
674                return NoResult;
675            }};
676        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
677    }
678
679    /**
680     * invoke task throws exception after invoking completeExceptionally
681     */
682    public void testCompleteExceptionally() {
683        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
684            public Integer realCompute() {
685                FibTask f = new FibTask(8);
686                f.completeExceptionally(new FJException());
687                try {
688                    Integer r = f.invoke();
689                    shouldThrow();
690                } catch (FJException success) {
691                    checkCompletedAbnormally(f, success);
692                }
693                return NoResult;
694            }};
695        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
696    }
697
698    /**
699     * invoke task suppresses execution invoking complete
700     */
701    public void testComplete() {
702        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
703            public Integer realCompute() {
704                FibTask f = new FibTask(8);
705                f.complete(NoResult);
706                Integer r = f.invoke();
707                assertSame(NoResult, r);
708                checkCompletedNormally(f, NoResult);
709                return r;
710            }};
711        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
712    }
713
714    /**
715     * invokeAll(t1, t2) invokes all task arguments
716     */
717    public void testInvokeAll2() {
718        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
719            public Integer realCompute() {
720                FibTask f = new FibTask(8);
721                FibTask g = new FibTask(9);
722                invokeAll(f, g);
723                checkCompletedNormally(f, 21);
724                checkCompletedNormally(g, 34);
725                return NoResult;
726            }};
727        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
728    }
729
730    /**
731     * invokeAll(tasks) with 1 argument invokes task
732     */
733    public void testInvokeAll1() {
734        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
735            public Integer realCompute() {
736                FibTask f = new FibTask(8);
737                invokeAll(f);
738                checkCompletedNormally(f, 21);
739                return NoResult;
740            }};
741        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
742    }
743
744    /**
745     * invokeAll(tasks) with > 2 argument invokes tasks
746     */
747    public void testInvokeAll3() {
748        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
749            public Integer realCompute() {
750                FibTask f = new FibTask(8);
751                FibTask g = new FibTask(9);
752                FibTask h = new FibTask(7);
753                invokeAll(f, g, h);
754                assertTrue(f.isDone());
755                assertTrue(g.isDone());
756                assertTrue(h.isDone());
757                checkCompletedNormally(f, 21);
758                checkCompletedNormally(g, 34);
759                checkCompletedNormally(h, 13);
760                return NoResult;
761            }};
762        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
763    }
764
765    /**
766     * invokeAll(collection) invokes all tasks in the collection
767     */
768    public void testInvokeAllCollection() {
769        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
770            public Integer realCompute() {
771                FibTask f = new FibTask(8);
772                FibTask g = new FibTask(9);
773                FibTask h = new FibTask(7);
774                HashSet set = new HashSet();
775                set.add(f);
776                set.add(g);
777                set.add(h);
778                invokeAll(set);
779                assertTrue(f.isDone());
780                assertTrue(g.isDone());
781                assertTrue(h.isDone());
782                checkCompletedNormally(f, 21);
783                checkCompletedNormally(g, 34);
784                checkCompletedNormally(h, 13);
785                return NoResult;
786            }};
787        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
788    }
789
790    /**
791     * invokeAll(tasks) with any null task throws NPE
792     */
793    public void testInvokeAllNPE() {
794        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
795            public Integer realCompute() {
796                FibTask f = new FibTask(8);
797                FibTask g = new FibTask(9);
798                FibTask h = null;
799                try {
800                    invokeAll(f, g, h);
801                    shouldThrow();
802                } catch (NullPointerException success) {}
803                return NoResult;
804            }};
805        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
806    }
807
808    /**
809     * invokeAll(t1, t2) throw exception if any task does
810     */
811    public void testAbnormalInvokeAll2() {
812        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
813            public Integer realCompute() {
814                FibTask f = new FibTask(8);
815                FailingFibTask g = new FailingFibTask(9);
816                try {
817                    invokeAll(f, g);
818                    shouldThrow();
819                } catch (FJException success) {
820                    checkCompletedAbnormally(g, success);
821                }
822                return NoResult;
823            }};
824        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
825    }
826
827    /**
828     * invokeAll(tasks) with 1 argument throws exception if task does
829     */
830    public void testAbnormalInvokeAll1() {
831        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
832            public Integer realCompute() {
833                FailingFibTask g = new FailingFibTask(9);
834                try {
835                    invokeAll(g);
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(tasks) with > 2 argument throws exception if any task does
847     */
848    public void testAbnormalInvokeAll3() {
849        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
850            public Integer realCompute() {
851                FibTask f = new FibTask(8);
852                FailingFibTask g = new FailingFibTask(9);
853                FibTask h = new FibTask(7);
854                try {
855                    invokeAll(f, g, h);
856                    shouldThrow();
857                } catch (FJException success) {
858                    checkCompletedAbnormally(g, success);
859                }
860                return NoResult;
861            }};
862        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
863    }
864
865    /**
866     * invokeAll(collection) throws exception if any task does
867     */
868    public void testAbnormalInvokeAllCollection() {
869        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
870            public Integer realCompute() {
871                FailingFibTask f = new FailingFibTask(8);
872                FibTask g = new FibTask(9);
873                FibTask h = new FibTask(7);
874                HashSet set = new HashSet();
875                set.add(f);
876                set.add(g);
877                set.add(h);
878                try {
879                    invokeAll(set);
880                    shouldThrow();
881                } catch (FJException success) {
882                    checkCompletedAbnormally(f, success);
883                }
884                return NoResult;
885            }};
886        assertSame(NoResult, testInvokeOnPool(mainPool(), a));
887    }
888
889    /**
890     * tryUnfork returns true for most recent unexecuted task,
891     * and suppresses execution
892     */
893    public void testTryUnfork() {
894        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
895            public Integer realCompute() {
896                FibTask g = new FibTask(9);
897                assertSame(g, g.fork());
898                FibTask f = new FibTask(8);
899                assertSame(f, f.fork());
900                assertTrue(f.tryUnfork());
901                helpQuiesce();
902                checkNotDone(f);
903                checkCompletedNormally(g, 34);
904                return NoResult;
905            }};
906        assertSame(NoResult, testInvokeOnPool(singletonPool(), a));
907    }
908
909    /**
910     * getSurplusQueuedTaskCount returns > 0 when
911     * there are more tasks than threads
912     */
913    public void testGetSurplusQueuedTaskCount() {
914        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
915            public Integer realCompute() {
916                FibTask h = new FibTask(7);
917                assertSame(h, h.fork());
918                FibTask g = new FibTask(9);
919                assertSame(g, g.fork());
920                FibTask f = new FibTask(8);
921                assertSame(f, f.fork());
922                assertTrue(getSurplusQueuedTaskCount() > 0);
923                helpQuiesce();
924                assertEquals(0, getSurplusQueuedTaskCount());
925                checkCompletedNormally(f, 21);
926                checkCompletedNormally(g, 34);
927                checkCompletedNormally(h, 13);
928                return NoResult;
929            }};
930        assertSame(NoResult, testInvokeOnPool(singletonPool(), a));
931    }
932
933    /**
934     * peekNextLocalTask returns most recent unexecuted task.
935     */
936    public void testPeekNextLocalTask() {
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, peekNextLocalTask());
944                checkCompletesNormally(f, 21);
945                helpQuiesce();
946                checkCompletedNormally(g, 34);
947                return NoResult;
948            }};
949        assertSame(NoResult, testInvokeOnPool(singletonPool(), a));
950    }
951
952    /**
953     * pollNextLocalTask returns most recent unexecuted task
954     * without executing it
955     */
956    public void testPollNextLocalTask() {
957        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
958            public Integer realCompute() {
959                FibTask g = new FibTask(9);
960                assertSame(g, g.fork());
961                FibTask f = new FibTask(8);
962                assertSame(f, f.fork());
963                assertSame(f, pollNextLocalTask());
964                helpQuiesce();
965                checkNotDone(f);
966                checkCompletedNormally(g, 34);
967                return NoResult;
968            }};
969        assertSame(NoResult, testInvokeOnPool(singletonPool(), a));
970    }
971
972    /**
973     * pollTask returns an unexecuted task without executing it
974     */
975    public void testPollTask() {
976        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
977            public Integer realCompute() {
978                FibTask g = new FibTask(9);
979                assertSame(g, g.fork());
980                FibTask f = new FibTask(8);
981                assertSame(f, f.fork());
982                assertSame(f, pollTask());
983                helpQuiesce();
984                checkNotDone(f);
985                checkCompletedNormally(g, 34);
986                return NoResult;
987            }};
988        assertSame(NoResult, testInvokeOnPool(singletonPool(), a));
989    }
990
991    /**
992     * peekNextLocalTask returns least recent unexecuted task in async mode
993     */
994    public void testPeekNextLocalTaskAsync() {
995        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
996            public Integer realCompute() {
997                FibTask g = new FibTask(9);
998                assertSame(g, g.fork());
999                FibTask f = new FibTask(8);
1000                assertSame(f, f.fork());
1001                assertSame(g, peekNextLocalTask());
1002                assertEquals(21, (int) f.join());
1003                helpQuiesce();
1004                checkCompletedNormally(f, 21);
1005                checkCompletedNormally(g, 34);
1006                return NoResult;
1007            }};
1008        assertSame(NoResult, testInvokeOnPool(asyncSingletonPool(), a));
1009    }
1010
1011    /**
1012     * pollNextLocalTask returns least recent unexecuted task without
1013     * executing it, in async mode
1014     */
1015    public void testPollNextLocalTaskAsync() {
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, pollNextLocalTask());
1023                helpQuiesce();
1024                checkCompletedNormally(f, 21);
1025                checkNotDone(g);
1026                return NoResult;
1027            }};
1028        assertSame(NoResult, testInvokeOnPool(asyncSingletonPool(), a));
1029    }
1030
1031    /**
1032     * pollTask returns an unexecuted task without executing it, in
1033     * async mode
1034     */
1035    public void testPollTaskAsync() {
1036        RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
1037            public Integer realCompute() {
1038                FibTask g = new FibTask(9);
1039                assertSame(g, g.fork());
1040                FibTask f = new FibTask(8);
1041                assertSame(f, f.fork());
1042                assertSame(g, pollTask());
1043                helpQuiesce();
1044                checkCompletedNormally(f, 21);
1045                checkNotDone(g);
1046                return NoResult;
1047            }};
1048        assertSame(NoResult, testInvokeOnPool(asyncSingletonPool(), a));
1049    }
1050
1051}
1052