ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/PhaserTest.java
Revision: 1.7
Committed: Wed Aug 5 00:48:28 2009 UTC (14 years, 9 months ago) by jsr166
Branch: MAIN
Changes since 1.6: +56 -70 lines
Log Message:
Ensure threads started by tests are join()ed; perf improvements

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 jsr166 1.6 shouldThrow();
44 dl 1.1 } 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 jsr166 1.7 * arriveAndDeregister does not wait for others to arrive at barrier
194 dl 1.1 */
195 jsr166 1.7 public void testArrive2() throws InterruptedException {
196 dl 1.1 final Phaser phaser = new Phaser(1);
197     phaser.register();
198 jsr166 1.7 List<Thread> threads = new ArrayList<Thread>();
199     for (int i = 0; i < 10; i++)
200 dl 1.1 phaser.register();
201 jsr166 1.7 threads.add(newStartedThread(new CheckedRunnable() {
202     void realRun() throws InterruptedException {
203     Thread.sleep(SMALL_DELAY_MS);
204 dl 1.1 phaser.arriveAndDeregister();
205 jsr166 1.7 }}));
206 dl 1.1
207     phaser.arrive();
208 jsr166 1.7 assertTrue(threads.get(0).isAlive());
209 dl 1.1 assertFalse(phaser.isTerminated());
210 jsr166 1.7 for (Thread thread : threads)
211     thread.join();
212 dl 1.1 }
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     * arriveAndDeregister() throws IllegalStateException if number of
225 jsr166 1.3 * registered or unarrived parties would become negative
226 dl 1.1 */
227     public void testArriveAndDeregister1() {
228     try {
229     Phaser phaser = new Phaser();
230     phaser.arriveAndDeregister();
231     shouldThrow();
232     } catch (IllegalStateException success) {
233     }
234     }
235    
236     /**
237 jsr166 1.3 * arriveAndDeregister deregisters reduces the number of arrived parties
238 dl 1.1 */
239     public void testArriveAndDergeister2() {
240     final Phaser phaser = new Phaser(1);
241     phaser.register();
242     phaser.arrive();
243     int p = phaser.getArrivedParties();
244     assertTrue(p == 1);
245     phaser.arriveAndDeregister();
246     assertTrue(phaser.getArrivedParties() < p);
247     }
248    
249     /**
250     * arriveAndDeregister arrives to the barrier on a phaser with a parent and
251     * when a deregistration occurs and causes the phaser to have zero parties
252     * its parent will be deregistered as well
253     */
254     public void testArriveAndDeregsiter3() {
255     Phaser parent = new Phaser();
256     Phaser root = new Phaser(parent);
257     root.register();
258     assertTrue(parent.getUnarrivedParties() > 0);
259     assertTrue(root.getUnarrivedParties() > 0);
260     root.arriveAndDeregister();
261     assertTrue(parent.getUnarrivedParties() == 0);
262     assertTrue(root.getUnarrivedParties() == 0);
263     assertTrue(root.isTerminated() && parent.isTerminated());
264     }
265    
266     /**
267     * arriveAndDeregister deregisters one party from its parent when
268     * the number of parties of root is zero after deregistration
269     */
270     public void testArriveAndDeregsiter4() {
271     Phaser parent = new Phaser();
272     Phaser root = new Phaser(parent);
273     parent.register();
274     root.register();
275     int parentParties = parent.getUnarrivedParties();
276     root.arriveAndDeregister();
277     assertEquals(parentParties - 1, parent.getUnarrivedParties());
278     }
279    
280     /**
281     * arriveAndDeregister deregisters one party from its parent when
282     * the number of parties of root is nonzero after deregistration.
283     */
284     public void testArriveAndDeregister5() {
285     Phaser parent = new Phaser();
286     Phaser child = new Phaser(parent);
287     Phaser root = new Phaser(child);
288     assertTrue(parent.getUnarrivedParties() > 0);
289     assertTrue(child.getUnarrivedParties() > 0);
290     root.register();
291     root.arriveAndDeregister();
292     assertTrue(parent.getUnarrivedParties() == 0);
293     assertTrue(child.getUnarrivedParties() == 0);
294     assertTrue(root.isTerminated());
295     }
296    
297     /**
298     * arriveAndDeregister returns the phase in which it leaves the
299     * phaser in after deregistration
300     */
301 jsr166 1.7 public void testArriveAndDeregister6() throws InterruptedException {
302 dl 1.1 final Phaser phaser = new Phaser(2);
303 jsr166 1.7 Thread t = newStartedThread(new CheckedRunnable() {
304 jsr166 1.5 void realRun() {
305 jsr166 1.7 sleepTillInterrupted(SHORT_DELAY_MS);
306 dl 1.1 phaser.arrive();
307 jsr166 1.7 }});
308 dl 1.1 phaser.arriveAndAwaitAdvance();
309     int phase = phaser.arriveAndDeregister();
310     assertEquals(phase, phaser.getPhase());
311 jsr166 1.7 t.join();
312 dl 1.1 }
313    
314     /**
315     * awaitAdvance succeeds upon advance
316     */
317     public void testAwaitAdvance1() {
318     final Phaser phaser = new Phaser(1);
319     phaser.awaitAdvance(phaser.arrive());
320     }
321    
322     /**
323     * awaitAdvance with a negative parameter will return without affecting the
324     * phaser
325     */
326     public void testAwaitAdvance2() {
327 jsr166 1.6 Phaser phaser = new Phaser();
328     phaser.awaitAdvance(-1);
329 dl 1.1 }
330    
331     /**
332     * awaitAdvance while waiting does not abort on interrupt.
333     */
334 jsr166 1.6 public void testAwaitAdvance3() throws InterruptedException {
335 dl 1.1 final Phaser phaser = new Phaser();
336 jsr166 1.7 phaser.register();
337 dl 1.1
338 jsr166 1.7 Thread t = newStartedThread(new CheckedRunnable() {
339 jsr166 1.5 void realRun() throws InterruptedException {
340     phaser.register();
341 jsr166 1.7 sleepTillInterrupted(LONG_DELAY_MS);
342 jsr166 1.5 phaser.awaitAdvance(phaser.arrive());
343     }});
344 jsr166 1.7 Thread.sleep(SMALL_DELAY_MS);
345     t.interrupt();
346     Thread.sleep(SMALL_DELAY_MS);
347 jsr166 1.6 phaser.arrive();
348 jsr166 1.7 assertFalse(t.isInterrupted());
349     t.join();
350 dl 1.1 }
351    
352     /**
353     * awaitAdvance atomically waits for all parties within the same phase to
354     * complete before continuing
355     */
356 jsr166 1.5 public void testAwaitAdvance4() throws InterruptedException {
357     final Phaser phaser = new Phaser(4);
358 dl 1.1 final AtomicInteger phaseCount = new AtomicInteger(0);
359 jsr166 1.5 List<Thread> threads = new ArrayList<Thread>();
360     for (int i = 0; i < 4; i++) {
361 jsr166 1.7 threads.add(newStartedThread(new CheckedRunnable() {
362 jsr166 1.5 void realRun() {
363 dl 1.1 int phase = phaser.arrive();
364     phaseCount.incrementAndGet();
365 jsr166 1.7 sleepTillInterrupted(SMALL_DELAY_MS);
366 dl 1.1 phaser.awaitAdvance(phase);
367 jsr166 1.5 threadAssertTrue(phaseCount.get() == 4);
368     }}));
369 dl 1.1 }
370 jsr166 1.5 for (Thread thread : threads)
371     thread.join();
372 dl 1.1 }
373    
374     /**
375     * awaitAdvance returns the current phase
376     */
377 jsr166 1.7 public void testAwaitAdvance5() throws InterruptedException {
378 dl 1.1 final Phaser phaser = new Phaser(1);
379     int phase = phaser.awaitAdvance(phaser.arrive());
380     assertEquals(phase, phaser.getPhase());
381     phaser.register();
382 jsr166 1.7 List<Thread> threads = new ArrayList<Thread>();
383     for (int i = 0; i < 8; i++) {
384     threads.add(newStartedThread(new CheckedRunnable() {
385 jsr166 1.5 void realRun() {
386 jsr166 1.7 sleepTillInterrupted(SHORT_DELAY_MS);
387 dl 1.1 phaser.arrive();
388 jsr166 1.7 }}));
389 dl 1.1 phase = phaser.awaitAdvance(phaser.arrive());
390 jsr166 1.5 threadAssertEquals(phase, phaser.getPhase());
391 dl 1.1 }
392 jsr166 1.7 for (Thread thread : threads)
393     thread.join();
394 dl 1.1 }
395    
396     /**
397     * awaitAdvance returns when the phaser is externally terminated
398     */
399 jsr166 1.7 public void testAwaitAdvance6() throws InterruptedException {
400 dl 1.1 final Phaser phaser = new Phaser(3);
401     /*
402     * Start new thread. This thread waits a small amount of time
403     * and waits for the other two parties to arrive. The party
404     * in the main thread arrives quickly so at best this thread
405     * waits for the second thread's party to arrive
406     */
407 jsr166 1.7 Thread t1 = newStartedThread(new CheckedRunnable() {
408 jsr166 1.5 void realRun() {
409 jsr166 1.7 sleepTillInterrupted(SMALL_DELAY_MS);
410 dl 1.1 int phase = phaser.awaitAdvance(phaser.arrive());
411     /*
412     * This point is reached when force termination is called in which phase = -1
413     */
414     threadAssertTrue(phase < 0);
415     threadAssertTrue(phaser.isTerminated());
416 jsr166 1.7 }});
417 dl 1.1 /*
418     * This thread will cause the first thread run to wait, in doing so
419 jsr166 1.2 * the main thread will force termination in which the first thread
420     * should exit peacefully as this one
421 dl 1.1 */
422 jsr166 1.7 Thread t2 = newStartedThread(new CheckedRunnable() {
423 jsr166 1.5 void realRun() {
424 jsr166 1.7 sleepTillInterrupted(MEDIUM_DELAY_MS);
425 dl 1.1 int p1 = phaser.arrive();
426     int phase = phaser.awaitAdvance(p1);
427     threadAssertTrue(phase < 0);
428     threadAssertTrue(phaser.isTerminated());
429 jsr166 1.7 }});
430 dl 1.1
431     phaser.arrive();
432     phaser.forceTermination();
433 jsr166 1.7 t1.join();
434     t2.join();
435 dl 1.1 }
436    
437     /**
438     * arriveAndAwaitAdvance throws IllegalStateException with no
439     * unarrived parties
440     */
441     public void testArriveAndAwaitAdvance1() {
442     try {
443     Phaser phaser = new Phaser();
444     phaser.arriveAndAwaitAdvance();
445     shouldThrow();
446     } catch (IllegalStateException success) {
447     }
448     }
449    
450     /**
451     * Interrupted arriveAndAwaitAdvance does not throw InterruptedException
452     */
453 jsr166 1.6 public void testArriveAndAwaitAdvance2() throws InterruptedException {
454 dl 1.1 final Phaser phaser = new Phaser(2);
455 jsr166 1.7 Thread th = newStartedThread(new CheckedRunnable() {
456 jsr166 1.5 void realRun() {
457     phaser.arriveAndAwaitAdvance();
458     }});
459 dl 1.1
460 jsr166 1.7 Thread.sleep(SMALL_DELAY_MS);
461 jsr166 1.6 th.interrupt();
462 jsr166 1.7 Thread.sleep(SMALL_DELAY_MS);
463 jsr166 1.6 phaser.arrive();
464 dl 1.1 assertFalse(th.isInterrupted());
465 jsr166 1.7 th.join();
466 dl 1.1 }
467    
468     /**
469     * arriveAndAwaitAdvance waits for all threads to arrive, the
470     * number of arrived parties is the same number that is accounted
471     * for when the main thread awaitsAdvance
472     */
473 jsr166 1.7 public void testArriveAndAwaitAdvance3() throws InterruptedException {
474 dl 1.1 final Phaser phaser = new Phaser(1);
475     final AtomicInteger arrivingCount = new AtomicInteger(0);
476 jsr166 1.7 final List<Thread> threads = new ArrayList<Thread>();
477     for (int i = 0; i < 6; i++) {
478     threads.add(newStartedThread(new CheckedRunnable() {
479     void realRun() throws InterruptedException {
480 dl 1.1 phaser.register();
481 jsr166 1.7 sleepTillInterrupted(SHORT_DELAY_MS);
482 dl 1.1 arrivingCount.getAndIncrement();
483     phaser.arrive();
484 jsr166 1.7 }}));
485 dl 1.1 }
486     int phaseNumber = phaser.arriveAndAwaitAdvance();
487     arrivingCount.incrementAndGet();
488     //the + 1 adds to expectedArrive to account for the main threads arrival
489     int expectedArrived = phaseNumber > 0 ? phaseNumber * six + 1 : phaser.getArrivedParties() + 1;
490     threadAssertEquals(expectedArrived, arrivingCount.get());
491 jsr166 1.7 for (Thread thread : threads)
492     thread.join();
493 dl 1.1 }
494    
495     }