ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/ScheduledExecutorSubclassTest.java
Revision: 1.66
Committed: Sat Apr 1 16:28:31 2017 UTC (7 years, 1 month ago) by jsr166
Branch: MAIN
Changes since 1.65: +162 -65 lines
Log Message:
testShutdown_cancellation: sync with ScheduledExecutorTest

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