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

# 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.atomic.AtomicBoolean;
12 import java.util.concurrent.*;
13 import static java.util.concurrent.TimeUnit.MILLISECONDS;
14 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 shouldThrow();
46 } catch (IllegalArgumentException success) {}
47 }
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 } catch (IllegalArgumentException success) {}
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 * 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 * IllegalArgumentException
138 */
139 public void testBulkRegister1() {
140 try {
141 new Phaser().bulkRegister(-1);
142 shouldThrow();
143 } catch (IllegalArgumentException success) {}
144 }
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 * Registering with a number of parties greater than or equal to 1<<16
158 * throws IllegalStateException.
159 */
160 public void testBulkRegister3() {
161 try {
162 new Phaser().bulkRegister(1 << 16);
163 shouldThrow();
164 } catch (IllegalStateException success) {}
165 }
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 * Arrive() on a registered phaser increments phase.
182 */
183 public void testArrive1() {
184 Phaser phaser = new Phaser(1);
185 phaser.arrive();
186 assertEquals(1, phaser.getPhase());
187 }
188
189 /**
190 * arriveAndDeregister does not wait for others to arrive at barrier
191 */
192 public void testArrive2() throws InterruptedException {
193 final Phaser phaser = new Phaser(1);
194 phaser.register();
195 List<Thread> threads = new ArrayList<Thread>();
196 for (int i = 0; i < 10; i++)
197 phaser.register();
198 threads.add(newStartedThread(new CheckedRunnable() {
199 public void realRun() throws InterruptedException {
200 Thread.sleep(SMALL_DELAY_MS);
201 phaser.arriveAndDeregister();
202 }}));
203
204 phaser.arrive();
205 assertTrue(threads.get(0).isAlive());
206 assertFalse(phaser.isTerminated());
207 for (Thread thread : threads)
208 thread.join();
209 }
210
211 /**
212 * arrive() returns a negative number if the Phaser is terminated
213 */
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 * registered or unarrived parties would become negative
223 */
224 public void testArriveAndDeregister1() {
225 try {
226 Phaser phaser = new Phaser();
227 phaser.arriveAndDeregister();
228 shouldThrow();
229 } catch (IllegalStateException success) {}
230 }
231
232 /**
233 * arriveAndDeregister deregisters reduces the number of arrived parties
234 */
235 public void testArriveAndDergeister2() {
236 final Phaser phaser = new Phaser(1);
237 phaser.register();
238 phaser.arrive();
239 int p = phaser.getArrivedParties();
240 assertEquals(1, p);
241 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 assertEquals(0, parent.getUnarrivedParties());
258 assertEquals(0, root.getUnarrivedParties());
259 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 assertEquals(0, parent.getUnarrivedParties());
289 assertEquals(0, child.getUnarrivedParties());
290 assertTrue(root.isTerminated());
291 }
292
293 /**
294 * arriveAndDeregister returns the phase in which it leaves the
295 * phaser in after deregistration
296 */
297 public void testArriveAndDeregister6() throws InterruptedException {
298 final Phaser phaser = new Phaser(2);
299 Thread t = newStartedThread(new CheckedRunnable() {
300 public void realRun() {
301 sleepTillInterrupted(SHORT_DELAY_MS);
302 phaser.arrive();
303 }});
304 phaser.arriveAndAwaitAdvance();
305 int phase = phaser.arriveAndDeregister();
306 assertEquals(phase, phaser.getPhase());
307 t.join();
308 }
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 Phaser phaser = new Phaser();
324 phaser.awaitAdvance(-1);
325 }
326
327 /**
328 * awaitAdvance while waiting does not abort on interrupt.
329 */
330 public void testAwaitAdvance3() throws InterruptedException {
331 final Phaser phaser = new Phaser();
332 phaser.register();
333
334 Thread t = newStartedThread(new CheckedRunnable() {
335 public void realRun() throws InterruptedException {
336 phaser.register();
337 sleepTillInterrupted(LONG_DELAY_MS);
338 phaser.awaitAdvance(phaser.arrive());
339 }});
340 Thread.sleep(SMALL_DELAY_MS);
341 t.interrupt();
342 Thread.sleep(SMALL_DELAY_MS);
343 phaser.arrive();
344 assertFalse(t.isInterrupted());
345 t.join();
346 }
347
348 /**
349 * awaitAdvance atomically waits for all parties within the same phase to
350 * complete before continuing
351 */
352 public void testAwaitAdvance4() throws InterruptedException {
353 final Phaser phaser = new Phaser(4);
354 final AtomicInteger phaseCount = new AtomicInteger(0);
355 List<Thread> threads = new ArrayList<Thread>();
356 for (int i = 0; i < 4; i++) {
357 threads.add(newStartedThread(new CheckedRunnable() {
358 public void realRun() {
359 int phase = phaser.arrive();
360 phaseCount.incrementAndGet();
361 sleepTillInterrupted(SMALL_DELAY_MS);
362 phaser.awaitAdvance(phase);
363 assertEquals(phaseCount.get(), 4);
364 }}));
365 }
366 for (Thread thread : threads)
367 thread.join();
368 }
369
370 /**
371 * awaitAdvance returns the current phase
372 */
373 public void testAwaitAdvance5() throws InterruptedException {
374 final Phaser phaser = new Phaser(1);
375 int phase = phaser.awaitAdvance(phaser.arrive());
376 assertEquals(phase, phaser.getPhase());
377 phaser.register();
378 List<Thread> threads = new ArrayList<Thread>();
379 for (int i = 0; i < 8; i++) {
380 threads.add(newStartedThread(new CheckedRunnable() {
381 public void realRun() {
382 sleepTillInterrupted(SHORT_DELAY_MS);
383 phaser.arrive();
384 }}));
385 phase = phaser.awaitAdvance(phaser.arrive());
386 assertEquals(phase, phaser.getPhase());
387 }
388 for (Thread thread : threads)
389 thread.join();
390 }
391
392 /**
393 * awaitAdvance returns when the phaser is externally terminated
394 */
395 public void testAwaitAdvance6() throws InterruptedException {
396 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 Thread t1 = newStartedThread(new CheckedRunnable() {
404 public void realRun() {
405 sleepTillInterrupted(SMALL_DELAY_MS);
406 int phase = phaser.awaitAdvance(phaser.arrive());
407 /*
408 * This point is reached when force termination is called in which phase = -1
409 */
410 assertTrue(phase < 0);
411 assertTrue(phaser.isTerminated());
412 }});
413 /*
414 * This thread will cause the first thread run to wait, in doing so
415 * the main thread will force termination in which the first thread
416 * should exit peacefully as this one
417 */
418 Thread t2 = newStartedThread(new CheckedRunnable() {
419 public void realRun() {
420 sleepTillInterrupted(MEDIUM_DELAY_MS);
421 int p1 = phaser.arrive();
422 int phase = phaser.awaitAdvance(p1);
423 assertTrue(phase < 0);
424 assertTrue(phaser.isTerminated());
425 }});
426
427 phaser.arrive();
428 phaser.forceTermination();
429 t1.join();
430 t2.join();
431 }
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 } catch (IllegalStateException success) {}
443 }
444
445 /**
446 * Interrupted arriveAndAwaitAdvance does not throw InterruptedException
447 */
448 public void testArriveAndAwaitAdvance2() throws InterruptedException {
449 final Phaser phaser = new Phaser(2);
450 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 phaser.arriveAndAwaitAdvance();
457 advanced.set(true);
458 assertTrue(Thread.currentThread().isInterrupted());
459 while (!checkedInterruptStatus.get())
460 Thread.yield();
461 }});
462
463 assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS));
464 t.interrupt();
465 phaser.arrive();
466 while (!advanced.get())
467 Thread.yield();
468 assertTrue(t.isInterrupted());
469 checkedInterruptStatus.set(true);
470 awaitTermination(t, SMALL_DELAY_MS);
471 }
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 public void testArriveAndAwaitAdvance3() throws InterruptedException {
479 final Phaser phaser = new Phaser(1);
480 final List<Thread> threads = new ArrayList<Thread>();
481 for (int i = 0; i < 3; i++) {
482 threads.add(newStartedThread(new CheckedRunnable() {
483 public void realRun() throws InterruptedException {
484 phaser.register();
485 phaser.arriveAndAwaitAdvance();
486 }}));
487 }
488 Thread.sleep(MEDIUM_DELAY_MS);
489 assertEquals(phaser.getArrivedParties(), 3);
490 phaser.arriveAndAwaitAdvance();
491 for (Thread thread : threads)
492 thread.join();
493 }
494
495 }