ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/ScheduledExecutorSubclassTest.java
Revision: 1.69
Committed: Mon Jul 17 22:27:31 2017 UTC (6 years, 9 months ago) by jsr166
Branch: MAIN
Changes since 1.68: +47 -89 lines
Log Message:
improve executor tests, en passant removing [FutureReturnValueIgnored] warnings

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