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 package test.java.util.concurrent.tck; 37 import static java.util.concurrent.TimeUnit.MILLISECONDS; 38 39 import java.security.AccessControlContext; 40 import java.security.AccessControlException; 41 import java.security.AccessController; 42 import java.security.PrivilegedAction; 43 import java.security.PrivilegedExceptionAction; 44 import java.util.ArrayList; 45 import java.util.List; 46 import java.util.concurrent.Callable; 47 import java.util.concurrent.CountDownLatch; 48 import java.util.concurrent.Executors; 49 import java.util.concurrent.ExecutorService; 50 import java.util.concurrent.Future; 51 import java.util.concurrent.ScheduledExecutorService; 52 import java.util.concurrent.ThreadPoolExecutor; 53 54 import junit.framework.Test; 55 import junit.framework.TestSuite; 56 57 public class ExecutorsTest extends JSR166TestCase { main(String[] args)58 public static void main(String[] args) { 59 main(suite(), args); 60 } suite()61 public static Test suite() { 62 return new TestSuite(ExecutorsTest.class); 63 } 64 65 /** 66 * A newCachedThreadPool can execute runnables 67 */ testNewCachedThreadPool1()68 public void testNewCachedThreadPool1() { 69 final ExecutorService e = Executors.newCachedThreadPool(); 70 try (PoolCleaner cleaner = cleaner(e)) { 71 e.execute(new NoOpRunnable()); 72 e.execute(new NoOpRunnable()); 73 e.execute(new NoOpRunnable()); 74 } 75 } 76 77 /** 78 * A newCachedThreadPool with given ThreadFactory can execute runnables 79 */ testNewCachedThreadPool2()80 public void testNewCachedThreadPool2() { 81 final ExecutorService e = Executors.newCachedThreadPool(new SimpleThreadFactory()); 82 try (PoolCleaner cleaner = cleaner(e)) { 83 e.execute(new NoOpRunnable()); 84 e.execute(new NoOpRunnable()); 85 e.execute(new NoOpRunnable()); 86 } 87 } 88 89 /** 90 * A newCachedThreadPool with null ThreadFactory throws NPE 91 */ testNewCachedThreadPool3()92 public void testNewCachedThreadPool3() { 93 try { 94 ExecutorService e = Executors.newCachedThreadPool(null); 95 shouldThrow(); 96 } catch (NullPointerException success) {} 97 } 98 99 /** 100 * A new SingleThreadExecutor can execute runnables 101 */ testNewSingleThreadExecutor1()102 public void testNewSingleThreadExecutor1() { 103 final ExecutorService e = Executors.newSingleThreadExecutor(); 104 try (PoolCleaner cleaner = cleaner(e)) { 105 e.execute(new NoOpRunnable()); 106 e.execute(new NoOpRunnable()); 107 e.execute(new NoOpRunnable()); 108 } 109 } 110 111 /** 112 * A new SingleThreadExecutor with given ThreadFactory can execute runnables 113 */ testNewSingleThreadExecutor2()114 public void testNewSingleThreadExecutor2() { 115 final ExecutorService e = Executors.newSingleThreadExecutor(new SimpleThreadFactory()); 116 try (PoolCleaner cleaner = cleaner(e)) { 117 e.execute(new NoOpRunnable()); 118 e.execute(new NoOpRunnable()); 119 e.execute(new NoOpRunnable()); 120 } 121 } 122 123 /** 124 * A new SingleThreadExecutor with null ThreadFactory throws NPE 125 */ testNewSingleThreadExecutor3()126 public void testNewSingleThreadExecutor3() { 127 try { 128 ExecutorService e = Executors.newSingleThreadExecutor(null); 129 shouldThrow(); 130 } catch (NullPointerException success) {} 131 } 132 133 /** 134 * A new SingleThreadExecutor cannot be casted to concrete implementation 135 */ testCastNewSingleThreadExecutor()136 public void testCastNewSingleThreadExecutor() { 137 final ExecutorService e = Executors.newSingleThreadExecutor(); 138 try (PoolCleaner cleaner = cleaner(e)) { 139 try { 140 ThreadPoolExecutor tpe = (ThreadPoolExecutor)e; 141 shouldThrow(); 142 } catch (ClassCastException success) {} 143 } 144 } 145 146 /** 147 * A new newFixedThreadPool can execute runnables 148 */ testNewFixedThreadPool1()149 public void testNewFixedThreadPool1() { 150 final ExecutorService e = Executors.newFixedThreadPool(2); 151 try (PoolCleaner cleaner = cleaner(e)) { 152 e.execute(new NoOpRunnable()); 153 e.execute(new NoOpRunnable()); 154 e.execute(new NoOpRunnable()); 155 } 156 } 157 158 /** 159 * A new newFixedThreadPool with given ThreadFactory can execute runnables 160 */ testNewFixedThreadPool2()161 public void testNewFixedThreadPool2() { 162 final ExecutorService e = Executors.newFixedThreadPool(2, new SimpleThreadFactory()); 163 try (PoolCleaner cleaner = cleaner(e)) { 164 e.execute(new NoOpRunnable()); 165 e.execute(new NoOpRunnable()); 166 e.execute(new NoOpRunnable()); 167 } 168 } 169 170 /** 171 * A new newFixedThreadPool with null ThreadFactory throws NPE 172 */ testNewFixedThreadPool3()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 IAE 182 */ testNewFixedThreadPool4()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 */ testUnconfigurableExecutorService()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 */ testUnconfigurableExecutorServiceNPE()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 */ testUnconfigurableScheduledExecutorServiceNPE()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 */ testNewSingleThreadScheduledExecutor()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 */ testNewScheduledThreadPool()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 */ testUnconfigurableScheduledExecutorService()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 */ testTimedCallable()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 */ testDefaultThreadFactory()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 assertTrue(!current.isDaemon()); 338 assertTrue(current.getPriority() <= Thread.NORM_PRIORITY); 339 ThreadGroup g = current.getThreadGroup(); 340 SecurityManager s = System.getSecurityManager(); 341 if (s != null) 342 assertTrue(g == s.getThreadGroup()); 343 else 344 assertTrue(g == egroup); 345 String name = current.getName(); 346 assertTrue(name.endsWith("thread-1")); 347 } catch (SecurityException ok) { 348 // Also pass if not allowed to change setting 349 } 350 done.countDown(); 351 }}; 352 ExecutorService e = Executors.newSingleThreadExecutor(Executors.defaultThreadFactory()); 353 try (PoolCleaner cleaner = cleaner(e)) { 354 e.execute(r); 355 await(done); 356 } 357 } 358 359 /** 360 * ThreadPoolExecutor using privilegedThreadFactory has 361 * specified group, priority, daemon status, name, 362 * access control context and context class loader 363 */ testPrivilegedThreadFactory()364 public void testPrivilegedThreadFactory() throws Exception { 365 final CountDownLatch done = new CountDownLatch(1); 366 Runnable r = new CheckedRunnable() { 367 public void realRun() throws Exception { 368 final ThreadGroup egroup = Thread.currentThread().getThreadGroup(); 369 final ClassLoader thisccl = Thread.currentThread().getContextClassLoader(); 370 final AccessControlContext thisacc = AccessController.getContext(); 371 Runnable r = new CheckedRunnable() { 372 public void realRun() { 373 Thread current = Thread.currentThread(); 374 assertTrue(!current.isDaemon()); 375 assertTrue(current.getPriority() <= Thread.NORM_PRIORITY); 376 ThreadGroup g = current.getThreadGroup(); 377 SecurityManager s = System.getSecurityManager(); 378 if (s != null) 379 assertTrue(g == s.getThreadGroup()); 380 else 381 assertTrue(g == egroup); 382 String name = current.getName(); 383 assertTrue(name.endsWith("thread-1")); 384 assertSame(thisccl, current.getContextClassLoader()); 385 // Android-removed: Android doesn't support real AccessControlContext. 386 // assertEquals(thisacc, AccessController.getCossntext()); 387 done.countDown(); 388 }}; 389 ExecutorService e = Executors.newSingleThreadExecutor(Executors.privilegedThreadFactory()); 390 try (PoolCleaner cleaner = cleaner(e)) { 391 e.execute(r); 392 await(done); 393 } 394 }}; 395 396 runWithPermissions(r, 397 new RuntimePermission("getClassLoader"), 398 new RuntimePermission("setContextClassLoader"), 399 new RuntimePermission("modifyThread")); 400 } 401 haveCCLPermissions()402 boolean haveCCLPermissions() { 403 SecurityManager sm = System.getSecurityManager(); 404 if (sm != null) { 405 try { 406 sm.checkPermission(new RuntimePermission("setContextClassLoader")); 407 sm.checkPermission(new RuntimePermission("getClassLoader")); 408 } catch (AccessControlException e) { 409 return false; 410 } 411 } 412 return true; 413 } 414 checkCCL()415 void checkCCL() { 416 SecurityManager sm = System.getSecurityManager(); 417 if (sm != null) { 418 sm.checkPermission(new RuntimePermission("setContextClassLoader")); 419 sm.checkPermission(new RuntimePermission("getClassLoader")); 420 } 421 } 422 423 class CheckCCL implements Callable<Object> { call()424 public Object call() { 425 checkCCL(); 426 return null; 427 } 428 } 429 430 /** 431 * Without class loader permissions, creating 432 * privilegedCallableUsingCurrentClassLoader throws ACE 433 */ testCreatePrivilegedCallableUsingCCLWithNoPrivs()434 public void testCreatePrivilegedCallableUsingCCLWithNoPrivs() { 435 Runnable r = new CheckedRunnable() { 436 public void realRun() throws Exception { 437 if (System.getSecurityManager() == null) 438 return; 439 try { 440 Executors.privilegedCallableUsingCurrentClassLoader(new NoOpCallable()); 441 shouldThrow(); 442 } catch (AccessControlException success) {} 443 }}; 444 445 runWithoutPermissions(r); 446 } 447 448 /** 449 * With class loader permissions, calling 450 * privilegedCallableUsingCurrentClassLoader does not throw ACE 451 */ testPrivilegedCallableUsingCCLWithPrivs()452 public void testPrivilegedCallableUsingCCLWithPrivs() throws Exception { 453 Runnable r = new CheckedRunnable() { 454 public void realRun() throws Exception { 455 Executors.privilegedCallableUsingCurrentClassLoader 456 (new NoOpCallable()) 457 .call(); 458 }}; 459 460 runWithPermissions(r, 461 new RuntimePermission("getClassLoader"), 462 new RuntimePermission("setContextClassLoader")); 463 } 464 465 /** 466 * Without permissions, calling privilegedCallable throws ACE 467 */ testPrivilegedCallableWithNoPrivs()468 public void testPrivilegedCallableWithNoPrivs() throws Exception { 469 // Avoid classloader-related SecurityExceptions in swingui.TestRunner 470 Executors.privilegedCallable(new CheckCCL()); 471 472 Runnable r = new CheckedRunnable() { 473 public void realRun() throws Exception { 474 if (System.getSecurityManager() == null) 475 return; 476 Callable task = Executors.privilegedCallable(new CheckCCL()); 477 try { 478 task.call(); 479 shouldThrow(); 480 } catch (AccessControlException success) {} 481 }}; 482 483 runWithoutPermissions(r); 484 485 // It seems rather difficult to test that the 486 // AccessControlContext of the privilegedCallable is used 487 // instead of its caller. Below is a failed attempt to do 488 // that, which does not work because the AccessController 489 // cannot capture the internal state of the current Policy. 490 // It would be much more work to differentiate based on, 491 // e.g. CodeSource. 492 493 // final AccessControlContext[] noprivAcc = new AccessControlContext[1]; 494 // final Callable[] task = new Callable[1]; 495 496 // runWithPermissions 497 // (new CheckedRunnable() { 498 // public void realRun() { 499 // if (System.getSecurityManager() == null) 500 // return; 501 // noprivAcc[0] = AccessController.getContext(); 502 // task[0] = Executors.privilegedCallable(new CheckCCL()); 503 // try { 504 // AccessController.doPrivileged(new PrivilegedAction<Void>() { 505 // public Void run() { 506 // checkCCL(); 507 // return null; 508 // }}, noprivAcc[0]); 509 // shouldThrow(); 510 // } catch (AccessControlException success) {} 511 // }}); 512 513 // runWithPermissions 514 // (new CheckedRunnable() { 515 // public void realRun() throws Exception { 516 // if (System.getSecurityManager() == null) 517 // return; 518 // // Verify that we have an underprivileged ACC 519 // try { 520 // AccessController.doPrivileged(new PrivilegedAction<Void>() { 521 // public Void run() { 522 // checkCCL(); 523 // return null; 524 // }}, noprivAcc[0]); 525 // shouldThrow(); 526 // } catch (AccessControlException success) {} 527 528 // try { 529 // task[0].call(); 530 // shouldThrow(); 531 // } catch (AccessControlException success) {} 532 // }}, 533 // new RuntimePermission("getClassLoader"), 534 // new RuntimePermission("setContextClassLoader")); 535 } 536 537 /** 538 * With permissions, calling privilegedCallable succeeds 539 */ testPrivilegedCallableWithPrivs()540 public void testPrivilegedCallableWithPrivs() throws Exception { 541 Runnable r = new CheckedRunnable() { 542 public void realRun() throws Exception { 543 Executors.privilegedCallable(new CheckCCL()).call(); 544 }}; 545 546 runWithPermissions(r, 547 new RuntimePermission("getClassLoader"), 548 new RuntimePermission("setContextClassLoader")); 549 } 550 551 /** 552 * callable(Runnable) returns null when called 553 */ testCallable1()554 public void testCallable1() throws Exception { 555 Callable c = Executors.callable(new NoOpRunnable()); 556 assertNull(c.call()); 557 } 558 559 /** 560 * callable(Runnable, result) returns result when called 561 */ testCallable2()562 public void testCallable2() throws Exception { 563 Callable c = Executors.callable(new NoOpRunnable(), one); 564 assertSame(one, c.call()); 565 } 566 567 /** 568 * callable(PrivilegedAction) returns its result when called 569 */ testCallable3()570 public void testCallable3() throws Exception { 571 Callable c = Executors.callable(new PrivilegedAction() { 572 public Object run() { return one; }}); 573 assertSame(one, c.call()); 574 } 575 576 /** 577 * callable(PrivilegedExceptionAction) returns its result when called 578 */ testCallable4()579 public void testCallable4() throws Exception { 580 Callable c = Executors.callable(new PrivilegedExceptionAction() { 581 public Object run() { return one; }}); 582 assertSame(one, c.call()); 583 } 584 585 /** 586 * callable(null Runnable) throws NPE 587 */ testCallableNPE1()588 public void testCallableNPE1() { 589 try { 590 Callable c = Executors.callable((Runnable) null); 591 shouldThrow(); 592 } catch (NullPointerException success) {} 593 } 594 595 /** 596 * callable(null, result) throws NPE 597 */ testCallableNPE2()598 public void testCallableNPE2() { 599 try { 600 Callable c = Executors.callable((Runnable) null, one); 601 shouldThrow(); 602 } catch (NullPointerException success) {} 603 } 604 605 /** 606 * callable(null PrivilegedAction) throws NPE 607 */ testCallableNPE3()608 public void testCallableNPE3() { 609 try { 610 Callable c = Executors.callable((PrivilegedAction) null); 611 shouldThrow(); 612 } catch (NullPointerException success) {} 613 } 614 615 /** 616 * callable(null PrivilegedExceptionAction) throws NPE 617 */ testCallableNPE4()618 public void testCallableNPE4() { 619 try { 620 Callable c = Executors.callable((PrivilegedExceptionAction) null); 621 shouldThrow(); 622 } catch (NullPointerException success) {} 623 } 624 625 } 626