//CHECKSTYLE_OFF
/*
 * 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.
 */
package com.google.gwt.i18n;

import junit.framework.TestCase;

import org.apache.commons.collections.DefaultMapEntry;
import org.apache.commons.collections.TestCollection;
import org.apache.commons.collections.TestSet;

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * 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 implementation 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 #isRemoveModifiable()}
 * <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>
 * 
 * @author Michael Smith
 * @author Rodney Waldhoff
 * @author Paul Jack
 * @version $Id: TestMap.java,v 1.20.2.1 2004/05/22 12:14:05 scolebourne Exp $
 */
public abstract class TestMap extends TestCase {

  // 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 abstract boolean isRemoveModifiable();

  /**
   * 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 = new Object[]{
      "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 = new Object[]{
      "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 = new Object[]{
      (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);

        assertTrue("NullPointerException on null key, but "
          + "useNullKey is not overridden to return false.", keys[i] == null
          || !useNullKey());

        assertTrue("NullPointerException on null value, but "
          + "useNullValue is not overridden to return false.",
          values[i] == null || !useNullValue());

        assertTrue("Unknown reason for NullPointer.", false);
      }
    }
    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();

  /**
   * 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;
  }

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

  /**
   * 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();

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

    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 #isRemoveModifiable() 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 (!isRemoveModifiable())
      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 (!isRemoveModifiable())
      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 (!isRemoveModifiable())
      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 (!isRemoveModifiable())
      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();
  }

  /**
   * 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
    protected Object[] getFullElements() {
      Object[] k = getSampleKeys();
      Object[] v = getSampleValues();
      return makeEntryArray(k, v);
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

    protected boolean isAddSupported() {
      return false;
    }

    protected boolean isRemoveSupported() {
      return isRemoveModifiable();
    }

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

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

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

  class TestMapValues extends TestCollection {
    public TestMapValues() {

    }

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

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

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

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

    protected boolean isAddSupported() {
      return false;
    }

    protected boolean isRemoveSupported() {
      return isRemoveModifiable();
    }

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

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

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

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

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

    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 = new HashMap();
  }

  /**
   * 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 = new HashMap();
    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()));
    // Figure out why the hashcodes are not working for constant map
    // 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);
  }

}
