Added jsr166 tck tests as part of the libcore testsuite.

Change-Id: I6094d734f818fa043f2b277cf2b4ec7fec68e26e
diff --git a/jsr166-tests/src/test/java/jsr166/PhaserTest.java b/jsr166-tests/src/test/java/jsr166/PhaserTest.java
new file mode 100644
index 0000000..3889c1f
--- /dev/null
+++ b/jsr166-tests/src/test/java/jsr166/PhaserTest.java
@@ -0,0 +1,786 @@
+/*
+ * 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/publicdomain/zero/1.0/
+ * Other contributors include John Vint
+ */
+
+package jsr166;
+
+import junit.framework.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Phaser;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeoutException;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class PhaserTest extends JSR166TestCase {
+
+    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());
+        assertFalse(phaser.isTerminated());
+    }
+
+    /** Checks state of terminated phaser. */
+    protected void assertTerminated(Phaser phaser, int maxPhase, int parties) {
+        assertTrue(phaser.isTerminated());
+        int expectedPhase = maxPhase + Integer.MIN_VALUE;
+        assertEquals(expectedPhase, phaser.getPhase());
+        assertEquals(parties, phaser.getRegisteredParties());
+        assertEquals(expectedPhase, phaser.register());
+        assertEquals(expectedPhase, phaser.arrive());
+        assertEquals(expectedPhase, phaser.arriveAndDeregister());
+    }
+
+    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 testConstructorDefaultValues() {
+        Phaser phaser = new Phaser();
+        assertNull(phaser.getParent());
+        assertEquals(0, phaser.getRegisteredParties());
+        assertEquals(0, phaser.getArrivedParties());
+        assertEquals(0, phaser.getUnarrivedParties());
+        assertEquals(0, phaser.getPhase());
+    }
+
+    /**
+     * Constructing with a negative number of parties throws
+     * IllegalArgumentException
+     */
+    public void testConstructorNegativeParties() {
+        try {
+            new Phaser(-1);
+            shouldThrow();
+        } catch (IllegalArgumentException success) {}
+    }
+
+    /**
+     * Constructing with a negative number of parties throws
+     * IllegalArgumentException
+     */
+    public void testConstructorNegativeParties2() {
+        try {
+            new Phaser(new Phaser(), -1);
+            shouldThrow();
+        } catch (IllegalArgumentException success) {}
+    }
+
+    /**
+     * Constructing with a number of parties > 65535 throws
+     * IllegalArgumentException
+     */
+    public void testConstructorPartiesExceedsLimit() {
+        new Phaser(maxParties);
+        try {
+            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());
+    }
+
+    /**
+     * The parent being input into the parameter should equal the original
+     * parent when being returned
+     */
+    public void testConstructor5() {
+        Phaser parent = new Phaser();
+        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
+     */
+    public void testRegister1() {
+        Phaser phaser = new Phaser();
+        assertState(phaser, 0, 0, 0);
+        assertEquals(0, phaser.register());
+        assertState(phaser, 0, 1, 1);
+    }
+
+    /**
+     * Registering more than 65536 parties causes IllegalStateException
+     */
+    public void testRegister2() {
+        Phaser phaser = new Phaser(0);
+        assertState(phaser, 0, 0, 0);
+        assertEquals(0, phaser.bulkRegister(maxParties - 10));
+        assertState(phaser, 0, maxParties - 10, maxParties - 10);
+        for (int i = 0; i < 10; i++) {
+            assertState(phaser, 0, maxParties - 10 + i, maxParties - 10 + i);
+            assertEquals(0, phaser.register());
+        }
+        assertState(phaser, 0, maxParties, maxParties);
+        try {
+            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);
+    }
+
+    /**
+     * register() correctly returns the current barrier phase number
+     * when invoked
+     */
+    public void testRegister3() {
+        Phaser phaser = new Phaser();
+        assertEquals(0, phaser.register());
+        assertEquals(0, phaser.arrive());
+        assertEquals(1, phaser.register());
+        assertState(phaser, 1, 2, 2);
+    }
+
+    /**
+     * register causes the next arrive to not increment the phase
+     * rather retain the phase number
+     */
+    public void testRegister4() {
+        Phaser phaser = new Phaser(1);
+        assertEquals(0, phaser.arrive());
+        assertEquals(1, phaser.register());
+        assertEquals(1, phaser.arrive());
+        assertState(phaser, 1, 2, 1);
+    }
+
+    /**
+     * register on a subphaser that is currently empty succeeds, even
+     * in the presence of another non-empty subphaser
+     */
+    public void testRegisterEmptySubPhaser() {
+        Phaser root = new Phaser();
+        Phaser child1 = new Phaser(root, 1);
+        Phaser child2 = new Phaser(root, 0);
+        assertEquals(0, child2.register());
+        assertState(root, 0, 2, 2);
+        assertState(child1, 0, 1, 1);
+        assertState(child2, 0, 1, 1);
+        assertEquals(0, child2.arriveAndDeregister());
+        assertState(root, 0, 1, 1);
+        assertState(child1, 0, 1, 1);
+        assertState(child2, 0, 0, 0);
+        assertEquals(0, child2.register());
+        assertEquals(0, child2.arriveAndDeregister());
+        assertState(root, 0, 1, 1);
+        assertState(child1, 0, 1, 1);
+        assertState(child2, 0, 0, 0);
+        assertEquals(0, child1.arriveAndDeregister());
+        assertTerminated(root, 1);
+        assertTerminated(child1, 1);
+        assertTerminated(child2, 1);
+    }
+
+    /**
+     * Invoking bulkRegister with a negative parameter throws an
+     * IllegalArgumentException
+     */
+    public void testBulkRegister1() {
+        try {
+            new Phaser().bulkRegister(-1);
+            shouldThrow();
+        } catch (IllegalArgumentException success) {}
+    }
+
+    /**
+     * bulkRegister should correctly record the number of unarrived
+     * parties with the number of parties being registered
+     */
+    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);
+    }
+
+    /**
+     * Registering with a number of parties greater than or equal to 1<<16
+     * throws IllegalStateException.
+     */
+    public void testBulkRegister3() {
+        assertEquals(0, new Phaser().bulkRegister((1 << 16) - 1));
+
+        try {
+            new Phaser().bulkRegister(1 << 16);
+            shouldThrow();
+        } catch (IllegalStateException success) {}
+
+        try {
+            new Phaser(2).bulkRegister((1 << 16) - 2);
+            shouldThrow();
+        } catch (IllegalStateException success) {}
+    }
+
+    /**
+     * the phase number increments correctly when tripping the barrier
+     */
+    public void testPhaseIncrement1() {
+        for (int size = 1; size < nine; size++) {
+            final Phaser phaser = new Phaser(size);
+            for (int index = 0; index <= (1 << size); index++) {
+                int phase = phaser.arrive();
+                assertTrue(index % size == 0 ? (index / size) == phase : index - (phase * size) > 0);
+            }
+        }
+    }
+
+    /**
+     * arrive() on a registered phaser increments phase.
+     */
+    public void testArrive1() {
+        Phaser phaser = new Phaser(1);
+        assertState(phaser, 0, 1, 1);
+        assertEquals(0, phaser.arrive());
+        assertState(phaser, 1, 1, 1);
+    }
+
+    /**
+     * arriveAndDeregister does not wait for others to arrive at barrier
+     */
+    public void testArriveAndDeregister() {
+        final Phaser phaser = new Phaser(1);
+        for (int i = 0; i < 10; i++) {
+            assertState(phaser, 0, 1, 1);
+            assertEquals(0, phaser.register());
+            assertState(phaser, 0, 2, 2);
+            assertEquals(0, phaser.arriveAndDeregister());
+            assertState(phaser, 0, 1, 1);
+        }
+        assertEquals(0, phaser.arriveAndDeregister());
+        assertTerminated(phaser, 1);
+    }
+
+    /**
+     * arriveAndDeregister does not wait for others to arrive at barrier
+     */
+    public void testArrive2() {
+        final Phaser phaser = new Phaser();
+        assertEquals(0, phaser.register());
+        List<Thread> threads = new ArrayList<Thread>();
+        for (int i = 0; i < 10; i++) {
+            assertEquals(0, phaser.register());
+            threads.add(newStartedThread(new CheckedRunnable() {
+                public void realRun() {
+                    assertEquals(0, phaser.arriveAndDeregister());
+                }}));
+        }
+
+        for (Thread thread : threads)
+            awaitTermination(thread);
+        assertState(phaser, 0, 1, 1);
+        assertEquals(0, phaser.arrive());
+        assertState(phaser, 1, 1, 1);
+    }
+
+    /**
+     * arrive() returns a negative number if the Phaser is terminated
+     */
+    public void testArrive3() {
+        Phaser phaser = new Phaser(1);
+        phaser.forceTermination();
+        assertTerminated(phaser, 0, 1);
+        assertEquals(0, phaser.getPhase() + Integer.MIN_VALUE);
+        assertTrue(phaser.arrive() < 0);
+        assertTrue(phaser.register() < 0);
+        assertTrue(phaser.arriveAndDeregister() < 0);
+        assertTrue(phaser.awaitAdvance(1) < 0);
+        assertTrue(phaser.getPhase() < 0);
+    }
+
+    /**
+     * arriveAndDeregister() throws IllegalStateException if number of
+     * registered or unarrived parties would become negative
+     */
+    public void testArriveAndDeregister1() {
+        try {
+            Phaser phaser = new Phaser();
+            phaser.arriveAndDeregister();
+            shouldThrow();
+        } catch (IllegalStateException success) {}
+    }
+
+    /**
+     * arriveAndDeregister reduces the number of arrived parties
+     */
+    public void testArriveAndDeregister2() {
+        final Phaser phaser = new Phaser(1);
+        assertEquals(0, phaser.register());
+        assertEquals(0, phaser.arrive());
+        assertState(phaser, 0, 2, 1);
+        assertEquals(0, phaser.arriveAndDeregister());
+        assertState(phaser, 1, 1, 1);
+    }
+
+    /**
+     * arriveAndDeregister arrives at the barrier on a phaser with a parent and
+     * when a deregistration occurs and causes the phaser to have zero parties
+     * its parent will be deregistered as well
+     */
+    public void testArriveAndDeregister3() {
+        Phaser parent = new Phaser();
+        Phaser child = new Phaser(parent);
+        assertState(child, 0, 0, 0);
+        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, 1);
+        assertTerminated(parent, 1);
+    }
+
+    /**
+     * arriveAndDeregister deregisters one party from its parent when
+     * the number of parties of child is zero after deregistration
+     */
+    public void testArriveAndDeregister4() {
+        Phaser parent = new Phaser();
+        Phaser child = new Phaser(parent);
+        assertEquals(0, parent.register());
+        assertEquals(0, child.register());
+        assertState(child, 0, 1, 1);
+        assertState(parent, 0, 2, 2);
+        assertEquals(0, child.arriveAndDeregister());
+        assertState(child, 0, 0, 0);
+        assertState(parent, 0, 1, 1);
+    }
+
+    /**
+     * arriveAndDeregister deregisters one party from its parent when
+     * the number of parties of root is nonzero after deregistration.
+     */
+    public void testArriveAndDeregister5() {
+        Phaser root = new Phaser();
+        Phaser parent = new Phaser(root);
+        Phaser child = new Phaser(parent);
+        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, 1);
+        assertTerminated(parent, 1);
+        assertTerminated(root, 1);
+    }
+
+    /**
+     * arriveAndDeregister returns the phase in which it leaves the
+     * phaser in after deregistration
+     */
+    public void testArriveAndDeregister6() {
+        final Phaser phaser = new Phaser(2);
+        Thread t = newStartedThread(new CheckedRunnable() {
+            public void realRun() {
+                assertEquals(0, phaser.arrive());
+            }});
+        assertEquals(1, phaser.arriveAndAwaitAdvance());
+        assertState(phaser, 1, 2, 2);
+        assertEquals(1, phaser.arriveAndDeregister());
+        assertState(phaser, 1, 1, 1);
+        assertEquals(1, phaser.arriveAndDeregister());
+        assertTerminated(phaser, 2);
+        awaitTermination(t);
+    }
+
+    /**
+     * awaitAdvance succeeds upon advance
+     */
+    public void testAwaitAdvance1() {
+        final Phaser phaser = new Phaser(1);
+        assertEquals(0, phaser.arrive());
+        assertEquals(1, phaser.awaitAdvance(0));
+    }
+
+    /**
+     * awaitAdvance with a negative parameter will return without affecting the
+     * phaser
+     */
+    public void testAwaitAdvance2() {
+        Phaser phaser = new Phaser();
+        assertTrue(phaser.awaitAdvance(-1) < 0);
+        assertState(phaser, 0, 0, 0);
+    }
+
+    /**
+     * awaitAdvanceInterruptibly blocks interruptibly
+     */
+    public void testAwaitAdvanceInterruptibly_interruptible() throws InterruptedException {
+        final Phaser phaser = new Phaser(1);
+        final CountDownLatch pleaseInterrupt = new CountDownLatch(2);
+
+        Thread t1 = newStartedThread(new CheckedRunnable() {
+            public void realRun() {
+                Thread.currentThread().interrupt();
+                try {
+                    phaser.awaitAdvanceInterruptibly(0);
+                    shouldThrow();
+                } catch (InterruptedException success) {}
+                assertFalse(Thread.interrupted());
+
+                pleaseInterrupt.countDown();
+                try {
+                    phaser.awaitAdvanceInterruptibly(0);
+                    shouldThrow();
+                } catch (InterruptedException success) {}
+                assertFalse(Thread.interrupted());
+            }});
+
+        Thread t2 = newStartedThread(new CheckedRunnable() {
+            public void realRun() throws TimeoutException {
+                Thread.currentThread().interrupt();
+                try {
+                    phaser.awaitAdvanceInterruptibly(0, 2*LONG_DELAY_MS, MILLISECONDS);
+                    shouldThrow();
+                } catch (InterruptedException success) {}
+                assertFalse(Thread.interrupted());
+
+                pleaseInterrupt.countDown();
+                try {
+                    phaser.awaitAdvanceInterruptibly(0, 2*LONG_DELAY_MS, MILLISECONDS);
+                    shouldThrow();
+                } catch (InterruptedException success) {}
+                assertFalse(Thread.interrupted());
+            }});
+
+        await(pleaseInterrupt);
+        assertState(phaser, 0, 1, 1);
+        assertThreadsStayAlive(t1, t2);
+        t1.interrupt();
+        t2.interrupt();
+        awaitTermination(t1);
+        awaitTermination(t2);
+        assertState(phaser, 0, 1, 1);
+        assertEquals(0, phaser.arrive());
+        assertState(phaser, 1, 1, 1);
+    }
+
+    /**
+     * awaitAdvance continues waiting if interrupted before waiting
+     */
+    public void testAwaitAdvanceAfterInterrupt() {
+        final Phaser phaser = new Phaser();
+        assertEquals(0, phaser.register());
+        final CountDownLatch pleaseArrive = new CountDownLatch(1);
+
+        Thread t = newStartedThread(new CheckedRunnable() {
+            public void realRun() {
+                Thread.currentThread().interrupt();
+                assertEquals(0, phaser.register());
+                assertEquals(0, phaser.arrive());
+                pleaseArrive.countDown();
+                assertTrue(Thread.currentThread().isInterrupted());
+                assertEquals(1, phaser.awaitAdvance(0));
+                assertTrue(Thread.interrupted());
+            }});
+
+        await(pleaseArrive);
+        waitForThreadToEnterWaitState(t, SHORT_DELAY_MS);
+        assertEquals(0, phaser.arrive());
+        awaitTermination(t);
+
+        Thread.currentThread().interrupt();
+        assertEquals(1, phaser.awaitAdvance(0));
+        assertTrue(Thread.interrupted());
+    }
+
+    /**
+     *  awaitAdvance continues waiting if interrupted while waiting
+     */
+    public void testAwaitAdvanceBeforeInterrupt() {
+        final Phaser phaser = new Phaser();
+        assertEquals(0, phaser.register());
+        final CountDownLatch pleaseArrive = new CountDownLatch(1);
+
+        Thread t = newStartedThread(new CheckedRunnable() {
+            public void realRun() {
+                assertEquals(0, phaser.register());
+                assertEquals(0, phaser.arrive());
+                assertFalse(Thread.currentThread().isInterrupted());
+                pleaseArrive.countDown();
+                assertEquals(1, phaser.awaitAdvance(0));
+                assertTrue(Thread.interrupted());
+            }});
+
+        await(pleaseArrive);
+        waitForThreadToEnterWaitState(t, SHORT_DELAY_MS);
+        t.interrupt();
+        assertEquals(0, phaser.arrive());
+        awaitTermination(t);
+
+        Thread.currentThread().interrupt();
+        assertEquals(1, phaser.awaitAdvance(0));
+        assertTrue(Thread.interrupted());
+    }
+
+    /**
+     * arriveAndAwaitAdvance continues waiting if interrupted before waiting
+     */
+    public void testArriveAndAwaitAdvanceAfterInterrupt() {
+        final Phaser phaser = new Phaser();
+        assertEquals(0, phaser.register());
+        final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
+
+        Thread t = newStartedThread(new CheckedRunnable() {
+            public void realRun() {
+                Thread.currentThread().interrupt();
+                assertEquals(0, phaser.register());
+                pleaseInterrupt.countDown();
+                assertTrue(Thread.currentThread().isInterrupted());
+                assertEquals(1, phaser.arriveAndAwaitAdvance());
+                assertTrue(Thread.currentThread().isInterrupted());
+            }});
+
+        await(pleaseInterrupt);
+        waitForThreadToEnterWaitState(t, SHORT_DELAY_MS);
+        Thread.currentThread().interrupt();
+        assertEquals(1, phaser.arriveAndAwaitAdvance());
+        assertTrue(Thread.interrupted());
+        awaitTermination(t);
+    }
+
+    /**
+     * arriveAndAwaitAdvance continues waiting if interrupted while waiting
+     */
+    public void testArriveAndAwaitAdvanceBeforeInterrupt() {
+        final Phaser phaser = new Phaser();
+        assertEquals(0, phaser.register());
+        final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
+
+        Thread t = newStartedThread(new CheckedRunnable() {
+            public void realRun() {
+                assertEquals(0, phaser.register());
+                assertFalse(Thread.currentThread().isInterrupted());
+                pleaseInterrupt.countDown();
+                assertEquals(1, phaser.arriveAndAwaitAdvance());
+                assertTrue(Thread.currentThread().isInterrupted());
+            }});
+
+        await(pleaseInterrupt);
+        waitForThreadToEnterWaitState(t, SHORT_DELAY_MS);
+        t.interrupt();
+        Thread.currentThread().interrupt();
+        assertEquals(1, phaser.arriveAndAwaitAdvance());
+        assertTrue(Thread.interrupted());
+        awaitTermination(t);
+    }
+
+    /**
+     * awaitAdvance atomically waits for all parties within the same phase to
+     * complete before continuing
+     */
+    public void testAwaitAdvance4() {
+        final Phaser phaser = new Phaser(4);
+        final AtomicInteger count = new AtomicInteger(0);
+        List<Thread> threads = new ArrayList<Thread>();
+        for (int i = 0; i < 4; i++)
+            threads.add(newStartedThread(new CheckedRunnable() {
+                public void realRun() {
+                    for (int k = 0; k < 3; k++) {
+                        assertEquals(2*k+1, phaser.arriveAndAwaitAdvance());
+                        count.incrementAndGet();
+                        assertEquals(2*k+1, phaser.arrive());
+                        assertEquals(2*k+2, phaser.awaitAdvance(2*k+1));
+                        assertEquals(4*(k+1), count.get());
+                    }}}));
+
+        for (Thread thread : threads)
+            awaitTermination(thread);
+    }
+
+    /**
+     * awaitAdvance returns the current phase
+     */
+    public void testAwaitAdvance5() {
+        final Phaser phaser = new Phaser(1);
+        assertEquals(1, phaser.awaitAdvance(phaser.arrive()));
+        assertEquals(1, phaser.getPhase());
+        assertEquals(1, phaser.register());
+        List<Thread> threads = new ArrayList<Thread>();
+        for (int i = 0; i < 8; i++) {
+            final CountDownLatch latch = new CountDownLatch(1);
+            final boolean goesFirst = ((i & 1) == 0);
+            threads.add(newStartedThread(new CheckedRunnable() {
+                public void realRun() {
+                    if (goesFirst)
+                        latch.countDown();
+                    else
+                        await(latch);
+                    phaser.arrive();
+                }}));
+            if (goesFirst)
+                await(latch);
+            else
+                latch.countDown();
+            assertEquals(i + 2, phaser.awaitAdvance(phaser.arrive()));
+            assertEquals(i + 2, phaser.getPhase());
+        }
+        for (Thread thread : threads)
+            awaitTermination(thread);
+    }
+
+    /**
+     * awaitAdvance returns the current phase in child phasers
+     */
+    public void testAwaitAdvanceTieredPhaser() throws Exception {
+        final Phaser parent = new Phaser();
+        final List<Phaser> zeroPartyChildren = new ArrayList<Phaser>(3);
+        final List<Phaser> onePartyChildren = new ArrayList<Phaser>(3);
+        for (int i = 0; i < 3; i++) {
+            zeroPartyChildren.add(new Phaser(parent, 0));
+            onePartyChildren.add(new Phaser(parent, 1));
+        }
+        final List<Phaser> phasers = new ArrayList<Phaser>();
+        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() {
+        final Phaser phaser = new Phaser(3);
+        final CountDownLatch pleaseForceTermination = new CountDownLatch(2);
+        final List<Thread> threads = new ArrayList<Thread>();
+        for (int i = 0; i < 2; i++) {
+            Runnable r = new CheckedRunnable() {
+                public void realRun() {
+                    assertEquals(0, phaser.arrive());
+                    pleaseForceTermination.countDown();
+                    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));
+        }
+        await(pleaseForceTermination);
+        phaser.forceTermination();
+        assertTrue(phaser.isTerminated());
+        assertEquals(0, phaser.getPhase() + Integer.MIN_VALUE);
+        for (Thread thread : threads)
+            awaitTermination(thread);
+        assertEquals(3, phaser.getRegisteredParties());
+    }
+
+    /**
+     * arriveAndAwaitAdvance throws IllegalStateException with no
+     * unarrived parties
+     */
+    public void testArriveAndAwaitAdvance1() {
+        try {
+            Phaser phaser = new Phaser();
+            phaser.arriveAndAwaitAdvance();
+            shouldThrow();
+        } catch (IllegalStateException success) {}
+    }
+
+    /**
+     * 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
+     */
+    public void testArriveAndAwaitAdvance3() {
+        final Phaser phaser = new Phaser(1);
+        final int THREADS = 3;
+        final CountDownLatch pleaseArrive = new CountDownLatch(THREADS);
+        final List<Thread> threads = new ArrayList<Thread>();
+        for (int i = 0; i < THREADS; i++)
+            threads.add(newStartedThread(new CheckedRunnable() {
+                public void realRun() {
+                    assertEquals(0, phaser.register());
+                    pleaseArrive.countDown();
+                    assertEquals(1, phaser.arriveAndAwaitAdvance());
+                }}));
+
+        await(pleaseArrive);
+        long startTime = System.nanoTime();
+        while (phaser.getArrivedParties() < THREADS)
+            Thread.yield();
+        assertEquals(THREADS, phaser.getArrivedParties());
+        assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS);
+        for (Thread thread : threads)
+            waitForThreadToEnterWaitState(thread, SHORT_DELAY_MS);
+        for (Thread thread : threads)
+            assertTrue(thread.isAlive());
+        assertState(phaser, 0, THREADS + 1, 1);
+        phaser.arriveAndAwaitAdvance();
+        for (Thread thread : threads)
+            awaitTermination(thread);
+        assertState(phaser, 1, THREADS + 1, THREADS + 1);
+    }
+
+}