ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/PhaserTest.java
Revision: 1.16
Committed: Mon Oct 11 05:35:19 2010 UTC (13 years, 6 months ago) by jsr166
Branch: MAIN
Changes since 1.15: +19 -7 lines
Log Message:
optimize and prevent rare failure in testArriveAndAwaitAdvance2

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 jsr166 1.16 import java.util.concurrent.atomic.AtomicBoolean;
12 dl 1.1 import java.util.concurrent.*;
13 jsr166 1.16 import static java.util.concurrent.TimeUnit.MILLISECONDS;
14 dl 1.1 import junit.framework.Test;
15     import junit.framework.TestSuite;
16    
17     public class PhaserTest extends JSR166TestCase {
18    
19     public static void main(String[] args) {
20     junit.textui.TestRunner.run(suite());
21     }
22    
23     public static Test suite() {
24     return new TestSuite(PhaserTest.class);
25     }
26    
27     /**
28     * Empty constructor builds a new Phaser with no parent, no registered
29     * parties and initial phase number of 0
30     */
31     public void testConstructor1() {
32     Phaser phaser = new Phaser();
33     assertNull(phaser.getParent());
34     assertEquals(0, phaser.getArrivedParties());
35     assertEquals(0, phaser.getPhase());
36     }
37    
38     /**
39     * A negative party number for the constructor throws illegal argument
40     * exception
41     */
42     public void testConstructor2() {
43     try {
44     new Phaser(-1);
45 jsr166 1.6 shouldThrow();
46 jsr166 1.8 } catch (IllegalArgumentException success) {}
47 dl 1.1 }
48    
49     /**
50     * The parent being input into the constructor should equal the original
51     * parent when being returned
52     */
53     public void testConstructor3() {
54     Phaser parent = new Phaser();
55     assertEquals(parent, new Phaser(parent).getParent());
56     }
57    
58     /**
59     * A negative party number for the constructor throws illegal argument
60     * exception
61     */
62     public void testConstructor4() {
63     try {
64     new Phaser(new Phaser(), -1);
65     shouldThrow();
66 jsr166 1.8 } catch (IllegalArgumentException success) {}
67 dl 1.1 }
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 jsr166 1.8 } catch (IllegalStateException success) {}
104 dl 1.1 }
105    
106     /**
107     * register() correctly returns the current barrier phase number when
108     * invoked
109     */
110     public void testRegister3() {
111     Phaser phaser = new Phaser();
112     assertEquals(0, phaser.register());
113     phaser.arrive();
114     assertEquals(1, phaser.register());
115     }
116    
117     /**
118     * register causes the next arrive to not increment the phase rather retain
119     * the phase number
120     */
121     public void testRegister4() {
122     Phaser phaser = new Phaser(1);
123     phaser.arrive();
124     int expectedPhase = phaser.register();
125     phaser.arrive();
126     assertEquals(expectedPhase, phaser.getPhase());
127     }
128    
129     public void testRegister5() {
130     Phaser phaser = new Phaser();
131     phaser.register();
132     assertEquals(1, phaser.getUnarrivedParties());
133     }
134    
135     /**
136     * Invoking bulkRegister with a negative parameter throws an
137 jsr166 1.4 * IllegalArgumentException
138 dl 1.1 */
139     public void testBulkRegister1() {
140     try {
141     new Phaser().bulkRegister(-1);
142     shouldThrow();
143 jsr166 1.8 } catch (IllegalArgumentException success) {}
144 dl 1.1 }
145    
146     /**
147     * bulkRegister should correctly record the number of unarrived parties with
148     * the number of parties being registered
149     */
150     public void testBulkRegister2() {
151     Phaser phaser = new Phaser();
152     phaser.bulkRegister(20);
153     assertEquals(20, phaser.getUnarrivedParties());
154     }
155    
156     /**
157 jsr166 1.4 * Registering with a number of parties greater than or equal to 1<<16
158     * throws IllegalStateException.
159 dl 1.1 */
160     public void testBulkRegister3() {
161     try {
162     new Phaser().bulkRegister(1 << 16);
163     shouldThrow();
164 jsr166 1.8 } catch (IllegalStateException success) {}
165 dl 1.1 }
166    
167     /**
168     * the phase number increments correctly when tripping the barrier
169     */
170     public void testPhaseIncrement1() {
171     for (int size = 1; size < nine; size++) {
172     final Phaser phaser = new Phaser(size);
173     for (int index = 0; index <= (1 << size); index++) {
174     int phase = phaser.arrive();
175     assertTrue(index % size == 0 ? (index / size) == phase : index - (phase * size) > 0);
176     }
177     }
178     }
179    
180     /**
181 jsr166 1.15 * Arrive() on a registered phaser increments phase.
182 dl 1.1 */
183     public void testArrive1() {
184     Phaser phaser = new Phaser(1);
185     phaser.arrive();
186     assertEquals(1, phaser.getPhase());
187     }
188    
189     /**
190 jsr166 1.7 * arriveAndDeregister does not wait for others to arrive at barrier
191 dl 1.1 */
192 jsr166 1.7 public void testArrive2() throws InterruptedException {
193 dl 1.1 final Phaser phaser = new Phaser(1);
194     phaser.register();
195 jsr166 1.7 List<Thread> threads = new ArrayList<Thread>();
196     for (int i = 0; i < 10; i++)
197 dl 1.1 phaser.register();
198 jsr166 1.7 threads.add(newStartedThread(new CheckedRunnable() {
199 jsr166 1.9 public void realRun() throws InterruptedException {
200 jsr166 1.7 Thread.sleep(SMALL_DELAY_MS);
201 dl 1.1 phaser.arriveAndDeregister();
202 jsr166 1.7 }}));
203 dl 1.1
204     phaser.arrive();
205 jsr166 1.7 assertTrue(threads.get(0).isAlive());
206 dl 1.1 assertFalse(phaser.isTerminated());
207 jsr166 1.7 for (Thread thread : threads)
208     thread.join();
209 dl 1.1 }
210    
211     /**
212 jsr166 1.3 * arrive() returns a negative number if the Phaser is terminated
213 dl 1.1 */
214     public void testArrive3() {
215     Phaser phaser = new Phaser(1);
216     phaser.forceTermination();
217     assertTrue(phaser.arrive() < 0);
218     }
219    
220     /**
221     * arriveAndDeregister() throws IllegalStateException if number of
222 jsr166 1.3 * registered or unarrived parties would become negative
223 dl 1.1 */
224     public void testArriveAndDeregister1() {
225     try {
226     Phaser phaser = new Phaser();
227     phaser.arriveAndDeregister();
228     shouldThrow();
229 jsr166 1.8 } catch (IllegalStateException success) {}
230 dl 1.1 }
231    
232     /**
233 jsr166 1.3 * arriveAndDeregister deregisters reduces the number of arrived parties
234 dl 1.1 */
235     public void testArriveAndDergeister2() {
236     final Phaser phaser = new Phaser(1);
237     phaser.register();
238     phaser.arrive();
239     int p = phaser.getArrivedParties();
240 jsr166 1.14 assertEquals(1, p);
241 dl 1.1 phaser.arriveAndDeregister();
242     assertTrue(phaser.getArrivedParties() < p);
243     }
244    
245     /**
246     * arriveAndDeregister arrives to the barrier on a phaser with a parent and
247     * when a deregistration occurs and causes the phaser to have zero parties
248     * its parent will be deregistered as well
249     */
250     public void testArriveAndDeregsiter3() {
251     Phaser parent = new Phaser();
252     Phaser root = new Phaser(parent);
253     root.register();
254     assertTrue(parent.getUnarrivedParties() > 0);
255     assertTrue(root.getUnarrivedParties() > 0);
256     root.arriveAndDeregister();
257 jsr166 1.14 assertEquals(0, parent.getUnarrivedParties());
258     assertEquals(0, root.getUnarrivedParties());
259 dl 1.1 assertTrue(root.isTerminated() && parent.isTerminated());
260     }
261    
262     /**
263     * arriveAndDeregister deregisters one party from its parent when
264     * the number of parties of root is zero after deregistration
265     */
266     public void testArriveAndDeregsiter4() {
267     Phaser parent = new Phaser();
268     Phaser root = new Phaser(parent);
269     parent.register();
270     root.register();
271     int parentParties = parent.getUnarrivedParties();
272     root.arriveAndDeregister();
273     assertEquals(parentParties - 1, parent.getUnarrivedParties());
274     }
275    
276     /**
277     * arriveAndDeregister deregisters one party from its parent when
278     * the number of parties of root is nonzero after deregistration.
279     */
280     public void testArriveAndDeregister5() {
281     Phaser parent = new Phaser();
282     Phaser child = new Phaser(parent);
283     Phaser root = new Phaser(child);
284     assertTrue(parent.getUnarrivedParties() > 0);
285     assertTrue(child.getUnarrivedParties() > 0);
286     root.register();
287     root.arriveAndDeregister();
288 jsr166 1.14 assertEquals(0, parent.getUnarrivedParties());
289     assertEquals(0, child.getUnarrivedParties());
290 dl 1.1 assertTrue(root.isTerminated());
291     }
292    
293     /**
294     * arriveAndDeregister returns the phase in which it leaves the
295     * phaser in after deregistration
296     */
297 jsr166 1.7 public void testArriveAndDeregister6() throws InterruptedException {
298 dl 1.1 final Phaser phaser = new Phaser(2);
299 jsr166 1.7 Thread t = newStartedThread(new CheckedRunnable() {
300 jsr166 1.9 public void realRun() {
301 jsr166 1.7 sleepTillInterrupted(SHORT_DELAY_MS);
302 dl 1.1 phaser.arrive();
303 jsr166 1.7 }});
304 dl 1.1 phaser.arriveAndAwaitAdvance();
305     int phase = phaser.arriveAndDeregister();
306     assertEquals(phase, phaser.getPhase());
307 jsr166 1.7 t.join();
308 dl 1.1 }
309    
310     /**
311     * awaitAdvance succeeds upon advance
312     */
313     public void testAwaitAdvance1() {
314     final Phaser phaser = new Phaser(1);
315     phaser.awaitAdvance(phaser.arrive());
316     }
317    
318     /**
319     * awaitAdvance with a negative parameter will return without affecting the
320     * phaser
321     */
322     public void testAwaitAdvance2() {
323 jsr166 1.6 Phaser phaser = new Phaser();
324     phaser.awaitAdvance(-1);
325 dl 1.1 }
326    
327     /**
328     * awaitAdvance while waiting does not abort on interrupt.
329     */
330 jsr166 1.6 public void testAwaitAdvance3() throws InterruptedException {
331 dl 1.1 final Phaser phaser = new Phaser();
332 jsr166 1.7 phaser.register();
333 dl 1.1
334 jsr166 1.7 Thread t = newStartedThread(new CheckedRunnable() {
335 jsr166 1.9 public void realRun() throws InterruptedException {
336 jsr166 1.5 phaser.register();
337 jsr166 1.7 sleepTillInterrupted(LONG_DELAY_MS);
338 jsr166 1.5 phaser.awaitAdvance(phaser.arrive());
339     }});
340 jsr166 1.7 Thread.sleep(SMALL_DELAY_MS);
341     t.interrupt();
342     Thread.sleep(SMALL_DELAY_MS);
343 jsr166 1.6 phaser.arrive();
344 jsr166 1.7 assertFalse(t.isInterrupted());
345     t.join();
346 dl 1.1 }
347    
348     /**
349     * awaitAdvance atomically waits for all parties within the same phase to
350     * complete before continuing
351     */
352 jsr166 1.5 public void testAwaitAdvance4() throws InterruptedException {
353     final Phaser phaser = new Phaser(4);
354 dl 1.1 final AtomicInteger phaseCount = new AtomicInteger(0);
355 jsr166 1.5 List<Thread> threads = new ArrayList<Thread>();
356     for (int i = 0; i < 4; i++) {
357 jsr166 1.7 threads.add(newStartedThread(new CheckedRunnable() {
358 jsr166 1.9 public void realRun() {
359 dl 1.1 int phase = phaser.arrive();
360     phaseCount.incrementAndGet();
361 jsr166 1.7 sleepTillInterrupted(SMALL_DELAY_MS);
362 dl 1.1 phaser.awaitAdvance(phase);
363 jsr166 1.10 assertEquals(phaseCount.get(), 4);
364 jsr166 1.5 }}));
365 dl 1.1 }
366 jsr166 1.5 for (Thread thread : threads)
367     thread.join();
368 dl 1.1 }
369    
370     /**
371     * awaitAdvance returns the current phase
372     */
373 jsr166 1.7 public void testAwaitAdvance5() throws InterruptedException {
374 dl 1.1 final Phaser phaser = new Phaser(1);
375     int phase = phaser.awaitAdvance(phaser.arrive());
376     assertEquals(phase, phaser.getPhase());
377     phaser.register();
378 jsr166 1.7 List<Thread> threads = new ArrayList<Thread>();
379     for (int i = 0; i < 8; i++) {
380     threads.add(newStartedThread(new CheckedRunnable() {
381 jsr166 1.9 public void realRun() {
382 jsr166 1.7 sleepTillInterrupted(SHORT_DELAY_MS);
383 dl 1.1 phaser.arrive();
384 jsr166 1.7 }}));
385 dl 1.1 phase = phaser.awaitAdvance(phaser.arrive());
386 jsr166 1.10 assertEquals(phase, phaser.getPhase());
387 dl 1.1 }
388 jsr166 1.7 for (Thread thread : threads)
389     thread.join();
390 dl 1.1 }
391    
392     /**
393     * awaitAdvance returns when the phaser is externally terminated
394     */
395 jsr166 1.7 public void testAwaitAdvance6() throws InterruptedException {
396 dl 1.1 final Phaser phaser = new Phaser(3);
397     /*
398     * Start new thread. This thread waits a small amount of time
399     * and waits for the other two parties to arrive. The party
400     * in the main thread arrives quickly so at best this thread
401     * waits for the second thread's party to arrive
402     */
403 jsr166 1.7 Thread t1 = newStartedThread(new CheckedRunnable() {
404 jsr166 1.9 public void realRun() {
405 jsr166 1.7 sleepTillInterrupted(SMALL_DELAY_MS);
406 dl 1.1 int phase = phaser.awaitAdvance(phaser.arrive());
407     /*
408     * This point is reached when force termination is called in which phase = -1
409     */
410 jsr166 1.10 assertTrue(phase < 0);
411     assertTrue(phaser.isTerminated());
412 jsr166 1.7 }});
413 dl 1.1 /*
414     * This thread will cause the first thread run to wait, in doing so
415 jsr166 1.2 * the main thread will force termination in which the first thread
416     * should exit peacefully as this one
417 dl 1.1 */
418 jsr166 1.7 Thread t2 = newStartedThread(new CheckedRunnable() {
419 jsr166 1.9 public void realRun() {
420 jsr166 1.7 sleepTillInterrupted(MEDIUM_DELAY_MS);
421 dl 1.1 int p1 = phaser.arrive();
422     int phase = phaser.awaitAdvance(p1);
423 jsr166 1.10 assertTrue(phase < 0);
424     assertTrue(phaser.isTerminated());
425 jsr166 1.7 }});
426 dl 1.1
427     phaser.arrive();
428     phaser.forceTermination();
429 jsr166 1.7 t1.join();
430     t2.join();
431 dl 1.1 }
432    
433     /**
434     * arriveAndAwaitAdvance throws IllegalStateException with no
435     * unarrived parties
436     */
437     public void testArriveAndAwaitAdvance1() {
438     try {
439     Phaser phaser = new Phaser();
440     phaser.arriveAndAwaitAdvance();
441     shouldThrow();
442 jsr166 1.8 } catch (IllegalStateException success) {}
443 dl 1.1 }
444    
445     /**
446     * Interrupted arriveAndAwaitAdvance does not throw InterruptedException
447     */
448 jsr166 1.6 public void testArriveAndAwaitAdvance2() throws InterruptedException {
449 dl 1.1 final Phaser phaser = new Phaser(2);
450 jsr166 1.16 final CountDownLatch threadStarted = new CountDownLatch(1);
451     final AtomicBoolean advanced = new AtomicBoolean(false);
452     final AtomicBoolean checkedInterruptStatus = new AtomicBoolean(false);
453     Thread t = newStartedThread(new CheckedRunnable() {
454     public void realRun() throws InterruptedException {
455     threadStarted.countDown();
456 jsr166 1.5 phaser.arriveAndAwaitAdvance();
457 jsr166 1.16 advanced.set(true);
458     assertTrue(Thread.currentThread().isInterrupted());
459     while (!checkedInterruptStatus.get())
460     Thread.yield();
461 jsr166 1.5 }});
462 dl 1.1
463 jsr166 1.16 assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
464     t.interrupt();
465 jsr166 1.6 phaser.arrive();
466 jsr166 1.16 while (!advanced.get())
467     Thread.yield();
468     assertTrue(t.isInterrupted());
469     checkedInterruptStatus.set(true);
470     awaitTermination(t, SMALL_DELAY_MS);
471 dl 1.1 }
472    
473     /**
474     * arriveAndAwaitAdvance waits for all threads to arrive, the
475     * number of arrived parties is the same number that is accounted
476     * for when the main thread awaitsAdvance
477     */
478 jsr166 1.7 public void testArriveAndAwaitAdvance3() throws InterruptedException {
479 dl 1.1 final Phaser phaser = new Phaser(1);
480 jsr166 1.7 final List<Thread> threads = new ArrayList<Thread>();
481 dl 1.11 for (int i = 0; i < 3; i++) {
482 jsr166 1.7 threads.add(newStartedThread(new CheckedRunnable() {
483 dl 1.11 public void realRun() throws InterruptedException {
484     phaser.register();
485 dl 1.12 phaser.arriveAndAwaitAdvance();
486 dl 1.11 }}));
487 dl 1.1 }
488 jsr166 1.13 Thread.sleep(MEDIUM_DELAY_MS);
489 dl 1.11 assertEquals(phaser.getArrivedParties(), 3);
490 dl 1.12 phaser.arriveAndAwaitAdvance();
491 jsr166 1.7 for (Thread thread : threads)
492     thread.join();
493 dl 1.1 }
494    
495     }