ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/ScheduledExecutorSubclassTest.java
Revision: 1.61
Committed: Mon Feb 22 23:16:06 2016 UTC (8 years, 2 months ago) by jsr166
Branch: MAIN
Changes since 1.60: +47 -21 lines
Log Message:
make tests more robust against slow VMs; fix for JDK-8150319: ScheduledExecutorTest:testFixedDelaySequence timeout with slow VMs

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