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 import static java.util.concurrent.TimeUnit.NANOSECONDS;
  36 import static java.util.concurrent.TimeUnit.SECONDS;
  37 
  38 import java.util.ArrayList;
  39 import java.util.Collection;
  40 import java.util.Collections;
  41 import java.util.HashSet;
  42 import java.util.List;
  43 import java.util.concurrent.BlockingQueue;
  44 import java.util.concurrent.Callable;
  45 import java.util.concurrent.CancellationException;
  46 import java.util.concurrent.CountDownLatch;
  47 import java.util.concurrent.Delayed;
  48 import java.util.concurrent.ExecutionException;
  49 import java.util.concurrent.ExecutorService;
  50 import java.util.concurrent.Future;
  51 import java.util.concurrent.RejectedExecutionException;
  52 import java.util.concurrent.RejectedExecutionHandler;
  53 import java.util.concurrent.RunnableScheduledFuture;
  54 import java.util.concurrent.ScheduledFuture;
  55 import java.util.concurrent.ScheduledThreadPoolExecutor;
  56 import java.util.concurrent.ThreadFactory;
  57 import java.util.concurrent.ThreadLocalRandom;
  58 import java.util.concurrent.ThreadPoolExecutor;
  59 import java.util.concurrent.TimeoutException;
  60 import java.util.concurrent.TimeUnit;
  61 import java.util.concurrent.atomic.AtomicBoolean;
  62 import java.util.concurrent.atomic.AtomicInteger;
  63 import java.util.concurrent.atomic.AtomicLong;
  64 import java.util.stream.Stream;
  65 
  66 import junit.framework.Test;
  67 import junit.framework.TestSuite;
  68 
  69 public class ScheduledExecutorSubclassTest extends JSR166TestCase {
  70     public static void main(String[] args) {
  71         main(suite(), args);
  72     }
  73     public static Test suite() {
  74         return new TestSuite(ScheduledExecutorSubclassTest.class);
  75     }
  76 
  77     static class CustomTask<V> implements RunnableScheduledFuture<V> {
  78         private final RunnableScheduledFuture<V> task;
  79         volatile boolean ran;
  80         CustomTask(RunnableScheduledFuture<V> task) { this.task = task; }
  81         public boolean isPeriodic() { return task.isPeriodic(); }
  82         public void run() {
  83             ran = true;
  84             task.run();
  85         }
  86         public long getDelay(TimeUnit unit) { return task.getDelay(unit); }
  87         public int compareTo(Delayed t) {
  88             return task.compareTo(((CustomTask)t).task);
  89         }
  90         public boolean cancel(boolean mayInterruptIfRunning) {
  91             return task.cancel(mayInterruptIfRunning);
  92         }
  93         public boolean isCancelled() { return task.isCancelled(); }
  94         public boolean isDone() { return task.isDone(); }
  95         public V get() throws InterruptedException, ExecutionException {
  96             V v = task.get();
  97             assertTrue(ran);
  98             return v;
  99         }
 100         public V get(long time, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
 101             V v = task.get(time, unit);
 102             assertTrue(ran);
 103             return v;
 104         }
 105     }
 106 
 107     public class CustomExecutor extends ScheduledThreadPoolExecutor {
 108 
 109         protected <V> RunnableScheduledFuture<V> decorateTask(Runnable r, RunnableScheduledFuture<V> task) {
 110             return new CustomTask<V>(task);
 111         }
 112 
 113         protected <V> RunnableScheduledFuture<V> decorateTask(Callable<V> c, RunnableScheduledFuture<V> task) {
 114             return new CustomTask<V>(task);
 115         }
 116         CustomExecutor(int corePoolSize) { super(corePoolSize); }
 117         CustomExecutor(int corePoolSize, RejectedExecutionHandler handler) {
 118             super(corePoolSize, handler);
 119         }
 120 
 121         CustomExecutor(int corePoolSize, ThreadFactory threadFactory) {
 122             super(corePoolSize, threadFactory);
 123         }
 124         CustomExecutor(int corePoolSize, ThreadFactory threadFactory,
 125                        RejectedExecutionHandler handler) {
 126             super(corePoolSize, threadFactory, handler);
 127         }
 128 
 129     }
 130 
 131     /**
 132      * execute successfully executes a runnable
 133      */
 134     public void testExecute() throws InterruptedException {
 135         final CustomExecutor p = new CustomExecutor(1);
 136         try (PoolCleaner cleaner = cleaner(p)) {
 137             final CountDownLatch done = new CountDownLatch(1);
 138             final Runnable task = new CheckedRunnable() {
 139                 public void realRun() { done.countDown(); }};
 140             p.execute(task);
 141             await(done);
 142         }
 143     }
 144 
 145     /**
 146      * delayed schedule of callable successfully executes after delay
 147      */
 148     public void testSchedule1() throws Exception {
 149         final CountDownLatch done = new CountDownLatch(1);
 150         final CustomExecutor p = new CustomExecutor(1);
 151         try (PoolCleaner cleaner = cleaner(p, done)) {
 152             final long startTime = System.nanoTime();
 153             Callable task = new CheckedCallable<Boolean>() {
 154                 public Boolean realCall() {
 155                     done.countDown();
 156                     assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
 157                     return Boolean.TRUE;
 158                 }};
 159             Future f = p.schedule(task, timeoutMillis(), MILLISECONDS);
 160             assertSame(Boolean.TRUE, f.get());
 161             assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
 162         }
 163     }
 164 
 165     /**
 166      * delayed schedule of runnable successfully executes after delay
 167      */
 168     public void testSchedule3() throws Exception {
 169         final CustomExecutor p = new CustomExecutor(1);
 170         try (PoolCleaner cleaner = cleaner(p)) {
 171             final long startTime = System.nanoTime();
 172             final CountDownLatch done = new CountDownLatch(1);
 173             Runnable task = new CheckedRunnable() {
 174                 public void realRun() {
 175                     done.countDown();
 176                     assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
 177                 }};
 178             Future f = p.schedule(task, timeoutMillis(), MILLISECONDS);
 179             await(done);
 180             assertNull(f.get(LONG_DELAY_MS, MILLISECONDS));
 181             assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
 182         }
 183     }
 184 
 185     /**
 186      * scheduleAtFixedRate executes runnable after given initial delay
 187      */
 188     public void testSchedule4() throws InterruptedException {
 189         final CustomExecutor p = new CustomExecutor(1);
 190         try (PoolCleaner cleaner = cleaner(p)) {
 191             final long startTime = System.nanoTime();
 192             final CountDownLatch done = new CountDownLatch(1);
 193             Runnable task = new CheckedRunnable() {
 194                 public void realRun() {
 195                     done.countDown();
 196                     assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
 197                 }};
 198             ScheduledFuture f =
 199                 p.scheduleAtFixedRate(task, timeoutMillis(),
 200                                       LONG_DELAY_MS, MILLISECONDS);
 201             await(done);
 202             assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
 203             f.cancel(true);
 204         }
 205     }
 206 
 207     /**
 208      * scheduleWithFixedDelay executes runnable after given initial delay
 209      */
 210     public void testSchedule5() throws InterruptedException {
 211         final CustomExecutor p = new CustomExecutor(1);
 212         try (PoolCleaner cleaner = cleaner(p)) {
 213             final long startTime = System.nanoTime();
 214             final CountDownLatch done = new CountDownLatch(1);
 215             Runnable task = new CheckedRunnable() {
 216                 public void realRun() {
 217                     done.countDown();
 218                     assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
 219                 }};
 220             ScheduledFuture f =
 221                 p.scheduleWithFixedDelay(task, timeoutMillis(),
 222                                          LONG_DELAY_MS, MILLISECONDS);
 223             await(done);
 224             assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
 225             f.cancel(true);
 226         }
 227     }
 228 
 229     static class RunnableCounter implements Runnable {
 230         AtomicInteger count = new AtomicInteger(0);
 231         public void run() { count.getAndIncrement(); }
 232     }
 233 
 234     /**
 235      * scheduleAtFixedRate executes series of tasks at given rate.
 236      * Eventually, it must hold that:
 237      *   cycles - 1 <= elapsedMillis/delay < cycles
 238      */
 239     public void testFixedRateSequence() throws InterruptedException {
 240         final CustomExecutor p = new CustomExecutor(1);
 241         try (PoolCleaner cleaner = cleaner(p)) {
 242             for (int delay = 1; delay <= LONG_DELAY_MS; delay *= 3) {
 243                 final long startTime = System.nanoTime();
 244                 final int cycles = 8;
 245                 final CountDownLatch done = new CountDownLatch(cycles);
 246                 final Runnable task = new CheckedRunnable() {
 247                     public void realRun() { done.countDown(); }};
 248                 final ScheduledFuture periodicTask =
 249                     p.scheduleAtFixedRate(task, 0, delay, MILLISECONDS);
 250                 final int totalDelayMillis = (cycles - 1) * delay;
 251                 await(done, totalDelayMillis + LONG_DELAY_MS);
 252                 periodicTask.cancel(true);
 253                 final long elapsedMillis = millisElapsedSince(startTime);
 254                 assertTrue(elapsedMillis >= totalDelayMillis);
 255                 if (elapsedMillis <= cycles * delay)
 256                     return;
 257                 // else retry with longer delay
 258             }
 259             fail("unexpected execution rate");
 260         }
 261     }
 262 
 263     /**
 264      * scheduleWithFixedDelay executes series of tasks with given period.
 265      * Eventually, it must hold that each task starts at least delay and at
 266      * most 2 * delay after the termination of the previous task.
 267      */
 268     public void testFixedDelaySequence() throws InterruptedException {
 269         final CustomExecutor p = new CustomExecutor(1);
 270         try (PoolCleaner cleaner = cleaner(p)) {
 271             for (int delay = 1; delay <= LONG_DELAY_MS; delay *= 3) {
 272                 final long startTime = System.nanoTime();
 273                 final AtomicLong previous = new AtomicLong(startTime);
 274                 final AtomicBoolean tryLongerDelay = new AtomicBoolean(false);
 275                 final int cycles = 8;
 276                 final CountDownLatch done = new CountDownLatch(cycles);
 277                 final int d = delay;
 278                 final Runnable task = new CheckedRunnable() {
 279                     public void realRun() {
 280                         long now = System.nanoTime();
 281                         long elapsedMillis
 282                             = NANOSECONDS.toMillis(now - previous.get());
 283                         if (done.getCount() == cycles) { // first execution
 284                             if (elapsedMillis >= d)
 285                                 tryLongerDelay.set(true);
 286                         } else {
 287                             assertTrue(elapsedMillis >= d);
 288                             if (elapsedMillis >= 2 * d)
 289                                 tryLongerDelay.set(true);
 290                         }
 291                         previous.set(now);
 292                         done.countDown();
 293                     }};
 294                 final ScheduledFuture periodicTask =
 295                     p.scheduleWithFixedDelay(task, 0, delay, MILLISECONDS);
 296                 final int totalDelayMillis = (cycles - 1) * delay;
 297                 await(done, totalDelayMillis + cycles * LONG_DELAY_MS);
 298                 periodicTask.cancel(true);
 299                 final long elapsedMillis = millisElapsedSince(startTime);
 300                 assertTrue(elapsedMillis >= totalDelayMillis);
 301                 if (!tryLongerDelay.get())
 302                     return;
 303                 // else retry with longer delay
 304             }
 305             fail("unexpected execution rate");
 306         }
 307     }
 308 
 309     /**
 310      * Submitting null tasks throws NullPointerException
 311      */
 312     public void testNullTaskSubmission() {
 313         final CustomExecutor p = new CustomExecutor(1);
 314         try (PoolCleaner cleaner = cleaner(p)) {
 315             assertNullTaskSubmissionThrowsNullPointerException(p);
 316         }
 317     }
 318 
 319     /**
 320      * Submitted tasks are rejected when shutdown
 321      */
 322     public void testSubmittedTasksRejectedWhenShutdown() throws InterruptedException {
 323         final CustomExecutor p = new CustomExecutor(2);
 324         final ThreadLocalRandom rnd = ThreadLocalRandom.current();
 325         final CountDownLatch threadsStarted = new CountDownLatch(p.getCorePoolSize());
 326         final CountDownLatch done = new CountDownLatch(1);
 327         final Runnable r = () -> {
 328             threadsStarted.countDown();
 329             for (;;) {
 330                 try {
 331                     done.await();
 332                     return;
 333                 } catch (InterruptedException shutdownNowDeliberatelyIgnored) {}
 334             }};
 335         final Callable<Boolean> c = () -> {
 336             threadsStarted.countDown();
 337             for (;;) {
 338                 try {
 339                     done.await();
 340                     return Boolean.TRUE;
 341                 } catch (InterruptedException shutdownNowDeliberatelyIgnored) {}
 342             }};
 343 
 344         try (PoolCleaner cleaner = cleaner(p, done)) {
 345             for (int i = p.getCorePoolSize(); i--> 0; ) {
 346                 switch (rnd.nextInt(4)) {
 347                 case 0: p.execute(r); break;
 348                 case 1: assertFalse(p.submit(r).isDone()); break;
 349                 case 2: assertFalse(p.submit(r, Boolean.TRUE).isDone()); break;
 350                 case 3: assertFalse(p.submit(c).isDone()); break;
 351                 }
 352             }
 353 
 354             // ScheduledThreadPoolExecutor has an unbounded queue, so never saturated.
 355             await(threadsStarted);
 356 
 357             if (rnd.nextBoolean())
 358                 p.shutdownNow();
 359             else
 360                 p.shutdown();
 361             // Pool is shutdown, but not yet terminated
 362             assertTaskSubmissionsAreRejected(p);
 363             assertFalse(p.isTerminated());
 364 
 365             done.countDown();   // release blocking tasks
 366             assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
 367 
 368             assertTaskSubmissionsAreRejected(p);
 369         }
 370         assertEquals(p.getCorePoolSize(), p.getCompletedTaskCount());
 371     }
 372 
 373     /**
 374      * getActiveCount increases but doesn't overestimate, when a
 375      * thread becomes active
 376      */
 377     public void testGetActiveCount() throws InterruptedException {
 378         final CountDownLatch done = new CountDownLatch(1);
 379         final ThreadPoolExecutor p = new CustomExecutor(2);
 380         try (PoolCleaner cleaner = cleaner(p, done)) {
 381             final CountDownLatch threadStarted = new CountDownLatch(1);
 382             assertEquals(0, p.getActiveCount());
 383             p.execute(new CheckedRunnable() {
 384                 public void realRun() throws InterruptedException {
 385                     threadStarted.countDown();
 386                     assertEquals(1, p.getActiveCount());
 387                     await(done);
 388                 }});
 389             await(threadStarted);
 390             assertEquals(1, p.getActiveCount());
 391         }
 392     }
 393 
 394     /**
 395      * getCompletedTaskCount increases, but doesn't overestimate,
 396      * when tasks complete
 397      */
 398     public void testGetCompletedTaskCount() throws InterruptedException {
 399         final ThreadPoolExecutor p = new CustomExecutor(2);
 400         try (PoolCleaner cleaner = cleaner(p)) {
 401             final CountDownLatch threadStarted = new CountDownLatch(1);
 402             final CountDownLatch threadProceed = new CountDownLatch(1);
 403             final CountDownLatch threadDone = new CountDownLatch(1);
 404             assertEquals(0, p.getCompletedTaskCount());
 405             p.execute(new CheckedRunnable() {
 406                 public void realRun() throws InterruptedException {
 407                     threadStarted.countDown();
 408                     assertEquals(0, p.getCompletedTaskCount());
 409                     await(threadProceed);
 410                     threadDone.countDown();
 411                 }});
 412             await(threadStarted);
 413             assertEquals(0, p.getCompletedTaskCount());
 414             threadProceed.countDown();
 415             await(threadDone);
 416             long startTime = System.nanoTime();
 417             while (p.getCompletedTaskCount() != 1) {
 418                 if (millisElapsedSince(startTime) > LONG_DELAY_MS)
 419                     fail("timed out");
 420                 Thread.yield();
 421             }
 422         }
 423     }
 424 
 425     /**
 426      * getCorePoolSize returns size given in constructor if not otherwise set
 427      */
 428     public void testGetCorePoolSize() {
 429         final CustomExecutor p = new CustomExecutor(1);
 430         try (PoolCleaner cleaner = cleaner(p)) {
 431             assertEquals(1, p.getCorePoolSize());
 432         }
 433     }
 434 
 435     /**
 436      * getLargestPoolSize increases, but doesn't overestimate, when
 437      * multiple threads active
 438      */
 439     public void testGetLargestPoolSize() throws InterruptedException {
 440         final int THREADS = 3;
 441         final CountDownLatch done = new CountDownLatch(1);
 442         final ThreadPoolExecutor p = new CustomExecutor(THREADS);
 443         try (PoolCleaner cleaner = cleaner(p, done)) {
 444             final CountDownLatch threadsStarted = new CountDownLatch(THREADS);
 445             assertEquals(0, p.getLargestPoolSize());
 446             for (int i = 0; i < THREADS; i++)
 447                 p.execute(new CheckedRunnable() {
 448                     public void realRun() throws InterruptedException {
 449                         threadsStarted.countDown();
 450                         await(done);
 451                         assertEquals(THREADS, p.getLargestPoolSize());
 452                     }});
 453             await(threadsStarted);
 454             assertEquals(THREADS, p.getLargestPoolSize());
 455         }
 456         assertEquals(THREADS, p.getLargestPoolSize());
 457     }
 458 
 459     /**
 460      * getPoolSize increases, but doesn't overestimate, when threads
 461      * become active
 462      */
 463     public void testGetPoolSize() throws InterruptedException {
 464         final CountDownLatch done = new CountDownLatch(1);
 465         final ThreadPoolExecutor p = new CustomExecutor(1);
 466         try (PoolCleaner cleaner = cleaner(p, done)) {
 467             final CountDownLatch threadStarted = new CountDownLatch(1);
 468             assertEquals(0, p.getPoolSize());
 469             p.execute(new CheckedRunnable() {
 470                 public void realRun() throws InterruptedException {
 471                     threadStarted.countDown();
 472                     assertEquals(1, p.getPoolSize());
 473                     await(done);
 474                 }});
 475             await(threadStarted);
 476             assertEquals(1, p.getPoolSize());
 477         }
 478     }
 479 
 480     /**
 481      * getTaskCount increases, but doesn't overestimate, when tasks
 482      * submitted
 483      */
 484     public void testGetTaskCount() throws InterruptedException {
 485         final int TASKS = 3;
 486         final CountDownLatch done = new CountDownLatch(1);
 487         final ThreadPoolExecutor p = new CustomExecutor(1);
 488         try (PoolCleaner cleaner = cleaner(p, done)) {
 489             final CountDownLatch threadStarted = new CountDownLatch(1);
 490             assertEquals(0, p.getTaskCount());
 491             assertEquals(0, p.getCompletedTaskCount());
 492             p.execute(new CheckedRunnable() {
 493                 public void realRun() throws InterruptedException {
 494                     threadStarted.countDown();
 495                     await(done);
 496                 }});
 497             await(threadStarted);
 498             assertEquals(1, p.getTaskCount());
 499             assertEquals(0, p.getCompletedTaskCount());
 500             for (int i = 0; i < TASKS; i++) {
 501                 assertEquals(1 + i, p.getTaskCount());
 502                 p.execute(new CheckedRunnable() {
 503                     public void realRun() throws InterruptedException {
 504                         threadStarted.countDown();
 505                         assertEquals(1 + TASKS, p.getTaskCount());
 506                         await(done);
 507                     }});
 508             }
 509             assertEquals(1 + TASKS, p.getTaskCount());
 510             assertEquals(0, p.getCompletedTaskCount());
 511         }
 512         assertEquals(1 + TASKS, p.getTaskCount());
 513         assertEquals(1 + TASKS, p.getCompletedTaskCount());
 514     }
 515 
 516     /**
 517      * getThreadFactory returns factory in constructor if not set
 518      */
 519     public void testGetThreadFactory() {
 520         final ThreadFactory threadFactory = new SimpleThreadFactory();
 521         final CustomExecutor p = new CustomExecutor(1, threadFactory);
 522         try (PoolCleaner cleaner = cleaner(p)) {
 523             assertSame(threadFactory, p.getThreadFactory());
 524         }
 525     }
 526 
 527     /**
 528      * setThreadFactory sets the thread factory returned by getThreadFactory
 529      */
 530     public void testSetThreadFactory() {
 531         final ThreadFactory threadFactory = new SimpleThreadFactory();
 532         final CustomExecutor p = new CustomExecutor(1);
 533         try (PoolCleaner cleaner = cleaner(p)) {
 534             p.setThreadFactory(threadFactory);
 535             assertSame(threadFactory, p.getThreadFactory());
 536         }
 537     }
 538 
 539     /**
 540      * setThreadFactory(null) throws NPE
 541      */
 542     public void testSetThreadFactoryNull() {
 543         final CustomExecutor p = new CustomExecutor(1);
 544         try (PoolCleaner cleaner = cleaner(p)) {
 545             try {
 546                 p.setThreadFactory(null);
 547                 shouldThrow();
 548             } catch (NullPointerException success) {}
 549         }
 550     }
 551 
 552     /**
 553      * isShutdown is false before shutdown, true after
 554      */
 555     public void testIsShutdown() {
 556         final CustomExecutor p = new CustomExecutor(1);
 557         try (PoolCleaner cleaner = cleaner(p)) {
 558             assertFalse(p.isShutdown());
 559             try { p.shutdown(); } catch (SecurityException ok) { return; }
 560             assertTrue(p.isShutdown());
 561         }
 562     }
 563 
 564     /**
 565      * isTerminated is false before termination, true after
 566      */
 567     public void testIsTerminated() throws InterruptedException {
 568         final CountDownLatch done = new CountDownLatch(1);
 569         final ThreadPoolExecutor p = new CustomExecutor(1);
 570         try (PoolCleaner cleaner = cleaner(p)) {
 571             final CountDownLatch threadStarted = new CountDownLatch(1);
 572             p.execute(new CheckedRunnable() {
 573                 public void realRun() throws InterruptedException {
 574                     assertFalse(p.isTerminated());
 575                     threadStarted.countDown();
 576                     await(done);
 577                 }});
 578             await(threadStarted);
 579             assertFalse(p.isTerminated());
 580             assertFalse(p.isTerminating());
 581             done.countDown();
 582             try { p.shutdown(); } catch (SecurityException ok) { return; }
 583             assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
 584             assertTrue(p.isTerminated());
 585         }
 586     }
 587 
 588     /**
 589      * isTerminating is not true when running or when terminated
 590      */
 591     public void testIsTerminating() throws InterruptedException {
 592         final CountDownLatch done = new CountDownLatch(1);
 593         final ThreadPoolExecutor p = new CustomExecutor(1);
 594         try (PoolCleaner cleaner = cleaner(p)) {
 595             final CountDownLatch threadStarted = new CountDownLatch(1);
 596             assertFalse(p.isTerminating());
 597             p.execute(new CheckedRunnable() {
 598                 public void realRun() throws InterruptedException {
 599                     assertFalse(p.isTerminating());
 600                     threadStarted.countDown();
 601                     await(done);
 602                 }});
 603             await(threadStarted);
 604             assertFalse(p.isTerminating());
 605             done.countDown();
 606             try { p.shutdown(); } catch (SecurityException ok) { return; }
 607             assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
 608             assertTrue(p.isTerminated());
 609             assertFalse(p.isTerminating());
 610         }
 611     }
 612 
 613     /**
 614      * getQueue returns the work queue, which contains queued tasks
 615      */
 616     public void testGetQueue() throws InterruptedException {
 617         final CountDownLatch done = new CountDownLatch(1);
 618         final ScheduledThreadPoolExecutor p = new CustomExecutor(1);
 619         try (PoolCleaner cleaner = cleaner(p, done)) {
 620             final CountDownLatch threadStarted = new CountDownLatch(1);
 621             ScheduledFuture[] tasks = new ScheduledFuture[5];
 622             for (int i = 0; i < tasks.length; i++) {
 623                 Runnable r = new CheckedRunnable() {
 624                     public void realRun() throws InterruptedException {
 625                         threadStarted.countDown();
 626                         await(done);
 627                     }};
 628                 tasks[i] = p.schedule(r, 1, MILLISECONDS);
 629             }
 630             await(threadStarted);
 631             BlockingQueue<Runnable> q = p.getQueue();
 632             assertTrue(q.contains(tasks[tasks.length - 1]));
 633             assertFalse(q.contains(tasks[0]));
 634         }
 635     }
 636 
 637     /**
 638      * remove(task) removes queued task, and fails to remove active task
 639      */
 640     public void testRemove() throws InterruptedException {
 641         final CountDownLatch done = new CountDownLatch(1);
 642         final ScheduledThreadPoolExecutor p = new CustomExecutor(1);
 643         try (PoolCleaner cleaner = cleaner(p, done)) {
 644             ScheduledFuture[] tasks = new ScheduledFuture[5];
 645             final CountDownLatch threadStarted = new CountDownLatch(1);
 646             for (int i = 0; i < tasks.length; i++) {
 647                 Runnable r = new CheckedRunnable() {
 648                     public void realRun() throws InterruptedException {
 649                         threadStarted.countDown();
 650                         await(done);
 651                     }};
 652                 tasks[i] = p.schedule(r, 1, MILLISECONDS);
 653             }
 654             await(threadStarted);
 655             BlockingQueue<Runnable> q = p.getQueue();
 656             assertFalse(p.remove((Runnable)tasks[0]));
 657             assertTrue(q.contains((Runnable)tasks[4]));
 658             assertTrue(q.contains((Runnable)tasks[3]));
 659             assertTrue(p.remove((Runnable)tasks[4]));
 660             assertFalse(p.remove((Runnable)tasks[4]));
 661             assertFalse(q.contains((Runnable)tasks[4]));
 662             assertTrue(q.contains((Runnable)tasks[3]));
 663             assertTrue(p.remove((Runnable)tasks[3]));
 664             assertFalse(q.contains((Runnable)tasks[3]));
 665         }
 666     }
 667 
 668     /**
 669      * purge removes cancelled tasks from the queue
 670      */
 671     public void testPurge() throws InterruptedException {
 672         final ScheduledFuture[] tasks = new ScheduledFuture[5];
 673         final Runnable releaser = new Runnable() { public void run() {
 674             for (ScheduledFuture task : tasks)
 675                 if (task != null) task.cancel(true); }};
 676         final CustomExecutor p = new CustomExecutor(1);
 677         try (PoolCleaner cleaner = cleaner(p, releaser)) {
 678             for (int i = 0; i < tasks.length; i++)
 679                 tasks[i] = p.schedule(possiblyInterruptedRunnable(SMALL_DELAY_MS),
 680                                       LONG_DELAY_MS, MILLISECONDS);
 681             int max = tasks.length;
 682             if (tasks[4].cancel(true)) --max;
 683             if (tasks[3].cancel(true)) --max;
 684             // There must eventually be an interference-free point at
 685             // which purge will not fail. (At worst, when queue is empty.)
 686             long startTime = System.nanoTime();
 687             do {
 688                 p.purge();
 689                 long count = p.getTaskCount();
 690                 if (count == max)
 691                     return;
 692             } while (millisElapsedSince(startTime) < LONG_DELAY_MS);
 693             fail("Purge failed to remove cancelled tasks");
 694         }
 695     }
 696 
 697     /**
 698      * shutdownNow returns a list containing tasks that were not run,
 699      * and those tasks are drained from the queue
 700      */
 701     public void testShutdownNow() throws InterruptedException {
 702         final int poolSize = 2;
 703         final int count = 5;
 704         final AtomicInteger ran = new AtomicInteger(0);
 705         final CustomExecutor p = new CustomExecutor(poolSize);
 706         final CountDownLatch threadsStarted = new CountDownLatch(poolSize);
 707         Runnable waiter = new CheckedRunnable() { public void realRun() {
 708             threadsStarted.countDown();
 709             try {
 710                 MILLISECONDS.sleep(2 * LONG_DELAY_MS);
 711             } catch (InterruptedException success) {}
 712             ran.getAndIncrement();
 713         }};
 714         for (int i = 0; i < count; i++)
 715             p.execute(waiter);
 716         await(threadsStarted);
 717         assertEquals(poolSize, p.getActiveCount());
 718         assertEquals(0, p.getCompletedTaskCount());
 719         final List<Runnable> queuedTasks;
 720         try {
 721             queuedTasks = p.shutdownNow();
 722         } catch (SecurityException ok) {
 723             return; // Allowed in case test doesn't have privs
 724         }
 725         assertTrue(p.isShutdown());
 726         assertTrue(p.getQueue().isEmpty());
 727         assertEquals(count - poolSize, queuedTasks.size());
 728         assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
 729         assertTrue(p.isTerminated());
 730         assertEquals(poolSize, ran.get());
 731         assertEquals(poolSize, p.getCompletedTaskCount());
 732     }
 733 
 734     /**
 735      * shutdownNow returns a list containing tasks that were not run,
 736      * and those tasks are drained from the queue
 737      */
 738     public void testShutdownNow_delayedTasks() throws InterruptedException {
 739         final CustomExecutor p = new CustomExecutor(1);
 740         List<ScheduledFuture> tasks = new ArrayList<>();
 741         for (int i = 0; i < 3; i++) {
 742             Runnable r = new NoOpRunnable();
 743             tasks.add(p.schedule(r, 9, SECONDS));
 744             tasks.add(p.scheduleAtFixedRate(r, 9, 9, SECONDS));
 745             tasks.add(p.scheduleWithFixedDelay(r, 9, 9, SECONDS));
 746         }
 747         if (testImplementationDetails)
 748             assertEquals(new HashSet(tasks), new HashSet(p.getQueue()));
 749         final List<Runnable> queuedTasks;
 750         try {
 751             queuedTasks = p.shutdownNow();
 752         } catch (SecurityException ok) {
 753             return; // Allowed in case test doesn't have privs
 754         }
 755         assertTrue(p.isShutdown());
 756         assertTrue(p.getQueue().isEmpty());
 757         if (testImplementationDetails)
 758             assertEquals(new HashSet(tasks), new HashSet(queuedTasks));
 759         assertEquals(tasks.size(), queuedTasks.size());
 760         for (ScheduledFuture task : tasks) {
 761             assertFalse(((CustomTask)task).ran);
 762             assertFalse(task.isDone());
 763             assertFalse(task.isCancelled());
 764         }
 765         assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
 766         assertTrue(p.isTerminated());
 767     }
 768 
 769     /**
 770      * By default, periodic tasks are cancelled at shutdown.
 771      * By default, delayed tasks keep running after shutdown.
 772      * Check that changing the default values work:
 773      * - setExecuteExistingDelayedTasksAfterShutdownPolicy
 774      * - setContinueExistingPeriodicTasksAfterShutdownPolicy
 775      */
 776     @SuppressWarnings("FutureReturnValueIgnored")
 777     public void testShutdown_cancellation() throws Exception {
 778         final int poolSize = 4;
 779         final CustomExecutor p = new CustomExecutor(poolSize);
 780         final BlockingQueue<Runnable> q = p.getQueue();
 781         final ThreadLocalRandom rnd = ThreadLocalRandom.current();
 782         final long delay = rnd.nextInt(2);
 783         final int rounds = rnd.nextInt(1, 3);
 784         final boolean effectiveDelayedPolicy;
 785         final boolean effectivePeriodicPolicy;
 786         final boolean effectiveRemovePolicy;
 787 
 788         if (rnd.nextBoolean())
 789             p.setExecuteExistingDelayedTasksAfterShutdownPolicy(
 790                 effectiveDelayedPolicy = rnd.nextBoolean());
 791         else
 792             effectiveDelayedPolicy = true;
 793         assertEquals(effectiveDelayedPolicy,
 794                      p.getExecuteExistingDelayedTasksAfterShutdownPolicy());
 795 
 796         if (rnd.nextBoolean())
 797             p.setContinueExistingPeriodicTasksAfterShutdownPolicy(
 798                 effectivePeriodicPolicy = rnd.nextBoolean());
 799         else
 800             effectivePeriodicPolicy = false;
 801         assertEquals(effectivePeriodicPolicy,
 802                      p.getContinueExistingPeriodicTasksAfterShutdownPolicy());
 803 
 804         if (rnd.nextBoolean())
 805             p.setRemoveOnCancelPolicy(
 806                 effectiveRemovePolicy = rnd.nextBoolean());
 807         else
 808             effectiveRemovePolicy = false;
 809         assertEquals(effectiveRemovePolicy,
 810                      p.getRemoveOnCancelPolicy());
 811 
 812         final boolean periodicTasksContinue = effectivePeriodicPolicy && rnd.nextBoolean();
 813 
 814         // Strategy: Wedge the pool with one wave of "blocker" tasks,
 815         // then add a second wave that waits in the queue until unblocked.
 816         final AtomicInteger ran = new AtomicInteger(0);
 817         final CountDownLatch poolBlocked = new CountDownLatch(poolSize);
 818         final CountDownLatch unblock = new CountDownLatch(1);
 819         final RuntimeException exception = new RuntimeException();
 820 
 821         class Task implements Runnable {
 822             public void run() {
 823                 try {
 824                     ran.getAndIncrement();
 825                     poolBlocked.countDown();
 826                     await(unblock);
 827                 } catch (Throwable fail) { threadUnexpectedException(fail); }
 828             }
 829         }
 830 
 831         class PeriodicTask extends Task {
 832             PeriodicTask(int rounds) { this.rounds = rounds; }
 833             int rounds;
 834             public void run() {
 835                 if (--rounds == 0) super.run();
 836                 // throw exception to surely terminate this periodic task,
 837                 // but in a separate execution and in a detectable way.
 838                 if (rounds == -1) throw exception;
 839             }
 840         }
 841 
 842         Runnable task = new Task();
 843 
 844         List<Future<?>> immediates = new ArrayList<>();
 845         List<Future<?>> delayeds   = new ArrayList<>();
 846         List<Future<?>> periodics  = new ArrayList<>();
 847 
 848         immediates.add(p.submit(task));
 849         delayeds.add(p.schedule(task, delay, MILLISECONDS));
 850         periodics.add(p.scheduleAtFixedRate(
 851                           new PeriodicTask(rounds), delay, 1, MILLISECONDS));
 852         periodics.add(p.scheduleWithFixedDelay(
 853                           new PeriodicTask(rounds), delay, 1, MILLISECONDS));
 854 
 855         await(poolBlocked);
 856 
 857         assertEquals(poolSize, ran.get());
 858         assertEquals(poolSize, p.getActiveCount());
 859         assertTrue(q.isEmpty());
 860 
 861         // Add second wave of tasks.
 862         immediates.add(p.submit(task));
 863         delayeds.add(p.schedule(task, effectiveDelayedPolicy ? delay : LONG_DELAY_MS, MILLISECONDS));
 864         periodics.add(p.scheduleAtFixedRate(
 865                           new PeriodicTask(rounds), delay, 1, MILLISECONDS));
 866         periodics.add(p.scheduleWithFixedDelay(
 867                           new PeriodicTask(rounds), delay, 1, MILLISECONDS));
 868 
 869         assertEquals(poolSize, q.size());
 870         assertEquals(poolSize, ran.get());
 871 
 872         immediates.forEach(
 873             f -> assertTrue(((ScheduledFuture)f).getDelay(NANOSECONDS) <= 0L));
 874 
 875         Stream.of(immediates, delayeds, periodics).flatMap(Collection::stream)
 876             .forEach(f -> assertFalse(f.isDone()));
 877 
 878         try { p.shutdown(); } catch (SecurityException ok) { return; }
 879         assertTrue(p.isShutdown());
 880         assertTrue(p.isTerminating());
 881         assertFalse(p.isTerminated());
 882 
 883         if (rnd.nextBoolean())
 884             assertThrows(
 885                 RejectedExecutionException.class,
 886                 () -> p.submit(task),
 887                 () -> p.schedule(task, 1, SECONDS),
 888                 () -> p.scheduleAtFixedRate(
 889                     new PeriodicTask(1), 1, 1, SECONDS),
 890                 () -> p.scheduleWithFixedDelay(
 891                     new PeriodicTask(2), 1, 1, SECONDS));
 892 
 893         assertTrue(q.contains(immediates.get(1)));
 894         assertTrue(!effectiveDelayedPolicy
 895                    ^ q.contains(delayeds.get(1)));
 896         assertTrue(!effectivePeriodicPolicy
 897                    ^ q.containsAll(periodics.subList(2, 4)));
 898 
 899         immediates.forEach(f -> assertFalse(f.isDone()));
 900 
 901         assertFalse(delayeds.get(0).isDone());
 902         if (effectiveDelayedPolicy)
 903             assertFalse(delayeds.get(1).isDone());
 904         else
 905             assertTrue(delayeds.get(1).isCancelled());
 906 
 907         if (effectivePeriodicPolicy)
 908             periodics.forEach(
 909                 f -> {
 910                     assertFalse(f.isDone());
 911                     if (!periodicTasksContinue) {
 912                         assertTrue(f.cancel(false));
 913                         assertTrue(f.isCancelled());
 914                     }
 915                 });
 916         else {
 917             periodics.subList(0, 2).forEach(f -> assertFalse(f.isDone()));
 918             periodics.subList(2, 4).forEach(f -> assertTrue(f.isCancelled()));
 919         }
 920 
 921         unblock.countDown();    // Release all pool threads
 922 
 923         assertTrue(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
 924         assertFalse(p.isTerminating());
 925         assertTrue(p.isTerminated());
 926 
 927         assertTrue(q.isEmpty());
 928 
 929         Stream.of(immediates, delayeds, periodics).flatMap(Collection::stream)
 930             .forEach(f -> assertTrue(f.isDone()));
 931 
 932         for (Future<?> f : immediates) assertNull(f.get());
 933 
 934         assertNull(delayeds.get(0).get());
 935         if (effectiveDelayedPolicy)
 936             assertNull(delayeds.get(1).get());
 937         else
 938             assertTrue(delayeds.get(1).isCancelled());
 939 
 940         if (periodicTasksContinue)
 941             periodics.forEach(
 942                 f -> {
 943                     try { f.get(); }
 944                     catch (ExecutionException success) {
 945                         assertSame(exception, success.getCause());
 946                     }
 947                     catch (Throwable fail) { threadUnexpectedException(fail); }
 948                 });
 949         else
 950             periodics.forEach(f -> assertTrue(f.isCancelled()));
 951 
 952         assertEquals(poolSize + 1
 953                      + (effectiveDelayedPolicy ? 1 : 0)
 954                      + (periodicTasksContinue ? 2 : 0),
 955                      ran.get());
 956     }
 957 
 958     /**
 959      * completed submit of callable returns result
 960      */
 961     public void testSubmitCallable() throws Exception {
 962         final ExecutorService e = new CustomExecutor(2);
 963         try (PoolCleaner cleaner = cleaner(e)) {
 964             Future<String> future = e.submit(new StringTask());
 965             String result = future.get();
 966             assertSame(TEST_STRING, result);
 967         }
 968     }
 969 
 970     /**
 971      * completed submit of runnable returns successfully
 972      */
 973     public void testSubmitRunnable() throws Exception {
 974         final ExecutorService e = new CustomExecutor(2);
 975         try (PoolCleaner cleaner = cleaner(e)) {
 976             Future<?> future = e.submit(new NoOpRunnable());
 977             future.get();
 978             assertTrue(future.isDone());
 979         }
 980     }
 981 
 982     /**
 983      * completed submit of (runnable, result) returns result
 984      */
 985     public void testSubmitRunnable2() throws Exception {
 986         final ExecutorService e = new CustomExecutor(2);
 987         try (PoolCleaner cleaner = cleaner(e)) {
 988             Future<String> future = e.submit(new NoOpRunnable(), TEST_STRING);
 989             String result = future.get();
 990             assertSame(TEST_STRING, result);
 991         }
 992     }
 993 
 994     /**
 995      * invokeAny(null) throws NPE
 996      */
 997     public void testInvokeAny1() throws Exception {
 998         final ExecutorService e = new CustomExecutor(2);
 999         try (PoolCleaner cleaner = cleaner(e)) {
1000             try {
1001                 e.invokeAny(null);
1002                 shouldThrow();
1003             } catch (NullPointerException success) {}
1004         }
1005     }
1006 
1007     /**
1008      * invokeAny(empty collection) throws IllegalArgumentException
1009      */
1010     public void testInvokeAny2() throws Exception {
1011         final ExecutorService e = new CustomExecutor(2);
1012         try (PoolCleaner cleaner = cleaner(e)) {
1013             try {
1014                 e.invokeAny(new ArrayList<Callable<String>>());
1015                 shouldThrow();
1016             } catch (IllegalArgumentException success) {}
1017         }
1018     }
1019 
1020     /**
1021      * invokeAny(c) throws NPE if c has null elements
1022      */
1023     public void testInvokeAny3() throws Exception {
1024         final CountDownLatch latch = new CountDownLatch(1);
1025         final ExecutorService e = new CustomExecutor(2);
1026         try (PoolCleaner cleaner = cleaner(e)) {
1027             List<Callable<String>> l = new ArrayList<>();
1028             l.add(latchAwaitingStringTask(latch));
1029             l.add(null);
1030             try {
1031                 e.invokeAny(l);
1032                 shouldThrow();
1033             } catch (NullPointerException success) {}
1034             latch.countDown();
1035         }
1036     }
1037 
1038     /**
1039      * invokeAny(c) throws ExecutionException if no task completes
1040      */
1041     public void testInvokeAny4() throws Exception {
1042         final ExecutorService e = new CustomExecutor(2);
1043         try (PoolCleaner cleaner = cleaner(e)) {
1044             List<Callable<String>> l = new ArrayList<>();
1045             l.add(new NPETask());
1046             try {
1047                 e.invokeAny(l);
1048                 shouldThrow();
1049             } catch (ExecutionException success) {
1050                 assertTrue(success.getCause() instanceof NullPointerException);
1051             }
1052         }
1053     }
1054 
1055     /**
1056      * invokeAny(c) returns result of some task
1057      */
1058     public void testInvokeAny5() throws Exception {
1059         final ExecutorService e = new CustomExecutor(2);
1060         try (PoolCleaner cleaner = cleaner(e)) {
1061             List<Callable<String>> l = new ArrayList<>();
1062             l.add(new StringTask());
1063             l.add(new StringTask());
1064             String result = e.invokeAny(l);
1065             assertSame(TEST_STRING, result);
1066         }
1067     }
1068 
1069     /**
1070      * invokeAll(null) throws NPE
1071      */
1072     public void testInvokeAll1() throws Exception {
1073         final ExecutorService e = new CustomExecutor(2);
1074         try (PoolCleaner cleaner = cleaner(e)) {
1075             try {
1076                 e.invokeAll(null);
1077                 shouldThrow();
1078             } catch (NullPointerException success) {}
1079         }
1080     }
1081 
1082     /**
1083      * invokeAll(empty collection) returns empty list
1084      */
1085     public void testInvokeAll2() throws Exception {
1086         final ExecutorService e = new CustomExecutor(2);
1087         final Collection<Callable<String>> emptyCollection
1088             = Collections.emptyList();
1089         try (PoolCleaner cleaner = cleaner(e)) {
1090             List<Future<String>> r = e.invokeAll(emptyCollection);
1091             assertTrue(r.isEmpty());
1092         }
1093     }
1094 
1095     /**
1096      * invokeAll(c) throws NPE if c has null elements
1097      */
1098     public void testInvokeAll3() throws Exception {
1099         final ExecutorService e = new CustomExecutor(2);
1100         try (PoolCleaner cleaner = cleaner(e)) {
1101             List<Callable<String>> l = new ArrayList<>();
1102             l.add(new StringTask());
1103             l.add(null);
1104             try {
1105                 e.invokeAll(l);
1106                 shouldThrow();
1107             } catch (NullPointerException success) {}
1108         }
1109     }
1110 
1111     /**
1112      * get of invokeAll(c) throws exception on failed task
1113      */
1114     public void testInvokeAll4() throws Exception {
1115         final ExecutorService e = new CustomExecutor(2);
1116         try (PoolCleaner cleaner = cleaner(e)) {
1117             List<Callable<String>> l = new ArrayList<>();
1118             l.add(new NPETask());
1119             List<Future<String>> futures = e.invokeAll(l);
1120             assertEquals(1, futures.size());
1121             try {
1122                 futures.get(0).get();
1123                 shouldThrow();
1124             } catch (ExecutionException success) {
1125                 assertTrue(success.getCause() instanceof NullPointerException);
1126             }
1127         }
1128     }
1129 
1130     /**
1131      * invokeAll(c) returns results of all completed tasks
1132      */
1133     public void testInvokeAll5() throws Exception {
1134         final ExecutorService e = new CustomExecutor(2);
1135         try (PoolCleaner cleaner = cleaner(e)) {
1136             List<Callable<String>> l = new ArrayList<>();
1137             l.add(new StringTask());
1138             l.add(new StringTask());
1139             List<Future<String>> futures = e.invokeAll(l);
1140             assertEquals(2, futures.size());
1141             for (Future<String> future : futures)
1142                 assertSame(TEST_STRING, future.get());
1143         }
1144     }
1145 
1146     /**
1147      * timed invokeAny(null) throws NPE
1148      */
1149     public void testTimedInvokeAny1() throws Exception {
1150         final ExecutorService e = new CustomExecutor(2);
1151         try (PoolCleaner cleaner = cleaner(e)) {
1152             try {
1153                 e.invokeAny(null, randomTimeout(), randomTimeUnit());
1154                 shouldThrow();
1155             } catch (NullPointerException success) {}
1156         }
1157     }
1158 
1159     /**
1160      * timed invokeAny(,,null) throws NPE
1161      */
1162     public void testTimedInvokeAnyNullTimeUnit() throws Exception {
1163         final ExecutorService e = new CustomExecutor(2);
1164         try (PoolCleaner cleaner = cleaner(e)) {
1165             List<Callable<String>> l = new ArrayList<>();
1166             l.add(new StringTask());
1167             try {
1168                 e.invokeAny(l, randomTimeout(), null);
1169                 shouldThrow();
1170             } catch (NullPointerException success) {}
1171         }
1172     }
1173 
1174     /**
1175      * timed invokeAny(empty collection) throws IllegalArgumentException
1176      */
1177     public void testTimedInvokeAny2() throws Exception {
1178         final ExecutorService e = new CustomExecutor(2);
1179         final Collection<Callable<String>> emptyCollection
1180             = Collections.emptyList();
1181         try (PoolCleaner cleaner = cleaner(e)) {
1182             try {
1183                 e.invokeAny(emptyCollection, randomTimeout(), randomTimeUnit());
1184                 shouldThrow();
1185             } catch (IllegalArgumentException success) {}
1186         }
1187     }
1188 
1189     /**
1190      * timed invokeAny(c) throws NPE if c has null elements
1191      */
1192     public void testTimedInvokeAny3() throws Exception {
1193         CountDownLatch latch = new CountDownLatch(1);
1194         final ExecutorService e = new CustomExecutor(2);
1195         try (PoolCleaner cleaner = cleaner(e)) {
1196             List<Callable<String>> l = new ArrayList<>();
1197             l.add(latchAwaitingStringTask(latch));
1198             l.add(null);
1199             try {
1200                 e.invokeAny(l, randomTimeout(), randomTimeUnit());
1201                 shouldThrow();
1202             } catch (NullPointerException success) {}
1203             latch.countDown();
1204         }
1205     }
1206 
1207     /**
1208      * timed invokeAny(c) throws ExecutionException if no task completes
1209      */
1210     public void testTimedInvokeAny4() throws Exception {
1211         final ExecutorService e = new CustomExecutor(2);
1212         try (PoolCleaner cleaner = cleaner(e)) {
1213             long startTime = System.nanoTime();
1214             List<Callable<String>> l = new ArrayList<>();
1215             l.add(new NPETask());
1216             try {
1217                 e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
1218                 shouldThrow();
1219             } catch (ExecutionException success) {
1220                 assertTrue(success.getCause() instanceof NullPointerException);
1221             }
1222             assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
1223         }
1224     }
1225 
1226     /**
1227      * timed invokeAny(c) returns result of some task
1228      */
1229     public void testTimedInvokeAny5() throws Exception {
1230         final ExecutorService e = new CustomExecutor(2);
1231         try (PoolCleaner cleaner = cleaner(e)) {
1232             long startTime = System.nanoTime();
1233             List<Callable<String>> l = new ArrayList<>();
1234             l.add(new StringTask());
1235             l.add(new StringTask());
1236             String result = e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
1237             assertSame(TEST_STRING, result);
1238             assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
1239         }
1240     }
1241 
1242     /**
1243      * timed invokeAll(null) throws NullPointerException
1244      */
1245     public void testTimedInvokeAll1() throws Exception {
1246         final ExecutorService e = new CustomExecutor(2);
1247         try (PoolCleaner cleaner = cleaner(e)) {
1248             try {
1249                 e.invokeAll(null, randomTimeout(), randomTimeUnit());
1250                 shouldThrow();
1251             } catch (NullPointerException success) {}
1252         }
1253     }
1254 
1255     /**
1256      * timed invokeAll(,,null) throws NullPointerException
1257      */
1258     public void testTimedInvokeAllNullTimeUnit() throws Exception {
1259         final ExecutorService e = new CustomExecutor(2);
1260         try (PoolCleaner cleaner = cleaner(e)) {
1261             List<Callable<String>> l = new ArrayList<>();
1262             l.add(new StringTask());
1263             try {
1264                 e.invokeAll(l, randomTimeout(), null);
1265                 shouldThrow();
1266             } catch (NullPointerException success) {}
1267         }
1268     }
1269 
1270     /**
1271      * timed invokeAll(empty collection) returns empty list
1272      */
1273     public void testTimedInvokeAll2() throws Exception {
1274         final ExecutorService e = new CustomExecutor(2);
1275         final Collection<Callable<String>> emptyCollection
1276             = Collections.emptyList();
1277         try (PoolCleaner cleaner = cleaner(e)) {
1278             List<Future<String>> r =
1279                 e.invokeAll(emptyCollection, randomTimeout(), randomTimeUnit());
1280             assertTrue(r.isEmpty());
1281         }
1282     }
1283 
1284     /**
1285      * timed invokeAll(c) throws NPE if c has null elements
1286      */
1287     public void testTimedInvokeAll3() throws Exception {
1288         final ExecutorService e = new CustomExecutor(2);
1289         try (PoolCleaner cleaner = cleaner(e)) {
1290             List<Callable<String>> l = new ArrayList<>();
1291             l.add(new StringTask());
1292             l.add(null);
1293             try {
1294                 e.invokeAll(l, randomTimeout(), randomTimeUnit());
1295                 shouldThrow();
1296             } catch (NullPointerException success) {}
1297         }
1298     }
1299 
1300     /**
1301      * get of element of invokeAll(c) throws exception on failed task
1302      */
1303     public void testTimedInvokeAll4() throws Exception {
1304         final ExecutorService e = new CustomExecutor(2);
1305         final Collection<Callable<String>> c = new ArrayList<>();
1306         c.add(new NPETask());
1307         try (PoolCleaner cleaner = cleaner(e)) {
1308             List<Future<String>> futures =
1309                 e.invokeAll(c, LONG_DELAY_MS, MILLISECONDS);
1310             assertEquals(1, futures.size());
1311             try {
1312                 futures.get(0).get();
1313                 shouldThrow();
1314             } catch (ExecutionException success) {
1315                 assertTrue(success.getCause() instanceof NullPointerException);
1316             }
1317         }
1318     }
1319 
1320     /**
1321      * timed invokeAll(c) returns results of all completed tasks
1322      */
1323     public void testTimedInvokeAll5() throws Exception {
1324         final ExecutorService e = new CustomExecutor(2);
1325         try (PoolCleaner cleaner = cleaner(e)) {
1326             List<Callable<String>> l = new ArrayList<>();
1327             l.add(new StringTask());
1328             l.add(new StringTask());
1329             List<Future<String>> futures =
1330                 e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS);
1331             assertEquals(2, futures.size());
1332             for (Future<String> future : futures)
1333                 assertSame(TEST_STRING, future.get());
1334         }
1335     }
1336 
1337     /**
1338      * timed invokeAll(c) cancels tasks not completed by timeout
1339      */
1340     public void testTimedInvokeAll6() throws Exception {
1341         for (long timeout = timeoutMillis();;) {
1342             final CountDownLatch done = new CountDownLatch(1);
1343             final Callable<String> waiter = new CheckedCallable<String>() {
1344                 public String realCall() {
1345                     try { done.await(LONG_DELAY_MS, MILLISECONDS); }
1346                     catch (InterruptedException ok) {}
1347                     return "1"; }};
1348             final ExecutorService p = new CustomExecutor(2);
1349             try (PoolCleaner cleaner = cleaner(p, done)) {
1350                 List<Callable<String>> tasks = new ArrayList<>();
1351                 tasks.add(new StringTask("0"));
1352                 tasks.add(waiter);
1353                 tasks.add(new StringTask("2"));
1354                 long startTime = System.nanoTime();
1355                 List<Future<String>> futures =
1356                     p.invokeAll(tasks, timeout, MILLISECONDS);
1357                 assertEquals(tasks.size(), futures.size());
1358                 assertTrue(millisElapsedSince(startTime) >= timeout);
1359                 for (Future future : futures)
1360                     assertTrue(future.isDone());
1361                 assertTrue(futures.get(1).isCancelled());
1362                 try {
1363                     assertEquals("0", futures.get(0).get());
1364                     assertEquals("2", futures.get(2).get());
1365                     break;
1366                 } catch (CancellationException retryWithLongerTimeout) {
1367                     timeout *= 2;
1368                     if (timeout >= LONG_DELAY_MS / 2)
1369                         fail("expected exactly one task to be cancelled");
1370                 }
1371             }
1372         }
1373     }
1374 
1375 }