--- jsr166/src/test/tck/PhaserTest.java 2010/10/15 22:43:02 1.19 +++ jsr166/src/test/tck/PhaserTest.java 2011/03/15 19:47:07 1.31 @@ -1,7 +1,7 @@ /* * 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 + * http://creativecommons.org/publicdomain/zero/1.0/ * Other contributors include John Vint */ @@ -25,45 +25,51 @@ public class PhaserTest extends JSR166Te return new TestSuite(PhaserTest.class); } - /** Checks state of phaser. */ + private static final int maxParties = 65535; + + /** Checks state of unterminated phaser. */ protected void assertState(Phaser phaser, int phase, int parties, int unarrived) { assertEquals(phase, phaser.getPhase()); assertEquals(parties, phaser.getRegisteredParties()); assertEquals(unarrived, phaser.getUnarrivedParties()); assertEquals(parties - unarrived, phaser.getArrivedParties()); - assertTrue((phaser.getPhase() >= 0) ^ phaser.isTerminated()); + assertFalse(phaser.isTerminated()); } /** Checks state of terminated phaser. */ - protected void assertTerminated(Phaser phaser, int parties, int unarrived) { + protected void assertTerminated(Phaser phaser, int maxPhase, int parties) { assertTrue(phaser.isTerminated()); - assertTrue(phaser.getPhase() < 0); + int expectedPhase = maxPhase + Integer.MIN_VALUE; + assertEquals(expectedPhase, phaser.getPhase()); assertEquals(parties, phaser.getRegisteredParties()); - assertEquals(unarrived, phaser.getUnarrivedParties()); - assertEquals(parties - unarrived, phaser.getArrivedParties()); + assertEquals(expectedPhase, phaser.register()); + assertEquals(expectedPhase, phaser.arrive()); + assertEquals(expectedPhase, phaser.arriveAndDeregister()); } - protected void assertTerminated(Phaser phaser) { - assertTerminated(phaser, 0, 0); + protected void assertTerminated(Phaser phaser, int maxPhase) { + assertTerminated(phaser, maxPhase, 0); } /** * Empty constructor builds a new Phaser with no parent, no registered * parties and initial phase number of 0 */ - public void testConstructor1() { + public void testConstructorDefaultValues() { Phaser phaser = new Phaser(); assertNull(phaser.getParent()); + assertEquals(0, phaser.getRegisteredParties()); assertEquals(0, phaser.getArrivedParties()); + assertEquals(0, phaser.getUnarrivedParties()); assertEquals(0, phaser.getPhase()); } /** - * A negative party number for the constructor throws illegal argument - * exception + * Constructing with a negative number of parties throws + * IllegalArgumentException */ - public void testConstructor2() { + public void testConstructorNegativeParties() { try { new Phaser(-1); shouldThrow(); @@ -71,23 +77,42 @@ public class PhaserTest extends JSR166Te } /** - * The parent being input into the constructor should equal the original - * parent when being returned + * Constructing with a negative number of parties throws + * IllegalArgumentException */ - public void testConstructor3() { - Phaser parent = new Phaser(); - assertEquals(parent, new Phaser(parent).getParent()); + public void testConstructorNegativeParties2() { + try { + new Phaser(new Phaser(), -1); + shouldThrow(); + } catch (IllegalArgumentException success) {} } /** - * A negative party number for the constructor throws illegal argument - * exception + * Constructing with a number of parties > 65535 throws + * IllegalArgumentException */ - public void testConstructor4() { + public void testConstructorPartiesExceedsLimit() { + new Phaser(maxParties); try { - new Phaser(new Phaser(), -1); + new Phaser(maxParties + 1); shouldThrow(); } catch (IllegalArgumentException success) {} + + new Phaser(new Phaser(), maxParties); + try { + new Phaser(new Phaser(), maxParties + 1); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + + /** + * The parent provided to the constructor should be returned from + * a later call to getParent + */ + public void testConstructor3() { + Phaser parent = new Phaser(); + assertSame(parent, new Phaser(parent).getParent()); + assertNull(new Phaser(null).getParent()); } /** @@ -96,12 +121,13 @@ public class PhaserTest extends JSR166Te */ public void testConstructor5() { Phaser parent = new Phaser(); - assertEquals(parent, new Phaser(parent, 0).getParent()); + assertSame(parent, new Phaser(parent, 0).getParent()); + assertNull(new Phaser(null, 0).getParent()); } /** - * register() will increment the number of unarrived parties by one and not - * affect its arrived parties + * register() will increment the number of unarrived parties by + * one and not affect its arrived parties */ public void testRegister1() { Phaser phaser = new Phaser(); @@ -115,7 +141,6 @@ public class PhaserTest extends JSR166Te */ public void testRegister2() { Phaser phaser = new Phaser(0); - int maxParties = (1 << 16) - 1; assertState(phaser, 0, 0, 0); assertEquals(0, phaser.bulkRegister(maxParties - 10)); assertState(phaser, 0, maxParties - 10, maxParties - 10); @@ -128,6 +153,14 @@ public class PhaserTest extends JSR166Te phaser.register(); shouldThrow(); } catch (IllegalStateException success) {} + + try { + phaser.bulkRegister(Integer.MAX_VALUE); + shouldThrow(); + } catch (IllegalStateException success) {} + + assertEquals(0, phaser.bulkRegister(0)); + assertState(phaser, 0, maxParties, maxParties); } /** @@ -171,6 +204,8 @@ public class PhaserTest extends JSR166Te */ public void testBulkRegister2() { Phaser phaser = new Phaser(); + assertEquals(0, phaser.bulkRegister(0)); + assertState(phaser, 0, 0, 0); assertEquals(0, phaser.bulkRegister(20)); assertState(phaser, 0, 20, 20); } @@ -229,7 +264,7 @@ public class PhaserTest extends JSR166Te assertState(phaser, 0, 1, 1); } assertEquals(0, phaser.arriveAndDeregister()); - assertTerminated(phaser); + assertTerminated(phaser, 1); } /** @@ -260,7 +295,8 @@ public class PhaserTest extends JSR166Te public void testArrive3() { Phaser phaser = new Phaser(1); phaser.forceTermination(); - assertTerminated(phaser, 1, 1); + assertTerminated(phaser, 0, 1); + assertEquals(0, phaser.getPhase() + Integer.MIN_VALUE); assertTrue(phaser.arrive() < 0); assertTrue(phaser.register() < 0); assertTrue(phaser.arriveAndDeregister() < 0); @@ -301,13 +337,13 @@ public class PhaserTest extends JSR166Te Phaser parent = new Phaser(); Phaser child = new Phaser(parent); assertState(child, 0, 0, 0); - assertState(parent, 0, 1, 1); + assertState(parent, 0, 0, 0); assertEquals(0, child.register()); assertState(child, 0, 1, 1); assertState(parent, 0, 1, 1); assertEquals(0, child.arriveAndDeregister()); - assertTerminated(child); - assertTerminated(parent); + assertTerminated(child, 1); + assertTerminated(parent, 1); } /** @@ -334,17 +370,17 @@ public class PhaserTest extends JSR166Te Phaser root = new Phaser(); Phaser parent = new Phaser(root); Phaser child = new Phaser(parent); - assertState(root, 0, 1, 1); - assertState(parent, 0, 1, 1); + assertState(root, 0, 0, 0); + assertState(parent, 0, 0, 0); assertState(child, 0, 0, 0); assertEquals(0, child.register()); assertState(root, 0, 1, 1); assertState(parent, 0, 1, 1); assertState(child, 0, 1, 1); assertEquals(0, child.arriveAndDeregister()); - assertTerminated(child); - assertTerminated(parent); - assertTerminated(root); + assertTerminated(child, 1); + assertTerminated(parent, 1); + assertTerminated(root, 1); } /** @@ -362,7 +398,7 @@ public class PhaserTest extends JSR166Te assertEquals(1, phaser.arriveAndDeregister()); assertState(phaser, 1, 1, 1); assertEquals(1, phaser.arriveAndDeregister()); - assertTerminated(phaser); + assertTerminated(phaser, 2); awaitTermination(t, SHORT_DELAY_MS); } @@ -386,24 +422,115 @@ public class PhaserTest extends JSR166Te } /** - * awaitAdvance continues waiting if interrupted + * awaitAdvance continues waiting if interrupted before waiting */ - public void testAwaitAdvance3() throws InterruptedException { + public void testAwaitAdvanceAfterInterrupt() throws InterruptedException { final Phaser phaser = new Phaser(); assertEquals(0, phaser.register()); final CountDownLatch threadStarted = new CountDownLatch(1); Thread t = newStartedThread(new CheckedRunnable() { public void realRun() throws InterruptedException { + Thread.currentThread().interrupt(); assertEquals(0, phaser.register()); + assertEquals(0, phaser.arrive()); threadStarted.countDown(); - assertEquals(1, phaser.awaitAdvance(phaser.arrive())); + assertTrue(Thread.currentThread().isInterrupted()); + assertEquals(1, phaser.awaitAdvance(0)); assertTrue(Thread.currentThread().isInterrupted()); }}); + assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS)); + waitForThreadToEnterWaitState(t, SMALL_DELAY_MS); + assertEquals(0, phaser.arrive()); + awaitTermination(t, SMALL_DELAY_MS); + + Thread.currentThread().interrupt(); + assertEquals(1, phaser.awaitAdvance(0)); + assertTrue(Thread.interrupted()); + } + + /** + * awaitAdvance continues waiting if interrupted while waiting + */ + public void testAwaitAdvanceBeforeInterrupt() throws InterruptedException { + final Phaser phaser = new Phaser(); + assertEquals(0, phaser.register()); + final CountDownLatch threadStarted = new CountDownLatch(1); + + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + assertEquals(0, phaser.register()); + assertEquals(0, phaser.arrive()); + threadStarted.countDown(); + assertFalse(Thread.currentThread().isInterrupted()); + assertEquals(1, phaser.awaitAdvance(0)); + assertTrue(Thread.currentThread().isInterrupted()); + }}); + + assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS)); + waitForThreadToEnterWaitState(t, SMALL_DELAY_MS); t.interrupt(); assertEquals(0, phaser.arrive()); awaitTermination(t, SMALL_DELAY_MS); + + Thread.currentThread().interrupt(); + assertEquals(1, phaser.awaitAdvance(0)); + assertTrue(Thread.interrupted()); + } + + /** + * arriveAndAwaitAdvance continues waiting if interrupted before waiting + */ + public void testArriveAndAwaitAdvanceAfterInterrupt() + throws InterruptedException { + final Phaser phaser = new Phaser(); + assertEquals(0, phaser.register()); + final CountDownLatch threadStarted = new CountDownLatch(1); + + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + Thread.currentThread().interrupt(); + assertEquals(0, phaser.register()); + threadStarted.countDown(); + assertTrue(Thread.currentThread().isInterrupted()); + assertEquals(1, phaser.arriveAndAwaitAdvance()); + assertTrue(Thread.currentThread().isInterrupted()); + }}); + + assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS)); + waitForThreadToEnterWaitState(t, SMALL_DELAY_MS); + Thread.currentThread().interrupt(); + assertEquals(1, phaser.arriveAndAwaitAdvance()); + assertTrue(Thread.interrupted()); + awaitTermination(t, SMALL_DELAY_MS); + } + + /** + * arriveAndAwaitAdvance continues waiting if interrupted while waiting + */ + public void testArriveAndAwaitAdvanceBeforeInterrupt() + throws InterruptedException { + final Phaser phaser = new Phaser(); + assertEquals(0, phaser.register()); + final CountDownLatch threadStarted = new CountDownLatch(1); + + Thread t = newStartedThread(new CheckedRunnable() { + public void realRun() throws InterruptedException { + assertEquals(0, phaser.register()); + threadStarted.countDown(); + assertFalse(Thread.currentThread().isInterrupted()); + assertEquals(1, phaser.arriveAndAwaitAdvance()); + assertTrue(Thread.currentThread().isInterrupted()); + }}); + + assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS)); + waitForThreadToEnterWaitState(t, SMALL_DELAY_MS); + t.interrupt(); + Thread.currentThread().interrupt(); + assertEquals(1, phaser.arriveAndAwaitAdvance()); + assertTrue(Thread.interrupted()); + awaitTermination(t, SMALL_DELAY_MS); } /** @@ -461,6 +588,53 @@ public class PhaserTest extends JSR166Te } /** + * awaitAdvance returns the current phase in child phasers + */ + public void testAwaitAdvanceTieredPhaser() throws Exception { + final Phaser parent = new Phaser(); + final List zeroPartyChildren = new ArrayList(3); + final List onePartyChildren = new ArrayList(3); + for (int i = 0; i < 3; i++) { + zeroPartyChildren.add(new Phaser(parent, 0)); + onePartyChildren.add(new Phaser(parent, 1)); + } + final List phasers = new ArrayList(); + phasers.addAll(zeroPartyChildren); + phasers.addAll(onePartyChildren); + phasers.add(parent); + for (Phaser phaser : phasers) { + assertEquals(-42, phaser.awaitAdvance(-42)); + assertEquals(-42, phaser.awaitAdvanceInterruptibly(-42)); + assertEquals(-42, phaser.awaitAdvanceInterruptibly(-42, SMALL_DELAY_MS, MILLISECONDS)); + } + + for (Phaser child : onePartyChildren) + assertEquals(0, child.arrive()); + for (Phaser phaser : phasers) { + assertEquals(-42, phaser.awaitAdvance(-42)); + assertEquals(-42, phaser.awaitAdvanceInterruptibly(-42)); + assertEquals(-42, phaser.awaitAdvanceInterruptibly(-42, SMALL_DELAY_MS, MILLISECONDS)); + assertEquals(1, phaser.awaitAdvance(0)); + assertEquals(1, phaser.awaitAdvanceInterruptibly(0)); + assertEquals(1, phaser.awaitAdvanceInterruptibly(0, SMALL_DELAY_MS, MILLISECONDS)); + } + + for (Phaser child : onePartyChildren) + assertEquals(1, child.arrive()); + for (Phaser phaser : phasers) { + assertEquals(-42, phaser.awaitAdvance(-42)); + assertEquals(-42, phaser.awaitAdvanceInterruptibly(-42)); + assertEquals(-42, phaser.awaitAdvanceInterruptibly(-42, SMALL_DELAY_MS, MILLISECONDS)); + assertEquals(2, phaser.awaitAdvance(0)); + assertEquals(2, phaser.awaitAdvanceInterruptibly(0)); + assertEquals(2, phaser.awaitAdvanceInterruptibly(0, SMALL_DELAY_MS, MILLISECONDS)); + assertEquals(2, phaser.awaitAdvance(1)); + assertEquals(2, phaser.awaitAdvanceInterruptibly(1)); + assertEquals(2, phaser.awaitAdvanceInterruptibly(1, SMALL_DELAY_MS, MILLISECONDS)); + } + } + + /** * awaitAdvance returns when the phaser is externally terminated */ public void testAwaitAdvance6() throws InterruptedException { @@ -475,16 +649,17 @@ public class PhaserTest extends JSR166Te assertTrue(phaser.awaitAdvance(0) < 0); assertTrue(phaser.isTerminated()); assertTrue(phaser.getPhase() < 0); + assertEquals(0, phaser.getPhase() + Integer.MIN_VALUE); assertEquals(3, phaser.getRegisteredParties()); }}; threads.add(newStartedThread(r)); } threadsStarted.await(); phaser.forceTermination(); + assertTrue(phaser.isTerminated()); + assertEquals(0, phaser.getPhase() + Integer.MIN_VALUE); for (Thread thread : threads) awaitTermination(thread, SMALL_DELAY_MS); - assertTrue(phaser.isTerminated()); - assertTrue(phaser.getPhase() < 0); assertEquals(3, phaser.getRegisteredParties()); } @@ -501,35 +676,6 @@ public class PhaserTest extends JSR166Te } /** - * Interrupted arriveAndAwaitAdvance does not throw InterruptedException - */ - public void testArriveAndAwaitAdvance2() throws InterruptedException { - final Phaser phaser = new Phaser(2); - final CountDownLatch threadStarted = new CountDownLatch(1); - final AtomicBoolean advanced = new AtomicBoolean(false); - final AtomicBoolean checkedInterruptStatus = new AtomicBoolean(false); - Thread t = newStartedThread(new CheckedRunnable() { - public void realRun() throws InterruptedException { - threadStarted.countDown(); - assertEquals(1, phaser.arriveAndAwaitAdvance()); - assertState(phaser, 1, 2, 2); - advanced.set(true); - assertTrue(Thread.currentThread().isInterrupted()); - while (!checkedInterruptStatus.get()) - Thread.yield(); - }}); - - assertTrue(threadStarted.await(SMALL_DELAY_MS, MILLISECONDS)); - t.interrupt(); - assertEquals(0, phaser.arrive()); - while (!advanced.get()) - Thread.yield(); - assertTrue(t.isInterrupted()); - checkedInterruptStatus.set(true); - awaitTermination(t, SMALL_DELAY_MS); - } - - /** * arriveAndAwaitAdvance waits for all threads to arrive, the * number of arrived parties is the same number that is accounted * for when the main thread awaitsAdvance