memory_datasrc_unittest.cc 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062
  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 <sstream>
  15. #include <vector>
  16. #include <boost/bind.hpp>
  17. #include <exceptions/exceptions.h>
  18. #include <dns/masterload.h>
  19. #include <dns/name.h>
  20. #include <dns/rdata.h>
  21. #include <dns/rdataclass.h>
  22. #include <dns/rrclass.h>
  23. #include <dns/rrsetlist.h>
  24. #include <dns/rrttl.h>
  25. #include <dns/masterload.h>
  26. #include <datasrc/memory_datasrc.h>
  27. #include <gtest/gtest.h>
  28. using namespace std;
  29. using namespace isc::dns;
  30. using namespace isc::dns::rdata;
  31. using namespace isc::datasrc;
  32. namespace {
  33. // Commonly used result codes (Who should write the prefix all the time)
  34. using result::SUCCESS;
  35. using result::EXIST;
  36. class InMemoryClientTest : public ::testing::Test {
  37. protected:
  38. InMemoryClientTest() : rrclass(RRClass::IN())
  39. {}
  40. RRClass rrclass;
  41. InMemoryClient memory_client;
  42. };
  43. TEST_F(InMemoryClientTest, add_find_Zone) {
  44. // test add zone
  45. // Bogus zone (NULL)
  46. EXPECT_THROW(memory_client.addZone(ZoneFinderPtr()),
  47. isc::InvalidParameter);
  48. // add zones with different names one by one
  49. EXPECT_EQ(result::SUCCESS, memory_client.addZone(
  50. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::IN(),
  51. Name("a")))));
  52. EXPECT_EQ(result::SUCCESS, memory_client.addZone(
  53. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::CH(),
  54. Name("b")))));
  55. EXPECT_EQ(result::SUCCESS, memory_client.addZone(
  56. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::IN(),
  57. Name("c")))));
  58. // add zones with the same name suffix
  59. EXPECT_EQ(result::SUCCESS, memory_client.addZone(
  60. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::CH(),
  61. Name("x.d.e.f")))));
  62. EXPECT_EQ(result::SUCCESS, memory_client.addZone(
  63. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::CH(),
  64. Name("o.w.y.d.e.f")))));
  65. EXPECT_EQ(result::SUCCESS, memory_client.addZone(
  66. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::CH(),
  67. Name("p.w.y.d.e.f")))));
  68. EXPECT_EQ(result::SUCCESS, memory_client.addZone(
  69. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::IN(),
  70. Name("q.w.y.d.e.f")))));
  71. // add super zone and its subzone
  72. EXPECT_EQ(result::SUCCESS, memory_client.addZone(
  73. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::CH(),
  74. Name("g.h")))));
  75. EXPECT_EQ(result::SUCCESS, memory_client.addZone(
  76. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::IN(),
  77. Name("i.g.h")))));
  78. EXPECT_EQ(result::SUCCESS, memory_client.addZone(
  79. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::IN(),
  80. Name("z.d.e.f")))));
  81. EXPECT_EQ(result::SUCCESS, memory_client.addZone(
  82. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::IN(),
  83. Name("j.z.d.e.f")))));
  84. // different zone class isn't allowed.
  85. EXPECT_EQ(result::EXIST, memory_client.addZone(
  86. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::CH(),
  87. Name("q.w.y.d.e.f")))));
  88. // names are compared in a case insensitive manner.
  89. EXPECT_EQ(result::EXIST, memory_client.addZone(
  90. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::IN(),
  91. Name("Q.W.Y.d.E.f")))));
  92. // test find zone
  93. EXPECT_EQ(result::SUCCESS, memory_client.findZone(Name("a")).code);
  94. EXPECT_EQ(Name("a"),
  95. memory_client.findZone(Name("a")).zone_finder->getOrigin());
  96. EXPECT_EQ(result::SUCCESS,
  97. memory_client.findZone(Name("j.z.d.e.f")).code);
  98. EXPECT_EQ(Name("j.z.d.e.f"),
  99. memory_client.findZone(Name("j.z.d.e.f")).zone_finder->
  100. getOrigin());
  101. // NOTFOUND
  102. EXPECT_EQ(result::NOTFOUND, memory_client.findZone(Name("d.e.f")).code);
  103. EXPECT_EQ(ConstZoneFinderPtr(),
  104. memory_client.findZone(Name("d.e.f")).zone_finder);
  105. EXPECT_EQ(result::NOTFOUND,
  106. memory_client.findZone(Name("w.y.d.e.f")).code);
  107. EXPECT_EQ(ConstZoneFinderPtr(),
  108. memory_client.findZone(Name("w.y.d.e.f")).zone_finder);
  109. // there's no exact match. the result should be the longest match,
  110. // and the code should be PARTIALMATCH.
  111. EXPECT_EQ(result::PARTIALMATCH,
  112. memory_client.findZone(Name("j.g.h")).code);
  113. EXPECT_EQ(Name("g.h"),
  114. memory_client.findZone(Name("g.h")).zone_finder->getOrigin());
  115. EXPECT_EQ(result::PARTIALMATCH,
  116. memory_client.findZone(Name("z.i.g.h")).code);
  117. EXPECT_EQ(Name("i.g.h"),
  118. memory_client.findZone(Name("z.i.g.h")).zone_finder->
  119. getOrigin());
  120. }
  121. TEST_F(InMemoryClientTest, getZoneCount) {
  122. EXPECT_EQ(0, memory_client.getZoneCount());
  123. memory_client.addZone(
  124. ZoneFinderPtr(new InMemoryZoneFinder(rrclass,
  125. Name("example.com"))));
  126. EXPECT_EQ(1, memory_client.getZoneCount());
  127. // duplicate add. counter shouldn't change
  128. memory_client.addZone(
  129. ZoneFinderPtr(new InMemoryZoneFinder(rrclass,
  130. Name("example.com"))));
  131. EXPECT_EQ(1, memory_client.getZoneCount());
  132. // add one more
  133. memory_client.addZone(
  134. ZoneFinderPtr(new InMemoryZoneFinder(rrclass,
  135. Name("example.org"))));
  136. EXPECT_EQ(2, memory_client.getZoneCount());
  137. }
  138. // A helper callback of masterLoad() used in InMemoryZoneFinderTest.
  139. void
  140. setRRset(RRsetPtr rrset, vector<RRsetPtr*>::iterator& it) {
  141. *(*it) = rrset;
  142. ++it;
  143. }
  144. /// \brief Test fixture for the InMemoryZoneFinder class
  145. class InMemoryZoneFinderTest : public ::testing::Test {
  146. // A straightforward pair of textual RR(set) and a RRsetPtr variable
  147. // to store the RRset. Used to build test data below.
  148. struct RRsetData {
  149. const char* const text; // textual representation of an RRset
  150. RRsetPtr* rrset;
  151. };
  152. public:
  153. InMemoryZoneFinderTest() :
  154. class_(RRClass::IN()),
  155. origin_("example.org"),
  156. zone_finder_(class_, origin_)
  157. {
  158. // Build test RRsets. Below, we construct an RRset for
  159. // each textual RR(s) of zone_data, and assign it to the corresponding
  160. // rr_xxx.
  161. const RRsetData zone_data[] = {
  162. {"example.org. 300 IN NS ns.example.org.", &rr_ns_},
  163. {"example.org. 300 IN A 192.0.2.1", &rr_a_},
  164. {"ns.example.org. 300 IN A 192.0.2.2", &rr_ns_a_},
  165. {"ns.example.org. 300 IN AAAA 2001:db8::2", &rr_ns_aaaa_},
  166. {"cname.example.org. 300 IN CNAME canonical.example.org",
  167. &rr_cname_},
  168. {"cname.example.org. 300 IN A 192.0.2.3", &rr_cname_a_},
  169. {"dname.example.org. 300 IN DNAME target.example.org.",
  170. &rr_dname_},
  171. {"dname.example.org. 300 IN A 192.0.2.39", &rr_dname_a_},
  172. {"dname.example.org. 300 IN NS ns.dname.example.org.",
  173. &rr_dname_ns_},
  174. {"example.org. 300 IN DNAME example.com.", &rr_dname_apex_},
  175. {"child.example.org. 300 IN NS ns.child.example.org.",
  176. &rr_child_ns_},
  177. {"ns.child.example.org. 300 IN A 192.0.2.153",
  178. &rr_child_glue_},
  179. {"grand.child.example.org. 300 IN NS ns.grand.child.example.org.",
  180. &rr_grandchild_ns_},
  181. {"ns.grand.child.example.org. 300 IN AAAA 2001:db8::253",
  182. &rr_grandchild_glue_},
  183. {"dname.child.example.org. 300 IN DNAME example.com.",
  184. &rr_child_dname_},
  185. {"example.com. 300 IN A 192.0.2.10", &rr_out_},
  186. {"*.wild.example.org. 300 IN A 192.0.2.1", &rr_wild_},
  187. {"foo.wild.example.org. 300 IN A 192.0.2.3", &rr_under_wild_},
  188. {"wild.*.foo.example.org. 300 IN A 192.0.2.1", &rr_emptywild_},
  189. {"wild.*.foo.*.bar.example.org. 300 IN A 192.0.2.1",
  190. &rr_nested_emptywild_},
  191. {"*.nswild.example.org. 300 IN NS nswild.example.", &rr_nswild_},
  192. {"*.dnamewild.example.org. 300 IN DNAME dnamewild.example.",
  193. &rr_dnamewild_},
  194. {"*.child.example.org. 300 IN A 192.0.2.1", &rr_child_wild_},
  195. {"bar.foo.wild.example.org. 300 IN A 192.0.2.2", &rr_not_wild_},
  196. {"baz.foo.wild.example.org. 300 IN A 192.0.2.3",
  197. &rr_not_wild_another_},
  198. {NULL, NULL}
  199. };
  200. stringstream zone_data_stream;
  201. vector<RRsetPtr*> rrsets;
  202. for (unsigned int i = 0; zone_data[i].text != NULL; ++i) {
  203. zone_data_stream << zone_data[i].text << "\n";
  204. rrsets.push_back(zone_data[i].rrset);
  205. }
  206. vector<RRsetPtr*>::iterator it = rrsets.begin();
  207. masterLoad(zone_data_stream, Name::ROOT_NAME(), class_,
  208. boost::bind(setRRset, _1, it));
  209. }
  210. // Some data to test with
  211. const RRClass class_;
  212. const Name origin_;
  213. // The zone finder to torture by tests
  214. InMemoryZoneFinder zone_finder_;
  215. /*
  216. * Some RRsets to put inside the zone.
  217. */
  218. RRsetPtr
  219. // Out of zone RRset
  220. rr_out_,
  221. // NS of example.org
  222. rr_ns_,
  223. // A of ns.example.org
  224. rr_ns_a_,
  225. // AAAA of ns.example.org
  226. rr_ns_aaaa_,
  227. // A of example.org
  228. rr_a_;
  229. RRsetPtr rr_cname_; // CNAME in example.org (RDATA will be added)
  230. RRsetPtr rr_cname_a_; // for mixed CNAME + A case
  231. RRsetPtr rr_dname_; // DNAME in example.org (RDATA will be added)
  232. RRsetPtr rr_dname_a_; // for mixed DNAME + A case
  233. RRsetPtr rr_dname_ns_; // for mixed DNAME + NS case
  234. RRsetPtr rr_dname_apex_; // for mixed DNAME + NS case in the apex
  235. RRsetPtr rr_child_ns_; // NS of a child domain (for delegation)
  236. RRsetPtr rr_child_glue_; // glue RR of the child domain
  237. RRsetPtr rr_grandchild_ns_; // NS below a zone cut (unusual)
  238. RRsetPtr rr_grandchild_glue_; // glue RR below a deeper zone cut
  239. RRsetPtr rr_child_dname_; // A DNAME under NS
  240. RRsetPtr rr_wild_;
  241. RRsetPtr rr_emptywild_;
  242. RRsetPtr rr_nested_emptywild_;
  243. RRsetPtr rr_nswild_, rr_dnamewild_;
  244. RRsetPtr rr_child_wild_;
  245. RRsetPtr rr_under_wild_;
  246. RRsetPtr rr_not_wild_;
  247. RRsetPtr rr_not_wild_another_;
  248. /**
  249. * \brief Test one find query to the zone finder.
  250. *
  251. * Asks a query to the zone finder and checks it does not throw and returns
  252. * expected results. It returns nothing, it just signals failures
  253. * to GTEST.
  254. *
  255. * \param name The name to ask for.
  256. * \param rrtype The RRType to ask of.
  257. * \param result The expected code of the result.
  258. * \param check_answer Should a check against equality of the answer be
  259. * done?
  260. * \param answer The expected rrset, if any should be returned.
  261. * \param zone_finder Check different InMemoryZoneFinder object than
  262. * zone_finder_ (if NULL, uses zone_finder_)
  263. * \param check_wild_answer Checks that the answer has the same RRs, type
  264. * class and TTL as the eqxpected answer and that the name corresponds
  265. * to the one searched. It is meant for checking answers for wildcard
  266. * queries.
  267. */
  268. void findTest(const Name& name, const RRType& rrtype,
  269. ZoneFinder::Result result,
  270. bool check_answer = true,
  271. const ConstRRsetPtr& answer = ConstRRsetPtr(),
  272. RRsetList* target = NULL,
  273. InMemoryZoneFinder* zone_finder = NULL,
  274. ZoneFinder::FindOptions options = ZoneFinder::FIND_DEFAULT,
  275. bool check_wild_answer = false)
  276. {
  277. if (zone_finder == NULL) {
  278. zone_finder = &zone_finder_;
  279. }
  280. // The whole block is inside, because we need to check the result and
  281. // we can't assign to FindResult
  282. EXPECT_NO_THROW({
  283. ZoneFinder::FindResult find_result(zone_finder->find(
  284. name, rrtype,
  285. target, options));
  286. // Check it returns correct answers
  287. EXPECT_EQ(result, find_result.code);
  288. if (check_answer) {
  289. EXPECT_EQ(answer, find_result.rrset);
  290. } else if (check_wild_answer) {
  291. ASSERT_NE(ConstRRsetPtr(), answer) <<
  292. "Wrong test, don't check for wild names if you expect "
  293. "empty answer";
  294. ASSERT_NE(ConstRRsetPtr(), find_result.rrset) <<
  295. "No answer found";
  296. RdataIteratorPtr expectedIt(answer->getRdataIterator());
  297. RdataIteratorPtr actualIt(
  298. find_result.rrset->getRdataIterator());
  299. while (!expectedIt->isLast() && !actualIt->isLast()) {
  300. EXPECT_EQ(0, expectedIt->getCurrent().compare(
  301. actualIt->getCurrent())) << "The RRs differ ('" <<
  302. expectedIt->getCurrent().toText() << "', '" <<
  303. actualIt->getCurrent().toText() << "')";
  304. expectedIt->next();
  305. actualIt->next();
  306. }
  307. EXPECT_TRUE(expectedIt->isLast()) <<
  308. "Result has less RRs than expected";
  309. EXPECT_TRUE(actualIt->isLast()) <<
  310. "Result has more RRs than expected";
  311. EXPECT_EQ(answer->getClass(),
  312. find_result.rrset->getClass());
  313. EXPECT_EQ(answer->getType(),
  314. find_result.rrset->getType());
  315. EXPECT_EQ(answer->getTTL(),
  316. find_result.rrset->getTTL());
  317. EXPECT_EQ(name, find_result.rrset->getName());
  318. }
  319. });
  320. }
  321. // Internal part of the cancelWildcard test that is multiple times
  322. void doCancelWildcardTest();
  323. };
  324. /**
  325. * \brief Test InMemoryZoneFinder::InMemoryZoneFinder constructor.
  326. *
  327. * Takes the created zone finder and checks its properties they are the same
  328. * as passed parameters.
  329. */
  330. TEST_F(InMemoryZoneFinderTest, constructor) {
  331. ASSERT_EQ(class_, zone_finder_.getClass());
  332. ASSERT_EQ(origin_, zone_finder_.getOrigin());
  333. }
  334. /**
  335. * \brief Test adding.
  336. *
  337. * We test that it throws at the correct moments and the correct exceptions.
  338. * And we test the return value.
  339. */
  340. TEST_F(InMemoryZoneFinderTest, add) {
  341. // This one does not belong to this zone
  342. EXPECT_THROW(zone_finder_.add(rr_out_), InMemoryZoneFinder::OutOfZone);
  343. // Test null pointer
  344. EXPECT_THROW(zone_finder_.add(ConstRRsetPtr()),
  345. InMemoryZoneFinder::NullRRset);
  346. // Now put all the data we have there. It should throw nothing
  347. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_)));
  348. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_a_)));
  349. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_aaaa_)));
  350. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_a_)));
  351. // Try putting there something twice, it should be rejected
  352. EXPECT_NO_THROW(EXPECT_EQ(EXIST, zone_finder_.add(rr_ns_)));
  353. EXPECT_NO_THROW(EXPECT_EQ(EXIST, zone_finder_.add(rr_ns_a_)));
  354. }
  355. TEST_F(InMemoryZoneFinderTest, addMultipleCNAMEs) {
  356. rr_cname_->addRdata(generic::CNAME("canonical2.example.org."));
  357. EXPECT_THROW(zone_finder_.add(rr_cname_), InMemoryZoneFinder::AddError);
  358. }
  359. TEST_F(InMemoryZoneFinderTest, addCNAMEThenOther) {
  360. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_cname_));
  361. EXPECT_THROW(zone_finder_.add(rr_cname_a_), InMemoryZoneFinder::AddError);
  362. }
  363. TEST_F(InMemoryZoneFinderTest, addOtherThenCNAME) {
  364. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_cname_a_));
  365. EXPECT_THROW(zone_finder_.add(rr_cname_), InMemoryZoneFinder::AddError);
  366. }
  367. TEST_F(InMemoryZoneFinderTest, findCNAME) {
  368. // install CNAME RR
  369. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_cname_));
  370. // Find A RR of the same. Should match the CNAME
  371. findTest(rr_cname_->getName(), RRType::NS(), ZoneFinder::CNAME, true,
  372. rr_cname_);
  373. // Find the CNAME itself. Should result in normal SUCCESS
  374. findTest(rr_cname_->getName(), RRType::CNAME(), ZoneFinder::SUCCESS, true,
  375. rr_cname_);
  376. }
  377. TEST_F(InMemoryZoneFinderTest, findCNAMEUnderZoneCut) {
  378. // There's nothing special when we find a CNAME under a zone cut
  379. // (with FIND_GLUE_OK). The behavior is different from BIND 9,
  380. // so we test this case explicitly.
  381. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_ns_));
  382. RRsetPtr rr_cname_under_cut_(new RRset(Name("cname.child.example.org"),
  383. class_, RRType::CNAME(),
  384. RRTTL(300)));
  385. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_cname_under_cut_));
  386. findTest(Name("cname.child.example.org"), RRType::AAAA(),
  387. ZoneFinder::CNAME, true, rr_cname_under_cut_, NULL, NULL,
  388. ZoneFinder::FIND_GLUE_OK);
  389. }
  390. // Two DNAMEs at single domain are disallowed by RFC 2672, section 3)
  391. // Having a CNAME there is disallowed too, but it is tested by
  392. // addOtherThenCNAME and addCNAMEThenOther.
  393. TEST_F(InMemoryZoneFinderTest, addMultipleDNAMEs) {
  394. rr_dname_->addRdata(generic::DNAME("target2.example.org."));
  395. EXPECT_THROW(zone_finder_.add(rr_dname_), InMemoryZoneFinder::AddError);
  396. }
  397. /*
  398. * These two tests ensure that we can't have DNAME and NS at the same
  399. * node with the exception of the apex of zone (forbidden by RFC 2672)
  400. */
  401. TEST_F(InMemoryZoneFinderTest, addDNAMEThenNS) {
  402. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_dname_)));
  403. EXPECT_THROW(zone_finder_.add(rr_dname_ns_), InMemoryZoneFinder::AddError);
  404. }
  405. TEST_F(InMemoryZoneFinderTest, addNSThenDNAME) {
  406. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_dname_ns_)));
  407. EXPECT_THROW(zone_finder_.add(rr_dname_), InMemoryZoneFinder::AddError);
  408. }
  409. // It is allowed to have NS and DNAME at apex
  410. TEST_F(InMemoryZoneFinderTest, DNAMEAndNSAtApex) {
  411. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_dname_apex_)));
  412. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_)));
  413. // The NS should be possible to be found, below should be DNAME, not
  414. // delegation
  415. findTest(origin_, RRType::NS(), ZoneFinder::SUCCESS, true, rr_ns_);
  416. findTest(rr_child_ns_->getName(), RRType::A(), ZoneFinder::DNAME, true,
  417. rr_dname_apex_);
  418. }
  419. TEST_F(InMemoryZoneFinderTest, NSAndDNAMEAtApex) {
  420. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_)));
  421. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_dname_apex_)));
  422. }
  423. // TODO: Test (and implement) adding data under DNAME. That is forbidden by
  424. // 2672 as well.
  425. // Search under a DNAME record. It should return the DNAME
  426. TEST_F(InMemoryZoneFinderTest, findBelowDNAME) {
  427. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_dname_)));
  428. findTest(Name("below.dname.example.org"), RRType::A(), ZoneFinder::DNAME,
  429. true, rr_dname_);
  430. }
  431. // Search at the domain with DNAME. It should act as DNAME isn't there, DNAME
  432. // influences only the data below (see RFC 2672, section 3)
  433. TEST_F(InMemoryZoneFinderTest, findAtDNAME) {
  434. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_dname_)));
  435. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_dname_a_)));
  436. const Name dname_name(rr_dname_->getName());
  437. findTest(dname_name, RRType::A(), ZoneFinder::SUCCESS, true, rr_dname_a_);
  438. findTest(dname_name, RRType::DNAME(), ZoneFinder::SUCCESS, true,
  439. rr_dname_);
  440. findTest(dname_name, RRType::TXT(), ZoneFinder::NXRRSET, true);
  441. }
  442. // Try searching something that is both under NS and DNAME, without and with
  443. // GLUE_OK mode (it should stop at the NS and DNAME respectively).
  444. TEST_F(InMemoryZoneFinderTest, DNAMEUnderNS) {
  445. zone_finder_.add(rr_child_ns_);
  446. zone_finder_.add(rr_child_dname_);
  447. Name lowName("below.dname.child.example.org.");
  448. findTest(lowName, RRType::A(), ZoneFinder::DELEGATION, true, rr_child_ns_);
  449. findTest(lowName, RRType::A(), ZoneFinder::DNAME, true, rr_child_dname_,
  450. NULL, NULL, ZoneFinder::FIND_GLUE_OK);
  451. }
  452. // Test adding child zones and zone cut handling
  453. TEST_F(InMemoryZoneFinderTest, delegationNS) {
  454. // add in-zone data
  455. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_)));
  456. // install a zone cut
  457. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_ns_)));
  458. // below the zone cut
  459. findTest(Name("www.child.example.org"), RRType::A(),
  460. ZoneFinder::DELEGATION, true, rr_child_ns_);
  461. // at the zone cut
  462. findTest(Name("child.example.org"), RRType::A(), ZoneFinder::DELEGATION,
  463. true, rr_child_ns_);
  464. findTest(Name("child.example.org"), RRType::NS(), ZoneFinder::DELEGATION,
  465. true, rr_child_ns_);
  466. // finding NS for the apex (origin) node. This must not be confused
  467. // with delegation due to the existence of an NS RR.
  468. findTest(origin_, RRType::NS(), ZoneFinder::SUCCESS, true, rr_ns_);
  469. // unusual case of "nested delegation": the highest cut should be used.
  470. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_grandchild_ns_)));
  471. findTest(Name("www.grand.child.example.org"), RRType::A(),
  472. // note: !rr_grandchild_ns_
  473. ZoneFinder::DELEGATION, true, rr_child_ns_);
  474. }
  475. TEST_F(InMemoryZoneFinderTest, findAny) {
  476. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_a_)));
  477. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_)));
  478. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_glue_)));
  479. // origin
  480. RRsetList origin_rrsets;
  481. findTest(origin_, RRType::ANY(), ZoneFinder::SUCCESS, true,
  482. ConstRRsetPtr(), &origin_rrsets);
  483. EXPECT_EQ(2, origin_rrsets.size());
  484. EXPECT_EQ(rr_a_, origin_rrsets.findRRset(RRType::A(), RRClass::IN()));
  485. EXPECT_EQ(rr_ns_, origin_rrsets.findRRset(RRType::NS(), RRClass::IN()));
  486. // out zone name
  487. RRsetList out_rrsets;
  488. findTest(Name("example.com"), RRType::ANY(), ZoneFinder::NXDOMAIN, true,
  489. ConstRRsetPtr(), &out_rrsets);
  490. EXPECT_EQ(0, out_rrsets.size());
  491. RRsetList glue_child_rrsets;
  492. findTest(rr_child_glue_->getName(), RRType::ANY(), ZoneFinder::SUCCESS,
  493. true, ConstRRsetPtr(), &glue_child_rrsets);
  494. EXPECT_EQ(rr_child_glue_, glue_child_rrsets.findRRset(RRType::A(),
  495. RRClass::IN()));
  496. EXPECT_EQ(1, glue_child_rrsets.size());
  497. // TODO: test NXRRSET case after rbtree non-terminal logic has
  498. // been implemented
  499. // add zone cut
  500. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_ns_)));
  501. // zone cut
  502. RRsetList child_rrsets;
  503. findTest(rr_child_ns_->getName(), RRType::ANY(), ZoneFinder::DELEGATION,
  504. true, rr_child_ns_, &child_rrsets);
  505. EXPECT_EQ(0, child_rrsets.size());
  506. // glue for this zone cut
  507. RRsetList new_glue_child_rrsets;
  508. findTest(rr_child_glue_->getName(), RRType::ANY(), ZoneFinder::DELEGATION,
  509. true, rr_child_ns_, &new_glue_child_rrsets);
  510. EXPECT_EQ(0, new_glue_child_rrsets.size());
  511. }
  512. TEST_F(InMemoryZoneFinderTest, glue) {
  513. // install zone data:
  514. // a zone cut
  515. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_ns_)));
  516. // glue for this cut
  517. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_glue_)));
  518. // a nested zone cut (unusual)
  519. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_grandchild_ns_)));
  520. // glue under the deeper zone cut
  521. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_grandchild_glue_)));
  522. // by default glue is hidden due to the zone cut
  523. findTest(rr_child_glue_->getName(), RRType::A(), ZoneFinder::DELEGATION,
  524. true, rr_child_ns_);
  525. // If we do it in the "glue OK" mode, we should find the exact match.
  526. findTest(rr_child_glue_->getName(), RRType::A(), ZoneFinder::SUCCESS, true,
  527. rr_child_glue_, NULL, NULL, ZoneFinder::FIND_GLUE_OK);
  528. // glue OK + NXRRSET case
  529. findTest(rr_child_glue_->getName(), RRType::AAAA(), ZoneFinder::NXRRSET,
  530. true, ConstRRsetPtr(), NULL, NULL, ZoneFinder::FIND_GLUE_OK);
  531. // glue OK + NXDOMAIN case
  532. findTest(Name("www.child.example.org"), RRType::A(),
  533. ZoneFinder::DELEGATION, true, rr_child_ns_, NULL, NULL,
  534. ZoneFinder::FIND_GLUE_OK);
  535. // nested cut case. The glue should be found.
  536. findTest(rr_grandchild_glue_->getName(), RRType::AAAA(),
  537. ZoneFinder::SUCCESS,
  538. true, rr_grandchild_glue_, NULL, NULL, ZoneFinder::FIND_GLUE_OK);
  539. // A non-existent name in nested cut. This should result in delegation
  540. // at the highest zone cut.
  541. findTest(Name("www.grand.child.example.org"), RRType::TXT(),
  542. ZoneFinder::DELEGATION, true, rr_child_ns_, NULL, NULL,
  543. ZoneFinder::FIND_GLUE_OK);
  544. }
  545. /**
  546. * \brief Test searching.
  547. *
  548. * Check it finds or does not find correctly and does not throw exceptions.
  549. * \todo This doesn't do any kind of CNAME and so on. If it isn't
  550. * directly there, it just tells it doesn't exist.
  551. */
  552. TEST_F(InMemoryZoneFinderTest, find) {
  553. // Fill some data inside
  554. // Now put all the data we have there. It should throw nothing
  555. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_)));
  556. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_a_)));
  557. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_aaaa_)));
  558. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_a_)));
  559. // These two should be successful
  560. findTest(origin_, RRType::NS(), ZoneFinder::SUCCESS, true, rr_ns_);
  561. findTest(rr_ns_a_->getName(), RRType::A(), ZoneFinder::SUCCESS, true,
  562. rr_ns_a_);
  563. // These domain exist but don't have the provided RRType
  564. findTest(origin_, RRType::AAAA(), ZoneFinder::NXRRSET);
  565. findTest(rr_ns_a_->getName(), RRType::NS(), ZoneFinder::NXRRSET);
  566. // These domains don't exist (and one is out of the zone)
  567. findTest(Name("nothere.example.org"), RRType::A(), ZoneFinder::NXDOMAIN);
  568. findTest(Name("example.net"), RRType::A(), ZoneFinder::NXDOMAIN);
  569. }
  570. TEST_F(InMemoryZoneFinderTest, emptyNode) {
  571. /*
  572. * The backend RBTree for this test should look like as follows:
  573. * example.org
  574. * |
  575. * baz (empty; easy case)
  576. * / | \
  577. * bar | x.foo ('foo' part is empty; a bit trickier)
  578. * bbb
  579. * /
  580. * aaa
  581. */
  582. // Construct the test zone
  583. const char* const names[] = {
  584. "bar.example.org", "x.foo.example.org", "aaa.baz.example.org",
  585. "bbb.baz.example.org.", NULL};
  586. for (int i = 0; names[i] != NULL; ++i) {
  587. ConstRRsetPtr rrset(new RRset(Name(names[i]), class_, RRType::A(),
  588. RRTTL(300)));
  589. EXPECT_EQ(SUCCESS, zone_finder_.add(rrset));
  590. }
  591. // empty node matching, easy case: the node for 'baz' exists with
  592. // no data.
  593. findTest(Name("baz.example.org"), RRType::A(), ZoneFinder::NXRRSET);
  594. // empty node matching, a trickier case: the node for 'foo' is part of
  595. // "x.foo", which should be considered an empty node.
  596. findTest(Name("foo.example.org"), RRType::A(), ZoneFinder::NXRRSET);
  597. // "org" is contained in "example.org", but it shouldn't be treated as
  598. // NXRRSET because it's out of zone.
  599. // Note: basically we don't expect such a query to be performed (the common
  600. // operation is to identify the best matching zone first then perform
  601. // search it), but we shouldn't be confused even in the unexpected case.
  602. findTest(Name("org"), RRType::A(), ZoneFinder::NXDOMAIN);
  603. }
  604. TEST_F(InMemoryZoneFinderTest, load) {
  605. // Put some data inside the zone
  606. EXPECT_NO_THROW(EXPECT_EQ(result::SUCCESS, zone_finder_.add(rr_ns_)));
  607. // Loading with different origin should fail
  608. EXPECT_THROW(zone_finder_.load(TEST_DATA_DIR "/root.zone"),
  609. MasterLoadError);
  610. // See the original data is still there, survived the exception
  611. findTest(origin_, RRType::NS(), ZoneFinder::SUCCESS, true, rr_ns_);
  612. // Create correct zone
  613. InMemoryZoneFinder rootzone(class_, Name("."));
  614. // Try putting something inside
  615. EXPECT_NO_THROW(EXPECT_EQ(result::SUCCESS, rootzone.add(rr_ns_aaaa_)));
  616. // Load the zone. It should overwrite/remove the above RRset
  617. EXPECT_NO_THROW(rootzone.load(TEST_DATA_DIR "/root.zone"));
  618. // Now see there are some rrsets (we don't look inside, though)
  619. findTest(Name("."), RRType::SOA(), ZoneFinder::SUCCESS, false,
  620. ConstRRsetPtr(), NULL, &rootzone);
  621. findTest(Name("."), RRType::NS(), ZoneFinder::SUCCESS, false,
  622. ConstRRsetPtr(), NULL, &rootzone);
  623. findTest(Name("a.root-servers.net."), RRType::A(), ZoneFinder::SUCCESS,
  624. false, ConstRRsetPtr(), NULL, &rootzone);
  625. // But this should no longer be here
  626. findTest(rr_ns_a_->getName(), RRType::AAAA(), ZoneFinder::NXDOMAIN, true,
  627. ConstRRsetPtr(), NULL, &rootzone);
  628. // Try loading zone that is wrong in a different way
  629. EXPECT_THROW(zone_finder_.load(TEST_DATA_DIR "/duplicate_rrset.zone"),
  630. MasterLoadError);
  631. }
  632. /*
  633. * Test that puts a (simple) wildcard into the zone and checks we can
  634. * correctly find the data.
  635. */
  636. TEST_F(InMemoryZoneFinderTest, wildcard) {
  637. /*
  638. * example.org.
  639. * |
  640. * wild (not *.wild, should have wild mark)
  641. * |
  642. * *
  643. */
  644. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_wild_));
  645. // Search at the parent. The parent will not have the A, but it will
  646. // be in the wildcard (so check the wildcard isn't matched at the parent)
  647. {
  648. SCOPED_TRACE("Search at parrent");
  649. findTest(Name("wild.example.org"), RRType::A(), ZoneFinder::NXRRSET);
  650. }
  651. // Search the original name of wildcard
  652. {
  653. SCOPED_TRACE("Search directly at *");
  654. findTest(Name("*.wild.example.org"), RRType::A(), ZoneFinder::SUCCESS,
  655. true, rr_wild_);
  656. }
  657. // Search "created" name.
  658. {
  659. SCOPED_TRACE("Search at created child");
  660. findTest(Name("a.wild.example.org"), RRType::A(), ZoneFinder::SUCCESS,
  661. false, rr_wild_, NULL, NULL, ZoneFinder::FIND_DEFAULT, true);
  662. }
  663. // Search another created name, this time little bit lower
  664. {
  665. SCOPED_TRACE("Search at created grand-child");
  666. findTest(Name("a.b.wild.example.org"), RRType::A(),
  667. ZoneFinder::SUCCESS, false, rr_wild_, NULL, NULL,
  668. ZoneFinder::FIND_DEFAULT, true);
  669. }
  670. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_under_wild_));
  671. {
  672. SCOPED_TRACE("Search under non-wildcard");
  673. findTest(Name("bar.foo.wild.example.org"), RRType::A(),
  674. ZoneFinder::NXDOMAIN);
  675. }
  676. }
  677. /*
  678. * Test that we don't match a wildcard if we get under delegation.
  679. * By 4.3.3 of RFC1034:
  680. * "Wildcard RRs do not apply:
  681. * - When the query is in another zone. That is, delegation cancels
  682. * the wildcard defaults."
  683. */
  684. TEST_F(InMemoryZoneFinderTest, delegatedWildcard) {
  685. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_wild_));
  686. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_ns_));
  687. {
  688. SCOPED_TRACE("Looking under delegation point");
  689. findTest(Name("a.child.example.org"), RRType::A(),
  690. ZoneFinder::DELEGATION, true, rr_child_ns_);
  691. }
  692. {
  693. SCOPED_TRACE("Looking under delegation point in GLUE_OK mode");
  694. findTest(Name("a.child.example.org"), RRType::A(),
  695. ZoneFinder::DELEGATION, true, rr_child_ns_, NULL, NULL,
  696. ZoneFinder::FIND_GLUE_OK);
  697. }
  698. }
  699. // Tests combination of wildcard and ANY.
  700. TEST_F(InMemoryZoneFinderTest, anyWildcard) {
  701. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_wild_));
  702. // First try directly the name (normal match)
  703. {
  704. SCOPED_TRACE("Asking direcly for *");
  705. RRsetList target;
  706. findTest(Name("*.wild.example.org"), RRType::ANY(),
  707. ZoneFinder::SUCCESS, true, ConstRRsetPtr(), &target);
  708. ASSERT_EQ(1, target.size());
  709. EXPECT_EQ(RRType::A(), (*target.begin())->getType());
  710. EXPECT_EQ(Name("*.wild.example.org"), (*target.begin())->getName());
  711. }
  712. // Then a wildcard match
  713. {
  714. SCOPED_TRACE("Asking in the wild way");
  715. RRsetList target;
  716. findTest(Name("a.wild.example.org"), RRType::ANY(),
  717. ZoneFinder::SUCCESS, true, ConstRRsetPtr(), &target);
  718. ASSERT_EQ(1, target.size());
  719. EXPECT_EQ(RRType::A(), (*target.begin())->getType());
  720. EXPECT_EQ(Name("a.wild.example.org"), (*target.begin())->getName());
  721. }
  722. }
  723. // Test there's nothing in the wildcard in the middle if we load
  724. // wild.*.foo.example.org.
  725. TEST_F(InMemoryZoneFinderTest, emptyWildcard) {
  726. /*
  727. * example.org.
  728. * foo
  729. * *
  730. * wild
  731. */
  732. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_emptywild_));
  733. {
  734. SCOPED_TRACE("Asking for the original record under wildcard");
  735. findTest(Name("wild.*.foo.example.org"), RRType::A(),
  736. ZoneFinder::SUCCESS, true, rr_emptywild_);
  737. }
  738. {
  739. SCOPED_TRACE("Asking for A record");
  740. findTest(Name("a.foo.example.org"), RRType::A(), ZoneFinder::NXRRSET);
  741. findTest(Name("*.foo.example.org"), RRType::A(), ZoneFinder::NXRRSET);
  742. findTest(Name("foo.example.org"), RRType::A(), ZoneFinder::NXRRSET);
  743. }
  744. {
  745. SCOPED_TRACE("Asking for ANY record");
  746. RRsetList normalTarget;
  747. findTest(Name("*.foo.example.org"), RRType::ANY(), ZoneFinder::NXRRSET,
  748. true, ConstRRsetPtr(), &normalTarget);
  749. EXPECT_EQ(0, normalTarget.size());
  750. RRsetList wildTarget;
  751. findTest(Name("a.foo.example.org"), RRType::ANY(),
  752. ZoneFinder::NXRRSET, true, ConstRRsetPtr(), &wildTarget);
  753. EXPECT_EQ(0, wildTarget.size());
  754. }
  755. {
  756. SCOPED_TRACE("Asking on the non-terminal");
  757. findTest(Name("wild.bar.foo.example.org"), RRType::A(),
  758. ZoneFinder::NXRRSET);
  759. }
  760. }
  761. // Same as emptyWildcard, but with multiple * in the path.
  762. TEST_F(InMemoryZoneFinderTest, nestedEmptyWildcard) {
  763. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nested_emptywild_));
  764. {
  765. SCOPED_TRACE("Asking for the original record under wildcards");
  766. findTest(Name("wild.*.foo.*.bar.example.org"), RRType::A(),
  767. ZoneFinder::SUCCESS, true, rr_nested_emptywild_);
  768. }
  769. {
  770. SCOPED_TRACE("Matching wildcard against empty nonterminal");
  771. const char* names[] = {
  772. "baz.foo.*.bar.example.org",
  773. "baz.foo.baz.bar.example.org",
  774. "*.foo.baz.bar.example.org",
  775. NULL
  776. };
  777. for (const char** name(names); *name != NULL; ++ name) {
  778. SCOPED_TRACE(string("Node ") + *name);
  779. findTest(Name(*name), RRType::A(), ZoneFinder::NXRRSET);
  780. }
  781. }
  782. // Domains to test
  783. const char* names[] = {
  784. "*.foo.*.bar.example.org",
  785. "foo.*.bar.example.org",
  786. "*.bar.example.org",
  787. "bar.example.org",
  788. NULL
  789. };
  790. {
  791. SCOPED_TRACE("Asking directly for A on parent nodes");
  792. for (const char** name(names); *name != NULL; ++ name) {
  793. SCOPED_TRACE(string("Node ") + *name);
  794. findTest(Name(*name), RRType::A(), ZoneFinder::NXRRSET);
  795. }
  796. }
  797. {
  798. SCOPED_TRACE("Asking for ANY on parent nodes");
  799. for (const char** name(names); *name != NULL; ++ name) {
  800. SCOPED_TRACE(string("Node ") + *name);
  801. RRsetList target;
  802. findTest(Name(*name), RRType::ANY(), ZoneFinder::NXRRSET, true,
  803. ConstRRsetPtr(), &target);
  804. EXPECT_EQ(0, target.size());
  805. }
  806. }
  807. }
  808. // We run this part twice from the below test, in two slightly different
  809. // situations
  810. void
  811. InMemoryZoneFinderTest::doCancelWildcardTest() {
  812. // These should be canceled
  813. {
  814. SCOPED_TRACE("Canceled under foo.wild.example.org");
  815. findTest(Name("aaa.foo.wild.example.org"), RRType::A(),
  816. ZoneFinder::NXDOMAIN);
  817. findTest(Name("zzz.foo.wild.example.org"), RRType::A(),
  818. ZoneFinder::NXDOMAIN);
  819. }
  820. // This is existing, non-wildcard domain, shouldn't wildcard at all
  821. {
  822. SCOPED_TRACE("Existing domain under foo.wild.example.org");
  823. findTest(Name("bar.foo.wild.example.org"), RRType::A(),
  824. ZoneFinder::SUCCESS, true, rr_not_wild_);
  825. }
  826. // These should be caught by the wildcard
  827. {
  828. SCOPED_TRACE("Neighbor wildcards to foo.wild.example.org");
  829. const char* names[] = {
  830. "aaa.bbb.wild.example.org",
  831. "aaa.zzz.wild.example.org",
  832. "zzz.wild.example.org",
  833. NULL
  834. };
  835. for (const char** name(names); *name != NULL; ++ name) {
  836. SCOPED_TRACE(string("Node ") + *name);
  837. findTest(Name(*name), RRType::A(), ZoneFinder::SUCCESS, false,
  838. rr_wild_, NULL, NULL, ZoneFinder::FIND_DEFAULT, true);
  839. }
  840. }
  841. // This shouldn't be wildcarded, it's an existing domain
  842. {
  843. SCOPED_TRACE("The foo.wild.example.org itself");
  844. findTest(Name("foo.wild.example.org"), RRType::A(),
  845. ZoneFinder::NXRRSET);
  846. }
  847. }
  848. /*
  849. * This tests that if there's a name between the wildcard domain and the
  850. * searched one, it will not trigger wildcard, for example, if we have
  851. * *.wild.example.org and bar.foo.wild.example.org, then we know
  852. * foo.wild.example.org exists and is not wildcard. Therefore, search for
  853. * aaa.foo.wild.example.org should return NXDOMAIN.
  854. *
  855. * Tests few cases "around" the canceled wildcard match, to see something that
  856. * shouldn't be canceled isn't.
  857. */
  858. TEST_F(InMemoryZoneFinderTest, cancelWildcard) {
  859. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_wild_));
  860. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_not_wild_));
  861. {
  862. SCOPED_TRACE("Runnig with single entry under foo.wild.example.org");
  863. doCancelWildcardTest();
  864. }
  865. // Try putting another one under foo.wild....
  866. // The result should be the same but it will be done in another way in the
  867. // code, because the foo.wild.example.org will exist in the tree.
  868. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_not_wild_another_));
  869. {
  870. SCOPED_TRACE("Runnig with two entries under foo.wild.example.org");
  871. doCancelWildcardTest();
  872. }
  873. }
  874. TEST_F(InMemoryZoneFinderTest, loadBadWildcard) {
  875. // We reject loading the zone if it contains a wildcard name for
  876. // NS or DNAME.
  877. EXPECT_THROW(zone_finder_.add(rr_nswild_), InMemoryZoneFinder::AddError);
  878. EXPECT_THROW(zone_finder_.add(rr_dnamewild_),
  879. InMemoryZoneFinder::AddError);
  880. }
  881. TEST_F(InMemoryZoneFinderTest, swap) {
  882. // build one zone finder with some data
  883. InMemoryZoneFinder finder1(class_, origin_);
  884. EXPECT_EQ(result::SUCCESS, finder1.add(rr_ns_));
  885. EXPECT_EQ(result::SUCCESS, finder1.add(rr_ns_aaaa_));
  886. // build another zone finder of a different RR class with some other data
  887. const Name other_origin("version.bind");
  888. ASSERT_NE(origin_, other_origin); // make sure these two are different
  889. InMemoryZoneFinder finder2(RRClass::CH(), other_origin);
  890. EXPECT_EQ(result::SUCCESS,
  891. finder2.add(RRsetPtr(new RRset(Name("version.bind"),
  892. RRClass::CH(), RRType::TXT(),
  893. RRTTL(0)))));
  894. finder1.swap(finder2);
  895. EXPECT_EQ(other_origin, finder1.getOrigin());
  896. EXPECT_EQ(origin_, finder2.getOrigin());
  897. EXPECT_EQ(RRClass::CH(), finder1.getClass());
  898. EXPECT_EQ(RRClass::IN(), finder2.getClass());
  899. // make sure the zone data is swapped, too
  900. findTest(origin_, RRType::NS(), ZoneFinder::NXDOMAIN, false,
  901. ConstRRsetPtr(), NULL, &finder1);
  902. findTest(other_origin, RRType::TXT(), ZoneFinder::SUCCESS, false,
  903. ConstRRsetPtr(), NULL, &finder1);
  904. findTest(origin_, RRType::NS(), ZoneFinder::SUCCESS, false,
  905. ConstRRsetPtr(), NULL, &finder2);
  906. findTest(other_origin, RRType::TXT(), ZoneFinder::NXDOMAIN, false,
  907. ConstRRsetPtr(), NULL, &finder2);
  908. }
  909. TEST_F(InMemoryZoneFinderTest, getFileName) {
  910. // for an empty zone the file name should also be empty.
  911. EXPECT_TRUE(zone_finder_.getFileName().empty());
  912. // if loading a zone fails the file name shouldn't be set.
  913. EXPECT_THROW(zone_finder_.load(TEST_DATA_DIR "/root.zone"),
  914. MasterLoadError);
  915. EXPECT_TRUE(zone_finder_.getFileName().empty());
  916. // after a successful load, the specified file name should be set
  917. InMemoryZoneFinder rootzone(class_, Name("."));
  918. EXPECT_NO_THROW(rootzone.load(TEST_DATA_DIR "/root.zone"));
  919. EXPECT_EQ(TEST_DATA_DIR "/root.zone", rootzone.getFileName());
  920. // overriding load, which will fail
  921. EXPECT_THROW(rootzone.load(TEST_DATA_DIR "/duplicate_rrset.zone"),
  922. MasterLoadError);
  923. // the file name should be intact.
  924. EXPECT_EQ(TEST_DATA_DIR "/root.zone", rootzone.getFileName());
  925. // After swap, file names should also be swapped.
  926. zone_finder_.swap(rootzone);
  927. EXPECT_EQ(TEST_DATA_DIR "/root.zone", zone_finder_.getFileName());
  928. EXPECT_TRUE(rootzone.getFileName().empty());
  929. }
  930. }