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

# 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 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 * arriveAndDeregister does not wait for others to arrive at barrier
194 */
195 public void testArrive2() throws InterruptedException {
196 final Phaser phaser = new Phaser(1);
197 phaser.register();
198 List<Thread> threads = new ArrayList<Thread>();
199 for (int i = 0; i < 10; i++)
200 phaser.register();
201 threads.add(newStartedThread(new CheckedRunnable() {
202 void realRun() throws InterruptedException {
203 Thread.sleep(SMALL_DELAY_MS);
204 phaser.arriveAndDeregister();
205 }}));
206
207 phaser.arrive();
208 assertTrue(threads.get(0).isAlive());
209 assertFalse(phaser.isTerminated());
210 for (Thread thread : threads)
211 thread.join();
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 * arriveAndDeregister() throws IllegalStateException if number of
225 * registered or unarrived parties would become negative
226 */
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 * arriveAndDeregister deregisters reduces the number of arrived parties
238 */
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 public void testArriveAndDeregister6() throws InterruptedException {
302 final Phaser phaser = new Phaser(2);
303 Thread t = newStartedThread(new CheckedRunnable() {
304 void realRun() {
305 sleepTillInterrupted(SHORT_DELAY_MS);
306 phaser.arrive();
307 }});
308 phaser.arriveAndAwaitAdvance();
309 int phase = phaser.arriveAndDeregister();
310 assertEquals(phase, phaser.getPhase());
311 t.join();
312 }
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 Phaser phaser = new Phaser();
328 phaser.awaitAdvance(-1);
329 }
330
331 /**
332 * awaitAdvance while waiting does not abort on interrupt.
333 */
334 public void testAwaitAdvance3() throws InterruptedException {
335 final Phaser phaser = new Phaser();
336 phaser.register();
337
338 Thread t = newStartedThread(new CheckedRunnable() {
339 void realRun() throws InterruptedException {
340 phaser.register();
341 sleepTillInterrupted(LONG_DELAY_MS);
342 phaser.awaitAdvance(phaser.arrive());
343 }});
344 Thread.sleep(SMALL_DELAY_MS);
345 t.interrupt();
346 Thread.sleep(SMALL_DELAY_MS);
347 phaser.arrive();
348 assertFalse(t.isInterrupted());
349 t.join();
350 }
351
352 /**
353 * awaitAdvance atomically waits for all parties within the same phase to
354 * complete before continuing
355 */
356 public void testAwaitAdvance4() throws InterruptedException {
357 final Phaser phaser = new Phaser(4);
358 final AtomicInteger phaseCount = new AtomicInteger(0);
359 List<Thread> threads = new ArrayList<Thread>();
360 for (int i = 0; i < 4; i++) {
361 threads.add(newStartedThread(new CheckedRunnable() {
362 void realRun() {
363 int phase = phaser.arrive();
364 phaseCount.incrementAndGet();
365 sleepTillInterrupted(SMALL_DELAY_MS);
366 phaser.awaitAdvance(phase);
367 threadAssertTrue(phaseCount.get() == 4);
368 }}));
369 }
370 for (Thread thread : threads)
371 thread.join();
372 }
373
374 /**
375 * awaitAdvance returns the current phase
376 */
377 public void testAwaitAdvance5() throws InterruptedException {
378 final Phaser phaser = new Phaser(1);
379 int phase = phaser.awaitAdvance(phaser.arrive());
380 assertEquals(phase, phaser.getPhase());
381 phaser.register();
382 List<Thread> threads = new ArrayList<Thread>();
383 for (int i = 0; i < 8; i++) {
384 threads.add(newStartedThread(new CheckedRunnable() {
385 void realRun() {
386 sleepTillInterrupted(SHORT_DELAY_MS);
387 phaser.arrive();
388 }}));
389 phase = phaser.awaitAdvance(phaser.arrive());
390 threadAssertEquals(phase, phaser.getPhase());
391 }
392 for (Thread thread : threads)
393 thread.join();
394 }
395
396 /**
397 * awaitAdvance returns when the phaser is externally terminated
398 */
399 public void testAwaitAdvance6() throws InterruptedException {
400 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 Thread t1 = newStartedThread(new CheckedRunnable() {
408 void realRun() {
409 sleepTillInterrupted(SMALL_DELAY_MS);
410 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 }});
417 /*
418 * This thread will cause the first thread run to wait, in doing so
419 * the main thread will force termination in which the first thread
420 * should exit peacefully as this one
421 */
422 Thread t2 = newStartedThread(new CheckedRunnable() {
423 void realRun() {
424 sleepTillInterrupted(MEDIUM_DELAY_MS);
425 int p1 = phaser.arrive();
426 int phase = phaser.awaitAdvance(p1);
427 threadAssertTrue(phase < 0);
428 threadAssertTrue(phaser.isTerminated());
429 }});
430
431 phaser.arrive();
432 phaser.forceTermination();
433 t1.join();
434 t2.join();
435 }
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 public void testArriveAndAwaitAdvance2() throws InterruptedException {
454 final Phaser phaser = new Phaser(2);
455 Thread th = newStartedThread(new CheckedRunnable() {
456 void realRun() {
457 phaser.arriveAndAwaitAdvance();
458 }});
459
460 Thread.sleep(SMALL_DELAY_MS);
461 th.interrupt();
462 Thread.sleep(SMALL_DELAY_MS);
463 phaser.arrive();
464 assertFalse(th.isInterrupted());
465 th.join();
466 }
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 public void testArriveAndAwaitAdvance3() throws InterruptedException {
474 final Phaser phaser = new Phaser(1);
475 final AtomicInteger arrivingCount = new AtomicInteger(0);
476 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 phaser.register();
481 sleepTillInterrupted(SHORT_DELAY_MS);
482 arrivingCount.getAndIncrement();
483 phaser.arrive();
484 }}));
485 }
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 for (Thread thread : threads)
492 thread.join();
493 }
494
495 }