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