ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck-jsr166e/RecursiveActionTest.java
Revision: 1.1
Committed: Sun Jul 14 19:55:05 2013 UTC (10 years, 10 months ago) by jsr166
Branch: MAIN
CVS Tags: HEAD
Log Message:
backport jsr166e to run on jdk6; backport all applicable tck tests from tck to tck-jsr166e

File Contents

# User Rev Content
1 jsr166 1.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     import jsr166e.*;
8     import junit.framework.*;
9     import java.util.concurrent.CancellationException;
10     import java.util.concurrent.SynchronousQueue;
11     import java.util.concurrent.ExecutionException;
12     import java.util.concurrent.TimeUnit;
13     import java.util.concurrent.TimeoutException;
14     import static java.util.concurrent.TimeUnit.SECONDS;
15     import java.util.Arrays;
16     import java.util.HashSet;
17    
18     public class RecursiveActionTest extends JSR166TestCase {
19    
20     public static void main(String[] args) {
21     junit.textui.TestRunner.run(suite());
22     }
23    
24     public static Test suite() {
25     return new TestSuite(RecursiveActionTest.class);
26     }
27    
28     private static ForkJoinPool mainPool() {
29     return new ForkJoinPool();
30     }
31    
32     private static ForkJoinPool singletonPool() {
33     return new ForkJoinPool(1);
34     }
35    
36     private static ForkJoinPool asyncSingletonPool() {
37     return new ForkJoinPool(1,
38     ForkJoinPool.defaultForkJoinWorkerThreadFactory,
39     null, true);
40     }
41    
42     private void testInvokeOnPool(ForkJoinPool pool, RecursiveAction a) {
43     try {
44     checkNotDone(a);
45    
46     assertNull(pool.invoke(a));
47    
48     checkCompletedNormally(a);
49     } finally {
50     joinPool(pool);
51     }
52     }
53    
54     void checkNotDone(RecursiveAction a) {
55     assertFalse(a.isDone());
56     assertFalse(a.isCompletedNormally());
57     assertFalse(a.isCompletedAbnormally());
58     assertFalse(a.isCancelled());
59     assertNull(a.getException());
60     assertNull(a.getRawResult());
61    
62     if (! ForkJoinTask.inForkJoinPool()) {
63     Thread.currentThread().interrupt();
64     try {
65     a.get();
66     shouldThrow();
67     } catch (InterruptedException success) {
68     } catch (Throwable fail) { threadUnexpectedException(fail); }
69    
70     Thread.currentThread().interrupt();
71     try {
72     a.get(5L, SECONDS);
73     shouldThrow();
74     } catch (InterruptedException success) {
75     } catch (Throwable fail) { threadUnexpectedException(fail); }
76     }
77    
78     try {
79     a.get(0L, SECONDS);
80     shouldThrow();
81     } catch (TimeoutException success) {
82     } catch (Throwable fail) { threadUnexpectedException(fail); }
83     }
84    
85     void checkCompletedNormally(RecursiveAction a) {
86     assertTrue(a.isDone());
87     assertFalse(a.isCancelled());
88     assertTrue(a.isCompletedNormally());
89     assertFalse(a.isCompletedAbnormally());
90     assertNull(a.getException());
91     assertNull(a.getRawResult());
92     assertNull(a.join());
93     assertFalse(a.cancel(false));
94     assertFalse(a.cancel(true));
95     try {
96     assertNull(a.get());
97     } catch (Throwable fail) { threadUnexpectedException(fail); }
98     try {
99     assertNull(a.get(5L, SECONDS));
100     } catch (Throwable fail) { threadUnexpectedException(fail); }
101     }
102    
103     void checkCancelled(RecursiveAction a) {
104     assertTrue(a.isDone());
105     assertTrue(a.isCancelled());
106     assertFalse(a.isCompletedNormally());
107     assertTrue(a.isCompletedAbnormally());
108     assertTrue(a.getException() instanceof CancellationException);
109     assertNull(a.getRawResult());
110    
111     try {
112     a.join();
113     shouldThrow();
114     } catch (CancellationException success) {
115     } catch (Throwable fail) { threadUnexpectedException(fail); }
116    
117     try {
118     a.get();
119     shouldThrow();
120     } catch (CancellationException success) {
121     } catch (Throwable fail) { threadUnexpectedException(fail); }
122    
123     try {
124     a.get(5L, SECONDS);
125     shouldThrow();
126     } catch (CancellationException success) {
127     } catch (Throwable fail) { threadUnexpectedException(fail); }
128     }
129    
130     void checkCompletedAbnormally(RecursiveAction a, Throwable t) {
131     assertTrue(a.isDone());
132     assertFalse(a.isCancelled());
133     assertFalse(a.isCompletedNormally());
134     assertTrue(a.isCompletedAbnormally());
135     assertSame(t.getClass(), a.getException().getClass());
136     assertNull(a.getRawResult());
137     assertFalse(a.cancel(false));
138     assertFalse(a.cancel(true));
139    
140     try {
141     a.join();
142     shouldThrow();
143     } catch (Throwable expected) {
144     assertSame(expected.getClass(), t.getClass());
145     }
146    
147     try {
148     a.get();
149     shouldThrow();
150     } catch (ExecutionException success) {
151     assertSame(t.getClass(), success.getCause().getClass());
152     } catch (Throwable fail) { threadUnexpectedException(fail); }
153    
154     try {
155     a.get(5L, SECONDS);
156     shouldThrow();
157     } catch (ExecutionException success) {
158     assertSame(t.getClass(), success.getCause().getClass());
159     } catch (Throwable fail) { threadUnexpectedException(fail); }
160     }
161    
162     public static final class FJException extends RuntimeException {
163     public FJException() { super(); }
164     public FJException(Throwable cause) { super(cause); }
165     }
166    
167     // A simple recursive action for testing
168     final class FibAction extends CheckedRecursiveAction {
169     final int number;
170     int result;
171     FibAction(int n) { number = n; }
172     protected void realCompute() {
173     int n = number;
174     if (n <= 1)
175     result = n;
176     else {
177     FibAction f1 = new FibAction(n - 1);
178     FibAction f2 = new FibAction(n - 2);
179     invokeAll(f1, f2);
180     result = f1.result + f2.result;
181     }
182     }
183     }
184    
185     // A recursive action failing in base case
186     static final class FailingFibAction extends RecursiveAction {
187     final int number;
188     int result;
189     FailingFibAction(int n) { number = n; }
190     public void compute() {
191     int n = number;
192     if (n <= 1)
193     throw new FJException();
194     else {
195     FailingFibAction f1 = new FailingFibAction(n - 1);
196     FailingFibAction f2 = new FailingFibAction(n - 2);
197     invokeAll(f1, f2);
198     result = f1.result + f2.result;
199     }
200     }
201     }
202    
203     /**
204     * invoke returns when task completes normally.
205     * isCompletedAbnormally and isCancelled return false for normally
206     * completed tasks. getRawResult of a RecursiveAction returns null;
207     */
208     public void testInvoke() {
209     RecursiveAction a = new CheckedRecursiveAction() {
210     protected void realCompute() {
211     FibAction f = new FibAction(8);
212     assertNull(f.invoke());
213     assertEquals(21, f.result);
214     checkCompletedNormally(f);
215     }};
216     testInvokeOnPool(mainPool(), a);
217     }
218    
219     /**
220     * quietlyInvoke task returns when task completes normally.
221     * isCompletedAbnormally and isCancelled return false for normally
222     * completed tasks
223     */
224     public void testQuietlyInvoke() {
225     RecursiveAction a = new CheckedRecursiveAction() {
226     protected void realCompute() {
227     FibAction f = new FibAction(8);
228     f.quietlyInvoke();
229     assertEquals(21, f.result);
230     checkCompletedNormally(f);
231     }};
232     testInvokeOnPool(mainPool(), a);
233     }
234    
235     /**
236     * join of a forked task returns when task completes
237     */
238     public void testForkJoin() {
239     RecursiveAction a = new CheckedRecursiveAction() {
240     protected void realCompute() {
241     FibAction f = new FibAction(8);
242     assertSame(f, f.fork());
243     assertNull(f.join());
244     assertEquals(21, f.result);
245     checkCompletedNormally(f);
246     }};
247     testInvokeOnPool(mainPool(), a);
248     }
249    
250     /**
251     * join/quietlyJoin of a forked task succeeds in the presence of interrupts
252     */
253     public void testJoinIgnoresInterrupts() {
254     RecursiveAction a = new CheckedRecursiveAction() {
255     protected void realCompute() {
256     FibAction f = new FibAction(8);
257     final Thread myself = Thread.currentThread();
258    
259     // test join()
260     assertSame(f, f.fork());
261     myself.interrupt();
262     assertTrue(myself.isInterrupted());
263     assertNull(f.join());
264     Thread.interrupted();
265     assertEquals(21, f.result);
266     checkCompletedNormally(f);
267    
268     f = new FibAction(8);
269     f.cancel(true);
270     assertSame(f, f.fork());
271     myself.interrupt();
272     assertTrue(myself.isInterrupted());
273     try {
274     f.join();
275     shouldThrow();
276     } catch (CancellationException success) {
277     Thread.interrupted();
278     checkCancelled(f);
279     }
280    
281     f = new FibAction(8);
282     f.completeExceptionally(new FJException());
283     assertSame(f, f.fork());
284     myself.interrupt();
285     assertTrue(myself.isInterrupted());
286     try {
287     f.join();
288     shouldThrow();
289     } catch (FJException success) {
290     Thread.interrupted();
291     checkCompletedAbnormally(f, success);
292     }
293    
294     // test quietlyJoin()
295     f = new FibAction(8);
296     assertSame(f, f.fork());
297     myself.interrupt();
298     assertTrue(myself.isInterrupted());
299     f.quietlyJoin();
300     Thread.interrupted();
301     assertEquals(21, f.result);
302     checkCompletedNormally(f);
303    
304     f = new FibAction(8);
305     f.cancel(true);
306     assertSame(f, f.fork());
307     myself.interrupt();
308     assertTrue(myself.isInterrupted());
309     f.quietlyJoin();
310     Thread.interrupted();
311     checkCancelled(f);
312    
313     f = new FibAction(8);
314     f.completeExceptionally(new FJException());
315     assertSame(f, f.fork());
316     myself.interrupt();
317     assertTrue(myself.isInterrupted());
318     f.quietlyJoin();
319     Thread.interrupted();
320     checkCompletedAbnormally(f, f.getException());
321     }};
322     testInvokeOnPool(mainPool(), a);
323     a.reinitialize();
324     testInvokeOnPool(singletonPool(), a);
325     }
326    
327     /**
328     * join/quietlyJoin of a forked task when not in ForkJoinPool
329     * succeeds in the presence of interrupts
330     */
331     public void testJoinIgnoresInterruptsOutsideForkJoinPool() {
332     final SynchronousQueue<FibAction[]> sq =
333     new SynchronousQueue<FibAction[]>();
334     RecursiveAction a = new CheckedRecursiveAction() {
335     protected void realCompute() throws InterruptedException {
336     FibAction[] fibActions = new FibAction[6];
337     for (int i = 0; i < fibActions.length; i++)
338     fibActions[i] = new FibAction(8);
339    
340     fibActions[1].cancel(false);
341     fibActions[2].completeExceptionally(new FJException());
342     fibActions[4].cancel(true);
343     fibActions[5].completeExceptionally(new FJException());
344    
345     for (int i = 0; i < fibActions.length; i++)
346     fibActions[i].fork();
347    
348     sq.put(fibActions);
349    
350     helpQuiesce();
351     }};
352    
353     Runnable r = new CheckedRunnable() {
354     public void realRun() throws InterruptedException {
355     FibAction[] fibActions = sq.take();
356     FibAction f;
357     final Thread myself = Thread.currentThread();
358    
359     // test join() ------------
360    
361     f = fibActions[0];
362     assertFalse(ForkJoinTask.inForkJoinPool());
363     myself.interrupt();
364     assertTrue(myself.isInterrupted());
365     assertNull(f.join());
366     assertTrue(Thread.interrupted());
367     assertEquals(21, f.result);
368     checkCompletedNormally(f);
369    
370     f = fibActions[1];
371     myself.interrupt();
372     assertTrue(myself.isInterrupted());
373     try {
374     f.join();
375     shouldThrow();
376     } catch (CancellationException success) {
377     assertTrue(Thread.interrupted());
378     checkCancelled(f);
379     }
380    
381     f = fibActions[2];
382     myself.interrupt();
383     assertTrue(myself.isInterrupted());
384     try {
385     f.join();
386     shouldThrow();
387     } catch (FJException success) {
388     assertTrue(Thread.interrupted());
389     checkCompletedAbnormally(f, success);
390     }
391    
392     // test quietlyJoin() ---------
393    
394     f = fibActions[3];
395     myself.interrupt();
396     assertTrue(myself.isInterrupted());
397     f.quietlyJoin();
398     assertTrue(Thread.interrupted());
399     assertEquals(21, f.result);
400     checkCompletedNormally(f);
401    
402     f = fibActions[4];
403     myself.interrupt();
404     assertTrue(myself.isInterrupted());
405     f.quietlyJoin();
406     assertTrue(Thread.interrupted());
407     checkCancelled(f);
408    
409     f = fibActions[5];
410     myself.interrupt();
411     assertTrue(myself.isInterrupted());
412     f.quietlyJoin();
413     assertTrue(Thread.interrupted());
414     assertTrue(f.getException() instanceof FJException);
415     checkCompletedAbnormally(f, f.getException());
416     }};
417    
418     Thread t;
419    
420     t = newStartedThread(r);
421     testInvokeOnPool(mainPool(), a);
422     awaitTermination(t, LONG_DELAY_MS);
423    
424     a.reinitialize();
425     t = newStartedThread(r);
426     testInvokeOnPool(singletonPool(), a);
427     awaitTermination(t, LONG_DELAY_MS);
428     }
429    
430     /**
431     * get of a forked task returns when task completes
432     */
433     public void testForkGet() {
434     RecursiveAction a = new CheckedRecursiveAction() {
435     protected void realCompute() throws Exception {
436     FibAction f = new FibAction(8);
437     assertSame(f, f.fork());
438     assertNull(f.get());
439     assertEquals(21, f.result);
440     checkCompletedNormally(f);
441     }};
442     testInvokeOnPool(mainPool(), a);
443     }
444    
445     /**
446     * timed get of a forked task returns when task completes
447     */
448     public void testForkTimedGet() {
449     RecursiveAction a = new CheckedRecursiveAction() {
450     protected void realCompute() throws Exception {
451     FibAction f = new FibAction(8);
452     assertSame(f, f.fork());
453     assertNull(f.get(5L, SECONDS));
454     assertEquals(21, f.result);
455     checkCompletedNormally(f);
456     }};
457     testInvokeOnPool(mainPool(), a);
458     }
459    
460     /**
461     * timed get with null time unit throws NPE
462     */
463     public void testForkTimedGetNPE() {
464     RecursiveAction a = new CheckedRecursiveAction() {
465     protected void realCompute() throws Exception {
466     FibAction f = new FibAction(8);
467     assertSame(f, f.fork());
468     try {
469     f.get(5L, null);
470     shouldThrow();
471     } catch (NullPointerException success) {}
472     }};
473     testInvokeOnPool(mainPool(), a);
474     }
475    
476     /**
477     * quietlyJoin of a forked task returns when task completes
478     */
479     public void testForkQuietlyJoin() {
480     RecursiveAction a = new CheckedRecursiveAction() {
481     protected void realCompute() {
482     FibAction f = new FibAction(8);
483     assertSame(f, f.fork());
484     f.quietlyJoin();
485     assertEquals(21, f.result);
486     checkCompletedNormally(f);
487     }};
488     testInvokeOnPool(mainPool(), a);
489     }
490    
491     /**
492     * helpQuiesce returns when tasks are complete.
493     * getQueuedTaskCount returns 0 when quiescent
494     */
495     public void testForkHelpQuiesce() {
496     RecursiveAction a = new CheckedRecursiveAction() {
497     protected void realCompute() {
498     FibAction f = new FibAction(8);
499     assertSame(f, f.fork());
500     helpQuiesce();
501     assertEquals(21, f.result);
502     assertEquals(0, getQueuedTaskCount());
503     checkCompletedNormally(f);
504     }};
505     testInvokeOnPool(mainPool(), a);
506     }
507    
508     /**
509     * invoke task throws exception when task completes abnormally
510     */
511     public void testAbnormalInvoke() {
512     RecursiveAction a = new CheckedRecursiveAction() {
513     protected void realCompute() {
514     FailingFibAction f = new FailingFibAction(8);
515     try {
516     f.invoke();
517     shouldThrow();
518     } catch (FJException success) {
519     checkCompletedAbnormally(f, success);
520     }
521     }};
522     testInvokeOnPool(mainPool(), a);
523     }
524    
525     /**
526     * quietlyInvoke task returns when task completes abnormally
527     */
528     public void testAbnormalQuietlyInvoke() {
529     RecursiveAction a = new CheckedRecursiveAction() {
530     protected void realCompute() {
531     FailingFibAction f = new FailingFibAction(8);
532     f.quietlyInvoke();
533     assertTrue(f.getException() instanceof FJException);
534     checkCompletedAbnormally(f, f.getException());
535     }};
536     testInvokeOnPool(mainPool(), a);
537     }
538    
539     /**
540     * join of a forked task throws exception when task completes abnormally
541     */
542     public void testAbnormalForkJoin() {
543     RecursiveAction a = new CheckedRecursiveAction() {
544     protected void realCompute() {
545     FailingFibAction f = new FailingFibAction(8);
546     assertSame(f, f.fork());
547     try {
548     f.join();
549     shouldThrow();
550     } catch (FJException success) {
551     checkCompletedAbnormally(f, success);
552     }
553     }};
554     testInvokeOnPool(mainPool(), a);
555     }
556    
557     /**
558     * get of a forked task throws exception when task completes abnormally
559     */
560     public void testAbnormalForkGet() {
561     RecursiveAction a = new CheckedRecursiveAction() {
562     protected void realCompute() throws Exception {
563     FailingFibAction f = new FailingFibAction(8);
564     assertSame(f, f.fork());
565     try {
566     f.get();
567     shouldThrow();
568     } catch (ExecutionException success) {
569     Throwable cause = success.getCause();
570     assertTrue(cause instanceof FJException);
571     checkCompletedAbnormally(f, cause);
572     }
573     }};
574     testInvokeOnPool(mainPool(), a);
575     }
576    
577     /**
578     * timed get of a forked task throws exception when task completes abnormally
579     */
580     public void testAbnormalForkTimedGet() {
581     RecursiveAction a = new CheckedRecursiveAction() {
582     protected void realCompute() throws Exception {
583     FailingFibAction f = new FailingFibAction(8);
584     assertSame(f, f.fork());
585     try {
586     f.get(5L, TimeUnit.SECONDS);
587     shouldThrow();
588     } catch (ExecutionException success) {
589     Throwable cause = success.getCause();
590     assertTrue(cause instanceof FJException);
591     checkCompletedAbnormally(f, cause);
592     }
593     }};
594     testInvokeOnPool(mainPool(), a);
595     }
596    
597     /**
598     * quietlyJoin of a forked task returns when task completes abnormally
599     */
600     public void testAbnormalForkQuietlyJoin() {
601     RecursiveAction a = new CheckedRecursiveAction() {
602     protected void realCompute() {
603     FailingFibAction f = new FailingFibAction(8);
604     assertSame(f, f.fork());
605     f.quietlyJoin();
606     assertTrue(f.getException() instanceof FJException);
607     checkCompletedAbnormally(f, f.getException());
608     }};
609     testInvokeOnPool(mainPool(), a);
610     }
611    
612     /**
613     * invoke task throws exception when task cancelled
614     */
615     public void testCancelledInvoke() {
616     RecursiveAction a = new CheckedRecursiveAction() {
617     protected void realCompute() {
618     FibAction f = new FibAction(8);
619     assertTrue(f.cancel(true));
620     try {
621     f.invoke();
622     shouldThrow();
623     } catch (CancellationException success) {
624     checkCancelled(f);
625     }
626     }};
627     testInvokeOnPool(mainPool(), a);
628     }
629    
630     /**
631     * join of a forked task throws exception when task cancelled
632     */
633     public void testCancelledForkJoin() {
634     RecursiveAction a = new CheckedRecursiveAction() {
635     protected void realCompute() {
636     FibAction f = new FibAction(8);
637     assertTrue(f.cancel(true));
638     assertSame(f, f.fork());
639     try {
640     f.join();
641     shouldThrow();
642     } catch (CancellationException success) {
643     checkCancelled(f);
644     }
645     }};
646     testInvokeOnPool(mainPool(), a);
647     }
648    
649     /**
650     * get of a forked task throws exception when task cancelled
651     */
652     public void testCancelledForkGet() {
653     RecursiveAction a = new CheckedRecursiveAction() {
654     protected void realCompute() throws Exception {
655     FibAction f = new FibAction(8);
656     assertTrue(f.cancel(true));
657     assertSame(f, f.fork());
658     try {
659     f.get();
660     shouldThrow();
661     } catch (CancellationException success) {
662     checkCancelled(f);
663     }
664     }};
665     testInvokeOnPool(mainPool(), a);
666     }
667    
668     /**
669     * timed get of a forked task throws exception when task cancelled
670     */
671     public void testCancelledForkTimedGet() {
672     RecursiveAction a = new CheckedRecursiveAction() {
673     protected void realCompute() throws Exception {
674     FibAction f = new FibAction(8);
675     assertTrue(f.cancel(true));
676     assertSame(f, f.fork());
677     try {
678     f.get(5L, SECONDS);
679     shouldThrow();
680     } catch (CancellationException success) {
681     checkCancelled(f);
682     }
683     }};
684     testInvokeOnPool(mainPool(), a);
685     }
686    
687     /**
688     * quietlyJoin of a forked task returns when task cancelled
689     */
690     public void testCancelledForkQuietlyJoin() {
691     RecursiveAction a = new CheckedRecursiveAction() {
692     protected void realCompute() {
693     FibAction f = new FibAction(8);
694     assertTrue(f.cancel(true));
695     assertSame(f, f.fork());
696     f.quietlyJoin();
697     checkCancelled(f);
698     }};
699     testInvokeOnPool(mainPool(), a);
700     }
701    
702     /**
703     * getPool of executing task returns its pool
704     */
705     public void testGetPool() {
706     final ForkJoinPool mainPool = mainPool();
707     RecursiveAction a = new CheckedRecursiveAction() {
708     protected void realCompute() {
709     assertSame(mainPool, getPool());
710     }};
711     testInvokeOnPool(mainPool, a);
712     }
713    
714     /**
715     * getPool of non-FJ task returns null
716     */
717     public void testGetPool2() {
718     RecursiveAction a = new CheckedRecursiveAction() {
719     protected void realCompute() {
720     assertNull(getPool());
721     }};
722     assertNull(a.invoke());
723     }
724    
725     /**
726     * inForkJoinPool of executing task returns true
727     */
728     public void testInForkJoinPool() {
729     RecursiveAction a = new CheckedRecursiveAction() {
730     protected void realCompute() {
731     assertTrue(inForkJoinPool());
732     }};
733     testInvokeOnPool(mainPool(), a);
734     }
735    
736     /**
737     * inForkJoinPool of non-FJ task returns false
738     */
739     public void testInForkJoinPool2() {
740     RecursiveAction a = new CheckedRecursiveAction() {
741     protected void realCompute() {
742     assertFalse(inForkJoinPool());
743     }};
744     assertNull(a.invoke());
745     }
746    
747     /**
748     * getPool of current thread in pool returns its pool
749     */
750     public void testWorkerGetPool() {
751     final ForkJoinPool mainPool = mainPool();
752     RecursiveAction a = new CheckedRecursiveAction() {
753     protected void realCompute() {
754     ForkJoinWorkerThread w =
755     (ForkJoinWorkerThread) Thread.currentThread();
756     assertSame(mainPool, w.getPool());
757     }};
758     testInvokeOnPool(mainPool, a);
759     }
760    
761     /**
762     * getPoolIndex of current thread in pool returns 0 <= value < poolSize
763     */
764     public void testWorkerGetPoolIndex() {
765     final ForkJoinPool mainPool = mainPool();
766     RecursiveAction a = new CheckedRecursiveAction() {
767     protected void realCompute() {
768     ForkJoinWorkerThread w =
769     (ForkJoinWorkerThread) Thread.currentThread();
770     assertTrue(w.getPoolIndex() >= 0);
771     // pool size can shrink after assigning index, so cannot check
772     // assertTrue(w.getPoolIndex() < mainPool.getPoolSize());
773     }};
774     testInvokeOnPool(mainPool, a);
775     }
776    
777     /**
778     * setRawResult(null) succeeds
779     */
780     public void testSetRawResult() {
781     RecursiveAction a = new CheckedRecursiveAction() {
782     protected void realCompute() {
783     setRawResult(null);
784     assertNull(getRawResult());
785     }};
786     assertNull(a.invoke());
787     }
788    
789     /**
790     * A reinitialized normally completed task may be re-invoked
791     */
792     public void testReinitialize() {
793     RecursiveAction a = new CheckedRecursiveAction() {
794     protected void realCompute() {
795     FibAction f = new FibAction(8);
796     checkNotDone(f);
797    
798     for (int i = 0; i < 3; i++) {
799     assertNull(f.invoke());
800     assertEquals(21, f.result);
801     checkCompletedNormally(f);
802     f.reinitialize();
803     checkNotDone(f);
804     }
805     }};
806     testInvokeOnPool(mainPool(), a);
807     }
808    
809     /**
810     * A reinitialized abnormally completed task may be re-invoked
811     */
812     public void testReinitializeAbnormal() {
813     RecursiveAction a = new CheckedRecursiveAction() {
814     protected void realCompute() {
815     FailingFibAction f = new FailingFibAction(8);
816     checkNotDone(f);
817    
818     for (int i = 0; i < 3; i++) {
819     try {
820     f.invoke();
821     shouldThrow();
822     } catch (FJException success) {
823     checkCompletedAbnormally(f, success);
824     }
825     f.reinitialize();
826     checkNotDone(f);
827     }
828     }};
829     testInvokeOnPool(mainPool(), a);
830     }
831    
832     /**
833     * invoke task throws exception after invoking completeExceptionally
834     */
835     public void testCompleteExceptionally() {
836     RecursiveAction a = new CheckedRecursiveAction() {
837     protected void realCompute() {
838     FibAction f = new FibAction(8);
839     f.completeExceptionally(new FJException());
840     try {
841     f.invoke();
842     shouldThrow();
843     } catch (FJException success) {
844     checkCompletedAbnormally(f, success);
845     }
846     }};
847     testInvokeOnPool(mainPool(), a);
848     }
849    
850     /**
851     * invoke task suppresses execution invoking complete
852     */
853     public void testComplete() {
854     RecursiveAction a = new CheckedRecursiveAction() {
855     protected void realCompute() {
856     FibAction f = new FibAction(8);
857     f.complete(null);
858     assertNull(f.invoke());
859     assertEquals(0, f.result);
860     checkCompletedNormally(f);
861     }};
862     testInvokeOnPool(mainPool(), a);
863     }
864    
865     /**
866     * invokeAll(t1, t2) invokes all task arguments
867     */
868     public void testInvokeAll2() {
869     RecursiveAction a = new CheckedRecursiveAction() {
870     protected void realCompute() {
871     FibAction f = new FibAction(8);
872     FibAction g = new FibAction(9);
873     invokeAll(f, g);
874     checkCompletedNormally(f);
875     assertEquals(21, f.result);
876     checkCompletedNormally(g);
877     assertEquals(34, g.result);
878     }};
879     testInvokeOnPool(mainPool(), a);
880     }
881    
882     /**
883     * invokeAll(tasks) with 1 argument invokes task
884     */
885     public void testInvokeAll1() {
886     RecursiveAction a = new CheckedRecursiveAction() {
887     protected void realCompute() {
888     FibAction f = new FibAction(8);
889     invokeAll(f);
890     checkCompletedNormally(f);
891     assertEquals(21, f.result);
892     }};
893     testInvokeOnPool(mainPool(), a);
894     }
895    
896     /**
897     * invokeAll(tasks) with > 2 argument invokes tasks
898     */
899     public void testInvokeAll3() {
900     RecursiveAction a = new CheckedRecursiveAction() {
901     protected void realCompute() {
902     FibAction f = new FibAction(8);
903     FibAction g = new FibAction(9);
904     FibAction h = new FibAction(7);
905     invokeAll(f, g, h);
906     assertTrue(f.isDone());
907     assertTrue(g.isDone());
908     assertTrue(h.isDone());
909     checkCompletedNormally(f);
910     assertEquals(21, f.result);
911     checkCompletedNormally(g);
912     assertEquals(34, g.result);
913     checkCompletedNormally(g);
914     assertEquals(13, h.result);
915     }};
916     testInvokeOnPool(mainPool(), a);
917     }
918    
919     /**
920     * invokeAll(collection) invokes all tasks in the collection
921     */
922     public void testInvokeAllCollection() {
923     RecursiveAction a = new CheckedRecursiveAction() {
924     protected void realCompute() {
925     FibAction f = new FibAction(8);
926     FibAction g = new FibAction(9);
927     FibAction h = new FibAction(7);
928     HashSet set = new HashSet();
929     set.add(f);
930     set.add(g);
931     set.add(h);
932     invokeAll(set);
933     assertTrue(f.isDone());
934     assertTrue(g.isDone());
935     assertTrue(h.isDone());
936     checkCompletedNormally(f);
937     assertEquals(21, f.result);
938     checkCompletedNormally(g);
939     assertEquals(34, g.result);
940     checkCompletedNormally(g);
941     assertEquals(13, h.result);
942     }};
943     testInvokeOnPool(mainPool(), a);
944     }
945    
946     /**
947     * invokeAll(tasks) with any null task throws NPE
948     */
949     public void testInvokeAllNPE() {
950     RecursiveAction a = new CheckedRecursiveAction() {
951     protected void realCompute() {
952     FibAction f = new FibAction(8);
953     FibAction g = new FibAction(9);
954     FibAction h = null;
955     try {
956     invokeAll(f, g, h);
957     shouldThrow();
958     } catch (NullPointerException success) {}
959     }};
960     testInvokeOnPool(mainPool(), a);
961     }
962    
963     /**
964     * invokeAll(t1, t2) throw exception if any task does
965     */
966     public void testAbnormalInvokeAll2() {
967     RecursiveAction a = new CheckedRecursiveAction() {
968     protected void realCompute() {
969     FibAction f = new FibAction(8);
970     FailingFibAction g = new FailingFibAction(9);
971     try {
972     invokeAll(f, g);
973     shouldThrow();
974     } catch (FJException success) {
975     checkCompletedAbnormally(g, success);
976     }
977     }};
978     testInvokeOnPool(mainPool(), a);
979     }
980    
981     /**
982     * invokeAll(tasks) with 1 argument throws exception if task does
983     */
984     public void testAbnormalInvokeAll1() {
985     RecursiveAction a = new CheckedRecursiveAction() {
986     protected void realCompute() {
987     FailingFibAction g = new FailingFibAction(9);
988     try {
989     invokeAll(g);
990     shouldThrow();
991     } catch (FJException success) {
992     checkCompletedAbnormally(g, success);
993     }
994     }};
995     testInvokeOnPool(mainPool(), a);
996     }
997    
998     /**
999     * invokeAll(tasks) with > 2 argument throws exception if any task does
1000     */
1001     public void testAbnormalInvokeAll3() {
1002     RecursiveAction a = new CheckedRecursiveAction() {
1003     protected void realCompute() {
1004     FibAction f = new FibAction(8);
1005     FailingFibAction g = new FailingFibAction(9);
1006     FibAction h = new FibAction(7);
1007     try {
1008     invokeAll(f, g, h);
1009     shouldThrow();
1010     } catch (FJException success) {
1011     checkCompletedAbnormally(g, success);
1012     }
1013     }};
1014     testInvokeOnPool(mainPool(), a);
1015     }
1016    
1017     /**
1018     * invokeAll(collection) throws exception if any task does
1019     */
1020     public void testAbnormalInvokeAllCollection() {
1021     RecursiveAction a = new CheckedRecursiveAction() {
1022     protected void realCompute() {
1023     FailingFibAction f = new FailingFibAction(8);
1024     FibAction g = new FibAction(9);
1025     FibAction h = new FibAction(7);
1026     HashSet set = new HashSet();
1027     set.add(f);
1028     set.add(g);
1029     set.add(h);
1030     try {
1031     invokeAll(set);
1032     shouldThrow();
1033     } catch (FJException success) {
1034     checkCompletedAbnormally(f, success);
1035     }
1036     }};
1037     testInvokeOnPool(mainPool(), a);
1038     }
1039    
1040     /**
1041     * tryUnfork returns true for most recent unexecuted task,
1042     * and suppresses execution
1043     */
1044     public void testTryUnfork() {
1045     RecursiveAction a = new CheckedRecursiveAction() {
1046     protected void realCompute() {
1047     FibAction g = new FibAction(9);
1048     assertSame(g, g.fork());
1049     FibAction f = new FibAction(8);
1050     assertSame(f, f.fork());
1051     assertTrue(f.tryUnfork());
1052     helpQuiesce();
1053     checkNotDone(f);
1054     checkCompletedNormally(g);
1055     }};
1056     testInvokeOnPool(singletonPool(), a);
1057     }
1058    
1059     /**
1060     * getSurplusQueuedTaskCount returns > 0 when
1061     * there are more tasks than threads
1062     */
1063     public void testGetSurplusQueuedTaskCount() {
1064     RecursiveAction a = new CheckedRecursiveAction() {
1065     protected void realCompute() {
1066     FibAction h = new FibAction(7);
1067     assertSame(h, h.fork());
1068     FibAction g = new FibAction(9);
1069     assertSame(g, g.fork());
1070     FibAction f = new FibAction(8);
1071     assertSame(f, f.fork());
1072     assertTrue(getSurplusQueuedTaskCount() > 0);
1073     helpQuiesce();
1074     assertEquals(0, getSurplusQueuedTaskCount());
1075     checkCompletedNormally(f);
1076     checkCompletedNormally(g);
1077     checkCompletedNormally(h);
1078     }};
1079     testInvokeOnPool(singletonPool(), a);
1080     }
1081    
1082     /**
1083     * peekNextLocalTask returns most recent unexecuted task.
1084     */
1085     public void testPeekNextLocalTask() {
1086     RecursiveAction a = new CheckedRecursiveAction() {
1087     protected void realCompute() {
1088     FibAction g = new FibAction(9);
1089     assertSame(g, g.fork());
1090     FibAction f = new FibAction(8);
1091     assertSame(f, f.fork());
1092     assertSame(f, peekNextLocalTask());
1093     assertNull(f.join());
1094     checkCompletedNormally(f);
1095     helpQuiesce();
1096     checkCompletedNormally(f);
1097     checkCompletedNormally(g);
1098     }};
1099     testInvokeOnPool(singletonPool(), a);
1100     }
1101    
1102     /**
1103     * pollNextLocalTask returns most recent unexecuted task
1104     * without executing it
1105     */
1106     public void testPollNextLocalTask() {
1107     RecursiveAction a = new CheckedRecursiveAction() {
1108     protected void realCompute() {
1109     FibAction g = new FibAction(9);
1110     assertSame(g, g.fork());
1111     FibAction f = new FibAction(8);
1112     assertSame(f, f.fork());
1113     assertSame(f, pollNextLocalTask());
1114     helpQuiesce();
1115     checkNotDone(f);
1116     checkCompletedNormally(g);
1117     }};
1118     testInvokeOnPool(singletonPool(), a);
1119     }
1120    
1121     /**
1122     * pollTask returns an unexecuted task without executing it
1123     */
1124     public void testPollTask() {
1125     RecursiveAction a = new CheckedRecursiveAction() {
1126     protected void realCompute() {
1127     FibAction g = new FibAction(9);
1128     assertSame(g, g.fork());
1129     FibAction f = new FibAction(8);
1130     assertSame(f, f.fork());
1131     assertSame(f, pollTask());
1132     helpQuiesce();
1133     checkNotDone(f);
1134     checkCompletedNormally(g);
1135     }};
1136     testInvokeOnPool(singletonPool(), a);
1137     }
1138    
1139     /**
1140     * peekNextLocalTask returns least recent unexecuted task in async mode
1141     */
1142     public void testPeekNextLocalTaskAsync() {
1143     RecursiveAction a = new CheckedRecursiveAction() {
1144     protected void realCompute() {
1145     FibAction g = new FibAction(9);
1146     assertSame(g, g.fork());
1147     FibAction f = new FibAction(8);
1148     assertSame(f, f.fork());
1149     assertSame(g, peekNextLocalTask());
1150     assertNull(f.join());
1151     helpQuiesce();
1152     checkCompletedNormally(f);
1153     checkCompletedNormally(g);
1154     }};
1155     testInvokeOnPool(asyncSingletonPool(), a);
1156     }
1157    
1158     /**
1159     * pollNextLocalTask returns least recent unexecuted task without
1160     * executing it, in async mode
1161     */
1162     public void testPollNextLocalTaskAsync() {
1163     RecursiveAction a = new CheckedRecursiveAction() {
1164     protected void realCompute() {
1165     FibAction g = new FibAction(9);
1166     assertSame(g, g.fork());
1167     FibAction f = new FibAction(8);
1168     assertSame(f, f.fork());
1169     assertSame(g, pollNextLocalTask());
1170     helpQuiesce();
1171     checkCompletedNormally(f);
1172     checkNotDone(g);
1173     }};
1174     testInvokeOnPool(asyncSingletonPool(), a);
1175     }
1176    
1177     /**
1178     * pollTask returns an unexecuted task without executing it, in
1179     * async mode
1180     */
1181     public void testPollTaskAsync() {
1182     RecursiveAction a = new CheckedRecursiveAction() {
1183     protected void realCompute() {
1184     FibAction g = new FibAction(9);
1185     assertSame(g, g.fork());
1186     FibAction f = new FibAction(8);
1187     assertSame(f, f.fork());
1188     assertSame(g, pollTask());
1189     helpQuiesce();
1190     checkCompletedNormally(f);
1191     checkNotDone(g);
1192     }};
1193     testInvokeOnPool(asyncSingletonPool(), a);
1194     }
1195    
1196     /** Demo from RecursiveAction javadoc */
1197     static class SortTask extends RecursiveAction {
1198     final long[] array; final int lo, hi;
1199     SortTask(long[] array, int lo, int hi) {
1200     this.array = array; this.lo = lo; this.hi = hi;
1201     }
1202     SortTask(long[] array) { this(array, 0, array.length); }
1203     protected void compute() {
1204     if (hi - lo < THRESHOLD)
1205     sortSequentially(lo, hi);
1206     else {
1207     int mid = (lo + hi) >>> 1;
1208     invokeAll(new SortTask(array, lo, mid),
1209     new SortTask(array, mid, hi));
1210     merge(lo, mid, hi);
1211     }
1212     }
1213     // implementation details follow:
1214     static final int THRESHOLD = 100;
1215     void sortSequentially(int lo, int hi) {
1216     Arrays.sort(array, lo, hi);
1217     }
1218     void merge(int lo, int mid, int hi) {
1219     long[] buf = Arrays.copyOfRange(array, lo, mid);
1220     for (int i = 0, j = lo, k = mid; i < buf.length; j++)
1221     array[j] = (k == hi || buf[i] < array[k]) ?
1222     buf[i++] : array[k++];
1223     }
1224     }
1225    
1226     /**
1227     * SortTask demo works as advertised
1228     */
1229     public void testSortTaskDemo() {
1230     ThreadLocalRandom rnd = ThreadLocalRandom.current();
1231     long[] array = new long[1007];
1232     for (int i = 0; i < array.length; i++)
1233     array[i] = rnd.nextLong();
1234     long[] arrayClone = array.clone();
1235     testInvokeOnPool(mainPool(), new SortTask(array));
1236     Arrays.sort(arrayClone);
1237     assertTrue(Arrays.equals(array, arrayClone));
1238     }
1239     }