/*
 * 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);
        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);
        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 pleaseArrive = new CountDownLatch(1);

        Thread t = newStartedThread(new CheckedRunnable() {
            public void realRun() {
                Thread.currentThread().interrupt();
                assertEquals(0, phaser.register());
                pleaseArrive.countDown();
                assertTrue(Thread.currentThread().isInterrupted());
                assertEquals(1, phaser.arriveAndAwaitAdvance());
                assertTrue(Thread.interrupted());
            }});

        await(pleaseArrive);
        waitForThreadToEnterWaitState(t);
        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.interrupted());
            }});

        await(pleaseInterrupt);
        waitForThreadToEnterWaitState(t);
        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);
        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);
    }

}
