import static org.junit.Assert.*;

import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;

import org.junit.Before;
import org.junit.Test;

public class DnaTreeSetTest {

  private static final List<DnaString> SAMPLE_DATA = Arrays.asList(
      new DnaString("A"), new DnaString("C"), new DnaString("G"),
      new DnaString("T"), new DnaString("AA"), new DnaString("AC"),
      new DnaString("AAA"), new DnaString("ACGT"));

  protected DnaTreeSet dnaTreeSet;

  private static int expectedSampleDataHashCode() {
    int hashCode = 0;
    for (DnaString dnaString : SAMPLE_DATA) {
      hashCode += dnaString.hashCode();
    }
    return hashCode;
  }

  /**
   * @throws java.lang.Exception
   */
  @Before
  public void setUp() throws Exception {
    dnaTreeSet = new DnaTreeSet();
  }

  @Test
  public void testDnaTreeSet() {
    assertNotNull("DnaTreeSet should not be null.", dnaTreeSet);
    assertEquals("size should be initally 0.", 0, dnaTreeSet.size());
    assertTrue("set should be initially empty.", dnaTreeSet.isEmpty());
  }

  @Test
  public void testDnaTreeSetCollection() {
    dnaTreeSet = new DnaTreeSet(SAMPLE_DATA);
    assertNotNull("DnaTreeSet should not be null.", dnaTreeSet);
    assertEquals("size should be initally the size of sample data.",
        SAMPLE_DATA.size(), dnaTreeSet.size());
    if (SAMPLE_DATA.isEmpty()) {
      assertTrue("list should be initially empty.", dnaTreeSet.isEmpty());
    } else {
      assertFalse("list should not be initially empty.", dnaTreeSet.isEmpty());
    }
  }

  @Test
  public void testAdd() {
    assertTrue("add should return true.", dnaTreeSet.add(new DnaString("A")));
    assertEquals("size should be 1.", 1, dnaTreeSet.size());
    assertTrue("DNA string 'A' should be in set.",
        dnaTreeSet.contains(new DnaString("A")));
    assertEquals("dnaTreeSet is incorrectly structured.", "A\n",
        dnaTreeSet.toString());
    assertTrue("add should return true.", dnaTreeSet.add(new DnaString("C")));
    assertEquals("size should be 2.", 2, dnaTreeSet.size());
    assertTrue("DNA string 'C' should be in set.",
        dnaTreeSet.contains(new DnaString("C")));
    assertEquals("dnaTreeSet is incorrectly structured.",
        "I\n  A\n  C\n  E\n  E\n  E\n", dnaTreeSet.toString());
    assertTrue("add should return true.", dnaTreeSet.add(new DnaString("G")));
    assertEquals("size should be 3.", 3, dnaTreeSet.size());
    assertTrue("DNA string 'G' should be in set.",
        dnaTreeSet.contains(new DnaString("G")));
    assertEquals("dnaTreeSet is incorrectly structured.",
        "I\n  A\n  C\n  G\n  E\n  E\n", dnaTreeSet.toString());
    assertTrue("add should return true.", dnaTreeSet.add(new DnaString("T")));
    assertEquals("size should be 4.", 4, dnaTreeSet.size());
    assertTrue("DNA string 'T' should be in set.",
        dnaTreeSet.contains(new DnaString("T")));
    assertEquals("dnaTreeSet is incorrectly structured.",
        "I\n  A\n  C\n  G\n  T\n  E\n", dnaTreeSet.toString());

    dnaTreeSet = new DnaTreeSet();
    assertTrue("add should return true.", dnaTreeSet.add(new DnaString("A")));
    assertTrue("add should return true.", dnaTreeSet.add(new DnaString("CA")));
    assertEquals("size should be 2.", 2, dnaTreeSet.size());
    assertTrue("DNA string 'CA' should be in set.",
        dnaTreeSet.contains(new DnaString("CA")));
    assertEquals("dnaTreeSet is incorrectly structured.",
        "I\n  A\n  CA\n  E\n  E\n  E\n", dnaTreeSet.toString());
    assertTrue("add should return true.", dnaTreeSet.add(new DnaString("AC")));
    assertEquals("size should be 3.", 3, dnaTreeSet.size());
    assertTrue("DNA string 'AC' should be in set.",
        dnaTreeSet.contains(new DnaString("AC")));
    assertEquals("dnaTreeSet is incorrectly structured.",
        "I\n  I\n    E\n    AC\n    E\n    E\n    A\n  CA\n  E\n  E\n  E\n",
        dnaTreeSet.toString());
    assertTrue("add should return true.", dnaTreeSet.add(new DnaString("C")));
    assertEquals("size should be 4.", 4, dnaTreeSet.size());
    assertTrue("DNA string 'C' should be in set.",
        dnaTreeSet.contains(new DnaString("C")));
    assertEquals(
        "dnaTreeSet is incorrectly structured.",
        "I\n  I\n    E\n    AC\n    E\n    E\n    A\n  I\n    CA\n    E\n    E\n    E\n    C\n  E\n  E\n  E\n",
        dnaTreeSet.toString());
    assertFalse("add should return false.", dnaTreeSet.add(new DnaString("C")));
    assertEquals("size should be 4.", 4, dnaTreeSet.size());
    assertEquals(
        "dnaTreeSet is incorrectly structured.",
        "I\n  I\n    E\n    AC\n    E\n    E\n    A\n  I\n    CA\n    E\n    E\n    E\n    C\n  E\n  E\n  E\n",
        dnaTreeSet.toString());
  }

  @Test
  public void testAddAll() {
    DnaString preDnaStringUnique = new DnaString("CC");
    DnaString preDnaStringDuplicate = SAMPLE_DATA.get(0);
    dnaTreeSet.add(preDnaStringUnique);
    dnaTreeSet.add(preDnaStringDuplicate);
    dnaTreeSet.addAll(SAMPLE_DATA);
    assertEquals("size should be one more than size of sample data.",
        SAMPLE_DATA.size() + 1, dnaTreeSet.size());
    assertTrue("DNA string 'CC' should be in set.",
        dnaTreeSet.contains(preDnaStringUnique));
    for (DnaString dnaString : SAMPLE_DATA) {
      assertTrue("DNA string '" + dnaString + "' should be in set.",
          dnaTreeSet.contains(dnaString));
    }
  }

  @Test
  public void testContains() {
    assertFalse("dnaTreeSet should not contain DNA string 'A'.",
        dnaTreeSet.contains(new DnaString("A")));
    dnaTreeSet.add(new DnaString("A"));
    assertTrue("dnaTreeSet should contain DNA string 'A'.",
        dnaTreeSet.contains(new DnaString("A")));
    assertFalse("dnaTreeSet should not contain DNA string 'C'.",
        dnaTreeSet.contains(new DnaString("C")));
    assertFalse("dnaTreeSet should not contain DNA string 'G'.",
        dnaTreeSet.contains(new DnaString("G")));
    assertFalse("dnaTreeSet should not contain DNA string 'T'.",
        dnaTreeSet.contains(new DnaString("T")));
    dnaTreeSet.add(new DnaString("C"));
    dnaTreeSet.add(new DnaString("G"));
    dnaTreeSet.add(new DnaString("T"));
    assertTrue("dnaTreeSet should contain DNA string 'C'.",
        dnaTreeSet.contains(new DnaString("C")));
    assertTrue("dnaTreeSet should contain DNA string 'G'.",
        dnaTreeSet.contains(new DnaString("G")));
    assertTrue("dnaTreeSet should contain DNA string 'T'.",
        dnaTreeSet.contains(new DnaString("T")));
    assertFalse("dnaTreeSet should not contain DNA string 'ACGT'.",
        dnaTreeSet.contains(new DnaString("ACGT")));
    dnaTreeSet.add(new DnaString("ACGT"));
    assertTrue("dnaTreeSet should contain DNA string 'A'.",
        dnaTreeSet.contains(new DnaString("A")));
    assertTrue("dnaTreeSet should contain DNA string 'ACGT'.",
        dnaTreeSet.contains(new DnaString("ACGT")));
  }

  @Test
  public void testContainsAll() {
    for (int i = 0; i < SAMPLE_DATA.size() - 1; i++) {
      dnaTreeSet.add(SAMPLE_DATA.get(i));
    }
    assertFalse(
        "dnaTreeSet should not contain all DNA strings in sample data.",
        dnaTreeSet.containsAll(SAMPLE_DATA));
    dnaTreeSet.add(SAMPLE_DATA.get(SAMPLE_DATA.size() - 1));
    assertTrue("dnaTreeSet should contain all DNA strings in sample data.",
        dnaTreeSet.containsAll(SAMPLE_DATA));
  }

  @Test
  public void testContainsPrefix() {
    assertFalse("dnaTreeSet should not contain prefix 'A'.",
        dnaTreeSet.containsPrefix(new DnaString("A")));
    dnaTreeSet.add(new DnaString("A"));
    assertTrue("dnaTreeSet should contain prefix 'A'.",
        dnaTreeSet.containsPrefix(new DnaString("A")));
    assertFalse("dnaTreeSet should not contain prefix 'C'.",
        dnaTreeSet.containsPrefix(new DnaString("C")));
    assertFalse("dnaTreeSet should not contain prefix 'G'.",
        dnaTreeSet.containsPrefix(new DnaString("G")));
    assertFalse("dnaTreeSet should not contain prefix 'T'.",
        dnaTreeSet.containsPrefix(new DnaString("T")));
    dnaTreeSet.add(new DnaString("C"));
    dnaTreeSet.add(new DnaString("G"));
    dnaTreeSet.add(new DnaString("T"));
    assertTrue("dnaTreeSet should contain prefix 'C'.",
        dnaTreeSet.containsPrefix(new DnaString("C")));
    assertTrue("dnaTreeSet should contain prefix 'G'.",
        dnaTreeSet.containsPrefix(new DnaString("G")));
    assertTrue("dnaTreeSet should contain prefix 'T'.",
        dnaTreeSet.containsPrefix(new DnaString("T")));

    assertFalse("dnaTreeSet should not contain prefix 'AC'.",
        dnaTreeSet.containsPrefix(new DnaString("AC")));
    dnaTreeSet.add(new DnaString("AC"));
    assertTrue("dnaTreeSet should contain prefix 'AC'.",
        dnaTreeSet.containsPrefix(new DnaString("AC")));
    assertFalse("dnaTreeSet should not contain prefix 'CG'.",
        dnaTreeSet.containsPrefix(new DnaString("CG")));
    dnaTreeSet.add(new DnaString("CGT"));
    assertTrue("dnaTreeSet should contain prefix 'CG'.",
        dnaTreeSet.containsPrefix(new DnaString("CG")));
  }

  @Test
  public void testSearch() {
    Collection<DnaString> found;
    found = dnaTreeSet.search(new DnaStringDescriptor("A"));
    assertTrue("search should have found no elements.", found.isEmpty());
    dnaTreeSet.add(new DnaString("A"));
    found = dnaTreeSet.search(new DnaStringDescriptor("A"));
    assertEquals("search should have returned 1 DNA string.", 1, found.size());
    assertTrue("search should have found DNA string 'A'.",
        found.contains(new DnaString("A")));
    dnaTreeSet.add(new DnaString("C"));
    dnaTreeSet.add(new DnaString("G"));
    dnaTreeSet.add(new DnaString("T"));
    found = dnaTreeSet.search(new DnaStringDescriptor("C"));
    assertEquals("search should have returned 1 DNA string.", 1, found.size());
    assertTrue("search should have found DNA string 'C'.",
        found.contains(new DnaString("C")));
    found = dnaTreeSet.search(new DnaStringDescriptor("G"));
    assertEquals("search should have returned 1 DNA string.", 1, found.size());
    assertTrue("search should have found DNA string 'G'.",
        found.contains(new DnaString("G")));
    found = dnaTreeSet.search(new DnaStringDescriptor("T"));
    assertEquals("search should have returned 1 DNA string.", 1, found.size());
    assertTrue("search should have found DNA string 'T'.",
        found.contains(new DnaString("T")));

    found = dnaTreeSet.search(new DnaStringDescriptor("AC"));
    assertTrue("search should have found no elements.", found.isEmpty());
    dnaTreeSet.add(new DnaString("AC"));
    found = dnaTreeSet.search(new DnaStringDescriptor("AC"));
    assertEquals("search should have returned 1 DNA string.", 1, found.size());
    assertTrue("search should have found DNA string 'AC'.",
        found.contains(new DnaString("AC")));
    found = dnaTreeSet.search(new DnaStringDescriptor("A"));
    assertEquals("search should have returned 2 DNA strings.", 2, found.size());
    assertTrue("search should have found DNA string 'A'.",
        found.contains(new DnaString("A")));
    assertTrue("search should have found DNA string 'AC'.",
        found.contains(new DnaString("AC")));

    found = dnaTreeSet.search(new DnaStringDescriptor("$"));
    assertTrue("search should have found no elements.", found.isEmpty());
    found = dnaTreeSet.search(new DnaStringDescriptor("A$"));
    assertEquals("search should have returned 1 DNA string.", 1, found.size());
    assertTrue("search should have found DNA string 'A'.",
        found.contains(new DnaString("A")));
  }

  @Test
  public void testValues() {
    Collection<DnaString> values = dnaTreeSet.values();
    assertTrue("values should return an empty list.", values.isEmpty());
    dnaTreeSet.add(new DnaString("A"));
    values = dnaTreeSet.values();
    assertEquals("values should return a list of size 1.", 1, values.size());
    assertTrue("values should return a list containing DNA string 'A'.",
        values.contains(new DnaString("A")));
    dnaTreeSet.add(new DnaString("C"));
    dnaTreeSet.add(new DnaString("G"));
    dnaTreeSet.add(new DnaString("T"));
    values = dnaTreeSet.values();
    assertEquals("values should return a list of size 4.", 4, values.size());
    assertTrue("values should return a list containing DNA string 'A'.",
        values.contains(new DnaString("A")));
    assertTrue("values should return a list containing DNA string 'C'.",
        values.contains(new DnaString("C")));
    assertTrue("values should return a list containing DNA string 'G'.",
        values.contains(new DnaString("G")));
    assertTrue("values should return a list containing DNA string 'T'.",
        values.contains(new DnaString("T")));
    dnaTreeSet.add(new DnaString("AC"));
    values = dnaTreeSet.values();
    assertEquals("values should return a list of size 5.", 5, values.size());
    assertTrue("values should return a list containing DNA string 'A'.",
        values.contains(new DnaString("A")));
    assertTrue("values should return a list containing DNA string 'AC'.",
        values.contains(new DnaString("AC")));
  }

  @Test
  public void testRemove() {
    assertFalse("remove should have returned false.",
        dnaTreeSet.remove(new DnaString("A")));
    dnaTreeSet.add(new DnaString("A"));
    assertTrue("remove should have returned true.",
        dnaTreeSet.remove(new DnaString("A")));
    assertEquals("size should be 0.", 0, dnaTreeSet.size());
    assertEquals("dnaTreeSet is incorrectly structured.", "E\n",
        dnaTreeSet.toString());
    dnaTreeSet.add(new DnaString("C"));
    dnaTreeSet.add(new DnaString("G"));
    dnaTreeSet.add(new DnaString("T"));
    assertTrue("remove should have returned true.",
        dnaTreeSet.remove(new DnaString("C")));
    assertEquals("size should be 2.", 2, dnaTreeSet.size());
    assertEquals("dnaTreeSet is incorrectly structured.",
        "I\n  E\n  E\n  G\n  T\n  E\n", dnaTreeSet.toString());
    assertTrue("remove should have returned true.",
        dnaTreeSet.remove(new DnaString("G")));
    assertEquals("size should be 1.", 1, dnaTreeSet.size());
    assertEquals("dnaTreeSet is incorrectly structured.", "T\n",
        dnaTreeSet.toString());
    assertTrue("remove should have returned true.",
        dnaTreeSet.remove(new DnaString("T")));
    assertEquals("size should be 0.", 0, dnaTreeSet.size());
    assertEquals("dnaTreeSet is incorrectly structured.", "E\n",
        dnaTreeSet.toString());

    dnaTreeSet.add(new DnaString("A"));
    dnaTreeSet.add(new DnaString("AC"));
    dnaTreeSet.add(new DnaString("G"));
    assertTrue("remove should have returned true.",
        dnaTreeSet.remove(new DnaString("A")));
    assertEquals("size should be 2.", 2, dnaTreeSet.size());
    assertEquals("dnaTreeSet is incorrectly structured.",
        "I\n  AC\n  E\n  G\n  E\n  E\n", dnaTreeSet.toString());
  }

  @Test
  public void testRemoveAll() {
    DnaString preDnaStringUnique = new DnaString("CC");
    dnaTreeSet.add(preDnaStringUnique);
    dnaTreeSet.addAll(SAMPLE_DATA);
    dnaTreeSet.removeAll(SAMPLE_DATA);
    assertEquals("size should be 1.", 1, dnaTreeSet.size());
    assertTrue("dnaTreeSet should contain DNA string '" + preDnaStringUnique
        + "'.", dnaTreeSet.contains(preDnaStringUnique));
  }

  @Test
  public void testRetainAll() {
    DnaString preDnaStringUnique = new DnaString("CC");
    dnaTreeSet.addAll(SAMPLE_DATA);
    dnaTreeSet.add(preDnaStringUnique);
    dnaTreeSet.retainAll(SAMPLE_DATA);
    assertEquals("size should be size of sample data.", SAMPLE_DATA.size(),
        dnaTreeSet.size());
    assertFalse("list should not contain DNA string '" + preDnaStringUnique
        + "'.", dnaTreeSet.contains(preDnaStringUnique));
  }

  @Test
  public void testClear() {
    dnaTreeSet.add(new DnaString("A"));
    dnaTreeSet.add(new DnaString("C"));
    dnaTreeSet.clear();
    assertEquals("size should be 0.", 0, dnaTreeSet.size());
    assertTrue("dnaTreeSet should be empty.", dnaTreeSet.isEmpty());
  }

  @Test
  public void testSize() {
    assertEquals("size should be 0.", 0, dnaTreeSet.size());
    dnaTreeSet.add(new DnaString("A"));
    assertEquals("size should be 1.", 1, dnaTreeSet.size());
    dnaTreeSet.remove(new DnaString("A"));
    assertEquals("size should be 0.", 0, dnaTreeSet.size());
  }

  @Test
  public void testIsEmpty() {
    assertTrue("dnaTreeSet should be empty.", dnaTreeSet.isEmpty());
    dnaTreeSet.add(new DnaString("A"));
    assertFalse("dnaTreeSet should not be empty.", dnaTreeSet.isEmpty());
    dnaTreeSet.remove(new DnaString("A"));
    assertTrue("dnaTreeSet should be empty.", dnaTreeSet.isEmpty());
  }

  @Test
  public void testIterator() {
    assertNotNull("iterator should not return null.", dnaTreeSet.iterator());
  }

  @Test
  public void testToArray() {
    Object[] array = dnaTreeSet.toArray();
    assertNotNull("array should not be null.", array);
    assertEquals("size of array should be 0.", 0, array.length);
    dnaTreeSet.add(new DnaString("A"));
    array = dnaTreeSet.toArray();
    assertNotNull("array should not be null.", array);
    assertEquals("size of array should be 1.", 1, array.length);
    assertEquals("position 0 of array should be DNA string 'A'", new DnaString(
        "A"), array[0]);
    dnaTreeSet.add(new DnaString("C"));
    dnaTreeSet.add(new DnaString("G"));
    dnaTreeSet.add(new DnaString("T"));
    array = dnaTreeSet.toArray();
    assertNotNull("array should not be null.", array);
    assertEquals("size of array should be 4.", 4, array.length);
    assertEquals("position 0 of array should be DNA string 'A'", new DnaString(
        "A"), array[0]);
    assertEquals("position 1 of array should be DNA string 'C'", new DnaString(
        "C"), array[1]);
    assertEquals("position 2 of array should be DNA string 'G'", new DnaString(
        "G"), array[2]);
    assertEquals("position 3 of array should be DNA string 'T'", new DnaString(
        "T"), array[3]);
    dnaTreeSet.add(new DnaString("AC"));
    array = dnaTreeSet.toArray();
    assertNotNull("array should not be null.", array);
    assertEquals("size of array should be 5.", 5, array.length);
    assertEquals("position 0 of array should be DNA string 'AC'",
        new DnaString("AC"), array[0]);
    assertEquals("position 1 of array should be DNA string 'A'", new DnaString(
        "A"), array[1]);
    assertEquals("position 2 of array should be DNA string 'C'", new DnaString(
        "C"), array[2]);
    assertEquals("position 3 of array should be DNA string 'G'", new DnaString(
        "G"), array[3]);
    assertEquals("position 4 of array should be DNA string 'T'", new DnaString(
        "T"), array[4]);
  }

  @Test
  public void testToString() {
    assertEquals("toString returned incorrect string.", "E\n",
        dnaTreeSet.toString());
    dnaTreeSet.add(new DnaString("A"));
    dnaTreeSet.add(new DnaString("AC"));
    dnaTreeSet.add(new DnaString("C"));
    assertEquals("toString returned incorrect string.",
        "I\n  I\n    E\n    AC\n    E\n    E\n    A\n  C\n  E\n  E\n  E\n",
        dnaTreeSet.toString());
  }

  @Test
  public void testToStringWithLengths() {
    assertEquals("toStringWithLengths returned incorrect string.", "E\n",
        dnaTreeSet.toStringWithLengths());
    dnaTreeSet.add(new DnaString("A"));
    dnaTreeSet.add(new DnaString("AC"));
    dnaTreeSet.add(new DnaString("C"));
    assertEquals(
        "toStringWithLengths returned incorrect string.",
        "I\n  I\n    E\n    AC [2]\n    E\n    E\n    A [1]\n  C [1]\n  E\n  E\n  E\n",
        dnaTreeSet.toStringWithLengths());
  }

  @Test
  public void testToStringWithStatistics() {
    assertEquals("toStringWithStatistics returned incorrect string.", "E\n",
        dnaTreeSet.toStringWithStatistics());
    dnaTreeSet.add(new DnaString("A"));
    dnaTreeSet.add(new DnaString("AC"));
    dnaTreeSet.add(new DnaString("C"));
    assertEquals(
        "toStringWithStatistics returned incorrect string.",
        "I\n  I\n    E\n    AC [A: 50.00%, C: 50.00%, G: 0.00%, T: 0.00%]\n    E\n    E\n    A [A: 100.00%, C: 0.00%, G: 0.00%, T: 0.00%]\n  C [A: 0.00%, C: 100.00%, G: 0.00%, T: 0.00%]\n  E\n  E\n  E\n",
        dnaTreeSet.toStringWithStatistics());
    dnaTreeSet = new DnaTreeSet();
    dnaTreeSet.add(new DnaString("ACGT"));
    assertEquals("toStringWithStatistics returned incorrect string.",
        "ACGT [A: 25.00%, C: 25.00%, G: 25.00%, T: 25.00%]\n",
        dnaTreeSet.toStringWithStatistics());
  }

  @Test
  public void testHashCode() {
    assertEquals("hashCode should be 0.", 0, dnaTreeSet.hashCode());
    dnaTreeSet.addAll(SAMPLE_DATA);
    int sampleDataHashCode = expectedSampleDataHashCode();
    assertEquals("hashCode should be hashCode of sample data.",
        sampleDataHashCode, dnaTreeSet.hashCode());
  }

  @Test
  public void testEqualsObject() {
    assertTrue("dnaTreeSet should be equal to itself.",
        dnaTreeSet.equals(dnaTreeSet));
    assertFalse("dnaTreeSet should not be equal to null.",
        dnaTreeSet.equals(null));
    assertFalse("dnaTreeSet should not be equal to non-list",
        dnaTreeSet.equals(new Object()));
    DnaTreeSet other = new DnaTreeSet();
    assertTrue("dnaTreeSet should be equal.", dnaTreeSet.equals(other));
    dnaTreeSet.add(new DnaString("A"));
    other.add(new DnaString("A"));
    assertTrue("dnaTreeSets should be equal.", dnaTreeSet.equals(other));
    dnaTreeSet.add(new DnaString("C"));
    assertFalse("dnaTreeSets should not be equal.", dnaTreeSet.equals(other));
    dnaTreeSet.add(new DnaString("G"));
    other.add(new DnaString("G"));
    other.add(new DnaString("C"));
    assertTrue("dnaTreeSets should be equal.", dnaTreeSet.equals(other));
  }

  // --------------------------------------------------
  // ITERATOR TESTS
  // --------------------------------------------------

  /**
   * Test method for {@link DnaTreeSet$DnaTreeSetIterator#DnaTreeSetIterator()}.
   */
  @Test
  public void testDnaTreeSetIteratorDnaTreeSetIterator() {
    Iterator<DnaString> it = dnaTreeSet.iterator();
    assertNotNull("iterator should not return null.", it);
  }

  /**
   * Test method for {@link DnaTreeSet$DnaTreeSetIterator#hasNext()}.
   */
  @Test
  public void testDnaTreeSetIteratorHasNext() {
    Iterator<DnaString> it = dnaTreeSet.iterator();
    assertFalse("hasNext should return false.", it.hasNext());
    dnaTreeSet.add(new DnaString("A"));
    it = dnaTreeSet.iterator();
    assertTrue("hasNext should return true.", it.hasNext());
    it.next();
    assertFalse("hasNext should return false.", it.hasNext());
  }

  /**
   * Test method for {@link DnaTreeSet$DnaTreeSetIterator#next()}.
   */
  @Test
  public void testDnaTreeSetIteratorNext() {
    Iterator<DnaString> it = dnaTreeSet.iterator();
    try {
      it.next();
      fail("next should have thrown NoSuchElementException.");
    } catch (NoSuchElementException e) {
      // test passed
    }
    dnaTreeSet.add(new DnaString("A"));
    dnaTreeSet.add(new DnaString("AC"));
    dnaTreeSet.add(new DnaString("C"));
    it = dnaTreeSet.iterator();
    assertEquals("next should return DNA string 'AC'.", new DnaString("AC"),
        it.next());
    assertEquals("next should return DNA string 'A'.", new DnaString("A"),
        it.next());
    assertEquals("next should return DNA string 'C'.", new DnaString("C"),
        it.next());
    try {
      it.next();
      fail("next should have thrown NoSuchElementException.");
    } catch (NoSuchElementException e) {
      // test passed
    }
  }
}
