1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. 7 * 8 * This code is distributed in the hope that it will be useful, but WITHOUT 9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 11 * version 2 for more details (a copy is included in the LICENSE file that 12 * accompanied this code). 13 * 14 * You should have received a copy of the GNU General Public License version 15 * 2 along with this work; if not, write to the Free Software Foundation, 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 17 * 18 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 19 * or visit www.oracle.com if you need additional information or have any 20 * questions. 21 */ 22 23 /* 24 * This file is available under and governed by the GNU General Public 25 * License version 2 only, as published by the Free Software Foundation. 26 * However, the following notice accompanied the original version of this 27 * file: 28 * 29 * Written by Doug Lea with assistance from members of JCP JSR-166 30 * Expert Group and released to the public domain, as explained at 31 * http://creativecommons.org/publicdomain/zero/1.0/ 32 * Other contributors include Andrew Wright, Jeffrey Hayes, 33 * Pat Fisher, Mike Judd. 34 */ 35 36 import static java.util.concurrent.TimeUnit.MILLISECONDS; 37 38 import java.security.AccessControlContext; 39 import java.security.AccessControlException; 40 import java.security.AccessController; 41 import java.security.PrivilegedAction; 42 import java.security.PrivilegedExceptionAction; 43 import java.util.ArrayList; 44 import java.util.List; 45 import java.util.concurrent.Callable; 46 import java.util.concurrent.CountDownLatch; 47 import java.util.concurrent.Executors; 48 import java.util.concurrent.ExecutorService; 49 import java.util.concurrent.Future; 50 import java.util.concurrent.ScheduledExecutorService; 51 import java.util.concurrent.ThreadPoolExecutor; 52 53 import junit.framework.Test; 54 import junit.framework.TestSuite; 55 56 public class ExecutorsTest extends JSR166TestCase { 57 public static void main(String[] args) { 58 main(suite(), args); 59 } 60 public static Test suite() { 61 return new TestSuite(ExecutorsTest.class); 62 } 63 64 /** 65 * A newCachedThreadPool can execute runnables 66 */ 67 public void testNewCachedThreadPool1() { 68 final ExecutorService e = Executors.newCachedThreadPool(); 69 try (PoolCleaner cleaner = cleaner(e)) { 70 e.execute(new NoOpRunnable()); 71 e.execute(new NoOpRunnable()); 72 e.execute(new NoOpRunnable()); 73 } 74 } 75 76 /** 77 * A newCachedThreadPool with given ThreadFactory can execute runnables 78 */ 79 public void testNewCachedThreadPool2() { 80 final ExecutorService e = Executors.newCachedThreadPool(new SimpleThreadFactory()); 81 try (PoolCleaner cleaner = cleaner(e)) { 82 e.execute(new NoOpRunnable()); 83 e.execute(new NoOpRunnable()); 84 e.execute(new NoOpRunnable()); 85 } 86 } 87 88 /** 89 * A newCachedThreadPool with null ThreadFactory throws NPE 90 */ 91 public void testNewCachedThreadPool3() { 92 try { 93 ExecutorService e = Executors.newCachedThreadPool(null); 94 shouldThrow(); 95 } catch (NullPointerException success) {} 96 } 97 98 /** 99 * A new SingleThreadExecutor can execute runnables 100 */ 101 public void testNewSingleThreadExecutor1() { 102 final ExecutorService e = Executors.newSingleThreadExecutor(); 103 try (PoolCleaner cleaner = cleaner(e)) { 104 e.execute(new NoOpRunnable()); 105 e.execute(new NoOpRunnable()); 106 e.execute(new NoOpRunnable()); 107 } 108 } 109 110 /** 111 * A new SingleThreadExecutor with given ThreadFactory can execute runnables 112 */ 113 public void testNewSingleThreadExecutor2() { 114 final ExecutorService e = Executors.newSingleThreadExecutor(new SimpleThreadFactory()); 115 try (PoolCleaner cleaner = cleaner(e)) { 116 e.execute(new NoOpRunnable()); 117 e.execute(new NoOpRunnable()); 118 e.execute(new NoOpRunnable()); 119 } 120 } 121 122 /** 123 * A new SingleThreadExecutor with null ThreadFactory throws NPE 124 */ 125 public void testNewSingleThreadExecutor3() { 126 try { 127 ExecutorService e = Executors.newSingleThreadExecutor(null); 128 shouldThrow(); 129 } catch (NullPointerException success) {} 130 } 131 132 /** 133 * A new SingleThreadExecutor cannot be casted to concrete implementation 134 */ 135 public void testCastNewSingleThreadExecutor() { 136 final ExecutorService e = Executors.newSingleThreadExecutor(); 137 try (PoolCleaner cleaner = cleaner(e)) { 138 try { 139 ThreadPoolExecutor tpe = (ThreadPoolExecutor)e; 140 shouldThrow(); 141 } catch (ClassCastException success) {} 142 } 143 } 144 145 /** 146 * A new newFixedThreadPool can execute runnables 147 */ 148 public void testNewFixedThreadPool1() { 149 final ExecutorService e = Executors.newFixedThreadPool(2); 150 try (PoolCleaner cleaner = cleaner(e)) { 151 e.execute(new NoOpRunnable()); 152 e.execute(new NoOpRunnable()); 153 e.execute(new NoOpRunnable()); 154 } 155 } 156 157 /** 158 * A new newFixedThreadPool with given ThreadFactory can execute runnables 159 */ 160 public void testNewFixedThreadPool2() { 161 final ExecutorService e = Executors.newFixedThreadPool(2, new SimpleThreadFactory()); 162 try (PoolCleaner cleaner = cleaner(e)) { 163 e.execute(new NoOpRunnable()); 164 e.execute(new NoOpRunnable()); 165 e.execute(new NoOpRunnable()); 166 } 167 } 168 169 /** 170 * A new newFixedThreadPool with null ThreadFactory throws 171 * NullPointerException 172 */ 173 public void testNewFixedThreadPool3() { 174 try { 175 ExecutorService e = Executors.newFixedThreadPool(2, null); 176 shouldThrow(); 177 } catch (NullPointerException success) {} 178 } 179 180 /** 181 * A new newFixedThreadPool with 0 threads throws IllegalArgumentException 182 */ 183 public void testNewFixedThreadPool4() { 184 try { 185 ExecutorService e = Executors.newFixedThreadPool(0); 186 shouldThrow(); 187 } catch (IllegalArgumentException success) {} 188 } 189 190 /** 191 * An unconfigurable newFixedThreadPool can execute runnables 192 */ 193 public void testUnconfigurableExecutorService() { 194 final ExecutorService e = Executors.unconfigurableExecutorService(Executors.newFixedThreadPool(2)); 195 try (PoolCleaner cleaner = cleaner(e)) { 196 e.execute(new NoOpRunnable()); 197 e.execute(new NoOpRunnable()); 198 e.execute(new NoOpRunnable()); 199 } 200 } 201 202 /** 203 * unconfigurableExecutorService(null) throws NPE 204 */ 205 public void testUnconfigurableExecutorServiceNPE() { 206 try { 207 ExecutorService e = Executors.unconfigurableExecutorService(null); 208 shouldThrow(); 209 } catch (NullPointerException success) {} 210 } 211 212 /** 213 * unconfigurableScheduledExecutorService(null) throws NPE 214 */ 215 public void testUnconfigurableScheduledExecutorServiceNPE() { 216 try { 217 ExecutorService e = Executors.unconfigurableScheduledExecutorService(null); 218 shouldThrow(); 219 } catch (NullPointerException success) {} 220 } 221 222 /** 223 * a newSingleThreadScheduledExecutor successfully runs delayed task 224 */ 225 public void testNewSingleThreadScheduledExecutor() throws Exception { 226 final ScheduledExecutorService p = Executors.newSingleThreadScheduledExecutor(); 227 try (PoolCleaner cleaner = cleaner(p)) { 228 final CountDownLatch proceed = new CountDownLatch(1); 229 final Runnable task = new CheckedRunnable() { 230 public void realRun() { 231 await(proceed); 232 }}; 233 long startTime = System.nanoTime(); 234 Future f = p.schedule(Executors.callable(task, Boolean.TRUE), 235 timeoutMillis(), MILLISECONDS); 236 assertFalse(f.isDone()); 237 proceed.countDown(); 238 assertSame(Boolean.TRUE, f.get(LONG_DELAY_MS, MILLISECONDS)); 239 assertSame(Boolean.TRUE, f.get()); 240 assertTrue(f.isDone()); 241 assertFalse(f.isCancelled()); 242 assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); 243 } 244 } 245 246 /** 247 * a newScheduledThreadPool successfully runs delayed task 248 */ 249 public void testNewScheduledThreadPool() throws Exception { 250 final ScheduledExecutorService p = Executors.newScheduledThreadPool(2); 251 try (PoolCleaner cleaner = cleaner(p)) { 252 final CountDownLatch proceed = new CountDownLatch(1); 253 final Runnable task = new CheckedRunnable() { 254 public void realRun() { 255 await(proceed); 256 }}; 257 long startTime = System.nanoTime(); 258 Future f = p.schedule(Executors.callable(task, Boolean.TRUE), 259 timeoutMillis(), MILLISECONDS); 260 assertFalse(f.isDone()); 261 proceed.countDown(); 262 assertSame(Boolean.TRUE, f.get(LONG_DELAY_MS, MILLISECONDS)); 263 assertSame(Boolean.TRUE, f.get()); 264 assertTrue(f.isDone()); 265 assertFalse(f.isCancelled()); 266 assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); 267 } 268 } 269 270 /** 271 * an unconfigurable newScheduledThreadPool successfully runs delayed task 272 */ 273 public void testUnconfigurableScheduledExecutorService() throws Exception { 274 final ScheduledExecutorService p = 275 Executors.unconfigurableScheduledExecutorService 276 (Executors.newScheduledThreadPool(2)); 277 try (PoolCleaner cleaner = cleaner(p)) { 278 final CountDownLatch proceed = new CountDownLatch(1); 279 final Runnable task = new CheckedRunnable() { 280 public void realRun() { 281 await(proceed); 282 }}; 283 long startTime = System.nanoTime(); 284 Future f = p.schedule(Executors.callable(task, Boolean.TRUE), 285 timeoutMillis(), MILLISECONDS); 286 assertFalse(f.isDone()); 287 proceed.countDown(); 288 assertSame(Boolean.TRUE, f.get(LONG_DELAY_MS, MILLISECONDS)); 289 assertSame(Boolean.TRUE, f.get()); 290 assertTrue(f.isDone()); 291 assertFalse(f.isCancelled()); 292 assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); 293 } 294 } 295 296 /** 297 * Future.get on submitted tasks will time out if they compute too long. 298 */ 299 public void testTimedCallable() throws Exception { 300 final ExecutorService[] executors = { 301 Executors.newSingleThreadExecutor(), 302 Executors.newCachedThreadPool(), 303 Executors.newFixedThreadPool(2), 304 Executors.newScheduledThreadPool(2), 305 }; 306 307 final Runnable sleeper = new CheckedInterruptedRunnable() { 308 public void realRun() throws InterruptedException { 309 delay(LONG_DELAY_MS); 310 }}; 311 312 List<Thread> threads = new ArrayList<>(); 313 for (final ExecutorService executor : executors) { 314 threads.add(newStartedThread(new CheckedRunnable() { 315 public void realRun() { 316 Future future = executor.submit(sleeper); 317 assertFutureTimesOut(future); 318 }})); 319 } 320 for (Thread thread : threads) 321 awaitTermination(thread); 322 for (ExecutorService executor : executors) 323 joinPool(executor); 324 } 325 326 /** 327 * ThreadPoolExecutor using defaultThreadFactory has 328 * specified group, priority, daemon status, and name 329 */ 330 public void testDefaultThreadFactory() throws Exception { 331 final ThreadGroup egroup = Thread.currentThread().getThreadGroup(); 332 final CountDownLatch done = new CountDownLatch(1); 333 Runnable r = new CheckedRunnable() { 334 public void realRun() { 335 try { 336 Thread current = Thread.currentThread(); 337 assertFalse(current.isDaemon()); 338 assertTrue(current.getPriority() <= Thread.NORM_PRIORITY); 339 SecurityManager s = System.getSecurityManager(); 340 assertSame(current.getThreadGroup(), 341 (s == null) ? egroup : s.getThreadGroup()); 342 assertTrue(current.getName().endsWith("thread-1")); 343 } catch (SecurityException ok) { 344 // Also pass if not allowed to change setting 345 } 346 done.countDown(); 347 }}; 348 ExecutorService e = Executors.newSingleThreadExecutor(Executors.defaultThreadFactory()); 349 try (PoolCleaner cleaner = cleaner(e)) { 350 e.execute(r); 351 await(done); 352 } 353 } 354 355 /** 356 * ThreadPoolExecutor using privilegedThreadFactory has 357 * specified group, priority, daemon status, name, 358 * access control context and context class loader 359 */ 360 public void testPrivilegedThreadFactory() throws Exception { 361 final CountDownLatch done = new CountDownLatch(1); 362 Runnable r = new CheckedRunnable() { 363 public void realRun() throws Exception { 364 final ThreadGroup egroup = Thread.currentThread().getThreadGroup(); 365 final ClassLoader thisccl = Thread.currentThread().getContextClassLoader(); 366 final AccessControlContext thisacc = AccessController.getContext(); 367 Runnable r = new CheckedRunnable() { 368 public void realRun() { 369 Thread current = Thread.currentThread(); 370 assertFalse(current.isDaemon()); 371 assertTrue(current.getPriority() <= Thread.NORM_PRIORITY); 372 SecurityManager s = System.getSecurityManager(); 373 assertSame(current.getThreadGroup(), 374 (s == null) ? egroup : s.getThreadGroup()); 375 assertTrue(current.getName().endsWith("thread-1")); 376 assertSame(thisccl, current.getContextClassLoader()); 377 assertEquals(thisacc, AccessController.getContext()); 378 done.countDown(); 379 }}; 380 ExecutorService e = Executors.newSingleThreadExecutor(Executors.privilegedThreadFactory()); 381 try (PoolCleaner cleaner = cleaner(e)) { 382 e.execute(r); 383 await(done); 384 } 385 }}; 386 387 runWithPermissions(r, 388 new RuntimePermission("getClassLoader"), 389 new RuntimePermission("setContextClassLoader"), 390 new RuntimePermission("modifyThread")); 391 } 392 393 boolean haveCCLPermissions() { 394 SecurityManager sm = System.getSecurityManager(); 395 if (sm != null) { 396 try { 397 sm.checkPermission(new RuntimePermission("setContextClassLoader")); 398 sm.checkPermission(new RuntimePermission("getClassLoader")); 399 } catch (AccessControlException e) { 400 return false; 401 } 402 } 403 return true; 404 } 405 406 void checkCCL() { 407 SecurityManager sm = System.getSecurityManager(); 408 if (sm != null) { 409 sm.checkPermission(new RuntimePermission("setContextClassLoader")); 410 sm.checkPermission(new RuntimePermission("getClassLoader")); 411 } 412 } 413 414 class CheckCCL implements Callable<Object> { 415 public Object call() { 416 checkCCL(); 417 return null; 418 } 419 } 420 421 /** 422 * Without class loader permissions, creating 423 * privilegedCallableUsingCurrentClassLoader throws ACE 424 */ 425 public void testCreatePrivilegedCallableUsingCCLWithNoPrivs() { 426 Runnable r = new CheckedRunnable() { 427 public void realRun() throws Exception { 428 if (System.getSecurityManager() == null) 429 return; 430 try { 431 Executors.privilegedCallableUsingCurrentClassLoader(new NoOpCallable()); 432 shouldThrow(); 433 } catch (AccessControlException success) {} 434 }}; 435 436 runWithoutPermissions(r); 437 } 438 439 /** 440 * With class loader permissions, calling 441 * privilegedCallableUsingCurrentClassLoader does not throw ACE 442 */ 443 public void testPrivilegedCallableUsingCCLWithPrivs() throws Exception { 444 Runnable r = new CheckedRunnable() { 445 public void realRun() throws Exception { 446 Executors.privilegedCallableUsingCurrentClassLoader 447 (new NoOpCallable()) 448 .call(); 449 }}; 450 451 runWithPermissions(r, 452 new RuntimePermission("getClassLoader"), 453 new RuntimePermission("setContextClassLoader")); 454 } 455 456 /** 457 * Without permissions, calling privilegedCallable throws ACE 458 */ 459 public void testPrivilegedCallableWithNoPrivs() throws Exception { 460 // Avoid classloader-related SecurityExceptions in swingui.TestRunner 461 Executors.privilegedCallable(new CheckCCL()); 462 463 Runnable r = new CheckedRunnable() { 464 public void realRun() throws Exception { 465 if (System.getSecurityManager() == null) 466 return; 467 Callable task = Executors.privilegedCallable(new CheckCCL()); 468 try { 469 task.call(); 470 shouldThrow(); 471 } catch (AccessControlException success) {} 472 }}; 473 474 runWithoutPermissions(r); 475 476 // It seems rather difficult to test that the 477 // AccessControlContext of the privilegedCallable is used 478 // instead of its caller. Below is a failed attempt to do 479 // that, which does not work because the AccessController 480 // cannot capture the internal state of the current Policy. 481 // It would be much more work to differentiate based on, 482 // e.g. CodeSource. 483 484 // final AccessControlContext[] noprivAcc = new AccessControlContext[1]; 485 // final Callable[] task = new Callable[1]; 486 487 // runWithPermissions 488 // (new CheckedRunnable() { 489 // public void realRun() { 490 // if (System.getSecurityManager() == null) 491 // return; 492 // noprivAcc[0] = AccessController.getContext(); 493 // task[0] = Executors.privilegedCallable(new CheckCCL()); 494 // try { 495 // AccessController.doPrivileged(new PrivilegedAction<Void>() { 496 // public Void run() { 497 // checkCCL(); 498 // return null; 499 // }}, noprivAcc[0]); 500 // shouldThrow(); 501 // } catch (AccessControlException success) {} 502 // }}); 503 504 // runWithPermissions 505 // (new CheckedRunnable() { 506 // public void realRun() throws Exception { 507 // if (System.getSecurityManager() == null) 508 // return; 509 // // Verify that we have an underprivileged ACC 510 // try { 511 // AccessController.doPrivileged(new PrivilegedAction<Void>() { 512 // public Void run() { 513 // checkCCL(); 514 // return null; 515 // }}, noprivAcc[0]); 516 // shouldThrow(); 517 // } catch (AccessControlException success) {} 518 519 // try { 520 // task[0].call(); 521 // shouldThrow(); 522 // } catch (AccessControlException success) {} 523 // }}, 524 // new RuntimePermission("getClassLoader"), 525 // new RuntimePermission("setContextClassLoader")); 526 } 527 528 /** 529 * With permissions, calling privilegedCallable succeeds 530 */ 531 public void testPrivilegedCallableWithPrivs() throws Exception { 532 Runnable r = new CheckedRunnable() { 533 public void realRun() throws Exception { 534 Executors.privilegedCallable(new CheckCCL()).call(); 535 }}; 536 537 runWithPermissions(r, 538 new RuntimePermission("getClassLoader"), 539 new RuntimePermission("setContextClassLoader")); 540 } 541 542 /** 543 * callable(Runnable) returns null when called 544 */ 545 public void testCallable1() throws Exception { 546 Callable c = Executors.callable(new NoOpRunnable()); 547 assertNull(c.call()); 548 } 549 550 /** 551 * callable(Runnable, result) returns result when called 552 */ 553 public void testCallable2() throws Exception { 554 Callable c = Executors.callable(new NoOpRunnable(), one); 555 assertSame(one, c.call()); 556 } 557 558 /** 559 * callable(PrivilegedAction) returns its result when called 560 */ 561 public void testCallable3() throws Exception { 562 Callable c = Executors.callable(new PrivilegedAction() { 563 public Object run() { return one; }}); 564 assertSame(one, c.call()); 565 } 566 567 /** 568 * callable(PrivilegedExceptionAction) returns its result when called 569 */ 570 public void testCallable4() throws Exception { 571 Callable c = Executors.callable(new PrivilegedExceptionAction() { 572 public Object run() { return one; }}); 573 assertSame(one, c.call()); 574 } 575 576 /** 577 * callable(null Runnable) throws NPE 578 */ 579 public void testCallableNPE1() { 580 try { 581 Callable c = Executors.callable((Runnable) null); 582 shouldThrow(); 583 } catch (NullPointerException success) {} 584 } 585 586 /** 587 * callable(null, result) throws NPE 588 */ 589 public void testCallableNPE2() { 590 try { 591 Callable c = Executors.callable((Runnable) null, one); 592 shouldThrow(); 593 } catch (NullPointerException success) {} 594 } 595 596 /** 597 * callable(null PrivilegedAction) throws NPE 598 */ 599 public void testCallableNPE3() { 600 try { 601 Callable c = Executors.callable((PrivilegedAction) null); 602 shouldThrow(); 603 } catch (NullPointerException success) {} 604 } 605 606 /** 607 * callable(null PrivilegedExceptionAction) throws NPE 608 */ 609 public void testCallableNPE4() { 610 try { 611 Callable c = Executors.callable((PrivilegedExceptionAction) null); 612 shouldThrow(); 613 } catch (NullPointerException success) {} 614 } 615 616 /** 617 * callable(runnable, x).toString() contains toString of wrapped task 618 */ 619 public void testCallable_withResult_toString() { 620 if (testImplementationDetails) { 621 Runnable r = () -> {}; 622 Callable<String> c = Executors.callable(r, ""); 623 assertEquals( 624 identityString(c) + "[Wrapped task = " + r.toString() + "]", 625 c.toString()); 626 } 627 } 628 629 /** 630 * callable(runnable).toString() contains toString of wrapped task 631 */ 632 public void testCallable_toString() { 633 if (testImplementationDetails) { 634 Runnable r = () -> {}; 635 Callable<Object> c = Executors.callable(r); 636 assertEquals( 637 identityString(c) + "[Wrapped task = " + r.toString() + "]", 638 c.toString()); 639 } 640 } 641 642 /** 643 * privilegedCallable(callable).toString() contains toString of wrapped task 644 */ 645 public void testPrivilegedCallable_toString() { 646 if (testImplementationDetails) { 647 Callable<String> c = () -> ""; 648 Callable<String> priv = Executors.privilegedCallable(c); 649 assertEquals( 650 identityString(priv) + "[Wrapped task = " + c.toString() + "]", 651 priv.toString()); 652 } 653 } 654 655 /** 656 * privilegedCallableUsingCurrentClassLoader(callable).toString() 657 * contains toString of wrapped task 658 */ 659 public void testPrivilegedCallableUsingCurrentClassLoader_toString() { 660 if (testImplementationDetails) { 661 Callable<String> c = () -> ""; 662 Callable<String> priv = Executors.privilegedCallableUsingCurrentClassLoader(c); 663 assertEquals( 664 identityString(priv) + "[Wrapped task = " + c.toString() + "]", 665 priv.toString()); 666 } 667 } 668 }