zone_finder_context_unittest.cc 20 KB

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