ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/ScheduledExecutorSubclassTest.java
Revision: 1.49
Committed: Mon Oct 5 21:54:33 2015 UTC (8 years, 7 months ago) by jsr166
Branch: MAIN
Changes since 1.48: +9 -10 lines
Log Message:
improve testPurge

File Contents

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