rbtree_unittest.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. // Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include <gtest/gtest.h>
  15. #include <dns/name.h>
  16. #include <dns/rrclass.h>
  17. #include <dns/rrset.h>
  18. #include <dns/rrtype.h>
  19. #include <dns/rrttl.h>
  20. #include <datasrc/rbtree.h>
  21. #include <dns/tests/unittest_util.h>
  22. using namespace std;
  23. using namespace isc::dns;
  24. using isc::UnitTestUtil;
  25. using namespace isc::datasrc;
  26. /* The initial structure of rbtree
  27. *
  28. * b
  29. * / \
  30. * a d.e.f
  31. * / | \
  32. * c | g.h
  33. * | |
  34. * w.y i
  35. * / | \
  36. * x | z
  37. * | |
  38. * p j
  39. * / \
  40. * o q
  41. */
  42. namespace {
  43. class RBTreeTest : public::testing::Test {
  44. protected:
  45. RBTreeTest() : rbtree() {
  46. rbtree.insert(Name("c"), &rbtnode);
  47. rbtnode->setData(RBNode<int>::NodeDataPtr(new int(1)));
  48. rbtree.insert(Name("b"), &rbtnode);
  49. rbtnode->setData(RBNode<int>::NodeDataPtr(new int(2)));
  50. rbtree.insert(Name("a"), &rbtnode);
  51. rbtnode->setData(RBNode<int>::NodeDataPtr(new int(3)));
  52. rbtree.insert(Name("x.d.e.f"), &rbtnode);
  53. rbtnode->setData(RBNode<int>::NodeDataPtr(new int(4)));
  54. rbtree.insert(Name("z.d.e.f"), &rbtnode);
  55. rbtnode->setData(RBNode<int>::NodeDataPtr(new int(5)));
  56. rbtree.insert(Name("g.h"), &rbtnode);
  57. rbtnode->setData(RBNode<int>::NodeDataPtr(new int(6)));
  58. rbtree.insert(Name("i.g.h"), &rbtnode);
  59. rbtnode->setData(RBNode<int>::NodeDataPtr(new int(7)));
  60. rbtree.insert(Name("o.w.y.d.e.f"), &rbtnode);
  61. rbtnode->setData(RBNode<int>::NodeDataPtr(new int(8)));
  62. rbtree.insert(Name("j.z.d.e.f"), &rbtnode);
  63. rbtnode->setData(RBNode<int>::NodeDataPtr(new int(9)));
  64. rbtree.insert(Name("p.w.y.d.e.f"), &rbtnode);
  65. rbtnode->setData(RBNode<int>::NodeDataPtr(new int(10)));
  66. rbtree.insert(Name("q.w.y.d.e.f"), &rbtnode);
  67. rbtnode->setData(RBNode<int>::NodeDataPtr(new int(11)));
  68. }
  69. RBTree<int> rbtree;
  70. RBNode<int>* rbtnode;
  71. const RBNode<int>* crbtnode;
  72. };
  73. TEST_F(RBTreeTest, getNodeCount) {
  74. EXPECT_EQ(13, rbtree.getNodeCount());
  75. }
  76. TEST_F(RBTreeTest, setGetData) {
  77. rbtnode->setData(RBNode<int>::NodeDataPtr(new int(11)));
  78. EXPECT_EQ(11, *(rbtnode->getData()));
  79. }
  80. TEST_F(RBTreeTest, insertNames) {
  81. EXPECT_EQ(RBTree<int>::ALREADYEXISTS, rbtree.insert(Name("d.e.f"), &rbtnode));
  82. EXPECT_EQ(Name("d.e.f"), rbtnode->getName());
  83. EXPECT_EQ(13, rbtree.getNodeCount());
  84. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("."), &rbtnode));
  85. EXPECT_EQ(Name("."), rbtnode->getName());
  86. EXPECT_EQ(14, rbtree.getNodeCount());
  87. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("example.com"), &rbtnode));
  88. EXPECT_EQ(15, rbtree.getNodeCount());
  89. rbtnode->setData(RBNode<int>::NodeDataPtr(new int(12)));
  90. // return ALREADYEXISTS, since node "example.com" already has been explicitly inserted
  91. EXPECT_EQ(RBTree<int>::ALREADYEXISTS, rbtree.insert(Name("example.com"), &rbtnode));
  92. EXPECT_EQ(15, rbtree.getNodeCount());
  93. // split the node "d.e.f"
  94. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("k.e.f"), &rbtnode));
  95. EXPECT_EQ(Name("k"), rbtnode->getName());
  96. EXPECT_EQ(17, rbtree.getNodeCount());
  97. // split the node "g.h"
  98. EXPECT_EQ(RBTree<int>::ALREADYEXISTS, rbtree.insert(Name("h"), &rbtnode));
  99. EXPECT_EQ(Name("h"), rbtnode->getName());
  100. EXPECT_EQ(18, rbtree.getNodeCount());
  101. // add child domain
  102. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("m.p.w.y.d.e.f"), &rbtnode));
  103. EXPECT_EQ(Name("m"), rbtnode->getName());
  104. EXPECT_EQ(19, rbtree.getNodeCount());
  105. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("n.p.w.y.d.e.f"), &rbtnode));
  106. EXPECT_EQ(Name("n"), rbtnode->getName());
  107. EXPECT_EQ(20, rbtree.getNodeCount());
  108. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("l.a"), &rbtnode));
  109. EXPECT_EQ(Name("l"), rbtnode->getName());
  110. EXPECT_EQ(21, rbtree.getNodeCount());
  111. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("r.d.e.f"), &rbtnode));
  112. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("s.d.e.f"), &rbtnode));
  113. EXPECT_EQ(23, rbtree.getNodeCount());
  114. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("h.w.y.d.e.f"), &rbtnode));
  115. // add more nodes one by one to cover leftRotate and rightRotate
  116. EXPECT_EQ(RBTree<int>::ALREADYEXISTS, rbtree.insert(Name("f"), &rbtnode));
  117. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("m"), &rbtnode));
  118. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("nm"), &rbtnode));
  119. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("om"), &rbtnode));
  120. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("k"), &rbtnode));
  121. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("l"), &rbtnode));
  122. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("fe"), &rbtnode));
  123. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("ge"), &rbtnode));
  124. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("i"), &rbtnode));
  125. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("ae"), &rbtnode));
  126. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("n"), &rbtnode));
  127. }
  128. TEST_F(RBTreeTest, findName) {
  129. // find const rbtnode
  130. // exact match
  131. EXPECT_EQ(RBTree<int>::EXACTMATCH, rbtree.find(Name("a"), &crbtnode));
  132. EXPECT_EQ(Name("a"), crbtnode->getName());
  133. // not found
  134. EXPECT_EQ(RBTree<int>::NOTFOUND, rbtree.find(Name("d.e.f"), &crbtnode));
  135. EXPECT_EQ(RBTree<int>::NOTFOUND, rbtree.find(Name("y.d.e.f"), &crbtnode));
  136. EXPECT_EQ(RBTree<int>::NOTFOUND, rbtree.find(Name("x"), &crbtnode));
  137. EXPECT_EQ(RBTree<int>::NOTFOUND, rbtree.find(Name("m.n"), &crbtnode));
  138. // partial match
  139. EXPECT_EQ(RBTree<int>::PARTIALMATCH, rbtree.find(Name("m.b"), &crbtnode));
  140. EXPECT_EQ(Name("b"), crbtnode->getName());
  141. // find rbtnode
  142. EXPECT_EQ(RBTree<int>::EXACTMATCH, rbtree.find(Name("q.w.y.d.e.f"), &rbtnode));
  143. EXPECT_EQ(Name("q"), rbtnode->getName());
  144. }
  145. bool
  146. testCallback(const RBNode<int>&, bool* callack_checker) {
  147. *callack_checker = true;
  148. return (false);
  149. }
  150. TEST_F(RBTreeTest, callback) {
  151. // by default callback isn't enabled
  152. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("callback.example"),
  153. &rbtnode));
  154. rbtnode->setData(RBNode<int>::NodeDataPtr(new int(1)));
  155. EXPECT_FALSE(rbtnode->isCallbackEnabled());
  156. // enable/re-disable callback
  157. rbtnode->enableCallback();
  158. EXPECT_TRUE(rbtnode->isCallbackEnabled());
  159. rbtnode->disableCallback();
  160. EXPECT_FALSE(rbtnode->isCallbackEnabled());
  161. // enable again for subsequent tests
  162. rbtnode->enableCallback();
  163. // add more levels below and above the callback node for partial match.
  164. RBNode<int>* subrbtnode;
  165. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("sub.callback.example"),
  166. &subrbtnode));
  167. subrbtnode->setData(RBNode<int>::NodeDataPtr(new int(2)));
  168. RBNode<int>* parentrbtnode;
  169. EXPECT_EQ(RBTree<int>::ALREADYEXISTS, rbtree.insert(Name("example"),
  170. &parentrbtnode));
  171. // the chilld/parent nodes shouldn't "inherit" the callback flag.
  172. // "rbtnode" may be invalid due to the insertion, so we need to re-find
  173. // it.
  174. EXPECT_EQ(RBTree<int>::EXACTMATCH, rbtree.find(Name("callback.example"),
  175. &rbtnode));
  176. EXPECT_TRUE(rbtnode->isCallbackEnabled());
  177. EXPECT_FALSE(subrbtnode->isCallbackEnabled());
  178. EXPECT_FALSE(parentrbtnode->isCallbackEnabled());
  179. // check if the callback is called from find()
  180. bool callback_called = false;
  181. EXPECT_EQ(RBTree<int>::EXACTMATCH,
  182. rbtree.find(Name("sub.callback.example"), &crbtnode,
  183. testCallback, &callback_called));
  184. EXPECT_TRUE(callback_called);
  185. // enable callback at the parent node, but it doesn't have data so
  186. // the callback shouldn't be called.
  187. parentrbtnode->enableCallback();
  188. callback_called = false;
  189. EXPECT_EQ(RBTree<int>::EXACTMATCH,
  190. rbtree.find(Name("callback.example"), &crbtnode,
  191. testCallback, &callback_called));
  192. EXPECT_FALSE(callback_called);
  193. }
  194. TEST_F(RBTreeTest, dumpTree) {
  195. std::ostringstream str;
  196. std::ostringstream str2;
  197. rbtree.dumpTree(str);
  198. str2 << "tree has 13 node(s)\nb. (black)\n a. (black)\n NULL\n NULL\n d.e.f. (black)[invisible] \n begin down from d.e.f.\n w.y. (black)[invisible] \n begin down from w.y.\n p. (black)\n o. (red)\n NULL\n NULL\n q. (red)\n NULL\n NULL\n end down from w.y.\n x. (red)\n NULL\n NULL\n z. (red)\n begin down from z.\n j. (black)\n NULL\n NULL\n end down from z.\n NULL\n NULL\n end down from d.e.f.\n c. (red)\n NULL\n NULL\n g.h. (red)\n begin down from g.h.\n i. (black)\n NULL\n NULL\n end down from g.h.\n NULL\n NULL\n";
  199. EXPECT_EQ(str.str(), str2.str());
  200. }
  201. TEST_F(RBTreeTest, swap) {
  202. // Store info about the first tree
  203. std::ostringstream str1;
  204. rbtree.dumpTree(str1);
  205. size_t count1(rbtree.getNodeCount());
  206. // Create second one and store state
  207. RBTree<int> tree2;
  208. RBNode<int>* node;
  209. tree2.insert(Name("second"), &node);
  210. std::ostringstream str2;
  211. tree2.dumpTree(str2);
  212. // Swap them
  213. ASSERT_NO_THROW(tree2.swap(rbtree));
  214. // Check their sizes
  215. ASSERT_EQ(1, rbtree.getNodeCount());
  216. ASSERT_EQ(count1, tree2.getNodeCount());
  217. // And content
  218. std::ostringstream out;
  219. rbtree.dumpTree(out);
  220. ASSERT_EQ(str2.str(), out.str());
  221. out.str("");
  222. tree2.dumpTree(out);
  223. ASSERT_EQ(str1.str(), out.str());
  224. }
  225. }