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