ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/PhaserTest.java
Revision: 1.19
Committed: Fri Oct 15 22:43:02 2010 UTC (13 years, 6 months ago) by jsr166
Branch: MAIN
Changes since 1.18: +189 -112 lines
Log Message:
add assertions; improve reliabililty and performance

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
390 */
391 public void testAwaitAdvance3() 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 assertEquals(0, phaser.register());
399 threadStarted.countDown();
400 assertEquals(1, phaser.awaitAdvance(phaser.arrive()));
401 assertTrue(Thread.currentThread().isInterrupted());
402 }});
403 assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
404 t.interrupt();
405 assertEquals(0, phaser.arrive());
406 awaitTermination(t, SMALL_DELAY_MS);
407 }
408
409 /**
410 * awaitAdvance atomically waits for all parties within the same phase to
411 * complete before continuing
412 */
413 public void testAwaitAdvance4() throws InterruptedException {
414 final Phaser phaser = new Phaser(4);
415 final AtomicInteger count = new AtomicInteger(0);
416 List<Thread> threads = new ArrayList<Thread>();
417 for (int i = 0; i < 4; i++)
418 threads.add(newStartedThread(new CheckedRunnable() {
419 public void realRun() {
420 for (int k = 0; k < 3; k++) {
421 assertEquals(2*k+1, phaser.arriveAndAwaitAdvance());
422 count.incrementAndGet();
423 assertEquals(2*k+1, phaser.arrive());
424 assertEquals(2*k+2, phaser.awaitAdvance(2*k+1));
425 assertEquals(count.get(), 4*(k+1));
426 }}}));
427
428 for (Thread thread : threads)
429 awaitTermination(thread, MEDIUM_DELAY_MS);
430 }
431
432 /**
433 * awaitAdvance returns the current phase
434 */
435 public void testAwaitAdvance5() throws InterruptedException {
436 final Phaser phaser = new Phaser(1);
437 assertEquals(1, phaser.awaitAdvance(phaser.arrive()));
438 assertEquals(1, phaser.getPhase());
439 assertEquals(1, phaser.register());
440 List<Thread> threads = new ArrayList<Thread>();
441 for (int i = 0; i < 8; i++) {
442 final CountDownLatch latch = new CountDownLatch(1);
443 final boolean goesFirst = ((i & 1) == 0);
444 threads.add(newStartedThread(new CheckedRunnable() {
445 public void realRun() throws InterruptedException {
446 if (goesFirst)
447 latch.countDown();
448 else
449 assertTrue(latch.await(SMALL_DELAY_MS, MILLISECONDS));
450 phaser.arrive();
451 }}));
452 if (goesFirst)
453 assertTrue(latch.await(SMALL_DELAY_MS, MILLISECONDS));
454 else
455 latch.countDown();
456 assertEquals(i + 2, phaser.awaitAdvance(phaser.arrive()));
457 assertEquals(i + 2, phaser.getPhase());
458 }
459 for (Thread thread : threads)
460 awaitTermination(thread, SMALL_DELAY_MS);
461 }
462
463 /**
464 * awaitAdvance returns when the phaser is externally terminated
465 */
466 public void testAwaitAdvance6() throws InterruptedException {
467 final Phaser phaser = new Phaser(3);
468 final CountDownLatch threadsStarted = new CountDownLatch(2);
469 final List<Thread> threads = new ArrayList<Thread>();
470 for (int i = 0; i < 2; i++) {
471 Runnable r = new CheckedRunnable() {
472 public void realRun() {
473 assertEquals(0, phaser.arrive());
474 threadsStarted.countDown();
475 assertTrue(phaser.awaitAdvance(0) < 0);
476 assertTrue(phaser.isTerminated());
477 assertTrue(phaser.getPhase() < 0);
478 assertEquals(3, phaser.getRegisteredParties());
479 }};
480 threads.add(newStartedThread(r));
481 }
482 threadsStarted.await();
483 phaser.forceTermination();
484 for (Thread thread : threads)
485 awaitTermination(thread, SMALL_DELAY_MS);
486 assertTrue(phaser.isTerminated());
487 assertTrue(phaser.getPhase() < 0);
488 assertEquals(3, phaser.getRegisteredParties());
489 }
490
491 /**
492 * arriveAndAwaitAdvance throws IllegalStateException with no
493 * unarrived parties
494 */
495 public void testArriveAndAwaitAdvance1() {
496 try {
497 Phaser phaser = new Phaser();
498 phaser.arriveAndAwaitAdvance();
499 shouldThrow();
500 } catch (IllegalStateException success) {}
501 }
502
503 /**
504 * Interrupted arriveAndAwaitAdvance does not throw InterruptedException
505 */
506 public void testArriveAndAwaitAdvance2() throws InterruptedException {
507 final Phaser phaser = new Phaser(2);
508 final CountDownLatch threadStarted = new CountDownLatch(1);
509 final AtomicBoolean advanced = new AtomicBoolean(false);
510 final AtomicBoolean checkedInterruptStatus = new AtomicBoolean(false);
511 Thread t = newStartedThread(new CheckedRunnable() {
512 public void realRun() throws InterruptedException {
513 threadStarted.countDown();
514 assertEquals(1, phaser.arriveAndAwaitAdvance());
515 assertState(phaser, 1, 2, 2);
516 advanced.set(true);
517 assertTrue(Thread.currentThread().isInterrupted());
518 while (!checkedInterruptStatus.get())
519 Thread.yield();
520 }});
521
522 assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
523 t.interrupt();
524 assertEquals(0, phaser.arrive());
525 while (!advanced.get())
526 Thread.yield();
527 assertTrue(t.isInterrupted());
528 checkedInterruptStatus.set(true);
529 awaitTermination(t, SMALL_DELAY_MS);
530 }
531
532 /**
533 * arriveAndAwaitAdvance waits for all threads to arrive, the
534 * number of arrived parties is the same number that is accounted
535 * for when the main thread awaitsAdvance
536 */
537 public void testArriveAndAwaitAdvance3() throws InterruptedException {
538 final Phaser phaser = new Phaser(1);
539 final int THREADS = 3;
540 final CountDownLatch threadsStarted = new CountDownLatch(THREADS);
541 final List<Thread> threads = new ArrayList<Thread>();
542 for (int i = 0; i < THREADS; i++)
543 threads.add(newStartedThread(new CheckedRunnable() {
544 public void realRun() throws InterruptedException {
545 assertEquals(0, phaser.register());
546 threadsStarted.countDown();
547 assertEquals(1, phaser.arriveAndAwaitAdvance());
548 }}));
549
550 assertTrue(threadsStarted.await(MEDIUM_DELAY_MS, MILLISECONDS));
551 long t0 = System.nanoTime();
552 while (phaser.getArrivedParties() < THREADS)
553 Thread.yield();
554 assertEquals(THREADS, phaser.getArrivedParties());
555 assertTrue(NANOSECONDS.toMillis(System.nanoTime() - t0) < SMALL_DELAY_MS);
556 for (Thread thread : threads)
557 assertTrue(thread.isAlive());
558 assertState(phaser, 0, THREADS + 1, 1);
559 phaser.arriveAndAwaitAdvance();
560 for (Thread thread : threads)
561 awaitTermination(thread, SMALL_DELAY_MS);
562 assertState(phaser, 1, THREADS + 1, THREADS + 1);
563 }
564
565 }