ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/ForkJoinPool19Test.java
Revision: 1.2
Committed: Fri May 6 16:02:32 2022 UTC (22 months, 3 weeks ago) by dl
Branch: MAIN
Changes since 1.1: +27 -0 lines
Log Message:
Sync with openjdk

File Contents

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