Browse Source

add more unittest for rbtree

git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac397@3457 e5f2f494-b856-4b98-b285-d166d9295462
Jerry 14 years ago
parent
commit
14937ed405

+ 1 - 1
src/bin/auth/auth_srv.cc

@@ -435,7 +435,7 @@ AuthSrvImpl::processNotify(const IOMessage& io_message, Message& message,
         }
         }
         return (false);
         return (false);
     }
     }
-    
+
     const string remote_ip_address =
     const string remote_ip_address =
         io_message.getRemoteEndpoint().getAddress().toText();
         io_message.getRemoteEndpoint().getAddress().toText();
     static const string command_template_start =
     static const string command_template_start =

+ 10 - 10
src/bin/auth/rbt_datasrc.cc

@@ -46,7 +46,7 @@ RBNode::~RBNode() {
         delete down_;
         delete down_;
 }
 }
 
 
-RBNode* 
+RBNode*
 RBNode::successor() {
 RBNode::successor() {
     RBNode* current = this;
     RBNode* current = this;
 
 
@@ -128,14 +128,14 @@ RBTree::~RBTree() {
     root_ = NULL;
     root_ = NULL;
 }
 }
 
 
-RBTree::FindResult 
+RBTree::FindResult
 RBTree::find(const Name &name, RBNode **node)const {
 RBTree::find(const Name &name, RBNode **node)const {
     RBTree *tree;
     RBTree *tree;
     return findHelper(name, &tree, node);
     return findHelper(name, &tree, node);
 }
 }
 
 
 
 
-RBTree::FindResult 
+RBTree::FindResult
 RBTree::findHelper(const Name &name, RBTree **tree, RBNode **ret)const {
 RBTree::findHelper(const Name &name, RBTree **tree, RBNode **ret)const {
     RBNode* node = root_;
     RBNode* node = root_;
     while (node != NULLNODE) {
     while (node != NULLNODE) {
@@ -187,7 +187,7 @@ RBTree::getNodeCountHelper(const RBNode *node) const {
     return 1 + sub_tree_node_count + getNodeCountHelper(node->left_) + getNodeCountHelper(node->right_);
     return 1 + sub_tree_node_count + getNodeCountHelper(node->left_) + getNodeCountHelper(node->right_);
 }
 }
 
 
-int 
+int
 RBTree::insert(const Name &name, RBNode **new_node) {
 RBTree::insert(const Name &name, RBNode **new_node) {
     RBNode* parent = NULLNODE;
     RBNode* parent = NULLNODE;
     RBNode* current = root_;
     RBNode* current = root_;
@@ -262,7 +262,7 @@ RBTree::insert(const Name &name, RBNode **new_node) {
     return 0;
     return 0;
 }
 }
 
 
-void 
+void
 RBTree::insertRebalance(RBNode * node) {
 RBTree::insertRebalance(RBNode * node) {
     RBNode* uncle;
     RBNode* uncle;
 
 
@@ -313,7 +313,7 @@ RBTree::insertRebalance(RBNode * node) {
 }
 }
 
 
 
 
-RBNode* 
+RBNode*
 RBTree::leftRotate(RBNode * p) {
 RBTree::leftRotate(RBNode * p) {
     RBNode* c = p->right_;
     RBNode* c = p->right_;
 
 
@@ -337,7 +337,7 @@ RBTree::leftRotate(RBNode * p) {
     return c;
     return c;
 }
 }
 
 
-RBNode* 
+RBNode*
 RBTree::rightRotate(RBNode * p) {
 RBTree::rightRotate(RBNode * p) {
     RBNode* c = p->left_;
     RBNode* c = p->left_;
 
 
@@ -362,7 +362,7 @@ RBTree::rightRotate(RBNode * p) {
 }
 }
 
 
 
 
-int 
+int
 RBTree::erase(const Name &name) {
 RBTree::erase(const Name &name) {
     RBNode *node;
     RBNode *node;
     RBTree *tree;
     RBTree *tree;
@@ -393,7 +393,7 @@ RBTree::erase(const Name &name) {
 }
 }
 
 
 
 
-void 
+void
 RBTree::eraseNode(RBNode *node) {
 RBTree::eraseNode(RBNode *node) {
     RBNode* y = NULLNODE;
     RBNode* y = NULLNODE;
     RBNode* x = NULLNODE;
     RBNode* x = NULLNODE;
@@ -436,7 +436,7 @@ RBTree::eraseNode(RBNode *node) {
     --node_count_;
     --node_count_;
 }
 }
 
 
-void 
+void
 RBTree::deleteRebalance(RBNode * node) {
 RBTree::deleteRebalance(RBNode * node) {
     RBNode* w = NULLNODE;
     RBNode* w = NULLNODE;
 
 

+ 4 - 4
src/bin/auth/rbt_datasrc.h

@@ -74,7 +74,7 @@ class RBNode {
 };
 };
 
 
 /// RBTree is a generic red black tree, it contains all the node with same suffix
 /// RBTree is a generic red black tree, it contains all the node with same suffix
-/// So for one zone, severl RBTrees are involved. But from outside, the sub tree is 
+/// So for one zone, severl RBTrees are involved. But from outside, the sub tree is
 /// opaque for end user. if the sub tree only has one node and the base node which is pointed by the
 /// opaque for end user. if the sub tree only has one node and the base node which is pointed by the
 /// "up_" pointer is one non-terminal, the single node will merge with the "up_" node then the sub tree will
 /// "up_" pointer is one non-terminal, the single node will merge with the "up_" node then the sub tree will
 /// be deleted
 /// be deleted
@@ -95,10 +95,10 @@ class RBTree {
         /// the interface just used for test the tree logic, later will be removed
         /// the interface just used for test the tree logic, later will be removed
         int getNodeCount() const;
         int getNodeCount() const;
 
 
-        
+
         void printTree(int depth = 0)const;
         void printTree(int depth = 0)const;
-    
-        /// if the name exists, return value will be one, and inserted_node will point to 
+
+        /// if the name exists, return value will be one, and inserted_node will point to
         /// the existed node, otherwise return value is zero, and inserted_node points to
         /// the existed node, otherwise return value is zero, and inserted_node points to
         /// new created node
         /// new created node
         int insert(const Name &name, RBNode **inserted_node);
         int insert(const Name &name, RBNode **inserted_node);

+ 91 - 33
src/bin/auth/tests/rbt_datasrc_unittest.cc

@@ -34,14 +34,14 @@ using namespace isc::datasrc;
  *             b
  *             b
  *           /   \
  *           /   \
  *          a    d.e.f
  *          a    d.e.f
- *               / | \
- *              c  |  g.h
- *                 |
- *                w.y
- *               / | \
- *              x  |  z
- *                 |
- *                 p
+ *              /  |   \
+ *             c   |    g.h
+ *                 |     |
+ *                w.y    i
+ *              /  |  \
+ *             x   |   z
+ *                 |   |
+ *                 p   j
  *               /   \
  *               /   \
  *              o     q
  *              o     q
  */
  */
@@ -57,7 +57,9 @@ protected:
         rbtree.insert(Name("x.d.e.f"), &rbtnode);
         rbtree.insert(Name("x.d.e.f"), &rbtnode);
         rbtree.insert(Name("z.d.e.f"), &rbtnode);
         rbtree.insert(Name("z.d.e.f"), &rbtnode);
         rbtree.insert(Name("g.h"), &rbtnode);
         rbtree.insert(Name("g.h"), &rbtnode);
+        rbtree.insert(Name("i.g.h"), &rbtnode);
         rbtree.insert(Name("o.w.y.d.e.f"), &rbtnode);
         rbtree.insert(Name("o.w.y.d.e.f"), &rbtnode);
+        rbtree.insert(Name("j.z.d.e.f"), &rbtnode);
         rbtree.insert(Name("p.w.y.d.e.f"), &rbtnode);
         rbtree.insert(Name("p.w.y.d.e.f"), &rbtnode);
         rbtree.insert(Name("q.w.y.d.e.f"), &rbtnode);
         rbtree.insert(Name("q.w.y.d.e.f"), &rbtnode);
     }
     }
@@ -67,41 +69,54 @@ protected:
 
 
 
 
 TEST_F(RBTreeTest, getNodeCount) {
 TEST_F(RBTreeTest, getNodeCount) {
-    EXPECT_EQ(11, rbtree.getNodeCount());
+    EXPECT_EQ(13, rbtree.getNodeCount());
 }
 }
 
 
 TEST_F(RBTreeTest, insertNames) {
 TEST_F(RBTreeTest, insertNames) {
     // a node is considered to "formally" exist only if it has data
     // a node is considered to "formally" exist only if it has data
     // associated with it
     // associated with it
 
 
+    // EXPECT_EQ(0, rbtree.insert(Name("r"), &rbtnode));
     // return 0, since node "d.e.f" doesn't have data
     // return 0, since node "d.e.f" doesn't have data
     EXPECT_EQ(0, rbtree.insert(Name("d.e.f"), &rbtnode));
     EXPECT_EQ(0, rbtree.insert(Name("d.e.f"), &rbtnode));
     EXPECT_EQ(Name("d.e.f"), rbtnode->getName());
     EXPECT_EQ(Name("d.e.f"), rbtnode->getName());
-    EXPECT_EQ(11, rbtree.getNodeCount());
+    EXPECT_EQ(13, rbtree.getNodeCount());
 
 
     EXPECT_EQ(0, rbtree.insert(Name("."), &rbtnode));
     EXPECT_EQ(0, rbtree.insert(Name("."), &rbtnode));
     EXPECT_EQ(Name("."), rbtnode->getName());
     EXPECT_EQ(Name("."), rbtnode->getName());
-    EXPECT_EQ(12, rbtree.getNodeCount());
+    EXPECT_EQ(14, rbtree.getNodeCount());
 
 
     EXPECT_EQ(0, rbtree.insert(Name("example.com"), &rbtnode));
     EXPECT_EQ(0, rbtree.insert(Name("example.com"), &rbtnode));
-    EXPECT_EQ(13, rbtree.getNodeCount());
+    EXPECT_EQ(15, rbtree.getNodeCount());
 
 
     // return 1, since node "d.e.f" already has data associated with it
     // return 1, since node "d.e.f" already has data associated with it
     RRsetPtr rrset = RRsetPtr(new RRset(Name("example.com"), RRClass::IN(), RRType::NS(),
     RRsetPtr rrset = RRsetPtr(new RRset(Name("example.com"), RRClass::IN(), RRType::NS(),
                                        RRTTL(3600)));
                                        RRTTL(3600)));
     rbtnode->addRRset(rrset);
     rbtnode->addRRset(rrset);
     EXPECT_EQ(1, rbtree.insert(Name("example.com"), &rbtnode));
     EXPECT_EQ(1, rbtree.insert(Name("example.com"), &rbtnode));
-    EXPECT_EQ(13, rbtree.getNodeCount());
+    EXPECT_EQ(15, rbtree.getNodeCount());
 
 
     // split the node "d.e.f"
     // split the node "d.e.f"
     EXPECT_EQ(0, rbtree.insert(Name("k.e.f"), &rbtnode));
     EXPECT_EQ(0, rbtree.insert(Name("k.e.f"), &rbtnode));
     EXPECT_EQ(Name("k"), rbtnode->getName());
     EXPECT_EQ(Name("k"), rbtnode->getName());
-    EXPECT_EQ(15, rbtree.getNodeCount());
+    EXPECT_EQ(17, rbtree.getNodeCount());
 
 
     // split the node "g.h"
     // split the node "g.h"
     EXPECT_EQ(0, rbtree.insert(Name("h"), &rbtnode));
     EXPECT_EQ(0, rbtree.insert(Name("h"), &rbtnode));
     EXPECT_EQ(Name("h"), rbtnode->getName());
     EXPECT_EQ(Name("h"), rbtnode->getName());
-    EXPECT_EQ(16, rbtree.getNodeCount());
+    EXPECT_EQ(18, rbtree.getNodeCount());
+
+    // add child domain
+    EXPECT_EQ(0, rbtree.insert(Name("m.p.w.y.d.e.f"), &rbtnode));
+    EXPECT_EQ(Name("m"), rbtnode->getName());
+    EXPECT_EQ(19, rbtree.getNodeCount());
+    EXPECT_EQ(0, rbtree.insert(Name("n.p.w.y.d.e.f"), &rbtnode));
+    EXPECT_EQ(Name("n"), rbtnode->getName());
+    EXPECT_EQ(20, rbtree.getNodeCount());
+
+    EXPECT_EQ(0, rbtree.insert(Name("l.a"), &rbtnode));
+    EXPECT_EQ(Name("l"), rbtnode->getName());
+    EXPECT_EQ(21, rbtree.getNodeCount());
 }
 }
 
 
 TEST_F(RBTreeTest, findName) {
 TEST_F(RBTreeTest, findName) {
@@ -114,7 +129,8 @@ TEST_F(RBTreeTest, findName) {
     // not found
     // not found
     EXPECT_EQ(RBTree::NOTFOUND, rbtree.find(Name("x"), &rbtnode));
     EXPECT_EQ(RBTree::NOTFOUND, rbtree.find(Name("x"), &rbtnode));
     EXPECT_EQ(RBTree::NOTFOUND, rbtree.find(Name("m.n"), &rbtnode));
     EXPECT_EQ(RBTree::NOTFOUND, rbtree.find(Name("m.n"), &rbtnode));
-    EXPECT_EQ(RBTree::NOTFOUND, rbtree.find(Name("m.d.e.f"), &rbtnode));
+    EXPECT_EQ(RBTree::NOTFOUND, rbtree.find(Name("o.p.w.y.d.e.f"), &rbtnode));
+    EXPECT_EQ(RBTree::NOTFOUND, rbtree.find(Name("m.w.y.d.e.f"), &rbtnode));
 
 
     // find referral
     // find referral
     RRsetPtr rrset = RRsetPtr(new RRset(Name("d.e.f"), RRClass::IN(), RRType::NS(),
     RRsetPtr rrset = RRsetPtr(new RRset(Name("d.e.f"), RRClass::IN(), RRType::NS(),
@@ -124,20 +140,51 @@ TEST_F(RBTreeTest, findName) {
     EXPECT_EQ(Name("d.e.f"), rbtnode->getName());
     EXPECT_EQ(Name("d.e.f"), rbtnode->getName());
 }
 }
 
 
+TEST_F(RBTreeTest, successor) {
+    // traverse the trees
+    EXPECT_EQ(RBTree::EXACTMATCH, rbtree.find(Name("a"), &rbtnode));
+    RBNode *successor_node = rbtnode->successor();
+    EXPECT_EQ(Name("b"), successor_node->getName());
+    successor_node = successor_node->successor();
+    EXPECT_EQ(Name("c"), successor_node->getName());
+    successor_node = successor_node->successor();
+    EXPECT_EQ(Name("d.e.f"), successor_node->getName());
+    successor_node = successor_node->successor();
+    EXPECT_EQ(Name("g.h"), successor_node->getName());
+    successor_node = successor_node->successor();
+
+    EXPECT_EQ(RBTree::EXACTMATCH, rbtree.find(Name("x.d.e.f"), &rbtnode));
+    EXPECT_EQ(Name("x"), rbtnode->getName());
+    successor_node = rbtnode->successor();
+    EXPECT_EQ(Name("w.y"), successor_node->getName());
+    successor_node = successor_node->successor();
+    EXPECT_EQ(Name("z"), successor_node->getName());
+
+    EXPECT_EQ(RBTree::EXACTMATCH, rbtree.find(Name("o.w.y.d.e.f"), &rbtnode));
+    EXPECT_EQ(Name("o"), rbtnode->getName());
+    successor_node = rbtnode->successor();
+    EXPECT_EQ(Name("p"), successor_node->getName());
+    successor_node = successor_node->successor();
+    EXPECT_EQ(Name("q"), successor_node->getName());
+}
+
 TEST_F(RBTreeTest, eraseName) {
 TEST_F(RBTreeTest, eraseName) {
-    EXPECT_EQ(11, rbtree.getNodeCount());
+    EXPECT_EQ(13, rbtree.getNodeCount());
+    // can't delete non terminal
+    int ret = rbtree.erase(Name("d.e.f"));
+    EXPECT_EQ(1, ret);
     EXPECT_EQ(RBTree::EXACTMATCH, rbtree.find(Name("w.y.d.e.f"), &rbtnode));
     EXPECT_EQ(RBTree::EXACTMATCH, rbtree.find(Name("w.y.d.e.f"), &rbtnode));
     RRsetPtr rrset = RRsetPtr(new RRset(Name("w.y.d.e.f"), RRClass::IN(), RRType::A(),
     RRsetPtr rrset = RRsetPtr(new RRset(Name("w.y.d.e.f"), RRClass::IN(), RRType::A(),
                                        RRTTL(3600)));
                                        RRTTL(3600)));
     rbtnode->addRRset(rrset);
     rbtnode->addRRset(rrset);
-    int ret = rbtree.erase(Name("p.w.y.d.e.f"));
+    ret = rbtree.erase(Name("p.w.y.d.e.f"));
     EXPECT_EQ(0, ret);
     EXPECT_EQ(0, ret);
-    EXPECT_EQ(10, rbtree.getNodeCount());
+    EXPECT_EQ(12, rbtree.getNodeCount());
     EXPECT_EQ(RBTree::NOTFOUND, rbtree.find(Name("p.w.y.d.e.f"), &rbtnode));
     EXPECT_EQ(RBTree::NOTFOUND, rbtree.find(Name("p.w.y.d.e.f"), &rbtnode));
 
 
     ret = rbtree.erase(Name("q.w.y.d.e.f"));
     ret = rbtree.erase(Name("q.w.y.d.e.f"));
     EXPECT_EQ(0, ret);
     EXPECT_EQ(0, ret);
-    EXPECT_EQ(9, rbtree.getNodeCount());
+    EXPECT_EQ(11, rbtree.getNodeCount());
     EXPECT_EQ(RBTree::NOTFOUND, rbtree.find(Name("q.w.y.d.e.f"), &rbtnode));
     EXPECT_EQ(RBTree::NOTFOUND, rbtree.find(Name("q.w.y.d.e.f"), &rbtnode));
 
 
     // o would not be rejoined with w.y if w.y had data
     // o would not be rejoined with w.y if w.y had data
@@ -150,30 +197,32 @@ TEST_F(RBTreeTest, eraseName) {
      *          a    d.e.f
      *          a    d.e.f
      *               / | \
      *               / | \
      *              c  |  g.h
      *              c  |  g.h
-     *                 |
-     *                w.y
+     *                 |   |
+     *                w.y  i
      *               / | \
      *               / | \
      *              x  |  z
      *              x  |  z
-     *                 |
-     *                 o
+     *                 |  |
+     *                 o  j
      */
      */
     // z would be rejoined with d.e.f, since d.e.f has no data associated with the key
     // z would be rejoined with d.e.f, since d.e.f has no data associated with the key
     ret = rbtree.erase(Name("o.w.y.d.e.f"));
     ret = rbtree.erase(Name("o.w.y.d.e.f"));
+
     EXPECT_EQ(0, ret);
     EXPECT_EQ(0, ret);
-    EXPECT_EQ(8, rbtree.getNodeCount());
+    EXPECT_EQ(10, rbtree.getNodeCount());
     ret = rbtree.erase(Name("w.y.d.e.f"));
     ret = rbtree.erase(Name("w.y.d.e.f"));
     EXPECT_EQ(0, ret);
     EXPECT_EQ(0, ret);
-    EXPECT_EQ(7, rbtree.getNodeCount());
+    EXPECT_EQ(9, rbtree.getNodeCount());
     ret = rbtree.erase(Name("x.d.e.f"));
     ret = rbtree.erase(Name("x.d.e.f"));
     EXPECT_EQ(0, ret);
     EXPECT_EQ(0, ret);
-    EXPECT_EQ(5, rbtree.getNodeCount());
+    EXPECT_EQ(7, rbtree.getNodeCount());
     /*
     /*
      *             b
      *             b
      *           /   \
      *           /   \
      *          a   z.d.e.f
      *          a   z.d.e.f
-     *               /   \
-     *              c     g.h
-     *
+     *               / | \
+     *              c  j  g.h
+     *                     |
+     *                     i
      */
      */
     // erase a non-exist node
     // erase a non-exist node
     ret = rbtree.erase(Name("x.d.e.f"));
     ret = rbtree.erase(Name("x.d.e.f"));
@@ -182,14 +231,23 @@ TEST_F(RBTreeTest, eraseName) {
     // delete all the nodes one by one
     // delete all the nodes one by one
     ret = rbtree.erase(Name("a"));
     ret = rbtree.erase(Name("a"));
     EXPECT_EQ(0, ret);
     EXPECT_EQ(0, ret);
-    EXPECT_EQ(4, rbtree.getNodeCount());
+    EXPECT_EQ(6, rbtree.getNodeCount());
     ret = rbtree.erase(Name("g.h"));
     ret = rbtree.erase(Name("g.h"));
+    EXPECT_EQ(1, ret);
+    EXPECT_EQ(6, rbtree.getNodeCount());
+    ret = rbtree.erase(Name("c"));
     EXPECT_EQ(0, ret);
     EXPECT_EQ(0, ret);
-    EXPECT_EQ(3, rbtree.getNodeCount());
+    EXPECT_EQ(5, rbtree.getNodeCount());
     ret = rbtree.erase(Name("b"));
     ret = rbtree.erase(Name("b"));
     EXPECT_EQ(0, ret);
     EXPECT_EQ(0, ret);
+    EXPECT_EQ(4, rbtree.getNodeCount());
+    ret = rbtree.erase(Name("i.g.h"));
+    EXPECT_EQ(0, ret);
+    EXPECT_EQ(3, rbtree.getNodeCount());
+    ret = rbtree.erase(Name("j.z.d.e.f"));
+    EXPECT_EQ(0, ret);
     EXPECT_EQ(2, rbtree.getNodeCount());
     EXPECT_EQ(2, rbtree.getNodeCount());
-    ret = rbtree.erase(Name("c"));
+    ret = rbtree.erase(Name("g.h"));
     EXPECT_EQ(0, ret);
     EXPECT_EQ(0, ret);
     EXPECT_EQ(1, rbtree.getNodeCount());
     EXPECT_EQ(1, rbtree.getNodeCount());
     ret = rbtree.erase(Name("z.d.e.f"));
     ret = rbtree.erase(Name("z.d.e.f"));