ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/PhaserTest.java
Revision: 1.3
Committed: Sat Aug 1 21:56:02 2009 UTC (14 years, 9 months ago) by jsr166
Branch: MAIN
Changes since 1.2: +3 -3 lines
Log Message:
javadoc cleanup

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.*;
12 import junit.framework.Test;
13 import junit.framework.TestSuite;
14
15 public class PhaserTest extends JSR166TestCase {
16
17 public static void main(String[] args) {
18 junit.textui.TestRunner.run(suite());
19 }
20
21 public static Test suite() {
22 return new TestSuite(PhaserTest.class);
23 }
24
25 /**
26 * Empty constructor builds a new Phaser with no parent, no registered
27 * parties and initial phase number of 0
28 */
29 public void testConstructor1() {
30 Phaser phaser = new Phaser();
31 assertNull(phaser.getParent());
32 assertEquals(0, phaser.getArrivedParties());
33 assertEquals(0, phaser.getPhase());
34 }
35
36 /**
37 * A negative party number for the constructor throws illegal argument
38 * exception
39 */
40 public void testConstructor2() {
41 try {
42 new Phaser(-1);
43 this.shouldThrow();
44 } catch (IllegalArgumentException success) {
45 }
46 }
47
48 /**
49 * The parent being input into the constructor should equal the original
50 * parent when being returned
51 */
52 public void testConstructor3() {
53 Phaser parent = new Phaser();
54 assertEquals(parent, new Phaser(parent).getParent());
55 }
56
57 /**
58 * A negative party number for the constructor throws illegal argument
59 * exception
60 */
61 public void testConstructor4() {
62 try {
63 new Phaser(new Phaser(), -1);
64 shouldThrow();
65 } catch (IllegalArgumentException success) {
66 }
67 }
68
69 /**
70 * The parent being input into the parameter should equal the original
71 * parent when being returned
72 */
73 public void testConstructor5() {
74 Phaser parent = new Phaser();
75 assertEquals(parent, new Phaser(parent, 0).getParent());
76 }
77
78 /**
79 * register() will increment the number of unarrived parties by one and not
80 * affect its arrived parties
81 */
82 public void testRegister1() {
83 Phaser phaser = new Phaser();
84 assertEquals(0, phaser.getUnarrivedParties());
85 phaser.register();
86 assertEquals(1, phaser.getUnarrivedParties());
87 assertEquals(0, phaser.getArrivedParties());
88 }
89
90 /**
91 * Registering any more then 65536 parties causes IllegalStateExceptiom
92 */
93 public void testRegister2() {
94 Phaser phaser = new Phaser(0);
95 int expectedUnnarivedParties = (1 << 16) - 1;
96 for (int i = 0; i < expectedUnnarivedParties; i++) {
97 phaser.register();
98 assertEquals(i + 1, phaser.getUnarrivedParties());
99 }
100 try {
101 phaser.register();
102 shouldThrow();
103 } catch (IllegalStateException success) {
104 } catch (Exception ex) {
105 threadUnexpectedException(ex);
106 }
107 }
108
109 /**
110 * register() correctly returns the current barrier phase number when
111 * invoked
112 */
113 public void testRegister3() {
114 Phaser phaser = new Phaser();
115 assertEquals(0, phaser.register());
116 phaser.arrive();
117 assertEquals(1, phaser.register());
118 }
119
120 /**
121 * register causes the next arrive to not increment the phase rather retain
122 * the phase number
123 */
124 public void testRegister4() {
125 Phaser phaser = new Phaser(1);
126 phaser.arrive();
127 int expectedPhase = phaser.register();
128 phaser.arrive();
129 assertEquals(expectedPhase, phaser.getPhase());
130 }
131
132 public void testRegister5() {
133 Phaser phaser = new Phaser();
134 phaser.register();
135 assertEquals(1, phaser.getUnarrivedParties());
136 }
137
138 /**
139 * Invoking bulkRegister with a negative parameter throws an
140 * IllegalArgumentExceptiom
141 */
142 public void testBulkRegister1() {
143 try {
144 new Phaser().bulkRegister(-1);
145 shouldThrow();
146 } catch (IllegalArgumentException success) {
147 }
148 }
149
150 /**
151 * bulkRegister should correctly record the number of unarrived parties with
152 * the number of parties being registered
153 */
154 public void testBulkRegister2() {
155 Phaser phaser = new Phaser();
156 phaser.bulkRegister(20);
157 assertEquals(20, phaser.getUnarrivedParties());
158 }
159
160 /**
161 * Registering with a number of parties greater then or equal to 1<<16
162 * throws IllegalStateExceptiom.
163 */
164 public void testBulkRegister3() {
165 try {
166 new Phaser().bulkRegister(1 << 16);
167 shouldThrow();
168 } catch (IllegalStateException success) {
169 }
170 }
171
172 /**
173 * the phase number increments correctly when tripping the barrier
174 */
175 public void testPhaseIncrement1() {
176 for (int size = 1; size < nine; size++) {
177 final Phaser phaser = new Phaser(size);
178 for (int index = 0; index <= (1 << size); index++) {
179 int phase = phaser.arrive();
180 assertTrue(index % size == 0 ? (index / size) == phase : index - (phase * size) > 0);
181 }
182 }
183 }
184
185 /**
186 * Arrive() on a registered phaser increments phase.
187 */
188 public void testArrive1() {
189 Phaser phaser = new Phaser(1);
190 phaser.arrive();
191 assertEquals(1, phaser.getPhase());
192 }
193
194 /**
195 * arrive does not wait for others to arrive at barrier
196 */
197 public void testArrive2() {
198 final Phaser phaser = new Phaser(1);
199 phaser.register();
200 Thread thread = null;
201 for (final Runnable r : getRunnables(10, SHORT_DELAY_MS)) {
202 phaser.register();
203 thread = new Thread() {
204
205 public void run() {
206 r.run();
207 phaser.arriveAndDeregister();
208 }
209 };
210 thread.start();
211 }
212
213 phaser.arrive();
214 assertTrue(thread.isAlive());
215 assertFalse(phaser.isTerminated());
216 }
217
218 /**
219 * arrive() returns a negative number if the Phaser is terminated
220 */
221 public void testArrive3() {
222 Phaser phaser = new Phaser(1);
223 phaser.forceTermination();
224 assertTrue(phaser.arrive() < 0);
225
226 }
227
228 /**
229 * arriveAndDeregister() throws IllegalStateException if number of
230 * registered or unarrived parties would become negative
231 */
232 public void testArriveAndDeregister1() {
233 try {
234 Phaser phaser = new Phaser();
235 phaser.arriveAndDeregister();
236 shouldThrow();
237
238 } catch (IllegalStateException success) {
239 }
240 }
241
242 /**
243 * arriveAndDeregister deregisters reduces the number of arrived parties
244 */
245 public void testArriveAndDergeister2() {
246 final Phaser phaser = new Phaser(1);
247 phaser.register();
248 phaser.arrive();
249 int p = phaser.getArrivedParties();
250 assertTrue(p == 1);
251 phaser.arriveAndDeregister();
252 assertTrue(phaser.getArrivedParties() < p);
253 }
254
255 /**
256 * arriveAndDeregister arrives to the barrier on a phaser with a parent and
257 * when a deregistration occurs and causes the phaser to have zero parties
258 * its parent will be deregistered as well
259 */
260 public void testArriveAndDeregsiter3() {
261 Phaser parent = new Phaser();
262 Phaser root = new Phaser(parent);
263 root.register();
264 assertTrue(parent.getUnarrivedParties() > 0);
265 assertTrue(root.getUnarrivedParties() > 0);
266 root.arriveAndDeregister();
267 assertTrue(parent.getUnarrivedParties() == 0);
268 assertTrue(root.getUnarrivedParties() == 0);
269 assertTrue(root.isTerminated() && parent.isTerminated());
270 }
271
272 /**
273 * arriveAndDeregister deregisters one party from its parent when
274 * the number of parties of root is zero after deregistration
275 */
276 public void testArriveAndDeregsiter4() {
277 Phaser parent = new Phaser();
278 Phaser root = new Phaser(parent);
279 parent.register();
280 root.register();
281 int parentParties = parent.getUnarrivedParties();
282 root.arriveAndDeregister();
283 assertEquals(parentParties - 1, parent.getUnarrivedParties());
284 }
285
286 /**
287 * arriveAndDeregister deregisters one party from its parent when
288 * the number of parties of root is nonzero after deregistration.
289 */
290 public void testArriveAndDeregister5() {
291 Phaser parent = new Phaser();
292 Phaser child = new Phaser(parent);
293 Phaser root = new Phaser(child);
294 assertTrue(parent.getUnarrivedParties() > 0);
295 assertTrue(child.getUnarrivedParties() > 0);
296 root.register();
297 root.arriveAndDeregister();
298 assertTrue(parent.getUnarrivedParties() == 0);
299 assertTrue(child.getUnarrivedParties() == 0);
300 assertTrue(root.isTerminated());
301 }
302
303 /**
304 * arriveAndDeregister returns the phase in which it leaves the
305 * phaser in after deregistration
306 */
307 public void testArriveAndDeregister6() {
308 final Phaser phaser = new Phaser(2);
309 new Thread() {
310
311 public void run() {
312 getRunnable(SHORT_DELAY_MS).run();
313 phaser.arrive();
314 }
315 }.start();
316 phaser.arriveAndAwaitAdvance();
317 int phase = phaser.arriveAndDeregister();
318 assertEquals(phase, phaser.getPhase());
319 }
320
321 /**
322 * awaitAdvance succeeds upon advance
323 */
324 public void testAwaitAdvance1() {
325 final Phaser phaser = new Phaser(1);
326 phaser.awaitAdvance(phaser.arrive());
327 }
328
329 /**
330 * awaitAdvance with a negative parameter will return without affecting the
331 * phaser
332 */
333 public void testAwaitAdvance2() {
334 try {
335 Phaser phaser = new Phaser();
336 phaser.awaitAdvance(-1);
337 } catch (Exception failure) {
338 this.unexpectedException();
339 }
340 }
341
342 /**
343 * awaitAdvance while waiting does not abort on interrupt.
344 */
345 public void testAwaitAdvance3() {
346 final Phaser phaser = new Phaser();
347 Thread th1 = new Thread() {
348
349 public void run() {
350 try {
351 phaser.register();
352 getRunnable(LONG_DELAY_MS).run();
353 phaser.awaitAdvance(phaser.arrive());
354 } catch (Exception failure) {
355 threadUnexpectedException(failure);
356 }
357
358 }
359 };
360 phaser.register();
361 th1.start();
362 try {
363 Thread.sleep(SHORT_DELAY_MS);
364 th1.interrupt();
365 Thread.sleep(LONG_DELAY_MS);
366 phaser.arrive();
367 } catch (Exception failure) {
368 unexpectedException();
369 }
370 assertFalse(th1.isInterrupted());
371 }
372
373 /**
374 * awaitAdvance atomically waits for all parties within the same phase to
375 * complete before continuing
376 */
377 public void testAwaitAdvance4() {
378 final Phaser phaser = new Phaser(four);
379 final AtomicInteger phaseCount = new AtomicInteger(0);
380 for (int i = 0; i < four; i++) {
381 new Thread() {
382
383 public void run() {
384 int phase = phaser.arrive();
385 phaseCount.incrementAndGet();
386 getRunnable(LONG_DELAY_MS).run();
387 phaser.awaitAdvance(phase);
388 assertTrue(phaseCount.get() == four);
389 }
390 }.start();
391 }
392 }
393
394 /**
395 * awaitAdvance returns the current phase
396 */
397 public void testAwaitAdvance5() {
398 final Phaser phaser = new Phaser(1);
399 int phase = phaser.awaitAdvance(phaser.arrive());
400 assertEquals(phase, phaser.getPhase());
401 phaser.register();
402 for (int i = 0; i < eight; i++) {
403 new Thread() {
404
405 public void run() {
406 getRunnable(SHORT_DELAY_MS).run();
407 phaser.arrive();
408 }
409 }.start();
410 phase = phaser.awaitAdvance(phaser.arrive());
411 assertEquals(phase, phaser.getPhase());
412 }
413 }
414
415 /**
416 * awaitAdvance returns when the phaser is externally terminated
417 */
418 public void testAwaitAdvance6() {
419 final Phaser phaser = new Phaser(3);
420 /*
421 * Start new thread. This thread waits a small amount of time
422 * and waits for the other two parties to arrive. The party
423 * in the main thread arrives quickly so at best this thread
424 * waits for the second thread's party to arrive
425 */
426 new Thread() {
427
428 public void run() {
429 getRunnable(SMALL_DELAY_MS).run();
430 int phase = phaser.awaitAdvance(phaser.arrive());
431 /*
432 * This point is reached when force termination is called in which phase = -1
433 */
434 threadAssertTrue(phase < 0);
435 threadAssertTrue(phaser.isTerminated());
436 }
437 }.start();
438 /*
439 * This thread will cause the first thread run to wait, in doing so
440 * the main thread will force termination in which the first thread
441 * should exit peacefully as this one
442 */
443 new Thread() {
444
445 public void run() {
446 getRunnable(LONG_DELAY_MS).run();
447 int p1 = phaser.arrive();
448 int phase = phaser.awaitAdvance(p1);
449 threadAssertTrue(phase < 0);
450 threadAssertTrue(phaser.isTerminated());
451 }
452 }.start();
453
454 phaser.arrive();
455 phaser.forceTermination();
456 }
457
458 /**
459 * arriveAndAwaitAdvance throws IllegalStateException with no
460 * unarrived parties
461 */
462 public void testArriveAndAwaitAdvance1() {
463 try {
464 Phaser phaser = new Phaser();
465 phaser.arriveAndAwaitAdvance();
466 shouldThrow();
467 } catch (IllegalStateException success) {
468 }
469 }
470
471 /**
472 * Interrupted arriveAndAwaitAdvance does not throw InterruptedException
473 */
474 public void testArriveAndAwaitAdvance2() {
475 final Phaser phaser = new Phaser(2);
476 Thread th = new Thread() {
477 public void run() {
478 try {
479 phaser.arriveAndAwaitAdvance();
480 } catch (Exception failure) {
481 threadUnexpectedException(failure);
482 }
483 }
484 };
485
486 try {
487 th.start();
488 Thread.sleep(LONG_DELAY_MS);
489 th.interrupt();
490 Thread.sleep(LONG_DELAY_MS);
491 phaser.arrive();
492 } catch (InterruptedException failure) {
493 this.unexpectedException();
494 }
495 assertFalse(th.isInterrupted());
496 }
497
498 /**
499 * arriveAndAwaitAdvance waits for all threads to arrive, the
500 * number of arrived parties is the same number that is accounted
501 * for when the main thread awaitsAdvance
502 */
503 public void testArriveAndAwaitAdvance3() {
504 final Phaser phaser = new Phaser(1);
505 final AtomicInteger arrivingCount = new AtomicInteger(0);
506 for (final Runnable run : getRunnables(six, SHORT_DELAY_MS)) {
507 new Thread() {
508
509 public void run() {
510 phaser.register();
511 run.run();
512 arrivingCount.getAndIncrement();
513 phaser.arrive();
514 }
515 }.start();
516 }
517 int phaseNumber = phaser.arriveAndAwaitAdvance();
518 arrivingCount.incrementAndGet();
519 //the + 1 adds to expectedArrive to account for the main threads arrival
520 int expectedArrived = phaseNumber > 0 ? phaseNumber * six + 1 : phaser.getArrivedParties() + 1;
521 threadAssertEquals(expectedArrived, arrivingCount.get());
522 }
523 // .. initially called, for n tasks via
524 private List<Runnable> getRunnables(int size, long wait) {
525 List<Runnable> list = new ArrayList<Runnable>();
526 for (int i = 0; i < size; i++) {
527 list.add(getRunnable(wait));
528 }
529 return list;
530 }
531
532 private Runnable getRunnable(final long wait) {
533 return new Runnable() {
534
535 public void run() {
536 try {
537 Thread.sleep(wait);
538 } catch (InterruptedException noop) {
539 // sleep interruption isn't a problem case for these example
540 } catch (Exception ex) {
541 threadUnexpectedException(ex);
542 }
543
544 }
545 };
546 }
547
548 }