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