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 */ 33 34 package test.java.util.concurrent.tck; 35 36 import static java.util.concurrent.TimeUnit.MILLISECONDS; 37 import static org.junit.Assert.assertEquals; 38 import static org.junit.Assert.assertFalse; 39 import static org.junit.Assert.assertNull; 40 import static org.junit.Assert.assertSame; 41 import static org.junit.Assert.assertTrue; 42 43 import java.util.HashSet; 44 import java.util.concurrent.CancellationException; 45 import java.util.concurrent.CountedCompleter; 46 import java.util.concurrent.ExecutionException; 47 import java.util.concurrent.ForkJoinPool; 48 import java.util.concurrent.ForkJoinTask; 49 import java.util.concurrent.RecursiveAction; 50 import java.util.concurrent.TimeoutException; 51 import java.util.concurrent.Callable; 52 53 import org.junit.Test; 54 import org.junit.runner.RunWith; 55 import org.junit.runners.JUnit4; 56 57 /** 58 * Tests for ForkJoinPool and corresponding ForkJoinTask additions. 59 */ 60 // Android-changed: Use JUnit4. 61 @RunWith(JUnit4.class) 62 public class ForkJoinPool19Test extends JSR166TestCase { 63 // Android-changed: Use JUnitCore.main. main(String[] args)64 public static void main(String[] args) { 65 // main(suite(), args); 66 org.junit.runner.JUnitCore.main("test.java.util.concurrent.tck.ForkJoinPool19Test"); 67 } 68 69 // public static Test suite() { 70 // return new TestSuite(ForkJoinPool19Test.class); 71 // } 72 73 /** 74 * SetParallelism sets reported parallellism and returns previous value 75 */ 76 @Test testSetParallelism()77 public void testSetParallelism() { 78 final ForkJoinPool p = new ForkJoinPool(2); 79 assertEquals(2, p.getParallelism()); 80 assertEquals(2, p.setParallelism(3)); 81 assertEquals(3, p.setParallelism(2)); 82 p.shutdown(); 83 } 84 /** 85 * SetParallelism throws exception if argument out of bounds 86 */ 87 @Test testSetParallelismBadArgs()88 public void testSetParallelismBadArgs() { 89 final ForkJoinPool p = new ForkJoinPool(2); 90 try { 91 p.setParallelism(0); 92 shouldThrow(); 93 } catch (Exception success) { 94 } 95 try { 96 p.setParallelism(Integer.MAX_VALUE); 97 shouldThrow(); 98 } catch (Exception success) { 99 } 100 assertEquals(2, p.getParallelism()); 101 p.shutdown(); 102 } 103 104 105 /* 106 * Some test methods adapted from RecursiveAction 107 */ mainPool()108 private static ForkJoinPool mainPool() { 109 return new ForkJoinPool(); 110 } 111 testInvokeOnPool(ForkJoinPool pool, RecursiveAction a)112 private void testInvokeOnPool(ForkJoinPool pool, RecursiveAction a) { 113 try (PoolCleaner cleaner = cleaner(pool)) { 114 checkNotDone(a); 115 assertNull(pool.invoke(a)); 116 checkCompletedNormally(a); 117 } 118 } 119 checkInvoke(ForkJoinTask<?> a)120 private void checkInvoke(ForkJoinTask<?> a) { 121 checkNotDone(a); 122 assertNull(a.invoke()); 123 checkCompletedNormally(a); 124 } 125 checkNotDone(ForkJoinTask<?> a)126 void checkNotDone(ForkJoinTask<?> a) { 127 assertFalse(a.isDone()); 128 assertFalse(a.isCompletedNormally()); 129 assertFalse(a.isCompletedAbnormally()); 130 assertFalse(a.isCancelled()); 131 assertNull(a.getException()); 132 assertNull(a.getRawResult()); 133 134 if (! ForkJoinTask.inForkJoinPool()) { 135 Thread.currentThread().interrupt(); 136 try { 137 a.get(); 138 shouldThrow(); 139 } catch (InterruptedException success) { 140 } catch (Throwable fail) { threadUnexpectedException(fail); } 141 142 Thread.currentThread().interrupt(); 143 try { 144 a.get(randomTimeout(), randomTimeUnit()); 145 shouldThrow(); 146 } catch (InterruptedException success) { 147 } catch (Throwable fail) { threadUnexpectedException(fail); } 148 } 149 150 try { 151 a.get(randomExpiredTimeout(), randomTimeUnit()); 152 shouldThrow(); 153 } catch (TimeoutException success) { 154 } catch (Throwable fail) { threadUnexpectedException(fail); } 155 } 156 checkCompletedNormally(ForkJoinTask<?> a)157 void checkCompletedNormally(ForkJoinTask<?> a) { 158 assertTrue(a.isDone()); 159 assertFalse(a.isCancelled()); 160 assertTrue(a.isCompletedNormally()); 161 assertFalse(a.isCompletedAbnormally()); 162 assertNull(a.getException()); 163 assertNull(a.getRawResult()); 164 assertNull(a.join()); 165 assertFalse(a.cancel(false)); 166 assertFalse(a.cancel(true)); 167 168 Object v1 = null, v2 = null; 169 try { 170 v1 = a.get(); 171 v2 = a.get(randomTimeout(), randomTimeUnit()); 172 } catch (Throwable fail) { threadUnexpectedException(fail); } 173 assertNull(v1); 174 assertNull(v2); 175 } 176 checkCancelled(ForkJoinTask<?> a)177 void checkCancelled(ForkJoinTask<?> a) { 178 assertTrue(a.isDone()); 179 assertTrue(a.isCancelled()); 180 assertFalse(a.isCompletedNormally()); 181 assertTrue(a.isCompletedAbnormally()); 182 assertTrue(a.getException() instanceof CancellationException); 183 assertNull(a.getRawResult()); 184 185 try { 186 a.join(); 187 shouldThrow(); 188 } catch (CancellationException success) { 189 } catch (Throwable fail) { threadUnexpectedException(fail); } 190 191 try { 192 a.get(); 193 shouldThrow(); 194 } catch (CancellationException success) { 195 } catch (Throwable fail) { threadUnexpectedException(fail); } 196 197 try { 198 a.get(randomTimeout(), randomTimeUnit()); 199 shouldThrow(); 200 } catch (CancellationException success) { 201 } catch (Throwable fail) { threadUnexpectedException(fail); } 202 } 203 checkCompletedAbnormally(ForkJoinTask<?> a, Throwable t)204 void checkCompletedAbnormally(ForkJoinTask<?> a, Throwable t) { 205 assertTrue(a.isDone()); 206 assertFalse(a.isCancelled()); 207 assertFalse(a.isCompletedNormally()); 208 assertTrue(a.isCompletedAbnormally()); 209 assertSame(t.getClass(), a.getException().getClass()); 210 assertNull(a.getRawResult()); 211 assertFalse(a.cancel(false)); 212 assertFalse(a.cancel(true)); 213 214 try { 215 a.join(); 216 shouldThrow(); 217 } catch (Throwable expected) { 218 assertSame(expected.getClass(), t.getClass()); 219 } 220 221 try { 222 a.get(); 223 shouldThrow(); 224 } catch (ExecutionException success) { 225 assertSame(t.getClass(), success.getCause().getClass()); 226 } catch (Throwable fail) { threadUnexpectedException(fail); } 227 228 try { 229 a.get(randomTimeout(), randomTimeUnit()); 230 shouldThrow(); 231 } catch (ExecutionException success) { 232 assertSame(t.getClass(), success.getCause().getClass()); 233 } catch (Throwable fail) { threadUnexpectedException(fail); } 234 } 235 236 public static final class FJException extends RuntimeException { FJException()237 public FJException() { super(); } FJException(Throwable cause)238 public FJException(Throwable cause) { super(cause); } 239 } 240 241 /** A simple recursive action for testing. */ 242 final class FibAction extends CheckedRecursiveAction { 243 final int number; 244 int result; FibAction(int n)245 FibAction(int n) { number = n; } realCompute()246 protected void realCompute() { 247 int n = number; 248 if (n <= 1) 249 result = n; 250 else { 251 FibAction f1 = new FibAction(n - 1); 252 FibAction f2 = new FibAction(n - 2); 253 invokeAll(f1, f2); 254 result = f1.result + f2.result; 255 } 256 } 257 } 258 259 /** A recursive action failing in base case. */ 260 static final class FailingFibAction extends RecursiveAction { 261 final int number; 262 int result; FailingFibAction(int n)263 FailingFibAction(int n) { number = n; } compute()264 public void compute() { 265 int n = number; 266 if (n <= 1) 267 throw new FJException(); 268 else { 269 FailingFibAction f1 = new FailingFibAction(n - 1); 270 FailingFibAction f2 = new FailingFibAction(n - 2); 271 invokeAll(f1, f2); 272 result = f1.result + f2.result; 273 } 274 } 275 } 276 277 /** 278 * lazySubmit submits a task that is not executed until new 279 * workers are created or it is explicitly joined by a worker. 280 */ 281 @SuppressWarnings("removal") 282 @Test testLazySubmit()283 public void testLazySubmit() { 284 ForkJoinPool p; 285 try { 286 p = new ForkJoinPool(); 287 } catch (java.security.AccessControlException e) { 288 return; 289 } 290 FibAction f = new FibAction(8); 291 RecursiveAction j = new RecursiveAction() { 292 protected void compute() { 293 f.join(); 294 }}; 295 RecursiveAction a = new CheckedRecursiveAction() { 296 protected void realCompute() { 297 p.invoke(new FibAction(8)); 298 p.lazySubmit(f); 299 p.invoke(new FibAction(8)); 300 p.invoke(j); 301 assertEquals(21, f.result); 302 checkCompletedNormally(f); 303 }}; 304 testInvokeOnPool(p, a); 305 } 306 307 /** 308 * quietlyInvoke task returns when task completes normally. 309 * isCompletedAbnormally and isCancelled return false for normally 310 * completed tasks 311 */ 312 @Test testQuietlyInvoke()313 public void testQuietlyInvoke() { 314 RecursiveAction a = new CheckedRecursiveAction() { 315 protected void realCompute() { 316 FibAction f = new FibAction(8); 317 f.quietlyInvoke(); 318 assertEquals(21, f.result); 319 checkCompletedNormally(f); 320 }}; 321 checkInvoke(a); 322 } 323 324 /** 325 * join of a forked task returns when task completes 326 */ 327 @Test testForkJoin()328 public void testForkJoin() { 329 RecursiveAction a = new CheckedRecursiveAction() { 330 protected void realCompute() { 331 FibAction f = new FibAction(8); 332 assertSame(f, f.fork()); 333 assertNull(f.join()); 334 assertEquals(21, f.result); 335 checkCompletedNormally(f); 336 }}; 337 checkInvoke(a); 338 } 339 340 /** 341 * timed quietlyJoinUninterruptibly of a forked task succeeds in 342 * the presence of interrupts 343 */ 344 @Test testTimedQuietlyJoinUninterruptiblyInterrupts()345 public void testTimedQuietlyJoinUninterruptiblyInterrupts() { 346 RecursiveAction a = new CheckedRecursiveAction() { 347 protected void realCompute() { 348 FibAction f; 349 final Thread currentThread = Thread.currentThread(); 350 351 // test quietlyJoin() 352 f = new FibAction(8); 353 assertSame(f, f.fork()); 354 currentThread.interrupt(); 355 f.quietlyJoinUninterruptibly(LONG_DELAY_MS, MILLISECONDS); 356 Thread.interrupted(); 357 assertEquals(21, f.result); 358 checkCompletedNormally(f); 359 360 f = new FibAction(8); 361 f.cancel(true); 362 assertSame(f, f.fork()); 363 currentThread.interrupt(); 364 f.quietlyJoinUninterruptibly(LONG_DELAY_MS, MILLISECONDS); 365 Thread.interrupted(); 366 checkCancelled(f); 367 368 f = new FibAction(8); 369 f.completeExceptionally(new FJException()); 370 assertSame(f, f.fork()); 371 currentThread.interrupt(); 372 f.quietlyJoinUninterruptibly(LONG_DELAY_MS, MILLISECONDS); 373 Thread.interrupted(); 374 checkCompletedAbnormally(f, f.getException()); 375 }}; 376 checkInvoke(a); 377 a.reinitialize(); 378 checkInvoke(a); 379 } 380 381 /** 382 * timed quietlyJoin throws IE in the presence of interrupts 383 */ 384 @Test testTimedQuietlyJoinInterrupts()385 public void testTimedQuietlyJoinInterrupts() { 386 RecursiveAction a = new CheckedRecursiveAction() { 387 protected void realCompute() { 388 FibAction f; 389 final Thread currentThread = Thread.currentThread(); 390 391 f = new FibAction(8); 392 assertSame(f, f.fork()); 393 currentThread.interrupt(); 394 try { 395 f.quietlyJoin(LONG_DELAY_MS, MILLISECONDS); 396 } catch (InterruptedException success) { 397 } 398 Thread.interrupted(); 399 f.quietlyJoin(); 400 401 f = new FibAction(8); 402 f.cancel(true); 403 assertSame(f, f.fork()); 404 currentThread.interrupt(); 405 try { 406 f.quietlyJoin(LONG_DELAY_MS, MILLISECONDS); 407 } catch (InterruptedException success) { 408 } 409 f.quietlyJoin(); 410 checkCancelled(f); 411 }}; 412 checkInvoke(a); 413 a.reinitialize(); 414 checkInvoke(a); 415 } 416 417 /** 418 * timed quietlyJoin of a forked task returns when task completes 419 */ 420 @Test testForkTimedQuietlyJoin()421 public void testForkTimedQuietlyJoin() { 422 RecursiveAction a = new CheckedRecursiveAction() { 423 protected void realCompute() throws Exception { 424 FibAction f = new FibAction(8); 425 assertSame(f, f.fork()); 426 assertTrue(f.quietlyJoin(LONG_DELAY_MS, MILLISECONDS)); 427 assertEquals(21, f.result); 428 checkCompletedNormally(f); 429 }}; 430 checkInvoke(a); 431 } 432 433 /** 434 * timed quietlyJoin with null time unit throws NPE 435 */ 436 @Test testForkTimedQuietlyJoinNPE()437 public void testForkTimedQuietlyJoinNPE() { 438 RecursiveAction a = new CheckedRecursiveAction() { 439 protected void realCompute() throws Exception { 440 FibAction f = new FibAction(8); 441 assertSame(f, f.fork()); 442 try { 443 f.quietlyJoin(randomTimeout(), null); 444 shouldThrow(); 445 } catch (NullPointerException success) {} 446 }}; 447 checkInvoke(a); 448 } 449 450 /** 451 * quietlyInvoke task returns when task completes abnormally 452 */ 453 @Test testAbnormalTimedQuietlyJoin()454 public void testAbnormalTimedQuietlyJoin() { 455 RecursiveAction a = new CheckedRecursiveAction() { 456 protected void realCompute() throws Exception { 457 FailingFibAction f = new FailingFibAction(8); 458 assertSame(f, f.fork()); 459 assertTrue(f.quietlyJoin(LONG_DELAY_MS, MILLISECONDS)); 460 assertTrue(f.getException() instanceof FJException); 461 checkCompletedAbnormally(f, f.getException()); 462 }}; 463 checkInvoke(a); 464 } 465 466 /** 467 * timed quietlyJoinUninterruptibly of a forked task returns when task completes 468 */ 469 @Test testForkTimedQuietlyJoinUninterruptibly()470 public void testForkTimedQuietlyJoinUninterruptibly() { 471 RecursiveAction a = new CheckedRecursiveAction() { 472 protected void realCompute() throws Exception { 473 FibAction f = new FibAction(8); 474 assertSame(f, f.fork()); 475 assertTrue(f.quietlyJoinUninterruptibly(LONG_DELAY_MS, MILLISECONDS)); 476 assertEquals(21, f.result); 477 checkCompletedNormally(f); 478 }}; 479 checkInvoke(a); 480 } 481 482 /** 483 * timed quietlyJoinUninterruptibly with null time unit throws NPE 484 */ 485 @Test testForkTimedQuietlyJoinUninterruptiblyNPE()486 public void testForkTimedQuietlyJoinUninterruptiblyNPE() { 487 RecursiveAction a = new CheckedRecursiveAction() { 488 protected void realCompute() throws Exception { 489 FibAction f = new FibAction(8); 490 assertSame(f, f.fork()); 491 try { 492 f.quietlyJoinUninterruptibly(randomTimeout(), null); 493 shouldThrow(); 494 } catch (NullPointerException success) {} 495 }}; 496 checkInvoke(a); 497 } 498 499 /** 500 * quietlyInvoke task returns when task completes abnormally 501 */ 502 @Test testAbnormalTimedQuietlyJoinUninterruptibly()503 public void testAbnormalTimedQuietlyJoinUninterruptibly() { 504 RecursiveAction a = new CheckedRecursiveAction() { 505 protected void realCompute() { 506 FailingFibAction f = new FailingFibAction(8); 507 assertSame(f, f.fork()); 508 assertTrue(f.quietlyJoinUninterruptibly(LONG_DELAY_MS, MILLISECONDS)); 509 assertTrue(f.getException() instanceof FJException); 510 checkCompletedAbnormally(f, f.getException()); 511 }}; 512 checkInvoke(a); 513 } 514 515 /** 516 * adaptInterruptible(callable).toString() contains toString of wrapped task 517 */ 518 @Test testAdaptInterruptible_Callable_toString()519 public void testAdaptInterruptible_Callable_toString() { 520 if (testImplementationDetails) { 521 Callable<String> c = () -> ""; 522 ForkJoinTask<String> task = ForkJoinTask.adaptInterruptible(c); 523 assertEquals( 524 identityString(task) + "[Wrapped task = " + c.toString() + "]", 525 task.toString()); 526 } 527 } 528 529 /** 530 * Implicitly closing a new pool using try-with-resources terminates it 531 */ 532 @Test testClose()533 public void testClose() { 534 ForkJoinTask f = new FibAction(8); 535 ForkJoinPool pool = null; 536 try (ForkJoinPool p = new ForkJoinPool()) { 537 pool = p; 538 p.execute(f); 539 } 540 checkCompletedNormally(f); 541 assertTrue(pool != null && pool.isTerminated()); 542 } 543 544 /** 545 * Implicitly closing common pool using try-with-resources has no effect. 546 */ 547 @Test testCloseCommonPool()548 public void testCloseCommonPool() { 549 ForkJoinTask f = new FibAction(8); 550 ForkJoinPool pool; 551 try (ForkJoinPool p = pool = ForkJoinPool.commonPool()) { 552 p.execute(f); 553 } 554 555 assertFalse(pool.isShutdown()); 556 assertFalse(pool.isTerminating()); 557 assertFalse(pool.isTerminated()); 558 559 String prop = System.getProperty( 560 "java.util.concurrent.ForkJoinPool.common.parallelism"); 561 if (! "0".equals(prop)) { 562 f.join(); 563 checkCompletedNormally(f); 564 } 565 } 566 567 } 568