// CHECKSTYLE_OFF: Copyrighted to ASF
/*
 * Copyright 1999-2004 The Apache Software Foundation
 *
 * Licensed 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.
 */
// CHECKSTYLE_ON
package com.google.gwt.emultest.java.util;

import com.google.gwt.testing.TestUtils;
import java.util.Arrays;
import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import jsinterop.annotations.JsPackage;
import jsinterop.annotations.JsProperty;

/**
 * Tests base {@link java.util.Map} methods and contracts.
 * <p>
 * The forces at work here are similar to those in {@link TestCollection}.
 * If your class implements the full Map interface, including optional
 * operations, simply extend this class, and implement the {@link
 * #makeEmptyMap()} method.
 * <p>
 * On the other hand, if your map implemenation is weird, you may have to
 * override one or more of the other protected methods.  They're described
 * below.<P>
 *
 * <B>Entry Population Methods</B><P>
 *
 * Override these methods if your map requires special entries:
 *
 * <UL>
 * <LI>{@link #getSampleKeys()}
 * <LI>{@link #getSampleValues()}
 * <LI>{@link #getNewSampleValues()}
 * <LI>{@link #getOtherKeys()}
 * <LI>{@link #getOtherValues()}
 * </UL>
 *
 * <B>Supported Operation Methods</B><P>
 *
 * Override these methods if your map doesn't support certain operations:
 *
 * <UL>
 * <LI> {@link #useDuplicateValues()}
 * <LI> {@link #useNullKey()}
 * <LI> {@link #useNullValue()}
 * <LI> {@link #isAddRemoveModifiable()}
 * <LI> {@link #isChangeable()}
 * </UL>
 *
 * <B>Fixture Methods</B><P>
 *
 * For tests on modification operations (puts and removes), fixtures are used
 * to verify that that operation results in correct state for the map and its
 * collection views.  Basically, the modification is performed against your
 * map implementation, and an identical modification is performed against
 * a <I>confirmed</I> map implementation.  A confirmed map implementation is
 * something like <Code>java.util.HashMap</Code>, which is known to conform
 * exactly to the {@link Map} contract.  After the modification takes place
 * on both your map implementation and the confirmed map implementation, the
 * two maps are compared to see if their state is identical.  The comparison
 * also compares the collection views to make sure they're still the same.<P>
 *
 * The upshot of all that is that <I>any</I> test that modifies the map in
 * <I>any</I> way will verify that <I>all</I> of the map's state is still
 * correct, including the state of its collection views.  So for instance
 * if a key is removed by the map's key set's iterator, then the entry set
 * is checked to make sure the key/value pair no longer appears.<P>
 *
 * The {@link #map} field holds an instance of your collection implementation.
 * The {@link #entrySet}, {@link #keySet} and {@link #collectionValues} fields hold
 * that map's collection views.  And the {@link #confirmed} field holds
 * an instance of the confirmed collection implementation.  The
 * {@link #resetEmpty()} and {@link #resetFull()} methods set these fields to
 * empty or full maps, so that tests can proceed from a known state.<P>
 *
 * After a modification operation to both {@link #map} and {@link #confirmed},
 * the {@link #verify()} method is invoked to compare the results.  The {@link
 * verify()} method calls separate methods to verify the map and its three
 * collection views ({@link verifyMap(), {@link verifyEntrySet()}, {@link
 * verifyKeySet()}, and {@link verifyValues()}).  You may want to override one
 * of the verification methodsto perform additional verifications.  For
 * instance, {@link TestDoubleOrderedMap} would want override its {@link
 * #verifyValues()} method to verify that the values are unique and in
 * ascending order.<P>
 *
 * <B>Other Notes</B><P>
 *
 * If your {@link Map} fails one of these tests by design, you may still use
 * this base set of cases.  Simply override the test case (method) your {@link
 * Map} fails and/or the methods that define the assumptions used by the test
 * cases.  For example, if your map does not allow duplicate values, override
 * {@link #useDuplicateValues()} and have it return <code>false</code>
 */
@SuppressWarnings({"unchecked", "rawtypes"})
abstract class TestMap extends TestObject {

  // These instance variables are initialized with the reset method.
  // Tests for map methods that alter the map (put, putAll, remove)
  // first call reset() to create the map and its views; then perform
  // the modification on the map; perform the same modification on the
  // confirmed; and then call verify() to ensure that the map is equal
  // to the confirmed, that the already-constructed collection views
  // are still equal to the confirmed's collection views.

  /** Map created by reset(). */
  protected Map map;

  /** Entry set of map created by reset(). */
  protected Set entrySet;

  /** Key set of map created by reset(). */
  protected Set keySet;

  /** Values collection of map created by reset(). */
  protected Collection collectionValues;

  /** HashMap created by reset(). */
  protected Map confirmed;

  /**
   * Override if your map does not allow a <code>null</code> key. The default implementation returns
   * <code>true</code>
   */
  protected boolean useNullKey() {
    return true;
  }

  /**
   * Override if your map does not allow <code>null</code> values. The default implementation
   * returns <code>true</code>.
   */
  protected boolean useNullValue() {
    return true;
  }

  /**
   * Override if your map does not allow duplicate values. The default implementation returns <code>
   * true</code>.
   */
  protected boolean useDuplicateValues() {
    return true;
  }

  /**
   * Override if your map allows its mappings to be changed to new values. The default
   * implementation returns <code>true</code>.
   */
  protected boolean isChangeable() {
    return true;
  }

  /**
   * Override if your map does not allow add/remove modifications. The default implementation
   * returns <code>true</code>.
   */
  protected boolean isAddRemoveModifiable() {
    return true;
  }

  /**
   * Override if your map allows concurrent modifications. The default implementation returns <code>
   * true</code>.
   */
  protected boolean isFailFastExpected() {
    return true;
  }

  /**
   * Returns the set of keys in the mappings used to test the map. This method must return an array
   * with the same length as {@link #getSampleValues()} and all array elements must be different.
   * The default implementation constructs a set of String keys, and includes a single null key if
   * {@link #useNullKey()} returns <code>true</code>.
   */
  protected Object[] getSampleKeys() {
    Object[] result = {
      "blah",
      "foo",
      "bar",
      "baz",
      "tmp",
      "gosh",
      "golly",
      "gee",
      "hello",
      "goodbye",
      "we'll",
      "see",
      "you",
      "all",
      "again",
      "key",
      "key2",
      useNullKey() ? null : "nonnullkey"
    };
    return result;
  }

  protected Object[] getOtherKeys() {
    return TestCollection.getOtherNonNullStringElements();
  }

  protected Object[] getOtherValues() {
    return TestCollection.getOtherNonNullStringElements();
  }

  /**
   * Returns the set of values in the mappings used to test the map. This method must return an
   * array with the same length as {@link #getSampleKeys()}. The default implementation contructs a
   * set of String values and includes a single null value if {@link #useNullValue()} returns <code>
   * true</code>, and includes two values that are the same if {@link #useDuplicateValues()} returns
   * <code>true</code>.
   */
  protected Object[] getSampleValues() {
    Object[] result = {
      "blahv",
      "foov",
      "barv",
      "bazv",
      "tmpv",
      "goshv",
      "gollyv",
      "geev",
      "hellov",
      "goodbyev",
      "we'llv",
      "seev",
      "youv",
      "allv",
      "againv",
      useNullValue() ? null : "nonnullvalue",
      "value",
      useDuplicateValues() ? "value" : "value2",
    };
    return result;
  }

  /**
   * Returns a the set of values that can be used to replace the values returned from {@link
   * #getSampleValues()}. This method must return an array with the same length as {@link
   * #getSampleValues()}. The values returned from this method should not be the same as those
   * returned from {@link #getSampleValues()}. The default implementation constructs a set of String
   * values and includes a single null value if {@link #useNullValue()} returns <code>true</code>,
   * and includes two values that are the same if {@link #useDuplicateValues()} returns <code>true
   * </code>.
   */
  protected Object[] getNewSampleValues() {
    Object[] result = {
      useNullValue() ? null : "newnonnullvalue",
      "newvalue",
      useDuplicateValues() ? "newvalue" : "newvalue2",
      "newblahv",
      "newfoov",
      "newbarv",
      "newbazv",
      "newtmpv",
      "newgoshv",
      "newgollyv",
      "newgeev",
      "newhellov",
      "newgoodbyev",
      "newwe'llv",
      "newseev",
      "newyouv",
      "newallv",
      "newagainv",
    };
    return result;
  }

  /**
   * Helper method to add all the mappings described by {@link #getSampleKeys()} and {@link
   * #getSampleValues()}.
   */
  protected void addSampleMappings(Map m) {

    Object[] keys = getSampleKeys();
    Object[] values = getSampleValues();

    for (int i = 0; i < keys.length; i++) {
      try {
        m.put(keys[i], values[i]);
      } catch (NullPointerException exception) {
        assertTrue(
            "NullPointerException only allowed to be thrown "
                + "if either the key or value is null.",
            keys[i] == null || values[i] == null);

        if (keys[i] == null) {
          if (useNullKey()) {
            throw new Error(
                "NullPointerException on null key, but "
                    + "useNullKey is not overridden to return false.",
                exception);
          }
        } else if (values[i] == null) {
          if (useNullValue()) {
            throw new Error(
                "NullPointerException on null value, but "
                    + "useNullValue is not overridden to return false.",
                exception);
          }
        } else {
          // Unknown reason for NullPointer.
          throw exception;
        }
      }
    }
    assertEquals("size must reflect number of mappings added.", keys.length, m.size());
  }

  /** Return a new, empty {@link Map} to be used for testing. */
  protected abstract Map makeEmptyMap();

  protected Map makeConfirmedMap() {
    return new HashMap();
  }

  /**
   * Return a new, populated map. The mappings in the map should match the keys and values returned
   * from {@link #getSampleKeys()} and {@link #getSampleValues()}. The default implementation uses
   * makeEmptyMap() and calls {@link #addSampleMappings()} to add all the mappings to the map.
   */
  protected Map makeFullMap() {
    Map m = makeEmptyMap();
    addSampleMappings(m);
    return m;
  }

  @Override
  public Object makeObject() {
    return makeEmptyMap();
  }

  public void testSpecialKeysValues() {
    String[] keys = {"toString", "constructor", "__proto__", "", "null"};
    Object[] values = {new Object(), new Object(), new Object(), new Object(), null};

    Map map = makeEmptyMap();

    assertMap(map, keys, values);

    Object[] undefineds = new Object[values.length];
    Arrays.fill(undefineds, getUndefined());
    assertMap(map, keys, undefineds);
  }

  private void assertMap(Map map, String[] keys, Object[] values) {
    assertEmptyMap(map, keys, values);

    // Fill the map with special keys/values.
    for (int i = 0; i < keys.length; i++) {
      map.put(keys[i], values[i]);
    }

    // Assert the map with filled in keys/values
    for (int i = 0; i < keys.length; i++) {
      assertTrue(keys[i], map.containsKey(keys[i]));
      assertTrue(keys[i], map.containsValue(values[i]));
      assertSame(keys[i], values[i], map.get(keys[i]));
    }
    assertEquals(map.toString(), keys.length, map.size());

    // Remove the keys and assert the results
    for (int i = 0; i < keys.length; i++) {
      assertSame(keys[i], values[i], map.remove(keys[i]));
    }
    assertEmptyMap(map, keys, values);
  }

  private static void assertEmptyMap(Map map, final String[] keys, final Object[] values) {
    for (int i = 0; i < keys.length; i++) {
      assertFalse(keys[i], map.containsKey(keys[i]));
      assertFalse(keys[i], map.containsValue(values[i]));
      assertNull(keys[i], map.get(keys[i]));
    }
  }

  private static Object getUndefined() {
    if (TestUtils.isJvm()) {
      return null;
    }
    return getUndefinedImpl();
  }

  @JsProperty(name = "undefined", namespace = JsPackage.GLOBAL)
  private static native Object getUndefinedImpl();

  /**
   * Test to ensure the test setup is working properly. This method checks to ensure that the
   * getSampleKeys and getSampleValues methods are returning results that look appropriate. That is,
   * they both return a non-null array of equal length. The keys array must not have any duplicate
   * values, and may only contain a (single) null key if useNullKey() returns true. The values array
   * must only have a null value if useNullValue() is true and may only have duplicate values if
   * useDuplicateValues() returns true.
   */
  public void testSampleMappings() {
    Object[] keys = getSampleKeys();
    Object[] values = getSampleValues();
    Object[] newValues = getNewSampleValues();

    assertNotNull("failure in test: Must have keys returned from " + "getSampleKeys.", keys);

    assertTrue(
        "failure in test: Must have values returned from " + "getSampleValues.", values != null);

    // verify keys and values have equivalent lengths (in case getSampleX are
    // overridden)
    assertEquals(
        "failure in test: not the same number of sample " + "keys and values.",
        keys.length,
        values.length);

    assertEquals(
        "failure in test: not the same number of values and new values.",
        values.length,
        newValues.length);

    // verify there aren't duplicate keys, and check values
    for (int i = 0; i < keys.length - 1; i++) {
      for (int j = i + 1; j < keys.length; j++) {
        assertTrue("failure in test: duplicate null keys.", (keys[i] != null || keys[j] != null));
        assertTrue(
            "failure in test: duplicate non-null key.",
            (keys[i] == null
                || keys[j] == null
                || (!keys[i].equals(keys[j]) && !keys[j].equals(keys[i]))));
      }
      assertTrue(
          "failure in test: found null key, but useNullKey " + "is false.",
          keys[i] != null || useNullKey());
      assertTrue(
          "failure in test: found null value, but useNullValue " + "is false.",
          values[i] != null || useNullValue());
      assertTrue(
          "failure in test: found null new value, but useNullValue " + "is false.",
          newValues[i] != null || useNullValue());
      assertTrue(
          "failure in test: values should not be the same as new value",
          values[i] != newValues[i] && (values[i] == null || !values[i].equals(newValues[i])));
    }
  }

  // tests begin here.  Each test adds a little bit of tested functionality.
  // Many methods assume previous methods passed.  That is, they do not
  // exhaustively recheck things that have already been checked in a previous
  // test methods.

  /**
   * Test to ensure that makeEmptyMap and makeFull returns a new non-null map with each invocation.
   */
  public void testMakeMap() {
    Map em = makeEmptyMap();
    assertTrue("failure in test: makeEmptyMap must return a non-null map.", em != null);

    Map em2 = makeEmptyMap();
    assertTrue("failure in test: makeEmptyMap must return a non-null map.", em != null);

    assertTrue(
        "failure in test: makeEmptyMap must return a new map " + "with each invocation.",
        em != em2);

    Map fm = makeFullMap();
    assertTrue("failure in test: makeFullMap must return a non-null map.", fm != null);

    Map fm2 = makeFullMap();
    assertTrue("failure in test: makeFullMap must return a non-null map.", fm != null);

    assertTrue(
        "failure in test: makeFullMap must return a new map " + "with each invocation.", fm != fm2);
  }

  /** Tests Map.isEmpty() */
  public void testMapIsEmpty() {

    resetEmpty();
    assertEquals("Map.isEmpty() should return true with an empty map", true, map.isEmpty());
    verify();

    resetFull();
    assertEquals("Map.isEmpty() should return false with a non-empty map", false, map.isEmpty());
    verify();
  }

  /** Tests Map.size() */
  public void testMapSize() {
    resetEmpty();
    assertEquals("Map.size() should be 0 with an empty map", 0, map.size());
    verify();

    resetFull();
    assertEquals(
        "Map.size() should equal the number of entries " + "in the map",
        getSampleKeys().length,
        map.size());
    verify();
  }

  /**
   * Tests {@link Map#clear()}. If the map {@link #isAddRemoveModifiable() can add and remove
   * elements}, then {@link Map#size()} and {@link Map#isEmpty()} are used to ensure that map has no
   * elements after a call to clear. If the map does not support adding and removing elements, this
   * method checks to ensure clear throws an UnsupportedOperationException.
   */
  public void testMapClear() {
    if (!isAddRemoveModifiable()) {
      return;
    }

    resetEmpty();
    map.clear();
    confirmed.clear();
    verify();

    resetFull();
    map.clear();
    confirmed.clear();
    verify();
  }

  /**
   * Tests Map.containsKey(Object) by verifying it returns false for all sample keys on a map
   * created using an empty map and returns true for all sample keys returned on a full map.
   */
  public void testMapContainsKey() {
    Object[] keys = getSampleKeys();

    resetEmpty();
    for (int i = 0; i < keys.length; i++) {
      assertTrue("Map must not contain key when map is empty", !map.containsKey(keys[i]));
    }
    verify();

    resetFull();
    for (int i = 0; i < keys.length; i++) {
      assertTrue(
          "Map must contain key for a mapping in the map. " + "Missing: " + keys[i],
          map.containsKey(keys[i]));
    }
    verify();
  }

  /**
   * Tests Map.containsValue(Object) by verifying it returns false for all sample values on an empty
   * map and returns true for all sample values on a full map.
   */
  public void testMapContainsValue() {
    Object[] values = getSampleValues();

    resetEmpty();
    for (int i = 0; i < values.length; i++) {
      assertTrue("Empty map must not contain value", !map.containsValue(values[i]));
    }
    verify();

    resetFull();
    for (int i = 0; i < values.length; i++) {
      assertTrue("Map must contain value for a mapping in the map.", map.containsValue(values[i]));
    }
    verify();
  }

  /** Tests Map.equals(Object) */
  public void testMapEquals() {
    resetEmpty();
    assertTrue("Empty maps unequal.", map.equals(confirmed));
    verify();

    resetFull();
    assertTrue("Full maps unequal.", map.equals(confirmed));
    verify();

    resetFull();
    // modify the HashMap created from the full map and make sure this
    // change results in map.equals() to return false.
    Iterator iter = confirmed.keySet().iterator();
    iter.next();
    iter.remove();
    assertTrue("Different maps equal.", !map.equals(confirmed));

    resetFull();
    assertTrue("equals(null) returned true.", !map.equals(null));
    assertTrue("equals(new Object()) returned true.", !map.equals(new Object()));
    verify();
  }

  /** Tests Map.get(Object) */
  public void testMapGet() {
    resetEmpty();

    Object[] keys = getSampleKeys();
    Object[] values = getSampleValues();

    for (int i = 0; i < keys.length; i++) {
      assertTrue("Empty map.get() should return null.", map.get(keys[i]) == null);
    }
    verify();

    resetFull();
    for (int i = 0; i < keys.length; i++) {
      assertEquals("Full map.get() should return value from mapping.", values[i], map.get(keys[i]));
    }
  }

  /** Tests Map.hashCode() */
  public void testMapHashCode() {
    resetEmpty();
    assertTrue("Empty maps have different hashCodes.", map.hashCode() == confirmed.hashCode());

    resetFull();
    assertTrue("Equal maps have different hashCodes.", map.hashCode() == confirmed.hashCode());
  }

  /**
   * Tests Map.toString(). Since the format of the string returned by the toString() method is not
   * defined in the Map interface, there is no common way to test the results of the toString()
   * method. Thereforce, it is encouraged that Map implementations override this test with one that
   * checks the format matches any format defined in its API. This default implementation just
   * verifies that the toString() method does not return null.
   */
  public void testMapToString() {
    resetEmpty();
    assertTrue("Empty map toString() should not return null", map.toString() != null);
    verify();

    resetFull();
    assertTrue("Empty map toString() should not return null", map.toString() != null);
    verify();
  }

  /** Tests Map.put(Object, Object) */
  public void testMapPut() {
    if (!isAddRemoveModifiable()) {
      return;
    }

    resetEmpty();

    Object[] keys = getSampleKeys();
    Object[] values = getSampleValues();
    Object[] newValues = getNewSampleValues();

    for (int i = 0; i < keys.length; i++) {
      Object o = map.put(keys[i], values[i]);
      confirmed.put(keys[i], values[i]);
      verify();
      assertTrue("First map.put should return null", o == null);
      assertTrue("Map should contain key after put", map.containsKey(keys[i]));
      assertTrue("Map should contain value after put", map.containsValue(values[i]));
    }

    for (int i = 0; i < keys.length; i++) {
      Object o = map.put(keys[i], newValues[i]);
      confirmed.put(keys[i], newValues[i]);
      verify();
      assertEquals("Second map.put should return previous value", values[i], o);
      assertTrue("Map should still contain key after put", map.containsKey(keys[i]));
      assertTrue("Map should contain new value after put", map.containsValue(newValues[i]));

      // if duplicates are allowed, we're not guarunteed that the value
      // no longer exists, so don't try checking that.
      if (!useDuplicateValues()) {
        assertTrue(
            "Map should not contain old value after second put", !map.containsValue(values[i]));
      }
    }
  }

  /** Tests Map.putAll(Collection) */
  public void testMapPutAll() {
    if (!isAddRemoveModifiable()) {
      return;
    }

    resetEmpty();

    Map m2 = makeFullMap();

    map.putAll(m2);
    confirmed.putAll(m2);
    verify();

    resetEmpty();

    m2 = new HashMap();
    Object[] keys = getSampleKeys();
    Object[] values = getSampleValues();
    for (int i = 0; i < keys.length; i++) {
      m2.put(keys[i], values[i]);
    }

    map.putAll(m2);
    confirmed.putAll(m2);
    verify();
  }

  /** Tests Map.remove(Object) */
  public void testMapRemove() {
    if (!isAddRemoveModifiable()) {
      return;
    }

    resetEmpty();

    Object[] keys = getSampleKeys();
    Object[] values = getSampleValues();
    for (int i = 0; i < keys.length; i++) {
      Object o = map.remove(keys[i]);
      assertTrue("First map.remove should return null", o == null);
    }
    verify();

    resetFull();

    for (int i = 0; i < keys.length; i++) {
      Object o = map.remove(keys[i]);
      confirmed.remove(keys[i]);
      verify();

      assertEquals("map.remove with valid key should return value", values[i], o);
    }

    Object[] other = getOtherKeys();

    resetFull();
    int size = map.size();
    for (int i = 0; i < other.length; i++) {
      Object o = map.remove(other[i]);
      assertEquals("map.remove for nonexistent key should return null", o, null);
      assertEquals("map.remove for nonexistent key should not " + "shrink map", size, map.size());
    }
    verify();
  }

  public void testFailFastEntrySet() {
    if (!isAddRemoveModifiable()) {
      return;
    }
    if (!isFailFastExpected()) {
      return;
    }
    resetFull();
    Iterator<Map.Entry> it = map.entrySet().iterator();
    final Map.Entry val = it.next();
    map.remove(val.getKey());
    try {
      it.next();
      fail();
    } catch (ConcurrentModificationException expected) {
    }

    resetFull();
    it = map.entrySet().iterator();
    it.next();
    map.clear();
    try {
      it.next();
      fail();
    } catch (ConcurrentModificationException expected) {
    }
  }

  public void testFailFastKeySet() {
    if (!isAddRemoveModifiable()) {
      return;
    }
    if (!isFailFastExpected()) {
      return;
    }
    resetFull();
    Iterator it = map.keySet().iterator();
    final Object val = it.next();
    map.remove(val);
    try {
      it.next();
      fail();
    } catch (ConcurrentModificationException expected) {
    }

    resetFull();
    it = map.keySet().iterator();
    it.next();
    map.clear();
    try {
      it.next();
      fail();
    } catch (ConcurrentModificationException expected) {
    }
  }

  public void testFailFastValues() {
    if (!isAddRemoveModifiable()) {
      return;
    }
    if (!isFailFastExpected()) {
      return;
    }
    resetFull();
    Iterator it = map.values().iterator();
    it.next();
    map.remove(map.keySet().iterator().next());
    try {
      it.next();
      fail();
    } catch (ConcurrentModificationException expected) {
    }

    resetFull();
    it = map.values().iterator();
    it.next();
    map.clear();
    try {
      it.next();
      fail();
    } catch (ConcurrentModificationException expected) {
    }
  }

  /**
   * Utility methods to create an array of Map.Entry objects out of the given key and value arrays.
   *
   * <p>
   *
   * @param keys the array of keys
   * @param values the array of values
   * @return an array of Map.Entry of those keys to those values
   */
  private Map.Entry[] makeEntryArray(Object[] keys, Object[] values) {
    Map.Entry[] result = new Map.Entry[keys.length];
    for (int i = 0; i < keys.length; i++) {
      result[i] = new DefaultMapEntry(keys[i], values[i]);
    }
    return result;
  }

  class TestMapEntrySet extends TestSet {
    public TestMapEntrySet() {
      super("");
    }

    // Have to implement manually; entrySet doesn't support addAll
    @Override
    protected Object[] getFullElements() {
      Object[] k = getSampleKeys();
      Object[] v = getSampleValues();
      return makeEntryArray(k, v);
    }

    // Have to implement manually; entrySet doesn't support addAll
    @Override
    protected Object[] getOtherElements() {
      Object[] k = getOtherKeys();
      Object[] v = getOtherValues();
      return makeEntryArray(k, v);
    }

    @Override
    protected Set makeEmptySet() {
      return makeEmptyMap().entrySet();
    }

    @Override
    protected Set makeFullSet() {
      return makeFullMap().entrySet();
    }

    @Override
    protected boolean isAddSupported() {
      // Collection views don't support add operations.
      return false;
    }

    @Override
    protected boolean isRemoveSupported() {
      // Entry set should only support remove if map does
      return isAddRemoveModifiable();
    }

    @Override
    protected void resetFull() {
      TestMap.this.resetFull();
      collection = map.entrySet();
      TestMapEntrySet.this.confirmed = TestMap.this.confirmed.entrySet();
    }

    @Override
    protected void resetEmpty() {
      TestMap.this.resetEmpty();
      collection = map.entrySet();
      TestMapEntrySet.this.confirmed = TestMap.this.confirmed.entrySet();
    }

    @Override
    protected void verify() {
      super.verify();
      TestMap.this.verify();
    }
  }

  class TestMapKeySet extends TestSet {
    public TestMapKeySet() {
      super("");
    }

    @Override
    protected Object[] getFullElements() {
      return getSampleKeys();
    }

    @Override
    protected Object[] getOtherElements() {
      return getOtherKeys();
    }

    @Override
    protected Set makeEmptySet() {
      return makeEmptyMap().keySet();
    }

    @Override
    protected Set makeFullSet() {
      return makeFullMap().keySet();
    }

    @Override
    protected boolean isAddSupported() {
      return false;
    }

    @Override
    protected boolean isRemoveSupported() {
      return isAddRemoveModifiable();
    }

    @Override
    protected void resetEmpty() {
      TestMap.this.resetEmpty();
      collection = map.keySet();
      TestMapKeySet.this.confirmed = TestMap.this.confirmed.keySet();
    }

    @Override
    protected void resetFull() {
      TestMap.this.resetFull();
      collection = map.keySet();
      TestMapKeySet.this.confirmed = TestMap.this.confirmed.keySet();
    }

    @Override
    protected void verify() {
      super.verify();
      TestMap.this.verify();
    }
  }

  class TestMapValues extends TestCollection {
    public TestMapValues() {}

    @Override
    protected Object[] getFullElements() {
      return getSampleValues();
    }

    @Override
    protected Object[] getOtherElements() {
      return getOtherValues();
    }

    @Override
    protected Collection makeCollection() {
      return makeEmptyMap().values();
    }

    @Override
    protected Collection makeFullCollection() {
      return makeFullMap().values();
    }

    @Override
    protected boolean isAddSupported() {
      return false;
    }

    @Override
    protected boolean isRemoveSupported() {
      return isAddRemoveModifiable();
    }

    @Override
    protected boolean areEqualElementsDistinguishable() {
      // equal values are associated with different keys, so they are
      // distinguishable.
      return true;
    }

    @Override
    protected Collection makeConfirmedCollection() {
      // never gets called, reset methods are overridden
      return null;
    }

    @Override
    protected Collection makeConfirmedFullCollection() {
      // never gets called, reset methods are overridden
      return null;
    }

    @Override
    protected void resetFull() {
      TestMap.this.resetFull();
      collection = map.values();
      TestMapValues.this.confirmed = TestMap.this.confirmed.values();
    }

    @Override
    protected void resetEmpty() {
      TestMap.this.resetEmpty();
      collection = map.values();
      TestMapValues.this.confirmed = TestMap.this.confirmed.values();
    }

    @Override
    protected void verify() {
      super.verify();
      TestMap.this.verify();
    }

    // TODO: should test that a remove on the values collection view
    // removes the proper mapping and not just any mapping that may have
    // the value equal to the value returned from the values iterator.
  }

  /**
   * Resets the {@link #map}, {@link #entrySet}, {@link #keySet}, {@link #collectionValues} and
   * {@link #confirmed} fields to empty.
   */
  protected void resetEmpty() {
    this.map = makeEmptyMap();
    views();
    this.confirmed = makeConfirmedMap();
  }

  /**
   * Resets the {@link #map}, {@link #entrySet}, {@link #keySet}, {@link #collectionValues} and
   * {@link #confirmed} fields to full.
   */
  protected void resetFull() {
    this.map = makeFullMap();
    views();
    this.confirmed = makeConfirmedMap();
    Object[] k = getSampleKeys();
    Object[] v = getSampleValues();
    for (int i = 0; i < k.length; i++) {
      confirmed.put(k[i], v[i]);
    }
  }

  /** Resets the collection view fields. */
  private void views() {
    this.keySet = map.keySet();
    this.collectionValues = map.values();
    this.entrySet = map.entrySet();
  }

  /**
   * Verifies that {@link #map} is still equal to {@link #confirmed}. This method checks that the
   * map is equal to the HashMap, <I>and</I> that the map's collection views are still equal to the
   * HashMap's collection views. An <Code>equals</Code> test is done on the maps and their
   * collection views; their size and <Code>isEmpty</Code> results are compared; their hashCodes are
   * compared; and <Code>containsAll</Code> tests are run on the collection views.
   */
  protected void verify() {
    verifyMap();
    verifyEntrySet();
    verifyKeySet();
  }

  protected void verifyMap() {
    int size = confirmed.size();
    boolean empty = confirmed.isEmpty();
    assertEquals("Map should be same size as HashMap", size, map.size());
    assertEquals("Map should be empty if HashMap is", empty, map.isEmpty());
    assertEquals("hashCodes should be the same", confirmed.hashCode(), map.hashCode());
    // this fails for LRUMap because confirmed.equals() somehow modifies
    // map, causing concurrent modification exceptions.
    // assertEquals("Map should still equal HashMap", confirmed, map);
    // this works though and performs the same verification:
    assertTrue("Map should still equal HashMap", map.equals(confirmed));
    // TODO: this should really be rexamined to figure out why LRU map
    // behaves like it does (the equals shouldn't modify since all accesses
    // by the confirmed collection should be through an iterator, thus not
    // causing LRUMap to change).
  }

  protected void verifyEntrySet() {
    int size = confirmed.size();
    boolean empty = confirmed.isEmpty();
    assertEquals("entrySet should be same size as HashMap's", size, entrySet.size());
    assertEquals("entrySet should be empty if HashMap is", empty, entrySet.isEmpty());
    assertTrue(
        "entrySet should contain all HashMap's elements",
        entrySet.containsAll(confirmed.entrySet()));
    assertEquals(
        "entrySet hashCodes should be the same",
        confirmed.entrySet().hashCode(),
        entrySet.hashCode());
    assertEquals("Map's entry set should still equal HashMap's", confirmed.entrySet(), entrySet);
  }

  protected void verifyKeySet() {
    int size = confirmed.size();
    boolean empty = confirmed.isEmpty();
    assertEquals("keySet should be same size as HashMap's", size, keySet.size());
    assertEquals("keySet should be empty if HashMap is", empty, keySet.isEmpty());
    assertTrue(
        "keySet should contain all HashMap's elements", keySet.containsAll(confirmed.keySet()));
    assertEquals(
        "keySet hashCodes should be the same", confirmed.keySet().hashCode(), keySet.hashCode());
    assertEquals("Map's key set should still equal HashMap's", confirmed.keySet(), keySet);
  }
}
