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