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.HashSet;
  37 import java.util.concurrent.CancellationException;
  38 import java.util.concurrent.ExecutionException;
  39 import java.util.concurrent.ForkJoinPool;
  40 import java.util.concurrent.ForkJoinTask;
  41 import java.util.concurrent.RecursiveTask;
  42 import java.util.concurrent.TimeoutException;
  43 
  44 import junit.framework.Test;
  45 import junit.framework.TestSuite;
  46 
  47 public class RecursiveTaskTest extends JSR166TestCase {
  48 
  49     public static void main(String[] args) {
  50         main(suite(), args);
  51     }
  52     public static Test suite() {
  53         return new TestSuite(RecursiveTaskTest.class);
  54     }
  55 
  56     private static ForkJoinPool mainPool() {
  57         return new ForkJoinPool();
  58     }
  59 
  60     private static ForkJoinPool singletonPool() {
  61         return new ForkJoinPool(1);
  62     }
  63 
  64     private static ForkJoinPool asyncSingletonPool() {
  65         return new ForkJoinPool(1,
  66                                 ForkJoinPool.defaultForkJoinWorkerThreadFactory,
  67                                 null, true);
  68     }
  69 
  70     private <T> T testInvokeOnPool(ForkJoinPool pool, RecursiveTask<T> a) {
  71         try (PoolCleaner cleaner = cleaner(pool)) {
  72             checkNotDone(a);
  73 
  74             T result = pool.invoke(a);
  75 
  76             checkCompletedNormally(a, result);
  77             return result;
  78         }
  79     }
  80 
  81     void checkNotDone(RecursiveTask a) {
  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         if (! ForkJoinTask.inForkJoinPool()) {
  90             Thread.currentThread().interrupt();
  91             try {
  92                 a.get();
  93                 shouldThrow();
  94             } catch (InterruptedException success) {
  95             } catch (Throwable fail) { threadUnexpectedException(fail); }
  96 
  97             Thread.currentThread().interrupt();
  98             try {
  99                 a.get(randomTimeout(), randomTimeUnit());
 100                 shouldThrow();
 101             } catch (InterruptedException success) {
 102             } catch (Throwable fail) { threadUnexpectedException(fail); }
 103         }
 104 
 105         try {
 106             a.get(randomExpiredTimeout(), randomTimeUnit());
 107             shouldThrow();
 108         } catch (TimeoutException success) {
 109         } catch (Throwable fail) { threadUnexpectedException(fail); }
 110     }
 111 
 112     <T> void checkCompletedNormally(RecursiveTask<T> a, T expectedValue) {
 113         assertTrue(a.isDone());
 114         assertFalse(a.isCancelled());
 115         assertTrue(a.isCompletedNormally());
 116         assertFalse(a.isCompletedAbnormally());
 117         assertNull(a.getException());
 118         assertSame(expectedValue, a.getRawResult());
 119         assertSame(expectedValue, a.join());
 120         assertFalse(a.cancel(false));
 121         assertFalse(a.cancel(true));
 122 
 123         T v1 = null, v2 = null;
 124         try {
 125             v1 = a.get();
 126             v2 = a.get(randomTimeout(), randomTimeUnit());
 127         } catch (Throwable fail) { threadUnexpectedException(fail); }
 128         assertSame(expectedValue, v1);
 129         assertSame(expectedValue, v2);
 130     }
 131 
 132     /**
 133      * Waits for the task to complete, and checks that when it does,
 134      * it will have an Integer result equals to the given int.
 135      */
 136     void checkCompletesNormally(RecursiveTask<Integer> a, int expectedValue) {
 137         Integer r = a.join();
 138         assertEquals(expectedValue, (int) r);
 139         checkCompletedNormally(a, r);
 140     }
 141 
 142     /**
 143      * Like checkCompletesNormally, but verifies that the task has
 144      * already completed.
 145      */
 146     void checkCompletedNormally(RecursiveTask<Integer> a, int expectedValue) {
 147         Integer r = a.getRawResult();
 148         assertEquals(expectedValue, (int) r);
 149         checkCompletedNormally(a, r);
 150     }
 151 
 152     void checkCancelled(RecursiveTask a) {
 153         assertTrue(a.isDone());
 154         assertTrue(a.isCancelled());
 155         assertFalse(a.isCompletedNormally());
 156         assertTrue(a.isCompletedAbnormally());
 157         assertTrue(a.getException() instanceof CancellationException);
 158         assertNull(a.getRawResult());
 159 
 160         try {
 161             a.join();
 162             shouldThrow();
 163         } catch (CancellationException success) {
 164         } catch (Throwable fail) { threadUnexpectedException(fail); }
 165 
 166         try {
 167             a.get();
 168             shouldThrow();
 169         } catch (CancellationException success) {
 170         } catch (Throwable fail) { threadUnexpectedException(fail); }
 171 
 172         try {
 173             a.get(randomTimeout(), randomTimeUnit());
 174             shouldThrow();
 175         } catch (CancellationException success) {
 176         } catch (Throwable fail) { threadUnexpectedException(fail); }
 177     }
 178 
 179     void checkCompletedAbnormally(RecursiveTask a, Throwable t) {
 180         assertTrue(a.isDone());
 181         assertFalse(a.isCancelled());
 182         assertFalse(a.isCompletedNormally());
 183         assertTrue(a.isCompletedAbnormally());
 184         assertSame(t.getClass(), a.getException().getClass());
 185         assertNull(a.getRawResult());
 186         assertFalse(a.cancel(false));
 187         assertFalse(a.cancel(true));
 188 
 189         try {
 190             a.join();
 191             shouldThrow();
 192         } catch (Throwable expected) {
 193             assertSame(t.getClass(), expected.getClass());
 194         }
 195 
 196         try {
 197             a.get();
 198             shouldThrow();
 199         } catch (ExecutionException success) {
 200             assertSame(t.getClass(), success.getCause().getClass());
 201         } catch (Throwable fail) { threadUnexpectedException(fail); }
 202 
 203         try {
 204             a.get(randomTimeout(), randomTimeUnit());
 205             shouldThrow();
 206         } catch (ExecutionException success) {
 207             assertSame(t.getClass(), success.getCause().getClass());
 208         } catch (Throwable fail) { threadUnexpectedException(fail); }
 209     }
 210 
 211     public static final class FJException extends RuntimeException {
 212         public FJException() { super(); }
 213     }
 214 
 215     /** An invalid return value for Fib. */
 216     static final Integer NoResult = Integer.valueOf(-17);
 217 
 218     /** A simple recursive task for testing. */
 219     final class FibTask extends CheckedRecursiveTask<Integer> {
 220         final int number;
 221         FibTask(int n) { number = n; }
 222         public Integer realCompute() {
 223             int n = number;
 224             if (n <= 1)
 225                 return n;
 226             FibTask f1 = new FibTask(n - 1);
 227             f1.fork();
 228             return new FibTask(n - 2).compute() + f1.join();
 229         }
 230 
 231         public void publicSetRawResult(Integer result) {
 232             setRawResult(result);
 233         }
 234     }
 235 
 236     /** A recursive action failing in base case. */
 237     final class FailingFibTask extends RecursiveTask<Integer> {
 238         final int number;
 239         int result;
 240         FailingFibTask(int n) { number = n; }
 241         public Integer compute() {
 242             int n = number;
 243             if (n <= 1)
 244                 throw new FJException();
 245             FailingFibTask f1 = new FailingFibTask(n - 1);
 246             f1.fork();
 247             return new FibTask(n - 2).compute() + f1.join();
 248         }
 249     }
 250 
 251     /**
 252      * invoke returns value when task completes normally.
 253      * isCompletedAbnormally and isCancelled return false for normally
 254      * completed tasks. getRawResult of a completed non-null task
 255      * returns value;
 256      */
 257     public void testInvoke() {
 258         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 259             public Integer realCompute() {
 260                 FibTask f = new FibTask(8);
 261                 Integer r = f.invoke();
 262                 assertEquals(21, (int) r);
 263                 checkCompletedNormally(f, r);
 264                 return r;
 265             }};
 266         assertEquals(21, (int) testInvokeOnPool(mainPool(), a));
 267     }
 268 
 269     /**
 270      * quietlyInvoke task returns when task completes normally.
 271      * isCompletedAbnormally and isCancelled return false for normally
 272      * completed tasks
 273      */
 274     public void testQuietlyInvoke() {
 275         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 276             public Integer realCompute() {
 277                 FibTask f = new FibTask(8);
 278                 f.quietlyInvoke();
 279                 checkCompletedNormally(f, 21);
 280                 return NoResult;
 281             }};
 282         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
 283     }
 284 
 285     /**
 286      * join of a forked task returns when task completes
 287      */
 288     public void testForkJoin() {
 289         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 290             public Integer realCompute() {
 291                 FibTask f = new FibTask(8);
 292                 assertSame(f, f.fork());
 293                 Integer r = f.join();
 294                 assertEquals(21, (int) r);
 295                 checkCompletedNormally(f, r);
 296                 return r;
 297             }};
 298         assertEquals(21, (int) testInvokeOnPool(mainPool(), a));
 299     }
 300 
 301     /**
 302      * get of a forked task returns when task completes
 303      */
 304     public void testForkGet() {
 305         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 306             public Integer realCompute() throws Exception {
 307                 FibTask f = new FibTask(8);
 308                 assertSame(f, f.fork());
 309                 Integer r = f.get();
 310                 assertEquals(21, (int) r);
 311                 checkCompletedNormally(f, r);
 312                 return r;
 313             }};
 314         assertEquals(21, (int) testInvokeOnPool(mainPool(), a));
 315     }
 316 
 317     /**
 318      * timed get of a forked task returns when task completes
 319      */
 320     public void testForkTimedGet() {
 321         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 322             public Integer realCompute() throws Exception {
 323                 FibTask f = new FibTask(8);
 324                 assertSame(f, f.fork());
 325                 Integer r = f.get(LONG_DELAY_MS, MILLISECONDS);
 326                 assertEquals(21, (int) r);
 327                 checkCompletedNormally(f, r);
 328                 return r;
 329             }};
 330         assertEquals(21, (int) testInvokeOnPool(mainPool(), a));
 331     }
 332 
 333     /**
 334      * quietlyJoin of a forked task returns when task completes
 335      */
 336     public void testForkQuietlyJoin() {
 337         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 338             public Integer realCompute() {
 339                 FibTask f = new FibTask(8);
 340                 assertSame(f, f.fork());
 341                 f.quietlyJoin();
 342                 Integer r = f.getRawResult();
 343                 assertEquals(21, (int) r);
 344                 checkCompletedNormally(f, r);
 345                 return r;
 346             }};
 347         assertEquals(21, (int) testInvokeOnPool(mainPool(), a));
 348     }
 349 
 350     /**
 351      * helpQuiesce returns when tasks are complete.
 352      * getQueuedTaskCount returns 0 when quiescent
 353      */
 354     public void testForkHelpQuiesce() {
 355         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 356             public Integer realCompute() {
 357                 FibTask f = new FibTask(8);
 358                 assertSame(f, f.fork());
 359                 helpQuiesce();
 360                 while (!f.isDone()) // wait out race
 361                     ;
 362                 assertEquals(0, getQueuedTaskCount());
 363                 checkCompletedNormally(f, 21);
 364                 return NoResult;
 365             }};
 366         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
 367     }
 368 
 369     /**
 370      * invoke task throws exception when task completes abnormally
 371      */
 372     public void testAbnormalInvoke() {
 373         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 374             public Integer realCompute() {
 375                 FailingFibTask f = new FailingFibTask(8);
 376                 try {
 377                     f.invoke();
 378                     shouldThrow();
 379                 } catch (FJException success) {
 380                     checkCompletedAbnormally(f, success);
 381                 }
 382                 return NoResult;
 383             }};
 384         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
 385     }
 386 
 387     /**
 388      * quietlyInvoke task returns when task completes abnormally
 389      */
 390     public void testAbnormalQuietlyInvoke() {
 391         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 392             public Integer realCompute() {
 393                 FailingFibTask f = new FailingFibTask(8);
 394                 f.quietlyInvoke();
 395                 assertTrue(f.getException() instanceof FJException);
 396                 checkCompletedAbnormally(f, f.getException());
 397                 return NoResult;
 398             }};
 399         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
 400     }
 401 
 402     /**
 403      * join of a forked task throws exception when task completes abnormally
 404      */
 405     public void testAbnormalForkJoin() {
 406         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 407             public Integer realCompute() {
 408                 FailingFibTask f = new FailingFibTask(8);
 409                 assertSame(f, f.fork());
 410                 try {
 411                     Integer r = f.join();
 412                     shouldThrow();
 413                 } catch (FJException success) {
 414                     checkCompletedAbnormally(f, success);
 415                 }
 416                 return NoResult;
 417             }};
 418         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
 419     }
 420 
 421     /**
 422      * get of a forked task throws exception when task completes abnormally
 423      */
 424     public void testAbnormalForkGet() {
 425         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 426             public Integer realCompute() throws Exception {
 427                 FailingFibTask f = new FailingFibTask(8);
 428                 assertSame(f, f.fork());
 429                 try {
 430                     Integer r = f.get();
 431                     shouldThrow();
 432                 } catch (ExecutionException success) {
 433                     Throwable cause = success.getCause();
 434                     assertTrue(cause instanceof FJException);
 435                     checkCompletedAbnormally(f, cause);
 436                 }
 437                 return NoResult;
 438             }};
 439         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
 440     }
 441 
 442     /**
 443      * timed get of a forked task throws exception when task completes abnormally
 444      */
 445     public void testAbnormalForkTimedGet() {
 446         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 447             public Integer realCompute() throws Exception {
 448                 FailingFibTask f = new FailingFibTask(8);
 449                 assertSame(f, f.fork());
 450                 try {
 451                     Integer r = f.get(LONG_DELAY_MS, MILLISECONDS);
 452                     shouldThrow();
 453                 } catch (ExecutionException success) {
 454                     Throwable cause = success.getCause();
 455                     assertTrue(cause instanceof FJException);
 456                     checkCompletedAbnormally(f, cause);
 457                 }
 458                 return NoResult;
 459             }};
 460         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
 461     }
 462 
 463     /**
 464      * quietlyJoin of a forked task returns when task completes abnormally
 465      */
 466     public void testAbnormalForkQuietlyJoin() {
 467         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 468             public Integer realCompute() {
 469                 FailingFibTask f = new FailingFibTask(8);
 470                 assertSame(f, f.fork());
 471                 f.quietlyJoin();
 472                 assertTrue(f.getException() instanceof FJException);
 473                 checkCompletedAbnormally(f, f.getException());
 474                 return NoResult;
 475             }};
 476         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
 477     }
 478 
 479     /**
 480      * invoke task throws exception when task cancelled
 481      */
 482     public void testCancelledInvoke() {
 483         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 484             public Integer realCompute() {
 485                 FibTask f = new FibTask(8);
 486                 assertTrue(f.cancel(true));
 487                 try {
 488                     Integer r = f.invoke();
 489                     shouldThrow();
 490                 } catch (CancellationException success) {
 491                     checkCancelled(f);
 492                 }
 493                 return NoResult;
 494             }};
 495         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
 496     }
 497 
 498     /**
 499      * join of a forked task throws exception when task cancelled
 500      */
 501     public void testCancelledForkJoin() {
 502         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 503             public Integer realCompute() {
 504                 FibTask f = new FibTask(8);
 505                 assertTrue(f.cancel(true));
 506                 assertSame(f, f.fork());
 507                 try {
 508                     Integer r = f.join();
 509                     shouldThrow();
 510                 } catch (CancellationException success) {
 511                     checkCancelled(f);
 512                 }
 513                 return NoResult;
 514             }};
 515         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
 516     }
 517 
 518     /**
 519      * get of a forked task throws exception when task cancelled
 520      */
 521     public void testCancelledForkGet() {
 522         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 523             public Integer realCompute() throws Exception {
 524                 FibTask f = new FibTask(8);
 525                 assertTrue(f.cancel(true));
 526                 assertSame(f, f.fork());
 527                 try {
 528                     Integer r = f.get();
 529                     shouldThrow();
 530                 } catch (CancellationException success) {
 531                     checkCancelled(f);
 532                 }
 533                 return NoResult;
 534             }};
 535         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
 536     }
 537 
 538     /**
 539      * timed get of a forked task throws exception when task cancelled
 540      */
 541     public void testCancelledForkTimedGet() {
 542         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 543             public Integer realCompute() throws Exception {
 544                 FibTask f = new FibTask(8);
 545                 assertTrue(f.cancel(true));
 546                 assertSame(f, f.fork());
 547                 try {
 548                     Integer r = f.get(LONG_DELAY_MS, MILLISECONDS);
 549                     shouldThrow();
 550                 } catch (CancellationException success) {
 551                     checkCancelled(f);
 552                 }
 553                 return NoResult;
 554             }};
 555         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
 556     }
 557 
 558     /**
 559      * quietlyJoin of a forked task returns when task cancelled
 560      */
 561     public void testCancelledForkQuietlyJoin() {
 562         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 563             public Integer realCompute() {
 564                 FibTask f = new FibTask(8);
 565                 assertTrue(f.cancel(true));
 566                 assertSame(f, f.fork());
 567                 f.quietlyJoin();
 568                 checkCancelled(f);
 569                 return NoResult;
 570             }};
 571         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
 572     }
 573 
 574     /**
 575      * getPool of executing task returns its pool
 576      */
 577     public void testGetPool() {
 578         final ForkJoinPool mainPool = mainPool();
 579         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 580             public Integer realCompute() {
 581                 assertSame(mainPool, getPool());
 582                 return NoResult;
 583             }};
 584         assertSame(NoResult, testInvokeOnPool(mainPool, a));
 585     }
 586 
 587     /**
 588      * getPool of non-FJ task returns null
 589      */
 590     public void testGetPool2() {
 591         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 592             public Integer realCompute() {
 593                 assertNull(getPool());
 594                 return NoResult;
 595             }};
 596         assertSame(NoResult, a.invoke());
 597     }
 598 
 599     /**
 600      * inForkJoinPool of executing task returns true
 601      */
 602     public void testInForkJoinPool() {
 603         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 604             public Integer realCompute() {
 605                 assertTrue(inForkJoinPool());
 606                 return NoResult;
 607             }};
 608         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
 609     }
 610 
 611     /**
 612      * inForkJoinPool of non-FJ task returns false
 613      */
 614     public void testInForkJoinPool2() {
 615         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 616             public Integer realCompute() {
 617                 assertFalse(inForkJoinPool());
 618                 return NoResult;
 619             }};
 620         assertSame(NoResult, a.invoke());
 621     }
 622 
 623     /**
 624      * The value set by setRawResult is returned by getRawResult
 625      */
 626     public void testSetRawResult() {
 627         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 628             public Integer realCompute() {
 629                 setRawResult(NoResult);
 630                 assertSame(NoResult, getRawResult());
 631                 return NoResult;
 632             }
 633         };
 634         assertSame(NoResult, a.invoke());
 635     }
 636 
 637     /**
 638      * A reinitialized normally completed task may be re-invoked
 639      */
 640     public void testReinitialize() {
 641         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 642             public Integer realCompute() {
 643                 FibTask f = new FibTask(8);
 644                 checkNotDone(f);
 645 
 646                 for (int i = 0; i < 3; i++) {
 647                     Integer r = f.invoke();
 648                     assertEquals(21, (int) r);
 649                     checkCompletedNormally(f, r);
 650                     f.reinitialize();
 651                     f.publicSetRawResult(null);
 652                     checkNotDone(f);
 653                 }
 654                 return NoResult;
 655             }};
 656         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
 657     }
 658 
 659     /**
 660      * A reinitialized abnormally completed task may be re-invoked
 661      */
 662     public void testReinitializeAbnormal() {
 663         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 664             public Integer realCompute() {
 665                 FailingFibTask f = new FailingFibTask(8);
 666                 checkNotDone(f);
 667 
 668                 for (int i = 0; i < 3; i++) {
 669                     try {
 670                         f.invoke();
 671                         shouldThrow();
 672                     } catch (FJException success) {
 673                         checkCompletedAbnormally(f, success);
 674                     }
 675                     f.reinitialize();
 676                     checkNotDone(f);
 677                 }
 678                 return NoResult;
 679             }};
 680         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
 681     }
 682 
 683     /**
 684      * invoke task throws exception after invoking completeExceptionally
 685      */
 686     public void testCompleteExceptionally() {
 687         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 688             public Integer realCompute() {
 689                 FibTask f = new FibTask(8);
 690                 f.completeExceptionally(new FJException());
 691                 try {
 692                     Integer r = f.invoke();
 693                     shouldThrow();
 694                 } catch (FJException success) {
 695                     checkCompletedAbnormally(f, success);
 696                 }
 697                 return NoResult;
 698             }};
 699         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
 700     }
 701 
 702     /**
 703      * invoke task suppresses execution invoking complete
 704      */
 705     public void testComplete() {
 706         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 707             public Integer realCompute() {
 708                 FibTask f = new FibTask(8);
 709                 f.complete(NoResult);
 710                 Integer r = f.invoke();
 711                 assertSame(NoResult, r);
 712                 checkCompletedNormally(f, NoResult);
 713                 return r;
 714             }};
 715         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
 716     }
 717 
 718     /**
 719      * invokeAll(t1, t2) invokes all task arguments
 720      */
 721     public void testInvokeAll2() {
 722         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 723             public Integer realCompute() {
 724                 FibTask f = new FibTask(8);
 725                 FibTask g = new FibTask(9);
 726                 invokeAll(f, g);
 727                 checkCompletedNormally(f, 21);
 728                 checkCompletedNormally(g, 34);
 729                 return NoResult;
 730             }};
 731         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
 732     }
 733 
 734     /**
 735      * invokeAll(tasks) with 1 argument invokes task
 736      */
 737     public void testInvokeAll1() {
 738         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 739             public Integer realCompute() {
 740                 FibTask f = new FibTask(8);
 741                 invokeAll(f);
 742                 checkCompletedNormally(f, 21);
 743                 return NoResult;
 744             }};
 745         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
 746     }
 747 
 748     /**
 749      * invokeAll(tasks) with > 2 argument invokes tasks
 750      */
 751     public void testInvokeAll3() {
 752         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 753             public Integer realCompute() {
 754                 FibTask f = new FibTask(8);
 755                 FibTask g = new FibTask(9);
 756                 FibTask h = new FibTask(7);
 757                 invokeAll(f, g, h);
 758                 assertTrue(f.isDone());
 759                 assertTrue(g.isDone());
 760                 assertTrue(h.isDone());
 761                 checkCompletedNormally(f, 21);
 762                 checkCompletedNormally(g, 34);
 763                 checkCompletedNormally(h, 13);
 764                 return NoResult;
 765             }};
 766         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
 767     }
 768 
 769     /**
 770      * invokeAll(collection) invokes all tasks in the collection
 771      */
 772     public void testInvokeAllCollection() {
 773         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 774             public Integer realCompute() {
 775                 FibTask f = new FibTask(8);
 776                 FibTask g = new FibTask(9);
 777                 FibTask h = new FibTask(7);
 778                 HashSet set = new HashSet();
 779                 set.add(f);
 780                 set.add(g);
 781                 set.add(h);
 782                 invokeAll(set);
 783                 assertTrue(f.isDone());
 784                 assertTrue(g.isDone());
 785                 assertTrue(h.isDone());
 786                 checkCompletedNormally(f, 21);
 787                 checkCompletedNormally(g, 34);
 788                 checkCompletedNormally(h, 13);
 789                 return NoResult;
 790             }};
 791         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
 792     }
 793 
 794     /**
 795      * invokeAll(tasks) with any null task throws NPE
 796      */
 797     public void testInvokeAllNPE() {
 798         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 799             public Integer realCompute() {
 800                 FibTask f = new FibTask(8);
 801                 FibTask g = new FibTask(9);
 802                 FibTask h = null;
 803                 try {
 804                     invokeAll(f, g, h);
 805                     shouldThrow();
 806                 } catch (NullPointerException success) {}
 807                 return NoResult;
 808             }};
 809         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
 810     }
 811 
 812     /**
 813      * invokeAll(t1, t2) throw exception if any task does
 814      */
 815     public void testAbnormalInvokeAll2() {
 816         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 817             public Integer realCompute() {
 818                 FibTask f = new FibTask(8);
 819                 FailingFibTask g = new FailingFibTask(9);
 820                 try {
 821                     invokeAll(f, g);
 822                     shouldThrow();
 823                 } catch (FJException success) {
 824                     checkCompletedAbnormally(g, success);
 825                 }
 826                 return NoResult;
 827             }};
 828         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
 829     }
 830 
 831     /**
 832      * invokeAll(tasks) with 1 argument throws exception if task does
 833      */
 834     public void testAbnormalInvokeAll1() {
 835         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 836             public Integer realCompute() {
 837                 FailingFibTask g = new FailingFibTask(9);
 838                 try {
 839                     invokeAll(g);
 840                     shouldThrow();
 841                 } catch (FJException success) {
 842                     checkCompletedAbnormally(g, success);
 843                 }
 844                 return NoResult;
 845             }};
 846         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
 847     }
 848 
 849     /**
 850      * invokeAll(tasks) with > 2 argument throws exception if any task does
 851      */
 852     public void testAbnormalInvokeAll3() {
 853         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 854             public Integer realCompute() {
 855                 FibTask f = new FibTask(8);
 856                 FailingFibTask g = new FailingFibTask(9);
 857                 FibTask h = new FibTask(7);
 858                 try {
 859                     invokeAll(f, g, h);
 860                     shouldThrow();
 861                 } catch (FJException success) {
 862                     checkCompletedAbnormally(g, success);
 863                 }
 864                 return NoResult;
 865             }};
 866         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
 867     }
 868 
 869     /**
 870      * invokeAll(collection) throws exception if any task does
 871      */
 872     public void testAbnormalInvokeAllCollection() {
 873         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 874             public Integer realCompute() {
 875                 FailingFibTask f = new FailingFibTask(8);
 876                 FibTask g = new FibTask(9);
 877                 FibTask h = new FibTask(7);
 878                 HashSet set = new HashSet();
 879                 set.add(f);
 880                 set.add(g);
 881                 set.add(h);
 882                 try {
 883                     invokeAll(set);
 884                     shouldThrow();
 885                 } catch (FJException success) {
 886                     checkCompletedAbnormally(f, success);
 887                 }
 888                 return NoResult;
 889             }};
 890         assertSame(NoResult, testInvokeOnPool(mainPool(), a));
 891     }
 892 
 893     /**
 894      * tryUnfork returns true for most recent unexecuted task,
 895      * and suppresses execution
 896      */
 897     public void testTryUnfork() {
 898         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 899             public Integer realCompute() {
 900                 FibTask g = new FibTask(9);
 901                 assertSame(g, g.fork());
 902                 FibTask f = new FibTask(8);
 903                 assertSame(f, f.fork());
 904                 assertTrue(f.tryUnfork());
 905                 helpQuiesce();
 906                 checkNotDone(f);
 907                 checkCompletedNormally(g, 34);
 908                 return NoResult;
 909             }};
 910         assertSame(NoResult, testInvokeOnPool(singletonPool(), a));
 911     }
 912 
 913     /**
 914      * getSurplusQueuedTaskCount returns > 0 when
 915      * there are more tasks than threads
 916      */
 917     public void testGetSurplusQueuedTaskCount() {
 918         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 919             public Integer realCompute() {
 920                 FibTask h = new FibTask(7);
 921                 assertSame(h, h.fork());
 922                 FibTask g = new FibTask(9);
 923                 assertSame(g, g.fork());
 924                 FibTask f = new FibTask(8);
 925                 assertSame(f, f.fork());
 926                 assertTrue(getSurplusQueuedTaskCount() > 0);
 927                 helpQuiesce();
 928                 assertEquals(0, getSurplusQueuedTaskCount());
 929                 checkCompletedNormally(f, 21);
 930                 checkCompletedNormally(g, 34);
 931                 checkCompletedNormally(h, 13);
 932                 return NoResult;
 933             }};
 934         assertSame(NoResult, testInvokeOnPool(singletonPool(), a));
 935     }
 936 
 937     /**
 938      * peekNextLocalTask returns most recent unexecuted task.
 939      */
 940     public void testPeekNextLocalTask() {
 941         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 942             public Integer realCompute() {
 943                 FibTask g = new FibTask(9);
 944                 assertSame(g, g.fork());
 945                 FibTask f = new FibTask(8);
 946                 assertSame(f, f.fork());
 947                 assertSame(f, peekNextLocalTask());
 948                 checkCompletesNormally(f, 21);
 949                 helpQuiesce();
 950                 checkCompletedNormally(g, 34);
 951                 return NoResult;
 952             }};
 953         assertSame(NoResult, testInvokeOnPool(singletonPool(), a));
 954     }
 955 
 956     /**
 957      * pollNextLocalTask returns most recent unexecuted task
 958      * without executing it
 959      */
 960     public void testPollNextLocalTask() {
 961         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 962             public Integer realCompute() {
 963                 FibTask g = new FibTask(9);
 964                 assertSame(g, g.fork());
 965                 FibTask f = new FibTask(8);
 966                 assertSame(f, f.fork());
 967                 assertSame(f, pollNextLocalTask());
 968                 helpQuiesce();
 969                 checkNotDone(f);
 970                 checkCompletedNormally(g, 34);
 971                 return NoResult;
 972             }};
 973         assertSame(NoResult, testInvokeOnPool(singletonPool(), a));
 974     }
 975 
 976     /**
 977      * pollTask returns an unexecuted task without executing it
 978      */
 979     public void testPollTask() {
 980         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
 981             public Integer realCompute() {
 982                 FibTask g = new FibTask(9);
 983                 assertSame(g, g.fork());
 984                 FibTask f = new FibTask(8);
 985                 assertSame(f, f.fork());
 986                 assertSame(f, pollTask());
 987                 helpQuiesce();
 988                 checkNotDone(f);
 989                 checkCompletedNormally(g, 34);
 990                 return NoResult;
 991             }};
 992         assertSame(NoResult, testInvokeOnPool(singletonPool(), a));
 993     }
 994 
 995     /**
 996      * peekNextLocalTask returns least recent unexecuted task in async mode
 997      */
 998     public void testPeekNextLocalTaskAsync() {
 999         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
1000             public Integer realCompute() {
1001                 FibTask g = new FibTask(9);
1002                 assertSame(g, g.fork());
1003                 FibTask f = new FibTask(8);
1004                 assertSame(f, f.fork());
1005                 assertSame(g, peekNextLocalTask());
1006                 assertEquals(21, (int) f.join());
1007                 helpQuiesce();
1008                 checkCompletedNormally(f, 21);
1009                 checkCompletedNormally(g, 34);
1010                 return NoResult;
1011             }};
1012         assertSame(NoResult, testInvokeOnPool(asyncSingletonPool(), a));
1013     }
1014 
1015     /**
1016      * pollNextLocalTask returns least recent unexecuted task without
1017      * executing it, in async mode
1018      */
1019     public void testPollNextLocalTaskAsync() {
1020         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
1021             public Integer realCompute() {
1022                 FibTask g = new FibTask(9);
1023                 assertSame(g, g.fork());
1024                 FibTask f = new FibTask(8);
1025                 assertSame(f, f.fork());
1026                 assertSame(g, pollNextLocalTask());
1027                 helpQuiesce();
1028                 checkCompletedNormally(f, 21);
1029                 checkNotDone(g);
1030                 return NoResult;
1031             }};
1032         assertSame(NoResult, testInvokeOnPool(asyncSingletonPool(), a));
1033     }
1034 
1035     /**
1036      * pollTask returns an unexecuted task without executing it, in
1037      * async mode
1038      */
1039     public void testPollTaskAsync() {
1040         RecursiveTask<Integer> a = new CheckedRecursiveTask<Integer>() {
1041             public Integer realCompute() {
1042                 FibTask g = new FibTask(9);
1043                 assertSame(g, g.fork());
1044                 FibTask f = new FibTask(8);
1045                 assertSame(f, f.fork());
1046                 assertSame(g, pollTask());
1047                 helpQuiesce();
1048                 checkCompletedNormally(f, 21);
1049                 checkNotDone(g);
1050                 return NoResult;
1051             }};
1052         assertSame(NoResult, testInvokeOnPool(asyncSingletonPool(), a));
1053     }
1054 
1055 }