ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/ScheduledExecutorSubclassTest.java
Revision: 1.53
Committed: Tue Oct 6 05:22:25 2015 UTC (8 years, 7 months ago) by jsr166
Branch: MAIN
Changes since 1.52: +2 -2 lines
Log Message:
improve test diagnosability

File Contents

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