rbtree_unittest.cc 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991
  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/rbtree.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;
  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 rbtree
  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. class TreeHolder {
  52. public:
  53. TreeHolder(util::MemorySegment& mem_sgmt, RBTree<int>* tree) :
  54. mem_sgmt_(mem_sgmt), tree_(tree)
  55. {}
  56. ~TreeHolder() {
  57. RBTree<int>::destroy(mem_sgmt_, tree_);
  58. }
  59. RBTree<int>* get() { return (tree_); }
  60. private:
  61. util::MemorySegment& mem_sgmt_;
  62. RBTree<int>* tree_;
  63. };
  64. class RBTreeTest : public::testing::Test {
  65. protected:
  66. RBTreeTest() :
  67. rbtree_holder_(mem_sgmt_, RBTree<int>::create(mem_sgmt_)),
  68. rbtree_expose_empty_node_holder_(mem_sgmt_,
  69. RBTree<int>::create(mem_sgmt_, true)),
  70. rbtree(*rbtree_holder_.get()),
  71. rbtree_expose_empty_node(*rbtree_expose_empty_node_holder_.get()),
  72. crbtnode(NULL)
  73. {
  74. const char* const domain_names[] = {
  75. "c", "b", "a", "x.d.e.f", "z.d.e.f", "g.h", "i.g.h", "o.w.y.d.e.f",
  76. "j.z.d.e.f", "p.w.y.d.e.f", "q.w.y.d.e.f", "k.g.h"};
  77. int name_count = sizeof(domain_names) / sizeof(domain_names[0]);
  78. for (int i = 0; i < name_count; ++i) {
  79. rbtree.insert(mem_sgmt_, Name(domain_names[i]), &rbtnode);
  80. rbtnode->setData(RBNode<int>::NodeDataPtr(new int(i + 1)));
  81. rbtree_expose_empty_node.insert(mem_sgmt_, Name(domain_names[i]),
  82. &rbtnode);
  83. rbtnode->setData(RBNode<int>::NodeDataPtr(new int(i + 1)));
  84. }
  85. }
  86. util::MemorySegmentLocal mem_sgmt_;
  87. TreeHolder rbtree_holder_;
  88. TreeHolder rbtree_expose_empty_node_holder_;
  89. RBTree<int>& rbtree;
  90. RBTree<int>& rbtree_expose_empty_node;
  91. RBNode<int>* rbtnode;
  92. const RBNode<int>* crbtnode;
  93. };
  94. TEST_F(RBTreeTest, nodeCount) {
  95. EXPECT_EQ(15, rbtree.getNodeCount());
  96. // Delete all nodes, then the count should be set to 0. This also tests
  97. // the behavior of deleteAllNodes().
  98. rbtree.deleteAllNodes(mem_sgmt_);
  99. EXPECT_EQ(0, rbtree.getNodeCount());
  100. }
  101. TEST_F(RBTreeTest, setGetData) {
  102. rbtnode->setData(RBNode<int>::NodeDataPtr(new int(11)));
  103. EXPECT_EQ(11, *(rbtnode->getData()));
  104. }
  105. TEST_F(RBTreeTest, insertNames) {
  106. EXPECT_EQ(RBTree<int>::ALREADYEXISTS, rbtree.insert(mem_sgmt_,
  107. Name("d.e.f"),
  108. &rbtnode));
  109. EXPECT_EQ(Name("d.e.f"), rbtnode->getName());
  110. EXPECT_EQ(15, rbtree.getNodeCount());
  111. // insert not exist node
  112. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_, Name("0"),
  113. &rbtnode));
  114. EXPECT_EQ(Name("0"), rbtnode->getName());
  115. EXPECT_EQ(16, rbtree.getNodeCount());
  116. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_,
  117. Name("example.com"),
  118. &rbtnode));
  119. EXPECT_EQ(17, rbtree.getNodeCount());
  120. rbtnode->setData(RBNode<int>::NodeDataPtr(new int(12)));
  121. // return ALREADYEXISTS, since node "example.com" already has
  122. // been explicitly inserted
  123. EXPECT_EQ(RBTree<int>::ALREADYEXISTS, rbtree.insert(mem_sgmt_,
  124. Name("example.com"),
  125. &rbtnode));
  126. EXPECT_EQ(17, rbtree.getNodeCount());
  127. // split the node "d.e.f"
  128. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_, Name("k.e.f"),
  129. &rbtnode));
  130. EXPECT_EQ(Name("k"), rbtnode->getName());
  131. EXPECT_EQ(19, rbtree.getNodeCount());
  132. // split the node "g.h"
  133. EXPECT_EQ(RBTree<int>::ALREADYEXISTS, rbtree.insert(mem_sgmt_, Name("h"),
  134. &rbtnode));
  135. EXPECT_EQ(Name("h"), rbtnode->getName());
  136. EXPECT_EQ(20, rbtree.getNodeCount());
  137. // add child domain
  138. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_,
  139. Name("m.p.w.y.d.e.f"),
  140. &rbtnode));
  141. EXPECT_EQ(Name("m"), rbtnode->getName());
  142. EXPECT_EQ(21, rbtree.getNodeCount());
  143. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_,
  144. Name("n.p.w.y.d.e.f"),
  145. &rbtnode));
  146. EXPECT_EQ(Name("n"), rbtnode->getName());
  147. EXPECT_EQ(22, rbtree.getNodeCount());
  148. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_, Name("l.a"),
  149. &rbtnode));
  150. EXPECT_EQ(Name("l"), rbtnode->getName());
  151. EXPECT_EQ(23, rbtree.getNodeCount());
  152. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_, Name("r.d.e.f"),
  153. &rbtnode));
  154. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_, Name("s.d.e.f"),
  155. &rbtnode));
  156. EXPECT_EQ(25, rbtree.getNodeCount());
  157. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_,
  158. Name("h.w.y.d.e.f"),
  159. &rbtnode));
  160. // add more nodes one by one to cover leftRotate and rightRotate
  161. EXPECT_EQ(RBTree<int>::ALREADYEXISTS, rbtree.insert(mem_sgmt_, Name("f"),
  162. &rbtnode));
  163. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_, Name("m"),
  164. &rbtnode));
  165. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_, Name("nm"),
  166. &rbtnode));
  167. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_, Name("om"),
  168. &rbtnode));
  169. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_, Name("k"),
  170. &rbtnode));
  171. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_, Name("l"),
  172. &rbtnode));
  173. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_, Name("fe"),
  174. &rbtnode));
  175. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_, Name("ge"),
  176. &rbtnode));
  177. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_, Name("i"),
  178. &rbtnode));
  179. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_, Name("ae"),
  180. &rbtnode));
  181. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_, Name("n"),
  182. &rbtnode));
  183. }
  184. TEST_F(RBTreeTest, subTreeRoot) {
  185. // This is a testcase for a particular issue that went unchecked in
  186. // #2089's implementation, but was fixed in #2092. The issue was
  187. // that when a node was fissioned, FLAG_SUBTREE_ROOT was not being
  188. // copied correctly.
  189. EXPECT_EQ(RBTree<int>::ALREADYEXISTS,
  190. rbtree_expose_empty_node.insert(mem_sgmt_, Name("d.e.f"),
  191. &rbtnode));
  192. EXPECT_EQ(RBTree<int>::SUCCESS,
  193. rbtree_expose_empty_node.insert(mem_sgmt_, Name("0"),
  194. &rbtnode));
  195. EXPECT_EQ(RBTree<int>::SUCCESS,
  196. rbtree_expose_empty_node.insert(mem_sgmt_, Name("example.com"),
  197. &rbtnode));
  198. EXPECT_EQ(RBTree<int>::ALREADYEXISTS,
  199. rbtree_expose_empty_node.insert(mem_sgmt_, Name("example.com"),
  200. &rbtnode));
  201. EXPECT_EQ(RBTree<int>::SUCCESS,
  202. rbtree_expose_empty_node.insert(mem_sgmt_, Name("k.e.f"),
  203. &rbtnode));
  204. // "g.h" is not a subtree root
  205. EXPECT_EQ(RBTree<int>::EXACTMATCH,
  206. rbtree_expose_empty_node.find(Name("g.h"), &rbtnode));
  207. EXPECT_FALSE(rbtnode->getFlag(RBNode<int>::FLAG_SUBTREE_ROOT));
  208. // fission the node "g.h"
  209. EXPECT_EQ(RBTree<int>::ALREADYEXISTS,
  210. rbtree_expose_empty_node.insert(mem_sgmt_, Name("h"),
  211. &rbtnode));
  212. // the node "h" (h.down_ -> "g") should not be a subtree root. "g"
  213. // should be a subtree root.
  214. EXPECT_FALSE(rbtnode->getFlag(RBNode<int>::FLAG_SUBTREE_ROOT));
  215. // "g.h" should be a subtree root now.
  216. EXPECT_EQ(RBTree<int>::EXACTMATCH,
  217. rbtree_expose_empty_node.find(Name("g.h"), &rbtnode));
  218. EXPECT_TRUE(rbtnode->getFlag(RBNode<int>::FLAG_SUBTREE_ROOT));
  219. }
  220. TEST_F(RBTreeTest, findName) {
  221. // find const rbtnode
  222. // exact match
  223. EXPECT_EQ(RBTree<int>::EXACTMATCH, rbtree.find(Name("a"), &crbtnode));
  224. EXPECT_EQ(Name("a"), crbtnode->getName());
  225. // not found
  226. EXPECT_EQ(RBTree<int>::NOTFOUND, rbtree.find(Name("d.e.f"), &crbtnode));
  227. EXPECT_EQ(RBTree<int>::NOTFOUND, rbtree.find(Name("y.d.e.f"), &crbtnode));
  228. EXPECT_EQ(RBTree<int>::NOTFOUND, rbtree.find(Name("x"), &crbtnode));
  229. EXPECT_EQ(RBTree<int>::NOTFOUND, rbtree.find(Name("m.n"), &crbtnode));
  230. // if we expose empty node, we can get the empty node created during insert
  231. EXPECT_EQ(RBTree<int>::EXACTMATCH,
  232. rbtree_expose_empty_node.find(Name("d.e.f"), &crbtnode));
  233. EXPECT_EQ(RBTree<int>::EXACTMATCH,
  234. rbtree_expose_empty_node.find(Name("w.y.d.e.f"), &crbtnode));
  235. // partial match
  236. EXPECT_EQ(RBTree<int>::PARTIALMATCH, rbtree.find(Name("m.b"), &crbtnode));
  237. EXPECT_EQ(Name("b"), crbtnode->getName());
  238. EXPECT_EQ(RBTree<int>::PARTIALMATCH,
  239. rbtree_expose_empty_node.find(Name("m.d.e.f"), &crbtnode));
  240. // find rbtnode
  241. EXPECT_EQ(RBTree<int>::EXACTMATCH, rbtree.find(Name("q.w.y.d.e.f"),
  242. &rbtnode));
  243. EXPECT_EQ(Name("q"), rbtnode->getName());
  244. }
  245. TEST_F(RBTreeTest, findError) {
  246. // For the version that takes a node chain, the chain must be empty.
  247. RBTreeNodeChain<int> chain;
  248. EXPECT_EQ(RBTree<int>::EXACTMATCH, rbtree.find(Name("a"), &crbtnode,
  249. chain));
  250. // trying to reuse the same chain. it should result in an exception.
  251. EXPECT_THROW(rbtree.find(Name("a"), &crbtnode, chain),
  252. BadValue);
  253. }
  254. TEST_F(RBTreeTest, flags) {
  255. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt_,
  256. Name("flags.example"),
  257. &rbtnode));
  258. // by default, flags are all off
  259. EXPECT_FALSE(rbtnode->getFlag(RBNode<int>::FLAG_CALLBACK));
  260. // set operation, by default it enables the flag
  261. rbtnode->setFlag(RBNode<int>::FLAG_CALLBACK);
  262. EXPECT_TRUE(rbtnode->getFlag(RBNode<int>::FLAG_CALLBACK));
  263. // try disable the flag explicitly
  264. rbtnode->setFlag(RBNode<int>::FLAG_CALLBACK, false);
  265. EXPECT_FALSE(rbtnode->getFlag(RBNode<int>::FLAG_CALLBACK));
  266. // try enable the flag explicitly
  267. rbtnode->setFlag(RBNode<int>::FLAG_CALLBACK, true);
  268. EXPECT_TRUE(rbtnode->getFlag(RBNode<int>::FLAG_CALLBACK));
  269. // setting an unknown flag will trigger an exception
  270. EXPECT_THROW(rbtnode->setFlag(static_cast<RBNode<int>::Flags>(2), true),
  271. isc::InvalidParameter);
  272. }
  273. bool
  274. testCallback(const RBNode<int>&, bool* callback_checker) {
  275. *callback_checker = true;
  276. return (false);
  277. }
  278. template <typename T>
  279. void
  280. performCallbackTest(RBTree<int>& rbtree,
  281. util::MemorySegmentLocal& mem_sgmt,
  282. const T& name_called,
  283. const T& name_not_called)
  284. {
  285. RBNode<int>* rbtnode;
  286. const RBNode<int>* crbtnode;
  287. // by default callback isn't enabled
  288. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt,
  289. Name("callback.example"),
  290. &rbtnode));
  291. rbtnode->setData(RBNode<int>::NodeDataPtr(new int(1)));
  292. EXPECT_FALSE(rbtnode->getFlag(RBNode<int>::FLAG_CALLBACK));
  293. // enable/re-disable callback
  294. rbtnode->setFlag(RBNode<int>::FLAG_CALLBACK);
  295. EXPECT_TRUE(rbtnode->getFlag(RBNode<int>::FLAG_CALLBACK));
  296. rbtnode->setFlag(RBNode<int>::FLAG_CALLBACK, false);
  297. EXPECT_FALSE(rbtnode->getFlag(RBNode<int>::FLAG_CALLBACK));
  298. // enable again for subsequent tests
  299. rbtnode->setFlag(RBNode<int>::FLAG_CALLBACK);
  300. // add more levels below and above the callback node for partial match.
  301. RBNode<int>* subrbtnode;
  302. EXPECT_EQ(RBTree<int>::SUCCESS, rbtree.insert(mem_sgmt,
  303. Name("sub.callback.example"),
  304. &subrbtnode));
  305. subrbtnode->setData(RBNode<int>::NodeDataPtr(new int(2)));
  306. RBNode<int>* parentrbtnode;
  307. EXPECT_EQ(RBTree<int>::ALREADYEXISTS, rbtree.insert(mem_sgmt,
  308. Name("example"),
  309. &parentrbtnode));
  310. // the child/parent nodes shouldn't "inherit" the callback flag.
  311. // "rbtnode" may be invalid due to the insertion, so we need to re-find
  312. // it.
  313. EXPECT_EQ(RBTree<int>::EXACTMATCH, rbtree.find(Name("callback.example"),
  314. &rbtnode));
  315. EXPECT_TRUE(rbtnode->getFlag(RBNode<int>::FLAG_CALLBACK));
  316. EXPECT_FALSE(subrbtnode->getFlag(RBNode<int>::FLAG_CALLBACK));
  317. EXPECT_FALSE(parentrbtnode->getFlag(RBNode<int>::FLAG_CALLBACK));
  318. // check if the callback is called from find()
  319. RBTreeNodeChain<int> node_path1;
  320. bool callback_called = false;
  321. EXPECT_EQ(RBTree<int>::EXACTMATCH,
  322. rbtree.find(name_called, &crbtnode, node_path1,
  323. testCallback, &callback_called));
  324. EXPECT_TRUE(callback_called);
  325. // enable callback at the parent node, but it doesn't have data so
  326. // the callback shouldn't be called.
  327. RBTreeNodeChain<int> node_path2;
  328. parentrbtnode->setFlag(RBNode<int>::FLAG_CALLBACK);
  329. callback_called = false;
  330. EXPECT_EQ(RBTree<int>::EXACTMATCH,
  331. rbtree.find(name_not_called, &crbtnode, node_path2,
  332. testCallback, &callback_called));
  333. EXPECT_FALSE(callback_called);
  334. }
  335. TEST_F(RBTreeTest, callbackName) {
  336. const Name n1("sub.callback.example");
  337. const Name n2("callback.example");
  338. performCallbackTest(rbtree, mem_sgmt_, n1, n2);
  339. }
  340. TEST_F(RBTreeTest, callbackLabelSequence) {
  341. const Name n1("sub.callback.example");
  342. const Name n2("callback.example");
  343. const LabelSequence ls1(n1);
  344. const LabelSequence ls2(n2);
  345. performCallbackTest(rbtree, mem_sgmt_, ls1, ls2);
  346. }
  347. TEST_F(RBTreeTest, chainLevel) {
  348. RBTreeNodeChain<int> chain;
  349. // by default there should be no level in the chain.
  350. EXPECT_EQ(0, chain.getLevelCount());
  351. // insert one node to the tree and find it. there should be exactly
  352. // one level in the chain.
  353. TreeHolder tree_holder(mem_sgmt_, RBTree<int>::create(mem_sgmt_, true));
  354. RBTree<int>& tree(*tree_holder.get());
  355. Name node_name(Name::ROOT_NAME());
  356. EXPECT_EQ(RBTree<int>::SUCCESS, tree.insert(mem_sgmt_, node_name,
  357. &rbtnode));
  358. EXPECT_EQ(RBTree<int>::EXACTMATCH,
  359. tree.find(node_name, &crbtnode, chain));
  360. EXPECT_EQ(1, chain.getLevelCount());
  361. /*
  362. * Now creating a possibly deepest tree with MAX_LABELS levels.
  363. * it should look like:
  364. * (.)
  365. * |
  366. * a
  367. * |
  368. * a
  369. * : (MAX_LABELS - 1) "a"'s
  370. *
  371. * then confirm that find() for the deepest name succeeds without any
  372. * disruption, and the resulting chain has the expected level.
  373. * Note that the root name (".") solely belongs to a single level,
  374. * so the levels begin with 2.
  375. */
  376. for (unsigned int i = 2; i <= Name::MAX_LABELS; ++i) {
  377. node_name = Name("a.").concatenate(node_name);
  378. EXPECT_EQ(RBTree<int>::SUCCESS, tree.insert(mem_sgmt_, node_name,
  379. &rbtnode));
  380. RBTreeNodeChain<int> found_chain;
  381. EXPECT_EQ(RBTree<int>::EXACTMATCH,
  382. tree.find(node_name, &crbtnode, found_chain));
  383. EXPECT_EQ(i, found_chain.getLevelCount());
  384. }
  385. // Confirm the last inserted name has the possible maximum length with
  386. // maximum label count. This confirms the rbtree and chain level cannot
  387. // be larger.
  388. EXPECT_EQ(Name::MAX_LABELS, node_name.getLabelCount());
  389. EXPECT_THROW(node_name.concatenate(Name("a.")), TooLongName);
  390. }
  391. TEST_F(RBTreeTest, getAbsoluteNameError) {
  392. // an empty chain isn't allowed.
  393. RBTreeNodeChain<int> chain;
  394. EXPECT_THROW(chain.getAbsoluteName(), BadValue);
  395. }
  396. /*
  397. * The domain order should be:
  398. * ., 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,
  399. * q.w.y.d.e.f, z.d.e.f, j.z.d.e.f, g.h, i.g.h, k.g.h
  400. * . (no data, can't be found)
  401. * |
  402. * b
  403. * / \
  404. * a d.e.f
  405. * / | \
  406. * c | g.h
  407. * | |
  408. * w.y i
  409. * / | \ \
  410. * x | z k
  411. * | |
  412. * p j
  413. * / \
  414. * o q
  415. */
  416. const char* const names[] = {
  417. "a", "b", "c", "d.e.f", "x.d.e.f", "w.y.d.e.f", "o.w.y.d.e.f",
  418. "p.w.y.d.e.f", "q.w.y.d.e.f", "z.d.e.f", "j.z.d.e.f",
  419. "g.h", "i.g.h", "k.g.h"};
  420. const size_t name_count(sizeof(names) / sizeof(*names));
  421. const char* const upper_node_names[] = {
  422. ".", ".", ".", ".", "d.e.f", "d.e.f", "w.y.d.e.f",
  423. "w.y.d.e.f", "w.y.d.e.f", "d.e.f", "z.d.e.f",
  424. ".", "g.h", "g.h"};
  425. TEST_F(RBTreeTest, getUpperNode) {
  426. RBTreeNodeChain<int> node_path;
  427. const RBNode<int>* node = NULL;
  428. EXPECT_EQ(RBTree<int>::EXACTMATCH,
  429. rbtree_expose_empty_node.find(Name(names[0]),
  430. &node,
  431. node_path));
  432. for (int i = 0; i < name_count; ++i) {
  433. EXPECT_NE(static_cast<void*>(NULL), node);
  434. const RBNode<int>* upper_node = node->getUpperNode();
  435. if (upper_node_names[i] != NULL) {
  436. const RBNode<int>* upper_node2 = NULL;
  437. EXPECT_EQ(RBTree<int>::EXACTMATCH,
  438. rbtree_expose_empty_node.find(Name(upper_node_names[i]),
  439. &upper_node2));
  440. EXPECT_NE(static_cast<void*>(NULL), upper_node2);
  441. EXPECT_EQ(upper_node, upper_node2);
  442. } else {
  443. EXPECT_EQ(static_cast<void*>(NULL), upper_node);
  444. }
  445. node = rbtree_expose_empty_node.nextNode(node_path);
  446. }
  447. // We should have reached the end of the tree.
  448. EXPECT_EQ(static_cast<void*>(NULL), node);
  449. }
  450. TEST_F(RBTreeTest, nextNode) {
  451. RBTreeNodeChain<int> node_path;
  452. const RBNode<int>* node = NULL;
  453. EXPECT_EQ(RBTree<int>::EXACTMATCH,
  454. rbtree.find(Name(names[0]), &node, node_path));
  455. for (int i = 0; i < name_count; ++i) {
  456. EXPECT_NE(static_cast<void*>(NULL), node);
  457. EXPECT_EQ(Name(names[i]), node_path.getAbsoluteName());
  458. node = rbtree.nextNode(node_path);
  459. }
  460. // We should have reached the end of the tree.
  461. EXPECT_EQ(static_cast<void*>(NULL), node);
  462. }
  463. // Just walk using previousNode until the beginning of the tree and check it is
  464. // OK
  465. //
  466. // rbtree - the tree to walk
  467. // node - result of previous call to find(), starting position of the walk
  468. // node_path - the path from the previous call to find(), will be modified
  469. // chain_length - the number of names that should be in the chain to be walked
  470. // (0 means it should be empty, 3 means 'a', 'b' and 'c' should be there -
  471. // this is always from the beginning of the names[] list).
  472. // skip_first - if this is false, the node should already contain the node with
  473. // the first name of the chain. If it is true, the node should be NULL
  474. // (true is for finds that return no match, false for the ones that return
  475. // match)
  476. void
  477. previousWalk(RBTree<int>& rbtree, const RBNode<int>* node,
  478. RBTreeNodeChain<int>& node_path, size_t chain_length,
  479. bool skip_first)
  480. {
  481. if (skip_first) {
  482. // If the first is not found, this is supposed to be NULL and we skip
  483. // it in our checks.
  484. EXPECT_EQ(static_cast<void*>(NULL), node);
  485. node = rbtree.previousNode(node_path);
  486. }
  487. for (size_t i(chain_length); i > 0; --i) {
  488. EXPECT_NE(static_cast<void*>(NULL), node);
  489. EXPECT_EQ(Name(names[i - 1]), node_path.getAbsoluteName());
  490. // Find the node at the path and check the value is the same
  491. // (that it really returns the correct corresponding node)
  492. //
  493. // The "empty" nodes can not be found
  494. if (node->getData()) {
  495. const RBNode<int>* node2(NULL);
  496. RBTreeNodeChain<int> node_path2;
  497. EXPECT_EQ(RBTree<int>::EXACTMATCH,
  498. rbtree.find(Name(names[i - 1]), &node2, node_path2));
  499. EXPECT_EQ(node, node2);
  500. }
  501. node = rbtree.previousNode(node_path);
  502. }
  503. // We should have reached the start of the tree.
  504. ASSERT_NE(static_cast<void*>(NULL), node);
  505. EXPECT_EQ(".", node->getLabels().toText());
  506. // With one more call it results in NULL
  507. node = rbtree.previousNode(node_path);
  508. EXPECT_EQ(static_cast<void*>(NULL), node);
  509. // Calling previousNode() yet again should still return NULL without
  510. // fail.
  511. node = rbtree.previousNode(node_path);
  512. EXPECT_EQ(static_cast<void*>(NULL), node);
  513. }
  514. // Check the previousNode
  515. TEST_F(RBTreeTest, previousNode) {
  516. // First, iterate the whole tree from the end to the beginning.
  517. RBTreeNodeChain<int> node_path;
  518. EXPECT_THROW(rbtree.previousNode(node_path), isc::BadValue) <<
  519. "Throw before a search was done on the path";
  520. const RBNode<int>* node(NULL);
  521. {
  522. SCOPED_TRACE("Iterate through");
  523. EXPECT_EQ(RBTree<int>::EXACTMATCH,
  524. rbtree.find(Name(names[name_count - 1]), &node, node_path));
  525. previousWalk(rbtree, node, node_path, name_count, false);
  526. node = NULL;
  527. node_path.clear();
  528. }
  529. {
  530. SCOPED_TRACE("Iterate from the middle");
  531. // Now, start somewhere in the middle, but within the real node.
  532. EXPECT_EQ(RBTree<int>::EXACTMATCH,
  533. rbtree.find(Name(names[4]), &node, node_path));
  534. previousWalk(rbtree, node, node_path, 5, false);
  535. node = NULL;
  536. node_path.clear();
  537. }
  538. {
  539. SCOPED_TRACE("Start at the first");
  540. // If we start at the lowest (which is "a"), we get to the beginning
  541. // right away.
  542. EXPECT_EQ(RBTree<int>::EXACTMATCH,
  543. rbtree.find(Name(names[0]), &node, node_path));
  544. EXPECT_NE(static_cast<void*>(NULL), node);
  545. node = rbtree.previousNode(node_path);
  546. ASSERT_NE(static_cast<void*>(NULL), node);
  547. EXPECT_EQ(".", node->getLabels().toText());
  548. node = NULL;
  549. node_path.clear();
  550. }
  551. {
  552. SCOPED_TRACE("Start before the first");
  553. // If we start before the lowest (. < 0. < a.), we should not get a
  554. // node. Its previous node should be the root.
  555. EXPECT_EQ(RBTree<int>::NOTFOUND,
  556. rbtree.find<void*>(Name("0"), &node, node_path, NULL, NULL));
  557. EXPECT_EQ(static_cast<void*>(NULL), node);
  558. node = rbtree.previousNode(node_path);
  559. ASSERT_NE(static_cast<void*>(NULL), node);
  560. EXPECT_EQ(".", node->getLabels().toText());
  561. node = NULL;
  562. node_path.clear();
  563. }
  564. {
  565. SCOPED_TRACE("Start after the last");
  566. EXPECT_EQ(RBTree<int>::NOTFOUND,
  567. rbtree.find(Name("z"), &node, node_path));
  568. previousWalk(rbtree, node, node_path, name_count, true);
  569. node = NULL;
  570. node_path.clear();
  571. }
  572. {
  573. SCOPED_TRACE("Start below a leaf");
  574. // We exit a leaf by going down. We should start by the one
  575. // we exited - 'c' (actually, we should get it by the find, as partial
  576. // match).
  577. EXPECT_EQ(RBTree<int>::PARTIALMATCH,
  578. rbtree.find(Name("b.c"), &node, node_path));
  579. previousWalk(rbtree, node, node_path, 3, false);
  580. node = NULL;
  581. node_path.clear();
  582. }
  583. {
  584. SCOPED_TRACE("Start to the right of a leaf");
  585. // When searching for this, we exit the 'x' node to the right side,
  586. // so we should go x afterwards.
  587. // The d.e.f is empty node, so it is hidden by find. Therefore NOTFOUND
  588. // and not PARTIALMATCH.
  589. EXPECT_EQ(RBTree<int>::NOTFOUND,
  590. rbtree.find(Name("xy.d.e.f"), &node, node_path));
  591. previousWalk(rbtree, node, node_path, 5, true);
  592. node = NULL;
  593. node_path.clear();
  594. }
  595. {
  596. SCOPED_TRACE("Start to the left of a leaf");
  597. // This is similar to the previous, but we exit the 'z' leaf to the
  598. // left side, so should not visit z at all then.
  599. // The d.e.f is empty node, so it is hidden by find. Therefore NOTFOUND
  600. // and not PARTIALMATCH.
  601. EXPECT_EQ(RBTree<int>::NOTFOUND,
  602. rbtree.find(Name("yz.d.e.f"), &node, node_path));
  603. previousWalk(rbtree, node, node_path, 9, true);
  604. node = NULL;
  605. node_path.clear();
  606. }
  607. {
  608. SCOPED_TRACE("Start to the right of a parent");
  609. // When searching for this, we exit the 'g.h' node to the right
  610. // side, so we should go to g.h's children afterwards.
  611. // 'g.h' is an empty node, so we get a NOTFOUND and not
  612. // PARTIALMATCH.
  613. EXPECT_EQ(RBTree<int>::NOTFOUND,
  614. rbtree.find(Name("x.h"), &node, node_path));
  615. // 'g.h' is the COMMONANCESTOR.
  616. EXPECT_EQ(node_path.getLastComparedNode()->getName(), Name("g.h"));
  617. EXPECT_EQ(NameComparisonResult::COMMONANCESTOR,
  618. node_path.getLastComparisonResult().getRelation());
  619. // find() exits to the right of 'g.h'
  620. EXPECT_GT(node_path.getLastComparisonResult().getOrder(), 0);
  621. // We then descend into 'i.g.h' and walk all the nodes in the
  622. // tree.
  623. previousWalk(rbtree, node, node_path, name_count, true);
  624. node = NULL;
  625. node_path.clear();
  626. }
  627. {
  628. SCOPED_TRACE("Start inside a wrong node");
  629. // The d.e.f is a single node, but we want only part of it. We
  630. // should start iterating before it.
  631. EXPECT_EQ(RBTree<int>::NOTFOUND,
  632. rbtree.find(Name("e.f"), &node, node_path));
  633. previousWalk(rbtree, node, node_path, 3, true);
  634. node = NULL;
  635. node_path.clear();
  636. }
  637. {
  638. SCOPED_TRACE("Lookup in empty tree");
  639. // Just check it doesn't crash, etc.
  640. TreeHolder tree_holder(mem_sgmt_, RBTree<int>::create(mem_sgmt_));
  641. RBTree<int>& empty_tree(*tree_holder.get());
  642. EXPECT_EQ(RBTree<int>::NOTFOUND,
  643. empty_tree.find(Name("x"), &node, node_path));
  644. EXPECT_EQ(static_cast<void*>(NULL), node);
  645. EXPECT_EQ(static_cast<void*>(NULL),
  646. empty_tree.previousNode(node_path));
  647. node = NULL;
  648. node_path.clear();
  649. }
  650. }
  651. TEST_F(RBTreeTest, nextNodeError) {
  652. // Empty chain for nextNode() is invalid.
  653. RBTreeNodeChain<int> chain;
  654. EXPECT_THROW(rbtree.nextNode(chain), BadValue);
  655. }
  656. // A helper function for getLastComparedNode() below.
  657. void
  658. comparisonChecks(const RBTreeNodeChain<int>& chain,
  659. int expected_order, int expected_common_labels,
  660. NameComparisonResult::NameRelation expected_reln)
  661. {
  662. if (expected_order > 0) {
  663. EXPECT_LT(0, chain.getLastComparisonResult().getOrder());
  664. } else if (expected_order < 0) {
  665. EXPECT_GT(0, chain.getLastComparisonResult().getOrder());
  666. } else {
  667. EXPECT_EQ(0, chain.getLastComparisonResult().getOrder());
  668. }
  669. EXPECT_EQ(expected_common_labels,
  670. chain.getLastComparisonResult().getCommonLabels());
  671. EXPECT_EQ(expected_reln,
  672. chain.getLastComparisonResult().getRelation());
  673. }
  674. TEST_F(RBTreeTest, getLastComparedNode) {
  675. RBTree<int>& tree = rbtree_expose_empty_node; // use the "empty OK" mode
  676. RBTreeNodeChain<int> chain;
  677. // initially there should be no 'last compared'.
  678. EXPECT_EQ(static_cast<void*>(NULL), chain.getLastComparedNode());
  679. // A search for an empty tree should result in no 'last compared', too.
  680. TreeHolder tree_holder(mem_sgmt_, RBTree<int>::create(mem_sgmt_));
  681. RBTree<int>& empty_tree(*tree_holder.get());
  682. EXPECT_EQ(RBTree<int>::NOTFOUND,
  683. empty_tree.find(Name("a"), &crbtnode, chain));
  684. EXPECT_EQ(static_cast<void*>(NULL), chain.getLastComparedNode());
  685. chain.clear();
  686. const RBNode<int>* expected_node = NULL;
  687. // Exact match case. The returned node should be last compared.
  688. EXPECT_EQ(RBTree<int>::EXACTMATCH,
  689. tree.find(Name("x.d.e.f"), &expected_node, chain));
  690. EXPECT_EQ(expected_node, chain.getLastComparedNode());
  691. // 1 = # labels of "x" (note: excluding ".")
  692. comparisonChecks(chain, 0, 1, NameComparisonResult::EQUAL);
  693. chain.clear();
  694. // Partial match, search stopped at the matching node, which should be
  695. // the last compared node.
  696. EXPECT_EQ(RBTree<int>::EXACTMATCH,
  697. tree.find(Name("k.g.h"), &expected_node));
  698. EXPECT_EQ(RBTree<int>::PARTIALMATCH,
  699. tree.find(Name("x.k.g.h"), &crbtnode, chain));
  700. EXPECT_EQ(expected_node, chain.getLastComparedNode());
  701. // k.g.h < x.k.g.h, 1 = # labels of "k"
  702. comparisonChecks(chain, 1, 1, NameComparisonResult::SUBDOMAIN);
  703. chain.clear();
  704. // Partial match, search stopped in the subtree below the matching node
  705. // after following a left branch.
  706. EXPECT_EQ(RBTree<int>::EXACTMATCH,
  707. tree.find(Name("x.d.e.f"), &expected_node));
  708. EXPECT_EQ(RBTree<int>::PARTIALMATCH,
  709. tree.find(Name("a.d.e.f"), &crbtnode, chain));
  710. EXPECT_EQ(expected_node, chain.getLastComparedNode());
  711. // a < x, no common labels
  712. comparisonChecks(chain, -1, 0, NameComparisonResult::NONE);
  713. chain.clear();
  714. // Partial match, search stopped in the subtree below the matching node
  715. // after following a right branch.
  716. EXPECT_EQ(RBTree<int>::EXACTMATCH,
  717. tree.find(Name("z.d.e.f"), &expected_node));
  718. EXPECT_EQ(RBTree<int>::PARTIALMATCH,
  719. tree.find(Name("zz.d.e.f"), &crbtnode, chain));
  720. EXPECT_EQ(expected_node, chain.getLastComparedNode());
  721. // zz > z, no common label
  722. comparisonChecks(chain, 1, 0, NameComparisonResult::NONE);
  723. chain.clear();
  724. // Partial match, search stopped at a node for a super domain of the
  725. // search name in the subtree below the matching node.
  726. EXPECT_EQ(RBTree<int>::EXACTMATCH,
  727. tree.find(Name("w.y.d.e.f"), &expected_node));
  728. EXPECT_EQ(RBTree<int>::PARTIALMATCH,
  729. tree.find(Name("y.d.e.f"), &crbtnode, chain));
  730. EXPECT_EQ(expected_node, chain.getLastComparedNode());
  731. // y < w.y, 1 = # labels of "y"
  732. comparisonChecks(chain, -1, 1, NameComparisonResult::SUPERDOMAIN);
  733. chain.clear();
  734. // Partial match, search stopped at a node that share a common ancestor
  735. // with the search name in the subtree below the matching node.
  736. // (the expected node is the same as the previous case)
  737. EXPECT_EQ(RBTree<int>::PARTIALMATCH,
  738. tree.find(Name("z.y.d.e.f"), &crbtnode, chain));
  739. EXPECT_EQ(expected_node, chain.getLastComparedNode());
  740. // z.y > w.y, 1 = # labels of "y"
  741. comparisonChecks(chain, 1, 1, NameComparisonResult::COMMONANCESTOR);
  742. chain.clear();
  743. // Search stops in the highest level (under ".") after following a left
  744. // branch. (find() still returns PARTIALMATCH due to the top level ".")
  745. EXPECT_EQ(RBTree<int>::EXACTMATCH, tree.find(Name("c"), &expected_node));
  746. EXPECT_EQ(RBTree<int>::PARTIALMATCH,
  747. tree.find(Name("bb"), &crbtnode, chain));
  748. EXPECT_EQ(expected_node, chain.getLastComparedNode());
  749. // bb < c, no common label
  750. comparisonChecks(chain, -1, 0, NameComparisonResult::NONE);
  751. chain.clear();
  752. // Search stops in the highest level (under ".") after following a right
  753. // branch. (the expected node is the same as the previous case)
  754. EXPECT_EQ(RBTree<int>::PARTIALMATCH,
  755. tree.find(Name("d"), &crbtnode, chain));
  756. EXPECT_EQ(expected_node, chain.getLastComparedNode());
  757. // d > c, no common label
  758. comparisonChecks(chain, 1, 0, NameComparisonResult::NONE);
  759. chain.clear();
  760. }
  761. TEST_F(RBTreeTest, dumpTree) {
  762. std::ostringstream str;
  763. std::ostringstream str2;
  764. rbtree.dumpTree(str);
  765. str2 << "tree has 15 node(s)\n"
  766. ". (black) [invisible] [subtreeroot]\n"
  767. " begin down from .\n"
  768. " b (black) [subtreeroot]\n"
  769. " a (black)\n"
  770. " NULL\n"
  771. " NULL\n"
  772. " d.e.f (black) [invisible]\n"
  773. " begin down from d.e.f\n"
  774. " w.y (black) [invisible] [subtreeroot]\n"
  775. " begin down from w.y\n"
  776. " p (black) [subtreeroot]\n"
  777. " o (red)\n"
  778. " NULL\n"
  779. " NULL\n"
  780. " q (red)\n"
  781. " NULL\n"
  782. " NULL\n"
  783. " end down from w.y\n"
  784. " x (red)\n"
  785. " NULL\n"
  786. " NULL\n"
  787. " z (red)\n"
  788. " begin down from z\n"
  789. " j (black) [subtreeroot]\n"
  790. " NULL\n"
  791. " NULL\n"
  792. " end down from z\n"
  793. " NULL\n"
  794. " NULL\n"
  795. " end down from d.e.f\n"
  796. " c (red)\n"
  797. " NULL\n"
  798. " NULL\n"
  799. " g.h (red)\n"
  800. " begin down from g.h\n"
  801. " i (black) [subtreeroot]\n"
  802. " NULL\n"
  803. " k (red)\n"
  804. " NULL\n"
  805. " NULL\n"
  806. " end down from g.h\n"
  807. " NULL\n"
  808. " NULL\n"
  809. " end down from .\n"
  810. " NULL\n"
  811. " NULL\n";
  812. EXPECT_EQ(str2.str(), str.str());
  813. }
  814. TEST_F(RBTreeTest, swap) {
  815. // Store info about the first tree
  816. std::ostringstream str1;
  817. rbtree.dumpTree(str1);
  818. size_t count1(rbtree.getNodeCount());
  819. // Create second one and store state
  820. TreeHolder tree_holder(mem_sgmt_, RBTree<int>::create(mem_sgmt_));
  821. RBTree<int>& tree2(*tree_holder.get());
  822. RBNode<int>* node;
  823. tree2.insert(mem_sgmt_, Name("second"), &node);
  824. std::ostringstream str2;
  825. tree2.dumpTree(str2);
  826. // Swap them
  827. ASSERT_NO_THROW(tree2.swap(rbtree));
  828. // Check their sizes
  829. ASSERT_EQ(1, rbtree.getNodeCount());
  830. ASSERT_EQ(count1, tree2.getNodeCount());
  831. // And content
  832. std::ostringstream out;
  833. rbtree.dumpTree(out);
  834. ASSERT_EQ(str2.str(), out.str());
  835. out.str("");
  836. tree2.dumpTree(out);
  837. ASSERT_EQ(str1.str(), out.str());
  838. }
  839. // Matching in the "root zone" may be special (e.g. there's no parent,
  840. // any domain names should be considered a subdomain of it), so it makes
  841. // sense to test cases with the root zone explicitly.
  842. TEST_F(RBTreeTest, root) {
  843. TreeHolder tree_holder(mem_sgmt_, RBTree<int>::create(mem_sgmt_));
  844. RBTree<int>& root(*tree_holder.get());
  845. root.insert(mem_sgmt_, Name::ROOT_NAME(), &rbtnode);
  846. rbtnode->setData(RBNode<int>::NodeDataPtr(new int(1)));
  847. EXPECT_EQ(RBTree<int>::EXACTMATCH,
  848. root.find(Name::ROOT_NAME(), &crbtnode));
  849. EXPECT_EQ(rbtnode, crbtnode);
  850. EXPECT_EQ(RBTree<int>::PARTIALMATCH,
  851. root.find(Name("example.com"), &crbtnode));
  852. EXPECT_EQ(rbtnode, crbtnode);
  853. // Insert a new name that better matches the query name. find() should
  854. // find the better one.
  855. root.insert(mem_sgmt_, Name("com"), &rbtnode);
  856. rbtnode->setData(RBNode<int>::NodeDataPtr(new int(2)));
  857. EXPECT_EQ(RBTree<int>::PARTIALMATCH,
  858. root.find(Name("example.com"), &crbtnode));
  859. EXPECT_EQ(rbtnode, crbtnode);
  860. // Perform the same tests for the tree that allows matching against empty
  861. // nodes.
  862. TreeHolder tree_holder_emptyok(mem_sgmt_,
  863. RBTree<int>::create(mem_sgmt_, true));
  864. RBTree<int>& root_emptyok(*tree_holder_emptyok.get());
  865. root_emptyok.insert(mem_sgmt_, Name::ROOT_NAME(), &rbtnode);
  866. EXPECT_EQ(RBTree<int>::EXACTMATCH,
  867. root_emptyok.find(Name::ROOT_NAME(), &crbtnode));
  868. EXPECT_EQ(rbtnode, crbtnode);
  869. EXPECT_EQ(RBTree<int>::PARTIALMATCH,
  870. root_emptyok.find(Name("example.com"), &crbtnode));
  871. EXPECT_EQ(rbtnode, crbtnode);
  872. root.insert(mem_sgmt_, Name("com"), &rbtnode);
  873. EXPECT_EQ(RBTree<int>::PARTIALMATCH,
  874. root.find(Name("example.com"), &crbtnode));
  875. EXPECT_EQ(rbtnode, crbtnode);
  876. }
  877. }