Browse Source

Merge branch 'trac2750'

Mukund Sivaraman 11 years ago
parent
commit
d3dbe8e164
2 changed files with 1356 additions and 193 deletions
  1. 939 106
      src/lib/datasrc/memory/domaintree.h
  2. 417 87
      src/lib/datasrc/tests/memory/domaintree_unittest.cc

File diff suppressed because it is too large
+ 939 - 106
src/lib/datasrc/memory/domaintree.h


+ 417 - 87
src/lib/datasrc/tests/memory/domaintree_unittest.cc

@@ -31,11 +31,17 @@
 
 
 #include <boost/format.hpp>
 #include <boost/format.hpp>
 
 
+#include <stdlib.h>
+
+#include <set>
+#include <algorithm>
+
 using namespace std;
 using namespace std;
 using namespace isc;
 using namespace isc;
 using namespace isc::dns;
 using namespace isc::dns;
 using isc::UnitTestUtil;
 using isc::UnitTestUtil;
 using namespace isc::datasrc::memory;
 using namespace isc::datasrc::memory;
+using isc::util::random::UniformRandomIntegerGenerator;
 
 
 // XXX: some compilers cannot find class static constants used in
 // XXX: some compilers cannot find class static constants used in
 // EXPECT_xxx macros, for which we need an explicit empty definition.
 // EXPECT_xxx macros, for which we need an explicit empty definition.
@@ -62,6 +68,53 @@ const size_t Name::MAX_LABELS;
 
 
 namespace {
 namespace {
 
 
+// The full absolute names of the nodes in the tree with the addition of
+// the explicit root node.
+const char* const domain_names[] = {
+    "c", "b", "a", "x.d.e.f", "z.d.e.f", "g.h", "i.g.h", "o.w.y.d.e.f",
+    "j.z.d.e.f", "p.w.y.d.e.f", "q.w.y.d.e.f", "k.g.h"
+};
+
+// These are set as the node data.
+const int node_distances[] = {
+    3, 1, 2, 2, 2, 3, 1, 2, 1, 1, 2, 2
+};
+
+const int name_count = sizeof(domain_names) / sizeof(domain_names[0]);
+
+/*
+ * The domain order should be:
+ * ., a, b, c, d.e.f, x.d.e.f, w.y.d.e.f, o.w.y.d.e.f, p.w.y.d.e.f,
+ * q.w.y.d.e.f, z.d.e.f, j.z.d.e.f, g.h, i.g.h, k.g.h
+ *             . (no data, can't be found)
+ *             |
+ *             b
+ *           /   \
+ *          a    d.e.f
+ *              /  |   \
+ *             c   |    g.h
+ *                 |     |
+ *                w.y    i
+ *              /  |  \   \
+ *             x   |   z   k
+ *                 |   |
+ *                 p   j
+ *               /   \
+ *              o     q
+ */
+
+const char* const ordered_names[] = {
+    "a", "b", "c", "d.e.f", "x.d.e.f", "w.y.d.e.f", "o.w.y.d.e.f",
+    "p.w.y.d.e.f", "q.w.y.d.e.f", "z.d.e.f", "j.z.d.e.f",
+    "g.h", "i.g.h", "k.g.h"};
+const size_t ordered_names_count(sizeof(ordered_names) /
+                                 sizeof(*ordered_names));
+
+const char* const upper_node_names[] = {
+    ".", ".", ".", ".", "d.e.f", "d.e.f", "w.y.d.e.f",
+    "w.y.d.e.f", "w.y.d.e.f", "d.e.f", "z.d.e.f",
+    ".", "g.h", "g.h"};
+
 void deleteData(int* i) {
 void deleteData(int* i) {
     delete i;
     delete i;
 }
 }
@@ -88,20 +141,13 @@ class DomainTreeTest : public::testing::Test {
 protected:
 protected:
     DomainTreeTest() :
     DomainTreeTest() :
         dtree_holder_(mem_sgmt_, TestDomainTree::create(mem_sgmt_)),
         dtree_holder_(mem_sgmt_, TestDomainTree::create(mem_sgmt_)),
-        dtree_expose_empty_node_holder_(mem_sgmt_,
-                                         TestDomainTree::create(mem_sgmt_, true)),
+        dtree_expose_empty_node_holder_
+            (mem_sgmt_, TestDomainTree::create(mem_sgmt_, true)),
         dtree(*dtree_holder_.get()),
         dtree(*dtree_holder_.get()),
         dtree_expose_empty_node(*dtree_expose_empty_node_holder_.get()),
         dtree_expose_empty_node(*dtree_expose_empty_node_holder_.get()),
-        cdtnode(NULL)
+        cdtnode(NULL),
+        name_gen_('a', 'z')
     {
     {
-        const char* const domain_names[] = {
-            "c", "b", "a", "x.d.e.f", "z.d.e.f", "g.h", "i.g.h", "o.w.y.d.e.f",
-            "j.z.d.e.f", "p.w.y.d.e.f", "q.w.y.d.e.f", "k.g.h"};
-        const int node_distances[] = {
-            3, 1, 2, 2, 2, 3, 1, 2, 1, 1, 2, 2
-        };
-
-        int name_count = sizeof(domain_names) / sizeof(domain_names[0]);
         for (int i = 0; i < name_count; ++i) {
         for (int i = 0; i < name_count; ++i) {
             dtree.insert(mem_sgmt_, Name(domain_names[i]), &dtnode);
             dtree.insert(mem_sgmt_, Name(domain_names[i]), &dtnode);
             // Check the node doesn't have any data initially.
             // Check the node doesn't have any data initially.
@@ -113,6 +159,8 @@ protected:
             EXPECT_EQ(static_cast<int*>(NULL), dtnode->setData(
             EXPECT_EQ(static_cast<int*>(NULL), dtnode->setData(
                           new int(node_distances[i])));
                           new int(node_distances[i])));
         }
         }
+
+        srandom(time(NULL));
     }
     }
 
 
     util::MemorySegmentLocal mem_sgmt_;
     util::MemorySegmentLocal mem_sgmt_;
@@ -122,6 +170,7 @@ protected:
     TestDomainTree& dtree_expose_empty_node;
     TestDomainTree& dtree_expose_empty_node;
     TestDomainTreeNode* dtnode;
     TestDomainTreeNode* dtnode;
     const TestDomainTreeNode* cdtnode;
     const TestDomainTreeNode* cdtnode;
+    UniformRandomIntegerGenerator name_gen_;
     uint8_t buf[LabelSequence::MAX_SERIALIZED_LENGTH];
     uint8_t buf[LabelSequence::MAX_SERIALIZED_LENGTH];
 };
 };
 
 
@@ -129,8 +178,8 @@ TEST_F(DomainTreeTest, nodeCount) {
     EXPECT_EQ(15, dtree.getNodeCount());
     EXPECT_EQ(15, dtree.getNodeCount());
 
 
     // Delete all nodes, then the count should be set to 0.  This also tests
     // Delete all nodes, then the count should be set to 0.  This also tests
-    // the behavior of deleteAllNodes().
-    dtree.deleteAllNodes(mem_sgmt_, deleteData);
+    // the behavior of removeAllNodes().
+    dtree.removeAllNodes(mem_sgmt_, deleteData);
     EXPECT_EQ(0, dtree.getNodeCount());
     EXPECT_EQ(0, dtree.getNodeCount());
 }
 }
 
 
@@ -150,22 +199,6 @@ TEST_F(DomainTreeTest, getDistance) {
     }
     }
 }
 }
 
 
-void
-checkDistances(const TestDomainTree& tree, int distance) {
-    TestDomainTreeNodeChain node_path;
-    const TestDomainTreeNode* node = NULL;
-
-    // Try to find a node left of the left-most node, and start from its
-    // next node (which is the left-most node in its subtree).
-    EXPECT_EQ(TestDomainTree::NOTFOUND,
-              tree.find<void*>(Name("0"), &node, node_path, NULL, NULL));
-    while ((node = tree.nextNode(node_path)) != NULL) {
-        // The distance from each node to its sub-tree root must be less
-        // than 2 * log(n).
-        EXPECT_GE(2 * distance, node->getDistance());
-    }
-}
-
 TEST_F(DomainTreeTest, checkDistanceRandom) {
 TEST_F(DomainTreeTest, checkDistanceRandom) {
     // This test checks an important performance-related property of the
     // This test checks an important performance-related property of the
     // DomainTree (a red-black tree), which is important for us: the
     // DomainTree (a red-black tree), which is important for us: the
@@ -176,7 +209,6 @@ TEST_F(DomainTreeTest, checkDistanceRandom) {
 
 
     TreeHolder mytree_holder(mem_sgmt_, TestDomainTree::create(mem_sgmt_));
     TreeHolder mytree_holder(mem_sgmt_, TestDomainTree::create(mem_sgmt_));
     TestDomainTree& mytree = *mytree_holder.get();
     TestDomainTree& mytree = *mytree_holder.get();
-    isc::util::random::UniformRandomIntegerGenerator gen('a', 'z');
     const int log_num_nodes = 20;
     const int log_num_nodes = 20;
 
 
     // Make a large million+ node top-level domain tree, i.e., the
     // Make a large million+ node top-level domain tree, i.e., the
@@ -191,7 +223,7 @@ TEST_F(DomainTreeTest, checkDistanceRandom) {
         string namestr;
         string namestr;
         while (true) {
         while (true) {
             for (int j = 0; j < 32; j++) {
             for (int j = 0; j < 32; j++) {
-                namestr += gen();
+                namestr += name_gen_();
             }
             }
             namestr += '.';
             namestr += '.';
 
 
@@ -206,7 +238,12 @@ TEST_F(DomainTreeTest, checkDistanceRandom) {
         EXPECT_EQ(static_cast<int*>(NULL), dtnode->setData(new int(i + 1)));
         EXPECT_EQ(static_cast<int*>(NULL), dtnode->setData(new int(i + 1)));
     }
     }
 
 
-    checkDistances(mytree, log_num_nodes);
+    // The distance from each node to its sub-tree root must be less
+    // than 2 * log(n).
+    EXPECT_GE(2 * log_num_nodes, mytree.getHeight());
+
+    // Also check RB tree properties
+    EXPECT_TRUE(mytree.checkProperties());
 }
 }
 
 
 TEST_F(DomainTreeTest, checkDistanceSorted) {
 TEST_F(DomainTreeTest, checkDistanceSorted) {
@@ -235,7 +272,12 @@ TEST_F(DomainTreeTest, checkDistanceSorted) {
         EXPECT_EQ(static_cast<int*>(NULL), dtnode->setData(new int(i + 1)));
         EXPECT_EQ(static_cast<int*>(NULL), dtnode->setData(new int(i + 1)));
     }
     }
 
 
-    checkDistances(mytree, log_num_nodes);
+    // The distance from each node to its sub-tree root must be less
+    // than 2 * log(n).
+    EXPECT_GE(2 * log_num_nodes, mytree.getHeight());
+
+    // Also check RB tree properties
+    EXPECT_TRUE(mytree.checkProperties());
 }
 }
 
 
 TEST_F(DomainTreeTest, setGetData) {
 TEST_F(DomainTreeTest, setGetData) {
@@ -344,6 +386,329 @@ TEST_F(DomainTreeTest, insertNames) {
                                                   &dtnode));
                                                   &dtnode));
 }
 }
 
 
+TEST_F(DomainTreeTest, remove) {
+    // This testcase checks that after node removal, the binary-search
+    // tree is valid and all nodes that are supposed to exist are
+    // present in the correct order. It mainly tests DomainTree as a
+    // BST, and not particularly as a red-black tree. This test checks
+    // node deletion when upper nodes have data.
+
+    // Delete single nodes and check if the rest of the nodes exist
+    for (int j = 0; j < ordered_names_count; ++j) {
+        TreeHolder holder(mem_sgmt_, TestDomainTree::create(mem_sgmt_, true));
+        TestDomainTree& tree(*holder.get());
+        TestDomainTreeNode* node;
+
+        for (int i = 0; i < name_count; ++i) {
+            tree.insert(mem_sgmt_, Name(domain_names[i]), NULL);
+        }
+
+        for (int i = 0; i < ordered_names_count; ++i) {
+            EXPECT_EQ(TestDomainTree::EXACTMATCH,
+                      tree.find(Name(ordered_names[i]), &node));
+            // Check nodes are not empty.
+            EXPECT_EQ(static_cast<int*>(NULL), node->setData(new int(i)));
+            EXPECT_FALSE(node->isEmpty());
+        }
+
+        // Now, delete the j'th node from the tree.
+        EXPECT_EQ(TestDomainTree::EXACTMATCH,
+                  tree.find(Name(ordered_names[j]), &node));
+        tree.remove(mem_sgmt_, node, deleteData);
+
+        // Check RB tree properties
+        ASSERT_TRUE(tree.checkProperties());
+
+        // Now, walk through nodes in order.
+        TestDomainTreeNodeChain node_path;
+        const TestDomainTreeNode* cnode;
+        int start_node;
+
+        if (j == 0) {
+            EXPECT_NE(TestDomainTree::EXACTMATCH,
+                      tree.find(Name(ordered_names[0]),
+                                &cnode));
+            EXPECT_EQ(TestDomainTree::EXACTMATCH,
+                      tree.find(Name(ordered_names[1]),
+                                &cnode, node_path));
+            start_node = 1;
+        } else {
+            EXPECT_EQ(TestDomainTree::EXACTMATCH,
+                      tree.find(Name(ordered_names[0]),
+                                &cnode, node_path));
+            start_node = 0;
+        }
+
+        for (int i = start_node; i < ordered_names_count; ++i) {
+            const Name nj(ordered_names[j]);
+            const Name ni(ordered_names[i]);
+
+            if (ni == nj) {
+                // This may be true for the last node if we seek ahead
+                // in the loop using nextNode() below.
+                if (!cnode) {
+                    break;
+                }
+                // All ordered nodes have data initially. If any node is
+                // empty, it means it was remove()d, but an empty node
+                // exists because it is a super-domain. Just skip it.
+                if (cnode->isEmpty()) {
+                     cnode = tree.nextNode(node_path);
+                }
+                continue;
+            }
+
+            ASSERT_NE(static_cast<void*>(NULL), cnode);
+            const int* data = cnode->getData();
+
+            if (data) {
+                 EXPECT_EQ(i, *data);
+            }
+
+            uint8_t buf[isc::dns::LabelSequence::MAX_SERIALIZED_LENGTH];
+            const LabelSequence ls(cnode->getAbsoluteLabels(buf));
+            EXPECT_EQ(LabelSequence(ni), ls);
+
+            cnode = tree.nextNode(node_path);
+        }
+
+        // We should have reached the end of the tree.
+        ASSERT_EQ(static_cast<void*>(NULL), cnode);
+    }
+}
+
+TEST_F(DomainTreeTest, removeEmpty) {
+    // This test is similar to the .remove test. But it checks node
+    // deletion when upper nodes are empty.
+
+    // Delete single nodes and check if the rest of the nodes exist
+    for (int j = 0; j < ordered_names_count; ++j) {
+        TreeHolder holder(mem_sgmt_, TestDomainTree::create(mem_sgmt_, true));
+        TestDomainTree& tree(*holder.get());
+        TestDomainTreeNode* node;
+
+        for (int i = 0; i < name_count; ++i) {
+            tree.insert(mem_sgmt_, Name(domain_names[i]), NULL);
+        }
+
+        for (int i = 0; i < ordered_names_count; ++i) {
+            EXPECT_EQ(TestDomainTree::EXACTMATCH,
+                      tree.find(Name(ordered_names[i]), &node));
+            // Check nodes are empty.
+            EXPECT_TRUE(node->isEmpty());
+        }
+
+        // Now, delete the j'th node from the tree.
+        EXPECT_EQ(TestDomainTree::EXACTMATCH,
+                  tree.find(Name(ordered_names[j]), &node));
+        tree.remove(mem_sgmt_, node, deleteData);
+
+        // Check RB tree properties
+        ASSERT_TRUE(tree.checkProperties());
+
+        // Now, walk through nodes in order.
+        TestDomainTreeNodeChain node_path;
+        const TestDomainTreeNode* cnode;
+        int start_node;
+
+        if (j == 0) {
+            EXPECT_NE(TestDomainTree::EXACTMATCH,
+                      tree.find(Name(ordered_names[0]),
+                                &cnode));
+            EXPECT_EQ(TestDomainTree::EXACTMATCH,
+                      tree.find(Name(ordered_names[1]),
+                                &cnode, node_path));
+            start_node = 1;
+        } else {
+            EXPECT_EQ(TestDomainTree::EXACTMATCH,
+                      tree.find(Name(ordered_names[0]),
+                                &cnode, node_path));
+            start_node = 0;
+        }
+
+        for (int i = start_node; i < ordered_names_count; ++i) {
+            const Name nj(ordered_names[j]);
+            const Name ni(ordered_names[i]);
+
+            if ((nj == Name("j.z.d.e.f")) &&
+                (ni == Name("z.d.e.f")))
+            {
+                // The only special case in the tree. Here, "z.d.e.f"
+                // will not exist as it would have been removed during
+                // removal of "j.z.d.e.f".
+                continue;
+            }
+
+            if (ni == nj) {
+                // This may be true for the last node if we seek ahead
+                // in the loop using nextNode() below.
+                if (!cnode) {
+                    break;
+                }
+                // All ordered nodes are empty initially. If an empty
+                // removed node exists because it is a super-domain,
+                // just skip it.
+                if ((nj == Name("d.e.f")) ||
+                    (nj == Name("w.y.d.e.f")) ||
+                    (nj == Name("z.d.e.f")) ||
+                    (nj == Name("g.h")))
+                {
+                     cnode = tree.nextNode(node_path);
+                }
+                continue;
+            }
+
+            ASSERT_NE(static_cast<void*>(NULL), cnode);
+
+            uint8_t buf[isc::dns::LabelSequence::MAX_SERIALIZED_LENGTH];
+            const LabelSequence ls(cnode->getAbsoluteLabels(buf));
+            EXPECT_EQ(LabelSequence(ni), ls);
+
+            cnode = tree.nextNode(node_path);
+        }
+
+        // We should have reached the end of the tree.
+        ASSERT_EQ(static_cast<void*>(NULL), cnode);
+    }
+}
+
+void
+insertNodes(util::MemorySegment& mem_sgmt, TestDomainTree& tree,
+            std::set<std::string>& names, size_t num_nodes,
+            UniformRandomIntegerGenerator& name_gen)
+{
+    for (size_t i = 0; i < num_nodes; ++i) {
+        std::string namestr;
+        while (true) {
+            for (int j = 0; j < 32; j++) {
+                namestr += name_gen();
+            }
+            namestr += '.';
+
+            TestDomainTreeNode* cnode;
+            if (tree.insert(mem_sgmt, Name(namestr), &cnode) ==
+                TestDomainTree::SUCCESS) {
+                names.insert(namestr);
+                break;
+            }
+
+            namestr.clear();
+        }
+    }
+}
+
+void
+removeNodes(util::MemorySegment& mem_sgmt, TestDomainTree& tree,
+            std::set<std::string>& names, size_t num_nodes)
+{
+    size_t set_size = names.size();
+
+    for (size_t i = 0; i < num_nodes; ++i) {
+        // Here, UniformRandomIntegerGenerator is not a great RNG as
+        // it'll likely get seeded with the same seed throughout this
+        // testcase, and the size of the names set keeps changing.
+
+        std::set<std::string>::iterator it(names.begin());
+        // This is rather inefficient, but it's a test...
+        std::advance(it, random() % set_size);
+        std::string nstr(*it);
+
+        TestDomainTreeNode* node;
+        EXPECT_EQ(TestDomainTree::EXACTMATCH,
+                  tree.find(Name(nstr), &node));
+
+        tree.remove(mem_sgmt, node, deleteData);
+
+        names.erase(*it);
+        --set_size;
+    }
+}
+
+void
+checkTree(const TestDomainTree& tree,
+          const std::set<std::string>& names)
+{
+    // The distance from each node to its sub-tree root must be less
+    // than 2 * log_2(1024).
+    EXPECT_GE(2 * 10, tree.getHeight());
+
+    // Also check RB tree properties
+    EXPECT_TRUE(tree.checkProperties());
+
+    // Now, walk through nodes in order.
+    TestDomainTreeNodeChain node_path;
+    const TestDomainTreeNode* cnode;
+
+    EXPECT_EQ(TestDomainTree::EXACTMATCH,
+              tree.find(Name("."), &cnode, node_path));
+
+    // Skip to the next node after "."
+    cnode = tree.nextNode(node_path);
+    if (names.empty()) {
+        // Empty tree.
+        EXPECT_EQ(static_cast<void*>(NULL), cnode);
+        return;
+    }
+
+    for (std::set<std::string>::const_iterator it = names.begin();
+         it != names.end(); ++it)
+    {
+        const Name n1(*it);
+        const Name n2(cnode->getName());
+
+        const NameComparisonResult result = n1.compare(n2);
+        EXPECT_EQ(NameComparisonResult::EQUAL, result.getRelation());
+
+        cnode = tree.nextNode(node_path);
+    }
+
+    // We should have reached the end of the tree.
+    EXPECT_EQ(static_cast<void*>(NULL), cnode);
+}
+
+TEST_F(DomainTreeTest, insertAndRemove) {
+    // What is the best way to test our red-black tree code? It is not a
+    // good method to test every case handled in the actual code itself
+    // (such as in insertRebalance() and removeRebalance()). This is
+    // because our approach itself may be incorrect.
+    //
+    // We test our code at the interface level here by exercising the
+    // tree randomly multiple times, checking that red-black tree
+    // properties are valid, and all the nodes that are supposed to be
+    // in the tree exist and are in order.
+
+    // NOTE: These tests are run within a single tree in the
+    // forest. Fusion, etc. are tested elsewhere. The number of nodes in
+    // the tree doesn't grow over 1024.
+
+    TreeHolder holder(mem_sgmt_, TestDomainTree::create(mem_sgmt_, true));
+    TestDomainTree& tree(*holder.get());
+    std::set<std::string> names;
+
+    size_t node_count = 0;
+
+    // Repeat the insert/remove test some 4096 times
+    for (int i = 0; i < 4096; ++i) {
+         UniformRandomIntegerGenerator gen(1, 1024 - node_count);
+         size_t num_nodes = gen();
+         node_count += num_nodes;
+
+         insertNodes(mem_sgmt_, tree, names, num_nodes, name_gen_);
+         checkTree(tree, names);
+
+         UniformRandomIntegerGenerator gen2(1, node_count);
+         num_nodes = gen2();
+         node_count -= num_nodes;
+
+         removeNodes(mem_sgmt_, tree, names, num_nodes);
+         checkTree(tree, names);
+    }
+
+    // Remove the rest of the nodes.
+    removeNodes(mem_sgmt_, tree, names, node_count);
+    checkTree(tree, names);
+}
+
 TEST_F(DomainTreeTest, subTreeRoot) {
 TEST_F(DomainTreeTest, subTreeRoot) {
     // This is a testcase for a particular issue that went unchecked in
     // This is a testcase for a particular issue that went unchecked in
     // #2089's implementation, but was fixed in #2092. The issue was
     // #2089's implementation, but was fixed in #2092. The issue was
@@ -778,45 +1143,14 @@ TEST_F(DomainTreeTest, getAbsoluteNameError) {
     EXPECT_THROW(chain.getAbsoluteName(), BadValue);
     EXPECT_THROW(chain.getAbsoluteName(), BadValue);
 }
 }
 
 
-/*
- * The domain order should be:
- * ., a, b, c, d.e.f, x.d.e.f, w.y.d.e.f, o.w.y.d.e.f, p.w.y.d.e.f,
- * q.w.y.d.e.f, z.d.e.f, j.z.d.e.f, g.h, i.g.h, k.g.h
- *             . (no data, can't be found)
- *             |
- *             b
- *           /   \
- *          a    d.e.f
- *              /  |   \
- *             c   |    g.h
- *                 |     |
- *                w.y    i
- *              /  |  \   \
- *             x   |   z   k
- *                 |   |
- *                 p   j
- *               /   \
- *              o     q
- */
-const char* const names[] = {
-    "a", "b", "c", "d.e.f", "x.d.e.f", "w.y.d.e.f", "o.w.y.d.e.f",
-    "p.w.y.d.e.f", "q.w.y.d.e.f", "z.d.e.f", "j.z.d.e.f",
-    "g.h", "i.g.h", "k.g.h"};
-const size_t name_count(sizeof(names) / sizeof(*names));
-
-const char* const upper_node_names[] = {
-    ".", ".", ".", ".", "d.e.f", "d.e.f", "w.y.d.e.f",
-    "w.y.d.e.f", "w.y.d.e.f", "d.e.f", "z.d.e.f",
-    ".", "g.h", "g.h"};
-
 TEST_F(DomainTreeTest, getUpperNode) {
 TEST_F(DomainTreeTest, getUpperNode) {
     TestDomainTreeNodeChain node_path;
     TestDomainTreeNodeChain node_path;
     const TestDomainTreeNode* node = NULL;
     const TestDomainTreeNode* node = NULL;
     EXPECT_EQ(TestDomainTree::EXACTMATCH,
     EXPECT_EQ(TestDomainTree::EXACTMATCH,
-              dtree_expose_empty_node.find(Name(names[0]),
-                                            &node,
-                                            node_path));
-    for (int i = 0; i < name_count; ++i) {
+              dtree_expose_empty_node.find(Name(ordered_names[0]),
+                                           &node,
+                                           node_path));
+    for (int i = 0; i < ordered_names_count; ++i) {
         EXPECT_NE(static_cast<void*>(NULL), node);
         EXPECT_NE(static_cast<void*>(NULL), node);
 
 
         const TestDomainTreeNode* upper_node = node->getUpperNode();
         const TestDomainTreeNode* upper_node = node->getUpperNode();
@@ -852,7 +1186,7 @@ TEST_F(DomainTreeTest, getSubTreeRoot) {
     TestDomainTreeNodeChain node_path;
     TestDomainTreeNodeChain node_path;
     const TestDomainTreeNode* node = NULL;
     const TestDomainTreeNode* node = NULL;
     EXPECT_EQ(TestDomainTree::EXACTMATCH,
     EXPECT_EQ(TestDomainTree::EXACTMATCH,
-              dtree_expose_empty_node.find(Name(names[0]),
+              dtree_expose_empty_node.find(Name(ordered_names[0]),
                                             &node,
                                             &node,
                                             node_path));
                                             node_path));
     for (int i = 0; i < name_count; ++i) {
     for (int i = 0; i < name_count; ++i) {
@@ -884,10 +1218,10 @@ TEST_F(DomainTreeTest, nextNode) {
     TestDomainTreeNodeChain node_path;
     TestDomainTreeNodeChain node_path;
     const TestDomainTreeNode* node = NULL;
     const TestDomainTreeNode* node = NULL;
     EXPECT_EQ(TestDomainTree::EXACTMATCH,
     EXPECT_EQ(TestDomainTree::EXACTMATCH,
-              dtree.find(Name(names[0]), &node, node_path));
-    for (int i = 0; i < name_count; ++i) {
+              dtree.find(Name(ordered_names[0]), &node, node_path));
+    for (int i = 0; i < ordered_names_count; ++i) {
         EXPECT_NE(static_cast<void*>(NULL), node);
         EXPECT_NE(static_cast<void*>(NULL), node);
-        EXPECT_EQ(Name(names[i]), node_path.getAbsoluteName());
+        EXPECT_EQ(Name(ordered_names[i]), node_path.getAbsoluteName());
         node = dtree.nextNode(node_path);
         node = dtree.nextNode(node_path);
     }
     }
 
 
@@ -903,7 +1237,7 @@ TEST_F(DomainTreeTest, nextNode) {
 // node_path - the path from the previous call to find(), will be modified
 // node_path - the path from the previous call to find(), will be modified
 // chain_length - the number of names that should be in the chain to be walked
 // chain_length - the number of names that should be in the chain to be walked
 //   (0 means it should be empty, 3 means 'a', 'b' and 'c' should be there -
 //   (0 means it should be empty, 3 means 'a', 'b' and 'c' should be there -
-//   this is always from the beginning of the names[] list).
+//   this is always from the beginning of the ordered_names[] list).
 // skip_first - if this is false, the node should already contain the node with
 // skip_first - if this is false, the node should already contain the node with
 //   the first name of the chain. If it is true, the node should be NULL
 //   the first name of the chain. If it is true, the node should be NULL
 //   (true is for finds that return no match, false for the ones that return
 //   (true is for finds that return no match, false for the ones that return
@@ -921,7 +1255,7 @@ previousWalk(TestDomainTree& dtree, const TestDomainTreeNode* node,
     }
     }
     for (size_t i(chain_length); i > 0; --i) {
     for (size_t i(chain_length); i > 0; --i) {
         EXPECT_NE(static_cast<void*>(NULL), node);
         EXPECT_NE(static_cast<void*>(NULL), node);
-        EXPECT_EQ(Name(names[i - 1]), node_path.getAbsoluteName());
+        EXPECT_EQ(Name(ordered_names[i - 1]), node_path.getAbsoluteName());
         // Find the node at the path and check the value is the same
         // Find the node at the path and check the value is the same
         // (that it really returns the correct corresponding node)
         // (that it really returns the correct corresponding node)
         //
         //
@@ -930,7 +1264,8 @@ previousWalk(TestDomainTree& dtree, const TestDomainTreeNode* node,
             const TestDomainTreeNode* node2(NULL);
             const TestDomainTreeNode* node2(NULL);
             TestDomainTreeNodeChain node_path2;
             TestDomainTreeNodeChain node_path2;
             EXPECT_EQ(TestDomainTree::EXACTMATCH,
             EXPECT_EQ(TestDomainTree::EXACTMATCH,
-                      dtree.find(Name(names[i - 1]), &node2, node_path2));
+                      dtree.find(Name(ordered_names[i - 1]),
+                                 &node2, node_path2));
             EXPECT_EQ(node, node2);
             EXPECT_EQ(node, node2);
         }
         }
         node = dtree.previousNode(node_path);
         node = dtree.previousNode(node_path);
@@ -960,8 +1295,9 @@ TEST_F(DomainTreeTest, previousNode) {
     {
     {
         SCOPED_TRACE("Iterate through");
         SCOPED_TRACE("Iterate through");
         EXPECT_EQ(TestDomainTree::EXACTMATCH,
         EXPECT_EQ(TestDomainTree::EXACTMATCH,
-                  dtree.find(Name(names[name_count - 1]), &node, node_path));
-        previousWalk(dtree, node, node_path, name_count, false);
+                  dtree.find(Name(ordered_names[ordered_names_count - 1]),
+                             &node, node_path));
+        previousWalk(dtree, node, node_path, ordered_names_count, false);
         node = NULL;
         node = NULL;
         node_path.clear();
         node_path.clear();
     }
     }
@@ -970,7 +1306,7 @@ TEST_F(DomainTreeTest, previousNode) {
         SCOPED_TRACE("Iterate from the middle");
         SCOPED_TRACE("Iterate from the middle");
         // Now, start somewhere in the middle, but within the real node.
         // Now, start somewhere in the middle, but within the real node.
         EXPECT_EQ(TestDomainTree::EXACTMATCH,
         EXPECT_EQ(TestDomainTree::EXACTMATCH,
-                  dtree.find(Name(names[4]), &node, node_path));
+                  dtree.find(Name(ordered_names[4]), &node, node_path));
         previousWalk(dtree, node, node_path, 5, false);
         previousWalk(dtree, node, node_path, 5, false);
         node = NULL;
         node = NULL;
         node_path.clear();
         node_path.clear();
@@ -981,7 +1317,7 @@ TEST_F(DomainTreeTest, previousNode) {
         // If we start at the lowest (which is "a"), we get to the beginning
         // If we start at the lowest (which is "a"), we get to the beginning
         // right away.
         // right away.
         EXPECT_EQ(TestDomainTree::EXACTMATCH,
         EXPECT_EQ(TestDomainTree::EXACTMATCH,
-                  dtree.find(Name(names[0]), &node, node_path));
+                  dtree.find(Name(ordered_names[0]), &node, node_path));
         EXPECT_NE(static_cast<void*>(NULL), node);
         EXPECT_NE(static_cast<void*>(NULL), node);
         node = dtree.previousNode(node_path);
         node = dtree.previousNode(node_path);
         ASSERT_NE(static_cast<void*>(NULL), node);
         ASSERT_NE(static_cast<void*>(NULL), node);
@@ -1008,7 +1344,7 @@ TEST_F(DomainTreeTest, previousNode) {
         SCOPED_TRACE("Start after the last");
         SCOPED_TRACE("Start after the last");
         EXPECT_EQ(TestDomainTree::NOTFOUND,
         EXPECT_EQ(TestDomainTree::NOTFOUND,
                   dtree.find(Name("z"), &node, node_path));
                   dtree.find(Name("z"), &node, node_path));
-        previousWalk(dtree, node, node_path, name_count, true);
+        previousWalk(dtree, node, node_path, ordered_names_count, true);
         node = NULL;
         node = NULL;
         node_path.clear();
         node_path.clear();
     }
     }
@@ -1070,7 +1406,7 @@ TEST_F(DomainTreeTest, previousNode) {
         EXPECT_GT(node_path.getLastComparisonResult().getOrder(), 0);
         EXPECT_GT(node_path.getLastComparisonResult().getOrder(), 0);
         // We then descend into 'i.g.h' and walk all the nodes in the
         // We then descend into 'i.g.h' and walk all the nodes in the
         // tree.
         // tree.
-        previousWalk(dtree, node, node_path, name_count, true);
+        previousWalk(dtree, node, node_path, ordered_names_count, true);
         node = NULL;
         node = NULL;
         node_path.clear();
         node_path.clear();
     }
     }
@@ -1364,17 +1700,11 @@ TEST_F(DomainTreeTest, root) {
 }
 }
 
 
 TEST_F(DomainTreeTest, getAbsoluteLabels) {
 TEST_F(DomainTreeTest, getAbsoluteLabels) {
-    // The full absolute names of the nodes in the tree
-    // with the addition of the explicit root node
-    const char* const domain_names[] = {
-        "c", "b", "a", "x.d.e.f", "z.d.e.f", "g.h", "i.g.h", "o.w.y.d.e.f",
-        "j.z.d.e.f", "p.w.y.d.e.f", "q.w.y.d.e.f", "k.g.h"};
     // The names of the nodes themselves, as they end up in the tree
     // The names of the nodes themselves, as they end up in the tree
     const char* const first_labels[] = {
     const char* const first_labels[] = {
         "c", "b", "a", "x", "z", "g.h", "i", "o",
         "c", "b", "a", "x", "z", "g.h", "i", "o",
         "j", "p", "q", "k"};
         "j", "p", "q", "k"};
 
 
-    const int name_count = sizeof(domain_names) / sizeof(domain_names[0]);
     for (int i = 0; i < name_count; ++i) {
     for (int i = 0; i < name_count; ++i) {
         EXPECT_EQ(TestDomainTree::EXACTMATCH, dtree.find(Name(domain_names[i]),
         EXPECT_EQ(TestDomainTree::EXACTMATCH, dtree.find(Name(domain_names[i]),
                   &cdtnode));
                   &cdtnode));