ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/ExecutorsTest.java
Revision: 1.56
Committed: Tue Mar 22 21:29:23 2022 UTC (2 years ago) by dl
Branch: MAIN
CVS Tags: HEAD
Changes since 1.55: +10 -0 lines
Log Message:
Updates for jdk17+

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 * Other contributors include Andrew Wright, Jeffrey Hayes,
6 * Pat Fisher, Mike Judd.
7 */
8
9 import static java.util.concurrent.TimeUnit.MILLISECONDS;
10
11 import java.security.AccessControlContext;
12 import java.security.AccessControlException;
13 import java.security.AccessController;
14 import java.security.PrivilegedAction;
15 import java.security.PrivilegedExceptionAction;
16 import java.util.ArrayList;
17 import java.util.List;
18 import java.util.concurrent.Callable;
19 import java.util.concurrent.CountDownLatch;
20 import java.util.concurrent.Executors;
21 import java.util.concurrent.ExecutorService;
22 import java.util.concurrent.Future;
23 import java.util.concurrent.ScheduledExecutorService;
24 import java.util.concurrent.ThreadPoolExecutor;
25
26 import junit.framework.Test;
27 import junit.framework.TestSuite;
28
29 public class ExecutorsTest extends JSR166TestCase {
30 public static void main(String[] args) {
31 main(suite(), args);
32 }
33 public static Test suite() {
34 return new TestSuite(ExecutorsTest.class);
35 }
36
37 /**
38 * A newCachedThreadPool can execute runnables
39 */
40 public void testNewCachedThreadPool1() {
41 final ExecutorService e = Executors.newCachedThreadPool();
42 try (PoolCleaner cleaner = cleaner(e)) {
43 e.execute(new NoOpRunnable());
44 e.execute(new NoOpRunnable());
45 e.execute(new NoOpRunnable());
46 }
47 }
48
49 /**
50 * A newCachedThreadPool with given ThreadFactory can execute runnables
51 */
52 public void testNewCachedThreadPool2() {
53 final ExecutorService e = Executors.newCachedThreadPool(new SimpleThreadFactory());
54 try (PoolCleaner cleaner = cleaner(e)) {
55 e.execute(new NoOpRunnable());
56 e.execute(new NoOpRunnable());
57 e.execute(new NoOpRunnable());
58 }
59 }
60
61 /**
62 * A newCachedThreadPool with null ThreadFactory throws NPE
63 */
64 public void testNewCachedThreadPool3() {
65 try {
66 ExecutorService unused = Executors.newCachedThreadPool(null);
67 shouldThrow();
68 } catch (NullPointerException success) {}
69 }
70
71 /**
72 * A new SingleThreadExecutor can execute runnables
73 */
74 public void testNewSingleThreadExecutor1() {
75 final ExecutorService e = Executors.newSingleThreadExecutor();
76 try (PoolCleaner cleaner = cleaner(e)) {
77 e.execute(new NoOpRunnable());
78 e.execute(new NoOpRunnable());
79 e.execute(new NoOpRunnable());
80 }
81 }
82
83 /**
84 * A new SingleThreadExecutor with given ThreadFactory can execute runnables
85 */
86 public void testNewSingleThreadExecutor2() {
87 final ExecutorService e = Executors.newSingleThreadExecutor(new SimpleThreadFactory());
88 try (PoolCleaner cleaner = cleaner(e)) {
89 e.execute(new NoOpRunnable());
90 e.execute(new NoOpRunnable());
91 e.execute(new NoOpRunnable());
92 }
93 }
94
95 /**
96 * A new SingleThreadExecutor with null ThreadFactory throws NPE
97 */
98 public void testNewSingleThreadExecutor3() {
99 try {
100 ExecutorService unused = Executors.newSingleThreadExecutor(null);
101 shouldThrow();
102 } catch (NullPointerException success) {}
103 }
104
105 /**
106 * A new SingleThreadExecutor cannot be casted to concrete implementation
107 */
108 public void testCastNewSingleThreadExecutor() {
109 final ExecutorService e = Executors.newSingleThreadExecutor();
110 try (PoolCleaner cleaner = cleaner(e)) {
111 try {
112 ThreadPoolExecutor tpe = (ThreadPoolExecutor)e;
113 shouldThrow();
114 } catch (ClassCastException success) {}
115 }
116 }
117
118 /**
119 * A new newFixedThreadPool can execute runnables
120 */
121 public void testNewFixedThreadPool1() {
122 final ExecutorService e = Executors.newFixedThreadPool(2);
123 try (PoolCleaner cleaner = cleaner(e)) {
124 e.execute(new NoOpRunnable());
125 e.execute(new NoOpRunnable());
126 e.execute(new NoOpRunnable());
127 }
128 }
129
130 /**
131 * A new newFixedThreadPool with given ThreadFactory can execute runnables
132 */
133 public void testNewFixedThreadPool2() {
134 final ExecutorService e = Executors.newFixedThreadPool(2, new SimpleThreadFactory());
135 try (PoolCleaner cleaner = cleaner(e)) {
136 e.execute(new NoOpRunnable());
137 e.execute(new NoOpRunnable());
138 e.execute(new NoOpRunnable());
139 }
140 }
141
142 /**
143 * A new newFixedThreadPool with null ThreadFactory throws
144 * NullPointerException
145 */
146 public void testNewFixedThreadPool3() {
147 try {
148 ExecutorService unused = Executors.newFixedThreadPool(2, null);
149 shouldThrow();
150 } catch (NullPointerException success) {}
151 }
152
153 /**
154 * A new newFixedThreadPool with 0 threads throws IllegalArgumentException
155 */
156 public void testNewFixedThreadPool4() {
157 try {
158 ExecutorService unused = Executors.newFixedThreadPool(0);
159 shouldThrow();
160 } catch (IllegalArgumentException success) {}
161 }
162
163 /**
164 * An unconfigurable newFixedThreadPool can execute runnables
165 */
166 public void testUnconfigurableExecutorService() {
167 final ExecutorService e = Executors.unconfigurableExecutorService(Executors.newFixedThreadPool(2));
168 try (PoolCleaner cleaner = cleaner(e)) {
169 e.execute(new NoOpRunnable());
170 e.execute(new NoOpRunnable());
171 e.execute(new NoOpRunnable());
172 }
173 }
174
175 /**
176 * unconfigurableExecutorService(null) throws NPE
177 */
178 public void testUnconfigurableExecutorServiceNPE() {
179 try {
180 ExecutorService unused =
181 Executors.unconfigurableExecutorService(null);
182 shouldThrow();
183 } catch (NullPointerException success) {}
184 }
185
186 /**
187 * unconfigurableScheduledExecutorService(null) throws NPE
188 */
189 public void testUnconfigurableScheduledExecutorServiceNPE() {
190 try {
191 ExecutorService unused =
192 Executors.unconfigurableScheduledExecutorService(null);
193 shouldThrow();
194 } catch (NullPointerException success) {}
195 }
196
197 /**
198 * a newSingleThreadScheduledExecutor successfully runs delayed task
199 */
200 public void testNewSingleThreadScheduledExecutor() throws Exception {
201 final ScheduledExecutorService p = Executors.newSingleThreadScheduledExecutor();
202 try (PoolCleaner cleaner = cleaner(p)) {
203 final CountDownLatch proceed = new CountDownLatch(1);
204 final Runnable task = new CheckedRunnable() {
205 public void realRun() {
206 await(proceed);
207 }};
208 long startTime = System.nanoTime();
209 Future<?> f = p.schedule(Executors.callable(task, Boolean.TRUE),
210 timeoutMillis(), MILLISECONDS);
211 assertFalse(f.isDone());
212 proceed.countDown();
213 assertSame(Boolean.TRUE, f.get(LONG_DELAY_MS, MILLISECONDS));
214 assertSame(Boolean.TRUE, f.get());
215 assertTrue(f.isDone());
216 assertFalse(f.isCancelled());
217 assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
218 }
219 }
220
221 /**
222 * a newScheduledThreadPool successfully runs delayed task
223 */
224 public void testNewScheduledThreadPool() throws Exception {
225 final ScheduledExecutorService p = Executors.newScheduledThreadPool(2);
226 try (PoolCleaner cleaner = cleaner(p)) {
227 final CountDownLatch proceed = new CountDownLatch(1);
228 final Runnable task = new CheckedRunnable() {
229 public void realRun() {
230 await(proceed);
231 }};
232 long startTime = System.nanoTime();
233 Future<?> f = p.schedule(Executors.callable(task, Boolean.TRUE),
234 timeoutMillis(), MILLISECONDS);
235 assertFalse(f.isDone());
236 proceed.countDown();
237 assertSame(Boolean.TRUE, f.get(LONG_DELAY_MS, MILLISECONDS));
238 assertSame(Boolean.TRUE, f.get());
239 assertTrue(f.isDone());
240 assertFalse(f.isCancelled());
241 assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
242 }
243 }
244
245 /**
246 * an unconfigurable newScheduledThreadPool successfully runs delayed task
247 */
248 public void testUnconfigurableScheduledExecutorService() throws Exception {
249 final ScheduledExecutorService p =
250 Executors.unconfigurableScheduledExecutorService
251 (Executors.newScheduledThreadPool(2));
252 try (PoolCleaner cleaner = cleaner(p)) {
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 }
269 }
270
271 /**
272 * Future.get on submitted tasks will time out if they compute too long.
273 */
274 public void testTimedCallable() throws Exception {
275 final ExecutorService[] executors = {
276 Executors.newSingleThreadExecutor(),
277 Executors.newCachedThreadPool(),
278 Executors.newFixedThreadPool(2),
279 Executors.newScheduledThreadPool(2),
280 };
281
282 final CountDownLatch done = new CountDownLatch(1);
283
284 final Runnable sleeper = new CheckedRunnable() {
285 public void realRun() throws InterruptedException {
286 done.await(LONG_DELAY_MS, MILLISECONDS);
287 }};
288
289 List<Thread> threads = new ArrayList<>();
290 for (final ExecutorService executor : executors) {
291 threads.add(newStartedThread(new CheckedRunnable() {
292 public void realRun() {
293 Future<?> future = executor.submit(sleeper);
294 assertFutureTimesOut(future);
295 }}));
296 }
297 for (Thread thread : threads)
298 awaitTermination(thread);
299 done.countDown();
300 for (ExecutorService executor : executors)
301 joinPool(executor);
302 }
303
304 /**
305 * ThreadPoolExecutor using defaultThreadFactory has
306 * specified group, priority, daemon status, and name
307 */
308 @SuppressWarnings("removal")
309 public void testDefaultThreadFactory() throws Exception {
310 final ThreadGroup egroup = Thread.currentThread().getThreadGroup();
311 final CountDownLatch done = new CountDownLatch(1);
312 Runnable r = new CheckedRunnable() {
313 public void realRun() {
314 try {
315 Thread current = Thread.currentThread();
316 assertFalse(current.isDaemon());
317 assertTrue(current.getPriority() <= Thread.NORM_PRIORITY);
318 SecurityManager s = System.getSecurityManager();
319 assertSame(current.getThreadGroup(),
320 (s == null) ? egroup : s.getThreadGroup());
321 assertTrue(current.getName().endsWith("thread-1"));
322 } catch (SecurityException ok) {
323 // Also pass if not allowed to change setting
324 }
325 done.countDown();
326 }};
327 ExecutorService e = Executors.newSingleThreadExecutor(Executors.defaultThreadFactory());
328 try (PoolCleaner cleaner = cleaner(e)) {
329 e.execute(r);
330 await(done);
331 }
332 }
333
334 /**
335 * ThreadPoolExecutor using privilegedThreadFactory has
336 * specified group, priority, daemon status, name,
337 * access control context and context class loader
338 */
339 @SuppressWarnings("removal")
340 public void testPrivilegedThreadFactory() throws Exception {
341 final CountDownLatch done = new CountDownLatch(1);
342 Runnable r = new CheckedRunnable() {
343 public void realRun() throws Exception {
344 final ThreadGroup egroup = Thread.currentThread().getThreadGroup();
345 final ClassLoader thisccl = Thread.currentThread().getContextClassLoader();
346 final AccessControlContext thisacc = AccessController.getContext();
347 Runnable r = new CheckedRunnable() {
348 public void realRun() {
349 Thread current = Thread.currentThread();
350 assertFalse(current.isDaemon());
351 assertTrue(current.getPriority() <= Thread.NORM_PRIORITY);
352 SecurityManager s = System.getSecurityManager();
353 assertSame(current.getThreadGroup(),
354 (s == null) ? egroup : s.getThreadGroup());
355 assertTrue(current.getName().endsWith("thread-1"));
356 assertSame(thisccl, current.getContextClassLoader());
357 assertEquals(thisacc, AccessController.getContext());
358 done.countDown();
359 }};
360 ExecutorService e = Executors.newSingleThreadExecutor(Executors.privilegedThreadFactory());
361 try (PoolCleaner cleaner = cleaner(e)) {
362 e.execute(r);
363 await(done);
364 }
365 }};
366
367 runWithPermissions(r,
368 new RuntimePermission("getClassLoader"),
369 new RuntimePermission("setContextClassLoader"),
370 new RuntimePermission("modifyThread"));
371 }
372
373 @SuppressWarnings("removal")
374 boolean haveCCLPermissions() {
375 SecurityManager sm = System.getSecurityManager();
376 if (sm != null) {
377 try {
378 sm.checkPermission(new RuntimePermission("setContextClassLoader"));
379 sm.checkPermission(new RuntimePermission("getClassLoader"));
380 } catch (AccessControlException e) {
381 return false;
382 }
383 }
384 return true;
385 }
386
387 @SuppressWarnings("removal")
388 void checkCCL() {
389 SecurityManager sm = System.getSecurityManager();
390 if (sm != null) {
391 sm.checkPermission(new RuntimePermission("setContextClassLoader"));
392 sm.checkPermission(new RuntimePermission("getClassLoader"));
393 }
394 }
395
396 class CheckCCL implements Callable<Object> {
397 public Object call() {
398 checkCCL();
399 return null;
400 }
401 }
402
403 /**
404 * Without class loader permissions, creating
405 * privilegedCallableUsingCurrentClassLoader throws ACE
406 */
407 @SuppressWarnings("removal")
408 public void testCreatePrivilegedCallableUsingCCLWithNoPrivs() {
409 Runnable r = new CheckedRunnable() {
410 public void realRun() throws Exception {
411 if (System.getSecurityManager() == null)
412 return;
413 try {
414 Executors.privilegedCallableUsingCurrentClassLoader(new NoOpCallable());
415 shouldThrow();
416 } catch (AccessControlException success) {}
417 }};
418
419 runWithoutPermissions(r);
420 }
421
422 /**
423 * With class loader permissions, calling
424 * privilegedCallableUsingCurrentClassLoader does not throw ACE
425 */
426 @SuppressWarnings("removal")
427 public void testPrivilegedCallableUsingCCLWithPrivs() throws Exception {
428 Runnable r = new CheckedRunnable() {
429 public void realRun() throws Exception {
430 Executors.privilegedCallableUsingCurrentClassLoader
431 (new NoOpCallable())
432 .call();
433 }};
434
435 runWithPermissions(r,
436 new RuntimePermission("getClassLoader"),
437 new RuntimePermission("setContextClassLoader"));
438 }
439
440 /**
441 * Without permissions, calling privilegedCallable throws ACE
442 */
443 @SuppressWarnings("removal")
444 public void testPrivilegedCallableWithNoPrivs() throws Exception {
445 // Avoid classloader-related SecurityExceptions in swingui.TestRunner
446 Executors.privilegedCallable(new CheckCCL());
447
448 Runnable r = new CheckedRunnable() {
449 public void realRun() throws Exception {
450 if (System.getSecurityManager() == null)
451 return;
452 Callable<?> task = Executors.privilegedCallable(new CheckCCL());
453 try {
454 task.call();
455 shouldThrow();
456 } catch (AccessControlException success) {}
457 }};
458
459 runWithoutPermissions(r);
460
461 // It seems rather difficult to test that the
462 // AccessControlContext of the privilegedCallable is used
463 // instead of its caller. Below is a failed attempt to do
464 // that, which does not work because the AccessController
465 // cannot capture the internal state of the current Policy.
466 // It would be much more work to differentiate based on,
467 // e.g. CodeSource.
468
469 // final AccessControlContext[] noprivAcc = new AccessControlContext[1];
470 // final Callable[] task = new Callable[1];
471
472 // runWithPermissions
473 // (new CheckedRunnable() {
474 // public void realRun() {
475 // if (System.getSecurityManager() == null)
476 // return;
477 // noprivAcc[0] = AccessController.getContext();
478 // task[0] = Executors.privilegedCallable(new CheckCCL());
479 // try {
480 // AccessController.doPrivileged(new PrivilegedAction<Void>() {
481 // public Void run() {
482 // checkCCL();
483 // return null;
484 // }}, noprivAcc[0]);
485 // shouldThrow();
486 // } catch (AccessControlException success) {}
487 // }});
488
489 // runWithPermissions
490 // (new CheckedRunnable() {
491 // public void realRun() throws Exception {
492 // if (System.getSecurityManager() == null)
493 // return;
494 // // Verify that we have an underprivileged ACC
495 // try {
496 // AccessController.doPrivileged(new PrivilegedAction<Void>() {
497 // public Void run() {
498 // checkCCL();
499 // return null;
500 // }}, noprivAcc[0]);
501 // shouldThrow();
502 // } catch (AccessControlException success) {}
503
504 // try {
505 // task[0].call();
506 // shouldThrow();
507 // } catch (AccessControlException success) {}
508 // }},
509 // new RuntimePermission("getClassLoader"),
510 // new RuntimePermission("setContextClassLoader"));
511 }
512
513 /**
514 * With permissions, calling privilegedCallable succeeds
515 */
516 @SuppressWarnings("removal")
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<?> unused = 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<?> unused = 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<?> unused = 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<?> unused = Executors.callable((PrivilegedExceptionAction) null);
598 shouldThrow();
599 } catch (NullPointerException success) {}
600 }
601
602 /**
603 * callable(runnable, x).toString() contains toString of wrapped task
604 */
605 public void testCallable_withResult_toString() {
606 if (testImplementationDetails) {
607 Runnable r = () -> {};
608 Callable<String> c = Executors.callable(r, "");
609 assertEquals(
610 identityString(c) + "[Wrapped task = " + r.toString() + "]",
611 c.toString());
612 }
613 }
614
615 /**
616 * callable(runnable).toString() contains toString of wrapped task
617 */
618 public void testCallable_toString() {
619 if (testImplementationDetails) {
620 Runnable r = () -> {};
621 Callable<Object> c = Executors.callable(r);
622 assertEquals(
623 identityString(c) + "[Wrapped task = " + r.toString() + "]",
624 c.toString());
625 }
626 }
627
628 /**
629 * privilegedCallable(callable).toString() contains toString of wrapped task
630 */
631 @SuppressWarnings("removal")
632 public void testPrivilegedCallable_toString() {
633 if (testImplementationDetails) {
634 Callable<String> c = () -> "";
635 Callable<String> priv = Executors.privilegedCallable(c);
636 assertEquals(
637 identityString(priv) + "[Wrapped task = " + c.toString() + "]",
638 priv.toString());
639 }
640 }
641
642 /**
643 * privilegedCallableUsingCurrentClassLoader(callable).toString()
644 * contains toString of wrapped task
645 */
646 @SuppressWarnings("removal")
647 public void testPrivilegedCallableUsingCurrentClassLoader_toString() {
648 if (testImplementationDetails) {
649 Callable<String> c = () -> "";
650 Callable<String> priv = Executors.privilegedCallableUsingCurrentClassLoader(c);
651 assertEquals(
652 identityString(priv) + "[Wrapped task = " + c.toString() + "]",
653 priv.toString());
654 }
655 }
656 }