ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/RecursiveActionTest.java
Revision: 1.51
Committed: Sat Oct 21 06:49:04 2017 UTC (6 years, 6 months ago) by jsr166
Branch: MAIN
Changes since 1.50: +1 -1 lines
Log Message:
better exception handling

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