blob: ae475f1a78c0b6105115a044876e56a363f4b7b2 [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 * Other contributors include Andrew Wright, Jeffrey Hayes,
6 * Pat Fisher, Mike Judd.
7 */
8
9package jsr166;
10
Calin Juravle8f0d92b2013-08-01 17:26:00 +010011import static java.util.concurrent.TimeUnit.MILLISECONDS;
Narayan Kamath8e9a0e92015-04-28 11:40:00 +010012
13import java.security.AccessControlContext;
14import java.security.AccessControlException;
15import java.security.AccessController;
16import java.security.PrivilegedAction;
17import java.security.PrivilegedExceptionAction;
18import java.util.ArrayList;
19import java.util.List;
20import java.util.concurrent.Callable;
21import java.util.concurrent.CountDownLatch;
22import java.util.concurrent.Executors;
23import java.util.concurrent.ExecutorService;
24import java.util.concurrent.Future;
25import java.util.concurrent.ScheduledExecutorService;
26import java.util.concurrent.ThreadPoolExecutor;
27
28import junit.framework.Test;
29import junit.framework.TestSuite;
Calin Juravle8f0d92b2013-08-01 17:26:00 +010030
31public class ExecutorsTest extends JSR166TestCase {
Narayan Kamath8e9a0e92015-04-28 11:40:00 +010032 // android-note: Removed because the CTS runner does a bad job of
33 // retrying tests that have suite() declarations.
34 //
35 // public static void main(String[] args) {
36 // main(suite(), args);
37 // }
38 // public static Test suite() {
39 // return new TestSuite(...);
40 // }
Calin Juravle8f0d92b2013-08-01 17:26:00 +010041
42 /**
43 * A newCachedThreadPool can execute runnables
44 */
45 public void testNewCachedThreadPool1() {
46 ExecutorService e = Executors.newCachedThreadPool();
47 e.execute(new NoOpRunnable());
48 e.execute(new NoOpRunnable());
49 e.execute(new NoOpRunnable());
50 joinPool(e);
51 }
52
53 /**
54 * A newCachedThreadPool with given ThreadFactory can execute runnables
55 */
56 public void testNewCachedThreadPool2() {
57 ExecutorService e = Executors.newCachedThreadPool(new SimpleThreadFactory());
58 e.execute(new NoOpRunnable());
59 e.execute(new NoOpRunnable());
60 e.execute(new NoOpRunnable());
61 joinPool(e);
62 }
63
64 /**
65 * A newCachedThreadPool with null ThreadFactory throws NPE
66 */
67 public void testNewCachedThreadPool3() {
68 try {
69 ExecutorService e = Executors.newCachedThreadPool(null);
70 shouldThrow();
71 } catch (NullPointerException success) {}
72 }
73
74 /**
75 * A new SingleThreadExecutor can execute runnables
76 */
77 public void testNewSingleThreadExecutor1() {
78 ExecutorService e = Executors.newSingleThreadExecutor();
79 e.execute(new NoOpRunnable());
80 e.execute(new NoOpRunnable());
81 e.execute(new NoOpRunnable());
82 joinPool(e);
83 }
84
85 /**
86 * A new SingleThreadExecutor with given ThreadFactory can execute runnables
87 */
88 public void testNewSingleThreadExecutor2() {
89 ExecutorService e = Executors.newSingleThreadExecutor(new SimpleThreadFactory());
90 e.execute(new NoOpRunnable());
91 e.execute(new NoOpRunnable());
92 e.execute(new NoOpRunnable());
93 joinPool(e);
94 }
95
96 /**
97 * A new SingleThreadExecutor with null ThreadFactory throws NPE
98 */
99 public void testNewSingleThreadExecutor3() {
100 try {
101 ExecutorService e = Executors.newSingleThreadExecutor(null);
102 shouldThrow();
103 } catch (NullPointerException success) {}
104 }
105
106 /**
107 * A new SingleThreadExecutor cannot be casted to concrete implementation
108 */
109 public void testCastNewSingleThreadExecutor() {
110 ExecutorService e = Executors.newSingleThreadExecutor();
111 try {
112 ThreadPoolExecutor tpe = (ThreadPoolExecutor)e;
113 shouldThrow();
114 } catch (ClassCastException success) {
115 } finally {
116 joinPool(e);
117 }
118 }
119
120 /**
121 * A new newFixedThreadPool can execute runnables
122 */
123 public void testNewFixedThreadPool1() {
124 ExecutorService e = Executors.newFixedThreadPool(2);
125 e.execute(new NoOpRunnable());
126 e.execute(new NoOpRunnable());
127 e.execute(new NoOpRunnable());
128 joinPool(e);
129 }
130
131 /**
132 * A new newFixedThreadPool with given ThreadFactory can execute runnables
133 */
134 public void testNewFixedThreadPool2() {
135 ExecutorService e = Executors.newFixedThreadPool(2, new SimpleThreadFactory());
136 e.execute(new NoOpRunnable());
137 e.execute(new NoOpRunnable());
138 e.execute(new NoOpRunnable());
139 joinPool(e);
140 }
141
142 /**
143 * A new newFixedThreadPool with null ThreadFactory throws NPE
144 */
145 public void testNewFixedThreadPool3() {
146 try {
147 ExecutorService e = Executors.newFixedThreadPool(2, null);
148 shouldThrow();
149 } catch (NullPointerException success) {}
150 }
151
152 /**
153 * A new newFixedThreadPool with 0 threads throws IAE
154 */
155 public void testNewFixedThreadPool4() {
156 try {
157 ExecutorService e = Executors.newFixedThreadPool(0);
158 shouldThrow();
159 } catch (IllegalArgumentException success) {}
160 }
161
162 /**
163 * An unconfigurable newFixedThreadPool can execute runnables
164 */
165 public void testUnconfigurableExecutorService() {
166 ExecutorService e = Executors.unconfigurableExecutorService(Executors.newFixedThreadPool(2));
167 e.execute(new NoOpRunnable());
168 e.execute(new NoOpRunnable());
169 e.execute(new NoOpRunnable());
170 joinPool(e);
171 }
172
173 /**
174 * unconfigurableExecutorService(null) throws NPE
175 */
176 public void testUnconfigurableExecutorServiceNPE() {
177 try {
178 ExecutorService e = Executors.unconfigurableExecutorService(null);
179 shouldThrow();
180 } catch (NullPointerException success) {}
181 }
182
183 /**
184 * unconfigurableScheduledExecutorService(null) throws NPE
185 */
186 public void testUnconfigurableScheduledExecutorServiceNPE() {
187 try {
188 ExecutorService e = Executors.unconfigurableScheduledExecutorService(null);
189 shouldThrow();
190 } catch (NullPointerException success) {}
191 }
192
193 /**
194 * a newSingleThreadScheduledExecutor successfully runs delayed task
195 */
196 public void testNewSingleThreadScheduledExecutor() throws Exception {
197 ScheduledExecutorService p = Executors.newSingleThreadScheduledExecutor();
198 try {
199 final CountDownLatch proceed = new CountDownLatch(1);
200 final Runnable task = new CheckedRunnable() {
201 public void realRun() {
202 await(proceed);
203 }};
204 long startTime = System.nanoTime();
205 Future f = p.schedule(Executors.callable(task, Boolean.TRUE),
206 timeoutMillis(), MILLISECONDS);
207 assertFalse(f.isDone());
208 proceed.countDown();
209 assertSame(Boolean.TRUE, f.get(LONG_DELAY_MS, MILLISECONDS));
210 assertSame(Boolean.TRUE, f.get());
211 assertTrue(f.isDone());
212 assertFalse(f.isCancelled());
213 assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
214 } finally {
215 joinPool(p);
216 }
217 }
218
219 /**
220 * a newScheduledThreadPool successfully runs delayed task
221 */
222 public void testNewScheduledThreadPool() throws Exception {
223 ScheduledExecutorService p = Executors.newScheduledThreadPool(2);
224 try {
225 final CountDownLatch proceed = new CountDownLatch(1);
226 final Runnable task = new CheckedRunnable() {
227 public void realRun() {
228 await(proceed);
229 }};
230 long startTime = System.nanoTime();
231 Future f = p.schedule(Executors.callable(task, Boolean.TRUE),
232 timeoutMillis(), MILLISECONDS);
233 assertFalse(f.isDone());
234 proceed.countDown();
235 assertSame(Boolean.TRUE, f.get(LONG_DELAY_MS, MILLISECONDS));
236 assertSame(Boolean.TRUE, f.get());
237 assertTrue(f.isDone());
238 assertFalse(f.isCancelled());
239 assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
240 } finally {
241 joinPool(p);
242 }
243 }
244
245 /**
246 * an unconfigurable newScheduledThreadPool successfully runs delayed task
247 */
248 public void testUnconfigurableScheduledExecutorService() throws Exception {
249 ScheduledExecutorService p =
250 Executors.unconfigurableScheduledExecutorService
251 (Executors.newScheduledThreadPool(2));
252 try {
253 final CountDownLatch proceed = new CountDownLatch(1);
254 final Runnable task = new CheckedRunnable() {
255 public void realRun() {
256 await(proceed);
257 }};
258 long startTime = System.nanoTime();
259 Future f = p.schedule(Executors.callable(task, Boolean.TRUE),
260 timeoutMillis(), MILLISECONDS);
261 assertFalse(f.isDone());
262 proceed.countDown();
263 assertSame(Boolean.TRUE, f.get(LONG_DELAY_MS, MILLISECONDS));
264 assertSame(Boolean.TRUE, f.get());
265 assertTrue(f.isDone());
266 assertFalse(f.isCancelled());
267 assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
268 } finally {
269 joinPool(p);
270 }
271 }
272
273 /**
274 * Future.get on submitted tasks will time out if they compute too long.
275 */
276 public void testTimedCallable() throws Exception {
277 final ExecutorService[] executors = {
278 Executors.newSingleThreadExecutor(),
279 Executors.newCachedThreadPool(),
280 Executors.newFixedThreadPool(2),
281 Executors.newScheduledThreadPool(2),
282 };
283
284 final Runnable sleeper = new CheckedInterruptedRunnable() {
285 public void realRun() throws InterruptedException {
286 delay(LONG_DELAY_MS);
287 }};
288
289 List<Thread> threads = new ArrayList<Thread>();
290 for (final ExecutorService executor : executors) {
291 threads.add(newStartedThread(new CheckedRunnable() {
292 public void realRun() {
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100293 Future future = executor.submit(sleeper);
294 assertFutureTimesOut(future);
295 }}));
296 }
297 for (Thread thread : threads)
298 awaitTermination(thread);
299 for (ExecutorService executor : executors)
300 joinPool(executor);
301 }
302
303 /**
304 * ThreadPoolExecutor using defaultThreadFactory has
305 * specified group, priority, daemon status, and name
306 */
307 public void testDefaultThreadFactory() throws Exception {
308 final ThreadGroup egroup = Thread.currentThread().getThreadGroup();
309 final CountDownLatch done = new CountDownLatch(1);
310 Runnable r = new CheckedRunnable() {
311 public void realRun() {
312 try {
313 Thread current = Thread.currentThread();
314 assertTrue(!current.isDaemon());
315 assertTrue(current.getPriority() <= Thread.NORM_PRIORITY);
316 ThreadGroup g = current.getThreadGroup();
317 SecurityManager s = System.getSecurityManager();
318 if (s != null)
319 assertTrue(g == s.getThreadGroup());
320 else
321 assertTrue(g == egroup);
322 String name = current.getName();
323 assertTrue(name.endsWith("thread-1"));
324 } catch (SecurityException ok) {
325 // Also pass if not allowed to change setting
326 }
327 done.countDown();
328 }};
329 ExecutorService e = Executors.newSingleThreadExecutor(Executors.defaultThreadFactory());
330
331 e.execute(r);
332 await(done);
333
334 try {
335 e.shutdown();
336 } catch (SecurityException ok) {
337 }
338
339 joinPool(e);
340 }
341
342 /**
343 * ThreadPoolExecutor using privilegedThreadFactory has
344 * specified group, priority, daemon status, name,
345 * access control context and context class loader
346 */
347 public void testPrivilegedThreadFactory() throws Exception {
348 final CountDownLatch done = new CountDownLatch(1);
349 Runnable r = new CheckedRunnable() {
350 public void realRun() throws Exception {
351 final ThreadGroup egroup = Thread.currentThread().getThreadGroup();
352 final ClassLoader thisccl = Thread.currentThread().getContextClassLoader();
Narayan Kamath05fd64a2015-04-30 10:36:15 +0100353 // android-note: Removed unsupported access controller check.
354 // final AccessControlContext thisacc = AccessController.getContext();
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100355 Runnable r = new CheckedRunnable() {
356 public void realRun() {
357 Thread current = Thread.currentThread();
358 assertTrue(!current.isDaemon());
359 assertTrue(current.getPriority() <= Thread.NORM_PRIORITY);
360 ThreadGroup g = current.getThreadGroup();
361 SecurityManager s = System.getSecurityManager();
362 if (s != null)
363 assertTrue(g == s.getThreadGroup());
364 else
365 assertTrue(g == egroup);
366 String name = current.getName();
367 assertTrue(name.endsWith("thread-1"));
368 assertSame(thisccl, current.getContextClassLoader());
Narayan Kamath05fd64a2015-04-30 10:36:15 +0100369 // assertEquals(thisacc, AccessController.getContext());
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100370 done.countDown();
371 }};
372 ExecutorService e = Executors.newSingleThreadExecutor(Executors.privilegedThreadFactory());
373 e.execute(r);
374 await(done);
375 e.shutdown();
376 joinPool(e);
377 }};
378
379 runWithPermissions(r,
380 new RuntimePermission("getClassLoader"),
381 new RuntimePermission("setContextClassLoader"),
382 new RuntimePermission("modifyThread"));
383 }
384
385 boolean haveCCLPermissions() {
386 SecurityManager sm = System.getSecurityManager();
387 if (sm != null) {
388 try {
389 sm.checkPermission(new RuntimePermission("setContextClassLoader"));
390 sm.checkPermission(new RuntimePermission("getClassLoader"));
391 } catch (AccessControlException e) {
392 return false;
393 }
394 }
395 return true;
396 }
397
398 void checkCCL() {
399 SecurityManager sm = System.getSecurityManager();
400 if (sm != null) {
401 sm.checkPermission(new RuntimePermission("setContextClassLoader"));
402 sm.checkPermission(new RuntimePermission("getClassLoader"));
403 }
404 }
405
406 class CheckCCL implements Callable<Object> {
407 public Object call() {
408 checkCCL();
409 return null;
410 }
411 }
412
413 /**
414 * Without class loader permissions, creating
415 * privilegedCallableUsingCurrentClassLoader throws ACE
416 */
417 public void testCreatePrivilegedCallableUsingCCLWithNoPrivs() {
418 Runnable r = new CheckedRunnable() {
419 public void realRun() throws Exception {
420 if (System.getSecurityManager() == null)
421 return;
422 try {
423 Executors.privilegedCallableUsingCurrentClassLoader(new NoOpCallable());
424 shouldThrow();
425 } catch (AccessControlException success) {}
426 }};
427
428 runWithoutPermissions(r);
429 }
430
431 /**
432 * With class loader permissions, calling
433 * privilegedCallableUsingCurrentClassLoader does not throw ACE
434 */
435 public void testPrivilegedCallableUsingCCLWithPrivs() throws Exception {
436 Runnable r = new CheckedRunnable() {
437 public void realRun() throws Exception {
438 Executors.privilegedCallableUsingCurrentClassLoader
439 (new NoOpCallable())
440 .call();
441 }};
442
443 runWithPermissions(r,
444 new RuntimePermission("getClassLoader"),
445 new RuntimePermission("setContextClassLoader"));
446 }
447
448 /**
449 * Without permissions, calling privilegedCallable throws ACE
450 */
451 public void testPrivilegedCallableWithNoPrivs() throws Exception {
452 // Avoid classloader-related SecurityExceptions in swingui.TestRunner
453 Executors.privilegedCallable(new CheckCCL());
454
455 Runnable r = new CheckedRunnable() {
456 public void realRun() throws Exception {
457 if (System.getSecurityManager() == null)
458 return;
459 Callable task = Executors.privilegedCallable(new CheckCCL());
460 try {
461 task.call();
462 shouldThrow();
463 } catch (AccessControlException success) {}
464 }};
465
466 runWithoutPermissions(r);
467
468 // It seems rather difficult to test that the
469 // AccessControlContext of the privilegedCallable is used
470 // instead of its caller. Below is a failed attempt to do
471 // that, which does not work because the AccessController
472 // cannot capture the internal state of the current Policy.
473 // It would be much more work to differentiate based on,
474 // e.g. CodeSource.
475
476// final AccessControlContext[] noprivAcc = new AccessControlContext[1];
477// final Callable[] task = new Callable[1];
478
479// runWithPermissions
480// (new CheckedRunnable() {
481// public void realRun() {
482// if (System.getSecurityManager() == null)
483// return;
484// noprivAcc[0] = AccessController.getContext();
485// task[0] = Executors.privilegedCallable(new CheckCCL());
486// try {
487// AccessController.doPrivileged(new PrivilegedAction<Void>() {
488// public Void run() {
489// checkCCL();
490// return null;
491// }}, noprivAcc[0]);
492// shouldThrow();
493// } catch (AccessControlException success) {}
494// }});
495
496// runWithPermissions
497// (new CheckedRunnable() {
498// public void realRun() throws Exception {
499// if (System.getSecurityManager() == null)
500// return;
501// // Verify that we have an underprivileged ACC
502// try {
503// AccessController.doPrivileged(new PrivilegedAction<Void>() {
504// public Void run() {
505// checkCCL();
506// return null;
507// }}, noprivAcc[0]);
508// shouldThrow();
509// } catch (AccessControlException success) {}
510
511// try {
512// task[0].call();
513// shouldThrow();
514// } catch (AccessControlException success) {}
515// }},
516// new RuntimePermission("getClassLoader"),
517// new RuntimePermission("setContextClassLoader"));
518 }
519
520 /**
521 * With permissions, calling privilegedCallable succeeds
522 */
523 public void testPrivilegedCallableWithPrivs() throws Exception {
524 Runnable r = new CheckedRunnable() {
525 public void realRun() throws Exception {
526 Executors.privilegedCallable(new CheckCCL()).call();
527 }};
528
529 runWithPermissions(r,
530 new RuntimePermission("getClassLoader"),
531 new RuntimePermission("setContextClassLoader"));
532 }
533
534 /**
535 * callable(Runnable) returns null when called
536 */
537 public void testCallable1() throws Exception {
538 Callable c = Executors.callable(new NoOpRunnable());
539 assertNull(c.call());
540 }
541
542 /**
543 * callable(Runnable, result) returns result when called
544 */
545 public void testCallable2() throws Exception {
546 Callable c = Executors.callable(new NoOpRunnable(), one);
547 assertSame(one, c.call());
548 }
549
550 /**
551 * callable(PrivilegedAction) returns its result when called
552 */
553 public void testCallable3() throws Exception {
554 Callable c = Executors.callable(new PrivilegedAction() {
555 public Object run() { return one; }});
556 assertSame(one, c.call());
557 }
558
559 /**
560 * callable(PrivilegedExceptionAction) returns its result when called
561 */
562 public void testCallable4() throws Exception {
563 Callable c = Executors.callable(new PrivilegedExceptionAction() {
564 public Object run() { return one; }});
565 assertSame(one, c.call());
566 }
567
568 /**
569 * callable(null Runnable) throws NPE
570 */
571 public void testCallableNPE1() {
572 try {
573 Callable c = Executors.callable((Runnable) null);
574 shouldThrow();
575 } catch (NullPointerException success) {}
576 }
577
578 /**
579 * callable(null, result) throws NPE
580 */
581 public void testCallableNPE2() {
582 try {
583 Callable c = Executors.callable((Runnable) null, one);
584 shouldThrow();
585 } catch (NullPointerException success) {}
586 }
587
588 /**
589 * callable(null PrivilegedAction) throws NPE
590 */
591 public void testCallableNPE3() {
592 try {
593 Callable c = Executors.callable((PrivilegedAction) null);
594 shouldThrow();
595 } catch (NullPointerException success) {}
596 }
597
598 /**
599 * callable(null PrivilegedExceptionAction) throws NPE
600 */
601 public void testCallableNPE4() {
602 try {
603 Callable c = Executors.callable((PrivilegedExceptionAction) null);
604 shouldThrow();
605 } catch (NullPointerException success) {}
606 }
607
608}