/*
 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/*
 * @test
 * @bug 7121314
 * @summary AbstractCollection.toArray(T[]) doesn't return the given array
 *           in concurrent modification.
 * @author Ulf Zibis, David Holmes
 */

import java.util.AbstractCollection;
import java.util.Arrays;
import java.util.Iterator;

public class ToArrayTest {

    static class TestCollection<E> extends AbstractCollection<E> {
        private final E[] elements;
        private int[] sizes;
        private int nextSize;

        public TestCollection(E[] elements) {
            this.elements = elements;
            setSizeSequence(new int[] { elements.length });
        }

        /*
         * Sets the values that size() will return on each use. The next
         * call to size will return sizes[0], then sizes[1] etc. This allows us
         * to emulate a concurrent change to the contents of the collection
         * without having to perform concurrent changes. If sizes[n+1] contains
         * a larger value, the collection will appear to have shrunk when
         * iterated; if a smaller value then the collection will appear to have
         * grown when iterated.
         */
        void setSizeSequence(int... sizes) {
            this.sizes = sizes;
            nextSize = 0;
        }

        /* can change collection's size after each invocation */
        @Override
        public int size() {
            return sizes[nextSize == sizes.length - 1 ? nextSize : nextSize++];
        }

        @Override
        public Iterator<E> iterator() {
            return new Iterator<E>() {
                int pos = 0;

                public boolean hasNext() {
                    return pos < sizes[nextSize];
                }
                public E next() {
                    return elements[pos++];
                }
                public void remove() {
                    throw new UnsupportedOperationException(
                            "Not supported yet.");
                }
            };
        }
    }

    static final Object[] OBJECTS = { new Object(), new Object(), new Object() };
    static final TestCollection<?> CANDIDATE = new TestCollection<Object>(OBJECTS);
    static final int CAP = OBJECTS.length; // capacity of the CANDIDATE
    static final int LAST = CAP - 1; // last possible array index
    Object[] a;
    Object[] res;

    int last() {
        return a.length - 1;
    }

    protected void test() throws Throwable {
        // Check array type conversion
        res = new TestCollection<>(new Object[] { "1", "2" }).toArray(new String[0]);
        check(res instanceof String[]);
        check(res.length == 2);
        check(res[1] == "2");

        // Check incompatible type of target array
        try {
            res = CANDIDATE.toArray(new String[CAP]);
            check(false);
        } catch (Throwable t) {
            check(t instanceof ArrayStoreException);
        }

        // Check more elements than a.length
        a = new Object[CAP - 1]; // appears too small
        res = CANDIDATE.toArray(a);
        check(res != a);
        check(res[LAST] != null);

        // Check equal elements as a.length
        a = new Object[CAP]; // appears to match
        res = CANDIDATE.toArray(a);
        check(res == a);
        check(res[last()] != null);

        // Check equal elements as a.length
        a = new Object[CAP + 1]; // appears too big
        res = CANDIDATE.toArray(a);
        check(res == a);
        check(res[last()] == null);

        // Check less elements than expected, but more than a.length
        a = new Object[CAP - 2]; // appears too small
        CANDIDATE.setSizeSequence(CAP, CAP - 1);
        res = CANDIDATE.toArray(a);
        check(res != a);
        check(res.length == CAP - 1);
        check(res[LAST - 1] != null);

        // Check less elements than expected, but equal as a.length
        a = Arrays.copyOf(OBJECTS, CAP); // appears to match
        CANDIDATE.setSizeSequence(CAP, CAP - 1);
        res = CANDIDATE.toArray(a);
        check(res == a);
        check(res[last()] == null);

        // Check more elements than expected and more than a.length
        a = new Object[CAP - 1]; // appears to match
        CANDIDATE.setSizeSequence(CAP - 1, CAP);
        res = CANDIDATE.toArray(a);
        check(res != a);
        check(res[LAST] != null);

        // Check more elements than expected, but equal as a.length
        a = new Object[CAP - 1]; // appears to match
        CANDIDATE.setSizeSequence(CAP - 2, CAP - 1);
        res = CANDIDATE.toArray(a);
        check(res == a);
        check(res[last()] != null);

        // Check more elements than expected, but less than a.length
        a = Arrays.copyOf(OBJECTS, CAP); // appears to match
        CANDIDATE.setSizeSequence(CAP - 2, CAP - 1);
        res = CANDIDATE.toArray(a);
        check(res == a);
        check(res[last()] == null);

        test_7121314();
    }

    /*
     * Major target of this testcase, bug 7121314.
     */
    protected void test_7121314() throws Throwable {
        // Check equal elements as a.length, but less than expected
        a = new Object[CAP - 1]; // appears too small
        CANDIDATE.setSizeSequence(CAP, CAP - 1);
        res = CANDIDATE.toArray(a);
        check(res == a);
        check(res[last()] != null);

        // Check less elements than a.length and less than expected
        a = Arrays.copyOf(OBJECTS, CAP - 1); // appears too small
        CANDIDATE.setSizeSequence(CAP, CAP - 2);
        res = CANDIDATE.toArray(a);
        check(res == a);
        check(res[last()] == null);

    }

    public static void main(String[] args) throws Throwable {
        ToArrayTest testcase = new ToArrayTest();
        try {
            testcase.test();
        } catch (Throwable t) {
            unexpected(t);
        }

        System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
        if (failed > 0) throw new Exception("Some tests failed");
    }

    //--------------------- Infrastructure ---------------------------
    static volatile int passed = 0, failed = 0;
    static void pass() { passed++; }
    static void fail() { failed++; Thread.dumpStack(); }
    static void fail(String msg) { System.out.println(msg); fail(); }
    static void unexpected(Throwable t) { failed++; t.printStackTrace(); }
    static void check(boolean cond) { if (cond) pass(); else fail(); }
    static void equal(Object x, Object y) {
        if (x == null ? y == null : x.equals(y)) pass();
        else {System.out.println(x + " not equal to " + y); fail(); }
    }
}


