memory_datasrc_unittest.cc 94 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232
  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 "faked_nsec3.h"
  15. #include <exceptions/exceptions.h>
  16. #include <dns/masterload.h>
  17. #include <dns/name.h>
  18. #include <dns/nsec3hash.h>
  19. #include <dns/rdata.h>
  20. #include <dns/rdataclass.h>
  21. #include <dns/rrclass.h>
  22. #include <dns/rrsetlist.h>
  23. #include <dns/rrttl.h>
  24. #include <dns/masterload.h>
  25. #include <datasrc/client.h>
  26. #include <datasrc/memory_datasrc.h>
  27. #include <datasrc/data_source.h>
  28. #include <datasrc/iterator.h>
  29. #include "test_client.h"
  30. #include <testutils/dnsmessage_test.h>
  31. #include <gtest/gtest.h>
  32. #include <boost/bind.hpp>
  33. #include <boost/foreach.hpp>
  34. #include <boost/shared_ptr.hpp>
  35. #include <sstream>
  36. #include <vector>
  37. using namespace std;
  38. using namespace isc::dns;
  39. using namespace isc::dns::rdata;
  40. using namespace isc::datasrc;
  41. using namespace isc::testutils;
  42. using boost::shared_ptr;
  43. using namespace isc::datasrc::test;
  44. namespace {
  45. // Commonly used result codes (Who should write the prefix all the time)
  46. using result::SUCCESS;
  47. using result::EXIST;
  48. class InMemoryClientTest : public ::testing::Test {
  49. protected:
  50. InMemoryClientTest() : rrclass(RRClass::IN())
  51. {}
  52. RRClass rrclass;
  53. InMemoryClient memory_client;
  54. };
  55. TEST_F(InMemoryClientTest, add_find_Zone) {
  56. // test add zone
  57. // Bogus zone (NULL)
  58. EXPECT_THROW(memory_client.addZone(ZoneFinderPtr()),
  59. isc::InvalidParameter);
  60. // add zones with different names one by one
  61. EXPECT_EQ(result::SUCCESS, memory_client.addZone(
  62. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::IN(),
  63. Name("a")))));
  64. EXPECT_EQ(result::SUCCESS, memory_client.addZone(
  65. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::CH(),
  66. Name("b")))));
  67. EXPECT_EQ(result::SUCCESS, memory_client.addZone(
  68. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::IN(),
  69. Name("c")))));
  70. // add zones with the same name suffix
  71. EXPECT_EQ(result::SUCCESS, memory_client.addZone(
  72. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::CH(),
  73. Name("x.d.e.f")))));
  74. EXPECT_EQ(result::SUCCESS, memory_client.addZone(
  75. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::CH(),
  76. Name("o.w.y.d.e.f")))));
  77. EXPECT_EQ(result::SUCCESS, memory_client.addZone(
  78. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::CH(),
  79. Name("p.w.y.d.e.f")))));
  80. EXPECT_EQ(result::SUCCESS, memory_client.addZone(
  81. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::IN(),
  82. Name("q.w.y.d.e.f")))));
  83. // add super zone and its subzone
  84. EXPECT_EQ(result::SUCCESS, memory_client.addZone(
  85. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::CH(),
  86. Name("g.h")))));
  87. EXPECT_EQ(result::SUCCESS, memory_client.addZone(
  88. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::IN(),
  89. Name("i.g.h")))));
  90. EXPECT_EQ(result::SUCCESS, memory_client.addZone(
  91. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::IN(),
  92. Name("z.d.e.f")))));
  93. EXPECT_EQ(result::SUCCESS, memory_client.addZone(
  94. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::IN(),
  95. Name("j.z.d.e.f")))));
  96. // different zone class isn't allowed.
  97. EXPECT_EQ(result::EXIST, memory_client.addZone(
  98. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::CH(),
  99. Name("q.w.y.d.e.f")))));
  100. // names are compared in a case insensitive manner.
  101. EXPECT_EQ(result::EXIST, memory_client.addZone(
  102. ZoneFinderPtr(new InMemoryZoneFinder(RRClass::IN(),
  103. Name("Q.W.Y.d.E.f")))));
  104. // test find zone
  105. EXPECT_EQ(result::SUCCESS, memory_client.findZone(Name("a")).code);
  106. EXPECT_EQ(Name("a"),
  107. memory_client.findZone(Name("a")).zone_finder->getOrigin());
  108. EXPECT_EQ(result::SUCCESS,
  109. memory_client.findZone(Name("j.z.d.e.f")).code);
  110. EXPECT_EQ(Name("j.z.d.e.f"),
  111. memory_client.findZone(Name("j.z.d.e.f")).zone_finder->
  112. getOrigin());
  113. // NOTFOUND
  114. EXPECT_EQ(result::NOTFOUND, memory_client.findZone(Name("d.e.f")).code);
  115. EXPECT_EQ(ConstZoneFinderPtr(),
  116. memory_client.findZone(Name("d.e.f")).zone_finder);
  117. EXPECT_EQ(result::NOTFOUND,
  118. memory_client.findZone(Name("w.y.d.e.f")).code);
  119. EXPECT_EQ(ConstZoneFinderPtr(),
  120. memory_client.findZone(Name("w.y.d.e.f")).zone_finder);
  121. // there's no exact match. the result should be the longest match,
  122. // and the code should be PARTIALMATCH.
  123. EXPECT_EQ(result::PARTIALMATCH,
  124. memory_client.findZone(Name("j.g.h")).code);
  125. EXPECT_EQ(Name("g.h"),
  126. memory_client.findZone(Name("g.h")).zone_finder->getOrigin());
  127. EXPECT_EQ(result::PARTIALMATCH,
  128. memory_client.findZone(Name("z.i.g.h")).code);
  129. EXPECT_EQ(Name("i.g.h"),
  130. memory_client.findZone(Name("z.i.g.h")).zone_finder->
  131. getOrigin());
  132. }
  133. TEST_F(InMemoryClientTest, iterator) {
  134. // Just some preparations of data
  135. boost::shared_ptr<InMemoryZoneFinder>
  136. zone(new InMemoryZoneFinder(RRClass::IN(), Name("a")));
  137. RRsetPtr aRRsetA(new RRset(Name("a"), RRClass::IN(), RRType::A(),
  138. RRTTL(300)));
  139. aRRsetA->addRdata(rdata::in::A("192.0.2.1"));
  140. RRsetPtr aRRsetAAAA(new RRset(Name("a"), RRClass::IN(), RRType::AAAA(),
  141. RRTTL(300)));
  142. aRRsetAAAA->addRdata(rdata::in::AAAA("2001:db8::1"));
  143. aRRsetAAAA->addRdata(rdata::in::AAAA("2001:db8::2"));
  144. RRsetPtr subRRsetA(new RRset(Name("sub.x.a"), RRClass::IN(), RRType::A(),
  145. RRTTL(300)));
  146. subRRsetA->addRdata(rdata::in::A("192.0.2.2"));
  147. EXPECT_EQ(result::SUCCESS, memory_client.addZone(zone));
  148. // First, the zone is not there, so it should throw
  149. EXPECT_THROW(memory_client.getIterator(Name("b")), DataSourceError);
  150. // This zone is not there either, even when there's a zone containing this
  151. EXPECT_THROW(memory_client.getIterator(Name("x.a")), DataSourceError);
  152. // Now, an empty zone
  153. ZoneIteratorPtr iterator(memory_client.getIterator(Name("a")));
  154. EXPECT_EQ(ConstRRsetPtr(), iterator->getNextRRset());
  155. // It throws Unexpected when we are past the end
  156. EXPECT_THROW(iterator->getNextRRset(), isc::Unexpected);
  157. EXPECT_EQ(result::SUCCESS, zone->add(aRRsetA));
  158. EXPECT_EQ(result::SUCCESS, zone->add(aRRsetAAAA));
  159. EXPECT_EQ(result::SUCCESS, zone->add(subRRsetA));
  160. // Check it with full zone.
  161. vector<ConstRRsetPtr> expected_rrsets;
  162. expected_rrsets.push_back(aRRsetA);
  163. expected_rrsets.push_back(aRRsetAAAA);
  164. expected_rrsets.push_back(subRRsetA);
  165. iterator = memory_client.getIterator(Name("a"));
  166. vector<ConstRRsetPtr> actual_rrsets;
  167. ConstRRsetPtr actual;
  168. while ((actual = iterator->getNextRRset()) != NULL) {
  169. actual_rrsets.push_back(actual);
  170. }
  171. rrsetsCheck(expected_rrsets.begin(), expected_rrsets.end(),
  172. actual_rrsets.begin(), actual_rrsets.end());
  173. }
  174. TEST_F(InMemoryClientTest, iterator_separate_rrs) {
  175. // Exactly the same tests as for iterator, but now with separate_rrs = true
  176. // For the one that returns actual data, the AAAA should now be split up
  177. boost::shared_ptr<InMemoryZoneFinder>
  178. zone(new InMemoryZoneFinder(RRClass::IN(), Name("a")));
  179. RRsetPtr aRRsetA(new RRset(Name("a"), RRClass::IN(), RRType::A(),
  180. RRTTL(300)));
  181. aRRsetA->addRdata(rdata::in::A("192.0.2.1"));
  182. RRsetPtr aRRsetAAAA(new RRset(Name("a"), RRClass::IN(), RRType::AAAA(),
  183. RRTTL(300)));
  184. aRRsetAAAA->addRdata(rdata::in::AAAA("2001:db8::1"));
  185. aRRsetAAAA->addRdata(rdata::in::AAAA("2001:db8::2"));
  186. RRsetPtr aRRsetAAAA_r1(new RRset(Name("a"), RRClass::IN(), RRType::AAAA(),
  187. RRTTL(300)));
  188. aRRsetAAAA_r1->addRdata(rdata::in::AAAA("2001:db8::1"));
  189. RRsetPtr aRRsetAAAA_r2(new RRset(Name("a"), RRClass::IN(), RRType::AAAA(),
  190. RRTTL(300)));
  191. aRRsetAAAA_r2->addRdata(rdata::in::AAAA("2001:db8::2"));
  192. RRsetPtr subRRsetA(new RRset(Name("sub.x.a"), RRClass::IN(), RRType::A(),
  193. RRTTL(300)));
  194. subRRsetA->addRdata(rdata::in::A("192.0.2.2"));
  195. EXPECT_EQ(result::SUCCESS, memory_client.addZone(zone));
  196. // First, the zone is not there, so it should throw
  197. EXPECT_THROW(memory_client.getIterator(Name("b"), true), DataSourceError);
  198. // This zone is not there either, even when there's a zone containing this
  199. EXPECT_THROW(memory_client.getIterator(Name("x.a")), DataSourceError);
  200. // Now, an empty zone
  201. ZoneIteratorPtr iterator(memory_client.getIterator(Name("a"), true));
  202. EXPECT_EQ(ConstRRsetPtr(), iterator->getNextRRset());
  203. // It throws Unexpected when we are past the end
  204. EXPECT_THROW(iterator->getNextRRset(), isc::Unexpected);
  205. ASSERT_EQ(result::SUCCESS, zone->add(aRRsetA));
  206. ASSERT_EQ(result::SUCCESS, zone->add(aRRsetAAAA));
  207. ASSERT_EQ(result::SUCCESS, zone->add(subRRsetA));
  208. // Check it with full zone, one by one.
  209. // It should be in ascending order in case of InMemory data source
  210. // (isn't guaranteed in general)
  211. iterator = memory_client.getIterator(Name("a"), true);
  212. EXPECT_EQ(aRRsetA->toText(), iterator->getNextRRset()->toText());
  213. EXPECT_EQ(aRRsetAAAA_r1->toText(), iterator->getNextRRset()->toText());
  214. EXPECT_EQ(aRRsetAAAA_r2->toText(), iterator->getNextRRset()->toText());
  215. EXPECT_EQ(subRRsetA->toText(), iterator->getNextRRset()->toText());
  216. EXPECT_EQ(ConstRRsetPtr(), iterator->getNextRRset());
  217. }
  218. TEST_F(InMemoryClientTest, getZoneCount) {
  219. EXPECT_EQ(0, memory_client.getZoneCount());
  220. memory_client.addZone(
  221. ZoneFinderPtr(new InMemoryZoneFinder(rrclass,
  222. Name("example.com"))));
  223. EXPECT_EQ(1, memory_client.getZoneCount());
  224. // duplicate add. counter shouldn't change
  225. memory_client.addZone(
  226. ZoneFinderPtr(new InMemoryZoneFinder(rrclass,
  227. Name("example.com"))));
  228. EXPECT_EQ(1, memory_client.getZoneCount());
  229. // add one more
  230. memory_client.addZone(
  231. ZoneFinderPtr(new InMemoryZoneFinder(rrclass,
  232. Name("example.org"))));
  233. EXPECT_EQ(2, memory_client.getZoneCount());
  234. }
  235. TEST_F(InMemoryClientTest, startUpdateZone) {
  236. EXPECT_THROW(memory_client.getUpdater(Name("example.org"), false),
  237. isc::NotImplemented);
  238. }
  239. // Commonly used RRSIG data
  240. const char* const rrsig_a_txt =
  241. "example.org. 300 IN RRSIG A 5 3 3600 20000101000000 20000201000000 12345 "
  242. "example.org. FAKEFAKEFAKE\n";
  243. const char* const rrsig_ns_txt =
  244. "example.org. 300 IN RRSIG NS 5 3 3600 20000101000000 20000201000000 "
  245. "54321 example.org. FAKEFAKEFAKEFAKE\n";
  246. // This RRset has two RRSIGs
  247. const char* const rrsig_aaaa_txt =
  248. "ns.example.org. 300 IN RRSIG AAAA 5 3 3600 20000101000000 20000201000000 "
  249. "12345 example.org. FAKEFAKEFAKE\n"
  250. "ns.example.org. 300 IN RRSIG AAAA 5 3 3600 20000101000000 20000201000000 "
  251. "54321 example.org. FAKEFAKEFAKEFAKE\n";
  252. // A helper callback of masterLoad() used in InMemoryZoneFinderTest.
  253. void
  254. setRRset(RRsetPtr rrset, vector<RRsetPtr*>::iterator& it) {
  255. *(*it) = rrset;
  256. ++it;
  257. }
  258. // Some faked NSEC3 hash values commonly used in tests and the faked NSEC3Hash
  259. // object.
  260. //
  261. // For apex (example.org)
  262. const char* const apex_hash = "0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM";
  263. const char* const apex_hash_lower = "0p9mhaveqvm6t7vbl5lop2u3t2rp3tom";
  264. // For ns1.example.org
  265. const char* const ns1_hash = "2T7B4G4VSA5SMI47K61MV5BV1A22BOJR";
  266. // For w.example.org
  267. const char* const w_hash = "01UDEMVP1J2F7EG6JEBPS17VP3N8I58H";
  268. // For x.y.w.example.org (lower-cased)
  269. const char* const xyw_hash = "2vptu5timamqttgl4luu9kg21e0aor3s";
  270. // For zzz.example.org.
  271. const char* const zzz_hash = "R53BQ7CC2UVMUBFU5OCMM6PERS9TK9EN";
  272. // A simple faked NSEC3 hash calculator with a dedicated creator for it.
  273. //
  274. // This is used in some NSEC3-related tests below.
  275. class TestNSEC3HashCreator : public NSEC3HashCreator {
  276. class TestNSEC3Hash : public NSEC3Hash {
  277. private:
  278. typedef map<Name, string> NSEC3HashMap;
  279. typedef NSEC3HashMap::value_type NSEC3HashPair;
  280. NSEC3HashMap map_;
  281. public:
  282. TestNSEC3Hash() {
  283. // Build pre-defined hash
  284. map_[Name("example.org")] = apex_hash;
  285. map_[Name("www.example.org")] = "2S9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM";
  286. map_[Name("xxx.example.org")] = "Q09MHAVEQVM6T7VBL5LOP2U3T2RP3TOM";
  287. map_[Name("yyy.example.org")] = "0A9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM";
  288. map_[Name("x.y.w.example.org")] =
  289. "2VPTU5TIMAMQTTGL4LUU9KG21E0AOR3S";
  290. map_[Name("y.w.example.org")] = "K8UDEMVP1J2F7EG6JEBPS17VP3N8I58H";
  291. map_[Name("w.example.org")] = w_hash;
  292. map_[Name("zzz.example.org")] = zzz_hash;
  293. map_[Name("smallest.example.org")] =
  294. "00000000000000000000000000000000";
  295. map_[Name("largest.example.org")] =
  296. "UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU";
  297. }
  298. virtual string calculate(const Name& name) const {
  299. const NSEC3HashMap::const_iterator found = map_.find(name);
  300. if (found != map_.end()) {
  301. return (found->second);
  302. }
  303. isc_throw(isc::Unexpected, "unexpected name for NSEC3 test: "
  304. << name);
  305. }
  306. virtual bool match(const generic::NSEC3PARAM&) const {
  307. return (true);
  308. }
  309. virtual bool match(const generic::NSEC3&) const {
  310. return (true);
  311. }
  312. };
  313. public:
  314. virtual NSEC3Hash* create(const generic::NSEC3PARAM&) const {
  315. return (new TestNSEC3Hash);
  316. }
  317. virtual NSEC3Hash* create(const generic::NSEC3&) const {
  318. return (new TestNSEC3Hash);
  319. }
  320. };
  321. /// \brief Test fixture for the InMemoryZoneFinder class
  322. class InMemoryZoneFinderTest : public ::testing::Test {
  323. // A straightforward pair of textual RR(set) and a RRsetPtr variable
  324. // to store the RRset. Used to build test data below.
  325. struct RRsetData {
  326. const char* const text; // textual representation of an RRset
  327. RRsetPtr* rrset;
  328. };
  329. protected:
  330. // The following sub tests are shared by multiple test cases, changing
  331. // the zone's DNSSEC status (unsigned, NSEC-signed or NSEC3-signed).
  332. // expected_flags is set to either RESULT_NSEC_SIGNED or
  333. // RESULT_NSEC3_SIGNED when it's NSEC/NSEC3 signed respectively and
  334. // find() is expected to set the corresponding flags.
  335. // find_options should be set to FIND_DNSSEC for NSEC-signed case when
  336. // NSEC is expected to be returned.
  337. void findCheck(ZoneFinder::FindResultFlags expected_flags =
  338. ZoneFinder::RESULT_DEFAULT,
  339. ZoneFinder::FindOptions find_options =
  340. ZoneFinder::FIND_DEFAULT);
  341. void emptyNodeCheck(ZoneFinder::FindResultFlags expected_flags =
  342. ZoneFinder::RESULT_DEFAULT);
  343. void wildcardCheck(ZoneFinder::FindResultFlags expected_flags =
  344. ZoneFinder::RESULT_DEFAULT,
  345. ZoneFinder::FindOptions find_options =
  346. ZoneFinder::FIND_DEFAULT);
  347. void doCancelWildcardCheck(ZoneFinder::FindResultFlags expected_flags =
  348. ZoneFinder::RESULT_DEFAULT,
  349. ZoneFinder::FindOptions find_options =
  350. ZoneFinder::FIND_DEFAULT);
  351. void anyWildcardCheck(ZoneFinder::FindResultFlags expected_flags =
  352. ZoneFinder::RESULT_DEFAULT);
  353. void emptyWildcardCheck(ZoneFinder::FindResultFlags expected_flags =
  354. ZoneFinder::RESULT_DEFAULT);
  355. public:
  356. InMemoryZoneFinderTest() :
  357. class_(RRClass::IN()),
  358. origin_("example.org"),
  359. zone_finder_(class_, origin_)
  360. {
  361. // Build test RRsets. Below, we construct an RRset for
  362. // each textual RR(s) of zone_data, and assign it to the corresponding
  363. // rr_xxx.
  364. // Note that this contains an out-of-zone RR, and due to the
  365. // validation check of masterLoad() used below, we cannot add SOA.
  366. const RRsetData zone_data[] = {
  367. {"example.org. 300 IN NS ns.example.org.", &rr_ns_},
  368. {"example.org. 300 IN A 192.0.2.1", &rr_a_},
  369. {"ns.example.org. 300 IN A 192.0.2.2", &rr_ns_a_},
  370. {"ns.example.org. 300 IN AAAA 2001:db8::2", &rr_ns_aaaa_},
  371. {"cname.example.org. 300 IN CNAME canonical.example.org",
  372. &rr_cname_},
  373. {"cname.example.org. 300 IN A 192.0.2.3", &rr_cname_a_},
  374. {"dname.example.org. 300 IN DNAME target.example.org.",
  375. &rr_dname_},
  376. {"dname.example.org. 300 IN A 192.0.2.39", &rr_dname_a_},
  377. {"dname.example.org. 300 IN NS ns.dname.example.org.",
  378. &rr_dname_ns_},
  379. {"example.org. 300 IN DNAME example.com.", &rr_dname_apex_},
  380. {"child.example.org. 300 IN NS ns.child.example.org.",
  381. &rr_child_ns_},
  382. {"child.example.org. 300 IN DS 12345 5 1 DEADBEEF",
  383. &rr_child_ds_},
  384. {"ns.child.example.org. 300 IN A 192.0.2.153",
  385. &rr_child_glue_},
  386. {"grand.child.example.org. 300 IN NS ns.grand.child.example.org.",
  387. &rr_grandchild_ns_},
  388. {"ns.grand.child.example.org. 300 IN AAAA 2001:db8::253",
  389. &rr_grandchild_glue_},
  390. {"dname.child.example.org. 300 IN DNAME example.com.",
  391. &rr_child_dname_},
  392. {"example.com. 300 IN A 192.0.2.10", &rr_out_},
  393. {"*.wild.example.org. 300 IN A 192.0.2.1", &rr_wild_},
  394. {"*.cnamewild.example.org. 300 IN CNAME canonial.example.org.",
  395. &rr_cnamewild_},
  396. {"foo.wild.example.org. 300 IN A 192.0.2.3", &rr_under_wild_},
  397. {"wild.*.foo.example.org. 300 IN A 192.0.2.1", &rr_emptywild_},
  398. {"wild.*.foo.*.bar.example.org. 300 IN A 192.0.2.1",
  399. &rr_nested_emptywild_},
  400. {"*.nswild.example.org. 300 IN NS nswild.example.", &rr_nswild_},
  401. {"*.dnamewild.example.org. 300 IN DNAME dnamewild.example.",
  402. &rr_dnamewild_},
  403. {"*.child.example.org. 300 IN A 192.0.2.1", &rr_child_wild_},
  404. {"bar.foo.wild.example.org. 300 IN A 192.0.2.2", &rr_not_wild_},
  405. {"baz.foo.wild.example.org. 300 IN A 192.0.2.3",
  406. &rr_not_wild_another_},
  407. {"0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM.example.org. 300 IN "
  408. "NSEC3 1 1 12 aabbccdd 2T7B4G4VSA5SMI47K61MV5BV1A22BOJR A RRSIG",
  409. &rr_nsec3_},
  410. {"example.org. 300 IN NSEC cname.example.org. A NS NSEC",
  411. &rr_nsec_},
  412. {"ns.example.org. 300 IN NSEC *.nswild.example.org. A AAAA NSEC",
  413. &rr_ns_nsec_},
  414. {NULL, NULL}
  415. };
  416. stringstream zone_data_stream;
  417. vector<RRsetPtr*> rrsets;
  418. for (unsigned int i = 0; zone_data[i].text != NULL; ++i) {
  419. zone_data_stream << zone_data[i].text << "\n";
  420. rrsets.push_back(zone_data[i].rrset);
  421. }
  422. masterLoad(zone_data_stream, Name::ROOT_NAME(), class_,
  423. boost::bind(setRRset, _1, rrsets.begin()));
  424. }
  425. ~InMemoryZoneFinderTest() {
  426. // Make sure we reset the hash creator to the default
  427. setNSEC3HashCreator(NULL);
  428. }
  429. // Some data to test with
  430. const RRClass class_;
  431. const Name origin_;
  432. // The zone finder to torture by tests
  433. InMemoryZoneFinder zone_finder_;
  434. // Placeholder for storing RRsets to be checked with rrsetsCheck()
  435. vector<ConstRRsetPtr> actual_rrsets_;
  436. /*
  437. * Some RRsets to put inside the zone.
  438. */
  439. RRsetPtr
  440. // Out of zone RRset
  441. rr_out_,
  442. // NS of example.org
  443. rr_ns_,
  444. // A of ns.example.org
  445. rr_ns_a_,
  446. // AAAA of ns.example.org
  447. rr_ns_aaaa_,
  448. // A of example.org
  449. rr_a_;
  450. RRsetPtr rr_cname_; // CNAME in example.org (RDATA will be added)
  451. RRsetPtr rr_cname_a_; // for mixed CNAME + A case
  452. RRsetPtr rr_dname_; // DNAME in example.org (RDATA will be added)
  453. RRsetPtr rr_dname_a_; // for mixed DNAME + A case
  454. RRsetPtr rr_dname_ns_; // for mixed DNAME + NS case
  455. RRsetPtr rr_dname_apex_; // for mixed DNAME + NS case in the apex
  456. RRsetPtr rr_child_ns_; // NS of a child domain (for delegation)
  457. RRsetPtr rr_child_ds_; // DS of a child domain (for delegation, auth data)
  458. RRsetPtr rr_child_glue_; // glue RR of the child domain
  459. RRsetPtr rr_grandchild_ns_; // NS below a zone cut (unusual)
  460. RRsetPtr rr_grandchild_glue_; // glue RR below a deeper zone cut
  461. RRsetPtr rr_child_dname_; // A DNAME under NS
  462. RRsetPtr rr_wild_; // Wildcard record
  463. RRsetPtr rr_cnamewild_; // CNAME at a wildcard
  464. RRsetPtr rr_emptywild_;
  465. RRsetPtr rr_nested_emptywild_;
  466. RRsetPtr rr_nswild_, rr_dnamewild_;
  467. RRsetPtr rr_child_wild_;
  468. RRsetPtr rr_under_wild_;
  469. RRsetPtr rr_not_wild_;
  470. RRsetPtr rr_not_wild_another_;
  471. RRsetPtr rr_nsec3_;
  472. RRsetPtr rr_nsec_;
  473. RRsetPtr rr_ns_nsec_;
  474. // A faked NSEC3 hash calculator for convenience.
  475. // Tests that need to use the faked hashed values should call
  476. // setNSEC3HashCreator() with a pointer to this variable at the beginning
  477. // of the test (at least before adding any NSEC3/NSEC3PARAM RR).
  478. TestNSEC3HashCreator nsec3_hash_creator_;
  479. /**
  480. * \brief Test one find query to the zone finder.
  481. *
  482. * Asks a query to the zone finder and checks it does not throw and returns
  483. * expected results. It returns nothing, it just signals failures
  484. * to GTEST.
  485. *
  486. * \param name The name to ask for.
  487. * \param rrtype The RRType to ask of.
  488. * \param result The expected code of the result.
  489. * \param check_answer Should a check against equality of the answer be
  490. * done?
  491. * \param answer The expected rrset, if any should be returned.
  492. * \param expected_flags The expected result flags returned via find().
  493. * These can be tested using isWildcard() etc.
  494. * \param zone_finder Check different InMemoryZoneFinder object than
  495. * zone_finder_ (if NULL, uses zone_finder_)
  496. * \param check_wild_answer Checks that the answer has the same RRs, type
  497. * class and TTL as the eqxpected answer and that the name corresponds
  498. * to the one searched. It is meant for checking answers for wildcard
  499. * queries.
  500. */
  501. void findTest(const Name& name, const RRType& rrtype,
  502. ZoneFinder::Result result,
  503. bool check_answer = true,
  504. const ConstRRsetPtr& answer = ConstRRsetPtr(),
  505. ZoneFinder::FindResultFlags expected_flags =
  506. ZoneFinder::RESULT_DEFAULT,
  507. InMemoryZoneFinder* zone_finder = NULL,
  508. ZoneFinder::FindOptions options = ZoneFinder::FIND_DEFAULT,
  509. bool check_wild_answer = false)
  510. {
  511. SCOPED_TRACE("findTest for " + name.toText() + "/" + rrtype.toText());
  512. if (zone_finder == NULL) {
  513. zone_finder = &zone_finder_;
  514. }
  515. const ConstRRsetPtr answer_sig = answer ? answer->getRRsig() :
  516. RRsetPtr(); // note we use the same type as of retval of getRRsig()
  517. // The whole block is inside, because we need to check the result and
  518. // we can't assign to FindResult
  519. EXPECT_NO_THROW({
  520. ZoneFinderContextPtr find_result(zone_finder->find(
  521. name, rrtype, options));
  522. // Check it returns correct answers
  523. EXPECT_EQ(result, find_result->code);
  524. EXPECT_EQ((expected_flags & ZoneFinder::RESULT_WILDCARD) != 0,
  525. find_result->isWildcard());
  526. EXPECT_EQ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED)
  527. != 0, find_result->isNSECSigned());
  528. EXPECT_EQ((expected_flags & ZoneFinder::RESULT_NSEC3_SIGNED)
  529. != 0, find_result->isNSEC3Signed());
  530. if (check_answer) {
  531. if (!answer) {
  532. ASSERT_FALSE(find_result->rrset);
  533. } else {
  534. ASSERT_TRUE(find_result->rrset);
  535. rrsetCheck(answer, find_result->rrset);
  536. if (answer_sig) {
  537. ASSERT_TRUE(find_result->rrset->getRRsig());
  538. rrsetCheck(answer_sig,
  539. find_result->rrset->getRRsig());
  540. }
  541. }
  542. } else if (check_wild_answer) {
  543. ASSERT_NE(ConstRRsetPtr(), answer) <<
  544. "Wrong test, don't check for wild names if you expect "
  545. "empty answer";
  546. ASSERT_NE(ConstRRsetPtr(), find_result->rrset) <<
  547. "No answer found";
  548. // Build the expected answer using the given name and
  549. // other parameter of the base wildcard RRset.
  550. RRsetPtr wildanswer(new RRset(name, answer->getClass(),
  551. answer->getType(),
  552. answer->getTTL()));
  553. RdataIteratorPtr expectedIt(answer->getRdataIterator());
  554. for (; !expectedIt->isLast(); expectedIt->next()) {
  555. wildanswer->addRdata(expectedIt->getCurrent());
  556. }
  557. rrsetCheck(wildanswer, find_result->rrset);
  558. // Same for the RRSIG, if any.
  559. if (answer_sig) {
  560. ASSERT_TRUE(find_result->rrset->getRRsig());
  561. RRsetPtr wildsig(new RRset(name,
  562. answer_sig->getClass(),
  563. RRType::RRSIG(),
  564. answer_sig->getTTL()));
  565. RdataIteratorPtr expectedIt(
  566. answer_sig->getRdataIterator());
  567. for (; !expectedIt->isLast(); expectedIt->next()) {
  568. wildsig->addRdata(expectedIt->getCurrent());
  569. }
  570. rrsetCheck(wildsig, find_result->rrset->getRRsig());
  571. }
  572. }
  573. });
  574. }
  575. /**
  576. * \brief Calls the findAll on the finder and checks the result.
  577. */
  578. void findAllTest(const Name& name, ZoneFinder::Result result,
  579. const vector<ConstRRsetPtr>& expected_rrsets,
  580. ZoneFinder::FindResultFlags expected_flags =
  581. ZoneFinder::RESULT_DEFAULT,
  582. InMemoryZoneFinder* finder = NULL,
  583. const ConstRRsetPtr &rrset_result = ConstRRsetPtr(),
  584. ZoneFinder::FindOptions options =
  585. ZoneFinder::FIND_DEFAULT)
  586. {
  587. if (finder == NULL) {
  588. finder = &zone_finder_;
  589. }
  590. std::vector<ConstRRsetPtr> target;
  591. ZoneFinderContextPtr find_result(finder->findAll(name, target,
  592. options));
  593. EXPECT_EQ(result, find_result->code);
  594. if (!rrset_result) {
  595. EXPECT_FALSE(find_result->rrset);
  596. } else {
  597. ASSERT_TRUE(find_result->rrset);
  598. rrsetCheck(rrset_result, find_result->rrset);
  599. }
  600. EXPECT_EQ((expected_flags & ZoneFinder::RESULT_WILDCARD) != 0,
  601. find_result->isWildcard());
  602. EXPECT_EQ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED)
  603. != 0, find_result->isNSECSigned());
  604. EXPECT_EQ((expected_flags & ZoneFinder::RESULT_NSEC3_SIGNED)
  605. != 0, find_result->isNSEC3Signed());
  606. rrsetsCheck(expected_rrsets.begin(), expected_rrsets.end(),
  607. target.begin(), target.end());
  608. }
  609. };
  610. /**
  611. * \brief Check that findPreviousName throws as it should now.
  612. */
  613. TEST_F(InMemoryZoneFinderTest, findPreviousName) {
  614. EXPECT_THROW(zone_finder_.findPreviousName(Name("www.example.org")),
  615. isc::NotImplemented);
  616. }
  617. /**
  618. * \brief Test InMemoryZoneFinder::InMemoryZoneFinder constructor.
  619. *
  620. * Takes the created zone finder and checks its properties they are the same
  621. * as passed parameters.
  622. */
  623. TEST_F(InMemoryZoneFinderTest, constructor) {
  624. ASSERT_EQ(class_, zone_finder_.getClass());
  625. ASSERT_EQ(origin_, zone_finder_.getOrigin());
  626. }
  627. /**
  628. * \brief Test adding.
  629. *
  630. * We test that it throws at the correct moments and the correct exceptions.
  631. * And we test the return value.
  632. */
  633. TEST_F(InMemoryZoneFinderTest, add) {
  634. // This one does not belong to this zone
  635. EXPECT_THROW(zone_finder_.add(rr_out_), OutOfZone);
  636. // Test null pointer
  637. EXPECT_THROW(zone_finder_.add(ConstRRsetPtr()),
  638. InMemoryZoneFinder::NullRRset);
  639. // Now put all the data we have there. It should throw nothing
  640. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_)));
  641. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_a_)));
  642. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_aaaa_)));
  643. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_a_)));
  644. // Try putting there something twice, it should be rejected
  645. EXPECT_NO_THROW(EXPECT_EQ(EXIST, zone_finder_.add(rr_ns_)));
  646. EXPECT_NO_THROW(EXPECT_EQ(EXIST, zone_finder_.add(rr_ns_a_)));
  647. }
  648. TEST_F(InMemoryZoneFinderTest, addMultipleCNAMEs) {
  649. rr_cname_->addRdata(generic::CNAME("canonical2.example.org."));
  650. EXPECT_THROW(zone_finder_.add(rr_cname_), InMemoryZoneFinder::AddError);
  651. }
  652. TEST_F(InMemoryZoneFinderTest, addCNAMEThenOther) {
  653. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_cname_));
  654. EXPECT_THROW(zone_finder_.add(rr_cname_a_), InMemoryZoneFinder::AddError);
  655. }
  656. TEST_F(InMemoryZoneFinderTest, addOtherThenCNAME) {
  657. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_cname_a_));
  658. EXPECT_THROW(zone_finder_.add(rr_cname_), InMemoryZoneFinder::AddError);
  659. }
  660. TEST_F(InMemoryZoneFinderTest, addCNAMEAndDNSSECRecords) {
  661. // CNAME and RRSIG can coexist
  662. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_cname_));
  663. EXPECT_EQ(SUCCESS, zone_finder_.add(
  664. textToRRset("cname.example.org. 300 IN RRSIG CNAME 5 3 "
  665. "3600 20000101000000 20000201000000 12345 "
  666. "example.org. FAKEFAKEFAKE")));
  667. // Same for NSEC
  668. EXPECT_EQ(SUCCESS, zone_finder_.add(
  669. textToRRset("cname.example.org. 300 IN NSEC "
  670. "dname.example.org. CNAME RRSIG NSEC")));
  671. // Same as above, but adding NSEC first.
  672. EXPECT_EQ(SUCCESS, zone_finder_.add(
  673. textToRRset("cname2.example.org. 300 IN NSEC "
  674. "dname.example.org. CNAME RRSIG NSEC")));
  675. EXPECT_EQ(SUCCESS, zone_finder_.add(
  676. textToRRset("cname2.example.org. 300 IN CNAME c.example.")));
  677. // If there's another type of RRset with NSEC, it should still fail.
  678. EXPECT_EQ(SUCCESS, zone_finder_.add(
  679. textToRRset("cname3.example.org. 300 IN A 192.0.2.1")));
  680. EXPECT_EQ(SUCCESS, zone_finder_.add(
  681. textToRRset("cname3.example.org. 300 IN NSEC "
  682. "dname.example.org. CNAME RRSIG NSEC")));
  683. EXPECT_THROW(zone_finder_.add(textToRRset("cname3.example.org. 300 "
  684. "IN CNAME c.example.")),
  685. InMemoryZoneFinder::AddError);
  686. }
  687. TEST_F(InMemoryZoneFinderTest, findCNAME) {
  688. // install CNAME RR
  689. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_cname_));
  690. // Find A RR of the same. Should match the CNAME
  691. findTest(rr_cname_->getName(), RRType::NS(), ZoneFinder::CNAME, true,
  692. rr_cname_);
  693. // Find the CNAME itself. Should result in normal SUCCESS
  694. findTest(rr_cname_->getName(), RRType::CNAME(), ZoneFinder::SUCCESS, true,
  695. rr_cname_);
  696. }
  697. TEST_F(InMemoryZoneFinderTest, findCNAMEUnderZoneCut) {
  698. // There's nothing special when we find a CNAME under a zone cut
  699. // (with FIND_GLUE_OK). The behavior is different from BIND 9,
  700. // so we test this case explicitly.
  701. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_ns_));
  702. ConstRRsetPtr rr_cname_under_cut_ = textToRRset(
  703. "cname.child.example.org. 300 IN CNAME target.child.example.org.");
  704. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_cname_under_cut_));
  705. findTest(Name("cname.child.example.org"), RRType::AAAA(),
  706. ZoneFinder::CNAME, true, rr_cname_under_cut_,
  707. ZoneFinder::RESULT_DEFAULT, NULL, ZoneFinder::FIND_GLUE_OK);
  708. }
  709. // Two DNAMEs at single domain are disallowed by RFC 2672, section 3)
  710. // Having a CNAME there is disallowed too, but it is tested by
  711. // addOtherThenCNAME and addCNAMEThenOther.
  712. TEST_F(InMemoryZoneFinderTest, addMultipleDNAMEs) {
  713. rr_dname_->addRdata(generic::DNAME("target2.example.org."));
  714. EXPECT_THROW(zone_finder_.add(rr_dname_), InMemoryZoneFinder::AddError);
  715. }
  716. /*
  717. * These two tests ensure that we can't have DNAME and NS at the same
  718. * node with the exception of the apex of zone (forbidden by RFC 2672)
  719. */
  720. TEST_F(InMemoryZoneFinderTest, addDNAMEThenNS) {
  721. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_dname_)));
  722. EXPECT_THROW(zone_finder_.add(rr_dname_ns_), InMemoryZoneFinder::AddError);
  723. }
  724. TEST_F(InMemoryZoneFinderTest, addNSThenDNAME) {
  725. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_dname_ns_)));
  726. EXPECT_THROW(zone_finder_.add(rr_dname_), InMemoryZoneFinder::AddError);
  727. }
  728. // It is allowed to have NS and DNAME at apex
  729. TEST_F(InMemoryZoneFinderTest, DNAMEAndNSAtApex) {
  730. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_dname_apex_)));
  731. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_)));
  732. // The NS should be possible to be found, below should be DNAME, not
  733. // delegation
  734. findTest(origin_, RRType::NS(), ZoneFinder::SUCCESS, true, rr_ns_);
  735. findTest(rr_child_ns_->getName(), RRType::A(), ZoneFinder::DNAME, true,
  736. rr_dname_apex_);
  737. }
  738. TEST_F(InMemoryZoneFinderTest, NSAndDNAMEAtApex) {
  739. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_)));
  740. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_dname_apex_)));
  741. }
  742. // TODO: Test (and implement) adding data under DNAME. That is forbidden by
  743. // 2672 as well.
  744. // Search under a DNAME record. It should return the DNAME
  745. TEST_F(InMemoryZoneFinderTest, findBelowDNAME) {
  746. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_dname_)));
  747. findTest(Name("below.dname.example.org"), RRType::A(), ZoneFinder::DNAME,
  748. true, rr_dname_);
  749. }
  750. // Search at the domain with DNAME. It should act as DNAME isn't there, DNAME
  751. // influences only the data below (see RFC 2672, section 3)
  752. TEST_F(InMemoryZoneFinderTest, findAtDNAME) {
  753. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_dname_)));
  754. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_dname_a_)));
  755. const Name dname_name(rr_dname_->getName());
  756. findTest(dname_name, RRType::A(), ZoneFinder::SUCCESS, true, rr_dname_a_);
  757. findTest(dname_name, RRType::DNAME(), ZoneFinder::SUCCESS, true,
  758. rr_dname_);
  759. findTest(dname_name, RRType::TXT(), ZoneFinder::NXRRSET, true);
  760. }
  761. // Try searching something that is both under NS and DNAME, without and with
  762. // GLUE_OK mode (it should stop at the NS and DNAME respectively).
  763. TEST_F(InMemoryZoneFinderTest, DNAMEUnderNS) {
  764. zone_finder_.add(rr_child_ns_);
  765. zone_finder_.add(rr_child_dname_);
  766. Name lowName("below.dname.child.example.org.");
  767. findTest(lowName, RRType::A(), ZoneFinder::DELEGATION, true, rr_child_ns_);
  768. findTest(lowName, RRType::A(), ZoneFinder::DNAME, true, rr_child_dname_,
  769. ZoneFinder::RESULT_DEFAULT, NULL, ZoneFinder::FIND_GLUE_OK);
  770. }
  771. // Test adding child zones and zone cut handling
  772. TEST_F(InMemoryZoneFinderTest, delegationNS) {
  773. // add in-zone data
  774. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_)));
  775. // install a zone cut
  776. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_ns_)));
  777. // below the zone cut
  778. findTest(Name("www.child.example.org"), RRType::A(),
  779. ZoneFinder::DELEGATION, true, rr_child_ns_);
  780. // at the zone cut
  781. findTest(Name("child.example.org"), RRType::A(), ZoneFinder::DELEGATION,
  782. true, rr_child_ns_);
  783. findTest(Name("child.example.org"), RRType::NS(), ZoneFinder::DELEGATION,
  784. true, rr_child_ns_);
  785. // finding NS for the apex (origin) node. This must not be confused
  786. // with delegation due to the existence of an NS RR.
  787. findTest(origin_, RRType::NS(), ZoneFinder::SUCCESS, true, rr_ns_);
  788. // unusual case of "nested delegation": the highest cut should be used.
  789. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_grandchild_ns_)));
  790. findTest(Name("www.grand.child.example.org"), RRType::A(),
  791. // note: !rr_grandchild_ns_
  792. ZoneFinder::DELEGATION, true, rr_child_ns_);
  793. }
  794. TEST_F(InMemoryZoneFinderTest, delegationWithDS) {
  795. // Similar setup to the previous one, but with DS RR at the delegation
  796. // point.
  797. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_));
  798. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_ns_));
  799. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_ds_));
  800. // Normal types of query should result in delegation, but DS query
  801. // should be considered in-zone (but only exactly at the delegation point).
  802. findTest(Name("child.example.org"), RRType::A(), ZoneFinder::DELEGATION,
  803. true, rr_child_ns_);
  804. findTest(Name("child.example.org"), RRType::DS(), ZoneFinder::SUCCESS,
  805. true, rr_child_ds_);
  806. findTest(Name("grand.child.example.org"), RRType::DS(),
  807. ZoneFinder::DELEGATION, true, rr_child_ns_);
  808. // There's nothing special for DS query at the zone apex. It would
  809. // normally result in NXRRSET.
  810. findTest(Name("example.org"), RRType::DS(), ZoneFinder::NXRRSET,
  811. true, ConstRRsetPtr());
  812. }
  813. TEST_F(InMemoryZoneFinderTest, findAny) {
  814. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_a_)));
  815. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_)));
  816. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_glue_)));
  817. vector<ConstRRsetPtr> expected_sets;
  818. // origin
  819. expected_sets.push_back(rr_a_);
  820. expected_sets.push_back(rr_ns_);
  821. findAllTest(origin_, ZoneFinder::SUCCESS, expected_sets);
  822. // out zone name
  823. EXPECT_THROW(findAllTest(Name("example.com"), ZoneFinder::NXDOMAIN,
  824. vector<ConstRRsetPtr>()),
  825. OutOfZone);
  826. expected_sets.clear();
  827. expected_sets.push_back(rr_child_glue_);
  828. findAllTest(rr_child_glue_->getName(), ZoneFinder::SUCCESS, expected_sets);
  829. // add zone cut
  830. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_ns_)));
  831. // zone cut
  832. findAllTest(rr_child_ns_->getName(), ZoneFinder::DELEGATION,
  833. vector<ConstRRsetPtr>(), ZoneFinder::RESULT_DEFAULT,
  834. NULL, rr_child_ns_);
  835. // glue for this zone cut
  836. findAllTest(rr_child_glue_->getName(),ZoneFinder::DELEGATION,
  837. vector<ConstRRsetPtr>(), ZoneFinder::RESULT_DEFAULT,
  838. NULL, rr_child_ns_);
  839. }
  840. TEST_F(InMemoryZoneFinderTest, glue) {
  841. // install zone data:
  842. // a zone cut
  843. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_ns_)));
  844. // glue for this cut
  845. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_glue_)));
  846. // a nested zone cut (unusual)
  847. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_grandchild_ns_)));
  848. // glue under the deeper zone cut
  849. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_grandchild_glue_)));
  850. // by default glue is hidden due to the zone cut
  851. findTest(rr_child_glue_->getName(), RRType::A(), ZoneFinder::DELEGATION,
  852. true, rr_child_ns_);
  853. // If we do it in the "glue OK" mode, we should find the exact match.
  854. findTest(rr_child_glue_->getName(), RRType::A(), ZoneFinder::SUCCESS, true,
  855. rr_child_glue_, ZoneFinder::RESULT_DEFAULT, NULL,
  856. ZoneFinder::FIND_GLUE_OK);
  857. // glue OK + NXRRSET case
  858. findTest(rr_child_glue_->getName(), RRType::AAAA(), ZoneFinder::NXRRSET,
  859. true, ConstRRsetPtr(), ZoneFinder::RESULT_DEFAULT, NULL,
  860. ZoneFinder::FIND_GLUE_OK);
  861. // glue OK + NXDOMAIN case
  862. findTest(Name("www.child.example.org"), RRType::A(),
  863. ZoneFinder::DELEGATION, true, rr_child_ns_,
  864. ZoneFinder::RESULT_DEFAULT, NULL, ZoneFinder::FIND_GLUE_OK);
  865. // nested cut case. The glue should be found.
  866. findTest(rr_grandchild_glue_->getName(), RRType::AAAA(),
  867. ZoneFinder::SUCCESS,
  868. true, rr_grandchild_glue_, ZoneFinder::RESULT_DEFAULT, NULL,
  869. ZoneFinder::FIND_GLUE_OK);
  870. // A non-existent name in nested cut. This should result in delegation
  871. // at the highest zone cut.
  872. findTest(Name("www.grand.child.example.org"), RRType::TXT(),
  873. ZoneFinder::DELEGATION, true, rr_child_ns_,
  874. ZoneFinder::RESULT_DEFAULT, NULL, ZoneFinder::FIND_GLUE_OK);
  875. }
  876. /**
  877. * \brief Test searching.
  878. *
  879. * Check it finds or does not find correctly and does not throw exceptions.
  880. * \todo This doesn't do any kind of CNAME and so on. If it isn't
  881. * directly there, it just tells it doesn't exist.
  882. */
  883. void
  884. InMemoryZoneFinderTest::findCheck(ZoneFinder::FindResultFlags expected_flags,
  885. ZoneFinder::FindOptions find_options)
  886. {
  887. // Fill some data inside
  888. // Now put all the data we have there. It should throw nothing
  889. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_)));
  890. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_a_)));
  891. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_aaaa_)));
  892. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_a_)));
  893. if ((expected_flags & ZoneFinder::RESULT_NSEC3_SIGNED) != 0) {
  894. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec3_));
  895. }
  896. if ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED) != 0) {
  897. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec_));
  898. }
  899. // These two should be successful
  900. findTest(origin_, RRType::NS(), ZoneFinder::SUCCESS, true, rr_ns_);
  901. findTest(rr_ns_a_->getName(), RRType::A(), ZoneFinder::SUCCESS, true,
  902. rr_ns_a_);
  903. // These domains don't exist. (and one is out of the zone). In an
  904. // NSEC-signed zone with DNSSEC records requested, it should return the
  905. // covering NSEC for the query name (the actual NSEC in the test data may
  906. // not really "cover" it, but for the purpose of this test it's okay).
  907. ConstRRsetPtr expected_nsec; // by default it's NULL
  908. if ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED) != 0 &&
  909. (find_options & ZoneFinder::FIND_DNSSEC) != 0) {
  910. expected_nsec = rr_nsec_;
  911. }
  912. // There's no other name between this one and the origin, so when NSEC
  913. // is to be returned it should be the origin NSEC.
  914. findTest(Name("nothere.example.org"), RRType::A(),
  915. ZoneFinder::NXDOMAIN, true, expected_nsec, expected_flags,
  916. NULL, find_options);
  917. // The previous name in the zone is "ns.example.org", but it doesn't
  918. // have an NSEC. It should be skipped and the origin NSEC will be
  919. // returned as the "closest NSEC".
  920. findTest(Name("nxdomain.example.org"), RRType::A(),
  921. ZoneFinder::NXDOMAIN, true, expected_nsec, expected_flags,
  922. NULL, find_options);
  923. EXPECT_THROW(zone_finder_.find(Name("example.net"), RRType::A()),
  924. OutOfZone);
  925. // These domain exist but don't have the provided RRType. For the latter
  926. // one we now add its NSEC (which was delayed so that it wouldn't break
  927. // other cases above).
  928. findTest(origin_, RRType::AAAA(), ZoneFinder::NXRRSET, true,
  929. expected_nsec, expected_flags, NULL, find_options);
  930. if ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED) != 0) {
  931. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_ns_nsec_));
  932. if ((find_options & ZoneFinder::FIND_DNSSEC) != 0) {
  933. expected_nsec = rr_ns_nsec_;
  934. }
  935. }
  936. findTest(rr_ns_a_->getName(), RRType::NS(), ZoneFinder::NXRRSET, true,
  937. expected_nsec, expected_flags, NULL, find_options);
  938. }
  939. // Test if NSEC works
  940. TEST_F(InMemoryZoneFinderTest, NSEC4NXRRSET) {
  941. findTest(origin_, RRType::TXT(), ZoneFinder::NXRRSET, true,
  942. ConstRRsetPtr());
  943. EXPECT_NO_THROW(EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec_)));
  944. findTest(origin_, RRType::A(), ZoneFinder::NXRRSET, true,
  945. rr_nsec_, ZoneFinder::RESULT_NSEC_SIGNED, NULL,
  946. ZoneFinder::FIND_DNSSEC);
  947. }
  948. TEST_F(InMemoryZoneFinderTest, find) {
  949. findCheck();
  950. }
  951. TEST_F(InMemoryZoneFinderTest, findNSEC3Signe) {
  952. findCheck(ZoneFinder::RESULT_NSEC3_SIGNED);
  953. }
  954. TEST_F(InMemoryZoneFinderTest, findNSEC3SignedWithDNSSEC) {
  955. // For NSEC3-signed zones, specifying the DNSSEC option shouldn't change
  956. // anything (the NSEC3_SIGNED flag is always set, and no records are
  957. // returned for negative cases regardless).
  958. findCheck(ZoneFinder::RESULT_NSEC3_SIGNED, ZoneFinder::FIND_DNSSEC);
  959. }
  960. TEST_F(InMemoryZoneFinderTest, findNSECSigned) {
  961. // NSEC-signed zone, without requesting DNSSEC (no NSEC should be provided)
  962. findCheck(ZoneFinder::RESULT_NSEC_SIGNED);
  963. }
  964. TEST_F(InMemoryZoneFinderTest, findNSECSignedWithDNSSEC) {
  965. // NSEC-signed zone, requesting DNSSEC (NSEC should be provided)
  966. findCheck(ZoneFinder::RESULT_NSEC_SIGNED, ZoneFinder::FIND_DNSSEC);
  967. }
  968. void
  969. InMemoryZoneFinderTest::emptyNodeCheck(
  970. ZoneFinder::FindResultFlags expected_flags)
  971. {
  972. /*
  973. * The backend RBTree for this test should look like as follows:
  974. * example.org
  975. * |
  976. * baz (empty; easy case)
  977. * / | \
  978. * bar | x.foo ('foo' part is empty; a bit trickier)
  979. * bbb
  980. * /
  981. * aaa
  982. */
  983. // Construct the test zone
  984. const char* const names[] = {
  985. "bar.example.org.", "x.foo.example.org.", "aaa.baz.example.org.",
  986. "bbb.baz.example.org.", NULL};
  987. for (int i = 0; names[i] != NULL; ++i) {
  988. ConstRRsetPtr rrset = textToRRset(string(names[i]) +
  989. " 300 IN A 192.0.2.1");
  990. EXPECT_EQ(SUCCESS, zone_finder_.add(rrset));
  991. }
  992. if ((expected_flags & ZoneFinder::RESULT_NSEC3_SIGNED) != 0) {
  993. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec3_));
  994. }
  995. if ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED) != 0) {
  996. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec_));
  997. }
  998. // empty node matching, easy case: the node for 'baz' exists with
  999. // no data.
  1000. findTest(Name("baz.example.org"), RRType::A(), ZoneFinder::NXRRSET, true,
  1001. ConstRRsetPtr(), expected_flags);
  1002. // empty node matching, a trickier case: the node for 'foo' is part of
  1003. // "x.foo", which should be considered an empty node.
  1004. findTest(Name("foo.example.org"), RRType::A(), ZoneFinder::NXRRSET, true,
  1005. ConstRRsetPtr(), expected_flags);
  1006. // "org" is contained in "example.org", but it shouldn't be treated as
  1007. // NXRRSET because it's out of zone.
  1008. // Note: basically we don't expect such a query to be performed (the common
  1009. // operation is to identify the best matching zone first then perform
  1010. // search it), but we shouldn't be confused even in the unexpected case.
  1011. EXPECT_THROW(zone_finder_.find(Name("org"), RRType::A()), OutOfZone);
  1012. }
  1013. TEST_F(InMemoryZoneFinderTest, emptyNode) {
  1014. emptyNodeCheck();
  1015. }
  1016. TEST_F(InMemoryZoneFinderTest, emptyNodeNSEC3) {
  1017. emptyNodeCheck(ZoneFinder::RESULT_NSEC3_SIGNED);
  1018. }
  1019. TEST_F(InMemoryZoneFinderTest, emptyNodeNSEC) {
  1020. emptyNodeCheck(ZoneFinder::RESULT_NSEC_SIGNED);
  1021. }
  1022. TEST_F(InMemoryZoneFinderTest, load) {
  1023. // Put some data inside the zone
  1024. EXPECT_NO_THROW(EXPECT_EQ(result::SUCCESS, zone_finder_.add(rr_ns_)));
  1025. // Loading with different origin should fail
  1026. EXPECT_THROW(zone_finder_.load(TEST_DATA_DIR "/root.zone"),
  1027. MasterLoadError);
  1028. // See the original data is still there, survived the exception
  1029. findTest(origin_, RRType::NS(), ZoneFinder::SUCCESS, true, rr_ns_);
  1030. // Create correct zone
  1031. InMemoryZoneFinder rootzone(class_, Name("."));
  1032. // Try putting something inside
  1033. EXPECT_NO_THROW(EXPECT_EQ(result::SUCCESS, rootzone.add(rr_ns_aaaa_)));
  1034. // Load the zone. It should overwrite/remove the above RRset
  1035. EXPECT_NO_THROW(rootzone.load(TEST_DATA_DIR "/root.zone"));
  1036. // Now see there are some rrsets (we don't look inside, though)
  1037. findTest(Name("."), RRType::SOA(), ZoneFinder::SUCCESS, false,
  1038. ConstRRsetPtr(), ZoneFinder::RESULT_DEFAULT, &rootzone);
  1039. findTest(Name("."), RRType::NS(), ZoneFinder::SUCCESS, false,
  1040. ConstRRsetPtr(), ZoneFinder::RESULT_DEFAULT, &rootzone);
  1041. findTest(Name("a.root-servers.net."), RRType::A(), ZoneFinder::SUCCESS,
  1042. false, ConstRRsetPtr(), ZoneFinder::RESULT_DEFAULT, &rootzone);
  1043. // But this should no longer be here
  1044. findTest(rr_ns_a_->getName(), RRType::AAAA(), ZoneFinder::NXDOMAIN, true,
  1045. ConstRRsetPtr(), ZoneFinder::RESULT_DEFAULT, &rootzone);
  1046. // Try loading zone that is wrong in a different way
  1047. EXPECT_THROW(zone_finder_.load(TEST_DATA_DIR "/duplicate_rrset.zone"),
  1048. MasterLoadError);
  1049. }
  1050. TEST_F(InMemoryZoneFinderTest, loadFromIterator) {
  1051. // The initial test set doesn't have SOA at the apex.
  1052. findTest(origin_, RRType::SOA(), ZoneFinder::NXRRSET, false,
  1053. ConstRRsetPtr());
  1054. // The content of the new version of zone to be first installed to
  1055. // the SQLite3 data source, then to in-memory via SQLite3. The data are
  1056. // chosen to cover major check points of the implementation:
  1057. // - the previously non-existent record is added (SOA)
  1058. // - An RRSIG is given from the iterator before the RRset it covers
  1059. // (RRSIG for SOA, because they are sorted by name then rrtype as text)
  1060. // - An RRset containing multiple RRs (ns1/A)
  1061. // - RRSIGs for different owner names
  1062. stringstream ss;
  1063. const char* const soa_txt = "example.org. 300 IN SOA . . 0 0 0 0 0\n";
  1064. const char* const soa_sig_txt = "example.org. 300 IN RRSIG SOA 5 3 300 "
  1065. "20000101000000 20000201000000 12345 example.org. FAKEFAKE\n";
  1066. const char* const a_txt =
  1067. "ns1.example.org. 300 IN A 192.0.2.1\n"
  1068. "ns1.example.org. 300 IN A 192.0.2.2\n";
  1069. const char* const a_sig_txt = "ns1.example.org. 300 IN RRSIG A 5 3 300 "
  1070. "20000101000000 20000201000000 12345 example.org. FAKEFAKE\n";
  1071. ss << soa_txt << soa_sig_txt << a_txt << a_sig_txt;
  1072. shared_ptr<DataSourceClient> db_client = unittest::createSQLite3Client(
  1073. class_, origin_, TEST_DATA_BUILDDIR "/contexttest.sqlite3.copied", ss);
  1074. zone_finder_.load(*db_client->getIterator(origin_));
  1075. // The new content should be visible, including the previously-nonexistent
  1076. // SOA.
  1077. RRsetPtr expected_answer = textToRRset(soa_txt, RRClass::IN(), origin_);
  1078. expected_answer->addRRsig(textToRRset(soa_sig_txt));
  1079. findTest(origin_, RRType::SOA(), ZoneFinder::SUCCESS, true,
  1080. expected_answer);
  1081. expected_answer = textToRRset(a_txt);
  1082. expected_answer->addRRsig(textToRRset(a_sig_txt));
  1083. findTest(Name("ns1.example.org"), RRType::A(), ZoneFinder::SUCCESS, true,
  1084. expected_answer);
  1085. // File name should be (re)set to empty.
  1086. EXPECT_TRUE(zone_finder_.getFileName().empty());
  1087. // Loading the zone with an iterator separating RRs of the same RRset
  1088. // will fail because the resulting sequence doesn't meet assumptions of
  1089. // the (current) in-memory implementation.
  1090. EXPECT_THROW(zone_finder_.load(*db_client->getIterator(origin_, true)),
  1091. MasterLoadError);
  1092. // Load the zone from a file that contains more realistic data (borrowed
  1093. // from a different test). There's nothing special in this case for the
  1094. // purpose of this test, so it should just succeed.
  1095. db_client = unittest::createSQLite3Client(
  1096. class_, origin_, TEST_DATA_BUILDDIR "/contexttest.sqlite3.copied",
  1097. TEST_DATA_DIR "/contexttest.zone");
  1098. zone_finder_.load(*db_client->getIterator(origin_));
  1099. // just checking a couple of RRs in the new version of zone.
  1100. findTest(Name("mx1.example.org"), RRType::A(), ZoneFinder::SUCCESS, true,
  1101. textToRRset("mx1.example.org. 3600 IN A 192.0.2.10"));
  1102. findTest(Name("ns1.example.org"), RRType::AAAA(), ZoneFinder::SUCCESS,
  1103. true, textToRRset("ns1.example.org. 3600 IN AAAA 2001:db8::1"));
  1104. }
  1105. /*
  1106. * Test that puts a (simple) wildcard into the zone and checks we can
  1107. * correctly find the data.
  1108. */
  1109. void
  1110. InMemoryZoneFinderTest::wildcardCheck(
  1111. ZoneFinder::FindResultFlags expected_flags,
  1112. ZoneFinder::FindOptions find_options)
  1113. {
  1114. /*
  1115. * example.org.
  1116. * |
  1117. * [cname]wild (not *.wild, should have wild mark)
  1118. * |
  1119. * *
  1120. */
  1121. // If the zone is "signed" (detecting it by the NSEC/NSEC3 signed flags),
  1122. // add RRSIGs to the records.
  1123. if ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED) != 0 ||
  1124. (expected_flags & ZoneFinder::RESULT_NSEC3_SIGNED) != 0) {
  1125. // Convenience shortcut. The RDATA is not really validatable, but
  1126. // it doesn't matter for our tests.
  1127. const char* const rrsig_common = "5 3 3600 "
  1128. "20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE";
  1129. find_options = find_options | ZoneFinder::FIND_DNSSEC;
  1130. rr_wild_->addRRsig(textToRRset("*.wild.example.org. 300 IN RRSIG A " +
  1131. string(rrsig_common)));
  1132. rr_cnamewild_->addRRsig(textToRRset("*.cnamewild.example.org. 300 IN "
  1133. "RRSIG CNAME " +
  1134. string(rrsig_common)));
  1135. }
  1136. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_wild_));
  1137. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_cnamewild_));
  1138. // If the zone is expected to be "signed" with NSEC3, add an NSEC3.
  1139. // (the content of the NSEC3 shouldn't matter)
  1140. if ((expected_flags & ZoneFinder::RESULT_NSEC3_SIGNED) != 0) {
  1141. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec3_));
  1142. }
  1143. if ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED) != 0) {
  1144. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec_));
  1145. }
  1146. // Search at the parent. The parent will not have the A, but it will
  1147. // be in the wildcard (so check the wildcard isn't matched at the parent)
  1148. {
  1149. SCOPED_TRACE("Search at parent");
  1150. findTest(Name("wild.example.org"), RRType::A(), ZoneFinder::NXRRSET,
  1151. true, ConstRRsetPtr(), expected_flags, NULL, find_options);
  1152. }
  1153. // For the test setup of "NSEC-signed" zone, we might expect it will
  1154. // be returned with a negative result, either because wildcard match is
  1155. // disabled by the search option or because wildcard match is canceled
  1156. // per protocol.
  1157. ConstRRsetPtr expected_nsec; // by default it's NULL
  1158. if ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED) != 0 &&
  1159. (find_options & ZoneFinder::FIND_DNSSEC) != 0) {
  1160. expected_nsec = rr_nsec_;
  1161. }
  1162. // Search the original name of wildcard
  1163. {
  1164. SCOPED_TRACE("Search directly at *");
  1165. findTest(Name("*.wild.example.org"), RRType::A(), ZoneFinder::SUCCESS,
  1166. true, rr_wild_, ZoneFinder::RESULT_DEFAULT, NULL,
  1167. find_options);
  1168. }
  1169. // Below some of the test cases will normally result in a wildcard match;
  1170. // if NO_WILDCARD is specified, it should result in NXDOMAIN instead,
  1171. // and, when available and requested, the covering NSEC will be returned.
  1172. // The following are shortcut parameters to unify these cases.
  1173. const bool wild_ok = ((find_options & ZoneFinder::NO_WILDCARD) == 0);
  1174. const ZoneFinder::FindResultFlags wild_expected_flags =
  1175. wild_ok ? (ZoneFinder::RESULT_WILDCARD | expected_flags) :
  1176. expected_flags;
  1177. // Search "created" name.
  1178. {
  1179. SCOPED_TRACE("Search at created child");
  1180. findTest(Name("a.wild.example.org"), RRType::A(),
  1181. wild_ok ? ZoneFinder::SUCCESS : ZoneFinder::NXDOMAIN, false,
  1182. wild_ok ? rr_wild_ : expected_nsec,
  1183. wild_expected_flags, NULL, find_options, wild_ok);
  1184. // Wildcard match, but no data
  1185. findTest(Name("a.wild.example.org"), RRType::AAAA(),
  1186. wild_ok ? ZoneFinder::NXRRSET : ZoneFinder::NXDOMAIN, true,
  1187. wild_ok ? ConstRRsetPtr() : expected_nsec,
  1188. wild_expected_flags, NULL, find_options);
  1189. }
  1190. // Search name that has CNAME.
  1191. {
  1192. SCOPED_TRACE("Matching CNAME");
  1193. findTest(Name("a.cnamewild.example.org"), RRType::A(),
  1194. wild_ok ? ZoneFinder::CNAME : ZoneFinder::NXDOMAIN, false,
  1195. wild_ok ? rr_cnamewild_ : expected_nsec,
  1196. wild_expected_flags, NULL, find_options, wild_ok);
  1197. }
  1198. // Search another created name, this time little bit lower
  1199. {
  1200. SCOPED_TRACE("Search at created grand-child");
  1201. findTest(Name("a.b.wild.example.org"), RRType::A(),
  1202. wild_ok ? ZoneFinder::SUCCESS : ZoneFinder::NXDOMAIN, false,
  1203. wild_ok ? rr_wild_ : expected_nsec,
  1204. wild_expected_flags, NULL, find_options, wild_ok);
  1205. }
  1206. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_under_wild_));
  1207. {
  1208. SCOPED_TRACE("Search under non-wildcard");
  1209. findTest(Name("bar.foo.wild.example.org"), RRType::A(),
  1210. ZoneFinder::NXDOMAIN, true, expected_nsec, expected_flags,
  1211. NULL, find_options);
  1212. }
  1213. }
  1214. TEST_F(InMemoryZoneFinderTest, wildcard) {
  1215. // Normal case
  1216. wildcardCheck();
  1217. }
  1218. TEST_F(InMemoryZoneFinderTest, wildcardNSEC3) {
  1219. // Similar to the previous one, but the zone signed with NSEC3
  1220. wildcardCheck(ZoneFinder::RESULT_NSEC3_SIGNED);
  1221. }
  1222. TEST_F(InMemoryZoneFinderTest, wildcardNSEC) {
  1223. // Similar to the previous one, but the zone signed with NSEC
  1224. wildcardCheck(ZoneFinder::RESULT_NSEC_SIGNED);
  1225. }
  1226. TEST_F(InMemoryZoneFinderTest, wildcardDisabledWithNSEC) {
  1227. // Wildcard is disabled. In practice, this is used as part of query
  1228. // processing for an NSEC-signed zone, so we test that case specifically.
  1229. wildcardCheck(ZoneFinder::RESULT_NSEC_SIGNED, ZoneFinder::NO_WILDCARD);
  1230. }
  1231. TEST_F(InMemoryZoneFinderTest, wildcardDisabledWithoutNSEC) {
  1232. // Similar to the previous once, but check the behavior for a non signed
  1233. // zone just in case.
  1234. wildcardCheck(ZoneFinder::RESULT_DEFAULT, ZoneFinder::NO_WILDCARD);
  1235. }
  1236. /*
  1237. * Test that we don't match a wildcard if we get under delegation.
  1238. * By 4.3.3 of RFC1034:
  1239. * "Wildcard RRs do not apply:
  1240. * - When the query is in another zone. That is, delegation cancels
  1241. * the wildcard defaults."
  1242. */
  1243. TEST_F(InMemoryZoneFinderTest, delegatedWildcard) {
  1244. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_wild_));
  1245. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_child_ns_));
  1246. {
  1247. SCOPED_TRACE("Looking under delegation point");
  1248. findTest(Name("a.child.example.org"), RRType::A(),
  1249. ZoneFinder::DELEGATION, true, rr_child_ns_);
  1250. }
  1251. {
  1252. SCOPED_TRACE("Looking under delegation point in GLUE_OK mode");
  1253. findTest(Name("a.child.example.org"), RRType::A(),
  1254. ZoneFinder::DELEGATION, true, rr_child_ns_,
  1255. ZoneFinder::RESULT_DEFAULT, NULL, ZoneFinder::FIND_GLUE_OK);
  1256. }
  1257. }
  1258. // Tests combination of wildcard and ANY.
  1259. void
  1260. InMemoryZoneFinderTest::anyWildcardCheck(
  1261. ZoneFinder::FindResultFlags expected_flags)
  1262. {
  1263. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_wild_));
  1264. if ((expected_flags & ZoneFinder::RESULT_NSEC3_SIGNED) != 0) {
  1265. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec3_));
  1266. }
  1267. if ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED) != 0) {
  1268. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec_));
  1269. }
  1270. vector<ConstRRsetPtr> expected_sets;
  1271. // First try directly the name (normal match)
  1272. {
  1273. SCOPED_TRACE("Asking direcly for *");
  1274. expected_sets.push_back(rr_wild_);
  1275. findAllTest(Name("*.wild.example.org"), ZoneFinder::SUCCESS,
  1276. expected_sets);
  1277. }
  1278. // Then a wildcard match
  1279. {
  1280. SCOPED_TRACE("Asking in the wild way");
  1281. expected_sets.clear();
  1282. RRsetPtr expected(new RRset(Name("a.wild.example.org"),
  1283. rr_wild_->getClass(), rr_wild_->getType(),
  1284. rr_wild_->getTTL()));
  1285. expected->addRdata(rr_wild_->getRdataIterator()->getCurrent());
  1286. expected_sets.push_back(expected);
  1287. findAllTest(Name("a.wild.example.org"), ZoneFinder::SUCCESS,
  1288. expected_sets,
  1289. ZoneFinder::RESULT_WILDCARD | expected_flags);
  1290. }
  1291. }
  1292. TEST_F(InMemoryZoneFinderTest, anyWildcard) {
  1293. anyWildcardCheck();
  1294. }
  1295. TEST_F(InMemoryZoneFinderTest, anyWildcardNSEC3) {
  1296. anyWildcardCheck(ZoneFinder::RESULT_NSEC3_SIGNED);
  1297. }
  1298. TEST_F(InMemoryZoneFinderTest, anyWildcardNSEC) {
  1299. anyWildcardCheck(ZoneFinder::RESULT_NSEC_SIGNED);
  1300. }
  1301. // Test there's nothing in the wildcard in the middle if we load
  1302. // wild.*.foo.example.org.
  1303. void
  1304. InMemoryZoneFinderTest::emptyWildcardCheck(
  1305. ZoneFinder::FindResultFlags expected_flags)
  1306. {
  1307. /*
  1308. * example.org.
  1309. * foo
  1310. * *
  1311. * wild
  1312. */
  1313. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_emptywild_));
  1314. if ((expected_flags & ZoneFinder::RESULT_NSEC3_SIGNED) != 0) {
  1315. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec3_));
  1316. }
  1317. if ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED) != 0) {
  1318. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec_));
  1319. }
  1320. {
  1321. SCOPED_TRACE("Asking for the original record under wildcard");
  1322. findTest(Name("wild.*.foo.example.org"), RRType::A(),
  1323. ZoneFinder::SUCCESS, true, rr_emptywild_);
  1324. }
  1325. {
  1326. SCOPED_TRACE("Asking for A record");
  1327. findTest(Name("a.foo.example.org"), RRType::A(), ZoneFinder::NXRRSET,
  1328. true, ConstRRsetPtr(),
  1329. ZoneFinder::RESULT_WILDCARD | expected_flags);
  1330. findTest(Name("*.foo.example.org"), RRType::A(), ZoneFinder::NXRRSET,
  1331. true, ConstRRsetPtr(), expected_flags);
  1332. findTest(Name("foo.example.org"), RRType::A(), ZoneFinder::NXRRSET,
  1333. true, ConstRRsetPtr(), expected_flags);
  1334. }
  1335. {
  1336. SCOPED_TRACE("Asking for ANY record");
  1337. findAllTest(Name("*.foo.example.org"), ZoneFinder::NXRRSET,
  1338. vector<ConstRRsetPtr>(), expected_flags);
  1339. findAllTest(Name("a.foo.example.org"), ZoneFinder::NXRRSET,
  1340. vector<ConstRRsetPtr>(),
  1341. ZoneFinder::RESULT_WILDCARD | expected_flags);
  1342. }
  1343. {
  1344. SCOPED_TRACE("Asking on the non-terminal");
  1345. findTest(Name("wild.bar.foo.example.org"), RRType::A(),
  1346. ZoneFinder::NXRRSET, true, ConstRRsetPtr(),
  1347. ZoneFinder::RESULT_WILDCARD | expected_flags);
  1348. }
  1349. }
  1350. TEST_F(InMemoryZoneFinderTest, emptyWildcard) {
  1351. emptyWildcardCheck();
  1352. }
  1353. TEST_F(InMemoryZoneFinderTest, emptyWildcardNSEC3) {
  1354. emptyWildcardCheck(ZoneFinder::RESULT_NSEC3_SIGNED);
  1355. }
  1356. TEST_F(InMemoryZoneFinderTest, emptyWildcardNSEC) {
  1357. emptyWildcardCheck(ZoneFinder::RESULT_NSEC_SIGNED);
  1358. }
  1359. // Same as emptyWildcard, but with multiple * in the path.
  1360. TEST_F(InMemoryZoneFinderTest, nestedEmptyWildcard) {
  1361. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nested_emptywild_));
  1362. {
  1363. SCOPED_TRACE("Asking for the original record under wildcards");
  1364. findTest(Name("wild.*.foo.*.bar.example.org"), RRType::A(),
  1365. ZoneFinder::SUCCESS, true, rr_nested_emptywild_);
  1366. }
  1367. {
  1368. SCOPED_TRACE("Matching wildcard against empty nonterminal");
  1369. const char* names[] = {
  1370. "baz.foo.*.bar.example.org",
  1371. "baz.foo.baz.bar.example.org",
  1372. "*.foo.baz.bar.example.org",
  1373. NULL
  1374. };
  1375. for (const char** name = names; *name != NULL; ++ name) {
  1376. SCOPED_TRACE(string("Node ") + *name);
  1377. findTest(Name(*name), RRType::A(), ZoneFinder::NXRRSET, true,
  1378. ConstRRsetPtr(), ZoneFinder::RESULT_WILDCARD);
  1379. }
  1380. }
  1381. // Domains to test
  1382. const char* names[] = {
  1383. "*.foo.*.bar.example.org",
  1384. "foo.*.bar.example.org",
  1385. "*.bar.example.org",
  1386. "bar.example.org",
  1387. NULL
  1388. };
  1389. {
  1390. SCOPED_TRACE("Asking directly for A on parent nodes");
  1391. for (const char** name = names; *name != NULL; ++ name) {
  1392. SCOPED_TRACE(string("Node ") + *name);
  1393. findTest(Name(*name), RRType::A(), ZoneFinder::NXRRSET);
  1394. }
  1395. }
  1396. {
  1397. SCOPED_TRACE("Asking for ANY on parent nodes");
  1398. for (const char** name = names; *name != NULL; ++ name) {
  1399. SCOPED_TRACE(string("Node ") + *name);
  1400. findAllTest(Name(*name), ZoneFinder::NXRRSET,
  1401. vector<ConstRRsetPtr>());
  1402. }
  1403. }
  1404. }
  1405. // We run this part twice from the below test, in two slightly different
  1406. // situations
  1407. void
  1408. InMemoryZoneFinderTest::doCancelWildcardCheck(
  1409. ZoneFinder::FindResultFlags expected_flags,
  1410. ZoneFinder::FindOptions find_options)
  1411. {
  1412. // These should be canceled
  1413. {
  1414. SCOPED_TRACE("Canceled under foo.wild.example.org");
  1415. // For an NSEC-signed zone with DNSSEC requested, the covering NSEC
  1416. // should be returned. The expected NSEC is actually just the only
  1417. // NSEC in the test data, but in this context it doesn't matter;
  1418. // it's sufficient just to check any NSEC is returned (or not).
  1419. ConstRRsetPtr expected_nsec; // by default it's NULL
  1420. if ((expected_flags & ZoneFinder::RESULT_NSEC_SIGNED) != 0 &&
  1421. (find_options & ZoneFinder::FIND_DNSSEC)) {
  1422. expected_nsec = rr_nsec_;
  1423. }
  1424. findTest(Name("aaa.foo.wild.example.org"), RRType::A(),
  1425. ZoneFinder::NXDOMAIN, true, expected_nsec, expected_flags,
  1426. NULL, find_options);
  1427. findTest(Name("zzz.foo.wild.example.org"), RRType::A(),
  1428. ZoneFinder::NXDOMAIN, true, expected_nsec, expected_flags,
  1429. NULL, find_options);
  1430. }
  1431. // This is existing, non-wildcard domain, shouldn't wildcard at all
  1432. {
  1433. SCOPED_TRACE("Existing domain under foo.wild.example.org");
  1434. findTest(Name("bar.foo.wild.example.org"), RRType::A(),
  1435. ZoneFinder::SUCCESS, true, rr_not_wild_);
  1436. }
  1437. // These should be caught by the wildcard
  1438. {
  1439. SCOPED_TRACE("Neighbor wildcards to foo.wild.example.org");
  1440. const char* names[] = {
  1441. "aaa.bbb.wild.example.org",
  1442. "aaa.zzz.wild.example.org",
  1443. "zzz.wild.example.org",
  1444. NULL
  1445. };
  1446. for (const char** name = names; *name != NULL; ++ name) {
  1447. SCOPED_TRACE(string("Node ") + *name);
  1448. findTest(Name(*name), RRType::A(), ZoneFinder::SUCCESS, false,
  1449. rr_wild_,
  1450. ZoneFinder::RESULT_WILDCARD | expected_flags, NULL,
  1451. ZoneFinder::FIND_DEFAULT, true);
  1452. }
  1453. }
  1454. // This shouldn't be wildcarded, it's an existing domain
  1455. {
  1456. SCOPED_TRACE("The foo.wild.example.org itself");
  1457. findTest(Name("foo.wild.example.org"), RRType::A(),
  1458. ZoneFinder::NXRRSET, true, ConstRRsetPtr(), expected_flags);
  1459. }
  1460. }
  1461. /*
  1462. * This tests that if there's a name between the wildcard domain and the
  1463. * searched one, it will not trigger wildcard, for example, if we have
  1464. * *.wild.example.org and bar.foo.wild.example.org, then we know
  1465. * foo.wild.example.org exists and is not wildcard. Therefore, search for
  1466. * aaa.foo.wild.example.org should return NXDOMAIN.
  1467. *
  1468. * Tests few cases "around" the canceled wildcard match, to see something that
  1469. * shouldn't be canceled isn't.
  1470. */
  1471. TEST_F(InMemoryZoneFinderTest, cancelWildcard) {
  1472. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_wild_));
  1473. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_not_wild_));
  1474. {
  1475. SCOPED_TRACE("Runnig with single entry under foo.wild.example.org");
  1476. doCancelWildcardCheck();
  1477. }
  1478. // Try putting another one under foo.wild....
  1479. // The result should be the same but it will be done in another way in the
  1480. // code, because the foo.wild.example.org will exist in the tree.
  1481. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_not_wild_another_));
  1482. {
  1483. SCOPED_TRACE("Runnig with two entries under foo.wild.example.org");
  1484. doCancelWildcardCheck();
  1485. }
  1486. }
  1487. // Same tests as cancelWildcard for NSEC3-signed zone
  1488. TEST_F(InMemoryZoneFinderTest, cancelWildcardNSEC3) {
  1489. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_wild_));
  1490. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_not_wild_));
  1491. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec3_));
  1492. {
  1493. SCOPED_TRACE("Runnig with single entry under foo.wild.example.org");
  1494. doCancelWildcardCheck(ZoneFinder::RESULT_NSEC3_SIGNED);
  1495. }
  1496. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_not_wild_another_));
  1497. {
  1498. SCOPED_TRACE("Runnig with two entries under foo.wild.example.org");
  1499. doCancelWildcardCheck(ZoneFinder::RESULT_NSEC3_SIGNED);
  1500. }
  1501. }
  1502. // Same tests as cancelWildcard for NSEC-signed zone. Check both cases with
  1503. // or without FIND_DNSSEC option. NSEC should be returned only when the option
  1504. // is given.
  1505. TEST_F(InMemoryZoneFinderTest, cancelWildcardNSEC) {
  1506. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_wild_));
  1507. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_not_wild_));
  1508. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_nsec_));
  1509. {
  1510. SCOPED_TRACE("Runnig with single entry under foo.wild.example.org");
  1511. doCancelWildcardCheck(ZoneFinder::RESULT_NSEC_SIGNED,
  1512. ZoneFinder::FIND_DNSSEC);
  1513. doCancelWildcardCheck(ZoneFinder::RESULT_NSEC_SIGNED);
  1514. }
  1515. EXPECT_EQ(SUCCESS, zone_finder_.add(rr_not_wild_another_));
  1516. {
  1517. SCOPED_TRACE("Runnig with two entries under foo.wild.example.org");
  1518. doCancelWildcardCheck(ZoneFinder::RESULT_NSEC_SIGNED,
  1519. ZoneFinder::FIND_DNSSEC);
  1520. doCancelWildcardCheck(ZoneFinder::RESULT_NSEC_SIGNED);
  1521. }
  1522. }
  1523. TEST_F(InMemoryZoneFinderTest, loadBadWildcard) {
  1524. // We reject loading the zone if it contains a wildcard name for
  1525. // NS or DNAME.
  1526. EXPECT_THROW(zone_finder_.add(rr_nswild_), InMemoryZoneFinder::AddError);
  1527. EXPECT_THROW(zone_finder_.add(rr_dnamewild_),
  1528. InMemoryZoneFinder::AddError);
  1529. }
  1530. TEST_F(InMemoryZoneFinderTest, swap) {
  1531. // build one zone finder with some data
  1532. InMemoryZoneFinder finder1(class_, origin_);
  1533. EXPECT_EQ(result::SUCCESS, finder1.add(rr_ns_));
  1534. EXPECT_EQ(result::SUCCESS, finder1.add(rr_ns_aaaa_));
  1535. // build another zone finder of a different RR class with some other data
  1536. const Name other_origin("version.bind");
  1537. ASSERT_NE(origin_, other_origin); // make sure these two are different
  1538. InMemoryZoneFinder finder2(RRClass::CH(), other_origin);
  1539. EXPECT_EQ(result::SUCCESS,
  1540. finder2.add(textToRRset("version.bind. 0 CH TXT \"test\"",
  1541. RRClass::CH())));
  1542. finder1.swap(finder2);
  1543. EXPECT_EQ(other_origin, finder1.getOrigin());
  1544. EXPECT_EQ(origin_, finder2.getOrigin());
  1545. EXPECT_EQ(RRClass::CH(), finder1.getClass());
  1546. EXPECT_EQ(RRClass::IN(), finder2.getClass());
  1547. // make sure the zone data is swapped, too
  1548. EXPECT_THROW(finder1.find(origin_, RRType::NS()), OutOfZone);
  1549. findTest(other_origin, RRType::TXT(), ZoneFinder::SUCCESS, false,
  1550. ConstRRsetPtr(), ZoneFinder::RESULT_DEFAULT, &finder1);
  1551. findTest(origin_, RRType::NS(), ZoneFinder::SUCCESS, false,
  1552. ConstRRsetPtr(), ZoneFinder::RESULT_DEFAULT, &finder2);
  1553. EXPECT_THROW(finder2.find(other_origin, RRType::TXT()), OutOfZone);
  1554. }
  1555. TEST_F(InMemoryZoneFinderTest, getFileName) {
  1556. // for an empty zone the file name should also be empty.
  1557. EXPECT_TRUE(zone_finder_.getFileName().empty());
  1558. // if loading a zone fails the file name shouldn't be set.
  1559. EXPECT_THROW(zone_finder_.load(TEST_DATA_DIR "/root.zone"),
  1560. MasterLoadError);
  1561. EXPECT_TRUE(zone_finder_.getFileName().empty());
  1562. // after a successful load, the specified file name should be set
  1563. InMemoryZoneFinder rootzone(class_, Name("."));
  1564. EXPECT_NO_THROW(rootzone.load(TEST_DATA_DIR "/root.zone"));
  1565. EXPECT_EQ(TEST_DATA_DIR "/root.zone", rootzone.getFileName());
  1566. // overriding load, which will fail
  1567. EXPECT_THROW(rootzone.load(TEST_DATA_DIR "/duplicate_rrset.zone"),
  1568. MasterLoadError);
  1569. // the file name should be intact.
  1570. EXPECT_EQ(TEST_DATA_DIR "/root.zone", rootzone.getFileName());
  1571. // After swap, file names should also be swapped.
  1572. zone_finder_.swap(rootzone);
  1573. EXPECT_EQ(TEST_DATA_DIR "/root.zone", zone_finder_.getFileName());
  1574. EXPECT_TRUE(rootzone.getFileName().empty());
  1575. }
  1576. TEST_F(InMemoryZoneFinderTest, addRRsig) {
  1577. // A simple valid case: adding an RRset to be signed followed by an RRSIG
  1578. // that covers the first RRset
  1579. zone_finder_.add(rr_a_);
  1580. zone_finder_.add(textToRRset(rrsig_a_txt));
  1581. ZoneFinderContextPtr result = zone_finder_.find(origin_, RRType::A(),
  1582. ZoneFinder::FIND_DNSSEC);
  1583. EXPECT_EQ(ZoneFinder::SUCCESS, result->code);
  1584. ASSERT_TRUE(result->rrset);
  1585. ASSERT_TRUE(result->rrset->getRRsig());
  1586. actual_rrsets_.push_back(result->rrset->getRRsig());
  1587. rrsetsCheck(rrsig_a_txt, actual_rrsets_.begin(), actual_rrsets_.end());
  1588. // Confirm a separate RRISG for a different type can be added
  1589. actual_rrsets_.clear();
  1590. zone_finder_.add(rr_ns_);
  1591. zone_finder_.add(textToRRset(rrsig_ns_txt));
  1592. result = zone_finder_.find(origin_, RRType::NS(), ZoneFinder::FIND_DNSSEC);
  1593. EXPECT_EQ(ZoneFinder::SUCCESS, result->code);
  1594. ASSERT_TRUE(result->rrset);
  1595. ASSERT_TRUE(result->rrset->getRRsig());
  1596. actual_rrsets_.push_back(result->rrset->getRRsig());
  1597. rrsetsCheck(rrsig_ns_txt, actual_rrsets_.begin(), actual_rrsets_.end());
  1598. // Check a case with multiple RRSIGs
  1599. actual_rrsets_.clear();
  1600. zone_finder_.add(rr_ns_aaaa_);
  1601. zone_finder_.add(textToRRset(rrsig_aaaa_txt));
  1602. result = zone_finder_.find(Name("ns.example.org"), RRType::AAAA(),
  1603. ZoneFinder::FIND_DNSSEC);
  1604. EXPECT_EQ(ZoneFinder::SUCCESS, result->code);
  1605. ASSERT_TRUE(result->rrset);
  1606. ASSERT_TRUE(result->rrset->getRRsig());
  1607. actual_rrsets_.push_back(result->rrset->getRRsig());
  1608. rrsetsCheck(rrsig_aaaa_txt, actual_rrsets_.begin(), actual_rrsets_.end());
  1609. }
  1610. TEST_F(InMemoryZoneFinderTest, addRRsigWithoutCovered) {
  1611. // The current implementation rejects attempts of adding RRSIG without
  1612. // covered RRsets already in the zone.
  1613. // Name doesn't exist
  1614. EXPECT_THROW(zone_finder_.add(
  1615. textToRRset("notexist.example.org. 300 IN RRSIG A 5 3 "
  1616. "3600 20000101000000 20000201000000 12345 "
  1617. "example.org. FAKEFAKEFAKE\n")),
  1618. InMemoryZoneFinder::AddError);
  1619. // Name exists, but is empty.
  1620. zone_finder_.add(rr_emptywild_);
  1621. EXPECT_THROW(zone_finder_.add(
  1622. textToRRset("foo.example.org. 300 IN RRSIG A 5 3 "
  1623. "3600 20000101000000 20000201000000 12345 "
  1624. "example.org. FAKEFAKEFAKE\n")),
  1625. InMemoryZoneFinder::AddError);
  1626. // Add RRSIG RRset without covered RR
  1627. zone_finder_.add(rr_a_);
  1628. EXPECT_THROW(zone_finder_.add(textToRRset(rrsig_ns_txt)),
  1629. InMemoryZoneFinder::AddError);
  1630. }
  1631. TEST_F(InMemoryZoneFinderTest, addbadRRsig) {
  1632. // Tests with other types of bogus input
  1633. // Empty RRSIG RRset.
  1634. EXPECT_THROW(zone_finder_.add(RRsetPtr(new RRset(origin_, class_,
  1635. RRType::RRSIG(),
  1636. RRTTL(300)))),
  1637. InMemoryZoneFinder::AddError);
  1638. // RRSIG with mixed covered types
  1639. zone_finder_.add(rr_a_); // make sure the covered name exists
  1640. // textToRRset() doesn't work as intended for this pathological case,
  1641. // so we need to construct the RRset by hand.
  1642. RRsetPtr rrset(new RRset(origin_, class_, RRType::RRSIG(), RRTTL(300)));
  1643. rrset->addRdata(generic::RRSIG("A 5 3 3600 20000101000000 20000201000000 "
  1644. "12345 example.org. FAKEFAKEFAKE"));
  1645. rrset->addRdata(generic::RRSIG("NS 5 3 3600 20000101000000 20000201000000 "
  1646. "54321 example.org. FAKEFAKEFAKEFAKE"));
  1647. EXPECT_THROW(zone_finder_.add(rrset), InMemoryZoneFinder::AddError);
  1648. // An attempt of overriding an existing RRSIG. The current implementation
  1649. // prohibits that.
  1650. zone_finder_.add(textToRRset(rrsig_a_txt));
  1651. EXPECT_THROW(zone_finder_.add(textToRRset(rrsig_a_txt)),
  1652. InMemoryZoneFinder::AddError);
  1653. }
  1654. TEST_F(InMemoryZoneFinderTest, addNSEC3) {
  1655. // Set up the faked hash calculator.
  1656. setNSEC3HashCreator(&nsec3_hash_creator_);
  1657. const string nsec3_text = string(apex_hash) + ".example.org." +
  1658. string(nsec3_common);
  1659. // This name shouldn't be found in the normal domain tree.
  1660. EXPECT_EQ(result::SUCCESS, zone_finder_.add(textToRRset(nsec3_text)));
  1661. EXPECT_EQ(ZoneFinder::NXDOMAIN,
  1662. zone_finder_.find(Name(string(apex_hash) + ".example.org"),
  1663. RRType::NSEC3())->code);
  1664. // Dedicated NSEC3 find should be able to find it.
  1665. findNSEC3Check(true, origin_.getLabelCount(), nsec3_text, "",
  1666. zone_finder_.findNSEC3(Name("example.org"), false));
  1667. // This implementation rejects duplicate/update add of the same hash name
  1668. EXPECT_EQ(result::EXIST,
  1669. zone_finder_.add(textToRRset(
  1670. string(apex_hash) + ".example.org." +
  1671. string(nsec3_common) + " AAAA")));
  1672. // The original NSEC3 should be intact
  1673. findNSEC3Check(true, origin_.getLabelCount(), nsec3_text, "",
  1674. zone_finder_.findNSEC3(Name("example.org"), false));
  1675. // NSEC3-like name but of ordinary RR type should go to normal tree.
  1676. const string nonsec3_text = string(apex_hash) + ".example.org. " +
  1677. "300 IN A 192.0.2.1";
  1678. EXPECT_EQ(result::SUCCESS, zone_finder_.add(textToRRset(nonsec3_text)));
  1679. EXPECT_EQ(ZoneFinder::SUCCESS,
  1680. zone_finder_.find(Name(string(apex_hash) + ".example.org"),
  1681. RRType::A())->code);
  1682. }
  1683. TEST_F(InMemoryZoneFinderTest, addNSEC3Lower) {
  1684. // Set up the faked hash calculator.
  1685. setNSEC3HashCreator(&nsec3_hash_creator_);
  1686. // Similar to the previous case, but NSEC3 owner name is lower-cased.
  1687. const string nsec3_text = string(apex_hash_lower) + ".example.org." +
  1688. string(nsec3_common);
  1689. EXPECT_EQ(result::SUCCESS, zone_finder_.add(textToRRset(nsec3_text)));
  1690. findNSEC3Check(true, origin_.getLabelCount(), nsec3_text, "",
  1691. zone_finder_.findNSEC3(Name("example.org"), false));
  1692. }
  1693. TEST_F(InMemoryZoneFinderTest, addNSEC3Ordering) {
  1694. // Set up the faked hash calculator.
  1695. setNSEC3HashCreator(&nsec3_hash_creator_);
  1696. // Check that the internal storage ensures comparison based on the NSEC3
  1697. // semantics, regardless of the add order or the letter-case of hash.
  1698. // Adding "0P..", "2v..", then "2T..".
  1699. const string smallest = string(apex_hash) + ".example.org." +
  1700. string(nsec3_common);
  1701. const string middle = string(ns1_hash) + ".example.org." +
  1702. string(nsec3_common);
  1703. const string largest = string(xyw_hash) + ".example.org." +
  1704. string(nsec3_common);
  1705. zone_finder_.add(textToRRset(smallest));
  1706. zone_finder_.add(textToRRset(largest));
  1707. zone_finder_.add(textToRRset(middle));
  1708. // Then look for NSEC3 that covers a name whose hash is "2S.."
  1709. // The covering NSEC3 should be "0P.."
  1710. findNSEC3Check(false, 4, smallest, "",
  1711. zone_finder_.findNSEC3(Name("www.example.org"), false));
  1712. // Look for NSEC3 that covers names whose hash are "Q0.." and "0A.."
  1713. // The covering NSEC3 should be "2v.." in both cases
  1714. findNSEC3Check(false, 4, largest, "",
  1715. zone_finder_.findNSEC3(Name("xxx.example.org"), false));
  1716. findNSEC3Check(false, 4, largest, "",
  1717. zone_finder_.findNSEC3(Name("yyy.example.org"), false));
  1718. }
  1719. TEST_F(InMemoryZoneFinderTest, badNSEC3Name) {
  1720. // Our implementation refuses to load NSEC3 at a wildcard name
  1721. EXPECT_THROW(zone_finder_.add(textToRRset("*.example.org." +
  1722. string(nsec3_common))),
  1723. InMemoryZoneFinder::AddError);
  1724. // Likewise, if the owner name of NSEC3 has too many labels, it's refused.
  1725. EXPECT_THROW(zone_finder_.add(textToRRset("a." + string(apex_hash) +
  1726. ".example.org." +
  1727. string(nsec3_common))),
  1728. InMemoryZoneFinder::AddError);
  1729. }
  1730. TEST_F(InMemoryZoneFinderTest, addMultiNSEC3) {
  1731. // In this current implementation multiple NSEC3 RDATA isn't supported.
  1732. RRsetPtr nsec3(new RRset(Name(string(apex_hash) + ".example.org"),
  1733. RRClass::IN(), RRType::NSEC3(), RRTTL(300)));
  1734. nsec3->addRdata(
  1735. generic::NSEC3("1 0 12 aabbccdd 2T7B4G4VSA5SMI47K61MV5BV1A22BOJR A"));
  1736. nsec3->addRdata(
  1737. generic::NSEC3("1 1 1 ddccbbaa 2T7B4G4VSA5SMI47K61MV5BV1A22BOJR A"));
  1738. EXPECT_THROW(zone_finder_.add(nsec3), InMemoryZoneFinder::AddError);
  1739. }
  1740. TEST_F(InMemoryZoneFinderTest, addNSEC3WithRRSIG) {
  1741. // Set up the faked hash calculator.
  1742. setNSEC3HashCreator(&nsec3_hash_creator_);
  1743. // Adding NSEC3 and its RRSIG
  1744. const string nsec3_text = string(apex_hash) + ".example.org." +
  1745. string(nsec3_common);
  1746. EXPECT_EQ(result::SUCCESS, zone_finder_.add(textToRRset(nsec3_text)));
  1747. const string nsec3_rrsig_text = string(apex_hash) + ".example.org." +
  1748. string(nsec3_rrsig_common);
  1749. EXPECT_EQ(result::SUCCESS, zone_finder_.add(textToRRset(nsec3_rrsig_text)));
  1750. // Then look for it. The NSEC3 should have the RRSIG that was just added.
  1751. findNSEC3Check(true, origin_.getLabelCount(),
  1752. nsec3_text + "\n" + nsec3_rrsig_text, "",
  1753. zone_finder_.findNSEC3(Name("example.org"), false), true);
  1754. // Duplicate add of RRSIG for the same NSEC3 is prohibited.
  1755. EXPECT_THROW(zone_finder_.add(textToRRset(nsec3_rrsig_text)),
  1756. InMemoryZoneFinder::AddError);
  1757. // Same check using the lower-cased name. This also confirms matching
  1758. // is case-insensitive.
  1759. EXPECT_THROW(zone_finder_.add(textToRRset(string(apex_hash_lower) +
  1760. ".example.org."
  1761. + string(nsec3_rrsig_common))),
  1762. InMemoryZoneFinder::AddError);
  1763. }
  1764. TEST_F(InMemoryZoneFinderTest, badRRsigForNSEC3) {
  1765. // adding RRSIG for NSEC3 even before adding any NSEC3 (internally,
  1766. // a space for NSEC3 namespace isn't yet allocated)
  1767. EXPECT_THROW(zone_finder_.add(textToRRset(string(apex_hash) +
  1768. ".example.org." +
  1769. string(nsec3_rrsig_common))),
  1770. InMemoryZoneFinder::AddError);
  1771. // Add an NSEC3
  1772. EXPECT_EQ(result::SUCCESS, zone_finder_.add(
  1773. textToRRset(string(apex_hash) + ".example.org." +
  1774. string(nsec3_common))));
  1775. // Then add an NSEC3 for a non existent NSEC3. It should fail in the
  1776. // current implementation.
  1777. EXPECT_THROW(zone_finder_.add(textToRRset(string(ns1_hash) +
  1778. ".example.org." +
  1779. string(nsec3_rrsig_common))),
  1780. InMemoryZoneFinder::AddError);
  1781. }
  1782. TEST_F(InMemoryZoneFinderTest, paramConsistencyWithNSEC3PARAM) {
  1783. // First, add an NSEC3PARAM RR
  1784. EXPECT_EQ(result::SUCCESS,
  1785. zone_finder_.add(textToRRset("example.org. 300 IN NSEC3PARAM "
  1786. "1 0 12 aabbccdd")));
  1787. // Adding an NSEC3 that has matching parameters is okay.
  1788. EXPECT_EQ(result::SUCCESS, zone_finder_.add(
  1789. textToRRset(string(apex_hash) + ".example.org." +
  1790. string(nsec3_common))));
  1791. // NSEC3 with inconsistent parameter will be rejected
  1792. EXPECT_THROW(zone_finder_.add(
  1793. textToRRset("a.example.org. 300 IN NSEC3 1 0 1 aabbccdd "
  1794. "2T7B4G4VSA5SMI47K61MV5BV1A22BOJR A RRSIG")),
  1795. InMemoryZoneFinder::AddError);
  1796. }
  1797. TEST_F(InMemoryZoneFinderTest, paramConsistencyWithNSEC3) {
  1798. // Add an NSEC3 without adding NSEC3PARAM
  1799. EXPECT_EQ(result::SUCCESS, zone_finder_.add(
  1800. textToRRset(string(apex_hash) + ".example.org." +
  1801. string(nsec3_common))));
  1802. // Adding an NSEC3 with inconsistent parameter will be rejected at this pt.
  1803. EXPECT_THROW(zone_finder_.add(
  1804. textToRRset("a.example.org. 300 IN NSEC3 1 0 1 aabbccdd "
  1805. "2T7B4G4VSA5SMI47K61MV5BV1A22BOJR A RRSIG")),
  1806. InMemoryZoneFinder::AddError);
  1807. // Likewise, NSEC3PARAM with inconsistent parameter will be rejected.
  1808. EXPECT_THROW(zone_finder_.add(textToRRset("example.org. 300 IN NSEC3PARAM "
  1809. "1 0 1 aabbccdd")),
  1810. InMemoryZoneFinder::AddError);
  1811. }
  1812. TEST_F(InMemoryZoneFinderTest, multiNSEC3PARAM) {
  1813. // In this current implementation multiple NSEC3PARAM isn't supported.
  1814. RRsetPtr nsec3param(new RRset(Name("example.org"), RRClass::IN(),
  1815. RRType::NSEC3PARAM(), RRTTL(300)));
  1816. nsec3param->addRdata(generic::NSEC3PARAM("1 0 12 aabbccdd"));
  1817. nsec3param->addRdata(generic::NSEC3PARAM("1 1 1 ddccbbaa"));
  1818. EXPECT_THROW(zone_finder_.add(nsec3param), InMemoryZoneFinder::AddError);
  1819. }
  1820. TEST_F(InMemoryZoneFinderTest, nonOriginNSEC3PARAM) {
  1821. // This is a normal NSEC3PARAM at the zone origin
  1822. EXPECT_EQ(result::SUCCESS,
  1823. zone_finder_.add(textToRRset("example.org. 300 IN NSEC3PARAM "
  1824. "1 0 12 aabbccdd")));
  1825. // Add another (with different param) at a non origin node. This is
  1826. // awkward, but the implementation accepts it as an ordinary RR.
  1827. EXPECT_EQ(result::SUCCESS,
  1828. zone_finder_.add(textToRRset("a.example.org. 300 IN NSEC3PARAM "
  1829. "1 1 1 aabbccdd")));
  1830. }
  1831. TEST_F(InMemoryZoneFinderTest, loadNSEC3Zone) {
  1832. // Check if it can load validly NSEC3-signed zone. At this moment
  1833. // it's sufficient to see it doesn't crash
  1834. zone_finder_.load(TEST_DATA_DIR "/example.org.nsec3-signed");
  1835. // Reload the zone with a version that doesn't have NSEC3PARAM.
  1836. // This is an abnormal case, but the implementation accepts it.
  1837. zone_finder_.load(TEST_DATA_DIR "/example.org.nsec3-signed-noparam");
  1838. }
  1839. // This test checks that the NSEC3 names don't really exist in the real
  1840. // namespace.
  1841. TEST_F(InMemoryZoneFinderTest, queryToNSEC3Name) {
  1842. // Add the NSEC3 and NSEC3PARAM there.
  1843. EXPECT_EQ(result::SUCCESS,
  1844. zone_finder_.add(textToRRset("example.org. 300 IN NSEC3PARAM "
  1845. "1 0 12 aabbccdd")));
  1846. const Name nsec3domain(string(apex_hash) + ".example.org.");
  1847. // Adding an NSEC3 that has matching parameters is okay.
  1848. EXPECT_EQ(result::SUCCESS, zone_finder_.add(
  1849. textToRRset(string(apex_hash) + ".example.org." +
  1850. string(nsec3_common))));
  1851. // Now, the domain should not exist
  1852. findTest(nsec3domain, RRType::AAAA(), ZoneFinder::NXDOMAIN, false,
  1853. ConstRRsetPtr(), ZoneFinder::RESULT_NSEC3_SIGNED, &zone_finder_,
  1854. ZoneFinder::FIND_DNSSEC);
  1855. // If we add an A record, the domain should exist
  1856. ConstRRsetPtr rrset(textToRRset(string(apex_hash) +
  1857. ".example.org. 300 IN A 192.0.2.1"));
  1858. EXPECT_EQ(result::SUCCESS, zone_finder_.add(rrset));
  1859. // Searching for a different RRType will tell us this RRset doesn't exist
  1860. findTest(nsec3domain, RRType::AAAA(), ZoneFinder::NXRRSET, false,
  1861. ConstRRsetPtr(), ZoneFinder::RESULT_NSEC3_SIGNED, &zone_finder_,
  1862. ZoneFinder::FIND_DNSSEC);
  1863. // Searching for the A record would find it
  1864. findTest(nsec3domain, RRType::A(), ZoneFinder::SUCCESS, true,
  1865. rrset, ZoneFinder::RESULT_DEFAULT, &zone_finder_,
  1866. ZoneFinder::FIND_DNSSEC);
  1867. }
  1868. // Continuation of the previous test (queryToNSEC3Name), we check we don't break
  1869. // the empty nonterminal case by existence of NSEC3 record with that name.
  1870. TEST_F(InMemoryZoneFinderTest, queryToNSEC3NameNonterminal) {
  1871. // Add the NSEC3 and NSEC3PARAM there.
  1872. EXPECT_EQ(result::SUCCESS,
  1873. zone_finder_.add(textToRRset("example.org. 300 IN NSEC3PARAM "
  1874. "1 0 12 aabbccdd")));
  1875. const Name nsec3domain(string(apex_hash) + ".example.org.");
  1876. // Adding an NSEC3 that has matching parameters is okay.
  1877. EXPECT_EQ(result::SUCCESS, zone_finder_.add(
  1878. textToRRset(string(apex_hash) + ".example.org." +
  1879. string(nsec3_common))));
  1880. // Something below the name
  1881. ConstRRsetPtr rrset(textToRRset("below." + string(apex_hash) +
  1882. ".example.org. 300 IN A 192.0.2.1"));
  1883. EXPECT_EQ(result::SUCCESS, zone_finder_.add(rrset));
  1884. // Now, the node is empty non-terminal.
  1885. findTest(nsec3domain, RRType::AAAA(), ZoneFinder::NXRRSET, false,
  1886. ConstRRsetPtr(), ZoneFinder::RESULT_NSEC3_SIGNED, &zone_finder_,
  1887. ZoneFinder::FIND_DNSSEC);
  1888. }
  1889. TEST_F(InMemoryZoneFinderTest, findNSEC3) {
  1890. // Set up the faked hash calculator.
  1891. setNSEC3HashCreator(&nsec3_hash_creator_);
  1892. // Add a few NSEC3 records:
  1893. // apex (example.org.): hash=0P..
  1894. // ns1.example.org: hash=2T..
  1895. // w.example.org: hash=01..
  1896. // zzz.example.org: hash=R5..
  1897. const string apex_nsec3_text = string(apex_hash) + ".example.org." +
  1898. string(nsec3_common);
  1899. EXPECT_EQ(result::SUCCESS, zone_finder_.add(textToRRset(apex_nsec3_text)));
  1900. const string ns1_nsec3_text = string(ns1_hash) + ".example.org." +
  1901. string(nsec3_common);
  1902. EXPECT_EQ(result::SUCCESS, zone_finder_.add(textToRRset(ns1_nsec3_text)));
  1903. const string w_nsec3_text = string(w_hash) + ".example.org." +
  1904. string(nsec3_common);
  1905. EXPECT_EQ(result::SUCCESS, zone_finder_.add(textToRRset(w_nsec3_text)));
  1906. const string zzz_nsec3_text = string(zzz_hash) + ".example.org." +
  1907. string(nsec3_common);
  1908. EXPECT_EQ(result::SUCCESS, zone_finder_.add(textToRRset(zzz_nsec3_text)));
  1909. performNSEC3Test(zone_finder_);
  1910. }
  1911. TEST_F(InMemoryZoneFinderTest, findNSEC3ForBadZone) {
  1912. // Set up the faked hash calculator.
  1913. setNSEC3HashCreator(&nsec3_hash_creator_);
  1914. // If the zone has nothing about NSEC3 (neither NSEC3 or NSEC3PARAM),
  1915. // findNSEC3() should be rejected.
  1916. EXPECT_THROW(zone_finder_.findNSEC3(Name("www.example.org"), true),
  1917. DataSourceError);
  1918. // Only having NSEC3PARAM isn't enough
  1919. EXPECT_EQ(result::SUCCESS,
  1920. zone_finder_.add(textToRRset("example.org. 300 IN NSEC3PARAM "
  1921. "1 0 12 aabbccdd")));
  1922. EXPECT_THROW(zone_finder_.findNSEC3(Name("www.example.org"), true),
  1923. DataSourceError);
  1924. // Unless NSEC3 for apex is added the result in the recursive mode
  1925. // is guaranteed.
  1926. const string ns1_nsec3_text = string(ns1_hash) + ".example.org." +
  1927. string(nsec3_common);
  1928. EXPECT_EQ(result::SUCCESS, zone_finder_.add(textToRRset(ns1_nsec3_text)));
  1929. EXPECT_THROW(zone_finder_.findNSEC3(Name("www.example.org"), true),
  1930. DataSourceError);
  1931. }
  1932. TEST_F(InMemoryZoneFinderTest, loadAndFindNSEC3) {
  1933. // Using more realistic example, borrowed from RFC5155, with compliant
  1934. // hash calculator. We only confirm the data source can load it
  1935. // successfully and find correct NSEC3 RRs for some selected cases
  1936. // (detailed tests have been done above).
  1937. InMemoryZoneFinder finder(class_, Name("example"));
  1938. finder.load(TEST_DATA_COMMONDIR "/rfc5155-example.zone.signed");
  1939. // See RFC5155 B.1
  1940. ZoneFinder::FindNSEC3Result result1 =
  1941. finder.findNSEC3(Name("c.x.w.example"), true);
  1942. ASSERT_TRUE(result1.closest_proof);
  1943. // We compare closest_labels as int so the error report will be more
  1944. // readable in case it fails.
  1945. EXPECT_EQ(4, static_cast<int>(result1.closest_labels));
  1946. EXPECT_EQ(Name("b4um86eghhds6nea196smvmlo4ors995.example"),
  1947. result1.closest_proof->getName());
  1948. ASSERT_TRUE(result1.next_proof);
  1949. EXPECT_EQ(Name("0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example"),
  1950. result1.next_proof->getName());
  1951. // See RFC5155 B.2.
  1952. ZoneFinder::FindNSEC3Result result2 =
  1953. finder.findNSEC3(Name("ns1.example"), true);
  1954. ASSERT_TRUE(result2.closest_proof);
  1955. EXPECT_EQ(3, static_cast<int>(result2.closest_labels));
  1956. EXPECT_EQ(Name("2t7b4g4vsa5smi47k61mv5bv1a22bojr.example"),
  1957. result2.closest_proof->getName());
  1958. ASSERT_FALSE(result2.next_proof);
  1959. // See RFC5155 B.5.
  1960. ZoneFinder::FindNSEC3Result result3 =
  1961. finder.findNSEC3(Name("a.z.w.example"), true);
  1962. ASSERT_TRUE(result3.closest_proof);
  1963. EXPECT_EQ(3, static_cast<int>(result3.closest_labels));
  1964. EXPECT_EQ(Name("k8udemvp1j2f7eg6jebps17vp3n8i58h.example"),
  1965. result3.closest_proof->getName());
  1966. ASSERT_TRUE(result3.next_proof);
  1967. EXPECT_EQ(Name("q04jkcevqvmu85r014c7dkba38o0ji5r.example"),
  1968. result3.next_proof->getName());
  1969. }
  1970. }