zone_finder_context_unittest.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. // Copyright (C) 2012 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 <exceptions/exceptions.h>
  15. #include <dns/masterload.h>
  16. #include <dns/name.h>
  17. #include <dns/rrclass.h>
  18. #include <datasrc/zone.h>
  19. #include <datasrc/memory_datasrc.h>
  20. #include <datasrc/database.h>
  21. #include <datasrc/sqlite3_accessor.h>
  22. #include "test_client.h"
  23. #include <testutils/dnsmessage_test.h>
  24. #include <gtest/gtest.h>
  25. #include <boost/bind.hpp>
  26. #include <boost/foreach.hpp>
  27. #include <boost/shared_ptr.hpp>
  28. #include <fstream>
  29. #include <sstream>
  30. #include <vector>
  31. using namespace std;
  32. using boost::shared_ptr;
  33. using namespace isc::dns;
  34. using namespace isc::datasrc;
  35. using namespace isc::testutils;
  36. namespace {
  37. // Commonly used test zone file.
  38. const char* const TEST_ZONE_FILE = TEST_DATA_DIR "/contexttest.zone";
  39. // Convenient shortcut
  40. typedef shared_ptr<DataSourceClient> DataSourceClientPtr;
  41. // This is the type used as the test parameter. Note that this is
  42. // intentionally a plain old type (i.e. a function pointer), not a class;
  43. // otherwise it could cause initialization fiasco at the instantiation time.
  44. typedef DataSourceClientPtr (*ClientCreator)(RRClass, const Name&);
  45. // Creator for the in-memory client to be tested
  46. DataSourceClientPtr
  47. createInMemoryClient(RRClass zclass, const Name& zname) {
  48. shared_ptr<InMemoryClient> client(new InMemoryClient);
  49. shared_ptr<InMemoryZoneFinder> finder(
  50. new InMemoryZoneFinder(zclass, zname));
  51. finder->load(TEST_ZONE_FILE);
  52. client->addZone(finder);
  53. return (client);
  54. }
  55. void
  56. addRRset(ZoneUpdaterPtr updater, ConstRRsetPtr rrset) {
  57. updater->addRRset(*rrset);
  58. }
  59. DataSourceClientPtr
  60. createSQLite3Client(RRClass zclass, const Name& zname) {
  61. // We always begin with an empty template SQLite3 DB file and install
  62. // the zone data from the zone file to ensure both cases have the
  63. // same test data.
  64. DataSourceClientPtr client = unittest::createSQLite3Client(
  65. zclass, zname, TEST_DATA_BUILDDIR "/contexttest.sqlite3.copied",
  66. TEST_ZONE_FILE);
  67. // Insert an out-of-zone name to test if it's incorrectly returned.
  68. // Note that neither updater nor SQLite3 accessor checks this condition,
  69. // so this should succeed.
  70. ZoneUpdaterPtr updater = client->getUpdater(zname, false);
  71. stringstream ss("ns.example.com. 3600 IN A 192.0.2.7");
  72. masterLoad(ss, Name::ROOT_NAME(), zclass,
  73. boost::bind(addRRset, updater, _1));
  74. updater->commit();
  75. return (client);
  76. }
  77. // The test class. Its parameterized so we can share the test scnearios
  78. // for any concrete data source implementaitons.
  79. class ZoneFinderContextTest :
  80. public ::testing::TestWithParam<ClientCreator>
  81. {
  82. protected:
  83. ZoneFinderContextTest() : qclass_(RRClass::IN()), qzone_("example.org") {
  84. client_ = (*GetParam())(qclass_, qzone_);
  85. REQUESTED_A.push_back(RRType::A());
  86. REQUESTED_AAAA.push_back(RRType::AAAA());
  87. REQUESTED_BOTH.push_back(RRType::A());
  88. REQUESTED_BOTH.push_back(RRType::AAAA());
  89. }
  90. void SetUp() {
  91. finder_ = client_->findZone(qzone_).zone_finder;
  92. ASSERT_TRUE(finder_);
  93. }
  94. const RRClass qclass_;
  95. const Name qzone_;
  96. DataSourceClientPtr client_;
  97. ZoneFinderPtr finder_;
  98. vector<RRType> requested_types_;
  99. vector<RRType> REQUESTED_A;
  100. vector<RRType> REQUESTED_AAAA;
  101. vector<RRType> REQUESTED_BOTH;
  102. vector<ConstRRsetPtr> result_sets_;
  103. };
  104. // We test the in-memory and SQLite3 data source implementations.
  105. INSTANTIATE_TEST_CASE_P(, ZoneFinderContextTest,
  106. ::testing::Values(createInMemoryClient,
  107. createSQLite3Client));
  108. TEST_P(ZoneFinderContextTest, getAdditionalAuthNS) {
  109. ZoneFinderContextPtr ctx = finder_->find(qzone_, RRType::NS());
  110. EXPECT_EQ(ZoneFinder::SUCCESS, ctx->code);
  111. // Getting both A and AAAA NS addresses
  112. ctx->getAdditional(REQUESTED_BOTH, result_sets_);
  113. rrsetsCheck("ns1.example.org. 3600 IN A 192.0.2.1\n"
  114. "ns1.example.org. 3600 IN AAAA 2001:db8::1\n"
  115. "ns2.example.org. 3600 IN A 192.0.2.2\n",
  116. result_sets_.begin(), result_sets_.end());
  117. // Getting only A
  118. result_sets_.clear();
  119. ctx->getAdditional(REQUESTED_A, result_sets_);
  120. rrsetsCheck("ns1.example.org. 3600 IN A 192.0.2.1\n"
  121. "ns2.example.org. 3600 IN A 192.0.2.2\n",
  122. result_sets_.begin(), result_sets_.end());
  123. // Getting only AAAA
  124. result_sets_.clear();
  125. ctx->getAdditional(REQUESTED_AAAA, result_sets_);
  126. rrsetsCheck("ns1.example.org. 3600 IN AAAA 2001:db8::1\n",
  127. result_sets_.begin(), result_sets_.end());
  128. // Getting A again, without clearing the result sets. This confirms
  129. // getAdditional() doesn't change the existing vector content.
  130. ctx->getAdditional(REQUESTED_A, result_sets_);
  131. // The first element should be the existing AAAA RR, followed by the A's.
  132. EXPECT_EQ(RRType::AAAA(), result_sets_[0]->getType());
  133. rrsetsCheck("ns1.example.org. 3600 IN AAAA 2001:db8::1\n"
  134. "ns1.example.org. 3600 IN A 192.0.2.1\n"
  135. "ns2.example.org. 3600 IN A 192.0.2.2\n",
  136. result_sets_.begin(), result_sets_.end());
  137. // Normally expected type set contain only A and/or AAAA, but others aren't
  138. // excluded.
  139. result_sets_.clear();
  140. requested_types_.push_back(RRType::TXT());
  141. ctx->getAdditional(requested_types_, result_sets_);
  142. rrsetsCheck("ns2.example.org. 3600 IN TXT \"text data\"",
  143. result_sets_.begin(), result_sets_.end());
  144. // Even empty set is okay. The result should also be empty.
  145. result_sets_.clear();
  146. ctx->getAdditional(vector<RRType>(), result_sets_);
  147. EXPECT_TRUE(result_sets_.empty());
  148. }
  149. TEST_P(ZoneFinderContextTest, getAdditionalDelegation) {
  150. // Basically similar to the AuthNS case, but NS names are glues.
  151. // It contains an out-of-zone NS name. Its address (even if it's somehow
  152. // inserted to the zone data) shouldn't be returned.
  153. const Name qname("www.a.example.org");
  154. ZoneFinderContextPtr ctx = finder_->find(qname, RRType::AAAA());
  155. EXPECT_EQ(ZoneFinder::DELEGATION, ctx->code);
  156. ctx->getAdditional(REQUESTED_BOTH, result_sets_);
  157. rrsetsCheck("ns1.a.example.org. 3600 IN A 192.0.2.5\n"
  158. "ns2.a.example.org. 3600 IN A 192.0.2.6\n"
  159. "ns2.a.example.org. 3600 IN AAAA 2001:db8::6\n",
  160. result_sets_.begin(), result_sets_.end());
  161. result_sets_.clear();
  162. ctx->getAdditional(REQUESTED_A, result_sets_);
  163. rrsetsCheck("ns1.a.example.org. 3600 IN A 192.0.2.5\n"
  164. "ns2.a.example.org. 3600 IN A 192.0.2.6\n",
  165. result_sets_.begin(), result_sets_.end());
  166. result_sets_.clear();
  167. ctx->getAdditional(REQUESTED_AAAA, result_sets_);
  168. rrsetsCheck("ns2.a.example.org. 3600 IN AAAA 2001:db8::6\n",
  169. result_sets_.begin(), result_sets_.end());
  170. }
  171. TEST_P(ZoneFinderContextTest, getAdditionalDelegationAtZoneCut) {
  172. // Similar to the previous case, but one of the NS addresses is at the
  173. // zone cut.
  174. ZoneFinderContextPtr ctx = finder_->find(Name("www.b.example.org"),
  175. RRType::SOA());
  176. EXPECT_EQ(ZoneFinder::DELEGATION, ctx->code);
  177. ctx->getAdditional(REQUESTED_BOTH, result_sets_);
  178. rrsetsCheck("b.example.org. 3600 IN AAAA 2001:db8::8\n"
  179. "ns.b.example.org. 3600 IN A 192.0.2.9\n",
  180. result_sets_.begin(), result_sets_.end());
  181. }
  182. TEST_P(ZoneFinderContextTest, getAdditionalDelegationWithDname) {
  183. // Delegation: One of the NS names under a DNAME delegation; another
  184. // is at the delegation point; yet another is under DNAME below a zone cut.
  185. // The first should be hidden.
  186. ZoneFinderContextPtr ctx = finder_->find(Name("www.c.example.org"),
  187. RRType::TXT());
  188. EXPECT_EQ(ZoneFinder::DELEGATION, ctx->code);
  189. ctx->getAdditional(REQUESTED_BOTH, result_sets_);
  190. rrsetsCheck("dname.example.org. 3600 IN A 192.0.2.12\n"
  191. "ns.deepdname.example.org. 3600 IN AAAA 2001:db8::9\n",
  192. result_sets_.begin(), result_sets_.end());
  193. }
  194. TEST_P(ZoneFinderContextTest, getAdditionalDelegationWithEmptyName) {
  195. // One of NS names is at an empty non terminal node. It shouldn't cause
  196. // any disruption.
  197. ZoneFinderContextPtr ctx = finder_->find(Name("www.d.example.org"),
  198. RRType::A());
  199. EXPECT_EQ(ZoneFinder::DELEGATION, ctx->code);
  200. ctx->getAdditional(REQUESTED_BOTH, result_sets_);
  201. rrsetsCheck("ns1.example.org. 3600 IN A 192.0.2.1\n"
  202. "ns1.example.org. 3600 IN AAAA 2001:db8::1\n",
  203. result_sets_.begin(), result_sets_.end());
  204. }
  205. TEST_P(ZoneFinderContextTest, getAdditionalDelegationWithWild) {
  206. // An NS name needs to be expanded by a wildcard. Another NS name
  207. // also matches a wildcard, but it's an empty node, so there's no
  208. // corresponding additional RR. The other NS name isn't subject to
  209. // wildcard expansion, which shouldn't cause any disruption.
  210. ZoneFinderContextPtr ctx = finder_->find(Name("www.e.example.org"),
  211. RRType::AAAA());
  212. EXPECT_EQ(ZoneFinder::DELEGATION, ctx->code);
  213. ctx->getAdditional(REQUESTED_BOTH, result_sets_);
  214. rrsetsCheck("ns.wild.example.org. 3600 IN A 192.0.2.15\n"
  215. "ns2.example.org. 3600 IN A 192.0.2.2\n",
  216. result_sets_.begin(), result_sets_.end());
  217. // ns.wild.example.org/A (expanded from a wildcard) should be considered
  218. // the same kind, whether it's a direct result of find() or a result of
  219. // getAdditional().
  220. ctx = finder_->find(Name("ns.wild.example.org"), RRType::A());
  221. EXPECT_EQ(ZoneFinder::SUCCESS, ctx->code);
  222. for (vector<ConstRRsetPtr>::const_iterator it = result_sets_.begin();
  223. it != result_sets_.end(); ++it) {
  224. const bool same_kind = (*it)->isSameKind(*ctx->rrset);
  225. EXPECT_EQ((*it)->getName() == ctx->rrset->getName(), same_kind);
  226. }
  227. }
  228. TEST_P(ZoneFinderContextTest, getAdditionalDelegationForWild) {
  229. // additional for an answer RRset (MX) as a result of wildcard expansion.
  230. // note the difference from the previous test. in this case wildcard
  231. // applies to the owner name of the answer, not the owner name of the
  232. // additional.
  233. ZoneFinderContextPtr ctx = finder_->find(Name("mx.wildmx.example.org"),
  234. RRType::MX());
  235. EXPECT_EQ(ZoneFinder::SUCCESS, ctx->code);
  236. ctx->getAdditional(REQUESTED_BOTH, result_sets_);
  237. rrsetsCheck("mx1.example.org. 3600 IN A 192.0.2.10\n",
  238. result_sets_.begin(), result_sets_.end());
  239. }
  240. TEST_P(ZoneFinderContextTest, getAdditionalMX) {
  241. // Similar to the previous cases, but for MX addresses. The test zone
  242. // contains MX name under a zone cut. Its address shouldn't be returned.
  243. ZoneFinderContextPtr ctx = finder_->find(qzone_, RRType::MX());
  244. EXPECT_EQ(ZoneFinder::SUCCESS, ctx->code);
  245. // Getting both A and AAAA NS addresses
  246. ctx->getAdditional(REQUESTED_BOTH, result_sets_);
  247. rrsetsCheck("mx1.example.org. 3600 IN A 192.0.2.10\n"
  248. "mx2.example.org. 3600 IN AAAA 2001:db8::10\n",
  249. result_sets_.begin(), result_sets_.end());
  250. // Getting only A
  251. result_sets_.clear();
  252. ctx->getAdditional(REQUESTED_A, result_sets_);
  253. rrsetsCheck("mx1.example.org. 3600 IN A 192.0.2.10\n",
  254. result_sets_.begin(), result_sets_.end());
  255. // Getting only AAAA
  256. result_sets_.clear();
  257. ctx->getAdditional(REQUESTED_AAAA, result_sets_);
  258. rrsetsCheck("mx2.example.org. 3600 IN AAAA 2001:db8::10\n",
  259. result_sets_.begin(), result_sets_.end());
  260. }
  261. TEST_P(ZoneFinderContextTest, getAdditionalMXAtZoneCut) {
  262. ZoneFinderContextPtr ctx = finder_->find(Name("mxatcut.example.org."),
  263. RRType::MX());
  264. EXPECT_EQ(ZoneFinder::SUCCESS, ctx->code);
  265. ctx->getAdditional(REQUESTED_BOTH, result_sets_);
  266. EXPECT_TRUE(result_sets_.empty());
  267. }
  268. TEST_P(ZoneFinderContextTest, getAdditionalWithSIG) {
  269. // Similar to the AuthNS test, but the original find() requested DNSSEC
  270. // RRSIGs. Then additional records will also have RRSIGs.
  271. ZoneFinderContextPtr ctx = finder_->find(qzone_, RRType::NS(),
  272. ZoneFinder::FIND_DNSSEC);
  273. EXPECT_EQ(ZoneFinder::SUCCESS, ctx->code);
  274. ctx->getAdditional(REQUESTED_BOTH, result_sets_);
  275. rrsetsCheck("ns1.example.org. 3600 IN A 192.0.2.1\n"
  276. "ns1.example.org. 3600 IN RRSIG A 7 3 3600 20150420235959 "
  277. "20051021000000 40430 example.org. FAKEFAKE\n"
  278. "ns1.example.org. 3600 IN AAAA 2001:db8::1\n"
  279. "ns1.example.org. 3600 IN RRSIG AAAA 7 3 3600 20150420235959 "
  280. "20051021000000 40430 example.org. FAKEFAKEFAKE\n"
  281. "ns2.example.org. 3600 IN A 192.0.2.2\n",
  282. result_sets_.begin(), result_sets_.end());
  283. vector<ConstRRsetPtr> sigresult_sets;
  284. BOOST_FOREACH(ConstRRsetPtr rrset, result_sets_) {
  285. ConstRRsetPtr sig_rrset = rrset->getRRsig();
  286. if (sig_rrset) {
  287. sigresult_sets.push_back(sig_rrset);
  288. }
  289. }
  290. rrsetsCheck("ns1.example.org. 3600 IN RRSIG A 7 3 3600 20150420235959 "
  291. "20051021000000 40430 example.org. FAKEFAKE\n"
  292. "ns1.example.org. 3600 IN RRSIG AAAA 7 3 3600 20150420235959 "
  293. "20051021000000 40430 example.org. FAKEFAKEFAKE\n",
  294. sigresult_sets.begin(), sigresult_sets.end());
  295. }
  296. TEST_P(ZoneFinderContextTest, getAdditionalNoOP) {
  297. // getAdditional() is only meaningful after SUCCESS or DELEGATION.
  298. ZoneFinderContextPtr ctx = finder_->find(Name("nxdomain.example.org"),
  299. RRType::NS());
  300. EXPECT_EQ(ZoneFinder::NXDOMAIN, ctx->code);
  301. ctx->getAdditional(REQUESTED_BOTH, result_sets_);
  302. EXPECT_TRUE(result_sets_.empty());
  303. ctx = finder_->find(qzone_, RRType::TXT());
  304. EXPECT_EQ(ZoneFinder::NXRRSET, ctx->code);
  305. ctx->getAdditional(REQUESTED_BOTH, result_sets_);
  306. EXPECT_TRUE(result_sets_.empty());
  307. ctx = finder_->find(Name("alias.example.org."), RRType::A());
  308. EXPECT_EQ(ZoneFinder::CNAME, ctx->code);
  309. ctx->getAdditional(REQUESTED_BOTH, result_sets_);
  310. EXPECT_TRUE(result_sets_.empty());
  311. ctx = finder_->find(Name("www.dname.example.org."), RRType::A());
  312. EXPECT_EQ(ZoneFinder::DNAME, ctx->code);
  313. ctx->getAdditional(REQUESTED_BOTH, result_sets_);
  314. EXPECT_TRUE(result_sets_.empty());
  315. }
  316. TEST_P(ZoneFinderContextTest, getAdditionalForAny) {
  317. // getAdditional() after successful type ANY query should return
  318. // the additional records of all returned RRsets.
  319. vector<ConstRRsetPtr> all_rrsets;
  320. ZoneFinderContextPtr ctx = finder_->findAll(qzone_, all_rrsets);
  321. EXPECT_EQ(ZoneFinder::SUCCESS, ctx->code);
  322. ctx->getAdditional(REQUESTED_BOTH, result_sets_);
  323. rrsetsCheck("ns1.example.org. 3600 IN A 192.0.2.1\n"
  324. "ns1.example.org. 3600 IN AAAA 2001:db8::1\n"
  325. "ns2.example.org. 3600 IN A 192.0.2.2\n"
  326. "mx1.example.org. 3600 IN A 192.0.2.10\n"
  327. "mx2.example.org. 3600 IN AAAA 2001:db8::10\n",
  328. result_sets_.begin(), result_sets_.end());
  329. // If the type ANY query results in DELEGATION, the result should be the
  330. // same as normal query.
  331. all_rrsets.clear();
  332. result_sets_.clear();
  333. ctx = finder_->findAll(Name("www.a.example.org"), all_rrsets);
  334. EXPECT_EQ(ZoneFinder::DELEGATION, ctx->code);
  335. ctx->getAdditional(REQUESTED_BOTH, result_sets_);
  336. rrsetsCheck("ns1.a.example.org. 3600 IN A 192.0.2.5\n"
  337. "ns2.a.example.org. 3600 IN A 192.0.2.6\n"
  338. "ns2.a.example.org. 3600 IN AAAA 2001:db8::6\n",
  339. result_sets_.begin(), result_sets_.end());
  340. }
  341. }