/*
 * Copyright 2008 Google Inc.
 *
 * 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.emultest.java.util;

import com.google.gwt.testing.TestUtils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.NavigableSet;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

/**
 * Tests <code>TreeSet</code>.
 *
 * <p>TODO(jat): this whole structure needs work. Ideally we would port a new Apache collections
 * test to GWT, but that is not an insignificant amount of work.
 *
 * @param <E> The key type for the underlying TreeSet
 */
abstract class TreeSetTest<E extends Comparable<E>> extends TestSet {

  /**
   * Verify a Set is explicitly and implicitly empty.
   *
   * @param set
   */
  private static <E> void _assertEmpty(Set<E> set) {
    assertNotNull(set);
    assertTrue(set.isEmpty());
    assertEquals(0, set.size());
  }

  /**
   * Verify that two Collections are deeply equivalent. Some of the Sets that need to be verified do
   * not implement a sensible equals method (TreeSet.values for example).
   *
   * @param expected
   * @param actual
   */
  private static <T> void _assertEquals(Collection<T> expected, Collection<T> actual) {
    // verify equivalence using collection interface
    assertEquals(expected.isEmpty(), actual.isEmpty());
    assertEquals(expected.size(), actual.size());
    assertTrue(expected.containsAll(actual));
    assertTrue(actual.containsAll(expected));
    for (T expectedValue : expected) {
      assertTrue(actual.contains(expectedValue));
    }
    for (T actualValue : actual) {
      assertTrue(expected.contains(actualValue));
    }
  }

  /**
   * Verify that two SortedMaps are deeply equivalent.
   *
   * @param expected
   * @param actual
   */
  private static <E> void _assertEquals(SortedSet<E> expected, SortedSet<E> actual) {
    _assertEquals(expected, (Set<E>) actual);

    // verify the order of the associated collections
    assertEquals(expected.toArray(), actual.toArray());
  }

  private static <E> Collection<E> asCollection(Iterator<E> it) {
    List<E> list = new ArrayList<E>();
    while (it.hasNext()) {
      list.add(it.next());
    }
    return list;
  }

  private static <E> Collection<E> reverseCollection(Collection<E> c) {
    List<E> reversedCollection = new ArrayList<E>(c);
    Collections.reverse(reversedCollection);
    return reversedCollection;
  }

  /** comparator used when creating the SortedSet. */
  private Comparator<E> comparator = null;

  private final boolean isAddSupported = true;
  private final boolean isClearSupported = true;
  private final boolean isNullKeySupported = true;
  private final boolean isPutAllSupported = true;
  private final boolean isRemoveSupported = true;

  public TreeSetTest() {
    super("TreeSetTest");
  }

  @Override
  public String getModuleName() {
    return "com.google.gwt.emultest.EmulSuite";
  }

  /**
   * Test method for 'java.util.Set.add(Object)'.
   *
   * @see java.util.Set#put(Object)
   */
  public void testAdd() {
    // The _throwsUnsupportedOperationException version of this test will
    // verify that the method is not supported.
    if (isAddSupported) {
      Set<E> set = createSet();
      assertTrue(set.add(getKeys()[0]));
      assertFalse(set.isEmpty());
      assertEquals(1, set.size());
    }
  }

  /**
   * Test method for 'java.util.Set.add(Object)'.
   *
   * @see java.util.Set#add(Object)
   */
  public void testAdd_entries3() {
    // The _throwsUnsupportedOperationException version of this test will
    // verify that the method is not supported.
    if (isAddSupported) {
      // populate the set
      Set<E> set = createSet();
      set.add(getKeys()[0]);
      set.add(getKeys()[1]);
      set.add(getKeys()[2]);

      // test contents
      assertFalse(set.isEmpty());
      assertEquals(3, set.size());
      Collection<E> keys = set;
      // test contains all keys
      assertTrue(keys.contains(getKeys()[0]));
      assertTrue(keys.contains(getKeys()[1]));
      assertTrue(keys.contains(getKeys()[2]));
    }
  }

  /**
   * Test method for 'java.util.Set.add(Object)'.
   *
   * @see java.util.Set#add(Object)
   */
  public void testAdd_replace() {
    // The _throwsUnsupportedOperationException version of this test will
    // verify that the method is not supported.
    if (isAddSupported) {
      Set<E> set = createSet();
      assertTrue(set.add(getKeys()[0]));
      assertFalse(set.isEmpty());
      assertEquals(1, set.size());

      assertFalse(set.add(getKeys()[0]));
      assertEquals(1, set.size());
    }
  }

  /**
   * Test method for 'java.util.Set.add(Object)'.
   *
   * @see java.util.Set#add(Object)
   */
  @SuppressWarnings("unchecked")
  public void testAdd_throwsClassCastException_key() {
    // The _throwsUnsupportedOperationException version of this test will
    // verify that the method is not supported.
    if (isAddSupported) {
      Set<E> set = createSet();
      set.add(getKeys()[0]);
      try {
        Set untypedSet = set;
        untypedSet.add(getConflictingKey());
        assertTrue("CCE expected in Development Mode", !TestUtils.isJvm());
      } catch (ClassCastException e) {
        // expected outcome
      }
    }
  }

  /**
   * Test method for 'java.util.Set.add(Object)'.
   *
   * @see java.util.Set#add(Object)
   */
  @SuppressWarnings("unchecked")
  public void testAdd_throwsClassCastException_value() {
    // The _throwsUnsupportedOperationException version of this test will
    // verify that the method is not supported.
    if (isAddSupported) {
      Set<E> set = createSet();
      set.add(getKeys()[0]);

      Set untypedSet = set;
      untypedSet.add(getKeys()[1]);
      // You might think this should throw an exception here but, no. Makes
      // sense since the class cast is attributed to comparability of the
      // keys... generics really have nothing to do with it .
    }
  }

  /**
   * Test method for 'java.util.Set.add(Object)'.
   *
   * @see java.util.Set#add(Object)
   */
  public void testAdd_throwsUnsupportedOperationException() {
    if (!isAddSupported) {
      Set<E> set = createSet();
      try {
        set.add(getKeys()[0]);
        fail("expected exception");
      } catch (UnsupportedOperationException e) {
        // expected outcome
      }
    }
  }

  /**
   * Test method for 'java.util.Set.addAll(Map)'.
   *
   * @see java.util.Set#addAll(Map)
   */
  public void testAddAll() {
    // The _throwsUnsupportedOperationException version of this test will
    // verify that the method is not supported.
    if (isPutAllSupported) {
      Set<E> sourceSet = createSet();
      sourceSet.add(getKeys()[0]);
      sourceSet.add(getKeys()[1]);
      sourceSet.add(getKeys()[2]);

      Set<E> destSet = createSet();
      destSet.addAll(sourceSet);
      // Make sure that the data is copied correctly
      _assertEquals(sourceSet, destSet);
    }
  }

  /**
   * Test method for 'java.util.Set.addAll(Map)'.
   *
   * @see java.util.Set#addAll(Map)
   */
  public void testAddAll_addEntries() {
    // The _throwsUnsupportedOperationException version of this test will
    // verify that the method is not supported.
    if (isPutAllSupported) {
      Set<E> sourceMap = createSet();
      sourceMap.add(getKeys()[0]);

      Set<E> destSet = createSet();
      destSet.addAll(sourceMap);
      // Verify that entries get added.
      sourceMap.add(getKeys()[1]);
      destSet.addAll(sourceMap);
      _assertEquals(sourceMap, destSet);
    }
  }

  /**
   * Test method for 'java.util.Set.addAll(Map)'.
   *
   * @see java.util.Set#addAll(Map)
   */
  public void testAddAll_emptyMap() {
    // The _throwsUnsupportedOperationException version of this test will
    // verify that the method is not supported.
    if (isPutAllSupported) {
      Set<E> sourceSet = createSet();
      sourceSet.add(getKeys()[0]);

      Set<E> destSet = createSet();
      destSet.addAll(sourceSet);
      // Verify that putting an empty set does not clear.
      destSet.addAll(createSet());
      _assertEquals(sourceSet, destSet);
    }
  }

  /**
   * Test method for 'java.util.Set.addAll(Map)'.
   *
   * @see java.util.Set#addAll(Map)
   */
  public void testAddAll_overwrite() {
    // The _throwsUnsupportedOperationException version of this test will
    // verify that the method is not supported.
    if (isPutAllSupported) {
      Set<E> sourceSet = createSet();
      sourceSet.add(getKeys()[0]);

      Set<E> destSet = createSet();
      destSet.addAll(sourceSet);
      // Verify that entries get replaced.
      sourceSet.add(getKeys()[0]);
      destSet.addAll(sourceSet);
      _assertEquals(sourceSet, destSet);
    }
  }

  /**
   * Test method for 'java.util.Set.addAll(Map)'.
   *
   * @see java.util.Set#addAll(Map)
   */
  @SuppressWarnings("ModifyingCollectionWithItself")
  public void testAddAll_self() {
    // The _throwsUnsupportedOperationException version of this test will
    // verify that the method is not supported.
    if (isPutAllSupported) {
      Set<E> sourceSet = createSet();
      sourceSet.add(getKeys()[0]);
      sourceSet.addAll(sourceSet);
      // verify putAll with self succeeds and has no effect.
      assertEquals(1, sourceSet.size());
      assertEquals(getKeys()[0], sourceSet.iterator().next());
    }
  }

  /**
   * Test method for 'java.util.Set.addAll(Map)'.
   *
   * @see java.util.Set#addAll(Map)
   */
  @SuppressWarnings("unchecked")
  public void testAddAll_throwsClassCastException() {
    // The _throwsUnsupportedOperationException version of this test will
    // verify that the method is not supported.
    if (isPutAllSupported) {
      Set sourceSet = new HashSet();
      sourceSet.add(getConflictingKey());

      Set<E> destSet = createSet();
      destSet.add(getKeys()[0]);
      try {
        // This throws in dev mode because we're putting a second entry in
        // the set and TreeSet calls the compare method to order them.
        destSet.addAll(sourceSet);
        assertTrue("CCE expected in Development Mode", !TestUtils.isJvm());
      } catch (ClassCastException e) {
        // expected outcome
      }
    }
  }

  /**
   * Test method for 'java.util.Set.addAll(Map)'.
   *
   * @see java.util.Set#addAll(Map)
   */
  public void testAddAll_throwsNullPointerException() {
    // The _throwsUnsupportedOperationException version of this test will
    // verify that the method is not supported.
    if (isPutAllSupported) {
      Set<E> set = createSet();
      try {
        set.addAll(null);
        fail("expected exception");
      } catch (NullPointerException e) {
        // expected outcome
      }
    }
  }

  /**
   * Test method for 'java.util.Set.addAll(Map)'.
   *
   * @see java.util.Set#addAll(Map)
   */
  public void testAddAll_throwsUnsupportedOperationException() {
    Set<E> set = createSet();
    if (!isPutAllSupported) {
      try {
        set.addAll(createSet());
        fail("expected exception");
      } catch (UnsupportedOperationException e) {
        // expected outcome
      }
    }
  }

  public void testCeiling() {
    NavigableSet<E> set = createNavigableSet();

    set.add(getKeys()[0]);
    assertEquals(getKeys()[0], set.ceiling(getKeys()[0]));
    assertEquals(getKeys()[0], set.ceiling(getLessThanMinimumKey()));
    assertEquals(set.toArray()[0], set.ceiling(getLessThanMinimumKey()));

    set.add(getKeys()[1]);
    assertEquals(getKeys()[0], set.ceiling(getLessThanMinimumKey()));
    assertEquals(getKeys()[0], set.ceiling(getKeys()[0]));
    assertEquals(getKeys()[1], set.ceiling(getKeys()[1]));
    assertEquals(null, set.ceiling(getGreaterThanMaximumKey()));
  }

  /**
   * Test method for 'java.util.Set.clear()'.
   *
   * @see java.util.Set#clear()
   */
  public void testClear() {
    // The _throwsUnsupportedOperationException version of this test will
    // verify that the method is not supported.
    if (isClearSupported) {
      // Execute this test only if supported.
      Set<E> set = createSet();
      set.add(getKeys()[0]);
      assertFalse(set.isEmpty());
      set.clear();
      _assertEmpty(set);
    }
  }

  /**
   * Test method for 'java.util.Set.clear()'.
   *
   * @see java.util.Set#clear()
   */
  public void testClear_throwsUnsupportedOperationException() {
    Set<E> set = createSet();
    if (!isClearSupported) {
      try {
        set.clear();
        fail("expected exception");
      } catch (UnsupportedOperationException e) {
        // expected outcome
      }
    }
  }

  /**
   * Test method for 'java.util.SortedSet.comparator()'.
   *
   * @see java.util.SortedSet#comparator()
   */
  public void testComparator() {
    SortedSet<E> sortedSet = createNavigableSet();
    if (isNaturalOrder()) {
      assertEquals(null, sortedSet.comparator());
    } else {
      assertEquals(getComparator(), sortedSet.comparator());
    }
  }

  /**
   * Test method for default constructor.
   *
   * @see java.util.TreeSet#TreeSet()
   */
  public void testConstructor() {
    TreeSet<E> treeSet = new TreeSet<E>();
    _assertEmpty(treeSet);
  }

  /**
   * Test method for 'java.util.TreeSet.TreeSet(Comparator)'.
   *
   * @see java.util.TreeSet#TreeSet(Comparator)
   */
  public void testConstructor_comparator() {
    TreeSet<E> treeSet = new TreeSet<E>(getComparator());
    _assertEmpty(treeSet);
    if (isNaturalOrder()) {
      assertNull(treeSet.comparator());
    } else {
      assertSame(getComparator(), treeSet.comparator());
    }
  }

  /**
   * Test method for 'java.util.TreeSet.TreeSet(Set)'.
   *
   * @see java.util.TreeSet#TreeSet(Set)
   */
  public void testConstructor_Set() {
    // The source set should be just a Map. Not a sorted set.
    Set<E> sourceMap = new HashSet<E>();

    // populate the source set
    sourceMap.add(getKeys()[0]);
    sourceMap.add(getKeys()[1]);
    sourceMap.add(getKeys()[2]);

    TreeSet<E> copyConstructed = new TreeSet<E>(sourceMap);
    _assertEquals(sourceMap, copyConstructed);
  }

  /**
   * Test method for 'java.util.TreeSet.TreeSet(Set)'.
   *
   * @see java.util.TreeSet#TreeSet(Set)
   */
  @SuppressWarnings("unchecked")
  public void testConstructor_Set_rawType() {
    Set sourceSet = new HashSet();
    sourceSet.add(getConflictingKey());
    // Raw types can be used to defeat the type system, and this will work
    // so long as the key is Comparable and there's only one entry (so compare()
    // won't be called.)
    new TreeSet<E>(sourceSet);
  }

  /**
   * Test method for 'java.util.TreeSet.TreeSet(Set)'.
   *
   * @see java.util.TreeSet#TreeSet(Set)
   */
  public void testConstructor_Set_throwsNullPointerException() {
    try {
      new TreeSet<E>((Set<E>) null);
      fail("expected exception");
    } catch (NullPointerException e) {
      // expected outcome
    }
  }

  /**
   * Test method for 'java.util.TreeSet.TreeSet(SortedSet).
   *
   * @see java.util.TreeSet#TreeSet(SortedSet)
   */
  public void testConstructor_SortedMap_throwsNullPointerException() {
    try {
      new TreeSet<E>((SortedSet<E>) null);
      fail("expected exception");
    } catch (NullPointerException e) {
      // expected outcome
    }
  }

  /**
   * Test method for 'java.util.TreeSet.TreeSet(SortedSet)'.
   *
   * @see java.util.TreeSet#TreeSet(SortedSet)
   */
  public void testConstructor_SortedSet() {
    SortedSet<E> sourceMap = new TreeSet<E>();
    _assertEmpty(sourceMap);

    // populate the source set
    sourceMap.add(getKeys()[0]);
    sourceMap.add(getKeys()[1]);
    sourceMap.add(getKeys()[2]);

    TreeSet<E> copyConstructed = new TreeSet<E>(sourceMap);
    _assertEquals(sourceMap, copyConstructed);
  }

  /**
   * Test method for 'java.util.Set.contains(Object)'. *
   *
   * @see java.util.Set#contains(Object)
   */
  public void testContains() {
    Set<E> set = createSet();
    assertFalse(set.contains(getKeys()[0]));
    assertTrue(set.add(getKeys()[0]));
    assertEquals(1, set.size());
    assertTrue(set.contains(getKeys()[0]));
    assertFalse(set.contains(getKeys()[1]));
  }

  /**
   * Test method for 'java.util.Set.contains(Object)'.
   *
   * @see java.util.Set#contains(Object)
   */
  public void testContains_throwsClassCastException() {
    Set<E> set = createSet();
    set.add(getKeys()[0]);
    try {
      set.contains(getConflictingKey());
      assertTrue("CCE expected in Development Mode", !TestUtils.isJvm());
    } catch (ClassCastException e) {
      // expected outcome
    }
  }

  /**
   * Test method for 'java.util.Set.contains(Object)'.
   *
   * @see java.util.Set#contains(Object)
   */
  public void testContains_throwsNullPointerException() {
    Set<E> set = createSet();
    if (isNaturalOrder() && !isNullKeySupported) {
      try {
        set.contains(null);
        fail("expected exception");
      } catch (NullPointerException e) {
        // expected outcome
      }
    }
  }

  public void testDescendingIterator() {
    NavigableSet<E> set = createNavigableSet();
    set.add(getKeys()[0]);

    Iterator<E> descendingIterator = set.descendingIterator();
    _assertEquals(set, reverseCollection(asCollection(descendingIterator)));

    set.add(getKeys()[1]);
    set.add(getKeys()[2]);
    descendingIterator = set.descendingIterator();
    _assertEquals(set, reverseCollection(asCollection(descendingIterator)));

    descendingIterator = set.descendingIterator();
    while (descendingIterator.hasNext()) {
      descendingIterator.next();
      descendingIterator.remove();
    }
    assertEquals(0, set.size());
  }

  public void testDescendingSet() {
    NavigableSet<E> set = createNavigableSet();
    set.add(getKeys()[0]);

    NavigableSet<E> descendingSet = set.descendingSet();
    _assertEquals(descendingSet, descendingSet);
    _assertEquals(set.descendingSet(), descendingSet);

    set.add(getKeys()[1]);
    set.add(getKeys()[2]);
    _assertEquals(reverseCollection(set), descendingSet);
    _assertEquals(set, descendingSet.descendingSet());

    set.remove(getKeys()[1]);
    _assertEquals(reverseCollection(set), descendingSet);

    descendingSet.add(getKeys()[0]);
    _assertEquals(reverseCollection(set), descendingSet);

    descendingSet.remove(getKeys()[1]);
    _assertEquals(reverseCollection(set), descendingSet);

    descendingSet.clear();
    assertEquals(0, descendingSet.size());
    _assertEquals(set, descendingSet);
  }

  /**
   * Test method for 'java.util.Object.equals(Object)'.
   *
   * @see java.util.Set#equals(Object)
   */
  public void testEquals() {
    Set<E> set0 = createSet();
    Set<E> set1 = createSet();
    assertTrue(set0.equals(set1));
    set0.add(getKeys()[0]);
    set1.add(getKeys()[0]);
    assertTrue(set0.equals(set0));
    assertTrue(set0.equals(set1));
    set0.add(getKeys()[1]);
    assertFalse(set0.equals(set1));
  }

  /**
   * Test method for 'java.util.SortedSet.first()'.
   *
   * @see java.util.SortedSet#first()
   */
  public void testFirst() {
    SortedSet<E> sortedSet = createNavigableSet();
    // test with a single entry set
    sortedSet.add(getKeys()[0]);
    assertEquals(getKeys()[0], sortedSet.first());
    // is it consistent with other methods
    assertEquals(sortedSet.toArray()[0], sortedSet.first());
    assertEquals(getKeys()[0], sortedSet.last());
    assertEquals(sortedSet.last(), sortedSet.first());

    // test with two entry set
    sortedSet.add(getKeys()[1]);
    assertEquals(getKeys()[0], sortedSet.first());
    assertFalse(getKeys()[1].equals(sortedSet.first()));
    // is it consistent with other methods
    assertEquals(sortedSet.toArray()[0], sortedSet.first());
    assertFalse(getKeys()[0].equals(sortedSet.last()));
    assertFalse(sortedSet.last().equals(sortedSet.first()));
  }

  /**
   * Test method for 'java.util.SortedSet.first()'.
   *
   * @see java.util.SortedSet#first()
   */
  public void testFirstKey_throwsNoSuchElementException() {
    SortedSet<E> sortedSet = createNavigableSet();
    // test with no entries
    try {
      sortedSet.first();
      fail("expected exception");
    } catch (NoSuchElementException e) {
      // expected outcome
    }
  }

  public void testFloor() {
    NavigableSet<E> set = createNavigableSet();

    set.add(getKeys()[0]);
    assertEquals(null, set.floor(getLessThanMinimumKey()));
    assertEquals(getKeys()[0], set.floor(getKeys()[0]));
    assertEquals(getKeys()[0], set.floor(getKeys()[1]));
    assertEquals(getKeys()[0], set.floor(getGreaterThanMaximumKey()));
    assertEquals(set.toArray()[0], set.floor(getKeys()[1]));

    set.add(getKeys()[1]);
    assertEquals(null, set.floor(getLessThanMinimumKey()));
    assertEquals(getKeys()[0], set.floor(getKeys()[0]));
    assertEquals(getKeys()[1], set.floor(getKeys()[1]));
    assertEquals(getKeys()[1], set.floor(getGreaterThanMaximumKey()));
  }

  /**
   * Test method for 'java.lang.Object.hashCode()'.
   *
   * @see java.util.Set#hashCode()
   */
  public void testHashCode() {
    Set<E> set0 = createSet();
    Set<E> set1 = createSet();

    int hashCode0 = set0.hashCode();
    int hashCode1 = set1.hashCode();
    assertTrue("empty maps have different hash codes", hashCode0 == hashCode1);

    // Check that hashCode changes
    set0.add(getKeys()[0]);
    hashCode0 = set0.hashCode();
    assertTrue("hash code didn't change", hashCode0 != hashCode1);

    Set<String> set2 = new TreeSet<String>();
    set2.add("");
    Set<Integer> set3 = new TreeSet<Integer>();
    set3.add(0);
    int hashCode2 = set2.hashCode();
    int hashCode3 = set3.hashCode();
    assertEquals("empty string/0 hash codes not the same", hashCode2, hashCode3);
  }

  /**
   * Test method for 'java.util.SortedSet.headSet(Object, Object)'.
   *
   * @see java.util.SortedSet#headSet(Object)
   */
  @SuppressWarnings("unchecked")
  public void testHeadMap_throwsClassCastException() {
    SortedSet sortedSet = createNavigableSet();
    sortedSet.add(getKeys()[0]);
    if (isNaturalOrder()) {
      // TODO Why does this succeed with natural ordering when subSet doesn't?
      sortedSet.headSet(getConflictingKey());
    } else {
      try {
        sortedSet.headSet(getConflictingKey());
        assertTrue("CCE expected in Development Mode", !TestUtils.isJvm());
      } catch (ClassCastException e) {
        // expected outcome
      }
    }
  }

  /**
   * Test method for 'java.util.SortedSet.headSet(Object)' and
   * 'java.util.NavigableSet.headSet(Object, boolean)'.
   *
   * @see java.util.SortedSet#headSet(Object)
   * @see java.util.NavigableSet#headSet(Object, boolean)
   */
  public void testHeadSet() {
    // test with no entries
    NavigableSet<E> set = createNavigableSet();
    assertNotNull(set.headSet(getKeys()[0]));
    assertNotNull(set.headSet(getKeys()[0], false));
    assertNotNull(set.headSet(getKeys()[0], true));
  }

  /**
   * Test method for 'java.util.SortedSet.headSet(Object)' and
   * 'java.util.NavigableSet.headSet(Object, boolean)'.
   *
   * @see java.util.SortedSet#headSet(Object)
   * @see java.util.NavigableSet#headSet(Object, boolean)
   */
  public void testHeadSet_entries0_size() {
    // test with no entries
    NavigableSet<E> set = createNavigableSet();
    assertEquals(0, set.headSet(getKeys()[0]).size());
    assertEquals(0, set.headSet(getKeys()[0], false).size());
    assertEquals(0, set.headSet(getKeys()[0], true).size());
  }

  /**
   * Test method for 'java.util.SortedSet.headSet(Object)' and
   * 'java.util.NavigableSet.headSet(Object, boolean)'.
   *
   * @see java.util.SortedSet#headSet(Object)
   * @see java.util.NavigableSet#headSet(Object, boolean)
   */
  public void testHeadSet_entries1() {
    NavigableSet<E> set = createNavigableSet();
    // test with a single entry set
    set.add(getKeys()[0]);

    assertEquals(0, set.headSet(getKeys()[0]).size());
    assertEquals(0, set.headSet(getKeys()[0], false).size());
    assertEquals(1, set.headSet(getKeys()[0], true).size());
  }

  /**
   * Test method for 'java.util.SortedSet.headSet(Object)' and
   * 'java.util.NavigableSet.headSet(Object, boolean)'.
   *
   * @see java.util.SortedSet#headSet(Object)
   * @see java.util.NavigableSet#headSet(Object, boolean)
   */
  public void testHeadSet_entries2() {
    NavigableSet<E> set = createNavigableSet();
    // test with two entry set
    set.add(getKeys()[0]);
    set.add(getKeys()[1]);

    assertEquals(0, set.headSet(getKeys()[0]).size());
    assertEquals(1, set.headSet(getKeys()[1]).size());
    assertEquals(getKeys()[0], set.tailSet(getKeys()[0]).toArray()[0]);

    assertEquals(0, set.headSet(getKeys()[0], false).size());
    assertEquals(1, set.headSet(getKeys()[1], false).size());
    assertEquals(getKeys()[0], set.headSet(getKeys()[0], true).toArray()[0]);

    assertEquals(1, set.headSet(getKeys()[0], true).size());
    assertEquals(2, set.headSet(getKeys()[1], true).size());
    assertEquals(getKeys()[0], set.headSet(getKeys()[1], false).toArray()[0]);
    assertEquals(getKeys()[1], set.headSet(getKeys()[1], true).toArray()[1]);
    assertEquals(0, set.headSet(getKeys()[0], false).size());
    assertEquals(getKeys()[1], set.headSet(getKeys()[1], true).toArray()[1]);
  }

  public void testHigher() {
    NavigableSet<E> set = createNavigableSet();

    set.add(getKeys()[0]);
    assertEquals(null, set.higher(getKeys()[0]));
    assertEquals(getKeys()[0], set.higher(getLessThanMinimumKey()));
    assertEquals(set.toArray()[0], set.higher(getLessThanMinimumKey()));

    set.add(getKeys()[1]);
    assertEquals(getKeys()[0], set.higher(getLessThanMinimumKey()));
    assertEquals(getKeys()[1], set.higher(getKeys()[0]));
    assertEquals(null, set.higher(getKeys()[1]));
    assertEquals(null, set.higher(getGreaterThanMaximumKey()));
  }

  /**
   * Test method for 'java.util.Set.isEmpty()'. *
   *
   * @see java.util.Set#isEmpty()
   */
  public void testIsEmpty() {
    Set<E> sourceSet = createSet();
    Set<E> destSet = createSet();

    destSet.addAll(sourceSet);
    assertTrue(destSet.isEmpty());

    destSet.add(getKeys()[0]);
    assertFalse(destSet.isEmpty());

    destSet.remove(getKeys()[0]);
    assertTrue(destSet.isEmpty());
    assertEquals(0, destSet.size());
  }

  /**
   * Test method for 'java.util.SortedSet.last()'.
   *
   * @see java.util.SortedSet#last()
   */
  public void testLastKey() {
    SortedSet<E> sortedSet = createNavigableSet();

    // test with a single entry set
    sortedSet.add(getKeys()[0]);
    assertEquals(getKeys()[0], sortedSet.last());
    // is it consistent with other methods
    assertEquals(sortedSet.toArray()[0], sortedSet.last());
    assertEquals(getKeys()[0], sortedSet.first());
    assertEquals(sortedSet.first(), sortedSet.last());

    // test with two entry set
    sortedSet.add(getKeys()[1]);
    assertEquals(getKeys()[1], sortedSet.last());
    assertFalse(getKeys()[0].equals(sortedSet.last()));
    // is it consistent with other methods
    assertEquals(sortedSet.toArray()[1], sortedSet.last());
    assertEquals(getKeys()[0], sortedSet.first());
    assertFalse(sortedSet.first().equals(sortedSet.last()));
  }

  /**
   * Test method for 'java.util.SortedSet.last()'.
   *
   * @see java.util.SortedSet#last()
   */
  public void testLastKey_throwsNoSuchElementException() {
    SortedSet<E> sortedSet = createNavigableSet();
    // test with no entries
    try {
      sortedSet.last();
      fail("expected exception");
    } catch (NoSuchElementException e) {
      // expected outcome
    }
  }

  public void testLower() {
    NavigableSet<E> set = createNavigableSet();

    set.add(getKeys()[0]);
    assertEquals(null, set.lower(getLessThanMinimumKey()));
    assertEquals(null, set.lower(getKeys()[0]));
    assertEquals(getKeys()[0], set.lower(getKeys()[1]));
    assertEquals(getKeys()[0], set.lower(getGreaterThanMaximumKey()));
    assertEquals(set.toArray()[0], set.lower(getKeys()[1]));

    set.add(getKeys()[1]);
    assertEquals(null, set.lower(getLessThanMinimumKey()));
    assertEquals(null, set.lower(getKeys()[0]));
    assertEquals(getKeys()[0], set.lower(getKeys()[1]));
    assertEquals(getKeys()[1], set.lower(getGreaterThanMaximumKey()));
  }

  public void testPollFirst() {
    NavigableSet<E> set = createNavigableSet();

    assertNull(set.pollFirst());
    assertEquals(0, set.size());

    set.add(getKeys()[0]);
    assertEquals(getKeys()[0], set.pollFirst());
    assertEquals(0, set.size());

    set.add(getKeys()[0]);
    set.add(getKeys()[1]);
    assertEquals(getKeys()[0], set.pollFirst());
    assertEquals(1, set.size());
    assertEquals(getKeys()[1], set.pollFirst());
    assertEquals(0, set.size());
    assertNull(set.pollFirst());
  }

  public void testPollLast() {
    NavigableSet<E> set = createNavigableSet();

    assertNull(set.pollLast());
    assertEquals(0, set.size());

    set.add(getKeys()[0]);
    assertEquals(getKeys()[0], set.pollLast());
    assertEquals(0, set.size());

    set.add(getKeys()[0]);
    set.add(getKeys()[1]);
    assertEquals(getKeys()[1], set.pollLast());
    assertEquals(1, set.size());
    assertEquals(getKeys()[0], set.pollLast());
    assertEquals(0, set.size());
    assertNull(set.pollLast());
  }

  /**
   * Test method for 'java.util.Set.remove(Object)'.
   *
   * @see java.util.Set#remove(Object)
   */
  public void testRemove() {
    // The _throwsUnsupportedOperationException version of this test will
    // verify that the method is not supported.
    if (isRemoveSupported) {
      Set<E> set = createSet();

      assertFalse(set.remove(getKeys()[0]));
      assertTrue(set.add(getKeys()[0]));
      assertTrue(set.remove(getKeys()[0]));
      assertFalse(set.remove(getKeys()[0]));
    }
  }

  /**
   * Test method for 'java.util.Set.remove(Object)'.
   *
   * @see java.util.Set#remove(Object)
   */
  public void testRemove_throwsClassCastException() {
    // The _throwsUnsupportedOperationException version of this test will
    // verify that the method is not supported.
    if (isRemoveSupported) {
      Set<E> set = createSet();
      set.add(getKeys()[0]);
      try {
        set.remove(getConflictingKey());
        assertTrue("CCE expected in Development Mode", !TestUtils.isJvm());
      } catch (ClassCastException e) {
        // expected outcome
      }
    }
  }

  /**
   * Test method for 'java.util.Set.remove(Object)'.
   *
   * @see java.util.Set#remove(Object)
   */
  public void testRemove_throwsUnsupportedOperationException() {
    Set<E> set = createSet();
    if (!isRemoveSupported) {
      try {
        set.remove(getKeys()[0]);
        fail("expected exception");
      } catch (UnsupportedOperationException e) {
        // expected outcome
      }
    }
  }

  /**
   * Test method for 'java.util.Set.size()'.
   *
   * @see java.util.Set#size()
   */
  public void testSize() {
    Set<E> set = createSet();

    // Test size behavior on add
    set.add(getKeys()[0]);
    assertEquals(1, set.size());
    set.add(getKeys()[1]);
    assertEquals(2, set.size());
    set.add(getKeys()[2]);
    assertEquals(3, set.size());

    // Test size behavior on remove
    set.remove(getKeys()[0]);
    assertEquals(2, set.size());
    set.remove(getKeys()[1]);
    assertEquals(1, set.size());
    set.remove(getKeys()[2]);
    assertEquals(0, set.size());

    // Test size behavior on putAll
    set.add(getKeys()[0]);
    set.add(getKeys()[1]);
    set.add(getKeys()[2]);
    assertEquals(3, set.size());

    // Test size behavior on clear
    set.clear();
    _assertEmpty(set);
  }

  /**
   * Test method for 'java.util.SortedSet.subSet(Object, Object)'.
   *
   * @see java.util.SortedSet#subSet(Object, Object)
   */
  @SuppressWarnings("unchecked")
  public void testSubMap_throwsClassCastException() {
    SortedSet sortedSet = createNavigableSet();
    sortedSet.add(getKeys()[0]);
    try {
      sortedSet.subSet(getConflictingKey(), getKeys()[0]);
      assertTrue("CCE expected in Development Mode", !TestUtils.isJvm());
    } catch (IllegalArgumentException e) {
      // since we can't ensure CCEs in Production Mode, we may get IAE
      assertTrue("IllegalArgumentException in Development Mode", !TestUtils.isJvm());
    } catch (ClassCastException e) {
      // expected outcome
    }
    try {
      sortedSet.subSet(getKeys()[0], getConflictingKey());
      assertTrue("CCE expected in Development Mode", !TestUtils.isJvm());
    } catch (IllegalArgumentException e) {
      // since we can't ensure CCEs in Production Mode, we may get IAE
      assertTrue("IllegalArgumentException in Development Mode", !TestUtils.isJvm());
    } catch (ClassCastException e) {
      // expected outcome
    }
  }

  /**
   * Test method for 'java.util.SortedSet.subSet(Object, Object)'.
   *
   * @see java.util.SortedSet#subSet(Object, Object)
   */
  public void testSubMap_throwsIllegalArgumentException() {
    SortedSet<E> sortedSet = createNavigableSet();
    try {
      sortedSet.subSet(getGreaterThanMaximumKey(), getLessThanMinimumKey());
      fail("expected exception");
    } catch (IllegalArgumentException e) {
      // from key is greater than the to key
      // expected outcome
    }
  }

  /**
   * Test method for 'java.util.SortedSet.subSet(Object, Object)' and
   * 'java.util.NavigableSet.subSet(Object, boolean, Object, boolean)'.
   *
   * @see java.util.SortedSet#subSet(Object, Object)
   * @see java.util.NavigableSet#subSet(Object, boolean, Object, boolean)
   */
  public void testSubSet() {
    NavigableSet<E> sortedSet = createNavigableSet();
    // test with no entries
    assertEquals(0, sortedSet.subSet(getKeys()[0], getKeys()[0]).size());
    assertEquals(0, sortedSet.subSet(getKeys()[0], false, getKeys()[0], false).size());
    assertEquals(0, sortedSet.subSet(getKeys()[0], true, getKeys()[0], false).size());
    assertEquals(0, sortedSet.subSet(getKeys()[0], false, getKeys()[0], true).size());
    assertEquals(0, sortedSet.subSet(getKeys()[0], true, getKeys()[0], true).size());

    // test with a single entry set
    sortedSet.add(getKeys()[0]);
    assertEquals(0, sortedSet.subSet(getKeys()[0], getKeys()[0]).size());
    // bounded by a "wide" range
    assertEquals(1, sortedSet.subSet(getLessThanMinimumKey(), getGreaterThanMaximumKey()).size());
    assertEquals(
        1,
        sortedSet.subSet(getLessThanMinimumKey(), false, getGreaterThanMaximumKey(), false).size());
    assertEquals(
        1,
        sortedSet.subSet(getLessThanMinimumKey(), true, getGreaterThanMaximumKey(), false).size());
    assertEquals(
        1,
        sortedSet.subSet(getLessThanMinimumKey(), false, getGreaterThanMaximumKey(), true).size());
    assertEquals(
        1,
        sortedSet.subSet(getLessThanMinimumKey(), true, getGreaterThanMaximumKey(), true).size());

    // test with two entry set
    sortedSet.add(getKeys()[1]);

    assertEquals(1, sortedSet.subSet(getKeys()[0], getKeys()[1]).size());
    assertEquals(getKeys()[0], sortedSet.subSet(getKeys()[0], getKeys()[1]).toArray()[0]);

    assertEquals(0, sortedSet.subSet(getKeys()[0], false, getKeys()[1], false).size());

    assertEquals(1, sortedSet.subSet(getKeys()[0], false, getKeys()[1], true).size());
    assertEquals(
        getKeys()[1], sortedSet.subSet(getKeys()[0], false, getKeys()[1], true).toArray()[0]);

    assertEquals(1, sortedSet.subSet(getKeys()[0], true, getKeys()[1], false).size());
    assertEquals(
        getKeys()[0], sortedSet.subSet(getKeys()[0], true, getKeys()[1], false).toArray()[0]);

    assertEquals(2, sortedSet.subSet(getKeys()[0], true, getKeys()[1], true).size());
    assertEquals(
        getKeys()[0], sortedSet.subSet(getKeys()[0], true, getKeys()[1], true).toArray()[0]);
    assertEquals(
        getKeys()[1], sortedSet.subSet(getKeys()[0], true, getKeys()[1], true).toArray()[1]);

    // bounded by a "wide" range
    SortedSet<E> subSet = sortedSet.subSet(getLessThanMinimumKey(), getGreaterThanMaximumKey());

    assertEquals(2, subSet.size());

    assertEquals(
        2,
        sortedSet.subSet(getLessThanMinimumKey(), false, getGreaterThanMaximumKey(), false).size());
    assertEquals(
        1, sortedSet.subSet(getKeys()[0], false, getGreaterThanMaximumKey(), false).size());
    assertEquals(0, sortedSet.subSet(getKeys()[0], false, getKeys()[1], false).size());
    assertEquals(2, sortedSet.subSet(getKeys()[0], true, getGreaterThanMaximumKey(), false).size());
    assertEquals(1, sortedSet.subSet(getKeys()[0], true, getKeys()[1], false).size());
    assertEquals(2, sortedSet.subSet(getKeys()[0], true, getGreaterThanMaximumKey(), true).size());
    assertEquals(2, sortedSet.subSet(getKeys()[0], true, getKeys()[1], true).size());
  }

  /**
   * Test method for 'java.util.SortedSet.tailSet(Object)' and '@see
   * java.util.NavigableSet.tailSet(Object, boolean)'.
   *
   * @see java.util.SortedSet#tailSet(Object)
   * @see java.util.NavigableSet#tailSet(Object, boolean)
   */
  public void testTailSet_entries0() {
    // test with no entries
    NavigableSet<E> navigableSet = createNavigableSet();

    assertNotNull(navigableSet.tailSet(getKeys()[0]));
    assertNotNull(navigableSet.tailSet(getKeys()[0], false));
    assertNotNull(navigableSet.tailSet(getKeys()[0], true));
  }

  /**
   * Test method for 'java.util.SortedSet.tailSet(Object)' and '@see
   * java.util.NavigableSet.tailSet(Object, boolean)'.
   *
   * @see java.util.SortedSet#tailSet(Object)
   * @see java.util.NavigableSet#tailSet(Object, boolean)
   */
  public void testTailSet_entries0_size() {
    // test with no entries
    NavigableSet<E> navigableSet = createNavigableSet();

    Set<E> tailSet = navigableSet.tailSet(getKeys()[0]);
    assertNotNull(tailSet);
    assertEquals(0, tailSet.size());

    Set<E> exclusiveTailSet = navigableSet.tailSet(getKeys()[0], false);
    assertNotNull(exclusiveTailSet);
    assertEquals(0, exclusiveTailSet.size());

    Set<E> inclusiveTailSet = navigableSet.tailSet(getKeys()[0], true);
    assertNotNull(inclusiveTailSet);
    assertEquals(0, inclusiveTailSet.size());
  }

  /**
   * Test method for 'java.util.SortedSet.tailSet(Object)' and '@see
   * java.util.NavigableSet.tailSet(Object, boolean)'.
   *
   * @see java.util.SortedSet#tailSet(Object)
   * @see java.util.NavigableSet#tailSet(Object, boolean)
   */
  public void testTailSet_entries1_size_keyValue() {
    NavigableSet<E> sortedSet = createNavigableSet();
    // test with a single entry set
    sortedSet.add(getKeys()[0]);

    Set<E> tailSet = sortedSet.tailSet(getKeys()[0]);
    assertEquals(1, tailSet.size());
    assertEquals(getKeys()[0], tailSet.toArray()[0]);

    Set<E> exclusiveTailSet = sortedSet.tailSet(getKeys()[0], false);
    assertEquals(0, exclusiveTailSet.size());
    assertEquals(0, exclusiveTailSet.size());

    Set<E> inclusiveTailSet = sortedSet.tailSet(getKeys()[0], true);
    assertEquals(1, inclusiveTailSet.size());
    assertEquals(getKeys()[0], inclusiveTailSet.toArray()[0]);
  }

  /**
   * Test method for 'java.util.SortedSet.tailSet(Object)' and '@see
   * java.util.NavigableSet.tailSet(Object, boolean)'.
   *
   * @see java.util.SortedSet#tailSet(Object)
   * @see java.util.NavigableSet#tailSet(Object, boolean)
   */
  public void testTailSet_entries2_size_keyValue() {
    NavigableSet<E> sortedSet = createNavigableSet();
    // test with two entry set
    sortedSet.add(getKeys()[0]);

    Set<E> tailSet = sortedSet.tailSet(getKeys()[0]);
    assertEquals(1, tailSet.size());
    Set<E> exclusiveTailMap = sortedSet.tailSet(getKeys()[0], false);
    assertEquals(0, exclusiveTailMap.size());
    Set<E> inclusiveTailMap = sortedSet.tailSet(getKeys()[0], true);
    assertEquals(1, inclusiveTailMap.size());

    sortedSet.add(getKeys()[1]);

    tailSet = sortedSet.tailSet(getKeys()[1]);
    assertEquals(1, tailSet.size());

    exclusiveTailMap = sortedSet.tailSet(getKeys()[1], false);
    assertEquals(0, exclusiveTailMap.size());

    inclusiveTailMap = sortedSet.tailSet(getKeys()[1], true);
    assertEquals(1, inclusiveTailMap.size());

    tailSet = sortedSet.tailSet(getKeys()[0]);
    assertEquals(2, tailSet.size());
    assertEquals(getKeys()[0], tailSet.toArray()[0]);
    assertEquals(getKeys()[1], tailSet.toArray()[1]);

    exclusiveTailMap = sortedSet.tailSet(getKeys()[0], false);
    assertEquals(1, exclusiveTailMap.size());
    assertEquals(getKeys()[1], exclusiveTailMap.toArray()[0]);

    inclusiveTailMap = sortedSet.tailSet(getKeys()[0], true);
    assertEquals(2, inclusiveTailMap.size());
    assertEquals(getKeys()[0], inclusiveTailMap.toArray()[0]);
    assertEquals(getKeys()[1], inclusiveTailMap.toArray()[1]);
  }

  /**
   * Test method for 'java.util.SortedSet.tailSet(Object, Object)'.
   *
   * @see java.util.SortedSet#tailSet(Object)
   */
  @SuppressWarnings("unchecked")
  public void testTailSet_throwsClassCastException() {
    SortedSet sortedSet = createNavigableSet();
    sortedSet.add(getKeys()[0]);
    if (isNaturalOrder()) {
      // TODO Why does this succeed with natural ordering when subSet doesn't?
      sortedSet.tailSet(getConflictingKey());
    } else {
      try {
        sortedSet.tailSet(getConflictingKey());
        assertTrue("CCE expected in Development Mode", !TestUtils.isJvm());
      } catch (ClassCastException e) {
        // expected outcome
      }
    }
  }

  /**
   * Test method for 'java.util.SortedSet.tailSet(Object, Object)'.
   *
   * @see java.util.SortedSet#tailSet(Object)
   */
  public void testTailSet_throwsIllegalArgumentException() {
    // TODO I don't know of any case where this could happen.
  }

  protected Comparator<E> getComparator() {
    return comparator;
  }

  protected abstract Object getConflictingKey();

  protected abstract Object getConflictingValue();

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

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

  @Override
  protected void gwtSetUp() throws Exception {
    setComparator(null);
  }

  protected boolean isNaturalOrder() {
    return comparator == null;
  }

  @Override
  protected Set makeEmptySet() {
    return createTreeSet();
  }

  protected void setComparator(Comparator<E> comparator) {
    this.comparator = comparator;
  }

  NavigableSet<E> createNavigableSet() {
    return createTreeSet();
  }

  Set<E> createSet() {
    return createNavigableSet();
  }

  TreeSet<E> createTreeSet() {
    if (isNaturalOrder()) {
      return new TreeSet<E>();
    } else {
      return new TreeSet<E>(getComparator());
    }
  }

  abstract E getGreaterThanMaximumKey();

  abstract E[] getKeys();

  abstract E[] getKeys2();

  abstract E getLessThanMinimumKey();
}
