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