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