1/*
2 * Written by Doug Lea with assistance from members of JCP JSR-166
3 * Expert Group and released to the public domain, as explained at
4 * http://creativecommons.org/publicdomain/zero/1.0/
5 */
6
7package jsr166;
8
9import static java.util.concurrent.TimeUnit.MILLISECONDS;
10import static java.util.concurrent.TimeUnit.SECONDS;
11
12import java.util.Arrays;
13import java.util.Collections;
14import java.util.concurrent.CountDownLatch;
15import java.util.concurrent.ExecutionException;
16import java.util.concurrent.ForkJoinPool;
17import java.util.concurrent.ForkJoinTask;
18import java.util.concurrent.ForkJoinWorkerThread;
19import java.util.concurrent.RecursiveAction;
20import java.util.concurrent.TimeoutException;
21
22import junit.framework.Test;
23import junit.framework.TestSuite;
24
25public class ForkJoinTask8Test extends JSR166TestCase {
26
27    /*
28     * Testing notes: This differs from ForkJoinTaskTest mainly by
29     * defining a version of BinaryAsyncAction that uses JDK8 task
30     * tags for control state, thereby testing getForkJoinTaskTag,
31     * setForkJoinTaskTag, and compareAndSetForkJoinTaskTag across
32     * various contexts. Most of the test methods using it are
33     * otherwise identical, but omitting retest of those dealing with
34     * cancellation, which is not represented in this tag scheme.
35     */
36
37    static final short INITIAL_STATE = -1;
38    static final short COMPLETE_STATE = 0;
39    static final short EXCEPTION_STATE = 1;
40
41    // android-note: Removed because the CTS runner does a bad job of
42    // retrying tests that have suite() declarations.
43    //
44    // public static void main(String[] args) {
45    //     main(suite(), args);
46    // }
47    // public static Test suite() {
48    //     return new TestSuite(ForkJoinTask8Test.class);
49    // }
50
51    // Runs with "mainPool" use > 1 thread. singletonPool tests use 1
52    static final int mainPoolSize =
53        Math.max(2, Runtime.getRuntime().availableProcessors());
54
55    private static ForkJoinPool mainPool() {
56        return new ForkJoinPool(mainPoolSize);
57    }
58
59    private static ForkJoinPool singletonPool() {
60        return new ForkJoinPool(1);
61    }
62
63    private static ForkJoinPool asyncSingletonPool() {
64        return new ForkJoinPool(1,
65                                ForkJoinPool.defaultForkJoinWorkerThreadFactory,
66                                null, true);
67    }
68
69    // Compute fib naively and efficiently
70    final int[] fib;
71    {
72        int[] fib = new int[10];
73        fib[0] = 0;
74        fib[1] = 1;
75        for (int i = 2; i < fib.length; i++)
76            fib[i] = fib[i - 1] + fib[i - 2];
77        this.fib = fib;
78    }
79
80    private void testInvokeOnPool(ForkJoinPool pool, RecursiveAction a) {
81        try (PoolCleaner cleaner = cleaner(pool)) {
82            assertFalse(a.isDone());
83            assertFalse(a.isCompletedNormally());
84            assertFalse(a.isCompletedAbnormally());
85            assertFalse(a.isCancelled());
86            assertNull(a.getException());
87            assertNull(a.getRawResult());
88
89            assertNull(pool.invoke(a));
90
91            assertTrue(a.isDone());
92            assertTrue(a.isCompletedNormally());
93            assertFalse(a.isCompletedAbnormally());
94            assertFalse(a.isCancelled());
95            assertNull(a.getException());
96            assertNull(a.getRawResult());
97        }
98    }
99
100    void checkNotDone(ForkJoinTask a) {
101        assertFalse(a.isDone());
102        assertFalse(a.isCompletedNormally());
103        assertFalse(a.isCompletedAbnormally());
104        assertFalse(a.isCancelled());
105        assertNull(a.getException());
106        assertNull(a.getRawResult());
107        if (a instanceof BinaryAsyncAction)
108            assertTrue(((BinaryAsyncAction)a).getForkJoinTaskTag() == INITIAL_STATE);
109
110        try {
111            a.get(0L, SECONDS);
112            shouldThrow();
113        } catch (TimeoutException success) {
114        } catch (Throwable fail) { threadUnexpectedException(fail); }
115    }
116
117    <T> void checkCompletedNormally(ForkJoinTask<T> a) {
118        checkCompletedNormally(a, null);
119    }
120
121    <T> void checkCompletedNormally(ForkJoinTask<T> a, T expected) {
122        assertTrue(a.isDone());
123        assertFalse(a.isCancelled());
124        assertTrue(a.isCompletedNormally());
125        assertFalse(a.isCompletedAbnormally());
126        assertNull(a.getException());
127        assertSame(expected, a.getRawResult());
128        if (a instanceof BinaryAsyncAction)
129            assertTrue(((BinaryAsyncAction)a).getForkJoinTaskTag() == COMPLETE_STATE);
130
131        {
132            Thread.currentThread().interrupt();
133            long startTime = System.nanoTime();
134            assertSame(expected, a.join());
135            assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS);
136            Thread.interrupted();
137        }
138
139        {
140            Thread.currentThread().interrupt();
141            long startTime = System.nanoTime();
142            a.quietlyJoin();        // should be no-op
143            assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS);
144            Thread.interrupted();
145        }
146
147        assertFalse(a.cancel(false));
148        assertFalse(a.cancel(true));
149        try {
150            assertSame(expected, a.get());
151        } catch (Throwable fail) { threadUnexpectedException(fail); }
152        try {
153            assertSame(expected, a.get(5L, SECONDS));
154        } catch (Throwable fail) { threadUnexpectedException(fail); }
155    }
156
157    void checkCompletedAbnormally(ForkJoinTask a, Throwable t) {
158        assertTrue(a.isDone());
159        assertFalse(a.isCancelled());
160        assertFalse(a.isCompletedNormally());
161        assertTrue(a.isCompletedAbnormally());
162        assertSame(t.getClass(), a.getException().getClass());
163        assertNull(a.getRawResult());
164        assertFalse(a.cancel(false));
165        assertFalse(a.cancel(true));
166        if (a instanceof BinaryAsyncAction)
167            assertTrue(((BinaryAsyncAction)a).getForkJoinTaskTag() != INITIAL_STATE);
168
169        try {
170            Thread.currentThread().interrupt();
171            a.join();
172            shouldThrow();
173        } catch (Throwable expected) {
174            assertSame(t.getClass(), expected.getClass());
175        }
176        Thread.interrupted();
177
178        {
179            long startTime = System.nanoTime();
180            a.quietlyJoin();        // should be no-op
181            assertTrue(millisElapsedSince(startTime) < SMALL_DELAY_MS);
182        }
183
184        try {
185            a.get();
186            shouldThrow();
187        } catch (ExecutionException success) {
188            assertSame(t.getClass(), success.getCause().getClass());
189        } catch (Throwable fail) { threadUnexpectedException(fail); }
190
191        try {
192            a.get(5L, SECONDS);
193            shouldThrow();
194        } catch (ExecutionException success) {
195            assertSame(t.getClass(), success.getCause().getClass());
196        } catch (Throwable fail) { threadUnexpectedException(fail); }
197    }
198
199    public static final class FJException extends RuntimeException {
200        FJException() { super(); }
201    }
202
203    abstract static class BinaryAsyncAction extends ForkJoinTask<Void> {
204
205        private volatile BinaryAsyncAction parent;
206
207        private volatile BinaryAsyncAction sibling;
208
209        protected BinaryAsyncAction() {
210            setForkJoinTaskTag(INITIAL_STATE);
211        }
212
213        public final Void getRawResult() { return null; }
214        protected final void setRawResult(Void mustBeNull) { }
215
216        public final void linkSubtasks(BinaryAsyncAction x, BinaryAsyncAction y) {
217            x.parent = y.parent = this;
218            x.sibling = y;
219            y.sibling = x;
220        }
221
222        protected void onComplete(BinaryAsyncAction x, BinaryAsyncAction y) {
223            if (this.getForkJoinTaskTag() != COMPLETE_STATE ||
224                x.getForkJoinTaskTag() != COMPLETE_STATE ||
225                y.getForkJoinTaskTag() != COMPLETE_STATE) {
226                completeThisExceptionally(new FJException());
227            }
228        }
229
230        protected boolean onException() {
231            return true;
232        }
233
234        public void linkAndForkSubtasks(BinaryAsyncAction x, BinaryAsyncAction y) {
235            linkSubtasks(x, y);
236            y.fork();
237            x.fork();
238        }
239
240        private void completeThis() {
241            setForkJoinTaskTag(COMPLETE_STATE);
242            super.complete(null);
243        }
244
245        private void completeThisExceptionally(Throwable ex) {
246            setForkJoinTaskTag(EXCEPTION_STATE);
247            super.completeExceptionally(ex);
248        }
249
250        public boolean cancel(boolean mayInterruptIfRunning) {
251            if (super.cancel(mayInterruptIfRunning)) {
252                completeExceptionally(new FJException());
253                return true;
254            }
255            return false;
256        }
257
258        public final void complete() {
259            BinaryAsyncAction a = this;
260            for (;;) {
261                BinaryAsyncAction s = a.sibling;
262                BinaryAsyncAction p = a.parent;
263                a.sibling = null;
264                a.parent = null;
265                a.completeThis();
266                if (p == null ||
267                    p.compareAndSetForkJoinTaskTag(INITIAL_STATE, COMPLETE_STATE))
268                    break;
269                try {
270                    p.onComplete(a, s);
271                } catch (Throwable rex) {
272                    p.completeExceptionally(rex);
273                    return;
274                }
275                a = p;
276            }
277        }
278
279        public final void completeExceptionally(Throwable ex) {
280            for (BinaryAsyncAction a = this;;) {
281                a.completeThisExceptionally(ex);
282                BinaryAsyncAction s = a.sibling;
283                if (s != null && !s.isDone())
284                    s.completeExceptionally(ex);
285                if ((a = a.parent) == null)
286                    break;
287            }
288        }
289
290        public final BinaryAsyncAction getParent() {
291            return parent;
292        }
293
294        public BinaryAsyncAction getSibling() {
295            return sibling;
296        }
297
298        public void reinitialize() {
299            parent = sibling = null;
300            super.reinitialize();
301        }
302
303    }
304
305    final class AsyncFib extends BinaryAsyncAction {
306        int number;
307        int expectedResult;
308        public AsyncFib(int number) {
309            this.number = number;
310            this.expectedResult = fib[number];
311        }
312
313        public final boolean exec() {
314            try {
315                AsyncFib f = this;
316                int n = f.number;
317                while (n > 1) {
318                    AsyncFib p = f;
319                    AsyncFib r = new AsyncFib(n - 2);
320                    f = new AsyncFib(--n);
321                    p.linkSubtasks(r, f);
322                    r.fork();
323                }
324                f.complete();
325            }
326            catch (Throwable ex) {
327                compareAndSetForkJoinTaskTag(INITIAL_STATE, EXCEPTION_STATE);
328            }
329            if (getForkJoinTaskTag() == EXCEPTION_STATE)
330                throw new FJException();
331            return false;
332        }
333
334        protected void onComplete(BinaryAsyncAction x, BinaryAsyncAction y) {
335            number = ((AsyncFib)x).number + ((AsyncFib)y).number;
336            super.onComplete(x, y);
337        }
338
339        public void checkCompletedNormally() {
340            assertEquals(expectedResult, number);
341            ForkJoinTask8Test.this.checkCompletedNormally(this);
342        }
343    }
344
345    static final class FailingAsyncFib extends BinaryAsyncAction {
346        int number;
347        public FailingAsyncFib(int n) {
348            this.number = n;
349        }
350
351        public final boolean exec() {
352            try {
353                FailingAsyncFib f = this;
354                int n = f.number;
355                while (n > 1) {
356                    FailingAsyncFib p = f;
357                    FailingAsyncFib r = new FailingAsyncFib(n - 2);
358                    f = new FailingAsyncFib(--n);
359                    p.linkSubtasks(r, f);
360                    r.fork();
361                }
362                f.complete();
363            }
364            catch (Throwable ex) {
365                compareAndSetForkJoinTaskTag(INITIAL_STATE, EXCEPTION_STATE);
366            }
367            if (getForkJoinTaskTag() == EXCEPTION_STATE)
368                throw new FJException();
369            return false;
370        }
371
372        protected void onComplete(BinaryAsyncAction x, BinaryAsyncAction y) {
373            completeExceptionally(new FJException());
374        }
375    }
376
377    /**
378     * invoke returns when task completes normally.
379     * isCompletedAbnormally and isCancelled return false for normally
380     * completed tasks; getRawResult returns null.
381     */
382    public void testInvoke() {
383        testInvoke(mainPool());
384    }
385    public void testInvoke_Singleton() {
386        testInvoke(singletonPool());
387    }
388    public void testInvoke(ForkJoinPool pool) {
389        RecursiveAction a = new CheckedRecursiveAction() {
390            protected void realCompute() {
391                AsyncFib f = new AsyncFib(8);
392                assertNull(f.invoke());
393                f.checkCompletedNormally();
394            }};
395        testInvokeOnPool(pool, a);
396    }
397
398    /**
399     * quietlyInvoke task returns when task completes normally.
400     * isCompletedAbnormally and isCancelled return false for normally
401     * completed tasks
402     */
403    public void testQuietlyInvoke() {
404        testQuietlyInvoke(mainPool());
405    }
406    public void testQuietlyInvoke_Singleton() {
407        testQuietlyInvoke(singletonPool());
408    }
409    public void testQuietlyInvoke(ForkJoinPool pool) {
410        RecursiveAction a = new CheckedRecursiveAction() {
411            protected void realCompute() {
412                AsyncFib f = new AsyncFib(8);
413                f.quietlyInvoke();
414                f.checkCompletedNormally();
415            }};
416        testInvokeOnPool(pool, a);
417    }
418
419    /**
420     * join of a forked task returns when task completes
421     */
422    public void testForkJoin() {
423        testForkJoin(mainPool());
424    }
425    public void testForkJoin_Singleton() {
426        testForkJoin(singletonPool());
427    }
428    public void testForkJoin(ForkJoinPool pool) {
429        RecursiveAction a = new CheckedRecursiveAction() {
430            protected void realCompute() {
431                AsyncFib f = new AsyncFib(8);
432                assertSame(f, f.fork());
433                assertNull(f.join());
434                f.checkCompletedNormally();
435            }};
436        testInvokeOnPool(pool, a);
437    }
438
439    /**
440     * get of a forked task returns when task completes
441     */
442    public void testForkGet() {
443        testForkGet(mainPool());
444    }
445    public void testForkGet_Singleton() {
446        testForkGet(singletonPool());
447    }
448    public void testForkGet(ForkJoinPool pool) {
449        RecursiveAction a = new CheckedRecursiveAction() {
450            protected void realCompute() throws Exception {
451                AsyncFib f = new AsyncFib(8);
452                assertSame(f, f.fork());
453                assertNull(f.get());
454                f.checkCompletedNormally();
455            }};
456        testInvokeOnPool(pool, a);
457    }
458
459    /**
460     * timed get of a forked task returns when task completes
461     */
462    public void testForkTimedGet() {
463        testForkTimedGet(mainPool());
464    }
465    public void testForkTimedGet_Singleton() {
466        testForkTimedGet(singletonPool());
467    }
468    public void testForkTimedGet(ForkJoinPool pool) {
469        RecursiveAction a = new CheckedRecursiveAction() {
470            protected void realCompute() throws Exception {
471                AsyncFib f = new AsyncFib(8);
472                assertSame(f, f.fork());
473                assertNull(f.get(LONG_DELAY_MS, MILLISECONDS));
474                f.checkCompletedNormally();
475            }};
476        testInvokeOnPool(pool, a);
477    }
478
479    /**
480     * timed get with null time unit throws NullPointerException
481     */
482    public void testForkTimedGetNullTimeUnit() {
483        testForkTimedGetNullTimeUnit(mainPool());
484    }
485    public void testForkTimedGetNullTimeUnit_Singleton() {
486        testForkTimedGet(singletonPool());
487    }
488    public void testForkTimedGetNullTimeUnit(ForkJoinPool pool) {
489        RecursiveAction a = new CheckedRecursiveAction() {
490            protected void realCompute() throws Exception {
491                AsyncFib f = new AsyncFib(8);
492                assertSame(f, f.fork());
493                try {
494                    f.get(5L, null);
495                    shouldThrow();
496                } catch (NullPointerException success) {}
497            }};
498        testInvokeOnPool(pool, a);
499    }
500
501    /**
502     * quietlyJoin of a forked task returns when task completes
503     */
504    public void testForkQuietlyJoin() {
505        testForkQuietlyJoin(mainPool());
506    }
507    public void testForkQuietlyJoin_Singleton() {
508        testForkQuietlyJoin(singletonPool());
509    }
510    public void testForkQuietlyJoin(ForkJoinPool pool) {
511        RecursiveAction a = new CheckedRecursiveAction() {
512            protected void realCompute() {
513                AsyncFib f = new AsyncFib(8);
514                assertSame(f, f.fork());
515                f.quietlyJoin();
516                f.checkCompletedNormally();
517            }};
518        testInvokeOnPool(pool, a);
519    }
520
521    /**
522     * helpQuiesce returns when tasks are complete.
523     * getQueuedTaskCount returns 0 when quiescent
524     */
525    public void testForkHelpQuiesce() {
526        testForkHelpQuiesce(mainPool());
527    }
528    public void testForkHelpQuiesce_Singleton() {
529        testForkHelpQuiesce(singletonPool());
530    }
531    public void testForkHelpQuiesce(ForkJoinPool pool) {
532        RecursiveAction a = new CheckedRecursiveAction() {
533            protected void realCompute() {
534                AsyncFib f = new AsyncFib(8);
535                assertSame(f, f.fork());
536                helpQuiesce();
537                assertEquals(0, getQueuedTaskCount());
538                f.checkCompletedNormally();
539            }};
540        testInvokeOnPool(pool, a);
541    }
542
543    /**
544     * invoke task throws exception when task completes abnormally
545     */
546    public void testAbnormalInvoke() {
547        testAbnormalInvoke(mainPool());
548    }
549    public void testAbnormalInvoke_Singleton() {
550        testAbnormalInvoke(singletonPool());
551    }
552    public void testAbnormalInvoke(ForkJoinPool pool) {
553        RecursiveAction a = new CheckedRecursiveAction() {
554            protected void realCompute() {
555                FailingAsyncFib f = new FailingAsyncFib(8);
556                try {
557                    f.invoke();
558                    shouldThrow();
559                } catch (FJException success) {
560                    checkCompletedAbnormally(f, success);
561                }
562            }};
563        testInvokeOnPool(pool, a);
564    }
565
566    /**
567     * quietlyInvoke task returns when task completes abnormally
568     */
569    public void testAbnormalQuietlyInvoke() {
570        testAbnormalQuietlyInvoke(mainPool());
571    }
572    public void testAbnormalQuietlyInvoke_Singleton() {
573        testAbnormalQuietlyInvoke(singletonPool());
574    }
575    public void testAbnormalQuietlyInvoke(ForkJoinPool pool) {
576        RecursiveAction a = new CheckedRecursiveAction() {
577            protected void realCompute() {
578                FailingAsyncFib f = new FailingAsyncFib(8);
579                f.quietlyInvoke();
580                assertTrue(f.getException() instanceof FJException);
581                checkCompletedAbnormally(f, f.getException());
582            }};
583        testInvokeOnPool(pool, a);
584    }
585
586    /**
587     * join of a forked task throws exception when task completes abnormally
588     */
589    public void testAbnormalForkJoin() {
590        testAbnormalForkJoin(mainPool());
591    }
592    public void testAbnormalForkJoin_Singleton() {
593        testAbnormalForkJoin(singletonPool());
594    }
595    public void testAbnormalForkJoin(ForkJoinPool pool) {
596        RecursiveAction a = new CheckedRecursiveAction() {
597            protected void realCompute() {
598                FailingAsyncFib f = new FailingAsyncFib(8);
599                assertSame(f, f.fork());
600                try {
601                    f.join();
602                    shouldThrow();
603                } catch (FJException success) {
604                    checkCompletedAbnormally(f, success);
605                }
606            }};
607        testInvokeOnPool(pool, a);
608    }
609
610    /**
611     * get of a forked task throws exception when task completes abnormally
612     */
613    public void testAbnormalForkGet() {
614        testAbnormalForkGet(mainPool());
615    }
616    public void testAbnormalForkGet_Singleton() {
617        testAbnormalForkJoin(singletonPool());
618    }
619    public void testAbnormalForkGet(ForkJoinPool pool) {
620        RecursiveAction a = new CheckedRecursiveAction() {
621            protected void realCompute() throws Exception {
622                FailingAsyncFib f = new FailingAsyncFib(8);
623                assertSame(f, f.fork());
624                try {
625                    f.get();
626                    shouldThrow();
627                } catch (ExecutionException success) {
628                    Throwable cause = success.getCause();
629                    assertTrue(cause instanceof FJException);
630                    checkCompletedAbnormally(f, cause);
631                }
632            }};
633        testInvokeOnPool(pool, a);
634    }
635
636    /**
637     * timed get of a forked task throws exception when task completes abnormally
638     */
639    public void testAbnormalForkTimedGet() {
640        testAbnormalForkTimedGet(mainPool());
641    }
642    public void testAbnormalForkTimedGet_Singleton() {
643        testAbnormalForkTimedGet(singletonPool());
644    }
645    public void testAbnormalForkTimedGet(ForkJoinPool pool) {
646        RecursiveAction a = new CheckedRecursiveAction() {
647            protected void realCompute() throws Exception {
648                FailingAsyncFib f = new FailingAsyncFib(8);
649                assertSame(f, f.fork());
650                try {
651                    f.get(LONG_DELAY_MS, MILLISECONDS);
652                    shouldThrow();
653                } catch (ExecutionException success) {
654                    Throwable cause = success.getCause();
655                    assertTrue(cause instanceof FJException);
656                    checkCompletedAbnormally(f, cause);
657                }
658            }};
659        testInvokeOnPool(pool, a);
660    }
661
662    /**
663     * quietlyJoin of a forked task returns when task completes abnormally
664     */
665    public void testAbnormalForkQuietlyJoin() {
666        testAbnormalForkQuietlyJoin(mainPool());
667    }
668    public void testAbnormalForkQuietlyJoin_Singleton() {
669        testAbnormalForkQuietlyJoin(singletonPool());
670    }
671    public void testAbnormalForkQuietlyJoin(ForkJoinPool pool) {
672        RecursiveAction a = new CheckedRecursiveAction() {
673            protected void realCompute() {
674                FailingAsyncFib f = new FailingAsyncFib(8);
675                assertSame(f, f.fork());
676                f.quietlyJoin();
677                assertTrue(f.getException() instanceof FJException);
678                checkCompletedAbnormally(f, f.getException());
679            }};
680        testInvokeOnPool(pool, a);
681    }
682
683    /**
684     * getPool of executing task returns its pool
685     */
686    public void testGetPool() {
687        testGetPool(mainPool());
688    }
689    public void testGetPool_Singleton() {
690        testGetPool(singletonPool());
691    }
692    public void testGetPool(ForkJoinPool pool) {
693        RecursiveAction a = new CheckedRecursiveAction() {
694            protected void realCompute() {
695                assertSame(pool, getPool());
696            }};
697        testInvokeOnPool(pool, a);
698    }
699
700    /**
701     * getPool of non-FJ task returns null
702     */
703    public void testGetPool2() {
704        RecursiveAction a = new CheckedRecursiveAction() {
705            protected void realCompute() {
706                assertNull(getPool());
707            }};
708        assertNull(a.invoke());
709    }
710
711    /**
712     * inForkJoinPool of executing task returns true
713     */
714    public void testInForkJoinPool() {
715        testInForkJoinPool(mainPool());
716    }
717    public void testInForkJoinPool_Singleton() {
718        testInForkJoinPool(singletonPool());
719    }
720    public void testInForkJoinPool(ForkJoinPool pool) {
721        RecursiveAction a = new CheckedRecursiveAction() {
722            protected void realCompute() {
723                assertTrue(inForkJoinPool());
724            }};
725        testInvokeOnPool(pool, a);
726    }
727
728    /**
729     * inForkJoinPool of non-FJ task returns false
730     */
731    public void testInForkJoinPool2() {
732        RecursiveAction a = new CheckedRecursiveAction() {
733            protected void realCompute() {
734                assertFalse(inForkJoinPool());
735            }};
736        assertNull(a.invoke());
737    }
738
739    /**
740     * setRawResult(null) succeeds
741     */
742    public void testSetRawResult() {
743        RecursiveAction a = new CheckedRecursiveAction() {
744            protected void realCompute() {
745                setRawResult(null);
746                assertNull(getRawResult());
747            }};
748        assertNull(a.invoke());
749    }
750
751    /**
752     * invoke task throws exception after invoking completeExceptionally
753     */
754    public void testCompleteExceptionally() {
755        testCompleteExceptionally(mainPool());
756    }
757    public void testCompleteExceptionally_Singleton() {
758        testCompleteExceptionally(singletonPool());
759    }
760    public void testCompleteExceptionally(ForkJoinPool pool) {
761        RecursiveAction a = new CheckedRecursiveAction() {
762            protected void realCompute() {
763                AsyncFib f = new AsyncFib(8);
764                f.completeExceptionally(new FJException());
765                try {
766                    f.invoke();
767                    shouldThrow();
768                } catch (FJException success) {
769                    checkCompletedAbnormally(f, success);
770                }
771            }};
772        testInvokeOnPool(pool, a);
773    }
774
775    /**
776     * invokeAll(tasks) with 1 argument invokes task
777     */
778    public void testInvokeAll1() {
779        testInvokeAll1(mainPool());
780    }
781    public void testInvokeAll1_Singleton() {
782        testInvokeAll1(singletonPool());
783    }
784    public void testInvokeAll1(ForkJoinPool pool) {
785        RecursiveAction a = new CheckedRecursiveAction() {
786            protected void realCompute() {
787                AsyncFib f = new AsyncFib(8);
788                invokeAll(f);
789                f.checkCompletedNormally();
790            }};
791        testInvokeOnPool(pool, a);
792    }
793
794    /**
795     * invokeAll(t1, t2) invokes all task arguments
796     */
797    public void testInvokeAll2() {
798        testInvokeAll2(mainPool());
799    }
800    public void testInvokeAll2_Singleton() {
801        testInvokeAll2(singletonPool());
802    }
803    public void testInvokeAll2(ForkJoinPool pool) {
804        RecursiveAction a = new CheckedRecursiveAction() {
805            protected void realCompute() {
806                AsyncFib[] tasks = {
807                    new AsyncFib(8),
808                    new AsyncFib(9),
809                };
810                invokeAll(tasks[0], tasks[1]);
811                for (AsyncFib task : tasks) assertTrue(task.isDone());
812                for (AsyncFib task : tasks) task.checkCompletedNormally();
813            }};
814        testInvokeOnPool(pool, a);
815    }
816
817    /**
818     * invokeAll(tasks) with > 2 argument invokes tasks
819     */
820    public void testInvokeAll3() {
821        testInvokeAll3(mainPool());
822    }
823    public void testInvokeAll3_Singleton() {
824        testInvokeAll3(singletonPool());
825    }
826    public void testInvokeAll3(ForkJoinPool pool) {
827        RecursiveAction a = new CheckedRecursiveAction() {
828            protected void realCompute() {
829                AsyncFib[] tasks = {
830                    new AsyncFib(8),
831                    new AsyncFib(9),
832                    new AsyncFib(7),
833                };
834                invokeAll(tasks[0], tasks[1], tasks[2]);
835                for (AsyncFib task : tasks) assertTrue(task.isDone());
836                for (AsyncFib task : tasks) task.checkCompletedNormally();
837            }};
838        testInvokeOnPool(pool, a);
839    }
840
841    /**
842     * invokeAll(collection) invokes all tasks in the collection
843     */
844    public void testInvokeAllCollection() {
845        testInvokeAllCollection(mainPool());
846    }
847    public void testInvokeAllCollection_Singleton() {
848        testInvokeAllCollection(singletonPool());
849    }
850    public void testInvokeAllCollection(ForkJoinPool pool) {
851        RecursiveAction a = new CheckedRecursiveAction() {
852            protected void realCompute() {
853                AsyncFib[] tasks = {
854                    new AsyncFib(8),
855                    new AsyncFib(9),
856                    new AsyncFib(7),
857                };
858                invokeAll(Arrays.asList(tasks));
859                for (AsyncFib task : tasks) assertTrue(task.isDone());
860                for (AsyncFib task : tasks) task.checkCompletedNormally();
861            }};
862        testInvokeOnPool(pool, a);
863    }
864
865    /**
866     * invokeAll(tasks) with any null task throws NullPointerException
867     */
868    public void testInvokeAllNullTask() {
869        testInvokeAllNullTask(mainPool());
870    }
871    public void testInvokeAllNullTask_Singleton() {
872        testInvokeAllNullTask(singletonPool());
873    }
874    public void testInvokeAllNullTask(ForkJoinPool pool) {
875        RecursiveAction a = new CheckedRecursiveAction() {
876            protected void realCompute() {
877                AsyncFib nul = null;
878                Runnable[] throwingActions = {
879                    () -> invokeAll(nul),
880                    () -> invokeAll(nul, nul),
881                    () -> invokeAll(new AsyncFib(8), new AsyncFib(9), nul),
882                    () -> invokeAll(new AsyncFib(8), nul, new AsyncFib(9)),
883                    () -> invokeAll(nul, new AsyncFib(8), new AsyncFib(9)),
884                };
885                assertThrows(NullPointerException.class, throwingActions);
886            }};
887        testInvokeOnPool(pool, a);
888    }
889
890    /**
891     * invokeAll(tasks) with 1 argument throws exception if task does
892     */
893    public void testAbnormalInvokeAll1() {
894        testAbnormalInvokeAll1(mainPool());
895    }
896    public void testAbnormalInvokeAll1_Singleton() {
897        testAbnormalInvokeAll1(singletonPool());
898    }
899    public void testAbnormalInvokeAll1(ForkJoinPool pool) {
900        RecursiveAction a = new CheckedRecursiveAction() {
901            protected void realCompute() {
902                FailingAsyncFib g = new FailingAsyncFib(9);
903                try {
904                    invokeAll(g);
905                    shouldThrow();
906                } catch (FJException success) {
907                    checkCompletedAbnormally(g, success);
908                }
909            }};
910        testInvokeOnPool(pool, a);
911    }
912
913    /**
914     * invokeAll(t1, t2) throw exception if any task does
915     */
916    public void testAbnormalInvokeAll2() {
917        testAbnormalInvokeAll2(mainPool());
918    }
919    public void testAbnormalInvokeAll2_Singleton() {
920        testAbnormalInvokeAll2(singletonPool());
921    }
922    public void testAbnormalInvokeAll2(ForkJoinPool pool) {
923        RecursiveAction a = new CheckedRecursiveAction() {
924            protected void realCompute() {
925                AsyncFib f = new AsyncFib(8);
926                FailingAsyncFib g = new FailingAsyncFib(9);
927                ForkJoinTask[] tasks = { f, g };
928                Collections.shuffle(Arrays.asList(tasks));
929                try {
930                    invokeAll(tasks[0], tasks[1]);
931                    shouldThrow();
932                } catch (FJException success) {
933                    checkCompletedAbnormally(g, success);
934                }
935            }};
936        testInvokeOnPool(pool, a);
937    }
938
939    /**
940     * invokeAll(tasks) with > 2 argument throws exception if any task does
941     */
942    public void testAbnormalInvokeAll3() {
943        testAbnormalInvokeAll3(mainPool());
944    }
945    public void testAbnormalInvokeAll3_Singleton() {
946        testAbnormalInvokeAll3(singletonPool());
947    }
948    public void testAbnormalInvokeAll3(ForkJoinPool pool) {
949        RecursiveAction a = new CheckedRecursiveAction() {
950            protected void realCompute() {
951                AsyncFib f = new AsyncFib(8);
952                FailingAsyncFib g = new FailingAsyncFib(9);
953                AsyncFib h = new AsyncFib(7);
954                ForkJoinTask[] tasks = { f, g, h };
955                Collections.shuffle(Arrays.asList(tasks));
956                try {
957                    invokeAll(tasks[0], tasks[1], tasks[2]);
958                    shouldThrow();
959                } catch (FJException success) {
960                    checkCompletedAbnormally(g, success);
961                }
962            }};
963        testInvokeOnPool(pool, a);
964    }
965
966    /**
967     * invokeAll(collection) throws exception if any task does
968     */
969    public void testAbnormalInvokeAllCollection() {
970        testAbnormalInvokeAllCollection(mainPool());
971    }
972    public void testAbnormalInvokeAllCollection_Singleton() {
973        testAbnormalInvokeAllCollection(singletonPool());
974    }
975    public void testAbnormalInvokeAllCollection(ForkJoinPool pool) {
976        RecursiveAction a = new CheckedRecursiveAction() {
977            protected void realCompute() {
978                FailingAsyncFib f = new FailingAsyncFib(8);
979                AsyncFib g = new AsyncFib(9);
980                AsyncFib h = new AsyncFib(7);
981                ForkJoinTask[] tasks = { f, g, h };
982                Collections.shuffle(Arrays.asList(tasks));
983                try {
984                    invokeAll(Arrays.asList(tasks));
985                    shouldThrow();
986                } catch (FJException success) {
987                    checkCompletedAbnormally(f, success);
988                }
989            }};
990        testInvokeOnPool(pool, a);
991    }
992
993    /**
994     * tryUnfork returns true for most recent unexecuted task,
995     * and suppresses execution
996     */
997    public void testTryUnfork() {
998        RecursiveAction a = new CheckedRecursiveAction() {
999            protected void realCompute() {
1000                AsyncFib g = new AsyncFib(9);
1001                assertSame(g, g.fork());
1002                AsyncFib f = new AsyncFib(8);
1003                assertSame(f, f.fork());
1004                assertTrue(f.tryUnfork());
1005                helpQuiesce();
1006                checkNotDone(f);
1007                g.checkCompletedNormally();
1008            }};
1009        testInvokeOnPool(singletonPool(), a);
1010    }
1011
1012    /**
1013     * getSurplusQueuedTaskCount returns > 0 when
1014     * there are more tasks than threads
1015     */
1016    public void testGetSurplusQueuedTaskCount() {
1017        RecursiveAction a = new CheckedRecursiveAction() {
1018            protected void realCompute() {
1019                AsyncFib h = new AsyncFib(7);
1020                assertSame(h, h.fork());
1021                AsyncFib g = new AsyncFib(9);
1022                assertSame(g, g.fork());
1023                AsyncFib f = new AsyncFib(8);
1024                assertSame(f, f.fork());
1025                assertTrue(getSurplusQueuedTaskCount() > 0);
1026                helpQuiesce();
1027                assertEquals(0, getSurplusQueuedTaskCount());
1028                f.checkCompletedNormally();
1029                g.checkCompletedNormally();
1030                h.checkCompletedNormally();
1031            }};
1032        testInvokeOnPool(singletonPool(), a);
1033    }
1034
1035    /**
1036     * peekNextLocalTask returns most recent unexecuted task.
1037     */
1038    public void testPeekNextLocalTask() {
1039        RecursiveAction a = new CheckedRecursiveAction() {
1040            protected void realCompute() {
1041                AsyncFib g = new AsyncFib(9);
1042                assertSame(g, g.fork());
1043                AsyncFib f = new AsyncFib(8);
1044                assertSame(f, f.fork());
1045                assertSame(f, peekNextLocalTask());
1046                assertNull(f.join());
1047                f.checkCompletedNormally();
1048                helpQuiesce();
1049                g.checkCompletedNormally();
1050            }};
1051        testInvokeOnPool(singletonPool(), a);
1052    }
1053
1054    /**
1055     * pollNextLocalTask returns most recent unexecuted task without
1056     * executing it
1057     */
1058    public void testPollNextLocalTask() {
1059        RecursiveAction a = new CheckedRecursiveAction() {
1060            protected void realCompute() {
1061                AsyncFib g = new AsyncFib(9);
1062                assertSame(g, g.fork());
1063                AsyncFib f = new AsyncFib(8);
1064                assertSame(f, f.fork());
1065                assertSame(f, pollNextLocalTask());
1066                helpQuiesce();
1067                checkNotDone(f);
1068                g.checkCompletedNormally();
1069            }};
1070        testInvokeOnPool(singletonPool(), a);
1071    }
1072
1073    /**
1074     * pollTask returns an unexecuted task without executing it
1075     */
1076    public void testPollTask() {
1077        RecursiveAction a = new CheckedRecursiveAction() {
1078            protected void realCompute() {
1079                AsyncFib g = new AsyncFib(9);
1080                assertSame(g, g.fork());
1081                AsyncFib f = new AsyncFib(8);
1082                assertSame(f, f.fork());
1083                assertSame(f, pollTask());
1084                helpQuiesce();
1085                checkNotDone(f);
1086                g.checkCompletedNormally();
1087            }};
1088        testInvokeOnPool(singletonPool(), a);
1089    }
1090
1091    /**
1092     * peekNextLocalTask returns least recent unexecuted task in async mode
1093     */
1094    public void testPeekNextLocalTaskAsync() {
1095        RecursiveAction a = new CheckedRecursiveAction() {
1096            protected void realCompute() {
1097                AsyncFib g = new AsyncFib(9);
1098                assertSame(g, g.fork());
1099                AsyncFib f = new AsyncFib(8);
1100                assertSame(f, f.fork());
1101                assertSame(g, peekNextLocalTask());
1102                assertNull(f.join());
1103                helpQuiesce();
1104                f.checkCompletedNormally();
1105                g.checkCompletedNormally();
1106            }};
1107        testInvokeOnPool(asyncSingletonPool(), a);
1108    }
1109
1110    /**
1111     * pollNextLocalTask returns least recent unexecuted task without
1112     * executing it, in async mode
1113     */
1114    public void testPollNextLocalTaskAsync() {
1115        RecursiveAction a = new CheckedRecursiveAction() {
1116            protected void realCompute() {
1117                AsyncFib g = new AsyncFib(9);
1118                assertSame(g, g.fork());
1119                AsyncFib f = new AsyncFib(8);
1120                assertSame(f, f.fork());
1121                assertSame(g, pollNextLocalTask());
1122                helpQuiesce();
1123                f.checkCompletedNormally();
1124                checkNotDone(g);
1125            }};
1126        testInvokeOnPool(asyncSingletonPool(), a);
1127    }
1128
1129    /**
1130     * pollTask returns an unexecuted task without executing it, in
1131     * async mode
1132     */
1133    public void testPollTaskAsync() {
1134        RecursiveAction a = new CheckedRecursiveAction() {
1135            protected void realCompute() {
1136                AsyncFib g = new AsyncFib(9);
1137                assertSame(g, g.fork());
1138                AsyncFib f = new AsyncFib(8);
1139                assertSame(f, f.fork());
1140                assertSame(g, pollTask());
1141                helpQuiesce();
1142                f.checkCompletedNormally();
1143                checkNotDone(g);
1144            }};
1145        testInvokeOnPool(asyncSingletonPool(), a);
1146    }
1147
1148    /**
1149     * ForkJoinTask.quietlyComplete returns when task completes
1150     * normally without setting a value. The most recent value
1151     * established by setRawResult(V) (or null by default) is returned
1152     * from invoke.
1153     */
1154    public void testQuietlyComplete() {
1155        RecursiveAction a = new CheckedRecursiveAction() {
1156                protected void realCompute() {
1157                    AsyncFib f = new AsyncFib(8);
1158                    f.quietlyComplete();
1159                    assertEquals(8, f.number);
1160                    assertTrue(f.isDone());
1161                    assertFalse(f.isCancelled());
1162                    assertTrue(f.isCompletedNormally());
1163                    assertFalse(f.isCompletedAbnormally());
1164                    assertNull(f.getException());
1165                }};
1166        testInvokeOnPool(mainPool(), a);
1167    }
1168
1169    // jdk9
1170
1171    /**
1172     * pollSubmission returns unexecuted submitted task, if present
1173     */
1174    public void testPollSubmission() {
1175        final CountDownLatch done = new CountDownLatch(1);
1176        final ForkJoinTask a = ForkJoinTask.adapt(awaiter(done));
1177        final ForkJoinTask b = ForkJoinTask.adapt(awaiter(done));
1178        final ForkJoinTask c = ForkJoinTask.adapt(awaiter(done));
1179        final ForkJoinPool p = singletonPool();
1180        try (PoolCleaner cleaner = cleaner(p, done)) {
1181            Thread external = new Thread(new CheckedRunnable() {
1182                public void realRun() {
1183                    p.execute(a);
1184                    p.execute(b);
1185                    p.execute(c);
1186                }});
1187            RecursiveAction s = new CheckedRecursiveAction() {
1188                protected void realCompute() {
1189                    external.start();
1190                    try {
1191                        external.join();
1192                    } catch (Exception ex) {
1193                        threadUnexpectedException(ex);
1194                    }
1195                    assertTrue(p.hasQueuedSubmissions());
1196                    assertTrue(Thread.currentThread() instanceof ForkJoinWorkerThread);
1197                    ForkJoinTask r = ForkJoinTask.pollSubmission();
1198                    assertTrue(r == a || r == b || r == c);
1199                    assertFalse(r.isDone());
1200                }};
1201            p.invoke(s);
1202        }
1203    }
1204
1205}
1206