TIMED_TEST(LexiconTests, initializerListTest_Lexicon, TEST_TIMEOUT_DEFAULT) {
    std::initializer_list<std::string> lexlist = {"sixty", "seventy"};
    std::initializer_list<std::string> lexallwords = {
        "ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy"
    };

    Lexicon lex {"ten", "twenty", "thirty"};
    assertEqualsString("init list Lexicon", "{\"ten\", \"thirty\", \"twenty\"}", lex.toString());
    assertEqualsInt("init list Lexicon size", 3, lex.size());
    assertTrue("init list Lexicon contains ten", lex.contains("ten"));
    assertTrue("init list Lexicon contains twenty", lex.contains("twenty"));
    assertTrue("init list Lexicon contains thirty", lex.contains("thirty"));
    assertFalse("init list Lexicon contains forty", lex.contains("forty"));
    assertFalse("init list Lexicon contains fifty", lex.contains("fifty"));

    lex += {"forty", "fifty"};
    assertEqualsString("after += Lexicon", "{\"fifty\", \"forty\", \"ten\", \"thirty\", \"twenty\"}", lex.toString());
    assertEqualsInt("after += Lexicon size", 5, lex.size());
    assertTrue("init list Lexicon contains ten", lex.contains("ten"));
    assertTrue("init list Lexicon contains twenty", lex.contains("twenty"));
    assertTrue("init list Lexicon contains thirty", lex.contains("thirty"));
    assertTrue("init list Lexicon contains forty", lex.contains("forty"));
    assertTrue("init list Lexicon contains fifty", lex.contains("fifty"));
    assertFalse("init list Lexicon contains sixty", lex.contains("sixty"));
    assertFalse("init list Lexicon contains seventy", lex.contains("seventy"));

    Lexicon lex2 = (lex + lexlist);
    assertEqualsString("after += Lexicon", "{\"fifty\", \"forty\", \"ten\", \"thirty\", \"twenty\"}", lex.toString());
    assertEqualsInt("after + Lexicon size", 5, lex.size());
    assertTrue("init list Lexicon contains ten", lex.contains("ten"));
    assertTrue("init list Lexicon contains twenty", lex.contains("twenty"));
    assertTrue("init list Lexicon contains thirty", lex.contains("thirty"));
    assertTrue("init list Lexicon contains forty", lex.contains("forty"));
    assertTrue("init list Lexicon contains fifty", lex.contains("fifty"));
    assertFalse("init list Lexicon contains sixty", lex.contains("sixty"));
    assertFalse("init list Lexicon contains seventy", lex.contains("seventy"));

    assertEqualsString("after + Lexicon 2", "{\"fifty\", \"forty\", \"seventy\", \"sixty\", \"ten\", \"thirty\", \"twenty\"}", lex2.toString());
    assertEqualsInt("after + Lexicon 2 size", 7, lex2.size());
    assertTrue("init list Lexicon contains ten", lex2.contains("ten"));
    assertTrue("init list Lexicon contains twenty", lex2.contains("twenty"));
    assertTrue("init list Lexicon contains thirty", lex2.contains("thirty"));
    assertTrue("init list Lexicon contains forty", lex2.contains("forty"));
    assertTrue("init list Lexicon contains fifty", lex2.contains("fifty"));
    assertTrue("init list Lexicon contains sixty", lex2.contains("sixty"));
    assertTrue("init list Lexicon contains seventy", lex2.contains("seventy"));
}
TIMED_TEST(StringTests, stringWithWeirdCharsTest, TEST_TIMEOUT_DEFAULT) {
    std::string s1 = "hello  there";
    std::string s2 = "hello\t";
    s2 += '\0';
    s2 += " there";
    s2 += '\377';    // octal for 255
    s2 += "\r\n";
    assertEqualsString("string w/ weird chars", s1, s2);
}
TIMED_TEST(DawgLexiconTests, forEachTest_DawgLexicon, TEST_TIMEOUT_DEFAULT) {
    DawgLexicon dlex;
    dlex.add("a");
    dlex.add("cc");
    dlex.add("bbb");
    Queue<std::string> expected {"a", "bbb", "cc"};
    for (std::string word : dlex) {
        std::string exp = expected.dequeue();
        assertEqualsString("DawgLexicon foreach", exp, word);
    }
}
TIMED_TEST(LinkedHashSetTests, compareTest_LinkedHashSet, TEST_TIMEOUT_DEFAULT) {
    LinkedHashSet<int> set1 {7, 5, 1, 2, 8};
    LinkedHashSet<int> set2 {1, 2, 3, 4};
    LinkedHashSet<int> set3 {2, 1, 3, 4};
    LinkedHashSet<int> set4;
    compareTestHelper(set1, set2, "LinkedHashSet", /* compareTo */  1);
    compareTestHelper(set2, set1, "LinkedHashSet", /* compareTo */ -1);
    compareTestHelper(set1, set3, "LinkedHashSet", /* compareTo */  1);
    compareTestHelper(set2, set3, "LinkedHashSet", /* compareTo */  0);
    compareTestHelper(set3, set2, "LinkedHashSet", /* compareTo */  0);
    compareTestHelper(set2, set4, "LinkedHashSet", /* compareTo */  1);

    // note: shouldn't add set3 because it is 'equal' to set2 (duplicate)
    Set<LinkedHashSet<int> > slhset {set1, set2, set3, set4};
    assertEqualsString("slhset", "{{}, {1, 2, 3, 4}, {7, 5, 1, 2, 8}}", slhset.toString());
}
TIMED_TEST(LexiconTests, compareTest_Lexicon, TEST_TIMEOUT_DEFAULT) {
    Lexicon lex;
    lex.add("a");
    lex.add("ab");
    lex.add("bc");
    Lexicon lex2;
    lex2.add("a");
    lex2.add("b");
    lex2.add("c");
    Lexicon lex3;
    compareTestHelper(lex, lex2, "Lexicon", /* compareTo */ -1);
    compareTestHelper(lex2, lex, "Lexicon", /* compareTo */ 1);
    compareTestHelper(lex, lex, "Lexicon", /* compareTo */ 0);

    Set<Lexicon> slex {lex, lex2, lex3};
    assertEqualsString("slex", "{{}, {\"a\", \"ab\", \"bc\"}, {\"a\", \"b\", \"c\"}}", slex.toString());
}
TIMED_TEST(DawgLexiconTests, compareTest_DawgLexicon, TEST_TIMEOUT_DEFAULT) {
    DawgLexicon dawg;
    dawg.add("a");
    dawg.add("b");
    dawg.add("c");
    DawgLexicon dawg2;
    dawg2.add("a");
    dawg2.add("ab");
    dawg2.add("bc");
    DawgLexicon dawg3;
    compareTestHelper(dawg, dawg2, "DawgLexicon", /* compareTo */ 1);
    compareTestHelper(dawg2, dawg, "DawgLexicon", /* compareTo */ -1);
    compareTestHelper(dawg, dawg, "DawgLexicon", /* compareTo */ 0);

    Set<DawgLexicon> sdlex {dawg, dawg2, dawg3};
    assertEqualsString("sdlex", "{{}, {\"a\", \"ab\", \"bc\"}, {\"a\", \"b\", \"c\"}}", sdlex.toString());
}
TIMED_TEST(StackTests, compareTest_Stack, TEST_TIMEOUT_DEFAULT) {
    Stack<int> s1;
    s1.add(1);
    s1.add(2);
    s1.add(1);
    s1.add(5);
    Stack<int> s2;
    s2.add(1);
    s2.add(2);
    s2.add(1);
    s2.add(4);
    s2.add(7);
    compareTestHelper(s1, s2, "Stack", /* compareTo */  1);
    compareTestHelper(s2, s1, "Stack", /* compareTo */ -1);
    compareTestHelper(s1, s1, "Stack", /* compareTo */  0);

    Set<Stack<int> > ss {s1, s2};
    assertEqualsString("ss", "{{1, 2, 1, 4, 7}, {1, 2, 1, 5}}", ss.toString());
}
TIMED_TEST(GridTests, compareTest_Grid, TEST_TIMEOUT_DEFAULT) {
    Grid<int> grid1;
    grid1.resize(2, 2);
    Grid<int> grid2;
    grid2.resize(2, 3);
    Grid<int> grid3;
    grid3.resize(3, 2);
    Grid<int> grid4;

    /* Comparison is lexicographic by rows, then cols, then
     * elements.
     */
    compareTestHelper(grid1, grid2, "Grid", /* compareTo */ -1);
    compareTestHelper(grid2, grid1, "Grid", /* compareTo */  1);
    compareTestHelper(grid1, grid3, "Grid", /* compareTo */ -1);
    compareTestHelper(grid3, grid1, "Grid", /* compareTo */  1);
    compareTestHelper(grid2, grid3, "Grid", /* compareTo */ -1);
    compareTestHelper(grid3, grid2, "Grid", /* compareTo */  1);
    compareTestHelper(grid1, grid1, "Grid", /* compareTo */  0);

    Set<Grid<int>> sgrid {grid1, grid2, grid3, grid4};
    assertEqualsString("sgrid", "{{}, {{0, 0}, {0, 0}}, {{0, 0, 0}, {0, 0, 0}}, {{0, 0}, {0, 0}, {0, 0}}}", sgrid.toString());
}
TIMED_TEST(MapTests, frontBackTest_Map, TEST_TIMEOUT_DEFAULT) {
    Map<std::string, int> map {{"a", 10}, {"b", 20}, {"c", 30}};
    assertEqualsString("Map front", "a", map.front());
    assertEqualsString("Map back",  "c", map.back());
}
TIMED_TEST(MapTests, streamExtractTest_Map, TEST_TIMEOUT_DEFAULT) {
    std::istringstream stream("{2:20, 1:10, 4:40, 3:30}");
    Map<int, int> map;
    stream >> map;
    assertEqualsString("map", "{1:10, 2:20, 3:30, 4:40}", map.toString());
}
TIMED_TEST(StackTests, initializerListTest_Stack, TEST_TIMEOUT_DEFAULT) {
    Stack<int> stack {10, 20, 30};
    assertEqualsString("init list Stack", "{10, 20, 30}", stack.toString());
}
TIMED_TEST(LexiconTests, frontBackTest_Lexicon, TEST_TIMEOUT_DEFAULT) {
    Lexicon lex {"apple", "apricot", "banana", "zebra"};
    assertEqualsString("Lexicon front", "apple", lex.front());
    assertEqualsString("Lexicon back",  "zebra", lex.back());
}