--- jsr166/src/test/tck/CyclicBarrierTest.java 2003/09/25 11:02:41 1.4 +++ jsr166/src/test/tck/CyclicBarrierTest.java 2009/11/16 05:30:07 1.11 @@ -1,17 +1,20 @@ /* - * Written by members of JCP JSR-166 Expert Group and released to the - * public domain. Use, modify, and redistribute this code in any way - * without acknowledgement. Other contributors include Andrew Wright, - * Jeffrey Hayes, Pat Fischer, Mike Judd. + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/licenses/publicdomain + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. */ import junit.framework.*; import java.util.*; import java.util.concurrent.*; +import java.util.concurrent.locks.*; +import java.util.concurrent.atomic.*; -public class CyclicBarrierTest extends JSR166TestCase{ +public class CyclicBarrierTest extends JSR166TestCase { public static void main(String[] args) { - junit.textui.TestRunner.run (suite()); + junit.textui.TestRunner.run (suite()); } public static Test suite() { return new TestSuite(CyclicBarrierTest.class); @@ -21,7 +24,7 @@ public class CyclicBarrierTest extends J private class MyAction implements Runnable { public void run() { ++countAction; } } - + /** * Creating with negative parties throws IAE */ @@ -29,7 +32,7 @@ public class CyclicBarrierTest extends J try { new CyclicBarrier(-1, (Runnable)null); shouldThrow(); - } catch(IllegalArgumentException e){} + } catch (IllegalArgumentException e) {} } /** @@ -39,7 +42,7 @@ public class CyclicBarrierTest extends J try { new CyclicBarrier(-1); shouldThrow(); - } catch(IllegalArgumentException e){} + } catch (IllegalArgumentException e) {} } /** @@ -52,7 +55,7 @@ public class CyclicBarrierTest extends J } /** - * A 1-party barrier triggers properly + * A 1-party barrier triggers after single await */ public void testSingleParty() { try { @@ -63,11 +66,11 @@ public class CyclicBarrierTest extends J b.await(); assertEquals(0, b.getNumberWaiting()); } - catch(Exception e) { + catch (Exception e) { unexpectedException(); } } - + /** * The supplied barrier action is run at barrier */ @@ -82,13 +85,13 @@ public class CyclicBarrierTest extends J assertEquals(0, b.getNumberWaiting()); assertEquals(countAction, 2); } - catch(Exception e) { + catch (Exception e) { unexpectedException(); } } /** - * A 2-party/thread barrier triggers properly + * A 2-party/thread barrier triggers after both threads invoke await */ public void testTwoParties() { final CyclicBarrier b = new CyclicBarrier(2); @@ -99,7 +102,7 @@ public class CyclicBarrierTest extends J b.await(); b.await(); b.await(); - } catch(Exception e){ + } catch (Exception e) { threadUnexpectedException(); }}}); @@ -110,7 +113,7 @@ public class CyclicBarrierTest extends J b.await(); b.await(); t.join(); - } catch(Exception e){ + } catch (Exception e) { unexpectedException(); } } @@ -127,8 +130,8 @@ public class CyclicBarrierTest extends J try { c.await(); threadShouldThrow(); - } catch(InterruptedException success){} - catch(Exception b){ + } catch (InterruptedException success) {} + catch (Exception b) { threadUnexpectedException(); } } @@ -137,9 +140,9 @@ public class CyclicBarrierTest extends J public void run() { try { c.await(); - threadShouldThrow(); - } catch(BrokenBarrierException success){ - } catch(Exception i){ + threadShouldThrow(); + } catch (BrokenBarrierException success) { + } catch (Exception i) { threadUnexpectedException(); } } @@ -149,9 +152,9 @@ public class CyclicBarrierTest extends J t2.start(); Thread.sleep(SHORT_DELAY_MS); t1.interrupt(); - t1.join(); + t1.join(); t2.join(); - } catch(InterruptedException e){ + } catch (InterruptedException e) { unexpectedException(); } } @@ -161,14 +164,14 @@ public class CyclicBarrierTest extends J * throw BrokenBarrierException */ public void testAwait2_Interrupted_BrokenBarrier() { - final CyclicBarrier c = new CyclicBarrier(3); + final CyclicBarrier c = new CyclicBarrier(3); Thread t1 = new Thread(new Runnable() { public void run() { try { - c.await(MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS); + c.await(LONG_DELAY_MS, TimeUnit.MILLISECONDS); threadShouldThrow(); - } catch(InterruptedException success){ - } catch(Exception b){ + } catch (InterruptedException success) { + } catch (Exception b) { threadUnexpectedException(); } } @@ -176,10 +179,10 @@ public class CyclicBarrierTest extends J Thread t2 = new Thread(new Runnable() { public void run() { try { - c.await(MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS); - threadShouldThrow(); - } catch(BrokenBarrierException success){ - } catch(Exception i){ + c.await(LONG_DELAY_MS, TimeUnit.MILLISECONDS); + threadShouldThrow(); + } catch (BrokenBarrierException success) { + } catch (Exception i) { threadUnexpectedException(); } } @@ -189,13 +192,13 @@ public class CyclicBarrierTest extends J t2.start(); Thread.sleep(SHORT_DELAY_MS); t1.interrupt(); - t1.join(); + t1.join(); t2.join(); - } catch(InterruptedException e){ + } catch (InterruptedException e) { unexpectedException(); } } - + /** * A timeout in timed await throws TimeoutException */ @@ -206,21 +209,97 @@ public class CyclicBarrierTest extends J try { c.await(SHORT_DELAY_MS, TimeUnit.MILLISECONDS); threadShouldThrow(); - } catch(TimeoutException success){ - } catch(Exception b){ + } catch (TimeoutException success) { + } catch (Exception b) { threadUnexpectedException(); - + } } }); try { t.start(); - t.join(); - } catch(InterruptedException e){ + t.join(); + } catch (InterruptedException e) { + unexpectedException(); + } + } + + /** + * A timeout in one party causes others waiting in timed await to + * throw BrokenBarrierException + */ + public void testAwait4_Timeout_BrokenBarrier() { + final CyclicBarrier c = new CyclicBarrier(3); + Thread t1 = new Thread(new Runnable() { + public void run() { + try { + c.await(SHORT_DELAY_MS, TimeUnit.MILLISECONDS); + threadShouldThrow(); + } catch (TimeoutException success) { + } catch (Exception b) { + threadUnexpectedException(); + } + } + }); + Thread t2 = new Thread(new Runnable() { + public void run() { + try { + c.await(MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS); + threadShouldThrow(); + } catch (BrokenBarrierException success) { + } catch (Exception i) { + threadUnexpectedException(); + } + } + }); + try { + t1.start(); + t2.start(); + t1.join(); + t2.join(); + } catch (InterruptedException e) { unexpectedException(); } } - + + /** + * A timeout in one party causes others waiting in await to + * throw BrokenBarrierException + */ + public void testAwait5_Timeout_BrokenBarrier() { + final CyclicBarrier c = new CyclicBarrier(3); + Thread t1 = new Thread(new Runnable() { + public void run() { + try { + c.await(SHORT_DELAY_MS, TimeUnit.MILLISECONDS); + threadShouldThrow(); + } catch (TimeoutException success) { + } catch (Exception b) { + threadUnexpectedException(); + } + } + }); + Thread t2 = new Thread(new Runnable() { + public void run() { + try { + c.await(); + threadShouldThrow(); + } catch (BrokenBarrierException success) { + } catch (Exception i) { + threadUnexpectedException(); + } + } + }); + try { + t1.start(); + t2.start(); + t1.join(); + t2.join(); + } catch (InterruptedException e) { + unexpectedException(); + } + } + /** * A reset of an active barrier causes waiting threads to throw * BrokenBarrierException @@ -232,8 +311,8 @@ public class CyclicBarrierTest extends J try { c.await(); threadShouldThrow(); - } catch(BrokenBarrierException success){} - catch(Exception b){ + } catch (BrokenBarrierException success) {} + catch (Exception b) { threadUnexpectedException(); } } @@ -242,9 +321,9 @@ public class CyclicBarrierTest extends J public void run() { try { c.await(); - threadShouldThrow(); - } catch(BrokenBarrierException success){ - } catch(Exception i){ + threadShouldThrow(); + } catch (BrokenBarrierException success) { + } catch (Exception i) { threadUnexpectedException(); } } @@ -254,9 +333,9 @@ public class CyclicBarrierTest extends J t2.start(); Thread.sleep(SHORT_DELAY_MS); c.reset(); - t1.join(); + t1.join(); t2.join(); - } catch(InterruptedException e){ + } catch (InterruptedException e) { unexpectedException(); } } @@ -271,7 +350,7 @@ public class CyclicBarrierTest extends J public void run() { try { c.await(); - } catch(Exception b){ + } catch (Exception b) { threadUnexpectedException(); } } @@ -280,7 +359,7 @@ public class CyclicBarrierTest extends J public void run() { try { c.await(); - } catch(Exception i){ + } catch (Exception i) { threadUnexpectedException(); } } @@ -290,11 +369,256 @@ public class CyclicBarrierTest extends J t1.start(); t2.start(); c.await(); - t1.join(); + t1.join(); t2.join(); - } catch(Exception e){ + } catch (Exception e) { unexpectedException(); } } + /** + * All threads block while a barrier is broken. + */ + public void testReset_Leakage() { + try { + final CyclicBarrier c = new CyclicBarrier(2); + final AtomicBoolean done = new AtomicBoolean(); + Thread t = new Thread() { + public void run() { + while (!done.get()) { + try { + while (c.isBroken()) + c.reset(); + + c.await(); + threadFail("await should not return"); + } + catch (BrokenBarrierException e) { + } + catch (InterruptedException ie) { + } + } + } + }; + + t.start(); + for ( int i = 0; i < 4; i++) { + Thread.sleep(SHORT_DELAY_MS); + t.interrupt(); + } + done.set(true); + t.interrupt(); + } + catch (Exception ex) { + unexpectedException(); + } + } + + /** + * Reset of a non-broken barrier does not break barrier + */ + public void testResetWithoutBreakage() { + try { + final CyclicBarrier start = new CyclicBarrier(3); + final CyclicBarrier barrier = new CyclicBarrier(3); + for (int i = 0; i < 3; i++) { + Thread t1 = new Thread(new Runnable() { + public void run() { + try { start.await(); } + catch (Exception ie) { + threadFail("start barrier"); + } + try { barrier.await(); } + catch (Throwable thrown) { + unexpectedException(); + }}}); + + Thread t2 = new Thread(new Runnable() { + public void run() { + try { start.await(); } + catch (Exception ie) { + threadFail("start barrier"); + } + try { barrier.await(); } + catch (Throwable thrown) { + unexpectedException(); + }}}); + + + t1.start(); + t2.start(); + try { start.await(); } + catch (Exception ie) { threadFail("start barrier"); } + barrier.await(); + t1.join(); + t2.join(); + assertFalse(barrier.isBroken()); + assertEquals(0, barrier.getNumberWaiting()); + if (i == 1) barrier.reset(); + assertFalse(barrier.isBroken()); + assertEquals(0, barrier.getNumberWaiting()); + } + } + catch (Exception ex) { + unexpectedException(); + } + } + + /** + * Reset of a barrier after interruption reinitializes it. + */ + public void testResetAfterInterrupt() { + try { + final CyclicBarrier start = new CyclicBarrier(3); + final CyclicBarrier barrier = new CyclicBarrier(3); + for (int i = 0; i < 2; i++) { + Thread t1 = new Thread(new Runnable() { + public void run() { + try { start.await(); } + catch (Exception ie) { + threadFail("start barrier"); + } + try { barrier.await(); } + catch (InterruptedException ok) {} + catch (Throwable thrown) { + unexpectedException(); + }}}); + + Thread t2 = new Thread(new Runnable() { + public void run() { + try { start.await(); } + catch (Exception ie) { + threadFail("start barrier"); + } + try { barrier.await(); } + catch (BrokenBarrierException ok) {} + catch (Throwable thrown) { + unexpectedException(); + }}}); + + t1.start(); + t2.start(); + try { start.await(); } + catch (Exception ie) { threadFail("start barrier"); } + t1.interrupt(); + t1.join(); + t2.join(); + assertTrue(barrier.isBroken()); + assertEquals(0, barrier.getNumberWaiting()); + barrier.reset(); + assertFalse(barrier.isBroken()); + assertEquals(0, barrier.getNumberWaiting()); + } + } + catch (Exception ex) { + unexpectedException(); + } + } + + /** + * Reset of a barrier after timeout reinitializes it. + */ + public void testResetAfterTimeout() { + try { + final CyclicBarrier start = new CyclicBarrier(3); + final CyclicBarrier barrier = new CyclicBarrier(3); + for (int i = 0; i < 2; i++) { + Thread t1 = new Thread(new Runnable() { + public void run() { + try { start.await(); } + catch (Exception ie) { + threadFail("start barrier"); + } + try { barrier.await(MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS); } + catch (TimeoutException ok) {} + catch (Throwable thrown) { + unexpectedException(); + }}}); + + Thread t2 = new Thread(new Runnable() { + public void run() { + try { start.await(); } + catch (Exception ie) { + threadFail("start barrier"); + } + try { barrier.await(); } + catch (BrokenBarrierException ok) {} + catch (Throwable thrown) { + unexpectedException(); + }}}); + + t1.start(); + t2.start(); + try { start.await(); } + catch (Exception ie) { threadFail("start barrier"); } + t1.join(); + t2.join(); + assertTrue(barrier.isBroken()); + assertEquals(0, barrier.getNumberWaiting()); + barrier.reset(); + assertFalse(barrier.isBroken()); + assertEquals(0, barrier.getNumberWaiting()); + } + } + catch (Exception ex) { + unexpectedException(); + } + } + + + /** + * Reset of a barrier after a failed command reinitializes it. + */ + public void testResetAfterCommandException() { + try { + final CyclicBarrier start = new CyclicBarrier(3); + final CyclicBarrier barrier = + new CyclicBarrier(3, new Runnable() { + public void run() { + throw new NullPointerException(); }}); + for (int i = 0; i < 2; i++) { + Thread t1 = new Thread(new Runnable() { + public void run() { + try { start.await(); } + catch (Exception ie) { + threadFail("start barrier"); + } + try { barrier.await(); } + catch (BrokenBarrierException ok) {} + catch (Throwable thrown) { + unexpectedException(); + }}}); + + Thread t2 = new Thread(new Runnable() { + public void run() { + try { start.await(); } + catch (Exception ie) { + threadFail("start barrier"); + } + try { barrier.await(); } + catch (BrokenBarrierException ok) {} + catch (Throwable thrown) { + unexpectedException(); + }}}); + + t1.start(); + t2.start(); + try { start.await(); } + catch (Exception ie) { threadFail("start barrier"); } + while (barrier.getNumberWaiting() < 2) { Thread.yield(); } + try { barrier.await(); } + catch (Exception ok) { } + t1.join(); + t2.join(); + assertTrue(barrier.isBroken()); + assertEquals(0, barrier.getNumberWaiting()); + barrier.reset(); + assertFalse(barrier.isBroken()); + assertEquals(0, barrier.getNumberWaiting()); + } + } + catch (Exception ex) { + unexpectedException(); + } + } }