blob: a9d8c54633e68d53e4e382ae9817ec06a8637cbf [file] [log] [blame]
Calin Juravle8f0d92b2013-08-01 17:26:00 +01001/*
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/publicdomain/zero/1.0/
5 * Other contributors include Andrew Wright, Jeffrey Hayes,
6 * Pat Fisher, Mike Judd.
7 */
8
9package jsr166;
10
Narayan Kamath8e9a0e92015-04-28 11:40:00 +010011import static java.util.concurrent.TimeUnit.MILLISECONDS;
12
Calin Juravle8f0d92b2013-08-01 17:26:00 +010013import java.util.concurrent.BrokenBarrierException;
14import java.util.concurrent.CountDownLatch;
15import java.util.concurrent.CyclicBarrier;
16import java.util.concurrent.TimeoutException;
17import java.util.concurrent.atomic.AtomicBoolean;
Narayan Kamath8e9a0e92015-04-28 11:40:00 +010018
19import junit.framework.Test;
20import junit.framework.TestSuite;
Calin Juravle8f0d92b2013-08-01 17:26:00 +010021
22public class CyclicBarrierTest extends JSR166TestCase {
Narayan Kamath8e9a0e92015-04-28 11:40:00 +010023 // android-note: Removed because the CTS runner does a bad job of
24 // retrying tests that have suite() declarations.
25 //
26 // public static void main(String[] args) {
27 // main(suite(), args);
28 // }
29 // public static Test suite() {
30 // return new TestSuite(...);
31 // }
Calin Juravle8f0d92b2013-08-01 17:26:00 +010032
33 private volatile int countAction;
34 private class MyAction implements Runnable {
35 public void run() { ++countAction; }
36 }
37
38 /**
39 * Spin-waits till the number of waiters == numberOfWaiters.
40 */
41 void awaitNumberWaiting(CyclicBarrier barrier, int numberOfWaiters) {
42 long startTime = System.nanoTime();
43 while (barrier.getNumberWaiting() != numberOfWaiters) {
44 if (millisElapsedSince(startTime) > LONG_DELAY_MS)
45 fail("timed out");
46 Thread.yield();
47 }
48 }
49
50 /**
51 * Creating with negative parties throws IAE
52 */
53 public void testConstructor1() {
54 try {
55 new CyclicBarrier(-1, (Runnable)null);
56 shouldThrow();
57 } catch (IllegalArgumentException success) {}
58 }
59
60 /**
61 * Creating with negative parties and no action throws IAE
62 */
63 public void testConstructor2() {
64 try {
65 new CyclicBarrier(-1);
66 shouldThrow();
67 } catch (IllegalArgumentException success) {}
68 }
69
70 /**
71 * getParties returns the number of parties given in constructor
72 */
73 public void testGetParties() {
74 CyclicBarrier b = new CyclicBarrier(2);
75 assertEquals(2, b.getParties());
76 assertEquals(0, b.getNumberWaiting());
77 }
78
79 /**
80 * A 1-party barrier triggers after single await
81 */
82 public void testSingleParty() throws Exception {
83 CyclicBarrier b = new CyclicBarrier(1);
84 assertEquals(1, b.getParties());
85 assertEquals(0, b.getNumberWaiting());
86 b.await();
87 b.await();
88 assertEquals(0, b.getNumberWaiting());
89 }
90
91 /**
92 * The supplied barrier action is run at barrier
93 */
94 public void testBarrierAction() throws Exception {
95 countAction = 0;
96 CyclicBarrier b = new CyclicBarrier(1, new MyAction());
97 assertEquals(1, b.getParties());
98 assertEquals(0, b.getNumberWaiting());
99 b.await();
100 b.await();
101 assertEquals(0, b.getNumberWaiting());
102 assertEquals(2, countAction);
103 }
104
105 /**
106 * A 2-party/thread barrier triggers after both threads invoke await
107 */
108 public void testTwoParties() throws Exception {
109 final CyclicBarrier b = new CyclicBarrier(2);
110 Thread t = newStartedThread(new CheckedRunnable() {
111 public void realRun() throws Exception {
112 b.await();
113 b.await();
114 b.await();
115 b.await();
116 }});
117
118 b.await();
119 b.await();
120 b.await();
121 b.await();
122 awaitTermination(t);
123 }
124
125 /**
126 * An interruption in one party causes others waiting in await to
127 * throw BrokenBarrierException
128 */
129 public void testAwait1_Interrupted_BrokenBarrier() {
130 final CyclicBarrier c = new CyclicBarrier(3);
131 final CountDownLatch pleaseInterrupt = new CountDownLatch(2);
132 Thread t1 = new ThreadShouldThrow(InterruptedException.class) {
133 public void realRun() throws Exception {
134 pleaseInterrupt.countDown();
135 c.await();
136 }};
137 Thread t2 = new ThreadShouldThrow(BrokenBarrierException.class) {
138 public void realRun() throws Exception {
139 pleaseInterrupt.countDown();
140 c.await();
141 }};
142
143 t1.start();
144 t2.start();
145 await(pleaseInterrupt);
146 t1.interrupt();
147 awaitTermination(t1);
148 awaitTermination(t2);
149 }
150
151 /**
152 * An interruption in one party causes others waiting in timed await to
153 * throw BrokenBarrierException
154 */
155 public void testAwait2_Interrupted_BrokenBarrier() throws Exception {
156 final CyclicBarrier c = new CyclicBarrier(3);
157 final CountDownLatch pleaseInterrupt = new CountDownLatch(2);
158 Thread t1 = new ThreadShouldThrow(InterruptedException.class) {
159 public void realRun() throws Exception {
160 pleaseInterrupt.countDown();
161 c.await(LONG_DELAY_MS, MILLISECONDS);
162 }};
163 Thread t2 = new ThreadShouldThrow(BrokenBarrierException.class) {
164 public void realRun() throws Exception {
165 pleaseInterrupt.countDown();
166 c.await(LONG_DELAY_MS, MILLISECONDS);
167 }};
168
169 t1.start();
170 t2.start();
171 await(pleaseInterrupt);
172 t1.interrupt();
173 awaitTermination(t1);
174 awaitTermination(t2);
175 }
176
177 /**
178 * A timeout in timed await throws TimeoutException
179 */
180 public void testAwait3_TimeoutException() throws InterruptedException {
181 final CyclicBarrier c = new CyclicBarrier(2);
182 Thread t = newStartedThread(new CheckedRunnable() {
183 public void realRun() throws Exception {
184 long startTime = System.nanoTime();
185 try {
186 c.await(timeoutMillis(), MILLISECONDS);
187 shouldThrow();
188 } catch (TimeoutException success) {}
189 assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
190 }});
191
192 awaitTermination(t);
193 }
194
195 /**
196 * A timeout in one party causes others waiting in timed await to
197 * throw BrokenBarrierException
198 */
199 public void testAwait4_Timeout_BrokenBarrier() throws InterruptedException {
200 final CyclicBarrier c = new CyclicBarrier(3);
201 Thread t1 = newStartedThread(new CheckedRunnable() {
202 public void realRun() throws Exception {
203 try {
204 c.await(LONG_DELAY_MS, MILLISECONDS);
205 shouldThrow();
206 } catch (BrokenBarrierException success) {}
207 }});
208 Thread t2 = newStartedThread(new CheckedRunnable() {
209 public void realRun() throws Exception {
210 awaitNumberWaiting(c, 1);
211 long startTime = System.nanoTime();
212 try {
213 c.await(timeoutMillis(), MILLISECONDS);
214 shouldThrow();
215 } catch (TimeoutException success) {}
216 assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
217 }});
218
219 awaitTermination(t1);
220 awaitTermination(t2);
221 }
222
223 /**
224 * A timeout in one party causes others waiting in await to
225 * throw BrokenBarrierException
226 */
227 public void testAwait5_Timeout_BrokenBarrier() throws InterruptedException {
228 final CyclicBarrier c = new CyclicBarrier(3);
229 Thread t1 = newStartedThread(new CheckedRunnable() {
230 public void realRun() throws Exception {
231 try {
232 c.await();
233 shouldThrow();
234 } catch (BrokenBarrierException success) {}
235 }});
236 Thread t2 = newStartedThread(new CheckedRunnable() {
237 public void realRun() throws Exception {
238 awaitNumberWaiting(c, 1);
239 long startTime = System.nanoTime();
240 try {
241 c.await(timeoutMillis(), MILLISECONDS);
242 shouldThrow();
243 } catch (TimeoutException success) {}
244 assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
245 }});
246
247 awaitTermination(t1);
248 awaitTermination(t2);
249 }
250
251 /**
252 * A reset of an active barrier causes waiting threads to throw
253 * BrokenBarrierException
254 */
255 public void testReset_BrokenBarrier() throws InterruptedException {
256 final CyclicBarrier c = new CyclicBarrier(3);
257 final CountDownLatch pleaseReset = new CountDownLatch(2);
258 Thread t1 = new ThreadShouldThrow(BrokenBarrierException.class) {
259 public void realRun() throws Exception {
260 pleaseReset.countDown();
261 c.await();
262 }};
263 Thread t2 = new ThreadShouldThrow(BrokenBarrierException.class) {
264 public void realRun() throws Exception {
265 pleaseReset.countDown();
266 c.await();
267 }};
268
269 t1.start();
270 t2.start();
271 await(pleaseReset);
272
273 awaitNumberWaiting(c, 2);
274 c.reset();
275 awaitTermination(t1);
276 awaitTermination(t2);
277 }
278
279 /**
280 * A reset before threads enter barrier does not throw
281 * BrokenBarrierException
282 */
283 public void testReset_NoBrokenBarrier() throws Exception {
284 final CyclicBarrier c = new CyclicBarrier(3);
285 c.reset();
286
287 Thread t1 = newStartedThread(new CheckedRunnable() {
288 public void realRun() throws Exception {
289 c.await();
290 }});
291 Thread t2 = newStartedThread(new CheckedRunnable() {
292 public void realRun() throws Exception {
293 c.await();
294 }});
295
296 c.await();
297 awaitTermination(t1);
298 awaitTermination(t2);
299 }
300
301 /**
302 * All threads block while a barrier is broken.
303 */
304 public void testReset_Leakage() throws InterruptedException {
305 final CyclicBarrier c = new CyclicBarrier(2);
306 final AtomicBoolean done = new AtomicBoolean();
307 Thread t = newStartedThread(new CheckedRunnable() {
308 public void realRun() {
309 while (!done.get()) {
310 try {
311 while (c.isBroken())
312 c.reset();
313
314 c.await();
315 shouldThrow();
316 }
317 catch (BrokenBarrierException ok) {}
318 catch (InterruptedException ok) {}
319 }}});
320
321 for (int i = 0; i < 4; i++) {
322 delay(timeoutMillis());
323 t.interrupt();
324 }
325 done.set(true);
326 t.interrupt();
327 awaitTermination(t);
328 }
329
330 /**
331 * Reset of a non-broken barrier does not break barrier
332 */
333 public void testResetWithoutBreakage() throws Exception {
334 final CyclicBarrier barrier = new CyclicBarrier(3);
335 for (int i = 0; i < 3; i++) {
336 final CyclicBarrier start = new CyclicBarrier(3);
337 Thread t1 = newStartedThread(new CheckedRunnable() {
338 public void realRun() throws Exception {
339 start.await();
340 barrier.await();
341 }});
342
343 Thread t2 = newStartedThread(new CheckedRunnable() {
344 public void realRun() throws Exception {
345 start.await();
346 barrier.await();
347 }});
348
349 start.await();
350 barrier.await();
351 awaitTermination(t1);
352 awaitTermination(t2);
353 assertFalse(barrier.isBroken());
354 assertEquals(0, barrier.getNumberWaiting());
355 if (i == 1) barrier.reset();
356 assertFalse(barrier.isBroken());
357 assertEquals(0, barrier.getNumberWaiting());
358 }
359 }
360
361 /**
362 * Reset of a barrier after interruption reinitializes it.
363 */
364 public void testResetAfterInterrupt() throws Exception {
365 final CyclicBarrier barrier = new CyclicBarrier(3);
366 for (int i = 0; i < 2; i++) {
367 final CyclicBarrier start = new CyclicBarrier(3);
368 Thread t1 = new ThreadShouldThrow(InterruptedException.class) {
369 public void realRun() throws Exception {
370 start.await();
371 barrier.await();
372 }};
373
374 Thread t2 = new ThreadShouldThrow(BrokenBarrierException.class) {
375 public void realRun() throws Exception {
376 start.await();
377 barrier.await();
378 }};
379
380 t1.start();
381 t2.start();
382 start.await();
383 t1.interrupt();
384 awaitTermination(t1);
385 awaitTermination(t2);
386 assertTrue(barrier.isBroken());
387 assertEquals(0, barrier.getNumberWaiting());
388 barrier.reset();
389 assertFalse(barrier.isBroken());
390 assertEquals(0, barrier.getNumberWaiting());
391 }
392 }
393
394 /**
395 * Reset of a barrier after timeout reinitializes it.
396 */
397 public void testResetAfterTimeout() throws Exception {
398 final CyclicBarrier barrier = new CyclicBarrier(3);
399 for (int i = 0; i < 2; i++) {
400 assertEquals(0, barrier.getNumberWaiting());
401 Thread t1 = newStartedThread(new CheckedRunnable() {
402 public void realRun() throws Exception {
403 try {
404 barrier.await();
405 shouldThrow();
406 } catch (BrokenBarrierException success) {}
407 }});
408 Thread t2 = newStartedThread(new CheckedRunnable() {
409 public void realRun() throws Exception {
410 awaitNumberWaiting(barrier, 1);
411 long startTime = System.nanoTime();
412 try {
413 barrier.await(timeoutMillis(), MILLISECONDS);
414 shouldThrow();
415 } catch (TimeoutException success) {}
416 assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
417 }});
418
419 awaitTermination(t1);
420 awaitTermination(t2);
421 assertEquals(0, barrier.getNumberWaiting());
422 assertTrue(barrier.isBroken());
423 assertEquals(0, barrier.getNumberWaiting());
424 barrier.reset();
425 assertFalse(barrier.isBroken());
426 assertEquals(0, barrier.getNumberWaiting());
427 }
428 }
429
430 /**
431 * Reset of a barrier after a failed command reinitializes it.
432 */
433 public void testResetAfterCommandException() throws Exception {
434 final CyclicBarrier barrier =
435 new CyclicBarrier(3, new Runnable() {
436 public void run() {
437 throw new NullPointerException(); }});
438 for (int i = 0; i < 2; i++) {
439 final CyclicBarrier start = new CyclicBarrier(3);
440 Thread t1 = new ThreadShouldThrow(BrokenBarrierException.class) {
441 public void realRun() throws Exception {
442 start.await();
443 barrier.await();
444 }};
445
446 Thread t2 = new ThreadShouldThrow(BrokenBarrierException.class) {
447 public void realRun() throws Exception {
448 start.await();
449 barrier.await();
450 }};
451
452 t1.start();
453 t2.start();
454 start.await();
455 awaitNumberWaiting(barrier, 2);
456 try {
457 barrier.await();
458 shouldThrow();
459 } catch (NullPointerException success) {}
460 awaitTermination(t1);
461 awaitTermination(t2);
462 assertTrue(barrier.isBroken());
463 assertEquals(0, barrier.getNumberWaiting());
464 barrier.reset();
465 assertFalse(barrier.isBroken());
466 assertEquals(0, barrier.getNumberWaiting());
467 }
468 }
469}