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