blob: d70ae6e395e4cf71f17b4d743d5335a46b666679 [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() {
Przemyslaw Szczepaniakb8b75112016-03-11 15:59:10 +000039 // return new TestSuite(ExecutorsTest.class);
Narayan Kamath8e9a0e92015-04-28 11:40:00 +010040 // }
Calin Juravle8f0d92b2013-08-01 17:26:00 +010041
42 /**
43 * A newCachedThreadPool can execute runnables
44 */
45 public void testNewCachedThreadPool1() {
Przemyslaw Szczepaniakb8b75112016-03-11 15:59:10 +000046 final ExecutorService e = Executors.newCachedThreadPool();
47 try (PoolCleaner cleaner = cleaner(e)) {
48 e.execute(new NoOpRunnable());
49 e.execute(new NoOpRunnable());
50 e.execute(new NoOpRunnable());
51 }
Calin Juravle8f0d92b2013-08-01 17:26:00 +010052 }
53
54 /**
55 * A newCachedThreadPool with given ThreadFactory can execute runnables
56 */
57 public void testNewCachedThreadPool2() {
Przemyslaw Szczepaniakb8b75112016-03-11 15:59:10 +000058 final ExecutorService e = Executors.newCachedThreadPool(new SimpleThreadFactory());
59 try (PoolCleaner cleaner = cleaner(e)) {
60 e.execute(new NoOpRunnable());
61 e.execute(new NoOpRunnable());
62 e.execute(new NoOpRunnable());
63 }
Calin Juravle8f0d92b2013-08-01 17:26:00 +010064 }
65
66 /**
67 * A newCachedThreadPool with null ThreadFactory throws NPE
68 */
69 public void testNewCachedThreadPool3() {
70 try {
71 ExecutorService e = Executors.newCachedThreadPool(null);
72 shouldThrow();
73 } catch (NullPointerException success) {}
74 }
75
76 /**
77 * A new SingleThreadExecutor can execute runnables
78 */
79 public void testNewSingleThreadExecutor1() {
Przemyslaw Szczepaniakb8b75112016-03-11 15:59:10 +000080 final ExecutorService e = Executors.newSingleThreadExecutor();
81 try (PoolCleaner cleaner = cleaner(e)) {
82 e.execute(new NoOpRunnable());
83 e.execute(new NoOpRunnable());
84 e.execute(new NoOpRunnable());
85 }
Calin Juravle8f0d92b2013-08-01 17:26:00 +010086 }
87
88 /**
89 * A new SingleThreadExecutor with given ThreadFactory can execute runnables
90 */
91 public void testNewSingleThreadExecutor2() {
Przemyslaw Szczepaniakb8b75112016-03-11 15:59:10 +000092 final ExecutorService e = Executors.newSingleThreadExecutor(new SimpleThreadFactory());
93 try (PoolCleaner cleaner = cleaner(e)) {
94 e.execute(new NoOpRunnable());
95 e.execute(new NoOpRunnable());
96 e.execute(new NoOpRunnable());
97 }
Calin Juravle8f0d92b2013-08-01 17:26:00 +010098 }
99
100 /**
101 * A new SingleThreadExecutor with null ThreadFactory throws NPE
102 */
103 public void testNewSingleThreadExecutor3() {
104 try {
105 ExecutorService e = Executors.newSingleThreadExecutor(null);
106 shouldThrow();
107 } catch (NullPointerException success) {}
108 }
109
110 /**
111 * A new SingleThreadExecutor cannot be casted to concrete implementation
112 */
113 public void testCastNewSingleThreadExecutor() {
Przemyslaw Szczepaniakb8b75112016-03-11 15:59:10 +0000114 final ExecutorService e = Executors.newSingleThreadExecutor();
115 try (PoolCleaner cleaner = cleaner(e)) {
116 try {
117 ThreadPoolExecutor tpe = (ThreadPoolExecutor)e;
118 shouldThrow();
119 } catch (ClassCastException success) {}
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100120 }
121 }
122
123 /**
124 * A new newFixedThreadPool can execute runnables
125 */
126 public void testNewFixedThreadPool1() {
Przemyslaw Szczepaniakb8b75112016-03-11 15:59:10 +0000127 final ExecutorService e = Executors.newFixedThreadPool(2);
128 try (PoolCleaner cleaner = cleaner(e)) {
129 e.execute(new NoOpRunnable());
130 e.execute(new NoOpRunnable());
131 e.execute(new NoOpRunnable());
132 }
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100133 }
134
135 /**
136 * A new newFixedThreadPool with given ThreadFactory can execute runnables
137 */
138 public void testNewFixedThreadPool2() {
Przemyslaw Szczepaniakb8b75112016-03-11 15:59:10 +0000139 final ExecutorService e = Executors.newFixedThreadPool(2, new SimpleThreadFactory());
140 try (PoolCleaner cleaner = cleaner(e)) {
141 e.execute(new NoOpRunnable());
142 e.execute(new NoOpRunnable());
143 e.execute(new NoOpRunnable());
144 }
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100145 }
146
147 /**
148 * A new newFixedThreadPool with null ThreadFactory throws NPE
149 */
150 public void testNewFixedThreadPool3() {
151 try {
152 ExecutorService e = Executors.newFixedThreadPool(2, null);
153 shouldThrow();
154 } catch (NullPointerException success) {}
155 }
156
157 /**
158 * A new newFixedThreadPool with 0 threads throws IAE
159 */
160 public void testNewFixedThreadPool4() {
161 try {
162 ExecutorService e = Executors.newFixedThreadPool(0);
163 shouldThrow();
164 } catch (IllegalArgumentException success) {}
165 }
166
167 /**
168 * An unconfigurable newFixedThreadPool can execute runnables
169 */
170 public void testUnconfigurableExecutorService() {
Przemyslaw Szczepaniakb8b75112016-03-11 15:59:10 +0000171 final ExecutorService e = Executors.unconfigurableExecutorService(Executors.newFixedThreadPool(2));
172 try (PoolCleaner cleaner = cleaner(e)) {
173 e.execute(new NoOpRunnable());
174 e.execute(new NoOpRunnable());
175 e.execute(new NoOpRunnable());
176 }
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100177 }
178
179 /**
180 * unconfigurableExecutorService(null) throws NPE
181 */
182 public void testUnconfigurableExecutorServiceNPE() {
183 try {
184 ExecutorService e = Executors.unconfigurableExecutorService(null);
185 shouldThrow();
186 } catch (NullPointerException success) {}
187 }
188
189 /**
190 * unconfigurableScheduledExecutorService(null) throws NPE
191 */
192 public void testUnconfigurableScheduledExecutorServiceNPE() {
193 try {
194 ExecutorService e = Executors.unconfigurableScheduledExecutorService(null);
195 shouldThrow();
196 } catch (NullPointerException success) {}
197 }
198
199 /**
200 * a newSingleThreadScheduledExecutor successfully runs delayed task
201 */
202 public void testNewSingleThreadScheduledExecutor() throws Exception {
Przemyslaw Szczepaniakb8b75112016-03-11 15:59:10 +0000203 final ScheduledExecutorService p = Executors.newSingleThreadScheduledExecutor();
204 try (PoolCleaner cleaner = cleaner(p)) {
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100205 final CountDownLatch proceed = new CountDownLatch(1);
206 final Runnable task = new CheckedRunnable() {
207 public void realRun() {
208 await(proceed);
209 }};
210 long startTime = System.nanoTime();
211 Future f = p.schedule(Executors.callable(task, Boolean.TRUE),
212 timeoutMillis(), MILLISECONDS);
213 assertFalse(f.isDone());
214 proceed.countDown();
215 assertSame(Boolean.TRUE, f.get(LONG_DELAY_MS, MILLISECONDS));
216 assertSame(Boolean.TRUE, f.get());
217 assertTrue(f.isDone());
218 assertFalse(f.isCancelled());
219 assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100220 }
221 }
222
223 /**
224 * a newScheduledThreadPool successfully runs delayed task
225 */
226 public void testNewScheduledThreadPool() throws Exception {
Przemyslaw Szczepaniakb8b75112016-03-11 15:59:10 +0000227 final ScheduledExecutorService p = Executors.newScheduledThreadPool(2);
228 try (PoolCleaner cleaner = cleaner(p)) {
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100229 final CountDownLatch proceed = new CountDownLatch(1);
230 final Runnable task = new CheckedRunnable() {
231 public void realRun() {
232 await(proceed);
233 }};
234 long startTime = System.nanoTime();
235 Future f = p.schedule(Executors.callable(task, Boolean.TRUE),
236 timeoutMillis(), MILLISECONDS);
237 assertFalse(f.isDone());
238 proceed.countDown();
239 assertSame(Boolean.TRUE, f.get(LONG_DELAY_MS, MILLISECONDS));
240 assertSame(Boolean.TRUE, f.get());
241 assertTrue(f.isDone());
242 assertFalse(f.isCancelled());
243 assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100244 }
245 }
246
247 /**
248 * an unconfigurable newScheduledThreadPool successfully runs delayed task
249 */
250 public void testUnconfigurableScheduledExecutorService() throws Exception {
Przemyslaw Szczepaniakb8b75112016-03-11 15:59:10 +0000251 final ScheduledExecutorService p =
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100252 Executors.unconfigurableScheduledExecutorService
253 (Executors.newScheduledThreadPool(2));
Przemyslaw Szczepaniakb8b75112016-03-11 15:59:10 +0000254 try (PoolCleaner cleaner = cleaner(p)) {
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100255 final CountDownLatch proceed = new CountDownLatch(1);
256 final Runnable task = new CheckedRunnable() {
257 public void realRun() {
258 await(proceed);
259 }};
260 long startTime = System.nanoTime();
261 Future f = p.schedule(Executors.callable(task, Boolean.TRUE),
262 timeoutMillis(), MILLISECONDS);
263 assertFalse(f.isDone());
264 proceed.countDown();
265 assertSame(Boolean.TRUE, f.get(LONG_DELAY_MS, MILLISECONDS));
266 assertSame(Boolean.TRUE, f.get());
267 assertTrue(f.isDone());
268 assertFalse(f.isCancelled());
269 assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100270 }
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());
Przemyslaw Szczepaniakb8b75112016-03-11 15:59:10 +0000330 try (PoolCleaner cleaner = cleaner(e)) {
331 e.execute(r);
332 await(done);
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100333 }
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100334 }
335
336 /**
337 * ThreadPoolExecutor using privilegedThreadFactory has
338 * specified group, priority, daemon status, name,
339 * access control context and context class loader
340 */
341 public void testPrivilegedThreadFactory() throws Exception {
342 final CountDownLatch done = new CountDownLatch(1);
343 Runnable r = new CheckedRunnable() {
344 public void realRun() throws Exception {
345 final ThreadGroup egroup = Thread.currentThread().getThreadGroup();
346 final ClassLoader thisccl = Thread.currentThread().getContextClassLoader();
Narayan Kamath05fd64a2015-04-30 10:36:15 +0100347 // android-note: Removed unsupported access controller check.
348 // final AccessControlContext thisacc = AccessController.getContext();
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100349 Runnable r = new CheckedRunnable() {
350 public void realRun() {
351 Thread current = Thread.currentThread();
352 assertTrue(!current.isDaemon());
353 assertTrue(current.getPriority() <= Thread.NORM_PRIORITY);
354 ThreadGroup g = current.getThreadGroup();
355 SecurityManager s = System.getSecurityManager();
356 if (s != null)
357 assertTrue(g == s.getThreadGroup());
358 else
359 assertTrue(g == egroup);
360 String name = current.getName();
361 assertTrue(name.endsWith("thread-1"));
362 assertSame(thisccl, current.getContextClassLoader());
Przemyslaw Szczepaniakb8b75112016-03-11 15:59:10 +0000363 //assertEquals(thisacc, AccessController.getContext());
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100364 done.countDown();
365 }};
366 ExecutorService e = Executors.newSingleThreadExecutor(Executors.privilegedThreadFactory());
Przemyslaw Szczepaniakb8b75112016-03-11 15:59:10 +0000367 try (PoolCleaner cleaner = cleaner(e)) {
368 e.execute(r);
369 await(done);
370 }
Calin Juravle8f0d92b2013-08-01 17:26:00 +0100371 }};
372
373 runWithPermissions(r,
374 new RuntimePermission("getClassLoader"),
375 new RuntimePermission("setContextClassLoader"),
376 new RuntimePermission("modifyThread"));
377 }
378
379 boolean haveCCLPermissions() {
380 SecurityManager sm = System.getSecurityManager();
381 if (sm != null) {
382 try {
383 sm.checkPermission(new RuntimePermission("setContextClassLoader"));
384 sm.checkPermission(new RuntimePermission("getClassLoader"));
385 } catch (AccessControlException e) {
386 return false;
387 }
388 }
389 return true;
390 }
391
392 void checkCCL() {
393 SecurityManager sm = System.getSecurityManager();
394 if (sm != null) {
395 sm.checkPermission(new RuntimePermission("setContextClassLoader"));
396 sm.checkPermission(new RuntimePermission("getClassLoader"));
397 }
398 }
399
400 class CheckCCL implements Callable<Object> {
401 public Object call() {
402 checkCCL();
403 return null;
404 }
405 }
406
407 /**
408 * Without class loader permissions, creating
409 * privilegedCallableUsingCurrentClassLoader throws ACE
410 */
411 public void testCreatePrivilegedCallableUsingCCLWithNoPrivs() {
412 Runnable r = new CheckedRunnable() {
413 public void realRun() throws Exception {
414 if (System.getSecurityManager() == null)
415 return;
416 try {
417 Executors.privilegedCallableUsingCurrentClassLoader(new NoOpCallable());
418 shouldThrow();
419 } catch (AccessControlException success) {}
420 }};
421
422 runWithoutPermissions(r);
423 }
424
425 /**
426 * With class loader permissions, calling
427 * privilegedCallableUsingCurrentClassLoader does not throw ACE
428 */
429 public void testPrivilegedCallableUsingCCLWithPrivs() throws Exception {
430 Runnable r = new CheckedRunnable() {
431 public void realRun() throws Exception {
432 Executors.privilegedCallableUsingCurrentClassLoader
433 (new NoOpCallable())
434 .call();
435 }};
436
437 runWithPermissions(r,
438 new RuntimePermission("getClassLoader"),
439 new RuntimePermission("setContextClassLoader"));
440 }
441
442 /**
443 * Without permissions, calling privilegedCallable throws ACE
444 */
445 public void testPrivilegedCallableWithNoPrivs() throws Exception {
446 // Avoid classloader-related SecurityExceptions in swingui.TestRunner
447 Executors.privilegedCallable(new CheckCCL());
448
449 Runnable r = new CheckedRunnable() {
450 public void realRun() throws Exception {
451 if (System.getSecurityManager() == null)
452 return;
453 Callable task = Executors.privilegedCallable(new CheckCCL());
454 try {
455 task.call();
456 shouldThrow();
457 } catch (AccessControlException success) {}
458 }};
459
460 runWithoutPermissions(r);
461
462 // It seems rather difficult to test that the
463 // AccessControlContext of the privilegedCallable is used
464 // instead of its caller. Below is a failed attempt to do
465 // that, which does not work because the AccessController
466 // cannot capture the internal state of the current Policy.
467 // It would be much more work to differentiate based on,
468 // e.g. CodeSource.
469
470// final AccessControlContext[] noprivAcc = new AccessControlContext[1];
471// final Callable[] task = new Callable[1];
472
473// runWithPermissions
474// (new CheckedRunnable() {
475// public void realRun() {
476// if (System.getSecurityManager() == null)
477// return;
478// noprivAcc[0] = AccessController.getContext();
479// task[0] = Executors.privilegedCallable(new CheckCCL());
480// try {
481// AccessController.doPrivileged(new PrivilegedAction<Void>() {
482// public Void run() {
483// checkCCL();
484// return null;
485// }}, noprivAcc[0]);
486// shouldThrow();
487// } catch (AccessControlException success) {}
488// }});
489
490// runWithPermissions
491// (new CheckedRunnable() {
492// public void realRun() throws Exception {
493// if (System.getSecurityManager() == null)
494// return;
495// // Verify that we have an underprivileged ACC
496// try {
497// AccessController.doPrivileged(new PrivilegedAction<Void>() {
498// public Void run() {
499// checkCCL();
500// return null;
501// }}, noprivAcc[0]);
502// shouldThrow();
503// } catch (AccessControlException success) {}
504
505// try {
506// task[0].call();
507// shouldThrow();
508// } catch (AccessControlException success) {}
509// }},
510// new RuntimePermission("getClassLoader"),
511// new RuntimePermission("setContextClassLoader"));
512 }
513
514 /**
515 * With permissions, calling privilegedCallable succeeds
516 */
517 public void testPrivilegedCallableWithPrivs() throws Exception {
518 Runnable r = new CheckedRunnable() {
519 public void realRun() throws Exception {
520 Executors.privilegedCallable(new CheckCCL()).call();
521 }};
522
523 runWithPermissions(r,
524 new RuntimePermission("getClassLoader"),
525 new RuntimePermission("setContextClassLoader"));
526 }
527
528 /**
529 * callable(Runnable) returns null when called
530 */
531 public void testCallable1() throws Exception {
532 Callable c = Executors.callable(new NoOpRunnable());
533 assertNull(c.call());
534 }
535
536 /**
537 * callable(Runnable, result) returns result when called
538 */
539 public void testCallable2() throws Exception {
540 Callable c = Executors.callable(new NoOpRunnable(), one);
541 assertSame(one, c.call());
542 }
543
544 /**
545 * callable(PrivilegedAction) returns its result when called
546 */
547 public void testCallable3() throws Exception {
548 Callable c = Executors.callable(new PrivilegedAction() {
549 public Object run() { return one; }});
550 assertSame(one, c.call());
551 }
552
553 /**
554 * callable(PrivilegedExceptionAction) returns its result when called
555 */
556 public void testCallable4() throws Exception {
557 Callable c = Executors.callable(new PrivilegedExceptionAction() {
558 public Object run() { return one; }});
559 assertSame(one, c.call());
560 }
561
562 /**
563 * callable(null Runnable) throws NPE
564 */
565 public void testCallableNPE1() {
566 try {
567 Callable c = Executors.callable((Runnable) null);
568 shouldThrow();
569 } catch (NullPointerException success) {}
570 }
571
572 /**
573 * callable(null, result) throws NPE
574 */
575 public void testCallableNPE2() {
576 try {
577 Callable c = Executors.callable((Runnable) null, one);
578 shouldThrow();
579 } catch (NullPointerException success) {}
580 }
581
582 /**
583 * callable(null PrivilegedAction) throws NPE
584 */
585 public void testCallableNPE3() {
586 try {
587 Callable c = Executors.callable((PrivilegedAction) null);
588 shouldThrow();
589 } catch (NullPointerException success) {}
590 }
591
592 /**
593 * callable(null PrivilegedExceptionAction) throws NPE
594 */
595 public void testCallableNPE4() {
596 try {
597 Callable c = Executors.callable((PrivilegedExceptionAction) null);
598 shouldThrow();
599 } catch (NullPointerException success) {}
600 }
601
602}