domaintree_unittest.cc 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230
  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 <util/memory_segment_local.h>
  17. #include <dns/name.h>
  18. #include <dns/rrclass.h>
  19. #include <dns/rrset.h>
  20. #include <dns/rrtype.h>
  21. #include <dns/rrttl.h>
  22. #include <datasrc/memory/domaintree.h>
  23. #include <dns/tests/unittest_util.h>
  24. using namespace std;
  25. using namespace isc;
  26. using namespace isc::dns;
  27. using isc::UnitTestUtil;
  28. using namespace isc::datasrc::memory;
  29. // XXX: some compilers cannot find class static constants used in
  30. // EXPECT_xxx macros, for which we need an explicit empty definition.
  31. const size_t Name::MAX_LABELS;
  32. /* The initial structure of dtree
  33. *
  34. * .
  35. * |
  36. * b
  37. * / \
  38. * a d.e.f
  39. * / | \
  40. * c | g.h
  41. * | |
  42. * w.y i
  43. * / | \ \
  44. * x | z k
  45. * | |
  46. * p j
  47. * / \
  48. * o q
  49. */
  50. namespace {
  51. void deleteData(int* i) {
  52. delete i;
  53. }
  54. typedef DomainTree<int> TestDomainTree;
  55. typedef DomainTreeNode<int> TestDomainTreeNode;
  56. typedef DomainTreeNodeChain<int> TestDomainTreeNodeChain;
  57. class TreeHolder {
  58. public:
  59. TreeHolder(util::MemorySegment& mem_sgmt, TestDomainTree* tree) :
  60. mem_sgmt_(mem_sgmt), tree_(tree)
  61. {}
  62. ~TreeHolder() {
  63. TestDomainTree::destroy(mem_sgmt_, tree_, deleteData);
  64. }
  65. TestDomainTree* get() { return (tree_); }
  66. private:
  67. util::MemorySegment& mem_sgmt_;
  68. TestDomainTree* tree_;
  69. };
  70. class DomainTreeTest : public::testing::Test {
  71. protected:
  72. DomainTreeTest() :
  73. dtree_holder_(mem_sgmt_, TestDomainTree::create(mem_sgmt_)),
  74. dtree_expose_empty_node_holder_(mem_sgmt_,
  75. TestDomainTree::create(mem_sgmt_, true)),
  76. dtree(*dtree_holder_.get()),
  77. dtree_expose_empty_node(*dtree_expose_empty_node_holder_.get()),
  78. cdtnode(NULL)
  79. {
  80. const char* const domain_names[] = {
  81. "c", "b", "a", "x.d.e.f", "z.d.e.f", "g.h", "i.g.h", "o.w.y.d.e.f",
  82. "j.z.d.e.f", "p.w.y.d.e.f", "q.w.y.d.e.f", "k.g.h"};
  83. int name_count = sizeof(domain_names) / sizeof(domain_names[0]);
  84. for (int i = 0; i < name_count; ++i) {
  85. dtree.insert(mem_sgmt_, Name(domain_names[i]), &dtnode);
  86. // Check the node doesn't have any data initially.
  87. EXPECT_EQ(static_cast<int*>(NULL),
  88. dtnode->setData(new int(i + 1)));
  89. dtree_expose_empty_node.insert(mem_sgmt_, Name(domain_names[i]),
  90. &dtnode);
  91. EXPECT_EQ(static_cast<int*>(NULL), dtnode->setData(new int(i + 1)));
  92. }
  93. }
  94. util::MemorySegmentLocal mem_sgmt_;
  95. TreeHolder dtree_holder_;
  96. TreeHolder dtree_expose_empty_node_holder_;
  97. TestDomainTree& dtree;
  98. TestDomainTree& dtree_expose_empty_node;
  99. TestDomainTreeNode* dtnode;
  100. const TestDomainTreeNode* cdtnode;
  101. uint8_t buf[LabelSequence::MAX_SERIALIZED_LENGTH];
  102. };
  103. TEST_F(DomainTreeTest, nodeCount) {
  104. EXPECT_EQ(15, dtree.getNodeCount());
  105. // Delete all nodes, then the count should be set to 0. This also tests
  106. // the behavior of deleteAllNodes().
  107. dtree.deleteAllNodes(mem_sgmt_, deleteData);
  108. EXPECT_EQ(0, dtree.getNodeCount());
  109. }
  110. TEST_F(DomainTreeTest, setGetData) {
  111. // set new data to an existing node. It should have some data.
  112. int* newdata = new int(11);
  113. int* olddata = dtnode->setData(newdata);
  114. EXPECT_NE(static_cast<int*>(NULL), olddata);
  115. deleteData(olddata);
  116. EXPECT_EQ(11, *(dtnode->getData()));
  117. // clear the node. we should get the new data back we just passed.
  118. olddata = dtnode->setData(NULL);
  119. EXPECT_EQ(newdata, olddata);
  120. deleteData(olddata);
  121. }
  122. TEST_F(DomainTreeTest, insertNames) {
  123. EXPECT_EQ(TestDomainTree::ALREADYEXISTS, dtree.insert(mem_sgmt_,
  124. Name("d.e.f"),
  125. &dtnode));
  126. EXPECT_EQ(Name("d.e.f"), dtnode->getName());
  127. EXPECT_EQ(15, dtree.getNodeCount());
  128. // insert not exist node
  129. EXPECT_EQ(TestDomainTree::SUCCESS, dtree.insert(mem_sgmt_, Name("0"),
  130. &dtnode));
  131. EXPECT_EQ(Name("0"), dtnode->getName());
  132. EXPECT_EQ(16, dtree.getNodeCount());
  133. EXPECT_EQ(TestDomainTree::SUCCESS, dtree.insert(mem_sgmt_,
  134. Name("example.com"),
  135. &dtnode));
  136. EXPECT_EQ(17, dtree.getNodeCount());
  137. // add data to it; also make sure it doesn't have data right now
  138. // (otherwise it would leak)
  139. EXPECT_EQ(static_cast<int*>(NULL), dtnode->setData(new int(12)));
  140. // return ALREADYEXISTS, since node "example.com" already has
  141. // been explicitly inserted
  142. EXPECT_EQ(TestDomainTree::ALREADYEXISTS, dtree.insert(mem_sgmt_,
  143. Name("example.com"),
  144. &dtnode));
  145. EXPECT_EQ(17, dtree.getNodeCount());
  146. // split the node "d.e.f"
  147. EXPECT_EQ(TestDomainTree::SUCCESS, dtree.insert(mem_sgmt_, Name("k.e.f"),
  148. &dtnode));
  149. EXPECT_EQ(Name("k"), dtnode->getName());
  150. EXPECT_EQ(19, dtree.getNodeCount());
  151. // split the node "g.h"
  152. EXPECT_EQ(TestDomainTree::ALREADYEXISTS, dtree.insert(mem_sgmt_, Name("h"),
  153. &dtnode));
  154. EXPECT_EQ(Name("h"), dtnode->getName());
  155. EXPECT_EQ(20, dtree.getNodeCount());
  156. // add child domain
  157. EXPECT_EQ(TestDomainTree::SUCCESS, dtree.insert(mem_sgmt_,
  158. Name("m.p.w.y.d.e.f"),
  159. &dtnode));
  160. EXPECT_EQ(Name("m"), dtnode->getName());
  161. EXPECT_EQ(21, dtree.getNodeCount());
  162. EXPECT_EQ(TestDomainTree::SUCCESS, dtree.insert(mem_sgmt_,
  163. Name("n.p.w.y.d.e.f"),
  164. &dtnode));
  165. EXPECT_EQ(Name("n"), dtnode->getName());
  166. EXPECT_EQ(22, dtree.getNodeCount());
  167. EXPECT_EQ(TestDomainTree::SUCCESS, dtree.insert(mem_sgmt_, Name("l.a"),
  168. &dtnode));
  169. EXPECT_EQ(Name("l"), dtnode->getName());
  170. EXPECT_EQ(23, dtree.getNodeCount());
  171. EXPECT_EQ(TestDomainTree::SUCCESS, dtree.insert(mem_sgmt_, Name("r.d.e.f"),
  172. &dtnode));
  173. EXPECT_EQ(TestDomainTree::SUCCESS, dtree.insert(mem_sgmt_, Name("s.d.e.f"),
  174. &dtnode));
  175. EXPECT_EQ(25, dtree.getNodeCount());
  176. EXPECT_EQ(TestDomainTree::SUCCESS, dtree.insert(mem_sgmt_,
  177. Name("h.w.y.d.e.f"),
  178. &dtnode));
  179. // add more nodes one by one to cover leftRotate and rightRotate
  180. EXPECT_EQ(TestDomainTree::ALREADYEXISTS, dtree.insert(mem_sgmt_, Name("f"),
  181. &dtnode));
  182. EXPECT_EQ(TestDomainTree::SUCCESS, dtree.insert(mem_sgmt_, Name("m"),
  183. &dtnode));
  184. EXPECT_EQ(TestDomainTree::SUCCESS, dtree.insert(mem_sgmt_, Name("nm"),
  185. &dtnode));
  186. EXPECT_EQ(TestDomainTree::SUCCESS, dtree.insert(mem_sgmt_, Name("om"),
  187. &dtnode));
  188. EXPECT_EQ(TestDomainTree::SUCCESS, dtree.insert(mem_sgmt_, Name("k"),
  189. &dtnode));
  190. EXPECT_EQ(TestDomainTree::SUCCESS, dtree.insert(mem_sgmt_, Name("l"),
  191. &dtnode));
  192. EXPECT_EQ(TestDomainTree::SUCCESS, dtree.insert(mem_sgmt_, Name("fe"),
  193. &dtnode));
  194. EXPECT_EQ(TestDomainTree::SUCCESS, dtree.insert(mem_sgmt_, Name("ge"),
  195. &dtnode));
  196. EXPECT_EQ(TestDomainTree::SUCCESS, dtree.insert(mem_sgmt_, Name("i"),
  197. &dtnode));
  198. EXPECT_EQ(TestDomainTree::SUCCESS, dtree.insert(mem_sgmt_, Name("ae"),
  199. &dtnode));
  200. EXPECT_EQ(TestDomainTree::SUCCESS, dtree.insert(mem_sgmt_, Name("n"),
  201. &dtnode));
  202. }
  203. TEST_F(DomainTreeTest, subTreeRoot) {
  204. // This is a testcase for a particular issue that went unchecked in
  205. // #2089's implementation, but was fixed in #2092. The issue was
  206. // that when a node was fissioned, FLAG_SUBTREE_ROOT was not being
  207. // copied correctly.
  208. EXPECT_EQ(TestDomainTree::ALREADYEXISTS,
  209. dtree_expose_empty_node.insert(mem_sgmt_, Name("d.e.f"),
  210. &dtnode));
  211. EXPECT_EQ(TestDomainTree::SUCCESS,
  212. dtree_expose_empty_node.insert(mem_sgmt_, Name("0"),
  213. &dtnode));
  214. EXPECT_EQ(TestDomainTree::SUCCESS,
  215. dtree_expose_empty_node.insert(mem_sgmt_, Name("example.com"),
  216. &dtnode));
  217. EXPECT_EQ(TestDomainTree::ALREADYEXISTS,
  218. dtree_expose_empty_node.insert(mem_sgmt_, Name("example.com"),
  219. &dtnode));
  220. EXPECT_EQ(TestDomainTree::SUCCESS,
  221. dtree_expose_empty_node.insert(mem_sgmt_, Name("k.e.f"),
  222. &dtnode));
  223. // "g.h" is not a subtree root
  224. EXPECT_EQ(TestDomainTree::EXACTMATCH,
  225. dtree_expose_empty_node.find(Name("g.h"), &dtnode));
  226. EXPECT_FALSE(dtnode->getFlag(TestDomainTreeNode::FLAG_SUBTREE_ROOT));
  227. // fission the node "g.h"
  228. EXPECT_EQ(TestDomainTree::ALREADYEXISTS,
  229. dtree_expose_empty_node.insert(mem_sgmt_, Name("h"),
  230. &dtnode));
  231. // the node "h" (h.down_ -> "g") should not be a subtree root. "g"
  232. // should be a subtree root.
  233. EXPECT_FALSE(dtnode->getFlag(TestDomainTreeNode::FLAG_SUBTREE_ROOT));
  234. // "g.h" should be a subtree root now.
  235. EXPECT_EQ(TestDomainTree::EXACTMATCH,
  236. dtree_expose_empty_node.find(Name("g.h"), &dtnode));
  237. EXPECT_TRUE(dtnode->getFlag(TestDomainTreeNode::FLAG_SUBTREE_ROOT));
  238. }
  239. TEST_F(DomainTreeTest, additionalNodeFission) {
  240. // These are additional nodeFission tests added by #2054's rewrite
  241. // of DomainTree::nodeFission(). These test specific corner cases that
  242. // are not covered by other tests.
  243. // Insert "t.0" (which becomes the left child of its parent)
  244. EXPECT_EQ(TestDomainTree::SUCCESS,
  245. dtree_expose_empty_node.insert(mem_sgmt_, Name("t.0"),
  246. &dtnode));
  247. // "t.0" is not a subtree root
  248. EXPECT_EQ(TestDomainTree::EXACTMATCH,
  249. dtree_expose_empty_node.find(Name("t.0"), &dtnode));
  250. EXPECT_FALSE(dtnode->getFlag(TestDomainTreeNode::FLAG_SUBTREE_ROOT));
  251. // fission the node "t.0"
  252. EXPECT_EQ(TestDomainTree::ALREADYEXISTS,
  253. dtree_expose_empty_node.insert(mem_sgmt_, Name("0"),
  254. &dtnode));
  255. // the node "0" ("0".down_ -> "t") should not be a subtree root. "t"
  256. // should be a subtree root.
  257. EXPECT_FALSE(dtnode->getFlag(TestDomainTreeNode::FLAG_SUBTREE_ROOT));
  258. // "t.0" should be a subtree root now.
  259. EXPECT_EQ(TestDomainTree::EXACTMATCH,
  260. dtree_expose_empty_node.find(Name("t.0"), &dtnode));
  261. EXPECT_TRUE(dtnode->getFlag(TestDomainTreeNode::FLAG_SUBTREE_ROOT));
  262. }
  263. TEST_F(DomainTreeTest, findName) {
  264. // find const dtnode
  265. // exact match
  266. EXPECT_EQ(TestDomainTree::EXACTMATCH, dtree.find(Name("a"), &cdtnode));
  267. EXPECT_EQ(Name("a"), cdtnode->getName());
  268. // not found
  269. EXPECT_EQ(TestDomainTree::NOTFOUND, dtree.find(Name("d.e.f"), &cdtnode));
  270. EXPECT_EQ(TestDomainTree::NOTFOUND, dtree.find(Name("y.d.e.f"), &cdtnode));
  271. EXPECT_EQ(TestDomainTree::NOTFOUND, dtree.find(Name("x"), &cdtnode));
  272. EXPECT_EQ(TestDomainTree::NOTFOUND, dtree.find(Name("m.n"), &cdtnode));
  273. // if we expose empty node, we can get the empty node created during insert
  274. EXPECT_EQ(TestDomainTree::EXACTMATCH,
  275. dtree_expose_empty_node.find(Name("d.e.f"), &cdtnode));
  276. EXPECT_EQ(TestDomainTree::EXACTMATCH,
  277. dtree_expose_empty_node.find(Name("w.y.d.e.f"), &cdtnode));
  278. // partial match
  279. EXPECT_EQ(TestDomainTree::PARTIALMATCH, dtree.find(Name("m.b"), &cdtnode));
  280. EXPECT_EQ(Name("b"), cdtnode->getName());
  281. EXPECT_EQ(TestDomainTree::PARTIALMATCH,
  282. dtree_expose_empty_node.find(Name("m.d.e.f"), &cdtnode));
  283. // find dtnode
  284. EXPECT_EQ(TestDomainTree::EXACTMATCH, dtree.find(Name("q.w.y.d.e.f"),
  285. &dtnode));
  286. EXPECT_EQ(Name("q"), dtnode->getName());
  287. }
  288. TEST_F(DomainTreeTest, findError) {
  289. // For the version that takes a node chain, the chain must be empty.
  290. TestDomainTreeNodeChain chain;
  291. EXPECT_EQ(TestDomainTree::EXACTMATCH, dtree.find(Name("a"), &cdtnode,
  292. chain));
  293. // trying to reuse the same chain. it should result in an exception.
  294. EXPECT_THROW(dtree.find(Name("a"), &cdtnode, chain),
  295. BadValue);
  296. }
  297. TEST_F(DomainTreeTest, flags) {
  298. EXPECT_EQ(TestDomainTree::SUCCESS, dtree.insert(mem_sgmt_,
  299. Name("flags.example"),
  300. &dtnode));
  301. // by default, flags are all off
  302. EXPECT_FALSE(dtnode->getFlag(TestDomainTreeNode::FLAG_CALLBACK));
  303. // set operation, by default it enables the flag
  304. dtnode->setFlag(TestDomainTreeNode::FLAG_CALLBACK);
  305. EXPECT_TRUE(dtnode->getFlag(TestDomainTreeNode::FLAG_CALLBACK));
  306. // try disable the flag explicitly
  307. dtnode->setFlag(TestDomainTreeNode::FLAG_CALLBACK, false);
  308. EXPECT_FALSE(dtnode->getFlag(TestDomainTreeNode::FLAG_CALLBACK));
  309. // try enable the flag explicitly
  310. dtnode->setFlag(TestDomainTreeNode::FLAG_CALLBACK, true);
  311. EXPECT_TRUE(dtnode->getFlag(TestDomainTreeNode::FLAG_CALLBACK));
  312. // setting an unknown flag will trigger an exception
  313. EXPECT_THROW(dtnode->setFlag(static_cast<TestDomainTreeNode::Flags>(2), true),
  314. isc::InvalidParameter);
  315. }
  316. bool
  317. testCallback(const TestDomainTreeNode&, bool* callback_checker) {
  318. *callback_checker = true;
  319. return (false);
  320. }
  321. template <typename T>
  322. void
  323. performCallbackTest(TestDomainTree& dtree,
  324. util::MemorySegmentLocal& mem_sgmt,
  325. const T& name_called,
  326. const T& name_not_called)
  327. {
  328. TestDomainTreeNode* dtnode;
  329. const TestDomainTreeNode* cdtnode;
  330. // by default callback isn't enabled
  331. EXPECT_EQ(TestDomainTree::SUCCESS, dtree.insert(mem_sgmt,
  332. Name("callback.example"),
  333. &dtnode));
  334. EXPECT_EQ(static_cast<int*>(NULL), dtnode->setData(new int(1)));
  335. EXPECT_FALSE(dtnode->getFlag(TestDomainTreeNode::FLAG_CALLBACK));
  336. // enable/re-disable callback
  337. dtnode->setFlag(TestDomainTreeNode::FLAG_CALLBACK);
  338. EXPECT_TRUE(dtnode->getFlag(TestDomainTreeNode::FLAG_CALLBACK));
  339. dtnode->setFlag(TestDomainTreeNode::FLAG_CALLBACK, false);
  340. EXPECT_FALSE(dtnode->getFlag(TestDomainTreeNode::FLAG_CALLBACK));
  341. // enable again for subsequent tests
  342. dtnode->setFlag(TestDomainTreeNode::FLAG_CALLBACK);
  343. // add more levels below and above the callback node for partial match.
  344. TestDomainTreeNode* subdtnode;
  345. EXPECT_EQ(TestDomainTree::SUCCESS, dtree.insert(mem_sgmt,
  346. Name("sub.callback.example"),
  347. &subdtnode));
  348. EXPECT_EQ(static_cast<int*>(NULL), subdtnode->setData(new int(2)));
  349. TestDomainTreeNode* parentdtnode;
  350. EXPECT_EQ(TestDomainTree::ALREADYEXISTS, dtree.insert(mem_sgmt,
  351. Name("example"),
  352. &parentdtnode));
  353. // the child/parent nodes shouldn't "inherit" the callback flag.
  354. // "dtnode" may be invalid due to the insertion, so we need to re-find
  355. // it.
  356. EXPECT_EQ(TestDomainTree::EXACTMATCH, dtree.find(Name("callback.example"),
  357. &dtnode));
  358. EXPECT_TRUE(dtnode->getFlag(TestDomainTreeNode::FLAG_CALLBACK));
  359. EXPECT_FALSE(subdtnode->getFlag(TestDomainTreeNode::FLAG_CALLBACK));
  360. EXPECT_FALSE(parentdtnode->getFlag(TestDomainTreeNode::FLAG_CALLBACK));
  361. // check if the callback is called from find()
  362. TestDomainTreeNodeChain node_path1;
  363. bool callback_called = false;
  364. EXPECT_EQ(TestDomainTree::EXACTMATCH,
  365. dtree.find(name_called, &cdtnode, node_path1,
  366. testCallback, &callback_called));
  367. EXPECT_TRUE(callback_called);
  368. // enable callback at the parent node, but it doesn't have data so
  369. // the callback shouldn't be called.
  370. TestDomainTreeNodeChain node_path2;
  371. parentdtnode->setFlag(TestDomainTreeNode::FLAG_CALLBACK);
  372. callback_called = false;
  373. EXPECT_EQ(TestDomainTree::EXACTMATCH,
  374. dtree.find(name_not_called, &cdtnode, node_path2,
  375. testCallback, &callback_called));
  376. EXPECT_FALSE(callback_called);
  377. }
  378. TEST_F(DomainTreeTest, callbackName) {
  379. const Name n1("sub.callback.example");
  380. const Name n2("callback.example");
  381. performCallbackTest(dtree, mem_sgmt_, n1, n2);
  382. }
  383. TEST_F(DomainTreeTest, callbackLabelSequence) {
  384. const Name n1("sub.callback.example");
  385. const Name n2("callback.example");
  386. const LabelSequence ls1(n1);
  387. const LabelSequence ls2(n2);
  388. performCallbackTest(dtree, mem_sgmt_, ls1, ls2);
  389. }
  390. TEST_F(DomainTreeTest, findInSubTree) {
  391. // For the version that takes a node chain, the chain must be empty.
  392. DomainTreeNodeChain<int> chain;
  393. bool flag;
  394. // Searching for a non-absolute (right-stripped) label sequence when
  395. // chain is empty should throw.
  396. const Name n0("w.y.d.e.f");
  397. LabelSequence ls0(n0);
  398. ls0.stripRight(1);
  399. EXPECT_THROW(dtree_expose_empty_node.find(ls0, &cdtnode, chain,
  400. testCallback, &flag),
  401. isc::BadValue);
  402. // First, find a sub-tree node
  403. chain.clear();
  404. const LabelSequence ls1(n0);
  405. DomainTree<int>::Result result =
  406. dtree_expose_empty_node.find(ls1, &cdtnode, chain,
  407. testCallback, &flag);
  408. EXPECT_EQ(DomainTree<int>::EXACTMATCH, result);
  409. EXPECT_EQ(n0, chain.getAbsoluteName());
  410. // Searching for an absolute label sequence when chain is already
  411. // populated should throw.
  412. const Name n2a("o");
  413. const LabelSequence ls2a(n2a);
  414. EXPECT_THROW(dtree_expose_empty_node.find(ls2a, &cdtnode, chain,
  415. testCallback, &flag),
  416. isc::BadValue);
  417. // Now, find "o.w.y.d.e.f." by right-stripping the "w.y.d.e.f."
  418. // suffix to "o" (non-absolute).
  419. const Name n2("o.w.y.d.e.f");
  420. LabelSequence ls2(n2);
  421. ls2.stripRight(6);
  422. EXPECT_EQ("o", ls2.toText());
  423. result = dtree_expose_empty_node.find(ls2, &cdtnode, chain,
  424. testCallback, &flag);
  425. EXPECT_EQ(DomainTree<int>::EXACTMATCH, result);
  426. EXPECT_EQ(n2, chain.getAbsoluteName());
  427. // Another test. Start with "d.e.f." node.
  428. chain.clear();
  429. const Name n3("d.e.f");
  430. const LabelSequence ls3(n3);
  431. result =
  432. dtree_expose_empty_node.find(ls3, &cdtnode, chain,
  433. testCallback, &flag);
  434. EXPECT_EQ(DomainTree<int>::EXACTMATCH, result);
  435. EXPECT_EQ(n3, chain.getAbsoluteName());
  436. // Now, find "o.w.y.d.e.f." by right-stripping the "w.y.d.e.f."
  437. // suffix to "o.w.y" (non-absolute).
  438. const Name n4("o.w.y.d.e.f");
  439. LabelSequence ls4(n2);
  440. ls4.stripRight(4);
  441. EXPECT_EQ("o.w.y", ls4.toText());
  442. result = dtree_expose_empty_node.find(ls4, &cdtnode, chain,
  443. testCallback, &flag);
  444. EXPECT_EQ(DomainTree<int>::EXACTMATCH, result);
  445. EXPECT_EQ(n4, chain.getAbsoluteName());
  446. }
  447. TEST_F(DomainTreeTest, findInSubTreeSameLabelSequence) {
  448. // For the version that takes a node chain, the chain must be empty.
  449. DomainTreeNodeChain<int> chain;
  450. bool flag;
  451. const Name n1("c.g.h");
  452. // First insert a "c.g.h." node.
  453. dtree_expose_empty_node.insert(mem_sgmt_, n1, &dtnode);
  454. /* Now, the tree looks like:
  455. *
  456. * .
  457. * |
  458. * b
  459. * / \
  460. * a d.e.f
  461. * / | \____
  462. * c | \
  463. * | g.h
  464. * | |
  465. * w.y i
  466. * / | \ / \
  467. * x | z c k
  468. * | |
  469. * p j
  470. * / \
  471. * o q
  472. */
  473. // Make a non-absolute label sequence. We will search for this same
  474. // sequence in two places in the tree.
  475. LabelSequence ls1(n1);
  476. ls1.stripRight(3);
  477. EXPECT_EQ("c", ls1.toText());
  478. // First, find "g.h."
  479. const Name n2("g.h");
  480. const LabelSequence ls2(n2);
  481. DomainTree<int>::Result result =
  482. dtree_expose_empty_node.find(ls2, &cdtnode, chain,
  483. testCallback, &flag);
  484. EXPECT_EQ(DomainTree<int>::EXACTMATCH, result);
  485. EXPECT_EQ(n2, chain.getAbsoluteName());
  486. // Now, find "c.g.h." by searching just the non-absolute ls1 label
  487. // sequence.
  488. result = dtree_expose_empty_node.find(ls1, &cdtnode, chain,
  489. testCallback, &flag);
  490. EXPECT_EQ(DomainTree<int>::EXACTMATCH, result);
  491. EXPECT_EQ(n1, chain.getAbsoluteName());
  492. // Now, find "." (the root node)
  493. chain.clear();
  494. const Name n3(".");
  495. const LabelSequence ls3(n3);
  496. result =
  497. dtree_expose_empty_node.find(ls3, &cdtnode, chain,
  498. testCallback, &flag);
  499. EXPECT_EQ(DomainTree<int>::EXACTMATCH, result);
  500. EXPECT_EQ(n3, chain.getAbsoluteName());
  501. // Now, find "c." by searching just the non-absolute ls1 label
  502. // sequence.
  503. result = dtree_expose_empty_node.find(ls1, &cdtnode, chain,
  504. testCallback, &flag);
  505. EXPECT_EQ(DomainTree<int>::EXACTMATCH, result);
  506. EXPECT_EQ(Name("c."), chain.getAbsoluteName());
  507. }
  508. TEST_F(DomainTreeTest, chainLevel) {
  509. TestDomainTreeNodeChain chain;
  510. // by default there should be no level in the chain.
  511. EXPECT_EQ(0, chain.getLevelCount());
  512. // insert one node to the tree and find it. there should be exactly
  513. // one level in the chain.
  514. TreeHolder tree_holder(mem_sgmt_, TestDomainTree::create(mem_sgmt_, true));
  515. TestDomainTree& tree(*tree_holder.get());
  516. Name node_name(Name::ROOT_NAME());
  517. EXPECT_EQ(TestDomainTree::SUCCESS, tree.insert(mem_sgmt_, node_name,
  518. &dtnode));
  519. EXPECT_EQ(TestDomainTree::EXACTMATCH,
  520. tree.find(node_name, &cdtnode, chain));
  521. EXPECT_EQ(1, chain.getLevelCount());
  522. // Check the name of the found node (should have '.' as both non-absolute
  523. // and absolute name
  524. EXPECT_EQ(".", cdtnode->getLabels().toText());
  525. EXPECT_EQ(".", cdtnode->getAbsoluteLabels(buf).toText());
  526. /*
  527. * Now creating a possibly deepest tree with MAX_LABELS levels.
  528. * it should look like:
  529. * (.)
  530. * |
  531. * a
  532. * |
  533. * a
  534. * : (MAX_LABELS - 1) "a"'s
  535. *
  536. * then confirm that find() for the deepest name succeeds without any
  537. * disruption, and the resulting chain has the expected level.
  538. * Note that the root name (".") solely belongs to a single level,
  539. * so the levels begin with 2.
  540. */
  541. for (unsigned int i = 2; i <= Name::MAX_LABELS; ++i) {
  542. node_name = Name("a.").concatenate(node_name);
  543. EXPECT_EQ(TestDomainTree::SUCCESS, tree.insert(mem_sgmt_, node_name,
  544. &dtnode));
  545. TestDomainTreeNodeChain found_chain;
  546. EXPECT_EQ(TestDomainTree::EXACTMATCH,
  547. tree.find(node_name, &cdtnode, found_chain));
  548. EXPECT_EQ(i, found_chain.getLevelCount());
  549. // The non-absolute name should only have the first label
  550. EXPECT_EQ("a", cdtnode->getLabels().toText());
  551. // But the absolute name should have all labels
  552. EXPECT_EQ(node_name.toText(),
  553. cdtnode->getAbsoluteLabels(buf).toText());
  554. }
  555. // Confirm the last inserted name has the possible maximum length with
  556. // maximum label count. This confirms the dtree and chain level cannot
  557. // be larger.
  558. EXPECT_EQ(Name::MAX_LABELS, node_name.getLabelCount());
  559. EXPECT_THROW(node_name.concatenate(Name("a.")), TooLongName);
  560. }
  561. TEST_F(DomainTreeTest, getAbsoluteNameError) {
  562. // an empty chain isn't allowed.
  563. TestDomainTreeNodeChain chain;
  564. EXPECT_THROW(chain.getAbsoluteName(), BadValue);
  565. }
  566. /*
  567. * The domain order should be:
  568. * ., 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,
  569. * q.w.y.d.e.f, z.d.e.f, j.z.d.e.f, g.h, i.g.h, k.g.h
  570. * . (no data, can't be found)
  571. * |
  572. * b
  573. * / \
  574. * a d.e.f
  575. * / | \
  576. * c | g.h
  577. * | |
  578. * w.y i
  579. * / | \ \
  580. * x | z k
  581. * | |
  582. * p j
  583. * / \
  584. * o q
  585. */
  586. const char* const names[] = {
  587. "a", "b", "c", "d.e.f", "x.d.e.f", "w.y.d.e.f", "o.w.y.d.e.f",
  588. "p.w.y.d.e.f", "q.w.y.d.e.f", "z.d.e.f", "j.z.d.e.f",
  589. "g.h", "i.g.h", "k.g.h"};
  590. const size_t name_count(sizeof(names) / sizeof(*names));
  591. const char* const upper_node_names[] = {
  592. ".", ".", ".", ".", "d.e.f", "d.e.f", "w.y.d.e.f",
  593. "w.y.d.e.f", "w.y.d.e.f", "d.e.f", "z.d.e.f",
  594. ".", "g.h", "g.h"};
  595. TEST_F(DomainTreeTest, getUpperNode) {
  596. TestDomainTreeNodeChain node_path;
  597. const TestDomainTreeNode* node = NULL;
  598. EXPECT_EQ(TestDomainTree::EXACTMATCH,
  599. dtree_expose_empty_node.find(Name(names[0]),
  600. &node,
  601. node_path));
  602. for (int i = 0; i < name_count; ++i) {
  603. EXPECT_NE(static_cast<void*>(NULL), node);
  604. const TestDomainTreeNode* upper_node = node->getUpperNode();
  605. if (upper_node_names[i] != NULL) {
  606. const TestDomainTreeNode* upper_node2 = NULL;
  607. EXPECT_EQ(TestDomainTree::EXACTMATCH,
  608. dtree_expose_empty_node.find(Name(upper_node_names[i]),
  609. &upper_node2));
  610. EXPECT_NE(static_cast<void*>(NULL), upper_node2);
  611. EXPECT_EQ(upper_node, upper_node2);
  612. } else {
  613. EXPECT_EQ(static_cast<void*>(NULL), upper_node);
  614. }
  615. node = dtree_expose_empty_node.nextNode(node_path);
  616. }
  617. // We should have reached the end of the tree.
  618. EXPECT_EQ(static_cast<void*>(NULL), node);
  619. }
  620. TEST_F(DomainTreeTest, nextNode) {
  621. TestDomainTreeNodeChain node_path;
  622. const TestDomainTreeNode* node = NULL;
  623. EXPECT_EQ(TestDomainTree::EXACTMATCH,
  624. dtree.find(Name(names[0]), &node, node_path));
  625. for (int i = 0; i < name_count; ++i) {
  626. EXPECT_NE(static_cast<void*>(NULL), node);
  627. EXPECT_EQ(Name(names[i]), node_path.getAbsoluteName());
  628. node = dtree.nextNode(node_path);
  629. }
  630. // We should have reached the end of the tree.
  631. EXPECT_EQ(static_cast<void*>(NULL), node);
  632. }
  633. // Just walk using previousNode until the beginning of the tree and check it is
  634. // OK
  635. //
  636. // dtree - the tree to walk
  637. // node - result of previous call to find(), starting position of the walk
  638. // node_path - the path from the previous call to find(), will be modified
  639. // chain_length - the number of names that should be in the chain to be walked
  640. // (0 means it should be empty, 3 means 'a', 'b' and 'c' should be there -
  641. // this is always from the beginning of the names[] list).
  642. // skip_first - if this is false, the node should already contain the node with
  643. // the first name of the chain. If it is true, the node should be NULL
  644. // (true is for finds that return no match, false for the ones that return
  645. // match)
  646. void
  647. previousWalk(TestDomainTree& dtree, const TestDomainTreeNode* node,
  648. TestDomainTreeNodeChain& node_path, size_t chain_length,
  649. bool skip_first)
  650. {
  651. if (skip_first) {
  652. // If the first is not found, this is supposed to be NULL and we skip
  653. // it in our checks.
  654. EXPECT_EQ(static_cast<void*>(NULL), node);
  655. node = dtree.previousNode(node_path);
  656. }
  657. for (size_t i(chain_length); i > 0; --i) {
  658. EXPECT_NE(static_cast<void*>(NULL), node);
  659. EXPECT_EQ(Name(names[i - 1]), node_path.getAbsoluteName());
  660. // Find the node at the path and check the value is the same
  661. // (that it really returns the correct corresponding node)
  662. //
  663. // The "empty" nodes can not be found
  664. if (node->getData()) {
  665. const TestDomainTreeNode* node2(NULL);
  666. TestDomainTreeNodeChain node_path2;
  667. EXPECT_EQ(TestDomainTree::EXACTMATCH,
  668. dtree.find(Name(names[i - 1]), &node2, node_path2));
  669. EXPECT_EQ(node, node2);
  670. }
  671. node = dtree.previousNode(node_path);
  672. }
  673. // We should have reached the start of the tree.
  674. ASSERT_NE(static_cast<void*>(NULL), node);
  675. EXPECT_EQ(".", node->getLabels().toText());
  676. // With one more call it results in NULL
  677. node = dtree.previousNode(node_path);
  678. EXPECT_EQ(static_cast<void*>(NULL), node);
  679. // Calling previousNode() yet again should still return NULL without
  680. // fail.
  681. node = dtree.previousNode(node_path);
  682. EXPECT_EQ(static_cast<void*>(NULL), node);
  683. }
  684. // Check the previousNode
  685. TEST_F(DomainTreeTest, previousNode) {
  686. // First, iterate the whole tree from the end to the beginning.
  687. TestDomainTreeNodeChain node_path;
  688. EXPECT_THROW(dtree.previousNode(node_path), isc::BadValue) <<
  689. "Throw before a search was done on the path";
  690. const TestDomainTreeNode* node(NULL);
  691. {
  692. SCOPED_TRACE("Iterate through");
  693. EXPECT_EQ(TestDomainTree::EXACTMATCH,
  694. dtree.find(Name(names[name_count - 1]), &node, node_path));
  695. previousWalk(dtree, node, node_path, name_count, false);
  696. node = NULL;
  697. node_path.clear();
  698. }
  699. {
  700. SCOPED_TRACE("Iterate from the middle");
  701. // Now, start somewhere in the middle, but within the real node.
  702. EXPECT_EQ(TestDomainTree::EXACTMATCH,
  703. dtree.find(Name(names[4]), &node, node_path));
  704. previousWalk(dtree, node, node_path, 5, false);
  705. node = NULL;
  706. node_path.clear();
  707. }
  708. {
  709. SCOPED_TRACE("Start at the first");
  710. // If we start at the lowest (which is "a"), we get to the beginning
  711. // right away.
  712. EXPECT_EQ(TestDomainTree::EXACTMATCH,
  713. dtree.find(Name(names[0]), &node, node_path));
  714. EXPECT_NE(static_cast<void*>(NULL), node);
  715. node = dtree.previousNode(node_path);
  716. ASSERT_NE(static_cast<void*>(NULL), node);
  717. EXPECT_EQ(".", node->getLabels().toText());
  718. node = NULL;
  719. node_path.clear();
  720. }
  721. {
  722. SCOPED_TRACE("Start before the first");
  723. // If we start before the lowest (. < 0. < a.), we should not get a
  724. // node. Its previous node should be the root.
  725. EXPECT_EQ(TestDomainTree::NOTFOUND,
  726. dtree.find<void*>(Name("0"), &node, node_path, NULL, NULL));
  727. EXPECT_EQ(static_cast<void*>(NULL), node);
  728. node = dtree.previousNode(node_path);
  729. ASSERT_NE(static_cast<void*>(NULL), node);
  730. EXPECT_EQ(".", node->getLabels().toText());
  731. node = NULL;
  732. node_path.clear();
  733. }
  734. {
  735. SCOPED_TRACE("Start after the last");
  736. EXPECT_EQ(TestDomainTree::NOTFOUND,
  737. dtree.find(Name("z"), &node, node_path));
  738. previousWalk(dtree, node, node_path, name_count, true);
  739. node = NULL;
  740. node_path.clear();
  741. }
  742. {
  743. SCOPED_TRACE("Start below a leaf");
  744. // We exit a leaf by going down. We should start by the one
  745. // we exited - 'c' (actually, we should get it by the find, as partial
  746. // match).
  747. EXPECT_EQ(TestDomainTree::PARTIALMATCH,
  748. dtree.find(Name("b.c"), &node, node_path));
  749. previousWalk(dtree, node, node_path, 3, false);
  750. node = NULL;
  751. node_path.clear();
  752. }
  753. {
  754. SCOPED_TRACE("Start to the right of a leaf");
  755. // When searching for this, we exit the 'x' node to the right side,
  756. // so we should go x afterwards.
  757. // The d.e.f is empty node, so it is hidden by find. Therefore NOTFOUND
  758. // and not PARTIALMATCH.
  759. EXPECT_EQ(TestDomainTree::NOTFOUND,
  760. dtree.find(Name("xy.d.e.f"), &node, node_path));
  761. previousWalk(dtree, node, node_path, 5, true);
  762. node = NULL;
  763. node_path.clear();
  764. }
  765. {
  766. SCOPED_TRACE("Start to the left of a leaf");
  767. // This is similar to the previous, but we exit the 'z' leaf to the
  768. // left side, so should not visit z at all then.
  769. // The d.e.f is empty node, so it is hidden by find. Therefore NOTFOUND
  770. // and not PARTIALMATCH.
  771. EXPECT_EQ(TestDomainTree::NOTFOUND,
  772. dtree.find(Name("yz.d.e.f"), &node, node_path));
  773. previousWalk(dtree, node, node_path, 9, true);
  774. node = NULL;
  775. node_path.clear();
  776. }
  777. {
  778. SCOPED_TRACE("Start to the right of a parent");
  779. // When searching for this, we exit the 'g.h' node to the right
  780. // side, so we should go to g.h's children afterwards.
  781. // 'g.h' is an empty node, so we get a NOTFOUND and not
  782. // PARTIALMATCH.
  783. EXPECT_EQ(TestDomainTree::NOTFOUND,
  784. dtree.find(Name("x.h"), &node, node_path));
  785. // 'g.h' is the COMMONANCESTOR.
  786. EXPECT_EQ(node_path.getLastComparedNode()->getName(), Name("g.h"));
  787. EXPECT_EQ(NameComparisonResult::COMMONANCESTOR,
  788. node_path.getLastComparisonResult().getRelation());
  789. // find() exits to the right of 'g.h'
  790. EXPECT_GT(node_path.getLastComparisonResult().getOrder(), 0);
  791. // We then descend into 'i.g.h' and walk all the nodes in the
  792. // tree.
  793. previousWalk(dtree, node, node_path, name_count, true);
  794. node = NULL;
  795. node_path.clear();
  796. }
  797. {
  798. SCOPED_TRACE("Start inside a wrong node");
  799. // The d.e.f is a single node, but we want only part of it. We
  800. // should start iterating before it.
  801. EXPECT_EQ(TestDomainTree::NOTFOUND,
  802. dtree.find(Name("e.f"), &node, node_path));
  803. previousWalk(dtree, node, node_path, 3, true);
  804. node = NULL;
  805. node_path.clear();
  806. }
  807. {
  808. SCOPED_TRACE("Lookup in empty tree");
  809. // Just check it doesn't crash, etc.
  810. TreeHolder tree_holder(mem_sgmt_, TestDomainTree::create(mem_sgmt_));
  811. TestDomainTree& empty_tree(*tree_holder.get());
  812. EXPECT_EQ(TestDomainTree::NOTFOUND,
  813. empty_tree.find(Name("x"), &node, node_path));
  814. EXPECT_EQ(static_cast<void*>(NULL), node);
  815. EXPECT_EQ(static_cast<void*>(NULL),
  816. empty_tree.previousNode(node_path));
  817. node = NULL;
  818. node_path.clear();
  819. }
  820. }
  821. TEST_F(DomainTreeTest, nextNodeError) {
  822. // Empty chain for nextNode() is invalid.
  823. TestDomainTreeNodeChain chain;
  824. EXPECT_THROW(dtree.nextNode(chain), BadValue);
  825. }
  826. // A helper function for getLastComparedNode() below.
  827. void
  828. comparisonChecks(const TestDomainTreeNodeChain& chain,
  829. int expected_order, int expected_common_labels,
  830. NameComparisonResult::NameRelation expected_reln)
  831. {
  832. if (expected_order > 0) {
  833. EXPECT_LT(0, chain.getLastComparisonResult().getOrder());
  834. } else if (expected_order < 0) {
  835. EXPECT_GT(0, chain.getLastComparisonResult().getOrder());
  836. } else {
  837. EXPECT_EQ(0, chain.getLastComparisonResult().getOrder());
  838. }
  839. EXPECT_EQ(expected_common_labels,
  840. chain.getLastComparisonResult().getCommonLabels());
  841. EXPECT_EQ(expected_reln,
  842. chain.getLastComparisonResult().getRelation());
  843. }
  844. TEST_F(DomainTreeTest, getLastComparedNode) {
  845. TestDomainTree& tree = dtree_expose_empty_node; // use the "empty OK" mode
  846. TestDomainTreeNodeChain chain;
  847. // initially there should be no 'last compared'.
  848. EXPECT_EQ(static_cast<void*>(NULL), chain.getLastComparedNode());
  849. // A search for an empty tree should result in no 'last compared', too.
  850. TreeHolder tree_holder(mem_sgmt_, TestDomainTree::create(mem_sgmt_));
  851. TestDomainTree& empty_tree(*tree_holder.get());
  852. EXPECT_EQ(TestDomainTree::NOTFOUND,
  853. empty_tree.find(Name("a"), &cdtnode, chain));
  854. EXPECT_EQ(static_cast<void*>(NULL), chain.getLastComparedNode());
  855. chain.clear();
  856. const TestDomainTreeNode* expected_node = NULL;
  857. // Exact match case. The returned node should be last compared.
  858. EXPECT_EQ(TestDomainTree::EXACTMATCH,
  859. tree.find(Name("x.d.e.f"), &expected_node, chain));
  860. EXPECT_EQ(expected_node, chain.getLastComparedNode());
  861. // 1 = # labels of "x" (note: excluding ".")
  862. comparisonChecks(chain, 0, 1, NameComparisonResult::EQUAL);
  863. chain.clear();
  864. // Partial match, search stopped at the matching node, which should be
  865. // the last compared node.
  866. EXPECT_EQ(TestDomainTree::EXACTMATCH,
  867. tree.find(Name("k.g.h"), &expected_node));
  868. EXPECT_EQ(TestDomainTree::PARTIALMATCH,
  869. tree.find(Name("x.k.g.h"), &cdtnode, chain));
  870. EXPECT_EQ(expected_node, chain.getLastComparedNode());
  871. // k.g.h < x.k.g.h, 1 = # labels of "k"
  872. comparisonChecks(chain, 1, 1, NameComparisonResult::SUBDOMAIN);
  873. chain.clear();
  874. // Partial match, search stopped in the subtree below the matching node
  875. // after following a left branch.
  876. EXPECT_EQ(TestDomainTree::EXACTMATCH,
  877. tree.find(Name("x.d.e.f"), &expected_node));
  878. EXPECT_EQ(TestDomainTree::PARTIALMATCH,
  879. tree.find(Name("a.d.e.f"), &cdtnode, chain));
  880. EXPECT_EQ(expected_node, chain.getLastComparedNode());
  881. // a < x, no common labels
  882. comparisonChecks(chain, -1, 0, NameComparisonResult::NONE);
  883. chain.clear();
  884. // Partial match, search stopped in the subtree below the matching node
  885. // after following a right branch.
  886. EXPECT_EQ(TestDomainTree::EXACTMATCH,
  887. tree.find(Name("z.d.e.f"), &expected_node));
  888. EXPECT_EQ(TestDomainTree::PARTIALMATCH,
  889. tree.find(Name("zz.d.e.f"), &cdtnode, chain));
  890. EXPECT_EQ(expected_node, chain.getLastComparedNode());
  891. // zz > z, no common label
  892. comparisonChecks(chain, 1, 0, NameComparisonResult::NONE);
  893. chain.clear();
  894. // Partial match, search stopped at a node for a super domain of the
  895. // search name in the subtree below the matching node.
  896. EXPECT_EQ(TestDomainTree::EXACTMATCH,
  897. tree.find(Name("w.y.d.e.f"), &expected_node));
  898. EXPECT_EQ(TestDomainTree::PARTIALMATCH,
  899. tree.find(Name("y.d.e.f"), &cdtnode, chain));
  900. EXPECT_EQ(expected_node, chain.getLastComparedNode());
  901. // y < w.y, 1 = # labels of "y"
  902. comparisonChecks(chain, -1, 1, NameComparisonResult::SUPERDOMAIN);
  903. chain.clear();
  904. // Partial match, search stopped at a node that share a common ancestor
  905. // with the search name in the subtree below the matching node.
  906. // (the expected node is the same as the previous case)
  907. EXPECT_EQ(TestDomainTree::PARTIALMATCH,
  908. tree.find(Name("z.y.d.e.f"), &cdtnode, chain));
  909. EXPECT_EQ(expected_node, chain.getLastComparedNode());
  910. // z.y > w.y, 1 = # labels of "y"
  911. comparisonChecks(chain, 1, 1, NameComparisonResult::COMMONANCESTOR);
  912. chain.clear();
  913. // Search stops in the highest level (under ".") after following a left
  914. // branch. (find() still returns PARTIALMATCH due to the top level ".")
  915. EXPECT_EQ(TestDomainTree::EXACTMATCH, tree.find(Name("c"), &expected_node));
  916. EXPECT_EQ(TestDomainTree::PARTIALMATCH,
  917. tree.find(Name("bb"), &cdtnode, chain));
  918. EXPECT_EQ(expected_node, chain.getLastComparedNode());
  919. // bb < c, no common label
  920. comparisonChecks(chain, -1, 0, NameComparisonResult::NONE);
  921. chain.clear();
  922. // Search stops in the highest level (under ".") after following a right
  923. // branch. (the expected node is the same as the previous case)
  924. EXPECT_EQ(TestDomainTree::PARTIALMATCH,
  925. tree.find(Name("d"), &cdtnode, chain));
  926. EXPECT_EQ(expected_node, chain.getLastComparedNode());
  927. // d > c, no common label
  928. comparisonChecks(chain, 1, 0, NameComparisonResult::NONE);
  929. chain.clear();
  930. }
  931. TEST_F(DomainTreeTest, dumpTree) {
  932. std::ostringstream str;
  933. std::ostringstream str2;
  934. dtree.dumpTree(str);
  935. str2 << "tree has 15 node(s)\n"
  936. ". (black) [invisible] [subtreeroot]\n"
  937. " begin down from .\n"
  938. " b (black) [subtreeroot]\n"
  939. " a (black)\n"
  940. " NULL\n"
  941. " NULL\n"
  942. " d.e.f (black) [invisible]\n"
  943. " begin down from d.e.f\n"
  944. " w.y (black) [invisible] [subtreeroot]\n"
  945. " begin down from w.y\n"
  946. " p (black) [subtreeroot]\n"
  947. " o (red)\n"
  948. " NULL\n"
  949. " NULL\n"
  950. " q (red)\n"
  951. " NULL\n"
  952. " NULL\n"
  953. " end down from w.y\n"
  954. " x (red)\n"
  955. " NULL\n"
  956. " NULL\n"
  957. " z (red)\n"
  958. " begin down from z\n"
  959. " j (black) [subtreeroot]\n"
  960. " NULL\n"
  961. " NULL\n"
  962. " end down from z\n"
  963. " NULL\n"
  964. " NULL\n"
  965. " end down from d.e.f\n"
  966. " c (red)\n"
  967. " NULL\n"
  968. " NULL\n"
  969. " g.h (red)\n"
  970. " begin down from g.h\n"
  971. " i (black) [subtreeroot]\n"
  972. " NULL\n"
  973. " k (red)\n"
  974. " NULL\n"
  975. " NULL\n"
  976. " end down from g.h\n"
  977. " NULL\n"
  978. " NULL\n"
  979. " end down from .\n"
  980. " NULL\n"
  981. " NULL\n";
  982. EXPECT_EQ(str2.str(), str.str());
  983. }
  984. TEST_F(DomainTreeTest, swap) {
  985. // Store info about the first tree
  986. std::ostringstream str1;
  987. dtree.dumpTree(str1);
  988. size_t count1(dtree.getNodeCount());
  989. // Create second one and store state
  990. TreeHolder tree_holder(mem_sgmt_, TestDomainTree::create(mem_sgmt_));
  991. TestDomainTree& tree2(*tree_holder.get());
  992. TestDomainTreeNode* node;
  993. tree2.insert(mem_sgmt_, Name("second"), &node);
  994. std::ostringstream str2;
  995. tree2.dumpTree(str2);
  996. // Swap them
  997. ASSERT_NO_THROW(tree2.swap(dtree));
  998. // Check their sizes
  999. ASSERT_EQ(1, dtree.getNodeCount());
  1000. ASSERT_EQ(count1, tree2.getNodeCount());
  1001. // And content
  1002. std::ostringstream out;
  1003. dtree.dumpTree(out);
  1004. ASSERT_EQ(str2.str(), out.str());
  1005. out.str("");
  1006. tree2.dumpTree(out);
  1007. ASSERT_EQ(str1.str(), out.str());
  1008. }
  1009. // Matching in the "root zone" may be special (e.g. there's no parent,
  1010. // any domain names should be considered a subdomain of it), so it makes
  1011. // sense to test cases with the root zone explicitly.
  1012. TEST_F(DomainTreeTest, root) {
  1013. TreeHolder tree_holder(mem_sgmt_, TestDomainTree::create(mem_sgmt_));
  1014. TestDomainTree& root(*tree_holder.get());
  1015. root.insert(mem_sgmt_, Name::ROOT_NAME(), &dtnode);
  1016. EXPECT_EQ(static_cast<int*>(NULL), dtnode->setData(new int(1)));
  1017. EXPECT_EQ(TestDomainTree::EXACTMATCH,
  1018. root.find(Name::ROOT_NAME(), &cdtnode));
  1019. EXPECT_EQ(dtnode, cdtnode);
  1020. EXPECT_EQ(TestDomainTree::PARTIALMATCH,
  1021. root.find(Name("example.com"), &cdtnode));
  1022. EXPECT_EQ(dtnode, cdtnode);
  1023. // Insert a new name that better matches the query name. find() should
  1024. // find the better one.
  1025. root.insert(mem_sgmt_, Name("com"), &dtnode);
  1026. EXPECT_EQ(static_cast<int*>(NULL), dtnode->setData(new int(2)));
  1027. EXPECT_EQ(TestDomainTree::PARTIALMATCH,
  1028. root.find(Name("example.com"), &cdtnode));
  1029. EXPECT_EQ(dtnode, cdtnode);
  1030. // Perform the same tests for the tree that allows matching against empty
  1031. // nodes.
  1032. TreeHolder tree_holder_emptyok(mem_sgmt_,
  1033. TestDomainTree::create(mem_sgmt_, true));
  1034. TestDomainTree& root_emptyok(*tree_holder_emptyok.get());
  1035. root_emptyok.insert(mem_sgmt_, Name::ROOT_NAME(), &dtnode);
  1036. EXPECT_EQ(TestDomainTree::EXACTMATCH,
  1037. root_emptyok.find(Name::ROOT_NAME(), &cdtnode));
  1038. EXPECT_EQ(dtnode, cdtnode);
  1039. EXPECT_EQ(TestDomainTree::PARTIALMATCH,
  1040. root_emptyok.find(Name("example.com"), &cdtnode));
  1041. EXPECT_EQ(dtnode, cdtnode);
  1042. root.insert(mem_sgmt_, Name("com"), &dtnode);
  1043. EXPECT_EQ(TestDomainTree::PARTIALMATCH,
  1044. root.find(Name("example.com"), &cdtnode));
  1045. EXPECT_EQ(dtnode, cdtnode);
  1046. }
  1047. TEST_F(DomainTreeTest, getAbsoluteLabels) {
  1048. // The full absolute names of the nodes in the tree
  1049. // with the addition of the explicit root node
  1050. const char* const domain_names[] = {
  1051. "c", "b", "a", "x.d.e.f", "z.d.e.f", "g.h", "i.g.h", "o.w.y.d.e.f",
  1052. "j.z.d.e.f", "p.w.y.d.e.f", "q.w.y.d.e.f", "k.g.h"};
  1053. // The names of the nodes themselves, as they end up in the tree
  1054. const char* const first_labels[] = {
  1055. "c", "b", "a", "x", "z", "g.h", "i", "o",
  1056. "j", "p", "q", "k"};
  1057. const int name_count = sizeof(domain_names) / sizeof(domain_names[0]);
  1058. for (int i = 0; i < name_count; ++i) {
  1059. EXPECT_EQ(TestDomainTree::EXACTMATCH, dtree.find(Name(domain_names[i]),
  1060. &cdtnode));
  1061. // First make sure the names themselves are not absolute
  1062. const LabelSequence ls(cdtnode->getLabels());
  1063. EXPECT_EQ(first_labels[i], ls.toText());
  1064. EXPECT_FALSE(ls.isAbsolute());
  1065. // Now check the absolute names
  1066. const LabelSequence abs_ls(cdtnode->getAbsoluteLabels(buf));
  1067. EXPECT_EQ(Name(domain_names[i]).toText(), abs_ls.toText());
  1068. EXPECT_TRUE(abs_ls.isAbsolute());
  1069. }
  1070. // Explicitly add and find a root node, to see that getAbsoluteLabels
  1071. // also works when getLabels() already returns an absolute LabelSequence
  1072. dtree.insert(mem_sgmt_, Name("."), &dtnode);
  1073. dtnode->setData(new int(1));
  1074. EXPECT_EQ(TestDomainTree::EXACTMATCH, dtree.find(Name("."), &cdtnode));
  1075. EXPECT_TRUE(cdtnode->getLabels().isAbsolute());
  1076. EXPECT_EQ(".", cdtnode->getLabels().toText());
  1077. EXPECT_TRUE(cdtnode->getAbsoluteLabels(buf).isAbsolute());
  1078. EXPECT_EQ(".", cdtnode->getAbsoluteLabels(buf).toText());
  1079. }
  1080. }