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

# User Rev Content
1 dl 1.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 jsr166 1.4 * Registering more than 65536 parties causes IllegalStateException
92 dl 1.1 */
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 jsr166 1.4 * IllegalArgumentException
139 dl 1.1 */
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 jsr166 1.4 * Registering with a number of parties greater than or equal to 1<<16
160     * throws IllegalStateException.
161 dl 1.1 */
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 jsr166 1.5 thread = new Thread(new CheckedRunnable() {
202     void realRun() {
203 dl 1.1 r.run();
204     phaser.arriveAndDeregister();
205 jsr166 1.5 }});
206 dl 1.1 thread.start();
207     }
208    
209     phaser.arrive();
210     assertTrue(thread.isAlive());
211     assertFalse(phaser.isTerminated());
212     }
213    
214     /**
215 jsr166 1.3 * arrive() returns a negative number if the Phaser is terminated
216 dl 1.1 */
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 jsr166 1.3 * registered or unarrived parties would become negative
227 dl 1.1 */
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 jsr166 1.3 * arriveAndDeregister deregisters reduces the number of arrived parties
240 dl 1.1 */
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 jsr166 1.5 new Thread(new CheckedRunnable() {
306     void realRun() {
307 dl 1.1 getRunnable(SHORT_DELAY_MS).run();
308     phaser.arrive();
309 jsr166 1.5 }}).start();
310 dl 1.1 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 jsr166 1.5 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 dl 1.1 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 jsr166 1.5 } catch (InterruptedException failure) {
356     threadUnexpectedException(failure);
357 dl 1.1 }
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 jsr166 1.5 public void testAwaitAdvance4() throws InterruptedException {
366     final Phaser phaser = new Phaser(4);
367 dl 1.1 final AtomicInteger phaseCount = new AtomicInteger(0);
368 jsr166 1.5 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 dl 1.1 int phase = phaser.arrive();
373     phaseCount.incrementAndGet();
374     getRunnable(LONG_DELAY_MS).run();
375     phaser.awaitAdvance(phase);
376 jsr166 1.5 threadAssertTrue(phaseCount.get() == 4);
377     }}));
378 dl 1.1 }
379 jsr166 1.5 for (Thread thread : threads)
380     thread.start();
381     for (Thread thread : threads)
382     thread.join();
383 dl 1.1 }
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 jsr166 1.5 new Thread(new CheckedRunnable() {
395     void realRun() {
396 dl 1.1 getRunnable(SHORT_DELAY_MS).run();
397     phaser.arrive();
398     }
399 jsr166 1.5 }).start();
400 dl 1.1 phase = phaser.awaitAdvance(phaser.arrive());
401 jsr166 1.5 threadAssertEquals(phase, phaser.getPhase());
402 dl 1.1 }
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 jsr166 1.5 new Thread(new CheckedRunnable() {
417     void realRun() {
418 dl 1.1 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 jsr166 1.5 }}).start();
426 dl 1.1 /*
427     * This thread will cause the first thread run to wait, in doing so
428 jsr166 1.2 * the main thread will force termination in which the first thread
429     * should exit peacefully as this one
430 dl 1.1 */
431 jsr166 1.5 new Thread(new CheckedRunnable() {
432     void realRun() {
433 dl 1.1 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 jsr166 1.5 }}).start();
439 dl 1.1
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 jsr166 1.5 Thread th = new Thread(new CheckedRunnable() {
463     void realRun() {
464     phaser.arriveAndAwaitAdvance();
465     }});
466 dl 1.1
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 jsr166 1.5 new Thread(new CheckedRunnable() {
489     void realRun() {
490 dl 1.1 phaser.register();
491     run.run();
492     arrivingCount.getAndIncrement();
493     phaser.arrive();
494 jsr166 1.5 }}).start();
495 dl 1.1 }
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 jsr166 1.5 return new CheckedRunnable() {
513     void realRun() {
514 dl 1.1 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     }