/*
 * 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 Andrew Wright, Jeffrey Hayes,
 * Pat Fisher, Mike Judd.
 */

package jsr166;

import java.util.Arrays;
import java.util.concurrent.atomic.AtomicReferenceArray;

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

public class AtomicReferenceArrayTest 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(...);
    // }

    /**
     * constructor creates array of given size with all elements null
     */
    public void testConstructor() {
        AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<Integer>(SIZE);
        for (int i = 0; i < SIZE; i++) {
            assertNull(aa.get(i));
        }
    }

    /**
     * constructor with null array throws NPE
     */
    public void testConstructor2NPE() {
        try {
            Integer[] a = null;
            new AtomicReferenceArray<Integer>(a);
            shouldThrow();
        } catch (NullPointerException success) {}
    }

    /**
     * constructor with array is of same size and has all elements
     */
    public void testConstructor2() {
        Integer[] a = { two, one, three, four, seven };
        AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<Integer>(a);
        assertEquals(a.length, aa.length());
        for (int i = 0; i < a.length; i++)
            assertEquals(a[i], aa.get(i));
    }

    /**
     * Initialize AtomicReferenceArray<Class> with SubClass[]
     */
    public void testConstructorSubClassArray() {
        Integer[] a = { two, one, three, four, seven };
        AtomicReferenceArray<Number> aa = new AtomicReferenceArray<Number>(a);
        assertEquals(a.length, aa.length());
        for (int i = 0; i < a.length; i++) {
            assertSame(a[i], aa.get(i));
            Long x = Long.valueOf(i);
            aa.set(i, x);
            assertSame(x, aa.get(i));
        }
    }

    /**
     * get and set for out of bound indices throw IndexOutOfBoundsException
     */
    public void testIndexing() {
        AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<Integer>(SIZE);
        for (int index : new int[] { -1, SIZE }) {
            try {
                aa.get(index);
                shouldThrow();
            } catch (IndexOutOfBoundsException success) {}
            try {
                aa.set(index, null);
                shouldThrow();
            } catch (IndexOutOfBoundsException success) {}
            try {
                aa.lazySet(index, null);
                shouldThrow();
            } catch (IndexOutOfBoundsException success) {}
            try {
                aa.compareAndSet(index, null, null);
                shouldThrow();
            } catch (IndexOutOfBoundsException success) {}
            try {
                aa.weakCompareAndSet(index, null, null);
                shouldThrow();
            } catch (IndexOutOfBoundsException success) {}
        }
    }

    /**
     * get returns the last value set at index
     */
    public void testGetSet() {
        AtomicReferenceArray aa = new AtomicReferenceArray(SIZE);
        for (int i = 0; i < SIZE; i++) {
            aa.set(i, one);
            assertSame(one, aa.get(i));
            aa.set(i, two);
            assertSame(two, aa.get(i));
            aa.set(i, m3);
            assertSame(m3, aa.get(i));
        }
    }

    /**
     * get returns the last value lazySet at index by same thread
     */
    public void testGetLazySet() {
        AtomicReferenceArray aa = new AtomicReferenceArray(SIZE);
        for (int i = 0; i < SIZE; i++) {
            aa.lazySet(i, one);
            assertSame(one, aa.get(i));
            aa.lazySet(i, two);
            assertSame(two, aa.get(i));
            aa.lazySet(i, m3);
            assertSame(m3, aa.get(i));
        }
    }

    /**
     * compareAndSet succeeds in changing value if equal to expected else fails
     */
    public void testCompareAndSet() {
        AtomicReferenceArray aa = new AtomicReferenceArray(SIZE);
        for (int i = 0; i < SIZE; i++) {
            aa.set(i, one);
            assertTrue(aa.compareAndSet(i, one, two));
            assertTrue(aa.compareAndSet(i, two, m4));
            assertSame(m4, aa.get(i));
            assertFalse(aa.compareAndSet(i, m5, seven));
            assertSame(m4, aa.get(i));
            assertTrue(aa.compareAndSet(i, m4, seven));
            assertSame(seven, aa.get(i));
        }
    }

    /**
     * compareAndSet in one thread enables another waiting for value
     * to succeed
     */
    public void testCompareAndSetInMultipleThreads() throws InterruptedException {
        final AtomicReferenceArray a = new AtomicReferenceArray(1);
        a.set(0, one);
        Thread t = new Thread(new CheckedRunnable() {
            public void realRun() {
                while (!a.compareAndSet(0, two, three))
                    Thread.yield();
            }});

        t.start();
        assertTrue(a.compareAndSet(0, one, two));
        t.join(LONG_DELAY_MS);
        assertFalse(t.isAlive());
        assertSame(three, a.get(0));
    }

    /**
     * repeated weakCompareAndSet succeeds in changing value when equal
     * to expected
     */
    public void testWeakCompareAndSet() {
        AtomicReferenceArray aa = new AtomicReferenceArray(SIZE);
        for (int i = 0; i < SIZE; i++) {
            aa.set(i, one);
            do {} while (!aa.weakCompareAndSet(i, one, two));
            do {} while (!aa.weakCompareAndSet(i, two, m4));
            assertSame(m4, aa.get(i));
            do {} while (!aa.weakCompareAndSet(i, m4, seven));
            assertSame(seven, aa.get(i));
        }
    }

    /**
     * getAndSet returns previous value and sets to given value at given index
     */
    public void testGetAndSet() {
        AtomicReferenceArray aa = new AtomicReferenceArray(SIZE);
        for (int i = 0; i < SIZE; i++) {
            aa.set(i, one);
            assertSame(one, aa.getAndSet(i, zero));
            assertSame(zero, aa.getAndSet(i, m10));
            assertSame(m10, aa.getAndSet(i, one));
        }
    }

    /**
     * a deserialized serialized array holds same values
     */
    public void testSerialization() throws Exception {
        AtomicReferenceArray x = new AtomicReferenceArray(SIZE);
        for (int i = 0; i < SIZE; i++) {
            x.set(i, new Integer(-i));
        }
        AtomicReferenceArray y = serialClone(x);
        assertNotSame(x, y);
        assertEquals(x.length(), y.length());
        for (int i = 0; i < SIZE; i++) {
            assertEquals(x.get(i), y.get(i));
        }
    }

    /**
     * toString returns current value.
     */
    public void testToString() {
        Integer[] a = { two, one, three, four, seven };
        AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<Integer>(a);
        assertEquals(Arrays.toString(a), aa.toString());
    }
}
