rbtree_unittest.cc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  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 <exceptions/exceptions.h>
  16. #include <dns/name.h>
  17. #include <dns/rrclass.h>
  18. #include <dns/rrset.h>
  19. #include <dns/rrtype.h>
  20. #include <dns/rrttl.h>
  21. #include <datasrc/rbtree.h>
  22. #include <dns/tests/unittest_util.h>
  23. using namespace std;
  24. using namespace isc;
  25. using namespace isc::dns;
  26. using isc::UnitTestUtil;
  27. using namespace isc::datasrc;
  28. // XXX: some compilers cannot find class static constants used in
  29. // EXPECT_xxx macros, for which we need an explicit empty definition.
  30. const size_t Name::MAX_LABELS;
  31. /* The initial structure of rbtree
  32. *
  33. * b
  34. * / \
  35. * a d.e.f
  36. * / | \
  37. * c | g.h
  38. * | |
  39. * w.y i
  40. * / | \
  41. * x | z
  42. * | |
  43. * p j
  44. * / \
  45. * o q
  46. */
  47. namespace {
  48. class RBTreeTest : public::testing::Test {
  49. protected:
  50. RBTreeTest() : rbtree_expose_empty_node(true) {
  51. const char* const domain_names[] = {
  52. "c", "b", "a", "x.d.e.f", "z.d.e.f", "g.h", "i.g.h", "o.w.y.d.e.f",
  53. "j.z.d.e.f", "p.w.y.d.e.f", "q.w.y.d.e.f"};
  54. int name_count = sizeof(domain_names) / sizeof(domain_names[0]);
  55. for (int i = 0; i < name_count; ++i) {
  56. rbtree.insert(Name(domain_names[i]), &rbtnode);
  57. rbtnode->setData(RBNode<int>::NodeDataPtr(new int(i + 1)));
  58. rbtree_expose_empty_node.insert(Name(domain_names[i]), &rbtnode);
  59. rbtnode->setData(RBNode<int>::NodeDataPtr(new int(i + 1)));
  60. }
  61. }
  62. RBTree<int> rbtree;
  63. RBTree<int> rbtree_expose_empty_node;
  64. RBNode<int>* rbtnode;
  65. const RBNode<int>* crbtnode;
  66. };
  67. TEST_F(RBTreeTest, getNodeCount) {
  68. EXPECT_EQ(13, rbtree.getNodeCount());
  69. }
  70. TEST_F(RBTreeTest, setGetData) {
  71. rbtnode->setData(RBNode<int>::NodeDataPtr(new int(11)));
  72. EXPECT_EQ(11, *(rbtnode->getData()));
  73. }
  74. TEST_F(RBTreeTest, insertNames) {
  75. EXPECT_EQ(RBTree<int>::ALREADYEXISTS, rbtree.insert(Name("d.e.f"),
  76. &rbtnode));
  77. EXPECT_EQ(Name("d.e.f"), rbtnode->getName());
  78. EXPECT_EQ(13, rbtree.getNodeCount());
  79. //insert not exist node
  80. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("."), &rbtnode));
  81. EXPECT_EQ(Name("."), rbtnode->getName());
  82. EXPECT_EQ(14, rbtree.getNodeCount());
  83. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("example.com"), &rbtnode));
  84. EXPECT_EQ(15, rbtree.getNodeCount());
  85. rbtnode->setData(RBNode<int>::NodeDataPtr(new int(12)));
  86. // return ALREADYEXISTS, since node "example.com" already has been explicitly inserted
  87. EXPECT_EQ(RBTree<int>::ALREADYEXISTS, rbtree.insert(Name("example.com"), &rbtnode));
  88. EXPECT_EQ(15, rbtree.getNodeCount());
  89. // split the node "d.e.f"
  90. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("k.e.f"), &rbtnode));
  91. EXPECT_EQ(Name("k"), rbtnode->getName());
  92. EXPECT_EQ(17, rbtree.getNodeCount());
  93. // split the node "g.h"
  94. EXPECT_EQ(RBTree<int>::ALREADYEXISTS, rbtree.insert(Name("h"), &rbtnode));
  95. EXPECT_EQ(Name("h"), rbtnode->getName());
  96. EXPECT_EQ(18, rbtree.getNodeCount());
  97. // add child domain
  98. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("m.p.w.y.d.e.f"), &rbtnode));
  99. EXPECT_EQ(Name("m"), rbtnode->getName());
  100. EXPECT_EQ(19, rbtree.getNodeCount());
  101. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("n.p.w.y.d.e.f"), &rbtnode));
  102. EXPECT_EQ(Name("n"), rbtnode->getName());
  103. EXPECT_EQ(20, rbtree.getNodeCount());
  104. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("l.a"), &rbtnode));
  105. EXPECT_EQ(Name("l"), rbtnode->getName());
  106. EXPECT_EQ(21, rbtree.getNodeCount());
  107. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("r.d.e.f"), &rbtnode));
  108. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("s.d.e.f"), &rbtnode));
  109. EXPECT_EQ(23, rbtree.getNodeCount());
  110. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("h.w.y.d.e.f"), &rbtnode));
  111. // add more nodes one by one to cover leftRotate and rightRotate
  112. EXPECT_EQ(RBTree<int>::ALREADYEXISTS, rbtree.insert(Name("f"), &rbtnode));
  113. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("m"), &rbtnode));
  114. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("nm"), &rbtnode));
  115. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("om"), &rbtnode));
  116. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("k"), &rbtnode));
  117. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("l"), &rbtnode));
  118. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("fe"), &rbtnode));
  119. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("ge"), &rbtnode));
  120. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("i"), &rbtnode));
  121. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("ae"), &rbtnode));
  122. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("n"), &rbtnode));
  123. }
  124. TEST_F(RBTreeTest, findName) {
  125. // find const rbtnode
  126. // exact match
  127. EXPECT_EQ(RBTree<int>::EXACTMATCH, rbtree.find(Name("a"), &crbtnode));
  128. EXPECT_EQ(Name("a"), crbtnode->getName());
  129. // not found
  130. EXPECT_EQ(RBTree<int>::NOTFOUND, rbtree.find(Name("d.e.f"), &crbtnode));
  131. EXPECT_EQ(RBTree<int>::NOTFOUND, rbtree.find(Name("y.d.e.f"), &crbtnode));
  132. EXPECT_EQ(RBTree<int>::NOTFOUND, rbtree.find(Name("x"), &crbtnode));
  133. EXPECT_EQ(RBTree<int>::NOTFOUND, rbtree.find(Name("m.n"), &crbtnode));
  134. // if we expose empty node, we can get the empty node created during insert
  135. EXPECT_EQ(RBTree<int>::EXACTMATCH,
  136. rbtree_expose_empty_node.find(Name("d.e.f"), &crbtnode));
  137. EXPECT_EQ(RBTree<int>::EXACTMATCH,
  138. rbtree_expose_empty_node.find(Name("w.y.d.e.f"), &crbtnode));
  139. // partial match
  140. EXPECT_EQ(RBTree<int>::PARTIALMATCH, rbtree.find(Name("m.b"), &crbtnode));
  141. EXPECT_EQ(Name("b"), crbtnode->getName());
  142. EXPECT_EQ(RBTree<int>::PARTIALMATCH,
  143. rbtree_expose_empty_node.find(Name("m.d.e.f"), &crbtnode));
  144. // find rbtnode
  145. EXPECT_EQ(RBTree<int>::EXACTMATCH, rbtree.find(Name("q.w.y.d.e.f"), &rbtnode));
  146. EXPECT_EQ(Name("q"), rbtnode->getName());
  147. }
  148. bool
  149. testCallback(const RBNode<int>&, bool* callack_checker) {
  150. *callack_checker = true;
  151. return (false);
  152. }
  153. TEST_F(RBTreeTest, callback) {
  154. RBTreeNodeChain<int> node_path;
  155. // by default callback isn't enabled
  156. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("callback.example"),
  157. &rbtnode));
  158. rbtnode->setData(RBNode<int>::NodeDataPtr(new int(1)));
  159. EXPECT_FALSE(rbtnode->isCallbackEnabled());
  160. // enable/re-disable callback
  161. rbtnode->enableCallback();
  162. EXPECT_TRUE(rbtnode->isCallbackEnabled());
  163. rbtnode->disableCallback();
  164. EXPECT_FALSE(rbtnode->isCallbackEnabled());
  165. // enable again for subsequent tests
  166. rbtnode->enableCallback();
  167. // add more levels below and above the callback node for partial match.
  168. RBNode<int>* subrbtnode;
  169. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(Name("sub.callback.example"),
  170. &subrbtnode));
  171. subrbtnode->setData(RBNode<int>::NodeDataPtr(new int(2)));
  172. RBNode<int>* parentrbtnode;
  173. EXPECT_EQ(RBTree<int>::ALREADYEXISTS, rbtree.insert(Name("example"),
  174. &parentrbtnode));
  175. // the chilld/parent nodes shouldn't "inherit" the callback flag.
  176. // "rbtnode" may be invalid due to the insertion, so we need to re-find
  177. // it.
  178. EXPECT_EQ(RBTree<int>::EXACTMATCH, rbtree.find(Name("callback.example"),
  179. &rbtnode));
  180. EXPECT_TRUE(rbtnode->isCallbackEnabled());
  181. EXPECT_FALSE(subrbtnode->isCallbackEnabled());
  182. EXPECT_FALSE(parentrbtnode->isCallbackEnabled());
  183. // check if the callback is called from find()
  184. bool callback_called = false;
  185. EXPECT_EQ(RBTree<int>::EXACTMATCH,
  186. rbtree.find(Name("sub.callback.example"), &crbtnode, node_path,
  187. testCallback, &callback_called));
  188. EXPECT_TRUE(callback_called);
  189. // enable callback at the parent node, but it doesn't have data so
  190. // the callback shouldn't be called.
  191. parentrbtnode->enableCallback();
  192. callback_called = false;
  193. EXPECT_EQ(RBTree<int>::EXACTMATCH,
  194. rbtree.find(Name("callback.example"), &crbtnode, node_path,
  195. testCallback, &callback_called));
  196. EXPECT_FALSE(callback_called);
  197. }
  198. TEST_F(RBTreeTest, chainLevel) {
  199. RBTreeNodeChain<int> chain;
  200. // by default there should be no level in the chain.
  201. EXPECT_EQ(0, chain.getLevelCount());
  202. // insert one node to the tree and find it. there should be exactly
  203. // one level in the chain.
  204. RBTree<int> tree(true);
  205. Name node_name(Name::ROOT_NAME());
  206. EXPECT_EQ(RBTree<int>::SUCCESS, tree.insert(node_name, &rbtnode));
  207. EXPECT_EQ(RBTree<int>::EXACTMATCH,
  208. tree.find<void*>(node_name, &crbtnode, chain, NULL, NULL));
  209. EXPECT_EQ(1, chain.getLevelCount());
  210. /*
  211. * Now creating a possibly deepest tree with MAX_LABELS - 1 levels.
  212. * it should look like:
  213. * a
  214. * /|
  215. * (.)a
  216. * |
  217. * a
  218. * : (MAX_LABELS - 1) "a"'s
  219. *
  220. * then confirm that find() for the deepest name succeeds without any
  221. * disruption, and the resulting chain has the expected level.
  222. * Note that "a." and the root name (".") belong to the same level.
  223. * So the possible maximum level is MAX_LABELS - 1, not MAX_LABELS.
  224. */
  225. for (unsigned int i = 1; i < Name::MAX_LABELS; ++i) {
  226. node_name = Name("a.").concatenate(node_name);
  227. EXPECT_EQ(RBTree<int>::SUCCESS, tree.insert(node_name, &rbtnode));
  228. RBTreeNodeChain<int> found_chain;
  229. EXPECT_EQ(RBTree<int>::EXACTMATCH,
  230. tree.find<void*>(node_name, &crbtnode, found_chain,
  231. NULL, NULL));
  232. EXPECT_EQ(i, found_chain.getLevelCount());
  233. }
  234. // Confirm the last inserted name has the possible maximum length with
  235. // maximum label count. This confirms the rbtree and chain level cannot
  236. // be larger.
  237. EXPECT_EQ(Name::MAX_LABELS, node_name.getLabelCount());
  238. EXPECT_THROW(node_name.concatenate(Name("a.")), TooLongName);
  239. }
  240. /*
  241. *the domain order should be:
  242. * 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,
  243. * z.d.e.f, j.z.d.e.f, g.h, i.g.h
  244. * b
  245. * / \
  246. * a d.e.f
  247. * / | \
  248. * c | g.h
  249. * | |
  250. * w.y i
  251. * / | \
  252. * x | z
  253. * | |
  254. * p j
  255. * / \
  256. * o q
  257. */
  258. TEST_F(RBTreeTest, nextNode) {
  259. const char* const names[] = {
  260. "a", "b", "c", "d.e.f", "x.d.e.f", "w.y.d.e.f", "o.w.y.d.e.f",
  261. "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"};
  262. const int name_count = sizeof(names) / sizeof(names[0]);
  263. RBTreeNodeChain<int> node_path;
  264. const RBNode<int>* node = NULL;
  265. EXPECT_EQ(RBTree<int>::EXACTMATCH,
  266. rbtree.find<void*>(Name(names[0]), &node, node_path, NULL,
  267. NULL));
  268. for (int i = 0; i < name_count; ++i) {
  269. EXPECT_NE(static_cast<void*>(NULL), node);
  270. EXPECT_EQ(Name(names[i]), node_path.getAbsoluteName());
  271. node = rbtree.nextNode(node_path);
  272. }
  273. // We should have reached the end of the tree.
  274. EXPECT_EQ(static_cast<void*>(NULL), node);
  275. }
  276. TEST_F(RBTreeTest, nextNodeError) {
  277. // Empty chain for nextNode() is invalid.
  278. RBTreeNodeChain<int> chain;
  279. EXPECT_THROW(rbtree.nextNode(chain), BadValue);
  280. }
  281. TEST_F(RBTreeTest, dumpTree) {
  282. std::ostringstream str;
  283. std::ostringstream str2;
  284. rbtree.dumpTree(str);
  285. 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";
  286. EXPECT_EQ(str.str(), str2.str());
  287. }
  288. TEST_F(RBTreeTest, swap) {
  289. // Store info about the first tree
  290. std::ostringstream str1;
  291. rbtree.dumpTree(str1);
  292. size_t count1(rbtree.getNodeCount());
  293. // Create second one and store state
  294. RBTree<int> tree2;
  295. RBNode<int>* node;
  296. tree2.insert(Name("second"), &node);
  297. std::ostringstream str2;
  298. tree2.dumpTree(str2);
  299. // Swap them
  300. ASSERT_NO_THROW(tree2.swap(rbtree));
  301. // Check their sizes
  302. ASSERT_EQ(1, rbtree.getNodeCount());
  303. ASSERT_EQ(count1, tree2.getNodeCount());
  304. // And content
  305. std::ostringstream out;
  306. rbtree.dumpTree(out);
  307. ASSERT_EQ(str2.str(), out.str());
  308. out.str("");
  309. tree2.dumpTree(out);
  310. ASSERT_EQ(str1.str(), out.str());
  311. }
  312. }