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.HashSet;
37 import java.util.concurrent.CancellationException;
38 import java.util.concurrent.ExecutionException;
39 import java.util.concurrent.ForkJoinPool;
40 import java.util.concurrent.ForkJoinTask;
41 import java.util.concurrent.RecursiveTask;
42 import java.util.concurrent.TimeoutException;
43 
44 import junit.framework.Test;
45 import junit.framework.TestSuite;
46 
47 public class RecursiveTaskTest extends JSR166TestCase {
48 
main(String[] args)49     public static void main(String[] args) {
50         main(suite(), args);
51     }
suite()52     public static Test suite() {
53         return new TestSuite(RecursiveTaskTest.class);
54     }
55 
mainPool()56     private static ForkJoinPool mainPool() {
57         return new ForkJoinPool();
58     }
59 
singletonPool()60     private static ForkJoinPool singletonPool() {
61         return new ForkJoinPool(1);
62     }
63 
asyncSingletonPool()64     private static ForkJoinPool asyncSingletonPool() {
65         return new ForkJoinPool(1,
66                                 ForkJoinPool.defaultForkJoinWorkerThreadFactory,
67                                 null, true);
68     }
69 
testInvokeOnPool(ForkJoinPool pool, RecursiveTask<T> a)70     private <T> T testInvokeOnPool(ForkJoinPool pool, RecursiveTask<T> a) {
71         try (PoolCleaner cleaner = cleaner(pool)) {
72             checkNotDone(a);
73 
74             T result = pool.invoke(a);
75 
76             checkCompletedNormally(a, result);
77             return result;
78         }
79     }
80 
checkNotDone(RecursiveTask a)81     void checkNotDone(RecursiveTask a) {
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         if (! ForkJoinTask.inForkJoinPool()) {
90             Thread.currentThread().interrupt();
91             try {
92                 a.get();
93                 shouldThrow();
94             } catch (InterruptedException success) {
95             } catch (Throwable fail) { threadUnexpectedException(fail); }
96 
97             Thread.currentThread().interrupt();
98             try {
99                 a.get(randomTimeout(), randomTimeUnit());
100                 shouldThrow();
101             } catch (InterruptedException success) {
102             } catch (Throwable fail) { threadUnexpectedException(fail); }
103         }
104 
105         try {
106             a.get(randomExpiredTimeout(), randomTimeUnit());
107             shouldThrow();
108         } catch (TimeoutException success) {
109         } catch (Throwable fail) { threadUnexpectedException(fail); }
110     }
111 
checkCompletedNormally(RecursiveTask<T> a, T expectedValue)112     <T> void checkCompletedNormally(RecursiveTask<T> a, T expectedValue) {
113         assertTrue(a.isDone());
114         assertFalse(a.isCancelled());
115         assertTrue(a.isCompletedNormally());
116         assertFalse(a.isCompletedAbnormally());
117         assertNull(a.getException());
118         assertSame(expectedValue, a.getRawResult());
119         assertSame(expectedValue, a.join());
120         assertFalse(a.cancel(false));
121         assertFalse(a.cancel(true));
122 
123         T v1 = null, v2 = null;
124         try {
125             v1 = a.get();
126             v2 = a.get(randomTimeout(), randomTimeUnit());
127         } catch (Throwable fail) { threadUnexpectedException(fail); }
128         assertSame(expectedValue, v1);
129         assertSame(expectedValue, v2);
130     }
131 
132     /**
133      * Waits for the task to complete, and checks that when it does,
134      * it will have an Integer result equals to the given int.
135      */
checkCompletesNormally(RecursiveTask<Integer> a, int expectedValue)136     void checkCompletesNormally(RecursiveTask<Integer> a, int expectedValue) {
137         Integer r = a.join();
138         assertEquals(expectedValue, (int) r);
139         checkCompletedNormally(a, r);
140     }
141 
142     /**
143      * Like checkCompletesNormally, but verifies that the task has
144      * already completed.
145      */
checkCompletedNormally(RecursiveTask<Integer> a, int expectedValue)146     void checkCompletedNormally(RecursiveTask<Integer> a, int expectedValue) {
147         Integer r = a.getRawResult();
148         assertEquals(expectedValue, (int) r);
149         checkCompletedNormally(a, r);
150     }
151 
checkCancelled(RecursiveTask a)152     void checkCancelled(RecursiveTask a) {
153         assertTrue(a.isDone());
154         assertTrue(a.isCancelled());
155         assertFalse(a.isCompletedNormally());
156         assertTrue(a.isCompletedAbnormally());
157         assertTrue(a.getException() instanceof CancellationException);
158         assertNull(a.getRawResult());
159 
160         try {
161             a.join();
162             shouldThrow();
163         } catch (CancellationException success) {
164         } catch (Throwable fail) { threadUnexpectedException(fail); }
165 
166         try {
167             a.get();
168             shouldThrow();
169         } catch (CancellationException success) {
170         } catch (Throwable fail) { threadUnexpectedException(fail); }
171 
172         try {
173             a.get(randomTimeout(), randomTimeUnit());
174             shouldThrow();
175         } catch (CancellationException success) {
176         } catch (Throwable fail) { threadUnexpectedException(fail); }
177     }
178 
checkCompletedAbnormally(RecursiveTask a, Throwable t)179     void checkCompletedAbnormally(RecursiveTask a, Throwable t) {
180         assertTrue(a.isDone());
181         assertFalse(a.isCancelled());
182         assertFalse(a.isCompletedNormally());
183         assertTrue(a.isCompletedAbnormally());
184         assertSame(t.getClass(), a.getException().getClass());
185         assertNull(a.getRawResult());
186         assertFalse(a.cancel(false));
187         assertFalse(a.cancel(true));
188 
189         try {
190             a.join();
191             shouldThrow();
192         } catch (Throwable expected) {
193             assertSame(t.getClass(), expected.getClass());
194         }
195 
196         try {
197             a.get();
198             shouldThrow();
199         } catch (ExecutionException success) {
200             assertSame(t.getClass(), success.getCause().getClass());
201         } catch (Throwable fail) { threadUnexpectedException(fail); }
202 
203         try {
204             a.get(randomTimeout(), randomTimeUnit());
205             shouldThrow();
206         } catch (ExecutionException success) {
207             assertSame(t.getClass(), success.getCause().getClass());
208         } catch (Throwable fail) { threadUnexpectedException(fail); }
209     }
210 
211     public static final class FJException extends RuntimeException {
FJException()212         public FJException() { super(); }
213     }
214 
215     /** An invalid return value for Fib. */
216     static final Integer NoResult = Integer.valueOf(-17);
217 
218     /** A simple recursive task for testing. */
219     final class FibTask extends CheckedRecursiveTask<Integer> {
220         final int number;
FibTask(int n)221         FibTask(int n) { number = n; }
realCompute()222         public Integer realCompute() {
223             int n = number;
224             if (n <= 1)
225                 return n;
226             FibTask f1 = new FibTask(n - 1);
227             f1.fork();
228             return new FibTask(n - 2).compute() + f1.join();
229         }
230 
publicSetRawResult(Integer result)231         public void publicSetRawResult(Integer result) {
232             setRawResult(result);
233         }
234     }
235 
236     /** A recursive action failing in base case. */
237     final class FailingFibTask extends RecursiveTask<Integer> {
238         final int number;
239         int result;
FailingFibTask(int n)240         FailingFibTask(int n) { number = n; }
compute()241         public Integer compute() {
242             int n = number;
243             if (n <= 1)
244                 throw new FJException();
245             FailingFibTask f1 = new FailingFibTask(n - 1);
246             f1.fork();
247             return new FibTask(n - 2).compute() + f1.join();
248         }
249     }
250 
251     /**
252      * invoke returns value when task completes normally.
253      * isCompletedAbnormally and isCancelled return false for normally
254      * completed tasks. getRawResult of a completed non-null task
255      * returns value;
256      */
testInvoke()257     public void testInvoke() {
258         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
259             public Integer realCompute() {
260                 FibTask f = new FibTask(8);
261                 Integer r = f.invoke();
262                 assertEquals(21, (int) r);
263                 checkCompletedNormally(f, r);
264                 return r;
265             }};
266         assertEquals(21, (int) testInvokeOnPool(mainPool(), a));
267     }
268 
269     /**
270      * quietlyInvoke task returns when task completes normally.
271      * isCompletedAbnormally and isCancelled return false for normally
272      * completed tasks
273      */
testQuietlyInvoke()274     public void testQuietlyInvoke() {
275         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
276             public Integer realCompute() {
277                 FibTask f = new FibTask(8);
278                 f.quietlyInvoke();
279                 checkCompletedNormally(f, 21);
280                 return NoResult;
281             }};
282         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
283     }
284 
285     /**
286      * join of a forked task returns when task completes
287      */
testForkJoin()288     public void testForkJoin() {
289         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
290             public Integer realCompute() {
291                 FibTask f = new FibTask(8);
292                 assertSame(f, f.fork());
293                 Integer r = f.join();
294                 assertEquals(21, (int) r);
295                 checkCompletedNormally(f, r);
296                 return r;
297             }};
298         assertEquals(21, (int) testInvokeOnPool(mainPool(), a));
299     }
300 
301     /**
302      * get of a forked task returns when task completes
303      */
testForkGet()304     public void testForkGet() {
305         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
306             public Integer realCompute() throws Exception {
307                 FibTask f = new FibTask(8);
308                 assertSame(f, f.fork());
309                 Integer r = f.get();
310                 assertEquals(21, (int) r);
311                 checkCompletedNormally(f, r);
312                 return r;
313             }};
314         assertEquals(21, (int) testInvokeOnPool(mainPool(), a));
315     }
316 
317     /**
318      * timed get of a forked task returns when task completes
319      */
testForkTimedGet()320     public void testForkTimedGet() {
321         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
322             public Integer realCompute() throws Exception {
323                 FibTask f = new FibTask(8);
324                 assertSame(f, f.fork());
325                 Integer r = f.get(LONG_DELAY_MS, MILLISECONDS);
326                 assertEquals(21, (int) r);
327                 checkCompletedNormally(f, r);
328                 return r;
329             }};
330         assertEquals(21, (int) testInvokeOnPool(mainPool(), a));
331     }
332 
333     /**
334      * quietlyJoin of a forked task returns when task completes
335      */
testForkQuietlyJoin()336     public void testForkQuietlyJoin() {
337         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
338             public Integer realCompute() {
339                 FibTask f = new FibTask(8);
340                 assertSame(f, f.fork());
341                 f.quietlyJoin();
342                 Integer r = f.getRawResult();
343                 assertEquals(21, (int) r);
344                 checkCompletedNormally(f, r);
345                 return r;
346             }};
347         assertEquals(21, (int) testInvokeOnPool(mainPool(), a));
348     }
349 
350     /**
351      * helpQuiesce returns when tasks are complete.
352      * getQueuedTaskCount returns 0 when quiescent
353      */
testForkHelpQuiesce()354     public void testForkHelpQuiesce() {
355         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
356             public Integer realCompute() {
357                 FibTask f = new FibTask(8);
358                 assertSame(f, f.fork());
359                 helpQuiesce();
360                 while (!f.isDone()) // wait out race
361                     ;
362                 assertEquals(0, getQueuedTaskCount());
363                 checkCompletedNormally(f, 21);
364                 return NoResult;
365             }};
366         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
367     }
368 
369     /**
370      * invoke task throws exception when task completes abnormally
371      */
testAbnormalInvoke()372     public void testAbnormalInvoke() {
373         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
374             public Integer realCompute() {
375                 FailingFibTask f = new FailingFibTask(8);
376                 try {
377                     f.invoke();
378                     shouldThrow();
379                 } catch (FJException success) {
380                     checkCompletedAbnormally(f, success);
381                 }
382                 return NoResult;
383             }};
384         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
385     }
386 
387     /**
388      * quietlyInvoke task returns when task completes abnormally
389      */
testAbnormalQuietlyInvoke()390     public void testAbnormalQuietlyInvoke() {
391         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
392             public Integer realCompute() {
393                 FailingFibTask f = new FailingFibTask(8);
394                 f.quietlyInvoke();
395                 assertTrue(f.getException() instanceof FJException);
396                 checkCompletedAbnormally(f, f.getException());
397                 return NoResult;
398             }};
399         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
400     }
401 
402     /**
403      * join of a forked task throws exception when task completes abnormally
404      */
testAbnormalForkJoin()405     public void testAbnormalForkJoin() {
406         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
407             public Integer realCompute() {
408                 FailingFibTask f = new FailingFibTask(8);
409                 assertSame(f, f.fork());
410                 try {
411                     Integer r = f.join();
412                     shouldThrow();
413                 } catch (FJException success) {
414                     checkCompletedAbnormally(f, success);
415                 }
416                 return NoResult;
417             }};
418         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
419     }
420 
421     /**
422      * get of a forked task throws exception when task completes abnormally
423      */
testAbnormalForkGet()424     public void testAbnormalForkGet() {
425         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
426             public Integer realCompute() throws Exception {
427                 FailingFibTask f = new FailingFibTask(8);
428                 assertSame(f, f.fork());
429                 try {
430                     Integer r = f.get();
431                     shouldThrow();
432                 } catch (ExecutionException success) {
433                     Throwable cause = success.getCause();
434                     assertTrue(cause instanceof FJException);
435                     checkCompletedAbnormally(f, cause);
436                 }
437                 return NoResult;
438             }};
439         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
440     }
441 
442     /**
443      * timed get of a forked task throws exception when task completes abnormally
444      */
testAbnormalForkTimedGet()445     public void testAbnormalForkTimedGet() {
446         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
447             public Integer realCompute() throws Exception {
448                 FailingFibTask f = new FailingFibTask(8);
449                 assertSame(f, f.fork());
450                 try {
451                     Integer r = f.get(LONG_DELAY_MS, MILLISECONDS);
452                     shouldThrow();
453                 } catch (ExecutionException success) {
454                     Throwable cause = success.getCause();
455                     assertTrue(cause instanceof FJException);
456                     checkCompletedAbnormally(f, cause);
457                 }
458                 return NoResult;
459             }};
460         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
461     }
462 
463     /**
464      * quietlyJoin of a forked task returns when task completes abnormally
465      */
testAbnormalForkQuietlyJoin()466     public void testAbnormalForkQuietlyJoin() {
467         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
468             public Integer realCompute() {
469                 FailingFibTask f = new FailingFibTask(8);
470                 assertSame(f, f.fork());
471                 f.quietlyJoin();
472                 assertTrue(f.getException() instanceof FJException);
473                 checkCompletedAbnormally(f, f.getException());
474                 return NoResult;
475             }};
476         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
477     }
478 
479     /**
480      * invoke task throws exception when task cancelled
481      */
testCancelledInvoke()482     public void testCancelledInvoke() {
483         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
484             public Integer realCompute() {
485                 FibTask f = new FibTask(8);
486                 assertTrue(f.cancel(true));
487                 try {
488                     Integer r = f.invoke();
489                     shouldThrow();
490                 } catch (CancellationException success) {
491                     checkCancelled(f);
492                 }
493                 return NoResult;
494             }};
495         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
496     }
497 
498     /**
499      * join of a forked task throws exception when task cancelled
500      */
testCancelledForkJoin()501     public void testCancelledForkJoin() {
502         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
503             public Integer realCompute() {
504                 FibTask f = new FibTask(8);
505                 assertTrue(f.cancel(true));
506                 assertSame(f, f.fork());
507                 try {
508                     Integer r = f.join();
509                     shouldThrow();
510                 } catch (CancellationException success) {
511                     checkCancelled(f);
512                 }
513                 return NoResult;
514             }};
515         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
516     }
517 
518     /**
519      * get of a forked task throws exception when task cancelled
520      */
testCancelledForkGet()521     public void testCancelledForkGet() {
522         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
523             public Integer realCompute() throws Exception {
524                 FibTask f = new FibTask(8);
525                 assertTrue(f.cancel(true));
526                 assertSame(f, f.fork());
527                 try {
528                     Integer r = f.get();
529                     shouldThrow();
530                 } catch (CancellationException success) {
531                     checkCancelled(f);
532                 }
533                 return NoResult;
534             }};
535         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
536     }
537 
538     /**
539      * timed get of a forked task throws exception when task cancelled
540      */
testCancelledForkTimedGet()541     public void testCancelledForkTimedGet() {
542         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
543             public Integer realCompute() throws Exception {
544                 FibTask f = new FibTask(8);
545                 assertTrue(f.cancel(true));
546                 assertSame(f, f.fork());
547                 try {
548                     Integer r = f.get(LONG_DELAY_MS, MILLISECONDS);
549                     shouldThrow();
550                 } catch (CancellationException success) {
551                     checkCancelled(f);
552                 }
553                 return NoResult;
554             }};
555         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
556     }
557 
558     /**
559      * quietlyJoin of a forked task returns when task cancelled
560      */
testCancelledForkQuietlyJoin()561     public void testCancelledForkQuietlyJoin() {
562         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
563             public Integer realCompute() {
564                 FibTask f = new FibTask(8);
565                 assertTrue(f.cancel(true));
566                 assertSame(f, f.fork());
567                 f.quietlyJoin();
568                 checkCancelled(f);
569                 return NoResult;
570             }};
571         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
572     }
573 
574     /**
575      * getPool of executing task returns its pool
576      */
testGetPool()577     public void testGetPool() {
578         final ForkJoinPool mainPool = mainPool();
579         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
580             public Integer realCompute() {
581                 assertSame(mainPool, getPool());
582                 return NoResult;
583             }};
584         assertSame(NoResult, testInvokeOnPool(mainPool, a));
585     }
586 
587     /**
588      * getPool of non-FJ task returns null
589      */
testGetPool2()590     public void testGetPool2() {
591         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
592             public Integer realCompute() {
593                 assertNull(getPool());
594                 return NoResult;
595             }};
596         assertSame(NoResult, a.invoke());
597     }
598 
599     /**
600      * inForkJoinPool of executing task returns true
601      */
testInForkJoinPool()602     public void testInForkJoinPool() {
603         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
604             public Integer realCompute() {
605                 assertTrue(inForkJoinPool());
606                 return NoResult;
607             }};
608         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
609     }
610 
611     /**
612      * inForkJoinPool of non-FJ task returns false
613      */
testInForkJoinPool2()614     public void testInForkJoinPool2() {
615         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
616             public Integer realCompute() {
617                 assertFalse(inForkJoinPool());
618                 return NoResult;
619             }};
620         assertSame(NoResult, a.invoke());
621     }
622 
623     /**
624      * The value set by setRawResult is returned by getRawResult
625      */
testSetRawResult()626     public void testSetRawResult() {
627         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
628             public Integer realCompute() {
629                 setRawResult(NoResult);
630                 assertSame(NoResult, getRawResult());
631                 return NoResult;
632             }
633         };
634         assertSame(NoResult, a.invoke());
635     }
636 
637     /**
638      * A reinitialized normally completed task may be re-invoked
639      */
testReinitialize()640     public void testReinitialize() {
641         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
642             public Integer realCompute() {
643                 FibTask f = new FibTask(8);
644                 checkNotDone(f);
645 
646                 for (int i = 0; i < 3; i++) {
647                     Integer r = f.invoke();
648                     assertEquals(21, (int) r);
649                     checkCompletedNormally(f, r);
650                     f.reinitialize();
651                     f.publicSetRawResult(null);
652                     checkNotDone(f);
653                 }
654                 return NoResult;
655             }};
656         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
657     }
658 
659     /**
660      * A reinitialized abnormally completed task may be re-invoked
661      */
testReinitializeAbnormal()662     public void testReinitializeAbnormal() {
663         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
664             public Integer realCompute() {
665                 FailingFibTask f = new FailingFibTask(8);
666                 checkNotDone(f);
667 
668                 for (int i = 0; i < 3; i++) {
669                     try {
670                         f.invoke();
671                         shouldThrow();
672                     } catch (FJException success) {
673                         checkCompletedAbnormally(f, success);
674                     }
675                     f.reinitialize();
676                     checkNotDone(f);
677                 }
678                 return NoResult;
679             }};
680         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
681     }
682 
683     /**
684      * invoke task throws exception after invoking completeExceptionally
685      */
testCompleteExceptionally()686     public void testCompleteExceptionally() {
687         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
688             public Integer realCompute() {
689                 FibTask f = new FibTask(8);
690                 f.completeExceptionally(new FJException());
691                 try {
692                     Integer r = f.invoke();
693                     shouldThrow();
694                 } catch (FJException success) {
695                     checkCompletedAbnormally(f, success);
696                 }
697                 return NoResult;
698             }};
699         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
700     }
701 
702     /**
703      * invoke task suppresses execution invoking complete
704      */
testComplete()705     public void testComplete() {
706         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
707             public Integer realCompute() {
708                 FibTask f = new FibTask(8);
709                 f.complete(NoResult);
710                 Integer r = f.invoke();
711                 assertSame(NoResult, r);
712                 checkCompletedNormally(f, NoResult);
713                 return r;
714             }};
715         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
716     }
717 
718     /**
719      * invokeAll(t1, t2) invokes all task arguments
720      */
testInvokeAll2()721     public void testInvokeAll2() {
722         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
723             public Integer realCompute() {
724                 FibTask f = new FibTask(8);
725                 FibTask g = new FibTask(9);
726                 invokeAll(f, g);
727                 checkCompletedNormally(f, 21);
728                 checkCompletedNormally(g, 34);
729                 return NoResult;
730             }};
731         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
732     }
733 
734     /**
735      * invokeAll(tasks) with 1 argument invokes task
736      */
testInvokeAll1()737     public void testInvokeAll1() {
738         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
739             public Integer realCompute() {
740                 FibTask f = new FibTask(8);
741                 invokeAll(f);
742                 checkCompletedNormally(f, 21);
743                 return NoResult;
744             }};
745         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
746     }
747 
748     /**
749      * invokeAll(tasks) with > 2 argument invokes tasks
750      */
testInvokeAll3()751     public void testInvokeAll3() {
752         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
753             public Integer realCompute() {
754                 FibTask f = new FibTask(8);
755                 FibTask g = new FibTask(9);
756                 FibTask h = new FibTask(7);
757                 invokeAll(f, g, h);
758                 assertTrue(f.isDone());
759                 assertTrue(g.isDone());
760                 assertTrue(h.isDone());
761                 checkCompletedNormally(f, 21);
762                 checkCompletedNormally(g, 34);
763                 checkCompletedNormally(h, 13);
764                 return NoResult;
765             }};
766         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
767     }
768 
769     /**
770      * invokeAll(collection) invokes all tasks in the collection
771      */
testInvokeAllCollection()772     public void testInvokeAllCollection() {
773         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
774             public Integer realCompute() {
775                 FibTask f = new FibTask(8);
776                 FibTask g = new FibTask(9);
777                 FibTask h = new FibTask(7);
778                 HashSet set = new HashSet();
779                 set.add(f);
780                 set.add(g);
781                 set.add(h);
782                 invokeAll(set);
783                 assertTrue(f.isDone());
784                 assertTrue(g.isDone());
785                 assertTrue(h.isDone());
786                 checkCompletedNormally(f, 21);
787                 checkCompletedNormally(g, 34);
788                 checkCompletedNormally(h, 13);
789                 return NoResult;
790             }};
791         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
792     }
793 
794     /**
795      * invokeAll(tasks) with any null task throws NPE
796      */
testInvokeAllNPE()797     public void testInvokeAllNPE() {
798         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
799             public Integer realCompute() {
800                 FibTask f = new FibTask(8);
801                 FibTask g = new FibTask(9);
802                 FibTask h = null;
803                 try {
804                     invokeAll(f, g, h);
805                     shouldThrow();
806                 } catch (NullPointerException success) {}
807                 return NoResult;
808             }};
809         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
810     }
811 
812     /**
813      * invokeAll(t1, t2) throw exception if any task does
814      */
testAbnormalInvokeAll2()815     public void testAbnormalInvokeAll2() {
816         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
817             public Integer realCompute() {
818                 FibTask f = new FibTask(8);
819                 FailingFibTask g = new FailingFibTask(9);
820                 try {
821                     invokeAll(f, g);
822                     shouldThrow();
823                 } catch (FJException success) {
824                     checkCompletedAbnormally(g, success);
825                 }
826                 return NoResult;
827             }};
828         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
829     }
830 
831     /**
832      * invokeAll(tasks) with 1 argument throws exception if task does
833      */
testAbnormalInvokeAll1()834     public void testAbnormalInvokeAll1() {
835         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
836             public Integer realCompute() {
837                 FailingFibTask g = new FailingFibTask(9);
838                 try {
839                     invokeAll(g);
840                     shouldThrow();
841                 } catch (FJException success) {
842                     checkCompletedAbnormally(g, success);
843                 }
844                 return NoResult;
845             }};
846         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
847     }
848 
849     /**
850      * invokeAll(tasks) with > 2 argument throws exception if any task does
851      */
testAbnormalInvokeAll3()852     public void testAbnormalInvokeAll3() {
853         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
854             public Integer realCompute() {
855                 FibTask f = new FibTask(8);
856                 FailingFibTask g = new FailingFibTask(9);
857                 FibTask h = new FibTask(7);
858                 try {
859                     invokeAll(f, g, h);
860                     shouldThrow();
861                 } catch (FJException success) {
862                     checkCompletedAbnormally(g, success);
863                 }
864                 return NoResult;
865             }};
866         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
867     }
868 
869     /**
870      * invokeAll(collection) throws exception if any task does
871      */
testAbnormalInvokeAllCollection()872     public void testAbnormalInvokeAllCollection() {
873         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
874             public Integer realCompute() {
875                 FailingFibTask f = new FailingFibTask(8);
876                 FibTask g = new FibTask(9);
877                 FibTask h = new FibTask(7);
878                 HashSet set = new HashSet();
879                 set.add(f);
880                 set.add(g);
881                 set.add(h);
882                 try {
883                     invokeAll(set);
884                     shouldThrow();
885                 } catch (FJException success) {
886                     checkCompletedAbnormally(f, success);
887                 }
888                 return NoResult;
889             }};
890         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
891     }
892 
893     /**
894      * tryUnfork returns true for most recent unexecuted task,
895      * and suppresses execution
896      */
testTryUnfork()897     public void testTryUnfork() {
898         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
899             public Integer realCompute() {
900                 FibTask g = new FibTask(9);
901                 assertSame(g, g.fork());
902                 FibTask f = new FibTask(8);
903                 assertSame(f, f.fork());
904                 assertTrue(f.tryUnfork());
905                 helpQuiesce();
906                 checkNotDone(f);
907                 checkCompletedNormally(g, 34);
908                 return NoResult;
909             }};
910         assertSame(NoResult, testInvokeOnPool(singletonPool(), a));
911     }
912 
913     /**
914      * getSurplusQueuedTaskCount returns > 0 when
915      * there are more tasks than threads
916      */
testGetSurplusQueuedTaskCount()917     public void testGetSurplusQueuedTaskCount() {
918         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
919             public Integer realCompute() {
920                 FibTask h = new FibTask(7);
921                 assertSame(h, h.fork());
922                 FibTask g = new FibTask(9);
923                 assertSame(g, g.fork());
924                 FibTask f = new FibTask(8);
925                 assertSame(f, f.fork());
926                 assertTrue(getSurplusQueuedTaskCount() > 0);
927                 helpQuiesce();
928                 assertEquals(0, getSurplusQueuedTaskCount());
929                 checkCompletedNormally(f, 21);
930                 checkCompletedNormally(g, 34);
931                 checkCompletedNormally(h, 13);
932                 return NoResult;
933             }};
934         assertSame(NoResult, testInvokeOnPool(singletonPool(), a));
935     }
936 
937     /**
938      * peekNextLocalTask returns most recent unexecuted task.
939      */
testPeekNextLocalTask()940     public void testPeekNextLocalTask() {
941         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
942             public Integer realCompute() {
943                 FibTask g = new FibTask(9);
944                 assertSame(g, g.fork());
945                 FibTask f = new FibTask(8);
946                 assertSame(f, f.fork());
947                 assertSame(f, peekNextLocalTask());
948                 checkCompletesNormally(f, 21);
949                 helpQuiesce();
950                 checkCompletedNormally(g, 34);
951                 return NoResult;
952             }};
953         assertSame(NoResult, testInvokeOnPool(singletonPool(), a));
954     }
955 
956     /**
957      * pollNextLocalTask returns most recent unexecuted task
958      * without executing it
959      */
testPollNextLocalTask()960     public void testPollNextLocalTask() {
961         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
962             public Integer realCompute() {
963                 FibTask g = new FibTask(9);
964                 assertSame(g, g.fork());
965                 FibTask f = new FibTask(8);
966                 assertSame(f, f.fork());
967                 assertSame(f, pollNextLocalTask());
968                 helpQuiesce();
969                 checkNotDone(f);
970                 checkCompletedNormally(g, 34);
971                 return NoResult;
972             }};
973         assertSame(NoResult, testInvokeOnPool(singletonPool(), a));
974     }
975 
976     /**
977      * pollTask returns an unexecuted task without executing it
978      */
testPollTask()979     public void testPollTask() {
980         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
981             public Integer realCompute() {
982                 FibTask g = new FibTask(9);
983                 assertSame(g, g.fork());
984                 FibTask f = new FibTask(8);
985                 assertSame(f, f.fork());
986                 assertSame(f, pollTask());
987                 helpQuiesce();
988                 checkNotDone(f);
989                 checkCompletedNormally(g, 34);
990                 return NoResult;
991             }};
992         assertSame(NoResult, testInvokeOnPool(singletonPool(), a));
993     }
994 
995     /**
996      * peekNextLocalTask returns least recent unexecuted task in async mode
997      */
testPeekNextLocalTaskAsync()998     public void testPeekNextLocalTaskAsync() {
999         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
1000             public Integer realCompute() {
1001                 FibTask g = new FibTask(9);
1002                 assertSame(g, g.fork());
1003                 FibTask f = new FibTask(8);
1004                 assertSame(f, f.fork());
1005                 assertSame(g, peekNextLocalTask());
1006                 assertEquals(21, (int) f.join());
1007                 helpQuiesce();
1008                 checkCompletedNormally(f, 21);
1009                 checkCompletedNormally(g, 34);
1010                 return NoResult;
1011             }};
1012         assertSame(NoResult, testInvokeOnPool(asyncSingletonPool(), a));
1013     }
1014 
1015     /**
1016      * pollNextLocalTask returns least recent unexecuted task without
1017      * executing it, in async mode
1018      */
testPollNextLocalTaskAsync()1019     public void testPollNextLocalTaskAsync() {
1020         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
1021             public Integer realCompute() {
1022                 FibTask g = new FibTask(9);
1023                 assertSame(g, g.fork());
1024                 FibTask f = new FibTask(8);
1025                 assertSame(f, f.fork());
1026                 assertSame(g, pollNextLocalTask());
1027                 helpQuiesce();
1028                 checkCompletedNormally(f, 21);
1029                 checkNotDone(g);
1030                 return NoResult;
1031             }};
1032         assertSame(NoResult, testInvokeOnPool(asyncSingletonPool(), a));
1033     }
1034 
1035     /**
1036      * pollTask returns an unexecuted task without executing it, in
1037      * async mode
1038      */
testPollTaskAsync()1039     public void testPollTaskAsync() {
1040         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
1041             public Integer realCompute() {
1042                 FibTask g = new FibTask(9);
1043                 assertSame(g, g.fork());
1044                 FibTask f = new FibTask(8);
1045                 assertSame(f, f.fork());
1046                 assertSame(g, pollTask());
1047                 helpQuiesce();
1048                 checkCompletedNormally(f, 21);
1049                 checkNotDone(g);
1050                 return NoResult;
1051             }};
1052         assertSame(NoResult, testInvokeOnPool(asyncSingletonPool(), a));
1053     }
1054 
1055 }
1056