memory_datasrc_unittest.cc 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643
  1. // Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
  2. // Copyright (C) 2011 CZ NIC
  3. //
  4. // Permission to use, copy, modify, and/or distribute this software for any
  5. // purpose with or without fee is hereby granted, provided that the above
  6. // copyright notice and this permission notice appear in all copies.
  7. //
  8. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  9. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  10. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  11. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  12. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  13. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  14. // PERFORMANCE OF THIS SOFTWARE.
  15. #include <exceptions/exceptions.h>
  16. #include <dns/name.h>
  17. #include <dns/rdata.h>
  18. #include <dns/rdataclass.h>
  19. #include <dns/rrclass.h>
  20. #include <dns/rrsetlist.h>
  21. #include <dns/rrttl.h>
  22. #include <dns/masterload.h>
  23. #include <datasrc/memory_datasrc.h>
  24. #include <gtest/gtest.h>
  25. using namespace isc::dns;
  26. using namespace isc::dns::rdata;
  27. using namespace isc::datasrc;
  28. namespace {
  29. // Commonly used result codes (Who should write the prefix all the time)
  30. using result::SUCCESS;
  31. using result::EXIST;
  32. class MemoryDataSrcTest : public ::testing::Test {
  33. protected:
  34. MemoryDataSrcTest() : rrclass(RRClass::IN())
  35. {}
  36. RRClass rrclass;
  37. MemoryDataSrc memory_datasrc;
  38. };
  39. TEST_F(MemoryDataSrcTest, add_find_Zone) {
  40. // test add zone
  41. // Bogus zone (NULL)
  42. EXPECT_THROW(memory_datasrc.addZone(ZonePtr()), isc::InvalidParameter);
  43. // add zones with different names one by one
  44. EXPECT_EQ(result::SUCCESS, memory_datasrc.addZone(
  45. ZonePtr(new MemoryZone(RRClass::IN(), Name("a")))));
  46. EXPECT_EQ(result::SUCCESS, memory_datasrc.addZone(
  47. ZonePtr(new MemoryZone(RRClass::CH(), Name("b")))));
  48. EXPECT_EQ(result::SUCCESS, memory_datasrc.addZone(
  49. ZonePtr(new MemoryZone(RRClass::IN(), Name("c")))));
  50. // add zones with the same name suffix
  51. EXPECT_EQ(result::SUCCESS, memory_datasrc.addZone(
  52. ZonePtr(new MemoryZone(RRClass::CH(),
  53. Name("x.d.e.f")))));
  54. EXPECT_EQ(result::SUCCESS, memory_datasrc.addZone(
  55. ZonePtr(new MemoryZone(RRClass::CH(),
  56. Name("o.w.y.d.e.f")))));
  57. EXPECT_EQ(result::SUCCESS, memory_datasrc.addZone(
  58. ZonePtr(new MemoryZone(RRClass::CH(),
  59. Name("p.w.y.d.e.f")))));
  60. EXPECT_EQ(result::SUCCESS, memory_datasrc.addZone(
  61. ZonePtr(new MemoryZone(RRClass::IN(),
  62. Name("q.w.y.d.e.f")))));
  63. // add super zone and its subzone
  64. EXPECT_EQ(result::SUCCESS, memory_datasrc.addZone(
  65. ZonePtr(new MemoryZone(RRClass::CH(), Name("g.h")))));
  66. EXPECT_EQ(result::SUCCESS, memory_datasrc.addZone(
  67. ZonePtr(new MemoryZone(RRClass::IN(), Name("i.g.h")))));
  68. EXPECT_EQ(result::SUCCESS, memory_datasrc.addZone(
  69. ZonePtr(new MemoryZone(RRClass::IN(),
  70. Name("z.d.e.f")))));
  71. EXPECT_EQ(result::SUCCESS, memory_datasrc.addZone(
  72. ZonePtr(new MemoryZone(RRClass::IN(),
  73. Name("j.z.d.e.f")))));
  74. // different zone class isn't allowed.
  75. EXPECT_EQ(result::EXIST, memory_datasrc.addZone(
  76. ZonePtr(new MemoryZone(RRClass::CH(),
  77. Name("q.w.y.d.e.f")))));
  78. // names are compared in a case insensitive manner.
  79. EXPECT_EQ(result::EXIST, memory_datasrc.addZone(
  80. ZonePtr(new MemoryZone(RRClass::IN(),
  81. Name("Q.W.Y.d.E.f")))));
  82. // test find zone
  83. EXPECT_EQ(result::SUCCESS, memory_datasrc.findZone(Name("a")).code);
  84. EXPECT_EQ(Name("a"),
  85. memory_datasrc.findZone(Name("a")).zone->getOrigin());
  86. EXPECT_EQ(result::SUCCESS,
  87. memory_datasrc.findZone(Name("j.z.d.e.f")).code);
  88. EXPECT_EQ(Name("j.z.d.e.f"),
  89. memory_datasrc.findZone(Name("j.z.d.e.f")).zone->getOrigin());
  90. // NOTFOUND
  91. EXPECT_EQ(result::NOTFOUND, memory_datasrc.findZone(Name("d.e.f")).code);
  92. EXPECT_EQ(ConstZonePtr(), memory_datasrc.findZone(Name("d.e.f")).zone);
  93. EXPECT_EQ(result::NOTFOUND,
  94. memory_datasrc.findZone(Name("w.y.d.e.f")).code);
  95. EXPECT_EQ(ConstZonePtr(),
  96. memory_datasrc.findZone(Name("w.y.d.e.f")).zone);
  97. // there's no exact match. the result should be the longest match,
  98. // and the code should be PARTIALMATCH.
  99. EXPECT_EQ(result::PARTIALMATCH,
  100. memory_datasrc.findZone(Name("j.g.h")).code);
  101. EXPECT_EQ(Name("g.h"),
  102. memory_datasrc.findZone(Name("g.h")).zone->getOrigin());
  103. EXPECT_EQ(result::PARTIALMATCH,
  104. memory_datasrc.findZone(Name("z.i.g.h")).code);
  105. EXPECT_EQ(Name("i.g.h"),
  106. memory_datasrc.findZone(Name("z.i.g.h")).zone->getOrigin());
  107. }
  108. TEST_F(MemoryDataSrcTest, getZoneCount) {
  109. EXPECT_EQ(0, memory_datasrc.getZoneCount());
  110. memory_datasrc.addZone(
  111. ZonePtr(new MemoryZone(rrclass, Name("example.com"))));
  112. EXPECT_EQ(1, memory_datasrc.getZoneCount());
  113. // duplicate add. counter shouldn't change
  114. memory_datasrc.addZone(
  115. ZonePtr(new MemoryZone(rrclass, Name("example.com"))));
  116. EXPECT_EQ(1, memory_datasrc.getZoneCount());
  117. // add one more
  118. memory_datasrc.addZone(
  119. ZonePtr(new MemoryZone(rrclass, Name("example.org"))));
  120. EXPECT_EQ(2, memory_datasrc.getZoneCount());
  121. }
  122. /// \brief Test fixture for the MemoryZone class
  123. class MemoryZoneTest : public ::testing::Test {
  124. public:
  125. MemoryZoneTest() :
  126. class_(RRClass::IN()),
  127. origin_("example.org"),
  128. ns_name_("ns.example.org"),
  129. cname_name_("cname.example.org"),
  130. dname_name_("dname.example.org"),
  131. child_ns_name_("child.example.org"),
  132. child_glue_name_("ns.child.example.org"),
  133. grandchild_ns_name_("grand.child.example.org"),
  134. grandchild_glue_name_("ns.grand.child.example.org"),
  135. child_dname_name_("dname.child.example.org"),
  136. zone_(class_, origin_),
  137. rr_out_(new RRset(Name("example.com"), class_, RRType::A(),
  138. RRTTL(300))),
  139. rr_ns_(new RRset(origin_, class_, RRType::NS(), RRTTL(300))),
  140. rr_ns_a_(new RRset(ns_name_, class_, RRType::A(), RRTTL(300))),
  141. rr_ns_aaaa_(new RRset(ns_name_, class_, RRType::AAAA(), RRTTL(300))),
  142. rr_a_(new RRset(origin_, class_, RRType::A(), RRTTL(300))),
  143. rr_cname_(new RRset(cname_name_, class_, RRType::CNAME(), RRTTL(300))),
  144. rr_cname_a_(new RRset(cname_name_, class_, RRType::A(), RRTTL(300))),
  145. rr_dname_(new RRset(dname_name_, class_, RRType::DNAME(), RRTTL(300))),
  146. rr_dname_a_(new RRset(dname_name_, class_, RRType::A(),
  147. RRTTL(300))),
  148. rr_dname_ns_(new RRset(dname_name_, class_, RRType::NS(), RRTTL(300))),
  149. rr_dname_apex_(new RRset(origin_, class_, RRType::DNAME(),
  150. RRTTL(300))),
  151. rr_child_ns_(new RRset(child_ns_name_, class_, RRType::NS(),
  152. RRTTL(300))),
  153. rr_child_glue_(new RRset(child_glue_name_, class_, RRType::A(),
  154. RRTTL(300))),
  155. rr_grandchild_ns_(new RRset(grandchild_ns_name_, class_, RRType::NS(),
  156. RRTTL(300))),
  157. rr_grandchild_glue_(new RRset(grandchild_glue_name_, class_,
  158. RRType::AAAA(), RRTTL(300))),
  159. rr_child_dname_(new RRset(child_dname_name_, class_, RRType::DNAME(),
  160. RRTTL(300)))
  161. {
  162. }
  163. // Some data to test with
  164. const RRClass class_;
  165. const Name origin_, ns_name_, cname_name_, dname_name_, child_ns_name_,
  166. child_glue_name_, grandchild_ns_name_, grandchild_glue_name_,
  167. child_dname_name_;
  168. // The zone to torture by tests
  169. MemoryZone zone_;
  170. /*
  171. * Some RRsets to put inside the zone.
  172. * They are empty, but the MemoryZone does not have a reason to look
  173. * inside anyway. We will check it finds them and does not change
  174. * the pointer.
  175. */
  176. ConstRRsetPtr
  177. // Out of zone RRset
  178. rr_out_,
  179. // NS of example.org
  180. rr_ns_,
  181. // A of ns.example.org
  182. rr_ns_a_,
  183. // AAAA of ns.example.org
  184. rr_ns_aaaa_,
  185. // A of example.org
  186. rr_a_;
  187. RRsetPtr rr_cname_; // CNAME in example.org (RDATA will be added)
  188. ConstRRsetPtr rr_cname_a_; // for mixed CNAME + A case
  189. RRsetPtr rr_dname_; // DNAME in example.org (RDATA will be added)
  190. ConstRRsetPtr rr_dname_a_; // for mixed DNAME + A case
  191. ConstRRsetPtr rr_dname_ns_; // for mixed DNAME + NS case
  192. ConstRRsetPtr rr_dname_apex_; // for mixed DNAME + NS case in the apex
  193. ConstRRsetPtr rr_child_ns_; // NS of a child domain (for delegation)
  194. ConstRRsetPtr rr_child_glue_; // glue RR of the child domain
  195. ConstRRsetPtr rr_grandchild_ns_; // NS below a zone cut (unusual)
  196. ConstRRsetPtr rr_grandchild_glue_; // glue RR below a deeper zone cut
  197. ConstRRsetPtr rr_child_dname_; // A DNAME under NS
  198. /**
  199. * \brief Test one find query to the zone.
  200. *
  201. * Asks a query to the zone and checks it does not throw and returns
  202. * expected results. It returns nothing, it just signals failures
  203. * to GTEST.
  204. *
  205. * \param name The name to ask for.
  206. * \param rrtype The RRType to ask of.
  207. * \param result The expected code of the result.
  208. * \param check_answer Should a check against equality of the answer be
  209. * done?
  210. * \param answer The expected rrset, if any should be returned.
  211. * \param zone Check different MemoryZone object than zone_ (if NULL,
  212. * uses zone_)
  213. */
  214. void findTest(const Name& name, const RRType& rrtype, Zone::Result result,
  215. bool check_answer = true,
  216. const ConstRRsetPtr& answer = ConstRRsetPtr(),
  217. RRsetList* target = NULL,
  218. MemoryZone* zone = NULL,
  219. Zone::FindOptions options = Zone::FIND_DEFAULT)
  220. {
  221. if (!zone) {
  222. zone = &zone_;
  223. }
  224. // The whole block is inside, because we need to check the result and
  225. // we can't assign to FindResult
  226. EXPECT_NO_THROW({
  227. Zone::FindResult find_result(zone->find(name, rrtype, target,
  228. options));
  229. // Check it returns correct answers
  230. EXPECT_EQ(result, find_result.code);
  231. if (check_answer) {
  232. EXPECT_EQ(answer, find_result.rrset);
  233. }
  234. });
  235. }
  236. };
  237. /**
  238. * \brief Test MemoryZone::MemoryZone constructor.
  239. *
  240. * Takes the created zone and checks its properties they are the same
  241. * as passed parameters.
  242. */
  243. TEST_F(MemoryZoneTest, constructor) {
  244. ASSERT_EQ(class_, zone_.getClass());
  245. ASSERT_EQ(origin_, zone_.getOrigin());
  246. }
  247. /**
  248. * \brief Test adding.
  249. *
  250. * We test that it throws at the correct moments and the correct exceptions.
  251. * And we test the return value.
  252. */
  253. TEST_F(MemoryZoneTest, add) {
  254. // This one does not belong to this zone
  255. EXPECT_THROW(zone_.add(rr_out_), MemoryZone::OutOfZone);
  256. // Test null pointer
  257. EXPECT_THROW(zone_.add(ConstRRsetPtr()), MemoryZone::NullRRset);
  258. // Now put all the data we have there. It should throw nothing
  259. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_.add(rr_ns_)));
  260. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_.add(rr_ns_a_)));
  261. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_.add(rr_ns_aaaa_)));
  262. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_.add(rr_a_)));
  263. // Try putting there something twice, it should be rejected
  264. EXPECT_NO_THROW(EXPECT_EQ(EXIST, zone_.add(rr_ns_)));
  265. EXPECT_NO_THROW(EXPECT_EQ(EXIST, zone_.add(rr_ns_a_)));
  266. }
  267. TEST_F(MemoryZoneTest, addMultipleCNAMEs) {
  268. rr_cname_->addRdata(generic::CNAME("canonical1.example.org."));
  269. rr_cname_->addRdata(generic::CNAME("canonical2.example.org."));
  270. EXPECT_THROW(zone_.add(rr_cname_), MemoryZone::AddError);
  271. }
  272. TEST_F(MemoryZoneTest, addCNAMEThenOther) {
  273. rr_cname_->addRdata(generic::CNAME("canonical.example.org."));
  274. EXPECT_EQ(SUCCESS, zone_.add(rr_cname_));
  275. EXPECT_THROW(zone_.add(rr_cname_a_), MemoryZone::AddError);
  276. }
  277. TEST_F(MemoryZoneTest, addOtherThenCNAME) {
  278. rr_cname_->addRdata(generic::CNAME("canonical.example.org."));
  279. EXPECT_EQ(SUCCESS, zone_.add(rr_cname_a_));
  280. EXPECT_THROW(zone_.add(rr_cname_), MemoryZone::AddError);
  281. }
  282. TEST_F(MemoryZoneTest, findCNAME) {
  283. // install CNAME RR
  284. rr_cname_->addRdata(generic::CNAME("canonical.example.org."));
  285. EXPECT_EQ(SUCCESS, zone_.add(rr_cname_));
  286. // Find A RR of the same. Should match the CNAME
  287. findTest(cname_name_, RRType::NS(), Zone::CNAME, true, rr_cname_);
  288. // Find the CNAME itself. Should result in normal SUCCESS
  289. findTest(cname_name_, RRType::CNAME(), Zone::SUCCESS, true, rr_cname_);
  290. }
  291. TEST_F(MemoryZoneTest, findCNAMEUnderZoneCut) {
  292. // There's nothing special when we find a CNAME under a zone cut
  293. // (with FIND_GLUE_OK). The behavior is different from BIND 9,
  294. // so we test this case explicitly.
  295. EXPECT_EQ(SUCCESS, zone_.add(rr_child_ns_));
  296. RRsetPtr rr_cname_under_cut_(new RRset(Name("cname.child.example.org"),
  297. class_, RRType::CNAME(),
  298. RRTTL(300)));
  299. EXPECT_EQ(SUCCESS, zone_.add(rr_cname_under_cut_));
  300. findTest(Name("cname.child.example.org"), RRType::AAAA(),
  301. Zone::CNAME, true, rr_cname_under_cut_, NULL, NULL,
  302. Zone::FIND_GLUE_OK);
  303. }
  304. // Two DNAMEs at single domain are disallowed by RFC 2672, section 3)
  305. // Having a CNAME there is disallowed too, but it is tested by
  306. // addOtherThenCNAME and addCNAMEThenOther.
  307. TEST_F(MemoryZoneTest, addMultipleDNAMEs) {
  308. rr_dname_->addRdata(generic::DNAME("dname1.example.org."));
  309. rr_dname_->addRdata(generic::DNAME("dname2.example.org."));
  310. EXPECT_THROW(zone_.add(rr_dname_), MemoryZone::AddError);
  311. }
  312. /*
  313. * These two tests ensure that we can't have DNAME and NS at the same
  314. * node with the exception of the apex of zone (forbidden by RFC 2672)
  315. */
  316. TEST_F(MemoryZoneTest, addDNAMEThenNS) {
  317. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_.add(rr_dname_)));
  318. EXPECT_THROW(zone_.add(rr_dname_ns_), MemoryZone::AddError);
  319. }
  320. TEST_F(MemoryZoneTest, addNSThenDNAME) {
  321. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_.add(rr_dname_ns_)));
  322. EXPECT_THROW(zone_.add(rr_dname_), MemoryZone::AddError);
  323. }
  324. // It is allowed to have NS and DNAME at apex
  325. TEST_F(MemoryZoneTest, DNAMEAndNSAtApex) {
  326. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_.add(rr_dname_apex_)));
  327. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_.add(rr_ns_)));
  328. // The NS should be possible to be found, below should be DNAME, not
  329. // delegation
  330. findTest(origin_, RRType::NS(), Zone::SUCCESS, true, rr_ns_);
  331. findTest(child_ns_name_, RRType::A(), Zone::DNAME, true, rr_dname_apex_);
  332. }
  333. TEST_F(MemoryZoneTest, NSAndDNAMEAtApex) {
  334. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_.add(rr_ns_)));
  335. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_.add(rr_dname_apex_)));
  336. }
  337. // TODO: Test (and implement) adding data under DNAME. That is forbidden by
  338. // 2672 as well.
  339. // Search under a DNAME record. It should return the DNAME
  340. TEST_F(MemoryZoneTest, findBelowDNAME) {
  341. rr_dname_->addRdata(generic::DNAME("target.example.org."));
  342. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_.add(rr_dname_)));
  343. findTest(Name("below.dname.example.org"), RRType::A(), Zone::DNAME, true,
  344. rr_dname_);
  345. }
  346. // Search at the domain with DNAME. It should act as DNAME isn't there, DNAME
  347. // influences only the data below (see RFC 2672, section 3)
  348. TEST_F(MemoryZoneTest, findAtDNAME) {
  349. rr_dname_->addRdata(generic::DNAME("target.example.org."));
  350. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_.add(rr_dname_)));
  351. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_.add(rr_dname_a_)));
  352. findTest(dname_name_, RRType::A(), Zone::SUCCESS, true, rr_dname_a_);
  353. findTest(dname_name_, RRType::DNAME(), Zone::SUCCESS, true, rr_dname_);
  354. findTest(dname_name_, RRType::TXT(), Zone::NXRRSET, true);
  355. }
  356. // Try searching something that is both under NS and DNAME, without and with
  357. // GLUE_OK mode (it should stop at the NS and DNAME respectively).
  358. TEST_F(MemoryZoneTest, DNAMEUnderNS) {
  359. zone_.add(rr_child_ns_);
  360. zone_.add(rr_child_dname_);
  361. Name lowName("below.dname.child.example.org.");
  362. findTest(lowName, RRType::A(), Zone::DELEGATION, true, rr_child_ns_);
  363. findTest(lowName, RRType::A(), Zone::DNAME, true, rr_child_dname_, NULL,
  364. NULL, Zone::FIND_GLUE_OK);
  365. }
  366. // Test adding child zones and zone cut handling
  367. TEST_F(MemoryZoneTest, delegationNS) {
  368. // add in-zone data
  369. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_.add(rr_ns_)));
  370. // install a zone cut
  371. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_.add(rr_child_ns_)));
  372. // below the zone cut
  373. findTest(Name("www.child.example.org"), RRType::A(), Zone::DELEGATION,
  374. true, rr_child_ns_);
  375. // at the zone cut
  376. findTest(Name("child.example.org"), RRType::A(), Zone::DELEGATION,
  377. true, rr_child_ns_);
  378. findTest(Name("child.example.org"), RRType::NS(), Zone::DELEGATION,
  379. true, rr_child_ns_);
  380. // finding NS for the apex (origin) node. This must not be confused
  381. // with delegation due to the existence of an NS RR.
  382. findTest(origin_, RRType::NS(), Zone::SUCCESS, true, rr_ns_);
  383. // unusual case of "nested delegation": the highest cut should be used.
  384. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_.add(rr_grandchild_ns_)));
  385. findTest(Name("www.grand.child.example.org"), RRType::A(),
  386. Zone::DELEGATION, true, rr_child_ns_); // note: !rr_grandchild_ns_
  387. }
  388. TEST_F(MemoryZoneTest, findAny) {
  389. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_.add(rr_a_)));
  390. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_.add(rr_ns_)));
  391. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_.add(rr_child_glue_)));
  392. // origin
  393. RRsetList origin_rrsets;
  394. findTest(origin_, RRType::ANY(), Zone::SUCCESS, true,
  395. ConstRRsetPtr(), &origin_rrsets);
  396. EXPECT_EQ(2, origin_rrsets.size());
  397. EXPECT_EQ(rr_a_, origin_rrsets.findRRset(RRType::A(), RRClass::IN()));
  398. EXPECT_EQ(rr_ns_, origin_rrsets.findRRset(RRType::NS(), RRClass::IN()));
  399. // out zone name
  400. RRsetList out_rrsets;
  401. findTest(Name("example.com"), RRType::ANY(), Zone::NXDOMAIN, true,
  402. ConstRRsetPtr(), &out_rrsets);
  403. EXPECT_EQ(0, out_rrsets.size());
  404. RRsetList glue_child_rrsets;
  405. findTest(child_glue_name_, RRType::ANY(), Zone::SUCCESS, true,
  406. ConstRRsetPtr(), &glue_child_rrsets);
  407. EXPECT_EQ(rr_child_glue_, glue_child_rrsets.findRRset(RRType::A(),
  408. RRClass::IN()));
  409. EXPECT_EQ(1, glue_child_rrsets.size());
  410. // TODO: test NXRRSET case after rbtree non-terminal logic has
  411. // been implemented
  412. // add zone cut
  413. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_.add(rr_child_ns_)));
  414. // zone cut
  415. RRsetList child_rrsets;
  416. findTest(child_ns_name_, RRType::ANY(), Zone::DELEGATION, true,
  417. rr_child_ns_, &child_rrsets);
  418. EXPECT_EQ(0, child_rrsets.size());
  419. // glue for this zone cut
  420. RRsetList new_glue_child_rrsets;
  421. findTest(child_glue_name_, RRType::ANY(), Zone::DELEGATION, true,
  422. rr_child_ns_, &new_glue_child_rrsets);
  423. EXPECT_EQ(0, new_glue_child_rrsets.size());
  424. }
  425. TEST_F(MemoryZoneTest, glue) {
  426. // install zone data:
  427. // a zone cut
  428. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_.add(rr_child_ns_)));
  429. // glue for this cut
  430. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_.add(rr_child_glue_)));
  431. // a nested zone cut (unusual)
  432. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_.add(rr_grandchild_ns_)));
  433. // glue under the deeper zone cut
  434. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_.add(rr_grandchild_glue_)));
  435. // by default glue is hidden due to the zone cut
  436. findTest(child_glue_name_, RRType::A(), Zone::DELEGATION, true,
  437. rr_child_ns_);
  438. // If we do it in the "glue OK" mode, we should find the exact match.
  439. findTest(child_glue_name_, RRType::A(), Zone::SUCCESS, true,
  440. rr_child_glue_, NULL, NULL, Zone::FIND_GLUE_OK);
  441. // glue OK + NXRRSET case
  442. findTest(child_glue_name_, RRType::AAAA(), Zone::NXRRSET, true,
  443. ConstRRsetPtr(), NULL, NULL, Zone::FIND_GLUE_OK);
  444. // glue OK + NXDOMAIN case
  445. findTest(Name("www.child.example.org"), RRType::A(), Zone::DELEGATION,
  446. true, rr_child_ns_, NULL, NULL, Zone::FIND_GLUE_OK);
  447. // TODO:
  448. // glue name would match a wildcard under a zone cut: wildcard match
  449. // shouldn't happen under a cut and result must be PARTIALMATCH
  450. // (This case cannot be tested yet)
  451. // nested cut case. The glue should be found.
  452. findTest(grandchild_glue_name_, RRType::AAAA(), Zone::SUCCESS,
  453. true, rr_grandchild_glue_, NULL, NULL, Zone::FIND_GLUE_OK);
  454. // A non-existent name in nested cut. This should result in delegation
  455. // at the highest zone cut.
  456. findTest(Name("www.grand.child.example.org"), RRType::TXT(),
  457. Zone::DELEGATION, true, rr_child_ns_, NULL, NULL,
  458. Zone::FIND_GLUE_OK);
  459. }
  460. /**
  461. * \brief Test searching.
  462. *
  463. * Check it finds or does not find correctly and does not throw exceptions.
  464. * \todo This doesn't do any kind of CNAME and so on. If it isn't
  465. * directly there, it just tells it doesn't exist.
  466. */
  467. TEST_F(MemoryZoneTest, find) {
  468. // Fill some data inside
  469. // Now put all the data we have there. It should throw nothing
  470. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_.add(rr_ns_)));
  471. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_.add(rr_ns_a_)));
  472. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_.add(rr_ns_aaaa_)));
  473. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_.add(rr_a_)));
  474. // These two should be successful
  475. findTest(origin_, RRType::NS(), Zone::SUCCESS, true, rr_ns_);
  476. findTest(ns_name_, RRType::A(), Zone::SUCCESS, true, rr_ns_a_);
  477. // These domain exist but don't have the provided RRType
  478. findTest(origin_, RRType::AAAA(), Zone::NXRRSET);
  479. findTest(ns_name_, RRType::NS(), Zone::NXRRSET);
  480. // These domains don't exist (and one is out of the zone)
  481. findTest(Name("nothere.example.org"), RRType::A(), Zone::NXDOMAIN);
  482. findTest(Name("example.net"), RRType::A(), Zone::NXDOMAIN);
  483. }
  484. TEST_F(MemoryZoneTest, load) {
  485. // Put some data inside the zone
  486. EXPECT_NO_THROW(EXPECT_EQ(result::SUCCESS, zone_.add(rr_ns_)));
  487. // Loading with different origin should fail
  488. EXPECT_THROW(zone_.load(TEST_DATA_DIR "/root.zone"), MasterLoadError);
  489. // See the original data is still there, survived the exception
  490. findTest(origin_, RRType::NS(), Zone::SUCCESS, true, rr_ns_);
  491. // Create correct zone
  492. MemoryZone rootzone(class_, Name("."));
  493. // Try putting something inside
  494. EXPECT_NO_THROW(EXPECT_EQ(result::SUCCESS, rootzone.add(rr_ns_aaaa_)));
  495. // Load the zone. It should overwrite/remove the above RRset
  496. EXPECT_NO_THROW(rootzone.load(TEST_DATA_DIR "/root.zone"));
  497. // Now see there are some rrsets (we don't look inside, though)
  498. findTest(Name("."), RRType::SOA(), Zone::SUCCESS, false, ConstRRsetPtr(),
  499. NULL, &rootzone);
  500. findTest(Name("."), RRType::NS(), Zone::SUCCESS, false, ConstRRsetPtr(),
  501. NULL, &rootzone);
  502. findTest(Name("a.root-servers.net."), RRType::A(), Zone::SUCCESS, false,
  503. ConstRRsetPtr(), NULL, &rootzone);
  504. // But this should no longer be here
  505. findTest(ns_name_, RRType::AAAA(), Zone::NXDOMAIN, true, ConstRRsetPtr(),
  506. NULL, &rootzone);
  507. // Try loading zone that is wrong in a different way
  508. EXPECT_THROW(zone_.load(TEST_DATA_DIR "/duplicate_rrset.zone"),
  509. MasterLoadError);
  510. }
  511. TEST_F(MemoryZoneTest, swap) {
  512. // build one zone with some data
  513. MemoryZone zone1(class_, origin_);
  514. EXPECT_EQ(result::SUCCESS, zone1.add(rr_ns_));
  515. EXPECT_EQ(result::SUCCESS, zone1.add(rr_ns_aaaa_));
  516. // build another zone of a different RR class with some other data
  517. const Name other_origin("version.bind");
  518. ASSERT_NE(origin_, other_origin); // make sure these two are different
  519. MemoryZone zone2(RRClass::CH(), other_origin);
  520. EXPECT_EQ(result::SUCCESS,
  521. zone2.add(RRsetPtr(new RRset(Name("version.bind"),
  522. RRClass::CH(), RRType::TXT(),
  523. RRTTL(0)))));
  524. zone1.swap(zone2);
  525. EXPECT_EQ(other_origin, zone1.getOrigin());
  526. EXPECT_EQ(origin_, zone2.getOrigin());
  527. EXPECT_EQ(RRClass::CH(), zone1.getClass());
  528. EXPECT_EQ(RRClass::IN(), zone2.getClass());
  529. // make sure the zone data is swapped, too
  530. findTest(origin_, RRType::NS(), Zone::NXDOMAIN, false, ConstRRsetPtr(),
  531. NULL, &zone1);
  532. findTest(other_origin, RRType::TXT(), Zone::SUCCESS, false,
  533. ConstRRsetPtr(), NULL, &zone1);
  534. findTest(origin_, RRType::NS(), Zone::SUCCESS, false, ConstRRsetPtr(),
  535. NULL, &zone2);
  536. findTest(other_origin, RRType::TXT(), Zone::NXDOMAIN, false,
  537. ConstRRsetPtr(), NULL, &zone2);
  538. }
  539. TEST_F(MemoryZoneTest, getFileName) {
  540. // for an empty zone the file name should also be empty.
  541. EXPECT_TRUE(zone_.getFileName().empty());
  542. // if loading a zone fails the file name shouldn't be set.
  543. EXPECT_THROW(zone_.load(TEST_DATA_DIR "/root.zone"), MasterLoadError);
  544. EXPECT_TRUE(zone_.getFileName().empty());
  545. // after a successful load, the specified file name should be set
  546. MemoryZone rootzone(class_, Name("."));
  547. EXPECT_NO_THROW(rootzone.load(TEST_DATA_DIR "/root.zone"));
  548. EXPECT_EQ(TEST_DATA_DIR "/root.zone", rootzone.getFileName());
  549. // overriding load, which will fail
  550. EXPECT_THROW(rootzone.load(TEST_DATA_DIR "/duplicate_rrset.zone"),
  551. MasterLoadError);
  552. // the file name should be intact.
  553. EXPECT_EQ(TEST_DATA_DIR "/root.zone", rootzone.getFileName());
  554. // After swap, file names should also be swapped.
  555. zone_.swap(rootzone);
  556. EXPECT_EQ(TEST_DATA_DIR "/root.zone", zone_.getFileName());
  557. EXPECT_TRUE(rootzone.getFileName().empty());
  558. }
  559. }