rdataset_unittest.cc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  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 <util/buffer.h>
  16. #include <util/memory_segment_local.h>
  17. #include <dns/rdata.h>
  18. #include <dns/rdataclass.h>
  19. #include <dns/rrset.h>
  20. #include <dns/rrclass.h>
  21. #include <dns/rrtype.h>
  22. #include <dns/rrttl.h>
  23. #include <datasrc/memory/segment_object_holder.h>
  24. #include <datasrc/memory/rdata_serialization.h>
  25. #include <datasrc/memory/rdataset.h>
  26. #include <testutils/dnsmessage_test.h>
  27. #include <gtest/gtest.h>
  28. #include <boost/lexical_cast.hpp>
  29. #include <string>
  30. using namespace isc::dns;
  31. using namespace isc::dns::rdata;
  32. using namespace isc::datasrc::memory;
  33. using namespace isc::testutils;
  34. using isc::datasrc::memory::detail::SegmentObjectHolder;
  35. using boost::lexical_cast;
  36. namespace {
  37. class RdataSetTest : public ::testing::Test {
  38. protected:
  39. RdataSetTest() :
  40. // 1076895760 = 0x40302010. Use this so we fill in all 8-bit "field"
  41. // of the 32-bit TTL
  42. a_rrset_(textToRRset("www.example.com. 1076895760 IN A 192.0.2.1")),
  43. rrsig_rrset_(textToRRset("www.example.com. 1076895760 IN RRSIG "
  44. "A 5 2 3600 20120814220826 20120715220826 "
  45. "1234 example.com. FAKE"))
  46. {}
  47. void TearDown() {
  48. EXPECT_TRUE(mem_sgmt_.allMemoryDeallocated());
  49. }
  50. ConstRRsetPtr a_rrset_, rrsig_rrset_;
  51. isc::util::MemorySegmentLocal mem_sgmt_;
  52. RdataEncoder encoder_;
  53. };
  54. // Convert the given 32-bit integer (network byte order) to the corresponding
  55. // RRTTL object.
  56. RRTTL
  57. restoreTTL(const void* ttl_data) {
  58. isc::util::InputBuffer b(ttl_data, sizeof(uint32_t));
  59. return (RRTTL(b));
  60. }
  61. // A helper callback for checkRdataSet. This confirms the given data
  62. // is the expected in::A RDATA (the value is taken from the RdataSetTest
  63. // constructor).
  64. void
  65. checkData(const void* data, size_t size) {
  66. isc::util::InputBuffer b(data, size);
  67. EXPECT_EQ(0, in::A(b, size).compare(in::A("192.0.2.1")));
  68. }
  69. // This is a set of checks for an RdataSet created with some simple
  70. // conditions. with_rrset/with_rrsig is true iff the RdataSet is supposed to
  71. // contain normal/RRSIG RDATA.
  72. void
  73. checkRdataSet(const RdataSet& rdataset, bool with_rrset, bool with_rrsig) {
  74. EXPECT_FALSE(rdataset.next); // by default the next pointer should be NULL
  75. EXPECT_EQ(RRType::A(), rdataset.type);
  76. // See the RdataSetTest constructor for the magic number.
  77. EXPECT_EQ(RRTTL(1076895760), restoreTTL(rdataset.getTTLData()));
  78. EXPECT_EQ(with_rrset ? 1 : 0, rdataset.getRdataCount());
  79. EXPECT_EQ(with_rrsig ? 1 : 0, rdataset.getSigRdataCount());
  80. // A simple test for the data content. Details tests for the encoder/
  81. // reader should be basically sufficient for various cases of the data,
  82. // and the fact that this test doesn't detect memory leak should be
  83. // reasonably sufficient that the implementation handles the data region
  84. // correctly. Here we check one simple case for a simple form of RDATA,
  85. // mainly for checking the behavior of getDataBuf().
  86. RdataReader reader(RRClass::IN(), RRType::A(),
  87. reinterpret_cast<const uint8_t*>(
  88. rdataset.getDataBuf()),
  89. rdataset.getRdataCount(), rdataset.getSigRdataCount(),
  90. &RdataReader::emptyNameAction, checkData);
  91. reader.iterate();
  92. }
  93. TEST_F(RdataSetTest, create) {
  94. // A simple case of creating an RdataSet. Confirming the resulting
  95. // fields have the expected values, and then destroying it (TearDown()
  96. // would detect any memory leak)
  97. RdataSet* rdataset = RdataSet::create(mem_sgmt_, encoder_, a_rrset_,
  98. ConstRRsetPtr());
  99. checkRdataSet(*rdataset, true, false);
  100. RdataSet::destroy(mem_sgmt_, rdataset, RRClass::IN());
  101. }
  102. TEST_F(RdataSetTest, getNext) {
  103. RdataSet* rdataset = RdataSet::create(mem_sgmt_, encoder_, a_rrset_,
  104. ConstRRsetPtr());
  105. // By default, the next pointer should be NULL (already tested in other
  106. // test cases), which should be the case with getNext(). We test both
  107. // mutable and immutable versions of getNext().
  108. EXPECT_EQ(static_cast<RdataSet*>(NULL), rdataset->getNext());
  109. EXPECT_EQ(static_cast<const RdataSet*>(NULL),
  110. static_cast<const RdataSet*>(rdataset)->getNext());
  111. // making a link (it would form an infinite loop, but it doesn't matter
  112. // in this test), and check the pointer returned by getNext().
  113. rdataset->next = rdataset;
  114. EXPECT_EQ(rdataset, static_cast<const RdataSet*>(rdataset)->getNext());
  115. RdataSet::destroy(mem_sgmt_, rdataset, RRClass::IN());
  116. }
  117. TEST_F(RdataSetTest, find) {
  118. // Create some RdataSets and make a chain of them.
  119. SegmentObjectHolder<RdataSet, RRClass> holder1(
  120. mem_sgmt_,
  121. RdataSet::create(mem_sgmt_, encoder_, a_rrset_, ConstRRsetPtr()),
  122. RRClass::IN());
  123. ConstRRsetPtr aaaa_rrset =
  124. textToRRset("www.example.com. 1076895760 IN AAAA 2001:db8::1");
  125. SegmentObjectHolder<RdataSet, RRClass> holder2(
  126. mem_sgmt_,
  127. RdataSet::create(mem_sgmt_, encoder_, aaaa_rrset, ConstRRsetPtr()),
  128. RRClass::IN());
  129. ConstRRsetPtr sigonly_rrset =
  130. textToRRset("www.example.com. 1076895760 IN RRSIG "
  131. "TXT 5 2 3600 20120814220826 20120715220826 "
  132. "1234 example.com. FAKE");
  133. SegmentObjectHolder<RdataSet, RRClass> holder3(
  134. mem_sgmt_,
  135. RdataSet::create(mem_sgmt_, encoder_, ConstRRsetPtr(), sigonly_rrset),
  136. RRClass::IN());
  137. RdataSet* rdataset_a = holder1.get();
  138. RdataSet* rdataset_aaaa = holder2.get();
  139. RdataSet* rdataset_sigonly = holder3.get();
  140. RdataSet* rdataset_null = NULL;
  141. rdataset_a->next = rdataset_aaaa;
  142. rdataset_aaaa->next = rdataset_sigonly;
  143. // If a non-RRSIG part of rdataset exists for the given type, it will be
  144. // returned regardless of the value of sigonly_ok. If it's RRSIG-only
  145. // rdataset, it returns non NULL iff sigonly_ok is explicitly set to true.
  146. EXPECT_EQ(rdataset_aaaa, RdataSet::find(rdataset_a, RRType::AAAA()));
  147. EXPECT_EQ(rdataset_aaaa, RdataSet::find(rdataset_a, RRType::AAAA(), true));
  148. EXPECT_EQ(rdataset_aaaa, RdataSet::find(rdataset_a, RRType::AAAA(), false));
  149. EXPECT_EQ(rdataset_null, RdataSet::find(rdataset_a, RRType::TXT()));
  150. EXPECT_EQ(rdataset_sigonly, RdataSet::find(rdataset_a, RRType::TXT(),
  151. true));
  152. EXPECT_EQ(rdataset_null, RdataSet::find(rdataset_a, RRType::TXT(), false));
  153. // Same tests for the const version of find().
  154. const RdataSet* rdataset_a_const = holder1.get();
  155. EXPECT_EQ(rdataset_aaaa, RdataSet::find(rdataset_a_const, RRType::AAAA()));
  156. EXPECT_EQ(rdataset_aaaa, RdataSet::find(rdataset_a_const, RRType::AAAA(),
  157. true));
  158. EXPECT_EQ(rdataset_aaaa, RdataSet::find(rdataset_a_const, RRType::AAAA(),
  159. false));
  160. EXPECT_EQ(rdataset_null, RdataSet::find(rdataset_a_const, RRType::TXT()));
  161. EXPECT_EQ(rdataset_sigonly, RdataSet::find(rdataset_a_const, RRType::TXT(),
  162. true));
  163. EXPECT_EQ(rdataset_null, RdataSet::find(rdataset_a_const, RRType::TXT(),
  164. false));
  165. }
  166. // A helper function to create an RRset containing the given number of
  167. // unique RDATAs.
  168. ConstRRsetPtr
  169. getRRsetWithRdataCount(size_t rdata_count) {
  170. RRsetPtr rrset(new RRset(Name("example.com"), RRClass::IN(), RRType::TXT(),
  171. RRTTL(3600)));
  172. for (size_t i = 0; i < rdata_count; ++i) {
  173. rrset->addRdata(rdata::createRdata(RRType::TXT(), RRClass::IN(),
  174. lexical_cast<std::string>(i)));
  175. }
  176. return (rrset);
  177. }
  178. TEST_F(RdataSetTest, createManyRRs) {
  179. // RRset with possible maximum number of RDATAs
  180. RdataSet* rdataset = RdataSet::create(mem_sgmt_, encoder_,
  181. getRRsetWithRdataCount(8191),
  182. ConstRRsetPtr());
  183. EXPECT_EQ(8191, rdataset->getRdataCount());
  184. EXPECT_EQ(0, rdataset->getSigRdataCount());
  185. RdataSet::destroy(mem_sgmt_, rdataset, RRClass::IN());
  186. // Exceeding that will result in an exception.
  187. EXPECT_THROW(RdataSet::create(mem_sgmt_, encoder_,
  188. getRRsetWithRdataCount(8192),
  189. ConstRRsetPtr()),
  190. RdataSetError);
  191. // To be very sure even try larger number than the threshold
  192. EXPECT_THROW(RdataSet::create(mem_sgmt_, encoder_,
  193. getRRsetWithRdataCount(65535),
  194. ConstRRsetPtr()),
  195. RdataSetError);
  196. }
  197. TEST_F(RdataSetTest, createWithRRSIG) {
  198. // Normal case.
  199. RdataSet* rdataset = RdataSet::create(mem_sgmt_, encoder_, a_rrset_,
  200. rrsig_rrset_);
  201. checkRdataSet(*rdataset, true, true);
  202. RdataSet::destroy(mem_sgmt_, rdataset, RRClass::IN());
  203. // Unusual case: TTL doesn't match. This implementation accepts that,
  204. // using the TTL of the covered RRset.
  205. ConstRRsetPtr rrsig_badttl(textToRRset(
  206. "www.example.com. 3600 IN RRSIG "
  207. "A 5 2 3600 20120814220826 "
  208. "20120715220826 1234 example.com. FAKE"));
  209. rdataset = RdataSet::create(mem_sgmt_, encoder_, a_rrset_, rrsig_badttl);
  210. checkRdataSet(*rdataset, true, true);
  211. RdataSet::destroy(mem_sgmt_, rdataset, RRClass::IN());
  212. }
  213. // A helper function to create an RRSIG RRset containing the given number of
  214. // unique RDATAs.
  215. ConstRRsetPtr
  216. getRRSIGWithRdataCount(size_t sig_count) {
  217. RRsetPtr rrset(new RRset(Name("example.com"), RRClass::IN(),
  218. RRType::RRSIG(), RRTTL(3600)));
  219. // We use a base wire-format image and tweak the original TTL field to
  220. // generate unique RDATAs in the loop. (Creating them from corresponding
  221. // text is simpler, but doing so for a large number of RRSIGs is
  222. // relatively heavy and could be too long for unittests).
  223. ConstRdataPtr rrsig_base =
  224. rdata::createRdata(RRType::RRSIG(), RRClass::IN(),
  225. "A 5 2 3600 20120814220826 20120715220826 1234 "
  226. "example.com. FAKE");
  227. isc::util::OutputBuffer ob(0);
  228. rrsig_base->toWire(ob);
  229. for (size_t i = 0; i < sig_count; ++i) {
  230. ob.writeUint16At((i >> 16) & 0xffff, 4);
  231. ob.writeUint16At(i & 0xffff, 6);
  232. isc::util::InputBuffer ib(ob.getData(), ob.getLength());
  233. rrset->addRdata(rdata::createRdata(RRType::RRSIG(), RRClass::IN(),
  234. ib, ib.getLength()));
  235. }
  236. return (rrset);
  237. }
  238. TEST_F(RdataSetTest, createManyRRSIGs) {
  239. // 7 has a special meaning in the implementation: if the number of the
  240. // RRSIGs reaches this value, an extra 'sig count' field will be created.
  241. RdataSet* rdataset = RdataSet::create(mem_sgmt_, encoder_, a_rrset_,
  242. getRRSIGWithRdataCount(7));
  243. EXPECT_EQ(7, rdataset->getSigRdataCount());
  244. RdataSet::destroy(mem_sgmt_, rdataset, RRClass::IN());
  245. // 8 would cause overflow in the normal 3-bit field if there were no extra
  246. // count field.
  247. rdataset = RdataSet::create(mem_sgmt_, encoder_, a_rrset_,
  248. getRRSIGWithRdataCount(8));
  249. EXPECT_EQ(8, rdataset->getSigRdataCount());
  250. RdataSet::destroy(mem_sgmt_, rdataset, RRClass::IN());
  251. // Up to 2^16-1 RRSIGs are allowed (although that would be useless
  252. // in practice)
  253. rdataset = RdataSet::create(mem_sgmt_, encoder_, a_rrset_,
  254. getRRSIGWithRdataCount(65535));
  255. EXPECT_EQ(65535, rdataset->getSigRdataCount());
  256. RdataSet::destroy(mem_sgmt_, rdataset, RRClass::IN());
  257. // Exceeding this limit will result in an exception.
  258. EXPECT_THROW(RdataSet::create(mem_sgmt_, encoder_, a_rrset_,
  259. getRRSIGWithRdataCount(65536)),
  260. RdataSetError);
  261. // To be very sure even try larger number than the threshold
  262. EXPECT_THROW(RdataSet::create(mem_sgmt_, encoder_, a_rrset_,
  263. getRRSIGWithRdataCount(70000)),
  264. RdataSetError);
  265. }
  266. TEST_F(RdataSetTest, createWithRRSIGOnly) {
  267. // A rare, but allowed, case: RdataSet without the main RRset but with
  268. // RRSIG.
  269. RdataSet* rdataset = RdataSet::create(mem_sgmt_, encoder_, ConstRRsetPtr(),
  270. rrsig_rrset_);
  271. checkRdataSet(*rdataset, false, true);
  272. RdataSet::destroy(mem_sgmt_, rdataset, RRClass::IN());
  273. }
  274. TEST_F(RdataSetTest, badCeate) {
  275. // Neither the RRset nor RRSIG RRset is given
  276. EXPECT_THROW(RdataSet::create(mem_sgmt_, encoder_, ConstRRsetPtr(),
  277. ConstRRsetPtr()), isc::BadValue);
  278. // Empty RRset (An RRset without RDATA)
  279. ConstRRsetPtr empty_rrset(new RRset(Name("example.com"), RRClass::IN(),
  280. RRType::A(), RRTTL(3600)));
  281. EXPECT_THROW(RdataSet::create(mem_sgmt_, encoder_, empty_rrset,
  282. ConstRRsetPtr()), isc::BadValue);
  283. ConstRRsetPtr empty_rrsig(new RRset(Name("example.com"), RRClass::IN(),
  284. RRType::RRSIG(), RRTTL(3600)));
  285. EXPECT_THROW(RdataSet::create(mem_sgmt_, encoder_, ConstRRsetPtr(),
  286. empty_rrsig), isc::BadValue);
  287. // The RRset type and RRSIG's type covered don't match
  288. ConstRRsetPtr bad_rrsig(textToRRset(
  289. "www.example.com. 1076895760 IN RRSIG "
  290. "NS 5 2 3600 20120814220826 20120715220826 "
  291. "1234 example.com. FAKE"));
  292. EXPECT_THROW(RdataSet::create(mem_sgmt_, encoder_, a_rrset_, bad_rrsig),
  293. isc::BadValue);
  294. // Pass non RRSIG for the sig parameter
  295. EXPECT_THROW(RdataSet::create(mem_sgmt_, encoder_, a_rrset_, a_rrset_),
  296. isc::BadValue);
  297. // Pass RRSIG for normal RRset (the RdataEncoder will catch this and throw)
  298. EXPECT_THROW(RdataSet::create(mem_sgmt_, encoder_, rrsig_rrset_,
  299. rrsig_rrset_),
  300. isc::BadValue);
  301. // RR class doesn't match between RRset and RRSIG
  302. ConstRRsetPtr badclass_rrsig(textToRRset(
  303. "www.example.com. 1076895760 CH RRSIG "
  304. "A 5 2 3600 20120814220826 "
  305. "20120715220826 1234 example.com. FAKE",
  306. RRClass::CH()));
  307. EXPECT_THROW(RdataSet::create(mem_sgmt_, encoder_, a_rrset_,
  308. badclass_rrsig),
  309. isc::BadValue);
  310. }
  311. }