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