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 package jsr166; 10 11 import static java.util.concurrent.TimeUnit.MILLISECONDS; 12 13 import java.security.PrivilegedAction; 14 import java.security.PrivilegedExceptionAction; 15 import java.util.ArrayList; 16 import java.util.Collections; 17 import java.util.List; 18 import java.util.concurrent.AbstractExecutorService; 19 import java.util.concurrent.ArrayBlockingQueue; 20 import java.util.concurrent.Callable; 21 import java.util.concurrent.CancellationException; 22 import java.util.concurrent.CountDownLatch; 23 import java.util.concurrent.ExecutionException; 24 import java.util.concurrent.Executors; 25 import java.util.concurrent.ExecutorService; 26 import java.util.concurrent.Future; 27 import java.util.concurrent.ThreadPoolExecutor; 28 import java.util.concurrent.TimeUnit; 29 import java.util.concurrent.atomic.AtomicBoolean; 30 31 import junit.framework.Test; 32 import junit.framework.TestSuite; 33 34 public class AbstractExecutorServiceTest extends JSR166TestCase { 35 // android-note: Removed because the CTS runner does a bad job of 36 // retrying tests that have suite() declarations. 37 // 38 // public static void main(String[] args) { 39 // main(suite(), args); 40 // } 41 // public static Test suite() { 42 // return new TestSuite(AbstractExecutorServiceTest.class); 43 // } 44 45 /** 46 * A no-frills implementation of AbstractExecutorService, designed 47 * to test the submit methods only. 48 */ 49 static class DirectExecutorService extends AbstractExecutorService { execute(Runnable r)50 public void execute(Runnable r) { r.run(); } shutdown()51 public void shutdown() { shutdown = true; } shutdownNow()52 public List<Runnable> shutdownNow() { 53 shutdown = true; 54 return Collections.EMPTY_LIST; 55 } isShutdown()56 public boolean isShutdown() { return shutdown; } isTerminated()57 public boolean isTerminated() { return isShutdown(); } awaitTermination(long timeout, TimeUnit unit)58 public boolean awaitTermination(long timeout, TimeUnit unit) { 59 return isShutdown(); 60 } 61 private volatile boolean shutdown = false; 62 } 63 64 /** 65 * execute(runnable) runs it to completion 66 */ testExecuteRunnable()67 public void testExecuteRunnable() throws Exception { 68 ExecutorService e = new DirectExecutorService(); 69 final AtomicBoolean done = new AtomicBoolean(false); 70 Future<?> future = e.submit(new CheckedRunnable() { 71 public void realRun() { 72 done.set(true); 73 }}); 74 assertNull(future.get()); 75 assertNull(future.get(0, MILLISECONDS)); 76 assertTrue(done.get()); 77 assertTrue(future.isDone()); 78 assertFalse(future.isCancelled()); 79 } 80 81 /** 82 * Completed submit(callable) returns result 83 */ testSubmitCallable()84 public void testSubmitCallable() throws Exception { 85 ExecutorService e = new DirectExecutorService(); 86 Future<String> future = e.submit(new StringTask()); 87 String result = future.get(); 88 assertSame(TEST_STRING, result); 89 } 90 91 /** 92 * Completed submit(runnable) returns successfully 93 */ testSubmitRunnable()94 public void testSubmitRunnable() throws Exception { 95 ExecutorService e = new DirectExecutorService(); 96 Future<?> future = e.submit(new NoOpRunnable()); 97 future.get(); 98 assertTrue(future.isDone()); 99 } 100 101 /** 102 * Completed submit(runnable, result) returns result 103 */ testSubmitRunnable2()104 public void testSubmitRunnable2() throws Exception { 105 ExecutorService e = new DirectExecutorService(); 106 Future<String> future = e.submit(new NoOpRunnable(), TEST_STRING); 107 String result = future.get(); 108 assertSame(TEST_STRING, result); 109 } 110 111 /** 112 * A submitted privileged action runs to completion 113 */ testSubmitPrivilegedAction()114 public void testSubmitPrivilegedAction() throws Exception { 115 Runnable r = new CheckedRunnable() { 116 public void realRun() throws Exception { 117 ExecutorService e = new DirectExecutorService(); 118 Future future = e.submit(Executors.callable(new PrivilegedAction() { 119 public Object run() { 120 return TEST_STRING; 121 }})); 122 123 assertSame(TEST_STRING, future.get()); 124 }}; 125 126 runWithPermissions(r, 127 new RuntimePermission("getClassLoader"), 128 new RuntimePermission("setContextClassLoader"), 129 new RuntimePermission("modifyThread")); 130 } 131 132 /** 133 * A submitted privileged exception action runs to completion 134 */ testSubmitPrivilegedExceptionAction()135 public void testSubmitPrivilegedExceptionAction() throws Exception { 136 Runnable r = new CheckedRunnable() { 137 public void realRun() throws Exception { 138 ExecutorService e = new DirectExecutorService(); 139 Future future = e.submit(Executors.callable(new PrivilegedExceptionAction() { 140 public Object run() { 141 return TEST_STRING; 142 }})); 143 144 assertSame(TEST_STRING, future.get()); 145 }}; 146 147 runWithPermissions(r); 148 } 149 150 /** 151 * A submitted failed privileged exception action reports exception 152 */ testSubmitFailedPrivilegedExceptionAction()153 public void testSubmitFailedPrivilegedExceptionAction() throws Exception { 154 Runnable r = new CheckedRunnable() { 155 public void realRun() throws Exception { 156 ExecutorService e = new DirectExecutorService(); 157 Future future = e.submit(Executors.callable(new PrivilegedExceptionAction() { 158 public Object run() throws Exception { 159 throw new IndexOutOfBoundsException(); 160 }})); 161 162 try { 163 future.get(); 164 shouldThrow(); 165 } catch (ExecutionException success) { 166 assertTrue(success.getCause() instanceof IndexOutOfBoundsException); 167 }}}; 168 169 runWithPermissions(r); 170 } 171 172 /** 173 * execute(null runnable) throws NPE 174 */ testExecuteNullRunnable()175 public void testExecuteNullRunnable() { 176 ExecutorService e = new DirectExecutorService(); 177 try { 178 e.submit((Runnable) null); 179 shouldThrow(); 180 } catch (NullPointerException success) {} 181 } 182 183 /** 184 * submit(null callable) throws NPE 185 */ testSubmitNullCallable()186 public void testSubmitNullCallable() { 187 ExecutorService e = new DirectExecutorService(); 188 try { 189 e.submit((Callable) null); 190 shouldThrow(); 191 } catch (NullPointerException success) {} 192 } 193 194 /** 195 * submit(callable).get() throws InterruptedException if interrupted 196 */ testInterruptedSubmit()197 public void testInterruptedSubmit() throws InterruptedException { 198 final CountDownLatch submitted = new CountDownLatch(1); 199 final CountDownLatch quittingTime = new CountDownLatch(1); 200 final Callable<Void> awaiter = new CheckedCallable<Void>() { 201 public Void realCall() throws InterruptedException { 202 assertTrue(quittingTime.await(2*LONG_DELAY_MS, MILLISECONDS)); 203 return null; 204 }}; 205 final ExecutorService p 206 = new ThreadPoolExecutor(1,1,60, TimeUnit.SECONDS, 207 new ArrayBlockingQueue<Runnable>(10)); 208 try (PoolCleaner cleaner = cleaner(p, quittingTime)) { 209 Thread t = newStartedThread(new CheckedInterruptedRunnable() { 210 public void realRun() throws Exception { 211 Future<Void> future = p.submit(awaiter); 212 submitted.countDown(); 213 future.get(); 214 }}); 215 216 await(submitted); 217 t.interrupt(); 218 awaitTermination(t); 219 } 220 } 221 222 /** 223 * get of submit(callable) throws ExecutionException if callable 224 * throws exception 225 */ testSubmitEE()226 public void testSubmitEE() throws InterruptedException { 227 final ThreadPoolExecutor p = 228 new ThreadPoolExecutor(1, 1, 229 60, TimeUnit.SECONDS, 230 new ArrayBlockingQueue<Runnable>(10)); 231 try (PoolCleaner cleaner = cleaner(p)) { 232 Callable c = new Callable() { 233 public Object call() { throw new ArithmeticException(); }}; 234 try { 235 p.submit(c).get(); 236 shouldThrow(); 237 } catch (ExecutionException success) { 238 assertTrue(success.getCause() instanceof ArithmeticException); 239 } 240 } 241 } 242 243 /** 244 * invokeAny(null) throws NPE 245 */ testInvokeAny1()246 public void testInvokeAny1() throws Exception { 247 final ExecutorService e = new DirectExecutorService(); 248 try (PoolCleaner cleaner = cleaner(e)) { 249 try { 250 e.invokeAny(null); 251 shouldThrow(); 252 } catch (NullPointerException success) {} 253 } 254 } 255 256 /** 257 * invokeAny(empty collection) throws IAE 258 */ testInvokeAny2()259 public void testInvokeAny2() throws Exception { 260 final ExecutorService e = new DirectExecutorService(); 261 try (PoolCleaner cleaner = cleaner(e)) { 262 try { 263 e.invokeAny(new ArrayList<Callable<String>>()); 264 shouldThrow(); 265 } catch (IllegalArgumentException success) {} 266 } 267 } 268 269 /** 270 * invokeAny(c) throws NPE if c has null elements 271 */ testInvokeAny3()272 public void testInvokeAny3() throws Exception { 273 final ExecutorService e = new DirectExecutorService(); 274 try (PoolCleaner cleaner = cleaner(e)) { 275 List<Callable<Long>> l = new ArrayList<Callable<Long>>(); 276 l.add(new Callable<Long>() { 277 public Long call() { throw new ArithmeticException(); }}); 278 l.add(null); 279 try { 280 e.invokeAny(l); 281 shouldThrow(); 282 } catch (NullPointerException success) {} 283 } 284 } 285 286 /** 287 * invokeAny(c) throws ExecutionException if no task in c completes 288 */ testInvokeAny4()289 public void testInvokeAny4() throws InterruptedException { 290 final ExecutorService e = new DirectExecutorService(); 291 try (PoolCleaner cleaner = cleaner(e)) { 292 List<Callable<String>> l = new ArrayList<Callable<String>>(); 293 l.add(new NPETask()); 294 try { 295 e.invokeAny(l); 296 shouldThrow(); 297 } catch (ExecutionException success) { 298 assertTrue(success.getCause() instanceof NullPointerException); 299 } 300 } 301 } 302 303 /** 304 * invokeAny(c) returns result of some task in c if at least one completes 305 */ testInvokeAny5()306 public void testInvokeAny5() throws Exception { 307 final ExecutorService e = new DirectExecutorService(); 308 try (PoolCleaner cleaner = cleaner(e)) { 309 List<Callable<String>> l = new ArrayList<Callable<String>>(); 310 l.add(new StringTask()); 311 l.add(new StringTask()); 312 String result = e.invokeAny(l); 313 assertSame(TEST_STRING, result); 314 } 315 } 316 317 /** 318 * invokeAll(null) throws NPE 319 */ testInvokeAll1()320 public void testInvokeAll1() throws InterruptedException { 321 final ExecutorService e = new DirectExecutorService(); 322 try (PoolCleaner cleaner = cleaner(e)) { 323 try { 324 e.invokeAll(null); 325 shouldThrow(); 326 } catch (NullPointerException success) {} 327 } 328 } 329 330 /** 331 * invokeAll(empty collection) returns empty collection 332 */ testInvokeAll2()333 public void testInvokeAll2() throws InterruptedException { 334 final ExecutorService e = new DirectExecutorService(); 335 try (PoolCleaner cleaner = cleaner(e)) { 336 List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>()); 337 assertTrue(r.isEmpty()); 338 } 339 } 340 341 /** 342 * invokeAll(c) throws NPE if c has null elements 343 */ testInvokeAll3()344 public void testInvokeAll3() throws InterruptedException { 345 final ExecutorService e = new DirectExecutorService(); 346 try (PoolCleaner cleaner = cleaner(e)) { 347 List<Callable<String>> l = new ArrayList<Callable<String>>(); 348 l.add(new StringTask()); 349 l.add(null); 350 try { 351 e.invokeAll(l); 352 shouldThrow(); 353 } catch (NullPointerException success) {} 354 } 355 } 356 357 /** 358 * get of returned element of invokeAll(c) throws exception on failed task 359 */ testInvokeAll4()360 public void testInvokeAll4() throws Exception { 361 final ExecutorService e = new DirectExecutorService(); 362 try (PoolCleaner cleaner = cleaner(e)) { 363 List<Callable<String>> l = new ArrayList<Callable<String>>(); 364 l.add(new NPETask()); 365 List<Future<String>> futures = e.invokeAll(l); 366 assertEquals(1, futures.size()); 367 try { 368 futures.get(0).get(); 369 shouldThrow(); 370 } catch (ExecutionException success) { 371 assertTrue(success.getCause() instanceof NullPointerException); 372 } 373 } 374 } 375 376 /** 377 * invokeAll(c) returns results of all completed tasks in c 378 */ testInvokeAll5()379 public void testInvokeAll5() throws Exception { 380 final ExecutorService e = new DirectExecutorService(); 381 try (PoolCleaner cleaner = cleaner(e)) { 382 List<Callable<String>> l = new ArrayList<Callable<String>>(); 383 l.add(new StringTask()); 384 l.add(new StringTask()); 385 List<Future<String>> futures = e.invokeAll(l); 386 assertEquals(2, futures.size()); 387 for (Future<String> future : futures) 388 assertSame(TEST_STRING, future.get()); 389 } 390 } 391 392 /** 393 * timed invokeAny(null) throws NPE 394 */ testTimedInvokeAny1()395 public void testTimedInvokeAny1() throws Exception { 396 final ExecutorService e = new DirectExecutorService(); 397 try (PoolCleaner cleaner = cleaner(e)) { 398 try { 399 e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS); 400 shouldThrow(); 401 } catch (NullPointerException success) {} 402 } 403 } 404 405 /** 406 * timed invokeAny(null time unit) throws NPE 407 */ testTimedInvokeAnyNullTimeUnit()408 public void testTimedInvokeAnyNullTimeUnit() throws Exception { 409 final ExecutorService e = new DirectExecutorService(); 410 try (PoolCleaner cleaner = cleaner(e)) { 411 List<Callable<String>> l = new ArrayList<Callable<String>>(); 412 l.add(new StringTask()); 413 try { 414 e.invokeAny(l, MEDIUM_DELAY_MS, null); 415 shouldThrow(); 416 } catch (NullPointerException success) {} 417 } 418 } 419 420 /** 421 * timed invokeAny(empty collection) throws IAE 422 */ testTimedInvokeAny2()423 public void testTimedInvokeAny2() throws Exception { 424 final ExecutorService e = new DirectExecutorService(); 425 try (PoolCleaner cleaner = cleaner(e)) { 426 try { 427 e.invokeAny(new ArrayList<Callable<String>>(), 428 MEDIUM_DELAY_MS, MILLISECONDS); 429 shouldThrow(); 430 } catch (IllegalArgumentException success) {} 431 } 432 } 433 434 /** 435 * timed invokeAny(c) throws NPE if c has null elements 436 */ testTimedInvokeAny3()437 public void testTimedInvokeAny3() throws Exception { 438 final ExecutorService e = new DirectExecutorService(); 439 try (PoolCleaner cleaner = cleaner(e)) { 440 List<Callable<Long>> l = new ArrayList<Callable<Long>>(); 441 l.add(new Callable<Long>() { 442 public Long call() { throw new ArithmeticException(); }}); 443 l.add(null); 444 try { 445 e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS); 446 shouldThrow(); 447 } catch (NullPointerException success) {} 448 } 449 } 450 451 /** 452 * timed invokeAny(c) throws ExecutionException if no task completes 453 */ testTimedInvokeAny4()454 public void testTimedInvokeAny4() throws Exception { 455 final ExecutorService e = new DirectExecutorService(); 456 try (PoolCleaner cleaner = cleaner(e)) { 457 long startTime = System.nanoTime(); 458 List<Callable<String>> l = new ArrayList<Callable<String>>(); 459 l.add(new NPETask()); 460 try { 461 e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS); 462 shouldThrow(); 463 } catch (ExecutionException success) { 464 assertTrue(success.getCause() instanceof NullPointerException); 465 } 466 assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); 467 } 468 } 469 470 /** 471 * timed invokeAny(c) returns result of some task in c 472 */ 473 public void testTimedInvokeAny5() throws Exception { 474 final ExecutorService e = new DirectExecutorService(); 475 try (PoolCleaner cleaner = cleaner(e)) { 476 long startTime = System.nanoTime(); 477 List<Callable<String>> l = new ArrayList<Callable<String>>(); 478 l.add(new StringTask()); 479 l.add(new StringTask()); 480 String result = e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS); 481 assertSame(TEST_STRING, result); 482 assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS); 483 } 484 } 485 486 /** 487 * timed invokeAll(null) throws NPE 488 */ 489 public void testTimedInvokeAll1() throws InterruptedException { 490 final ExecutorService e = new DirectExecutorService(); 491 try (PoolCleaner cleaner = cleaner(e)) { 492 try { 493 e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS); 494 shouldThrow(); 495 } catch (NullPointerException success) {} 496 } 497 } 498 499 /** 500 * timed invokeAll(null time unit) throws NPE 501 */ 502 public void testTimedInvokeAllNullTimeUnit() throws InterruptedException { 503 final ExecutorService e = new DirectExecutorService(); 504 try (PoolCleaner cleaner = cleaner(e)) { 505 List<Callable<String>> l = new ArrayList<Callable<String>>(); 506 l.add(new StringTask()); 507 try { 508 e.invokeAll(l, MEDIUM_DELAY_MS, null); 509 shouldThrow(); 510 } catch (NullPointerException success) {} 511 } 512 } 513 514 /** 515 * timed invokeAll(empty collection) returns empty collection 516 */ 517 public void testTimedInvokeAll2() throws InterruptedException { 518 final ExecutorService e = new DirectExecutorService(); 519 try (PoolCleaner cleaner = cleaner(e)) { 520 List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS); 521 assertTrue(r.isEmpty()); 522 } 523 } 524 525 /** 526 * timed invokeAll(c) throws NPE if c has null elements 527 */ 528 public void testTimedInvokeAll3() throws InterruptedException { 529 final ExecutorService e = new DirectExecutorService(); 530 try (PoolCleaner cleaner = cleaner(e)) { 531 List<Callable<String>> l = new ArrayList<Callable<String>>(); 532 l.add(new StringTask()); 533 l.add(null); 534 try { 535 e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS); 536 shouldThrow(); 537 } catch (NullPointerException success) {} 538 } 539 } 540 541 /** 542 * get of returned element of invokeAll(c) throws exception on failed task 543 */ 544 public void testTimedInvokeAll4() throws Exception { 545 final ExecutorService e = new DirectExecutorService(); 546 try (PoolCleaner cleaner = cleaner(e)) { 547 List<Callable<String>> l = new ArrayList<Callable<String>>(); 548 l.add(new NPETask()); 549 List<Future<String>> futures = 550 e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS); 551 assertEquals(1, futures.size()); 552 try { 553 futures.get(0).get(); 554 shouldThrow(); 555 } catch (ExecutionException success) { 556 assertTrue(success.getCause() instanceof NullPointerException); 557 } 558 } 559 } 560 561 /** 562 * timed invokeAll(c) returns results of all completed tasks in c 563 */ 564 public void testTimedInvokeAll5() throws Exception { 565 final ExecutorService e = new DirectExecutorService(); 566 try (PoolCleaner cleaner = cleaner(e)) { 567 List<Callable<String>> l = new ArrayList<Callable<String>>(); 568 l.add(new StringTask()); 569 l.add(new StringTask()); 570 List<Future<String>> futures = 571 e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS); 572 assertEquals(2, futures.size()); 573 for (Future<String> future : futures) 574 assertSame(TEST_STRING, future.get()); 575 } 576 } 577 578 /** 579 * timed invokeAll cancels tasks not completed by timeout 580 */ 581 public void testTimedInvokeAll6() throws Exception { 582 final ExecutorService e = new DirectExecutorService(); 583 try (PoolCleaner cleaner = cleaner(e)) { 584 for (long timeout = timeoutMillis();;) { 585 List<Callable<String>> tasks = new ArrayList<>(); 586 tasks.add(new StringTask("0")); 587 tasks.add(Executors.callable(possiblyInterruptedRunnable(timeout), 588 TEST_STRING)); 589 tasks.add(new StringTask("2")); 590 long startTime = System.nanoTime(); 591 List<Future<String>> futures = 592 e.invokeAll(tasks, timeout, MILLISECONDS); 593 assertEquals(tasks.size(), futures.size()); 594 assertTrue(millisElapsedSince(startTime) >= timeout); 595 for (Future future : futures) 596 assertTrue(future.isDone()); 597 try { 598 assertEquals("0", futures.get(0).get()); 599 assertEquals(TEST_STRING, futures.get(1).get()); 600 } catch (CancellationException retryWithLongerTimeout) { 601 // unusual delay before starting second task 602 timeout *= 2; 603 if (timeout >= LONG_DELAY_MS / 2) 604 fail("expected exactly one task to be cancelled"); 605 continue; 606 } 607 assertTrue(futures.get(2).isCancelled()); 608 break; 609 } 610 } 611 } 612 613 } 614