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