/*
 * 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 static java.util.concurrent.TimeUnit.MILLISECONDS;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Phaser;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;

import junit.framework.Test;
import junit.framework.TestSuite;

public class PhaserTest extends JSR166TestCase {

    // android-note: Removed because the CTS runner does a bad job of
    // retrying tests that have suite() declarations.
    //
    // public static void main(String[] args) {
    //     main(suite(), args);
    // }
    // public static Test suite() {
    //     return new TestSuite(PhaserTest.class);
    // }

    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() {
        Phaser phaser = new Phaser();
        try {
            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, MEDIUM_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, MEDIUM_DELAY_MS, MILLISECONDS));
            assertEquals(1, phaser.awaitAdvance(0));
            assertEquals(1, phaser.awaitAdvanceInterruptibly(0));
            assertEquals(1, phaser.awaitAdvanceInterruptibly(0, MEDIUM_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, MEDIUM_DELAY_MS, MILLISECONDS));
            assertEquals(2, phaser.awaitAdvance(0));
            assertEquals(2, phaser.awaitAdvanceInterruptibly(0));
            assertEquals(2, phaser.awaitAdvanceInterruptibly(0, MEDIUM_DELAY_MS, MILLISECONDS));
            assertEquals(2, phaser.awaitAdvance(1));
            assertEquals(2, phaser.awaitAdvanceInterruptibly(1));
            assertEquals(2, phaser.awaitAdvanceInterruptibly(1, MEDIUM_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() {
        Phaser phaser = new Phaser();
        try {
            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);
    }

}
