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 unused = 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 unused = 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 unused = 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 unused = 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 unused = 208 Executors.unconfigurableExecutorService(null); 209 shouldThrow(); 210 } catch (NullPointerException success) {} 211 } 212 213 /** 214 * unconfigurableScheduledExecutorService(null) throws NPE 215 */ 216 public void testUnconfigurableScheduledExecutorServiceNPE() { 217 try { 218 ExecutorService unused = 219 Executors.unconfigurableScheduledExecutorService(null); 220 shouldThrow(); 221 } catch (NullPointerException success) {} 222 } 223 224 /** 225 * a newSingleThreadScheduledExecutor successfully runs delayed task 226 */ 227 public void testNewSingleThreadScheduledExecutor() throws Exception { 228 final ScheduledExecutorService p = Executors.newSingleThreadScheduledExecutor(); 229 try (PoolCleaner cleaner = cleaner(p)) { 230 final CountDownLatch proceed = new CountDownLatch(1); 231 final Runnable task = new CheckedRunnable() { 232 public void realRun() { 233 await(proceed); 234 }}; 235 long startTime = System.nanoTime(); 236 Future f = p.schedule(Executors.callable(task, Boolean.TRUE), 237 timeoutMillis(), MILLISECONDS); 238 assertFalse(f.isDone()); 239 proceed.countDown(); 240 assertSame(Boolean.TRUE, f.get(LONG_DELAY_MS, MILLISECONDS)); 241 assertSame(Boolean.TRUE, f.get()); 242 assertTrue(f.isDone()); 243 assertFalse(f.isCancelled()); 244 assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); 245 } 246 } 247 248 /** 249 * a newScheduledThreadPool successfully runs delayed task 250 */ 251 public void testNewScheduledThreadPool() throws Exception { 252 final ScheduledExecutorService p = Executors.newScheduledThreadPool(2); 253 try (PoolCleaner cleaner = cleaner(p)) { 254 final CountDownLatch proceed = new CountDownLatch(1); 255 final Runnable task = new CheckedRunnable() { 256 public void realRun() { 257 await(proceed); 258 }}; 259 long startTime = System.nanoTime(); 260 Future f = p.schedule(Executors.callable(task, Boolean.TRUE), 261 timeoutMillis(), MILLISECONDS); 262 assertFalse(f.isDone()); 263 proceed.countDown(); 264 assertSame(Boolean.TRUE, f.get(LONG_DELAY_MS, MILLISECONDS)); 265 assertSame(Boolean.TRUE, f.get()); 266 assertTrue(f.isDone()); 267 assertFalse(f.isCancelled()); 268 assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); 269 } 270 } 271 272 /** 273 * an unconfigurable newScheduledThreadPool successfully runs delayed task 274 */ 275 public void testUnconfigurableScheduledExecutorService() throws Exception { 276 final ScheduledExecutorService p = 277 Executors.unconfigurableScheduledExecutorService 278 (Executors.newScheduledThreadPool(2)); 279 try (PoolCleaner cleaner = cleaner(p)) { 280 final CountDownLatch proceed = new CountDownLatch(1); 281 final Runnable task = new CheckedRunnable() { 282 public void realRun() { 283 await(proceed); 284 }}; 285 long startTime = System.nanoTime(); 286 Future f = p.schedule(Executors.callable(task, Boolean.TRUE), 287 timeoutMillis(), MILLISECONDS); 288 assertFalse(f.isDone()); 289 proceed.countDown(); 290 assertSame(Boolean.TRUE, f.get(LONG_DELAY_MS, MILLISECONDS)); 291 assertSame(Boolean.TRUE, f.get()); 292 assertTrue(f.isDone()); 293 assertFalse(f.isCancelled()); 294 assertTrue(millisElapsedSince(startTime) >= timeoutMillis()); 295 } 296 } 297 298 /** 299 * Future.get on submitted tasks will time out if they compute too long. 300 */ 301 public void testTimedCallable() throws Exception { 302 final ExecutorService[] executors = { 303 Executors.newSingleThreadExecutor(), 304 Executors.newCachedThreadPool(), 305 Executors.newFixedThreadPool(2), 306 Executors.newScheduledThreadPool(2), 307 }; 308 309 final CountDownLatch done = new CountDownLatch(1); 310 311 final Runnable sleeper = new CheckedRunnable() { 312 public void realRun() throws InterruptedException { 313 done.await(LONG_DELAY_MS, MILLISECONDS); 314 }}; 315 316 List<Thread> threads = new ArrayList<>(); 317 for (final ExecutorService executor : executors) { 318 threads.add(newStartedThread(new CheckedRunnable() { 319 public void realRun() { 320 Future future = executor.submit(sleeper); 321 assertFutureTimesOut(future); 322 }})); 323 } 324 for (Thread thread : threads) 325 awaitTermination(thread); 326 done.countDown(); 327 for (ExecutorService executor : executors) 328 joinPool(executor); 329 } 330 331 /** 332 * ThreadPoolExecutor using defaultThreadFactory has 333 * specified group, priority, daemon status, and name 334 */ 335 public void testDefaultThreadFactory() throws Exception { 336 final ThreadGroup egroup = Thread.currentThread().getThreadGroup(); 337 final CountDownLatch done = new CountDownLatch(1); 338 Runnable r = new CheckedRunnable() { 339 public void realRun() { 340 try { 341 Thread current = Thread.currentThread(); 342 assertFalse(current.isDaemon()); 343 assertTrue(current.getPriority() <= Thread.NORM_PRIORITY); 344 SecurityManager s = System.getSecurityManager(); 345 assertSame(current.getThreadGroup(), 346 (s == null) ? egroup : s.getThreadGroup()); 347 assertTrue(current.getName().endsWith("thread-1")); 348 } catch (SecurityException ok) { 349 // Also pass if not allowed to change setting 350 } 351 done.countDown(); 352 }}; 353 ExecutorService e = Executors.newSingleThreadExecutor(Executors.defaultThreadFactory()); 354 try (PoolCleaner cleaner = cleaner(e)) { 355 e.execute(r); 356 await(done); 357 } 358 } 359 360 /** 361 * ThreadPoolExecutor using privilegedThreadFactory has 362 * specified group, priority, daemon status, name, 363 * access control context and context class loader 364 */ 365 public void testPrivilegedThreadFactory() throws Exception { 366 final CountDownLatch done = new CountDownLatch(1); 367 Runnable r = new CheckedRunnable() { 368 public void realRun() throws Exception { 369 final ThreadGroup egroup = Thread.currentThread().getThreadGroup(); 370 final ClassLoader thisccl = Thread.currentThread().getContextClassLoader(); 371 final AccessControlContext thisacc = AccessController.getContext(); 372 Runnable r = new CheckedRunnable() { 373 public void realRun() { 374 Thread current = Thread.currentThread(); 375 assertFalse(current.isDaemon()); 376 assertTrue(current.getPriority() <= Thread.NORM_PRIORITY); 377 SecurityManager s = System.getSecurityManager(); 378 assertSame(current.getThreadGroup(), 379 (s == null) ? egroup : s.getThreadGroup()); 380 assertTrue(current.getName().endsWith("thread-1")); 381 assertSame(thisccl, current.getContextClassLoader()); 382 assertEquals(thisacc, AccessController.getContext()); 383 done.countDown(); 384 }}; 385 ExecutorService e = Executors.newSingleThreadExecutor(Executors.privilegedThreadFactory()); 386 try (PoolCleaner cleaner = cleaner(e)) { 387 e.execute(r); 388 await(done); 389 } 390 }}; 391 392 runWithPermissions(r, 393 new RuntimePermission("getClassLoader"), 394 new RuntimePermission("setContextClassLoader"), 395 new RuntimePermission("modifyThread")); 396 } 397 398 boolean haveCCLPermissions() { 399 SecurityManager sm = System.getSecurityManager(); 400 if (sm != null) { 401 try { 402 sm.checkPermission(new RuntimePermission("setContextClassLoader")); 403 sm.checkPermission(new RuntimePermission("getClassLoader")); 404 } catch (AccessControlException e) { 405 return false; 406 } 407 } 408 return true; 409 } 410 411 void checkCCL() { 412 SecurityManager sm = System.getSecurityManager(); 413 if (sm != null) { 414 sm.checkPermission(new RuntimePermission("setContextClassLoader")); 415 sm.checkPermission(new RuntimePermission("getClassLoader")); 416 } 417 } 418 419 class CheckCCL implements Callable<Object> { 420 public Object call() { 421 checkCCL(); 422 return null; 423 } 424 } 425 426 /** 427 * Without class loader permissions, creating 428 * privilegedCallableUsingCurrentClassLoader throws ACE 429 */ 430 public void testCreatePrivilegedCallableUsingCCLWithNoPrivs() { 431 Runnable r = new CheckedRunnable() { 432 public void realRun() throws Exception { 433 if (System.getSecurityManager() == null) 434 return; 435 try { 436 Executors.privilegedCallableUsingCurrentClassLoader(new NoOpCallable()); 437 shouldThrow(); 438 } catch (AccessControlException success) {} 439 }}; 440 441 runWithoutPermissions(r); 442 } 443 444 /** 445 * With class loader permissions, calling 446 * privilegedCallableUsingCurrentClassLoader does not throw ACE 447 */ 448 public void testPrivilegedCallableUsingCCLWithPrivs() throws Exception { 449 Runnable r = new CheckedRunnable() { 450 public void realRun() throws Exception { 451 Executors.privilegedCallableUsingCurrentClassLoader 452 (new NoOpCallable()) 453 .call(); 454 }}; 455 456 runWithPermissions(r, 457 new RuntimePermission("getClassLoader"), 458 new RuntimePermission("setContextClassLoader")); 459 } 460 461 /** 462 * Without permissions, calling privilegedCallable throws ACE 463 */ 464 public void testPrivilegedCallableWithNoPrivs() throws Exception { 465 // Avoid classloader-related SecurityExceptions in swingui.TestRunner 466 Executors.privilegedCallable(new CheckCCL()); 467 468 Runnable r = new CheckedRunnable() { 469 public void realRun() throws Exception { 470 if (System.getSecurityManager() == null) 471 return; 472 Callable task = Executors.privilegedCallable(new CheckCCL()); 473 try { 474 task.call(); 475 shouldThrow(); 476 } catch (AccessControlException success) {} 477 }}; 478 479 runWithoutPermissions(r); 480 481 // It seems rather difficult to test that the 482 // AccessControlContext of the privilegedCallable is used 483 // instead of its caller. Below is a failed attempt to do 484 // that, which does not work because the AccessController 485 // cannot capture the internal state of the current Policy. 486 // It would be much more work to differentiate based on, 487 // e.g. CodeSource. 488 489 // final AccessControlContext[] noprivAcc = new AccessControlContext[1]; 490 // final Callable[] task = new Callable[1]; 491 492 // runWithPermissions 493 // (new CheckedRunnable() { 494 // public void realRun() { 495 // if (System.getSecurityManager() == null) 496 // return; 497 // noprivAcc[0] = AccessController.getContext(); 498 // task[0] = Executors.privilegedCallable(new CheckCCL()); 499 // try { 500 // AccessController.doPrivileged(new PrivilegedAction<Void>() { 501 // public Void run() { 502 // checkCCL(); 503 // return null; 504 // }}, noprivAcc[0]); 505 // shouldThrow(); 506 // } catch (AccessControlException success) {} 507 // }}); 508 509 // runWithPermissions 510 // (new CheckedRunnable() { 511 // public void realRun() throws Exception { 512 // if (System.getSecurityManager() == null) 513 // return; 514 // // Verify that we have an underprivileged ACC 515 // try { 516 // AccessController.doPrivileged(new PrivilegedAction<Void>() { 517 // public Void run() { 518 // checkCCL(); 519 // return null; 520 // }}, noprivAcc[0]); 521 // shouldThrow(); 522 // } catch (AccessControlException success) {} 523 524 // try { 525 // task[0].call(); 526 // shouldThrow(); 527 // } catch (AccessControlException success) {} 528 // }}, 529 // new RuntimePermission("getClassLoader"), 530 // new RuntimePermission("setContextClassLoader")); 531 } 532 533 /** 534 * With permissions, calling privilegedCallable succeeds 535 */ 536 public void testPrivilegedCallableWithPrivs() throws Exception { 537 Runnable r = new CheckedRunnable() { 538 public void realRun() throws Exception { 539 Executors.privilegedCallable(new CheckCCL()).call(); 540 }}; 541 542 runWithPermissions(r, 543 new RuntimePermission("getClassLoader"), 544 new RuntimePermission("setContextClassLoader")); 545 } 546 547 /** 548 * callable(Runnable) returns null when called 549 */ 550 public void testCallable1() throws Exception { 551 Callable c = Executors.callable(new NoOpRunnable()); 552 assertNull(c.call()); 553 } 554 555 /** 556 * callable(Runnable, result) returns result when called 557 */ 558 public void testCallable2() throws Exception { 559 Callable c = Executors.callable(new NoOpRunnable(), one); 560 assertSame(one, c.call()); 561 } 562 563 /** 564 * callable(PrivilegedAction) returns its result when called 565 */ 566 public void testCallable3() throws Exception { 567 Callable c = Executors.callable(new PrivilegedAction() { 568 public Object run() { return one; }}); 569 assertSame(one, c.call()); 570 } 571 572 /** 573 * callable(PrivilegedExceptionAction) returns its result when called 574 */ 575 public void testCallable4() throws Exception { 576 Callable c = Executors.callable(new PrivilegedExceptionAction() { 577 public Object run() { return one; }}); 578 assertSame(one, c.call()); 579 } 580 581 /** 582 * callable(null Runnable) throws NPE 583 */ 584 public void testCallableNPE1() { 585 try { 586 Callable unused = Executors.callable((Runnable) null); 587 shouldThrow(); 588 } catch (NullPointerException success) {} 589 } 590 591 /** 592 * callable(null, result) throws NPE 593 */ 594 public void testCallableNPE2() { 595 try { 596 Callable unused = Executors.callable((Runnable) null, one); 597 shouldThrow(); 598 } catch (NullPointerException success) {} 599 } 600 601 /** 602 * callable(null PrivilegedAction) throws NPE 603 */ 604 public void testCallableNPE3() { 605 try { 606 Callable unused = Executors.callable((PrivilegedAction) null); 607 shouldThrow(); 608 } catch (NullPointerException success) {} 609 } 610 611 /** 612 * callable(null PrivilegedExceptionAction) throws NPE 613 */ 614 public void testCallableNPE4() { 615 try { 616 Callable unused = Executors.callable((PrivilegedExceptionAction) null); 617 shouldThrow(); 618 } catch (NullPointerException success) {} 619 } 620 621 /** 622 * callable(runnable, x).toString() contains toString of wrapped task 623 */ 624 public void testCallable_withResult_toString() { 625 if (testImplementationDetails) { 626 Runnable r = () -> {}; 627 Callable<String> c = Executors.callable(r, ""); 628 assertEquals( 629 identityString(c) + "[Wrapped task = " + r.toString() + "]", 630 c.toString()); 631 } 632 } 633 634 /** 635 * callable(runnable).toString() contains toString of wrapped task 636 */ 637 public void testCallable_toString() { 638 if (testImplementationDetails) { 639 Runnable r = () -> {}; 640 Callable<Object> c = Executors.callable(r); 641 assertEquals( 642 identityString(c) + "[Wrapped task = " + r.toString() + "]", 643 c.toString()); 644 } 645 } 646 647 /** 648 * privilegedCallable(callable).toString() contains toString of wrapped task 649 */ 650 public void testPrivilegedCallable_toString() { 651 if (testImplementationDetails) { 652 Callable<String> c = () -> ""; 653 Callable<String> priv = Executors.privilegedCallable(c); 654 assertEquals( 655 identityString(priv) + "[Wrapped task = " + c.toString() + "]", 656 priv.toString()); 657 } 658 } 659 660 /** 661 * privilegedCallableUsingCurrentClassLoader(callable).toString() 662 * contains toString of wrapped task 663 */ 664 public void testPrivilegedCallableUsingCurrentClassLoader_toString() { 665 if (testImplementationDetails) { 666 Callable<String> c = () -> ""; 667 Callable<String> priv = Executors.privilegedCallableUsingCurrentClassLoader(c); 668 assertEquals( 669 identityString(priv) + "[Wrapped task = " + c.toString() + "]", 670 priv.toString()); 671 } 672 } 673 }