ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/PhaserTest.java
Revision: 1.5
Committed: Mon Aug 3 20:33:57 2009 UTC (14 years, 9 months ago) by jsr166
Branch: MAIN
Changes since 1.4: +45 -70 lines
Log Message:
use checked runnables

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