/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package org.apache.harmony.tests.java.util;

import libcore.java.util.ForEachRemainingTester;
import libcore.java.util.SpliteratorTester;
import tests.support.Support_ListTest;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Spliterator;
import java.util.Vector;

import static libcore.java.util.RemoveIfTester.*;

public class VectorTest extends junit.framework.TestCase {

    private Vector tVector = new Vector();

    Object[] objArray;

    private String vString = "[Test 0, Test 1, Test 2, Test 3, Test 4, Test 5, Test 6, Test 7, Test 8, Test 9, Test 10, Test 11, Test 12, Test 13, Test 14, Test 15, Test 16, Test 17, Test 18, Test 19, Test 20, Test 21, Test 22, Test 23, Test 24, Test 25, Test 26, Test 27, Test 28, Test 29, Test 30, Test 31, Test 32, Test 33, Test 34, Test 35, Test 36, Test 37, Test 38, Test 39, Test 40, Test 41, Test 42, Test 43, Test 44, Test 45, Test 46, Test 47, Test 48, Test 49, Test 50, Test 51, Test 52, Test 53, Test 54, Test 55, Test 56, Test 57, Test 58, Test 59, Test 60, Test 61, Test 62, Test 63, Test 64, Test 65, Test 66, Test 67, Test 68, Test 69, Test 70, Test 71, Test 72, Test 73, Test 74, Test 75, Test 76, Test 77, Test 78, Test 79, Test 80, Test 81, Test 82, Test 83, Test 84, Test 85, Test 86, Test 87, Test 88, Test 89, Test 90, Test 91, Test 92, Test 93, Test 94, Test 95, Test 96, Test 97, Test 98, Test 99]";

    /**
     * java.util.Vector#Vector()
     */
    public void test_Constructor() {
        // Test for method java.util.Vector()

        Vector tv = new Vector(100);
        for (int i = 0; i < 100; i++)
            tv.addElement(new Integer(i));
        new Support_ListTest("", tv).runTest();

        tv = new Vector(200);
        for (int i = -50; i < 150; i++)
            tv.addElement(new Integer(i));
        new Support_ListTest("", tv.subList(50, 150)).runTest();

        Vector v = new Vector();
        assertEquals("Vector creation failed", 0, v.size());
        assertEquals("Wrong capacity", 10, v.capacity());
    }

    /**
     * java.util.Vector#Vector(int)
     */
    public void test_ConstructorI() {
        // Test for method java.util.Vector(int)

        Vector v = new Vector(100);
        assertEquals("Vector creation failed", 0, v.size());
        assertEquals("Wrong capacity", 100, v.capacity());

        try {
            new Vector(-1);
            fail("IllegalArgumentException expected");
        } catch (IllegalArgumentException e) {
            //expected
        }
    }

    /**
     * java.util.Vector#Vector(int, int)
     */
    public void test_ConstructorII() {
        // Test for method java.util.Vector(int, int)

        Vector v = new Vector(2, 10);
        v.addElement(new Object());
        v.addElement(new Object());
        v.addElement(new Object());

        assertEquals("Failed to inc capacity by proper amount",
                12, v.capacity());

        Vector grow = new Vector(3, -1);
        grow.addElement("one");
        grow.addElement("two");
        grow.addElement("three");
        grow.addElement("four");
        assertEquals("Wrong size", 4, grow.size());
        assertEquals("Wrong capacity", 6, grow.capacity());

        Vector emptyVector = new Vector(0, 0);
        emptyVector.addElement("one");
        assertEquals("Wrong size", 1, emptyVector.size());
        emptyVector.addElement("two");
        emptyVector.addElement("three");
        assertEquals("Wrong size", 3, emptyVector.size());

        try {
            Vector negativeVector = new Vector(-1, 0);
            fail("Should throw IllegalArgumentException");
        } catch (IllegalArgumentException e) {
            // Excepted
        }
    }

    /**
     * java.util.Vector#Vector(java.util.Collection)
     */
    public void test_ConstructorLjava_util_Collection() {
        // Test for method java.util.Vector(java.util.Collection)
        Collection l = new LinkedList();
        for (int i = 0; i < 100; i++)
            l.add("Test " + i);
        Vector myVector = new Vector(l);
        assertTrue("Vector is not correct size",
                myVector.size() == objArray.length);
        for (int counter = 0; counter < objArray.length; counter++)
            assertTrue("Vector does not contain correct elements", myVector
                    .contains(((List) l).get(counter)));

        try {
            new Vector(null);
            fail("NullPointerException expected");
        } catch (NullPointerException e) {
            //expected
        }
    }

    /**
     * java.util.Vector#add(int, java.lang.Object)
     */
    public void test_addILjava_lang_Object() {
        // Test for method void java.util.Vector.add(int, java.lang.Object)
        Object o = new Object();
        Object prev = tVector.get(45);
        tVector.add(45, o);
        assertTrue("Failed to add Object", tVector.get(45) == o);
        assertTrue("Failed to fix-up existing indices", tVector.get(46) == prev);
        assertEquals("Wrong size after add", 101, tVector.size());

        prev = tVector.get(50);
        tVector.add(50, null);
        assertNull("Failed to add null", tVector.get(50));
        assertTrue("Failed to fix-up existing indices after adding null",
                tVector.get(51) == prev);
        assertEquals("Wrong size after add", 102, tVector.size());

        try {
            tVector.add(-5, null);
            fail("ArrayIndexOutOfBoundsException expected");
        } catch(ArrayIndexOutOfBoundsException e) {
            //expected
        }

        try {
            tVector.add(tVector.size() + 1, null);
            fail("ArrayIndexOutOfBoundsException expected");
        } catch(ArrayIndexOutOfBoundsException e) {
            //expected
        }
    }

    /**
     * java.util.Vector#add(java.lang.Object)
     */
    public void test_addLjava_lang_Object() {
        // Test for method boolean java.util.Vector.add(java.lang.Object)
        Object o = new Object();
        tVector.add(o);
        assertTrue("Failed to add Object", tVector.lastElement() == o);
        assertEquals("Wrong size after add", 101, tVector.size());

        tVector.add(null);
        assertNull("Failed to add null", tVector.lastElement());
        assertEquals("Wrong size after add", 102, tVector.size());
    }

    /**
     * java.util.Vector#addAll(int, java.util.Collection)
     */
    public void test_addAllILjava_util_Collection() {
        // Test for method boolean java.util.Vector.addAll(int,
        // java.util.Collection)
        Collection l = new LinkedList();
        for (int i = 0; i < 100; i++)
            l.add("Test " + i);
        Vector v = new Vector();
        tVector.addAll(50, l);
        for (int i = 50; i < 100; i++)
            assertTrue("Failed to add all elements",
                    tVector.get(i) == ((List) l).get(i - 50));
        v = new Vector();
        v.add("one");
        int r = 0;
        try {
            v.addAll(3, Arrays.asList(new String[] { "two", "three" }));
        } catch (ArrayIndexOutOfBoundsException e) {
            r = 1;
        } catch (IndexOutOfBoundsException e) {
            r = 2;
        }
        assertTrue("Invalid add: " + r, r == 1);
        l = new LinkedList();
        l.add(null);
        l.add("gah");
        l.add(null);
        tVector.addAll(50, l);
        assertNull("Wrong element at position 50--wanted null",
                tVector.get(50));
        assertEquals("Wrong element at position 51--wanted 'gah'", "gah", tVector
                .get(51));
        assertNull("Wrong element at position 52--wanted null",
                tVector.get(52));

        try {
            tVector.addAll(-5, Arrays.asList(new String[] { "two", "three" }));
            fail("ArrayIndexOutOfBoundsException expected");
        } catch(ArrayIndexOutOfBoundsException e) {
            //expected
        }

        try {
            tVector.addAll(tVector.size() + 1, Arrays.asList(new String[] { "two", "three" }));
            fail("ArrayIndexOutOfBoundsException expected");
        } catch(ArrayIndexOutOfBoundsException e) {
            //expected
        }

        try {
            tVector.addAll(tVector.size() / 2, null);
            fail("NullPointerException expected");
        } catch(NullPointerException e) {
            //expected
        }
    }

    /**
     * java.util.Vector#addAll(java.util.Collection)
     */
    public void test_addAllLjava_util_Collection() {
        // Test for method boolean java.util.Vector.addAll(java.util.Collection)
        Vector v = new Vector();
        Collection l = new LinkedList();
        for (int i = 0; i < 100; i++)
            l.add("Test " + i);
        v.addAll(l);
        assertTrue("Failed to add all elements", tVector.equals(v));

        v.addAll(l);
        int vSize = tVector.size();
        for (int counter = vSize - 1; counter >= 0; counter--)
            assertTrue("Failed to add elements correctly", v.get(counter) == v
                    .get(counter + vSize));

        l = new LinkedList();
        l.add(null);
        l.add("gah");
        l.add(null);
        tVector.addAll(l);
        assertNull("Wrong element at 3rd last position--wanted null", tVector
                .get(vSize));
        assertEquals("Wrong element at 2nd last position--wanted 'gah'", "gah", tVector
                .get(vSize + 1));
        assertNull("Wrong element at last position--wanted null", tVector
                .get(vSize + 2));

        try {
            tVector.addAll(tVector.size() / 2, null);
            fail("NullPointerException expected");
        } catch(NullPointerException e) {
            //expected
        }
    }

    /**
     * java.util.Vector#addElement(java.lang.Object)
     */
    public void test_addElementLjava_lang_Object() {
        // Test for method void java.util.Vector.addElement(java.lang.Object)
        Vector v = vectorClone(tVector);
        v.addElement("Added Element");
        assertTrue("Failed to add element", v.contains("Added Element"));
        assertEquals("Added Element to wrong slot", "Added Element", ((String) v.elementAt(100))
        );
        v.addElement(null);
        assertTrue("Failed to add null", v.contains(null));
        assertNull("Added null to wrong slot", v.elementAt(101));
    }

    /**
     * java.util.Vector#addElement(java.lang.Object)
     */
    public void test_addElementLjava_lang_Object_subtest0() {
        // Test for method void java.util.Vector.addElement(java.lang.Object)
        Vector v = vectorClone(tVector);
        v.addElement("Added Element");
        assertTrue("Failed to add element", v.contains("Added Element"));
        assertEquals("Added Element to wrong slot", "Added Element", ((String) v.elementAt(100))
        );
        v.addElement(null);
        assertTrue("Failed to add null", v.contains(null));
        assertNull("Added null to wrong slot", v.elementAt(101));
    }

    /**
     * java.util.Vector#capacity()
     */
    public void test_capacity() {
        // Test for method int java.util.Vector.capacity()

        Vector v = new Vector(9);
        assertEquals("Incorrect capacity returned", 9, v.capacity());
    }

    /**
     * java.util.Vector#clear()
     */
    public void test_clear() {
        // Test for method void java.util.Vector.clear()
        Vector orgVector = vectorClone(tVector);
        tVector.clear();
        assertEquals("a) Cleared Vector has non-zero size", 0, tVector.size());
        Enumeration e = orgVector.elements();
        while (e.hasMoreElements())
            assertTrue("a) Cleared vector contained elements", !tVector
                    .contains(e.nextElement()));

        tVector.add(null);
        tVector.clear();
        assertEquals("b) Cleared Vector has non-zero size", 0, tVector.size());
        e = orgVector.elements();
        while (e.hasMoreElements())
            assertTrue("b) Cleared vector contained elements", !tVector
                    .contains(e.nextElement()));
    }

    /**
     * java.util.Vector#clone()
     */
    public void test_clone() {
        // Test for method java.lang.Object java.util.Vector.clone()
        tVector.add(25, null);
        tVector.add(75, null);
        Vector v = (Vector) tVector.clone();
        Enumeration orgNum = tVector.elements();
        Enumeration cnum = v.elements();

        while (orgNum.hasMoreElements()) {
            assertTrue("Not enough elements copied", cnum.hasMoreElements());
            assertTrue("Vector cloned improperly, elements do not match",
                    orgNum.nextElement() == cnum.nextElement());
        }
        assertTrue("Not enough elements copied", !cnum.hasMoreElements());

    }

    /**
     * java.util.Vector#contains(java.lang.Object)
     */
    public void test_containsLjava_lang_Object() {
        // Test for method boolean java.util.Vector.contains(java.lang.Object)
        assertTrue("Did not find element", tVector.contains("Test 42"));
        assertTrue("Found bogus element", !tVector.contains("Hello"));
        assertTrue(
                "Returned true looking for null in vector without null element",
                !tVector.contains(null));
        tVector.insertElementAt(null, 20);
        assertTrue(
                "Returned false looking for null in vector with null element",
                tVector.contains(null));
    }

    /**
     * java.util.Vector#containsAll(java.util.Collection)
     */
    public void test_containsAllLjava_util_Collection() {
        // Test for method boolean
        // java.util.Vector.containsAll(java.util.Collection)
        Collection s = new HashSet();
        for (int i = 0; i < 100; i++)
            s.add("Test " + i);

        assertTrue("Returned false for valid collection", tVector
                .containsAll(s));
        s.add(null);
        assertTrue("Returned true for invlaid collection containing null",
                !tVector.containsAll(s));
        tVector.add(25, null);
        assertTrue("Returned false for valid collection containing null",
                tVector.containsAll(s));
        s = new HashSet();
        s.add(new Object());
        assertTrue("Returned true for invalid collection", !tVector
                .containsAll(s));

        try {
            tVector.containsAll(null);
            fail("NullPointerException expected");
        } catch (NullPointerException e) {
            //expected
        }
    }

    /**
     * java.util.Vector#copyInto(java.lang.Object[])
     */
    public void test_copyInto$Ljava_lang_Object() {
        // Test for method void java.util.Vector.copyInto(java.lang.Object [])

        Object[] a = new Object[100];
        tVector.setElementAt(null, 20);
        tVector.copyInto(a);

        for (int i = 0; i < 100; i++)
            assertTrue("copyInto failed", a[i] == tVector.elementAt(i));

        try {
            tVector.copyInto(null);
            fail("NullPointerException expected");
        } catch (NullPointerException e) {
            //expected
        }
    }

    /**
     * java.util.Vector#elementAt(int)
     */
    public void test_elementAtI() {
        // Test for method java.lang.Object java.util.Vector.elementAt(int)
        assertEquals("Incorrect element returned", "Test 18", ((String) tVector
                .elementAt(18)));
        tVector.setElementAt(null, 20);
        assertNull("Incorrect element returned--wanted null", tVector
                .elementAt(20));

        try {
            tVector.elementAt(-5);
            fail("ArrayIndexOutOfBoundsException expected");
        } catch(ArrayIndexOutOfBoundsException e) {
            //expected
        }

        try {
            tVector.elementAt(tVector.size() + 1);
            fail("ArrayIndexOutOfBoundsException expected");
        } catch(ArrayIndexOutOfBoundsException e) {
            //expected
        }
    }

    /**
     * java.util.Vector#elements()
     */
    public void test_elements() {
        // Test for method java.util.Enumeration java.util.Vector.elements()
        tVector.insertElementAt(null, 20);
        Enumeration e = tVector.elements();
        int i = 0;
        while (e.hasMoreElements()) {
            assertTrue("Enumeration returned incorrect element at pos: " + i, e
                    .nextElement() == tVector.elementAt(i));
            i++;
        }
        assertTrue("Invalid enumeration", i == tVector.size());
    }

    /**
     * java.util.Vector#elements()
     */
    public void test_elements_subtest0() {
        final int iterations = 10000;
        final Vector v = new Vector();
        Thread t1 = new Thread() {
            public void run() {
                for (int i = 0; i < iterations; i++) {
                    synchronized (v) {
                        v.addElement(String.valueOf(i));
                        v.removeElementAt(0);
                    }
                }
            }
        };
        t1.start();
        for (int i = 0; i < iterations; i++) {
            Enumeration en = v.elements();
            try {
                while (true) {
                    Object result = en.nextElement();
                    if (result == null) {
                        fail("Null result: " + i);
                    }
                }
            } catch (NoSuchElementException e) {
            }
        }
    }

    /**
     * java.util.Vector#ensureCapacity(int)
     */
    public void test_ensureCapacityI() {
        // Test for method void java.util.Vector.ensureCapacity(int)

        Vector v = new Vector(9);
        v.ensureCapacity(20);
        assertEquals("ensureCapacity failed to set correct capacity", 20, v
                .capacity());
        v = new Vector(100);
        assertEquals("ensureCapacity reduced capacity", 100, v.capacity());

        v.ensureCapacity(150);
        assertEquals(
                "ensuieCapacity failed to set to be twice the old capacity",
                200, v.capacity());

        v = new Vector(9, -1);
        v.ensureCapacity(20);
        assertEquals("ensureCapacity failed to set to be minCapacity", 20, v
                .capacity());
        v.ensureCapacity(15);
        assertEquals("ensureCapacity reduced capacity", 20, v.capacity());
        v.ensureCapacity(35);
        assertEquals(
                "ensuieCapacity failed to set to be twice the old capacity",
                40, v.capacity());

        v = new Vector(9, 4);
        v.ensureCapacity(11);
        assertEquals("ensureCapacity failed to set correct capacity", 13, v
                .capacity());
        v.ensureCapacity(5);
        assertEquals("ensureCapacity reduced capacity", 13, v.capacity());
        v.ensureCapacity(20);
        assertEquals(
                "ensureCapacity failed to set to be twice the old capacity",
                20, v.capacity());
    }

    /**
     * java.util.Vector#equals(java.lang.Object)
     */
    public void test_equalsLjava_lang_Object() {
        // Test for method boolean java.util.Vector.equals(java.lang.Object)
        Vector v = new Vector();
        for (int i = 0; i < 100; i++)
            v.addElement("Test " + i);
        assertTrue("a) Equal vectors returned false", tVector.equals(v));
        v.addElement(null);
        assertTrue("b) UnEqual vectors returned true", !tVector.equals(v));
        tVector.addElement(null);
        assertTrue("c) Equal vectors returned false", tVector.equals(v));
        tVector.removeElementAt(22);
        assertTrue("d) UnEqual vectors returned true", !tVector.equals(v));
        assertTrue("e) Equal vectors returned false", tVector.equals(tVector));
        assertFalse("f) UnEqual vectors returned true", tVector
                .equals(new Object()));
        assertFalse("g) Unequal vectors returned true", tVector.equals(null));
    }

    /**
     * java.util.Vector#firstElement()
     */
    public void test_firstElement() {
        // Test for method java.lang.Object java.util.Vector.firstElement()
        assertEquals("Returned incorrect firstElement", "Test 0", tVector.firstElement()
        );
        tVector.insertElementAt(null, 0);
        assertNull("Returned incorrect firstElement--wanted null", tVector
                .firstElement());

        Vector v = new Vector(10);
        try {
            v.firstElement();
            fail("Should throw NoSuchElementException");
        } catch (NoSuchElementException e) {
            // Excepted
        }
    }

    /**
     * java.util.Vector#get(int)
     */
    public void test_getI() {
        // Test for method java.lang.Object java.util.Vector.get(int)
        assertEquals("Get returned incorrect object",
                "Test 80", tVector.get(80));
        tVector.add(25, null);
        assertNull("Returned incorrect element--wanted null",
                tVector.get(25));

        try {
            tVector.get(-5);
            fail("ArrayIndexOutOfBoundsException expected");
        } catch(ArrayIndexOutOfBoundsException e) {
            //expected
        }

        try {
            tVector.get(tVector.size() + 1);
            fail("ArrayIndexOutOfBoundsException expected");
        } catch(ArrayIndexOutOfBoundsException e) {
            //expected
        }
    }

    /**
     * java.util.Vector#hashCode()
     */
    public void test_hashCode() {
        // Test for method int java.util.Vector.hashCode()
        int hashCode = 1; // one
        tVector.insertElementAt(null, 20);
        for (int i = 0; i < tVector.size(); i++) {
            Object obj = tVector.elementAt(i);
            hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode());
        }
        assertTrue("Incorrect hashCode returned.  Wanted: " + hashCode
                + " got: " + tVector.hashCode(), tVector.hashCode() == hashCode);
    }

    /**
     * java.util.Vector#indexOf(java.lang.Object)
     */
    public void test_indexOfLjava_lang_Object() {
        // Test for method int java.util.Vector.indexOf(java.lang.Object)
        assertEquals("Incorrect index returned", 10, tVector.indexOf("Test 10"));
        assertEquals("Index returned for invalid Object", -1, tVector
                .indexOf("XXXXXXXXXXX"));
        tVector.setElementAt(null, 20);
        tVector.setElementAt(null, 40);
        assertTrue("Incorrect indexOf returned for null: "
                + tVector.indexOf(null), tVector.indexOf(null) == 20);
    }

    /**
     * java.util.Vector#indexOf(java.lang.Object, int)
     */
    public void test_indexOfLjava_lang_ObjectI() {
        // Test for method int java.util.Vector.indexOf(java.lang.Object, int)
        assertEquals("Failed to find correct index", tVector.indexOf("Test 98",
                50), 98);
        assertTrue("Found index of bogus element", (tVector.indexOf(
                "Test 1001", 50) == -1));
        tVector.setElementAt(null, 20);
        tVector.setElementAt(null, 40);
        tVector.setElementAt(null, 60);
        assertTrue("a) Incorrect indexOf returned for null: "
                + tVector.indexOf(null, 25), tVector.indexOf(null, 25) == 40);
        assertTrue("b) Incorrect indexOf returned for null: "
                + tVector.indexOf(null, 20), tVector.indexOf(null, 20) == 20);
        try {
            tVector.indexOf("Test 98", -1);
            fail("should throw ArrayIndexOutOfBoundsException");
        } catch (ArrayIndexOutOfBoundsException e) {

        }
        assertEquals(-1, tVector.indexOf("Test 98", 1000));
        assertEquals(-1, tVector.indexOf("Test 98", Integer.MAX_VALUE));
        assertEquals(-1, tVector.indexOf("Test 98", tVector.size()));
        assertEquals(98, tVector.indexOf("Test 98", 0));
        try {
            tVector.indexOf("Test 98", Integer.MIN_VALUE);
            fail("should throw ArrayIndexOutOfBoundsException");
        } catch (ArrayIndexOutOfBoundsException e) {

        }
    }

    /**
     * java.util.Vector#insertElementAt(java.lang.Object, int)
     */
    public void test_insertElementAtLjava_lang_ObjectI() {
        // Test for method void
        // java.util.Vector.insertElementAt(java.lang.Object, int)
        Vector v = vectorClone(tVector);
        String prevElement = (String) v.elementAt(99);
        v.insertElementAt("Inserted Element", 99);
        assertEquals("Element not inserted", "Inserted Element", ((String) v.elementAt(99))
        );
        assertTrue("Elements shifted incorrectly", ((String) v.elementAt(100))
                .equals(prevElement));
        v.insertElementAt(null, 20);
        assertNull("null not inserted", v.elementAt(20));

        try {
            tVector.insertElementAt("Inserted Element", -1);
            fail("Should throw ArrayIndexOutOfBoundsException");
        } catch (ArrayIndexOutOfBoundsException e) {
            // Excepted
        }

        try {
            tVector.insertElementAt(null, -1);
            fail("Should throw ArrayIndexOutOfBoundsException");
        } catch (ArrayIndexOutOfBoundsException e) {
            // Excepted
        }

        try {
            tVector.insertElementAt("Inserted Element", tVector.size() + 1);
            fail("Should throw ArrayIndexOutOfBoundsException");
        } catch (ArrayIndexOutOfBoundsException e) {
            // Excepted
        }

        try {
            tVector.insertElementAt(null, tVector.size() + 1);
            fail("Should throw ArrayIndexOutOfBoundsException");
        } catch (ArrayIndexOutOfBoundsException e) {
            // Excepted
        }
    }

    /**
     * java.util.Vector#isEmpty()
     */
    public void test_isEmpty() {
        // Test for method boolean java.util.Vector.isEmpty()Vector
        Vector v = new java.util.Vector();
        assertTrue("Empty vector returned false", v.isEmpty());
        v.addElement(new Object());
        assertTrue("non-Empty vector returned true", !v.isEmpty());
    }

    /**
     * java.util.Vector#isEmpty()
     */
    public void test_isEmpty_subtest0() {
        final Vector v = new Vector();
        v.addElement("initial");
        Thread t1 = new Thread() {
            public void run() {
                while (!v.isEmpty())
                    ;
                v.addElement("final");
            }
        };
        t1.start();
        for (int i = 0; i < 10000; i++) {
            synchronized (v) {
                v.removeElementAt(0);
                v.addElement(String.valueOf(i));
            }
            int size;
            if ((size = v.size()) != 1) {
                String result = "Size is not 1: " + size + " " + v;
                // terminate the thread
                v.removeAllElements();
                fail(result);
            }
        }
        // terminate the thread
        v.removeElementAt(0);
    }

    /**
     * java.util.Vector#lastElement()
     */
    public void test_lastElement() {
        // Test for method java.lang.Object java.util.Vector.lastElement()
        assertEquals("Incorrect last element returned", "Test 99", tVector.lastElement()
        );
        tVector.addElement(null);
        assertNull("Incorrect last element returned--wanted null", tVector
                .lastElement());

        Vector vector = new Vector();
        try {
            vector.lastElement();
            fail("Should throw NoSuchElementException");
        } catch (NoSuchElementException e) {
            // Excepted
        }
    }

    /**
     * java.util.Vector#lastIndexOf(java.lang.Object)
     */
    public void test_lastIndexOfLjava_lang_Object() {
        // Test for method int java.util.Vector.lastIndexOf(java.lang.Object)
        Vector v = new Vector(9);
        for (int i = 0; i < 9; i++)
            v.addElement("Test");
        v.addElement("z");
        assertEquals("Failed to return correct index", 8, v.lastIndexOf("Test"));
        tVector.setElementAt(null, 20);
        tVector.setElementAt(null, 40);
        assertTrue("Incorrect lastIndexOf returned for null: "
                + tVector.lastIndexOf(null), tVector.lastIndexOf(null) == 40);
    }

    /**
     * java.util.Vector#lastIndexOf(java.lang.Object, int)
     */
    public void test_lastIndexOfLjava_lang_ObjectI() {
        // Test for method int java.util.Vector.lastIndexOf(java.lang.Object,
        // int)
        assertEquals("Failed to find object",
                0, tVector.lastIndexOf("Test 0", 0));
        assertTrue("Found Object outside of index", (tVector.lastIndexOf(
                "Test 0", 10) > -1));
        tVector.setElementAt(null, 20);
        tVector.setElementAt(null, 40);
        tVector.setElementAt(null, 60);
        assertTrue("Incorrect lastIndexOf returned for null: "
                + tVector.lastIndexOf(null, 15),
                tVector.lastIndexOf(null, 15) == -1);
        assertTrue("Incorrect lastIndexOf returned for null: "
                + tVector.lastIndexOf(null, 45),
                tVector.lastIndexOf(null, 45) == 40);

        assertEquals(-1, tVector.lastIndexOf("Test 98", -1));
        assertEquals(-1, tVector.lastIndexOf("Test 98", 0));
        try {
            assertEquals(-1, tVector.lastIndexOf("Test 98", 1000));
            fail("should throw IndexOutOfBoundsException");
        } catch (IndexOutOfBoundsException e) {
        }
        try {
            assertEquals(-1, tVector.lastIndexOf("Test 98", Integer.MAX_VALUE));
            fail("should throw IndexOutOfBoundsException");
        } catch (IndexOutOfBoundsException e) {
        }
        try {
            tVector.lastIndexOf("Test 98", tVector.size());
            fail("should throw IndexOutOfBoundsException");
        } catch (IndexOutOfBoundsException e) {
        }
        try {
            tVector.indexOf("Test 98", Integer.MIN_VALUE);
            fail("should throw ArrayIndexOutOfBoundsException");
        } catch (ArrayIndexOutOfBoundsException e) {
        }
    }

    /**
     * java.util.Vector#remove(int)
     */
    public void test_removeI() {
        // Test for method java.lang.Object java.util.Vector.remove(int)
        Object removeElement = tVector.get(36);
        Object result = tVector.remove(36);
        assertFalse("Contained element after remove", tVector
                .contains("Test 36"));
        assertEquals("Should return the element that was removed",
                removeElement, result);
        assertEquals("Failed to decrement size after remove",
                99, tVector.size());
        tVector.add(20, null);
        removeElement = tVector.get(19);
        result = tVector.remove(19);
        assertNull("Didn't move null element over", tVector.get(19));
        assertEquals("Should return the element that was removed",
                removeElement, result);
        removeElement = tVector.get(19);
        result = tVector.remove(19);
        assertNotNull("Didn't remove null element", tVector.get(19));
        assertEquals("Should return the element that was removed",
                removeElement, result);
        assertEquals("Failed to decrement size after removing null", 98, tVector
                .size());

        try {
            tVector.remove(-1);
            fail("Should throw ArrayIndexOutOfBoundsException");
        } catch (ArrayIndexOutOfBoundsException e) {
            // Excepted
        }

        try {
            tVector.remove(tVector.size());
            fail("Should throw ArrayIndexOutOfBoundsException");
        } catch (ArrayIndexOutOfBoundsException e) {
            // Excepted
        }
    }

    /**
     * java.util.Vector#remove(java.lang.Object)
     */
    public void test_removeLjava_lang_Object() {
        // Test for method boolean java.util.Vector.remove(java.lang.Object)
        tVector.remove("Test 0");
        assertTrue("Contained element after remove", !tVector
                .contains("Test 0"));
        assertEquals("Failed to decrement size after remove",
                99, tVector.size());
        tVector.add(null);
        tVector.remove(null);
        assertTrue("Contained null after remove", !tVector.contains(null));
        assertEquals("Failed to decrement size after removing null", 99, tVector
                .size());
    }

    /**
     * java.util.Vector#removeAll(java.util.Collection)
     */
    public void test_removeAllLjava_util_Collection() {
        // Test for method boolean
        // java.util.Vector.removeAll(java.util.Collection)
        Vector v = new Vector();
        Collection l = new LinkedList();
        for (int i = 0; i < 5; i++)
            l.add("Test " + i);
        v.addElement(l);

        Collection s = new HashSet();
        Object o;
        s.add(o = v.firstElement());
        v.removeAll(s);
        assertTrue("Failed to remove items in collection", !v.contains(o));
        v.removeAll(l);
        assertTrue("Failed to remove all elements", v.isEmpty());

        v.add(null);
        v.add(null);
        v.add("Boom");
        v.removeAll(s);
        assertEquals("Should not have removed any elements", 3, v.size());
        l = new LinkedList();
        l.add(null);
        v.removeAll(l);
        assertEquals("Should only have one element", 1, v.size());
        assertEquals("Element should be 'Boom'", "Boom", v.firstElement());

        try {
            v.removeAll(null);
            fail("NullPointerException expected");
        } catch (NullPointerException e) {
            //expected
        }
    }

    /**
     * java.util.Vector#removeAllElements()
     */
    public void test_removeAllElements() {
        // Test for method void java.util.Vector.removeAllElements()
        Vector v = vectorClone(tVector);
        v.removeAllElements();
        assertEquals("Failed to remove all elements", 0, v.size());
    }

    /**
     * java.util.Vector#removeElement(java.lang.Object)
     */
    public void test_removeElementLjava_lang_Object() {
        // Test for method boolean
        // java.util.Vector.removeElement(java.lang.Object)
        Vector v = vectorClone(tVector);
        v.removeElement("Test 98");
        assertEquals("Element not removed", "Test 99", ((String) v.elementAt(98))
        );
        assertTrue("Vector is wrong size after removal: " + v.size(),
                v.size() == 99);
        tVector.addElement(null);
        v.removeElement(null);
        assertTrue("Vector is wrong size after removing null: " + v.size(), v
                .size() == 99);
    }

    /**
     * java.util.Vector#removeElementAt(int)
     */
    public void test_removeElementAtI() {
        // Test for method void java.util.Vector.removeElementAt(int)
        Vector v = vectorClone(tVector);
        int size = v.size();
        v.removeElementAt(50);
        assertEquals("Failed to remove element", -1, v.indexOf("Test 50", 0));
        assertEquals("Test 51", v.get(50));
        assertEquals(size - 1, v.size());

        tVector.insertElementAt(null, 60);
        assertNull(tVector.get(60));
        size = tVector.size();
        tVector.removeElementAt(60);
        assertNotNull("Element at 60 should not be null after removal", tVector
                .elementAt(60));
        assertEquals(size - 1, tVector.size());

        try {
            tVector.removeElementAt(-1);
            fail("Should throw ArrayIndexOutOfBoundsException");
        } catch (ArrayIndexOutOfBoundsException e) {
            // Excepted
        }

        try {
            tVector.removeElementAt(tVector.size());
            fail("Should throw ArrayIndexOutOfBoundsException");
        } catch (ArrayIndexOutOfBoundsException e) {
            // Excepted
        }
    }

    /**
     * {@link java.util.Vector#removeRange(int, int)}
     */
    public void test_removeRange() {
        MockVector myVector = new MockVector();
        myVector.removeRange(0, 0);

        try {
            myVector.removeRange(0, 1);
            fail("Should throw IndexOutOfBoundsException");
        } catch (IndexOutOfBoundsException e) {
            // Excepted
        }

        int[] data = { 1, 2, 3, 4 };
        for (int i = 0; i < data.length; i++) {
            myVector.add(i, data[i]);
        }

        myVector.removeRange(0, 2);
        assertEquals(data[2], myVector.get(0));
        assertEquals(data[3], myVector.get(1));

        try {
            myVector.removeRange(-1, 1);
            fail("Should throw IndexOutOfBoundsException");
        } catch (IndexOutOfBoundsException e) {
            // Excepted
        }

        try {
            myVector.removeRange(0, -1);
            fail("Should throw IndexOutOfBoundsException");
        } catch (IndexOutOfBoundsException e) {
            // Excepted
        }

        try {
            myVector.removeRange(1, 0);
            fail("Should throw IndexOutOfBoundsException");
        } catch (IndexOutOfBoundsException e) {
            // Excepted
        }

        try {
            myVector.removeRange(2, 1);
            fail("Should throw IndexOutOfBoundsException");
        } catch (IndexOutOfBoundsException e) {
            // Excepted
        }
    }

    /**
     * java.util.Vector#retainAll(java.util.Collection)
     */
    public void test_retainAllLjava_util_Collection() {
        // Test for method boolean
        // java.util.Vector.retainAll(java.util.Collection)
        Object o = tVector.firstElement();
        tVector.add(null);
        Collection s = new HashSet();
        s.add(o);
        s.add(null);
        tVector.retainAll(s);
        assertTrue("Retained items other than specified", tVector.size() == 2
                && tVector.contains(o) && tVector.contains(null));
    }

    /**
     * java.util.Vector#set(int, java.lang.Object)
     */
    public void test_setILjava_lang_Object() {
        // Test for method java.lang.Object java.util.Vector.set(int,
        // java.lang.Object)
        Object o = new Object();
        Object previous = tVector.get(23);
        Object result = tVector.set(23, o);
        assertEquals(
                "Should return the element previously at the specified position",
                previous, result);
        assertTrue("Failed to set Object", tVector.get(23) == o);

        previous = tVector.get(0);
        result = tVector.set(0, null);
        assertEquals(
                "Should return the element previously at the specified position",
                previous, result);
        assertNull("Failed to set Object", tVector.get(0));

        try {
            tVector.set(-1, o);
            fail("Should throw ArrayIndexOutOfBoundsException");
        } catch (ArrayIndexOutOfBoundsException e) {
            // Excepted
        }

        try {
            tVector.set(-1, null);
            fail("Should throw ArrayIndexOutOfBoundsException");
        } catch (ArrayIndexOutOfBoundsException e) {
            // Excepted
        }

        try {
            tVector.set(tVector.size(), o);
            fail("Should throw ArrayIndexOutOfBoundsException");
        } catch (ArrayIndexOutOfBoundsException e) {
            // Excepted
        }

        try {
            tVector.set(tVector.size(), null);
            fail("Should throw ArrayIndexOutOfBoundsException");
        } catch (ArrayIndexOutOfBoundsException e) {
            // Excepted
        }
    }

    /**
     * java.util.Vector#setElementAt(java.lang.Object, int)
     */
    public void test_setElementAtLjava_lang_ObjectI() {
        // Test for method void java.util.Vector.setElementAt(java.lang.Object,
        // int)
        Vector v = vectorClone(tVector);
        v.setElementAt("Inserted Element", 99);
        assertEquals("Element not set", "Inserted Element", ((String) v.elementAt(99))
        );

        v.setElementAt(null, 0);
        assertNull("Null element not set", v.elementAt(0));

        try {
            v.setElementAt("Inserted Element", -1);
            fail("Should throw ArrayIndexOutOfBoundsException");
        } catch (ArrayIndexOutOfBoundsException e) {
            // Excepted
        }

        try {
            v.setElementAt(null, -1);
            fail("Should throw ArrayIndexOutOfBoundsException");
        } catch (ArrayIndexOutOfBoundsException e) {
            // Excepted
        }

        try {
            v.setElementAt("Inserted Element", v.size());
            fail("Should throw ArrayIndexOutOfBoundsException");
        } catch (ArrayIndexOutOfBoundsException e) {
            // Excepted
        }

        try {
            v.setElementAt(null, v.size());
            fail("Should throw ArrayIndexOutOfBoundsException");
        } catch (ArrayIndexOutOfBoundsException e) {
            // Excepted
        }
    }

    /**
     * java.util.Vector#setSize(int)
     */
    public void test_setSizeI() {
        // Test for method void java.util.Vector.setSize(int)
        Vector v = vectorClone(tVector);
        int oldSize = v.size();
        Object preElement = v.get(10);
        v.setSize(10);
        assertEquals("Failed to set size", 10, v.size());
        assertEquals(
                "All components at index newSize and greater should be discarded",
                -1, v.indexOf(preElement));
        try {
            v.get(oldSize - 1);
        } catch (ArrayIndexOutOfBoundsException e) {
            // Excepted;
        }

        oldSize = v.size();
        v.setSize(20);
        assertEquals("Failed to set size", 20, v.size());
        for (int i = oldSize; i < v.size(); i++) {
            assertNull(v.get(i));
        }

        try {
            v.setSize(-1);
            fail("Should throw ArrayIndexOutOfBoundsException");
        } catch (ArrayIndexOutOfBoundsException e) {
            // Excepted
        }
    }

    /**
     * java.util.Vector#size()
     */
    public void test_size() {
        // Test for method int java.util.Vector.size()
        assertEquals("Returned incorrect size", 100, tVector.size());

        final Vector v = new Vector();
        v.addElement("initial");
        Thread t1 = new Thread() {
            public void run() {
                while (v.size() > 0)
                    ;
                v.addElement("final");
            }
        };
        t1.start();
        for (int i = 0; i < 10000; i++) {
            synchronized (v) {
                v.removeElementAt(0);
                v.addElement(String.valueOf(i));
            }
            int size;
            if ((size = v.size()) != 1) {
                String result = "Size is not 1: " + size + " " + v;
                // terminate the thread
                v.removeAllElements();
                fail(result);
            }
        }
        // terminate the thread
        v.removeElementAt(0);
    }

    /**
     * java.util.Vector#subList(int, int)
     */
    public void test_subListII() {
        // Test for method java.util.List java.util.Vector.subList(int, int)
        List sl = tVector.subList(10, 25);
        assertEquals("Returned sublist of incorrect size", 15, sl.size());
        for (int i = 10; i < 25; i++)
            assertTrue("Returned incorrect sublist", sl
                    .contains(tVector.get(i)));

        assertEquals("Not synchronized random access", "java.util.Collections$SynchronizedRandomAccessList", sl.getClass().getName()
        );

    }

    /**
     * java.util.Vector#toArray()
     */
    public void test_toArray() {
        // Test for method java.lang.Object [] java.util.Vector.toArray()
        assertTrue("Returned incorrect array", Arrays.equals(objArray, tVector
                .toArray()));
    }

    /**
     * java.util.Vector#toArray(java.lang.Object[])
     */
    public void test_toArray$Ljava_lang_Object() {
        // Test for method java.lang.Object []
        // java.util.Vector.toArray(java.lang.Object [])
        Object[] o = new Object[1000];
        Object f = new Object();
        for (int i = 0; i < o.length; i++)
            o[i] = f;
        tVector.toArray(o);
        assertNull("Failed to set slot to null", o[100]);
        for (int i = 0; i < tVector.size(); i++)
            assertTrue("Returned incorrect array", tVector.elementAt(i) == o[i]);
    }


    class SubVector<E> extends Vector<E> {

        private static final long serialVersionUID = 1L;

        public SubVector() {
            super();
        }

        public synchronized boolean add(E obj) {
            super.addElement(obj);
            return true;
        }

        public synchronized void addElement(E obj) {
            super.add(obj);
        }

        /**
         * java.util.Vector#add(Object)
         */
        @SuppressWarnings("nls")
        public void test_add() {
            SubVector<String> subvector = new SubVector<String>();
            subvector.add("foo");
            subvector.addElement("bar");
            assertEquals("Expected two elements in vector", 2, subvector.size());
        }

    }

    /**
     * java.util.Vector#toString()
     */
    public void test_toString() {
        // Ensure toString works with self-referencing elements.
        Vector<Object> vec = new Vector<Object>(3);
        vec.add(null);
        vec.add(new Object());
        vec.add(vec);
        assertNotNull(vec.toString());

        // Test for method java.lang.String java.util.Vector.toString()
        assertTrue("Incorrect String returned", tVector.toString().equals(
                vString));

        Vector v = new Vector();
        v.addElement("one");
        v.addElement(v);
        v.addElement("3");
        // test last element
        v.addElement(v);
        String result = v.toString();
        assertTrue("should contain self ref", result.indexOf("(this") > -1);
    }

    public void test_override_size() throws Exception {
        Vector v = new Vector();
        Vector testv = new MockVector();
        // though size is overriden, it should passed without exception
        testv.add(1);
        testv.add(2);
        testv.clear();

        testv.add(1);
        testv.add(2);
        v.add(1);
        v.add(2);
        // RI's bug here
        assertTrue(testv.equals(v));
    }

    /**
     * java.util.Vector#trimToSize()
     */
    public void test_trimToSize() {
        // Test for method void java.util.Vector.trimToSize()
        Vector v = new Vector(10);
        v.addElement(new Object());
        v.trimToSize();
        assertEquals("Failed to trim capacity", 1, v.capacity());
    }

    public void test_removeRangeII() {
        MockVector mv = new MockVector();
        mv.add("First");
        mv.add("Second");
        mv.add("One more");
        mv.add("Last");
        mv.removeRange(1, 3);
        assertTrue(mv.contains("First"));
        assertFalse(mv.contains("Second"));
        assertFalse(mv.contains("One more"));
        assertTrue(mv.contains("Last"));
    }

    protected Vector vectorClone(Vector s) {
        return (Vector) s.clone();
    }

    public class MockVector extends Vector {
        @Override
        public synchronized int size() {
            return 0;
        }

        public void removeRange(int start, int end) {
            super.removeRange(start, end);
        }
    }

    public void test_forEach() throws Exception {
      Vector<Integer> vector = new Vector<Integer>();
      vector.add(0);
      vector.add(1);
      vector.add(2);

      Vector<Integer> output = new Vector<Integer>();
      vector.forEach ( k -> output.add(k) );

      assertEquals(vector, output);
    }


    public void test_forEach_NPE() throws Exception {
        Vector<Integer> vector = new Vector<>();
        try {
            vector.forEach(null);
            fail();
        } catch(NullPointerException expected) {}
    }

    public void test_forEach_CME() throws Exception {
        Vector<Integer> vector = new Vector<>();
        vector.add(1);
        vector.add(2);
        try {
            vector.forEach(new java.util.function.Consumer<Integer>() {
                    @Override
                    public void accept(Integer t) {vector.add(t);}
                });
            fail();
        } catch(ConcurrentModificationException expected) {}
    }

    public void test_forEachRemaining_iterator() throws Exception {
        ForEachRemainingTester.runTests(Vector.class, new String[] { "foo", "bar", "baz" });
        ForEachRemainingTester.runTests(Vector.class, new String[] { "foo" });
    }

    public void test_spliterator() throws Exception {
        ArrayList<Integer> testElements = new ArrayList<>(
                Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16));
        Vector<Integer> list = new Vector<>();
        list.addAll(testElements);

        SpliteratorTester.runBasicIterationTests(list.spliterator(), testElements);
        SpliteratorTester.runBasicSplitTests(list, testElements);
        SpliteratorTester.testSpliteratorNPE(list.spliterator());

        assertTrue(list.spliterator().hasCharacteristics(
                Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED));

        SpliteratorTester.runOrderedTests(list);
        SpliteratorTester.runSizedTests(list, 16 /* expected size */);
        SpliteratorTester.runSubSizedTests(list, 16 /* expected size */);
    }

    public void test_spliterator_CME() throws Exception {
        Vector<Integer> list = new Vector<>();
        list.add(52);

        Spliterator<Integer> sp = list.spliterator();
        try {
            sp.tryAdvance(value -> list.add(value));
            fail();
        } catch (ConcurrentModificationException expected) {
        }

        try {
            sp.forEachRemaining(value -> list.add(value));
            fail();
        } catch (ConcurrentModificationException expected) {
        }
    }

    public void test_removeIf() {
        runBasicRemoveIfTests(Vector<Integer>::new);
        runBasicRemoveIfTestsUnordered(Vector<Integer>::new);
        runRemoveIfOnEmpty(Vector<Integer>::new);
        testRemoveIfNPE(Vector<Integer>::new);
        testRemoveIfCME(Vector<Integer>::new);
    }

    // http://b/25867131 et al.
    public void testIteratorAddAfterCompleteIteration() {
        Vector<String> strings = new Vector<>();
        strings.add("string1");
        Iterator<String> it = strings.iterator();
        assertTrue(it.hasNext());
        assertEquals("string1", it.next());
        assertFalse(it.hasNext());
        strings.add("string2");
        // The value of hasNext() must not flap between true and false. If we returned "true"
        // here, we'd fail with a CME on the next call to next() anyway.
        assertFalse(it.hasNext());
    }

    public void testHasNextAfterRemoval() {
        Vector<String> strings = new Vector<>();
        strings.add("string1");
        Iterator<String> it = strings.iterator();
        it.next();
        it.remove();
        assertFalse(it.hasNext());

        strings = new Vector<>();
        strings.add("string1");
        strings.add("string2");
        it = strings.iterator();
        it.next();
        it.remove();
        assertTrue(it.hasNext());
        assertEquals("string2", it.next());
    }

    // http://b/27430229
    public void testRemoveAllDuringIteration() {
        Vector<String> vector = new Vector<>();
        vector.add("food");
        Iterator<String> vectorIterator = vector.iterator();
        vectorIterator.next();
        vector.removeAllElements();
        assertFalse(vectorIterator.hasNext());
    }

    /**
     * Sets up the fixture, for example, open a network connection. This method
     * is called before a test is executed.
     */
    protected void setUp() {
        for (int i = 0; i < 100; i++) {
            tVector.addElement("Test " + i);
        }
        objArray = new Object[100];
        for (int i = 0; i < 100; i++) {
            objArray[i] = "Test " + i;
        }
    }

    /**
     * Tears down the fixture, for example, close a network connection. This
     * method is called after a test is executed.
     */
    protected void tearDown() {
    }
}
