ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/RecursiveActionTest.java
Revision: 1.44
Committed: Sat Apr 25 04:55:31 2015 UTC (9 years ago) by jsr166
Branch: MAIN
Changes since 1.43: +1 -1 lines
Log Message:
improve main methods; respect system properties; actually fail if a test fails

File Contents

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