Reland "Unwrap GrRedBlackTree unit test and use REPORTER_ASSERT()."

BUG=None
TEST=tests
R=robertphillips@google.com

Review URL: https://codereview.chromium.org/137423009

git-svn-id: http://skia.googlecode.com/svn/trunk@13233 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/tests/GrRedBlackTreeTest.cpp b/tests/GrRedBlackTreeTest.cpp
new file mode 100644
index 0000000..c3aa14b
--- /dev/null
+++ b/tests/GrRedBlackTreeTest.cpp
@@ -0,0 +1,180 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrRedBlackTree.h"
+#include "SkRandom.h"
+#include "Test.h"
+
+typedef GrRedBlackTree<int> Tree;
+
+DEF_TEST(GrRedBlackTreeTest, reporter) {
+    Tree tree;
+
+    SkRandom r;
+
+    int count[100] = {0};
+    // add 10K ints
+    for (int i = 0; i < 10000; ++i) {
+        int x = r.nextU() % 100;
+        Tree::Iter xi = tree.insert(x);
+        REPORTER_ASSERT(reporter, *xi == x);
+        ++count[x];
+    }
+
+    tree.insert(0);
+    ++count[0];
+    tree.insert(99);
+    ++count[99];
+    REPORTER_ASSERT(reporter, *tree.begin() == 0);
+    REPORTER_ASSERT(reporter, *tree.last() == 99);
+    REPORTER_ASSERT(reporter, --(++tree.begin()) == tree.begin());
+    REPORTER_ASSERT(reporter, --tree.end() == tree.last());
+    REPORTER_ASSERT(reporter, tree.count() == 10002);
+
+    int c = 0;
+    // check that we iterate through the correct number of
+    // elements and they are properly sorted.
+    for (Tree::Iter a = tree.begin(); tree.end() != a; ++a) {
+        Tree::Iter b = a;
+        ++b;
+        ++c;
+        REPORTER_ASSERT(reporter, b == tree.end() || *a <= *b);
+    }
+    REPORTER_ASSERT(reporter, c == tree.count());
+
+    // check that the tree reports the correct number of each int
+    // and that we can iterate through them correctly both forward
+    // and backward.
+    for (int i = 0; i < 100; ++i) {
+        int c;
+        c = tree.countOf(i);
+        REPORTER_ASSERT(reporter, c == count[i]);
+        c = 0;
+        Tree::Iter iter = tree.findFirst(i);
+        while (iter != tree.end() && *iter == i) {
+            ++c;
+            ++iter;
+        }
+        REPORTER_ASSERT(reporter, count[i] == c);
+        c = 0;
+        iter = tree.findLast(i);
+        if (iter != tree.end()) {
+            do {
+                if (*iter == i) {
+                    ++c;
+                } else {
+                    break;
+                }
+                if (iter != tree.begin()) {
+                    --iter;
+                } else {
+                    break;
+                }
+            } while (true);
+        }
+        REPORTER_ASSERT(reporter, c == count[i]);
+    }
+    // remove all the ints between 25 and 74. Randomly chose to remove
+    // the first, last, or any entry for each.
+    for (int i = 25; i < 75; ++i) {
+        while (0 != tree.countOf(i)) {
+            --count[i];
+            int x = r.nextU() % 3;
+            Tree::Iter iter;
+            switch (x) {
+            case 0:
+                iter = tree.findFirst(i);
+                break;
+            case 1:
+                iter = tree.findLast(i);
+                break;
+            case 2:
+            default:
+                iter = tree.find(i);
+                break;
+            }
+            tree.remove(iter);
+        }
+        REPORTER_ASSERT(reporter, 0 == count[i]);
+        REPORTER_ASSERT(reporter, tree.findFirst(i) == tree.end());
+        REPORTER_ASSERT(reporter, tree.findLast(i) == tree.end());
+        REPORTER_ASSERT(reporter, tree.find(i) == tree.end());
+    }
+    // remove all of the 0 entries. (tests removing begin())
+    REPORTER_ASSERT(reporter, *tree.begin() == 0);
+    REPORTER_ASSERT(reporter, *(--tree.end()) == 99);
+    while (0 != tree.countOf(0)) {
+        --count[0];
+        tree.remove(tree.find(0));
+    }
+    REPORTER_ASSERT(reporter, 0 == count[0]);
+    REPORTER_ASSERT(reporter, tree.findFirst(0) == tree.end());
+    REPORTER_ASSERT(reporter, tree.findLast(0) == tree.end());
+    REPORTER_ASSERT(reporter, tree.find(0) == tree.end());
+    REPORTER_ASSERT(reporter, 0 < *tree.begin());
+
+    // remove all the 99 entries (tests removing last()).
+    while (0 != tree.countOf(99)) {
+        --count[99];
+        tree.remove(tree.find(99));
+    }
+    REPORTER_ASSERT(reporter, 0 == count[99]);
+    REPORTER_ASSERT(reporter, tree.findFirst(99) == tree.end());
+    REPORTER_ASSERT(reporter, tree.findLast(99) == tree.end());
+    REPORTER_ASSERT(reporter, tree.find(99) == tree.end());
+    REPORTER_ASSERT(reporter, 99 > *(--tree.end()));
+    REPORTER_ASSERT(reporter, tree.last() == --tree.end());
+
+    // Make sure iteration still goes through correct number of entries
+    // and is still sorted correctly.
+    c = 0;
+    for (Tree::Iter a = tree.begin(); tree.end() != a; ++a) {
+        Tree::Iter b = a;
+        ++b;
+        ++c;
+        REPORTER_ASSERT(reporter, b == tree.end() || *a <= *b);
+    }
+    REPORTER_ASSERT(reporter, c == tree.count());
+
+    // repeat check that correct number of each entry is in the tree
+    // and iterates correctly both forward and backward.
+    for (int i = 0; i < 100; ++i) {
+        REPORTER_ASSERT(reporter, tree.countOf(i) == count[i]);
+        int c = 0;
+        Tree::Iter iter = tree.findFirst(i);
+        while (iter != tree.end() && *iter == i) {
+            ++c;
+            ++iter;
+        }
+        REPORTER_ASSERT(reporter, count[i] == c);
+        c = 0;
+        iter = tree.findLast(i);
+        if (iter != tree.end()) {
+            do {
+                if (*iter == i) {
+                    ++c;
+                } else {
+                    break;
+                }
+                if (iter != tree.begin()) {
+                    --iter;
+                } else {
+                    break;
+                }
+            } while (true);
+        }
+        REPORTER_ASSERT(reporter, count[i] == c);
+    }
+
+    // remove all entries
+    while (!tree.empty()) {
+        tree.remove(tree.begin());
+    }
+
+    // test reset on empty tree.
+    tree.reset();
+}