ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/PhaserTest.java
Revision: 1.20
Committed: Thu Oct 21 23:28:13 2010 UTC (13 years, 6 months ago) by jsr166
Branch: MAIN
Changes since 1.19: +94 -32 lines
Log Message:
Make "interrupt before/while waiting" tests more deterministic; fails deterministically with current Phaser implementation!

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/licenses/publicdomain
5 * Other contributors include John Vint
6 */
7
8 import java.util.ArrayList;
9 import java.util.List;
10 import java.util.concurrent.atomic.AtomicInteger;
11 import java.util.concurrent.atomic.AtomicBoolean;
12 import java.util.concurrent.*;
13 import static java.util.concurrent.TimeUnit.MILLISECONDS;
14 import static java.util.concurrent.TimeUnit.NANOSECONDS;
15 import junit.framework.Test;
16 import junit.framework.TestSuite;
17
18 public class PhaserTest extends JSR166TestCase {
19
20 public static void main(String[] args) {
21 junit.textui.TestRunner.run(suite());
22 }
23
24 public static Test suite() {
25 return new TestSuite(PhaserTest.class);
26 }
27
28 /** Checks state of phaser. */
29 protected void assertState(Phaser phaser,
30 int phase, int parties, int unarrived) {
31 assertEquals(phase, phaser.getPhase());
32 assertEquals(parties, phaser.getRegisteredParties());
33 assertEquals(unarrived, phaser.getUnarrivedParties());
34 assertEquals(parties - unarrived, phaser.getArrivedParties());
35 assertTrue((phaser.getPhase() >= 0) ^ phaser.isTerminated());
36 }
37
38 /** Checks state of terminated phaser. */
39 protected void assertTerminated(Phaser phaser, int parties, int unarrived) {
40 assertTrue(phaser.isTerminated());
41 assertTrue(phaser.getPhase() < 0);
42 assertEquals(parties, phaser.getRegisteredParties());
43 assertEquals(unarrived, phaser.getUnarrivedParties());
44 assertEquals(parties - unarrived, phaser.getArrivedParties());
45 }
46
47 protected void assertTerminated(Phaser phaser) {
48 assertTerminated(phaser, 0, 0);
49 }
50
51 /**
52 * Empty constructor builds a new Phaser with no parent, no registered
53 * parties and initial phase number of 0
54 */
55 public void testConstructor1() {
56 Phaser phaser = new Phaser();
57 assertNull(phaser.getParent());
58 assertEquals(0, phaser.getArrivedParties());
59 assertEquals(0, phaser.getPhase());
60 }
61
62 /**
63 * A negative party number for the constructor throws illegal argument
64 * exception
65 */
66 public void testConstructor2() {
67 try {
68 new Phaser(-1);
69 shouldThrow();
70 } catch (IllegalArgumentException success) {}
71 }
72
73 /**
74 * The parent being input into the constructor should equal the original
75 * parent when being returned
76 */
77 public void testConstructor3() {
78 Phaser parent = new Phaser();
79 assertEquals(parent, new Phaser(parent).getParent());
80 }
81
82 /**
83 * A negative party number for the constructor throws illegal argument
84 * exception
85 */
86 public void testConstructor4() {
87 try {
88 new Phaser(new Phaser(), -1);
89 shouldThrow();
90 } catch (IllegalArgumentException success) {}
91 }
92
93 /**
94 * The parent being input into the parameter should equal the original
95 * parent when being returned
96 */
97 public void testConstructor5() {
98 Phaser parent = new Phaser();
99 assertEquals(parent, new Phaser(parent, 0).getParent());
100 }
101
102 /**
103 * register() will increment the number of unarrived parties by one and not
104 * affect its arrived parties
105 */
106 public void testRegister1() {
107 Phaser phaser = new Phaser();
108 assertState(phaser, 0, 0, 0);
109 assertEquals(0, phaser.register());
110 assertState(phaser, 0, 1, 1);
111 }
112
113 /**
114 * Registering more than 65536 parties causes IllegalStateException
115 */
116 public void testRegister2() {
117 Phaser phaser = new Phaser(0);
118 int maxParties = (1 << 16) - 1;
119 assertState(phaser, 0, 0, 0);
120 assertEquals(0, phaser.bulkRegister(maxParties - 10));
121 assertState(phaser, 0, maxParties - 10, maxParties - 10);
122 for (int i = 0; i < 10; i++) {
123 assertState(phaser, 0, maxParties - 10 + i, maxParties - 10 + i);
124 assertEquals(0, phaser.register());
125 }
126 assertState(phaser, 0, maxParties, maxParties);
127 try {
128 phaser.register();
129 shouldThrow();
130 } catch (IllegalStateException success) {}
131 }
132
133 /**
134 * register() correctly returns the current barrier phase number when
135 * invoked
136 */
137 public void testRegister3() {
138 Phaser phaser = new Phaser();
139 assertEquals(0, phaser.register());
140 assertEquals(0, phaser.arrive());
141 assertEquals(1, phaser.register());
142 assertState(phaser, 1, 2, 2);
143 }
144
145 /**
146 * register causes the next arrive to not increment the phase rather retain
147 * the phase number
148 */
149 public void testRegister4() {
150 Phaser phaser = new Phaser(1);
151 assertEquals(0, phaser.arrive());
152 assertEquals(1, phaser.register());
153 assertEquals(1, phaser.arrive());
154 assertState(phaser, 1, 2, 1);
155 }
156
157 /**
158 * Invoking bulkRegister with a negative parameter throws an
159 * IllegalArgumentException
160 */
161 public void testBulkRegister1() {
162 try {
163 new Phaser().bulkRegister(-1);
164 shouldThrow();
165 } catch (IllegalArgumentException success) {}
166 }
167
168 /**
169 * bulkRegister should correctly record the number of unarrived parties with
170 * the number of parties being registered
171 */
172 public void testBulkRegister2() {
173 Phaser phaser = new Phaser();
174 assertEquals(0, phaser.bulkRegister(20));
175 assertState(phaser, 0, 20, 20);
176 }
177
178 /**
179 * Registering with a number of parties greater than or equal to 1<<16
180 * throws IllegalStateException.
181 */
182 public void testBulkRegister3() {
183 assertEquals(0, new Phaser().bulkRegister((1 << 16) - 1));
184
185 try {
186 new Phaser().bulkRegister(1 << 16);
187 shouldThrow();
188 } catch (IllegalStateException success) {}
189
190 try {
191 new Phaser(2).bulkRegister((1 << 16) - 2);
192 shouldThrow();
193 } catch (IllegalStateException success) {}
194 }
195
196 /**
197 * the phase number increments correctly when tripping the barrier
198 */
199 public void testPhaseIncrement1() {
200 for (int size = 1; size < nine; size++) {
201 final Phaser phaser = new Phaser(size);
202 for (int index = 0; index <= (1 << size); index++) {
203 int phase = phaser.arrive();
204 assertTrue(index % size == 0 ? (index / size) == phase : index - (phase * size) > 0);
205 }
206 }
207 }
208
209 /**
210 * arrive() on a registered phaser increments phase.
211 */
212 public void testArrive1() {
213 Phaser phaser = new Phaser(1);
214 assertState(phaser, 0, 1, 1);
215 assertEquals(0, phaser.arrive());
216 assertState(phaser, 1, 1, 1);
217 }
218
219 /**
220 * arriveAndDeregister does not wait for others to arrive at barrier
221 */
222 public void testArriveAndDeregister() throws InterruptedException {
223 final Phaser phaser = new Phaser(1);
224 for (int i = 0; i < 10; i++) {
225 assertState(phaser, 0, 1, 1);
226 assertEquals(0, phaser.register());
227 assertState(phaser, 0, 2, 2);
228 assertEquals(0, phaser.arriveAndDeregister());
229 assertState(phaser, 0, 1, 1);
230 }
231 assertEquals(0, phaser.arriveAndDeregister());
232 assertTerminated(phaser);
233 }
234
235 /**
236 * arriveAndDeregister does not wait for others to arrive at barrier
237 */
238 public void testArrive2() throws InterruptedException {
239 final Phaser phaser = new Phaser();
240 assertEquals(0, phaser.register());
241 List<Thread> threads = new ArrayList<Thread>();
242 for (int i = 0; i < 10; i++) {
243 assertEquals(0, phaser.register());
244 threads.add(newStartedThread(new CheckedRunnable() {
245 public void realRun() throws InterruptedException {
246 assertEquals(0, phaser.arriveAndDeregister());
247 }}));
248 }
249
250 for (Thread thread : threads)
251 awaitTermination(thread, LONG_DELAY_MS);
252 assertState(phaser, 0, 1, 1);
253 assertEquals(0, phaser.arrive());
254 assertState(phaser, 1, 1, 1);
255 }
256
257 /**
258 * arrive() returns a negative number if the Phaser is terminated
259 */
260 public void testArrive3() {
261 Phaser phaser = new Phaser(1);
262 phaser.forceTermination();
263 assertTerminated(phaser, 1, 1);
264 assertTrue(phaser.arrive() < 0);
265 assertTrue(phaser.register() < 0);
266 assertTrue(phaser.arriveAndDeregister() < 0);
267 assertTrue(phaser.awaitAdvance(1) < 0);
268 assertTrue(phaser.getPhase() < 0);
269 }
270
271 /**
272 * arriveAndDeregister() throws IllegalStateException if number of
273 * registered or unarrived parties would become negative
274 */
275 public void testArriveAndDeregister1() {
276 try {
277 Phaser phaser = new Phaser();
278 phaser.arriveAndDeregister();
279 shouldThrow();
280 } catch (IllegalStateException success) {}
281 }
282
283 /**
284 * arriveAndDeregister reduces the number of arrived parties
285 */
286 public void testArriveAndDeregister2() {
287 final Phaser phaser = new Phaser(1);
288 assertEquals(0, phaser.register());
289 assertEquals(0, phaser.arrive());
290 assertState(phaser, 0, 2, 1);
291 assertEquals(0, phaser.arriveAndDeregister());
292 assertState(phaser, 1, 1, 1);
293 }
294
295 /**
296 * arriveAndDeregister arrives at the barrier on a phaser with a parent and
297 * when a deregistration occurs and causes the phaser to have zero parties
298 * its parent will be deregistered as well
299 */
300 public void testArriveAndDeregister3() {
301 Phaser parent = new Phaser();
302 Phaser child = new Phaser(parent);
303 assertState(child, 0, 0, 0);
304 assertState(parent, 0, 1, 1);
305 assertEquals(0, child.register());
306 assertState(child, 0, 1, 1);
307 assertState(parent, 0, 1, 1);
308 assertEquals(0, child.arriveAndDeregister());
309 assertTerminated(child);
310 assertTerminated(parent);
311 }
312
313 /**
314 * arriveAndDeregister deregisters one party from its parent when
315 * the number of parties of child is zero after deregistration
316 */
317 public void testArriveAndDeregister4() {
318 Phaser parent = new Phaser();
319 Phaser child = new Phaser(parent);
320 assertEquals(0, parent.register());
321 assertEquals(0, child.register());
322 assertState(child, 0, 1, 1);
323 assertState(parent, 0, 2, 2);
324 assertEquals(0, child.arriveAndDeregister());
325 assertState(child, 0, 0, 0);
326 assertState(parent, 0, 1, 1);
327 }
328
329 /**
330 * arriveAndDeregister deregisters one party from its parent when
331 * the number of parties of root is nonzero after deregistration.
332 */
333 public void testArriveAndDeregister5() {
334 Phaser root = new Phaser();
335 Phaser parent = new Phaser(root);
336 Phaser child = new Phaser(parent);
337 assertState(root, 0, 1, 1);
338 assertState(parent, 0, 1, 1);
339 assertState(child, 0, 0, 0);
340 assertEquals(0, child.register());
341 assertState(root, 0, 1, 1);
342 assertState(parent, 0, 1, 1);
343 assertState(child, 0, 1, 1);
344 assertEquals(0, child.arriveAndDeregister());
345 assertTerminated(child);
346 assertTerminated(parent);
347 assertTerminated(root);
348 }
349
350 /**
351 * arriveAndDeregister returns the phase in which it leaves the
352 * phaser in after deregistration
353 */
354 public void testArriveAndDeregister6() throws InterruptedException {
355 final Phaser phaser = new Phaser(2);
356 Thread t = newStartedThread(new CheckedRunnable() {
357 public void realRun() {
358 assertEquals(0, phaser.arrive());
359 }});
360 assertEquals(1, phaser.arriveAndAwaitAdvance());
361 assertState(phaser, 1, 2, 2);
362 assertEquals(1, phaser.arriveAndDeregister());
363 assertState(phaser, 1, 1, 1);
364 assertEquals(1, phaser.arriveAndDeregister());
365 assertTerminated(phaser);
366 awaitTermination(t, SHORT_DELAY_MS);
367 }
368
369 /**
370 * awaitAdvance succeeds upon advance
371 */
372 public void testAwaitAdvance1() {
373 final Phaser phaser = new Phaser(1);
374 assertEquals(0, phaser.arrive());
375 assertEquals(1, phaser.awaitAdvance(0));
376 }
377
378 /**
379 * awaitAdvance with a negative parameter will return without affecting the
380 * phaser
381 */
382 public void testAwaitAdvance2() {
383 Phaser phaser = new Phaser();
384 assertTrue(phaser.awaitAdvance(-1) < 0);
385 assertState(phaser, 0, 0, 0);
386 }
387
388 /**
389 * awaitAdvance continues waiting if interrupted before waiting
390 */
391 public void testAwaitAdvanceAfterInterrupt() throws InterruptedException {
392 final Phaser phaser = new Phaser();
393 assertEquals(0, phaser.register());
394 final CountDownLatch threadStarted = new CountDownLatch(1);
395
396 Thread t = newStartedThread(new CheckedRunnable() {
397 public void realRun() throws InterruptedException {
398 Thread.currentThread().interrupt();
399 assertEquals(0, phaser.register());
400 assertEquals(0, phaser.arrive());
401 threadStarted.countDown();
402 assertTrue(Thread.currentThread().isInterrupted());
403 assertEquals(1, phaser.awaitAdvance(0));
404 assertTrue(Thread.currentThread().isInterrupted());
405 }});
406
407 assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
408 waitForThreadToEnterWaitState(t, SMALL_DELAY_MS);
409 assertEquals(0, phaser.arrive());
410 awaitTermination(t, SMALL_DELAY_MS);
411
412 Thread.currentThread().interrupt();
413 assertEquals(1, phaser.awaitAdvance(0));
414 assertTrue(Thread.interrupted());
415 }
416
417 /**
418 * awaitAdvance continues waiting if interrupted while waiting
419 */
420 public void testAwaitAdvanceBeforeInterrupt() throws InterruptedException {
421 final Phaser phaser = new Phaser();
422 assertEquals(0, phaser.register());
423 final CountDownLatch threadStarted = new CountDownLatch(1);
424
425 Thread t = newStartedThread(new CheckedRunnable() {
426 public void realRun() throws InterruptedException {
427 assertEquals(0, phaser.register());
428 assertEquals(0, phaser.arrive());
429 threadStarted.countDown();
430 assertFalse(Thread.currentThread().isInterrupted());
431 assertEquals(1, phaser.awaitAdvance(0));
432 assertTrue(Thread.currentThread().isInterrupted());
433 }});
434
435 assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
436 waitForThreadToEnterWaitState(t, SMALL_DELAY_MS);
437 t.interrupt();
438 assertEquals(0, phaser.arrive());
439 awaitTermination(t, SMALL_DELAY_MS);
440
441 Thread.currentThread().interrupt();
442 assertEquals(1, phaser.awaitAdvance(0));
443 assertTrue(Thread.interrupted());
444 }
445
446 /**
447 * arriveAndAwaitAdvance continues waiting if interrupted before waiting
448 */
449 public void testArriveAndAwaitAdvanceAfterInterrupt()
450 throws InterruptedException {
451 final Phaser phaser = new Phaser();
452 assertEquals(0, phaser.register());
453 final CountDownLatch threadStarted = new CountDownLatch(1);
454
455 Thread t = newStartedThread(new CheckedRunnable() {
456 public void realRun() throws InterruptedException {
457 Thread.currentThread().interrupt();
458 assertEquals(0, phaser.register());
459 threadStarted.countDown();
460 assertTrue(Thread.currentThread().isInterrupted());
461 assertEquals(1, phaser.arriveAndAwaitAdvance());
462 assertTrue(Thread.currentThread().isInterrupted());
463 }});
464
465 assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
466 waitForThreadToEnterWaitState(t, SMALL_DELAY_MS);
467 Thread.currentThread().interrupt();
468 assertEquals(1, phaser.arriveAndAwaitAdvance());
469 assertTrue(Thread.interrupted());
470 awaitTermination(t, SMALL_DELAY_MS);
471 }
472
473 /**
474 * arriveAndAwaitAdvance continues waiting if interrupted while waiting
475 */
476 public void testArriveAndAwaitAdvanceBeforeInterrupt()
477 throws InterruptedException {
478 final Phaser phaser = new Phaser();
479 assertEquals(0, phaser.register());
480 final CountDownLatch threadStarted = new CountDownLatch(1);
481
482 Thread t = newStartedThread(new CheckedRunnable() {
483 public void realRun() throws InterruptedException {
484 assertEquals(0, phaser.register());
485 threadStarted.countDown();
486 assertFalse(Thread.currentThread().isInterrupted());
487 assertEquals(1, phaser.arriveAndAwaitAdvance());
488 assertTrue(Thread.currentThread().isInterrupted());
489 }});
490
491 assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
492 waitForThreadToEnterWaitState(t, SMALL_DELAY_MS);
493 t.interrupt();
494 Thread.currentThread().interrupt();
495 assertEquals(1, phaser.arriveAndAwaitAdvance());
496 assertTrue(Thread.interrupted());
497 awaitTermination(t, SMALL_DELAY_MS);
498 }
499
500 /**
501 * awaitAdvance atomically waits for all parties within the same phase to
502 * complete before continuing
503 */
504 public void testAwaitAdvance4() throws InterruptedException {
505 final Phaser phaser = new Phaser(4);
506 final AtomicInteger count = new AtomicInteger(0);
507 List<Thread> threads = new ArrayList<Thread>();
508 for (int i = 0; i < 4; i++)
509 threads.add(newStartedThread(new CheckedRunnable() {
510 public void realRun() {
511 for (int k = 0; k < 3; k++) {
512 assertEquals(2*k+1, phaser.arriveAndAwaitAdvance());
513 count.incrementAndGet();
514 assertEquals(2*k+1, phaser.arrive());
515 assertEquals(2*k+2, phaser.awaitAdvance(2*k+1));
516 assertEquals(count.get(), 4*(k+1));
517 }}}));
518
519 for (Thread thread : threads)
520 awaitTermination(thread, MEDIUM_DELAY_MS);
521 }
522
523 /**
524 * awaitAdvance returns the current phase
525 */
526 public void testAwaitAdvance5() throws InterruptedException {
527 final Phaser phaser = new Phaser(1);
528 assertEquals(1, phaser.awaitAdvance(phaser.arrive()));
529 assertEquals(1, phaser.getPhase());
530 assertEquals(1, phaser.register());
531 List<Thread> threads = new ArrayList<Thread>();
532 for (int i = 0; i < 8; i++) {
533 final CountDownLatch latch = new CountDownLatch(1);
534 final boolean goesFirst = ((i & 1) == 0);
535 threads.add(newStartedThread(new CheckedRunnable() {
536 public void realRun() throws InterruptedException {
537 if (goesFirst)
538 latch.countDown();
539 else
540 assertTrue(latch.await(SMALL_DELAY_MS, MILLISECONDS));
541 phaser.arrive();
542 }}));
543 if (goesFirst)
544 assertTrue(latch.await(SMALL_DELAY_MS, MILLISECONDS));
545 else
546 latch.countDown();
547 assertEquals(i + 2, phaser.awaitAdvance(phaser.arrive()));
548 assertEquals(i + 2, phaser.getPhase());
549 }
550 for (Thread thread : threads)
551 awaitTermination(thread, SMALL_DELAY_MS);
552 }
553
554 /**
555 * awaitAdvance returns when the phaser is externally terminated
556 */
557 public void testAwaitAdvance6() throws InterruptedException {
558 final Phaser phaser = new Phaser(3);
559 final CountDownLatch threadsStarted = new CountDownLatch(2);
560 final List<Thread> threads = new ArrayList<Thread>();
561 for (int i = 0; i < 2; i++) {
562 Runnable r = new CheckedRunnable() {
563 public void realRun() {
564 assertEquals(0, phaser.arrive());
565 threadsStarted.countDown();
566 assertTrue(phaser.awaitAdvance(0) < 0);
567 assertTrue(phaser.isTerminated());
568 assertTrue(phaser.getPhase() < 0);
569 assertEquals(3, phaser.getRegisteredParties());
570 }};
571 threads.add(newStartedThread(r));
572 }
573 threadsStarted.await();
574 phaser.forceTermination();
575 for (Thread thread : threads)
576 awaitTermination(thread, SMALL_DELAY_MS);
577 assertTrue(phaser.isTerminated());
578 assertTrue(phaser.getPhase() < 0);
579 assertEquals(3, phaser.getRegisteredParties());
580 }
581
582 /**
583 * arriveAndAwaitAdvance throws IllegalStateException with no
584 * unarrived parties
585 */
586 public void testArriveAndAwaitAdvance1() {
587 try {
588 Phaser phaser = new Phaser();
589 phaser.arriveAndAwaitAdvance();
590 shouldThrow();
591 } catch (IllegalStateException success) {}
592 }
593
594 /**
595 * arriveAndAwaitAdvance waits for all threads to arrive, the
596 * number of arrived parties is the same number that is accounted
597 * for when the main thread awaitsAdvance
598 */
599 public void testArriveAndAwaitAdvance3() throws InterruptedException {
600 final Phaser phaser = new Phaser(1);
601 final int THREADS = 3;
602 final CountDownLatch threadsStarted = new CountDownLatch(THREADS);
603 final List<Thread> threads = new ArrayList<Thread>();
604 for (int i = 0; i < THREADS; i++)
605 threads.add(newStartedThread(new CheckedRunnable() {
606 public void realRun() throws InterruptedException {
607 assertEquals(0, phaser.register());
608 threadsStarted.countDown();
609 assertEquals(1, phaser.arriveAndAwaitAdvance());
610 }}));
611
612 assertTrue(threadsStarted.await(MEDIUM_DELAY_MS, MILLISECONDS));
613 long t0 = System.nanoTime();
614 while (phaser.getArrivedParties() < THREADS)
615 Thread.yield();
616 assertEquals(THREADS, phaser.getArrivedParties());
617 assertTrue(NANOSECONDS.toMillis(System.nanoTime() - t0) < SMALL_DELAY_MS);
618 for (Thread thread : threads)
619 assertTrue(thread.isAlive());
620 assertState(phaser, 0, THREADS + 1, 1);
621 phaser.arriveAndAwaitAdvance();
622 for (Thread thread : threads)
623 awaitTermination(thread, SMALL_DELAY_MS);
624 assertState(phaser, 1, THREADS + 1, THREADS + 1);
625 }
626
627 }