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 
7 package jsr166;
8 
9 import static java.util.concurrent.TimeUnit.MILLISECONDS;
10 import static java.util.concurrent.TimeUnit.SECONDS;
11 
12 import java.util.Arrays;
13 import java.util.Collections;
14 import java.util.concurrent.CountDownLatch;
15 import java.util.concurrent.ExecutionException;
16 import java.util.concurrent.ForkJoinPool;
17 import java.util.concurrent.ForkJoinTask;
18 import java.util.concurrent.ForkJoinWorkerThread;
19 import java.util.concurrent.RecursiveAction;
20 import java.util.concurrent.TimeoutException;
21 
22 import junit.framework.Test;
23 import junit.framework.TestSuite;
24 
25 public 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 
mainPool()55     private static ForkJoinPool mainPool() {
56         return new ForkJoinPool(mainPoolSize);
57     }
58 
singletonPool()59     private static ForkJoinPool singletonPool() {
60         return new ForkJoinPool(1);
61     }
62 
asyncSingletonPool()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 
testInvokeOnPool(ForkJoinPool pool, RecursiveAction a)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 
checkNotDone(ForkJoinTask a)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 
checkCompletedNormally(ForkJoinTask<T> a)117     <T> void checkCompletedNormally(ForkJoinTask<T> a) {
118         checkCompletedNormally(a, null);
119     }
120 
checkCompletedNormally(ForkJoinTask<T> a, T expected)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             }};
testInvokeOnPool(pool, a)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