rdata_encoder_unittest.cc 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  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 <dns/name.h>
  17. #include <dns/labelsequence.h>
  18. #include <dns/messagerenderer.h>
  19. #include <dns/rdata.h>
  20. #include <dns/rdataclass.h>
  21. #include <dns/rrclass.h>
  22. #include <dns/rrtype.h>
  23. #include <datasrc/memory/rdata_encoder.h>
  24. #include <util/unittests/wiredata.h>
  25. #include <gtest/gtest.h>
  26. #include <boost/bind.hpp>
  27. #include <boost/foreach.hpp>
  28. #include <cstring>
  29. #include <set>
  30. #include <string>
  31. #include <vector>
  32. using namespace isc::dns;
  33. using namespace isc::dns::rdata;
  34. using namespace isc::datasrc::memory;
  35. using namespace isc::datasrc::memory::testing;
  36. using isc::util::unittests::matchWireData;
  37. using std::string;
  38. using std::vector;
  39. namespace {
  40. // This defines a tuple of test data used in test_rdata_list below.
  41. struct TestRdata {
  42. const char* const rrclass; // RR class, textual form
  43. const char* const rrtype; // RR type, textual form
  44. const char* const rdata; // textual RDATA
  45. const size_t n_varlen_fields; // expected # of variable-len fields
  46. };
  47. // This test data consist of (almost) all supported types of RDATA (+ some
  48. // unusual and corner cases).
  49. const TestRdata test_rdata_list[] = {
  50. {"IN", "A", "192.0.2.1", 0},
  51. {"IN", "NS", "ns.example.com", 0},
  52. {"IN", "CNAME", "cname.example.com", 0},
  53. {"IN", "SOA", "ns.example.com root.example.com 0 0 0 0 0", 0},
  54. {"IN", "PTR", "reverse.example.com", 0},
  55. {"IN", "HINFO", "\"cpu-info\" \"OS-info\"", 1},
  56. {"IN", "MINFO", "root.example.com mbox.example.com", 0},
  57. {"IN", "MX", "10 mx.example.com", 0},
  58. {"IN", "TXT", "\"test1\" \"test 2\"", 1},
  59. {"IN", "RP", "root.example.com. rp-text.example.com", 0},
  60. {"IN", "AFSDB", "1 afsdb.example.com", 0},
  61. {"IN", "AAAA", "2001:db8::1", 0},
  62. {"IN", "SRV", "1 0 10 target.example.com", 0},
  63. {"IN", "NAPTR", "100 50 \"s\" \"http\" \"\" _http._tcp.example.com", 1},
  64. {"IN", "DNAME", "dname.example.com", 0},
  65. {"IN", "DS", "12892 5 2 5F0EB5C777586DE18DA6B5", 1},
  66. {"IN", "SSHFP", "1 1 dd465c09cfa51fb45020cc83316fff", 1},
  67. // We handle RRSIG separately, so it's excluded from the list
  68. {"IN", "NSEC", "next.example.com. A AAAA NSEC RRSIG", 1},
  69. {"IN", "DNSKEY", "256 3 5 FAKEFAKE", 1},
  70. {"IN", "DHCID", "FAKEFAKE", 1},
  71. {"IN", "NSEC3", "1 1 12 AABBCCDD FAKEFAKE A RRSIG", 1},
  72. {"IN", "NSEC3PARAM", "1 0 12 AABBCCDD", 1},
  73. {"IN", "SPF", "v=spf1 +mx a:colo.example.com/28 -all", 1},
  74. {"IN", "DLV", "12892 5 2 5F0EB5C777586DE18DA6B5", 1},
  75. {"IN", "TYPE65000", "\\# 3 010203", 1}, // some "custom" type
  76. {"IN", "TYPE65535", "\\# 0", 1}, // max RR type, 0-length RDATA
  77. {"CH", "A", "\\# 2 0102", 1}, // A RR for non-IN class; varlen data
  78. {"CH", "NS", "ns.example.com", 0}, // class CH, generic data
  79. {"CH", "TXT", "BIND10", 1}, // ditto
  80. {"HS", "A", "\\# 5 0102030405", 1}, // A RR for non-IN class; varlen data
  81. {NULL, NULL, NULL, 0}
  82. };
  83. // The following two functions will be used to generate wire format data
  84. // from encoded representation of each RDATA.
  85. void
  86. renderNameField(MessageRenderer* renderer, bool additional_required,
  87. const LabelSequence& labels, RdataNameAttributes attributes)
  88. {
  89. EXPECT_EQ(additional_required,
  90. (attributes & NAMEATTR_ADDITIONAL) != 0);
  91. renderer->writeName(labels, (attributes & NAMEATTR_COMPRESSIBLE) != 0);
  92. }
  93. void
  94. renderDataField(MessageRenderer* renderer, const uint8_t* data,
  95. size_t data_len)
  96. {
  97. renderer->writeData(data, data_len);
  98. }
  99. class RdataEncoderTest : public ::testing::Test {
  100. protected:
  101. RdataEncoderTest() : a_rdata_(createRdata(RRType::A(), RRClass::IN(),
  102. "192.0.2.53")),
  103. aaaa_rdata_(createRdata(RRType::AAAA(), RRClass::IN(),
  104. "2001:db8::53")),
  105. rrsig_rdata_(createRdata(
  106. RRType::RRSIG(), RRClass::IN(),
  107. "A 5 2 3600 20120814220826 "
  108. "20120715220826 12345 com. FAKE"))
  109. {}
  110. // This helper test method constructs encodes the given list of RDATAs
  111. // (in rdata_list), and then iterates over the data, rendering the fields
  112. // in the wire format. It then compares the wire data with the one
  113. // generated by the normal libdns++ interface to see the encoding/decoding
  114. // works as intended.
  115. void checkEncode(RRClass rrclass, RRType rrtype,
  116. const vector<ConstRdataPtr>& rdata_list,
  117. size_t expected_varlen_fields,
  118. const vector<ConstRdataPtr>& rrsig_list);
  119. // A wraper for RdataEncoder::encode() with buffer overrun check.
  120. void encodeWrapper(size_t data_len);
  121. void addRdataCommon(const vector<ConstRdataPtr>& rrsigs);
  122. void addRdataMultiCommon(const vector<ConstRdataPtr>& rrsigs);
  123. // Some commonly used RDATA
  124. const ConstRdataPtr a_rdata_;
  125. const ConstRdataPtr aaaa_rdata_;
  126. const ConstRdataPtr rrsig_rdata_;
  127. RdataEncoder encoder_;
  128. vector<uint8_t> encoded_data_;
  129. MessageRenderer expected_renderer_;
  130. MessageRenderer actual_renderer_;
  131. vector<ConstRdataPtr> rdata_list_;
  132. };
  133. void
  134. RdataEncoderTest::encodeWrapper(size_t data_len) {
  135. // make sure the data buffer is large enough for the canary
  136. encoded_data_.resize(data_len + 2);
  137. // set the canary data
  138. encoded_data_.at(data_len) = 0xde;
  139. encoded_data_.at(data_len + 1) = 0xad;
  140. // encode, then check the canary is intact
  141. encoder_.encode(&encoded_data_[0], data_len);
  142. EXPECT_EQ(0xde, encoded_data_.at(data_len));
  143. EXPECT_EQ(0xad, encoded_data_.at(data_len + 1));
  144. // shrink the data buffer to the originally expected size (some tests
  145. // expect that). the actual encoded data should be intact.
  146. encoded_data_.resize(data_len);
  147. }
  148. void
  149. RdataEncoderTest::checkEncode(RRClass rrclass, RRType rrtype,
  150. const vector<ConstRdataPtr>& rdata_list,
  151. size_t expected_varlen_fields,
  152. const vector<ConstRdataPtr>& rrsig_list =
  153. vector<ConstRdataPtr>())
  154. {
  155. // These two names will be rendered before and after the test RDATA,
  156. // to check in case the RDATA contain a domain name whether it's
  157. // compressed or not correctly. The names in the RDATA should basically
  158. // a subdomain of example.com, so it can be compressed due to dummy_name.
  159. // Likewise, dummy_name2 should be able to be fully compressed due to
  160. // the name in the RDATA.
  161. const Name dummy_name("com");
  162. const Name dummy_name2("example.com");
  163. // The set of RR types that require additional section processing.
  164. // We'll pass it to renderNameField to check the stored attribute matches
  165. // our expectation.
  166. std::set<RRType> need_additionals;
  167. need_additionals.insert(RRType::NS());
  168. need_additionals.insert(RRType::MX());
  169. need_additionals.insert(RRType::SRV());
  170. expected_renderer_.clear();
  171. actual_renderer_.clear();
  172. encoded_data_.clear();
  173. const bool additional_required =
  174. (need_additionals.find(rrtype) != need_additionals.end());
  175. // Build expected wire-format data
  176. expected_renderer_.writeName(dummy_name);
  177. BOOST_FOREACH(const ConstRdataPtr& rdata, rdata_list) {
  178. rdata->toWire(expected_renderer_);
  179. }
  180. expected_renderer_.writeName(dummy_name2);
  181. BOOST_FOREACH(const ConstRdataPtr& rdata, rrsig_list) {
  182. rdata->toWire(expected_renderer_);
  183. }
  184. // Then build wire format data using the encoded data.
  185. // 1st dummy name
  186. actual_renderer_.writeName(dummy_name);
  187. // Create encoded data
  188. encoder_.start(rrclass, rrtype);
  189. BOOST_FOREACH(const ConstRdataPtr& rdata, rdata_list) {
  190. encoder_.addRdata(*rdata);
  191. }
  192. BOOST_FOREACH(const ConstRdataPtr& rdata, rrsig_list) {
  193. encoder_.addSIGRdata(*rdata);
  194. }
  195. encodeWrapper(encoder_.getStorageLength());
  196. // If this type of RDATA is expected to contain variable-length fields,
  197. // we brute force the encoded data, exploiting our knowledge of actual
  198. // encoding, then adjust the encoded data excluding the list of length
  199. // fields. This is ugly, but we should be able to eliminate this hack
  200. // at #2096.
  201. vector<uint16_t> varlen_list;
  202. if (expected_varlen_fields > 0) {
  203. const size_t varlen_list_size =
  204. rdata_list.size() * expected_varlen_fields * sizeof(uint16_t);
  205. ASSERT_LE(varlen_list_size, encoded_data_.size());
  206. varlen_list.resize(rdata_list.size() * expected_varlen_fields);
  207. std::memcpy(&varlen_list[0], &encoded_data_[0], varlen_list_size);
  208. encoded_data_.assign(encoded_data_.begin() + varlen_list_size,
  209. encoded_data_.end());
  210. }
  211. // If RRSIGs are given, we need to extract the list of the RRSIG lengths
  212. // and adjust encoded_data_ further (this will be unnecessary at #2096,
  213. // too).
  214. vector<uint16_t> rrsiglen_list;
  215. if (rrsig_list.size() > 0) {
  216. const size_t rrsig_len_size = rrsig_list.size() * sizeof(uint16_t);
  217. ASSERT_LE(rrsig_len_size, encoded_data_.size());
  218. rrsiglen_list.resize(rrsig_list.size() * rrsig_len_size);
  219. std::memcpy(&rrsiglen_list[0], &encoded_data_[0], rrsig_len_size);
  220. encoded_data_.assign(encoded_data_.begin() + rrsig_len_size,
  221. encoded_data_.end());
  222. }
  223. // Create wire-format data from the encoded data
  224. foreachRdataField(rrclass, rrtype, rdata_list.size(), encoded_data_,
  225. varlen_list,
  226. boost::bind(renderNameField, &actual_renderer_,
  227. additional_required, _1, _2),
  228. boost::bind(renderDataField, &actual_renderer_, _1, _2));
  229. // 2nd dummy name
  230. actual_renderer_.writeName(dummy_name2);
  231. // Finally, dump any RRSIGs in wire format.
  232. foreachRRSig(encoded_data_, rrsiglen_list,
  233. boost::bind(renderDataField, &actual_renderer_, _1, _2));
  234. // Two sets of wire-format data should be identical.
  235. matchWireData(expected_renderer_.getData(), expected_renderer_.getLength(),
  236. actual_renderer_.getData(), actual_renderer_.getLength());
  237. }
  238. void
  239. RdataEncoderTest::addRdataCommon(const vector<ConstRdataPtr>& rrsigs) {
  240. // Basic check on the encoded data for (most of) all supported RR types,
  241. // in a comprehensive manner.
  242. for (size_t i = 0; test_rdata_list[i].rrclass != NULL; ++i) {
  243. SCOPED_TRACE(string(test_rdata_list[i].rrclass) + "/" +
  244. test_rdata_list[i].rrtype);
  245. const RRClass rrclass(test_rdata_list[i].rrclass);
  246. const RRType rrtype(test_rdata_list[i].rrtype);
  247. const ConstRdataPtr rdata = createRdata(rrtype, rrclass,
  248. test_rdata_list[i].rdata);
  249. rdata_list_.clear();
  250. rdata_list_.push_back(rdata);
  251. checkEncode(rrclass, rrtype, rdata_list_,
  252. test_rdata_list[i].n_varlen_fields, rrsigs);
  253. }
  254. }
  255. TEST_F(RdataEncoderTest, addRdata) {
  256. vector<ConstRdataPtr> rrsigs;
  257. addRdataCommon(rrsigs); // basic tests without RRSIGs (empty vector)
  258. // Test with RRSIGs (covered type doesn't always match, but the encoder
  259. // doesn't check that)
  260. rrsigs.push_back(rrsig_rdata_);
  261. addRdataCommon(rrsigs);
  262. }
  263. void
  264. RdataEncoderTest::addRdataMultiCommon(const vector<ConstRdataPtr>& rrsigs) {
  265. // Similar to addRdata(), but test with multiple RDATAs.
  266. // Four different cases are tested: a single fixed-len RDATA (A),
  267. // fixed-len data + domain name (MX), variable-len data only (TXT),
  268. // variable-len data + domain name (NAPTR).
  269. ConstRdataPtr a_rdata2 = createRdata(RRType::A(), RRClass::IN(),
  270. "192.0.2.54");
  271. rdata_list_.clear();
  272. rdata_list_.push_back(a_rdata_);
  273. rdata_list_.push_back(a_rdata2);
  274. checkEncode(RRClass::IN(), RRType::A(), rdata_list_, 0, rrsigs);
  275. ConstRdataPtr mx_rdata1 = createRdata(RRType::MX(), RRClass::IN(),
  276. "5 mx1.example.com");
  277. ConstRdataPtr mx_rdata2 = createRdata(RRType::MX(), RRClass::IN(),
  278. "10 mx2.example.com");
  279. rdata_list_.clear();
  280. rdata_list_.push_back(mx_rdata1);
  281. rdata_list_.push_back(mx_rdata2);
  282. checkEncode(RRClass::IN(), RRType::MX(), rdata_list_, 0, rrsigs);
  283. ConstRdataPtr txt_rdata1 = createRdata(RRType::TXT(), RRClass::IN(),
  284. "foo bar baz");
  285. ConstRdataPtr txt_rdata2 = createRdata(RRType::TXT(), RRClass::IN(),
  286. "another text data");
  287. rdata_list_.clear();
  288. rdata_list_.push_back(txt_rdata1);
  289. rdata_list_.push_back(txt_rdata2);
  290. checkEncode(RRClass::IN(), RRType::TXT(), rdata_list_, 1, rrsigs);
  291. ConstRdataPtr naptr_rdata1 =
  292. createRdata(RRType::NAPTR(), RRClass::IN(),
  293. "100 50 \"s\" \"http\" \"\" _http._tcp.example.com");
  294. ConstRdataPtr naptr_rdata2 =
  295. createRdata(RRType::NAPTR(), RRClass::IN(),
  296. "200 100 \"s\" \"http\" \"\" _http._tcp.example.com");
  297. rdata_list_.clear();
  298. rdata_list_.push_back(naptr_rdata1);
  299. rdata_list_.push_back(naptr_rdata2);
  300. checkEncode(RRClass::IN(), RRType::NAPTR(), rdata_list_, 1, rrsigs);
  301. }
  302. TEST_F(RdataEncoderTest, encodeLargeRdata) {
  303. // There should be no reason for a large RDATA to fail in encoding,
  304. // but we check such a case explicitly.
  305. encoded_data_.resize(65535); // max unsigned 16-bit int
  306. isc::util::InputBuffer buffer(&encoded_data_[0], encoded_data_.size());
  307. const in::DHCID large_dhcid(buffer, encoded_data_.size());
  308. encoder_.start(RRClass::IN(), RRType::DHCID());
  309. encoder_.addRdata(large_dhcid);
  310. encodeWrapper(encoder_.getStorageLength());
  311. // The encoded data should be identical to the original one.
  312. ASSERT_LT(sizeof(uint16_t), encoder_.getStorageLength());
  313. isc::util::InputBuffer ib(&encoded_data_[2], encoded_data_.size() - 2);
  314. const in::DHCID encoded_dhcid(ib, ib.getLength());
  315. EXPECT_EQ(0, encoded_dhcid.compare(large_dhcid));
  316. }
  317. TEST_F(RdataEncoderTest, addRdataMulti) {
  318. vector<ConstRdataPtr> rrsigs;
  319. addRdataMultiCommon(rrsigs); // test without RRSIGs (empty vector)
  320. // Tests with two RRSIGs
  321. rrsigs.push_back(rrsig_rdata_);
  322. rrsigs.push_back(createRdata(RRType::RRSIG(), RRClass::IN(),
  323. "A 5 2 3600 20120814220826 "
  324. "20120715220826 54321 com. FAKE"));
  325. addRdataMultiCommon(rrsigs);
  326. }
  327. TEST_F(RdataEncoderTest, badAddRdata) {
  328. // Some operations must follow start().
  329. EXPECT_THROW(encoder_.addRdata(*a_rdata_), isc::InvalidOperation);
  330. EXPECT_THROW(encoder_.getStorageLength(), isc::InvalidOperation);
  331. // will allocate space of some arbitrary size (256 bytes)
  332. EXPECT_THROW(encodeWrapper(256), isc::InvalidOperation);
  333. // Bad buffer for encode
  334. encoder_.start(RRClass::IN(), RRType::A());
  335. encoder_.addRdata(*a_rdata_);
  336. const size_t buf_len = encoder_.getStorageLength();
  337. // NULL buffer for encode
  338. EXPECT_THROW(encoder_.encode(NULL, buf_len), isc::BadValue);
  339. // buffer length is too short (we don't use the wrraper because we don't
  340. // like to tweak the length arg to encode()).
  341. encoded_data_.resize(buf_len - 1);
  342. EXPECT_THROW(encoder_.encode(&encoded_data_[0], buf_len - 1),
  343. isc::BadValue);
  344. // Type of RDATA and the specified RR type don't match. addRdata() should
  345. // detect this inconsistency.
  346. encoder_.start(RRClass::IN(), RRType::AAAA());
  347. EXPECT_THROW(encoder_.addRdata(*a_rdata_), isc::BadValue);
  348. // Likewise.
  349. encoder_.start(RRClass::IN(), RRType::A());
  350. EXPECT_THROW(encoder_.addRdata(*aaaa_rdata_), isc::BadValue);
  351. // Likewise. The encoder expects the first name completes the data, and
  352. // throws on the second due as an unexpected name field.
  353. const ConstRdataPtr rp_rdata =
  354. createRdata(RRType::RP(), RRClass::IN(), "a.example. b.example");
  355. encoder_.start(RRClass::IN(), RRType::NS());
  356. EXPECT_THROW(encoder_.addRdata(*rp_rdata), isc::BadValue);
  357. // Likewise. The encoder considers the name data a variable length data
  358. // field, and throws on the first name.
  359. encoder_.start(RRClass::IN(), RRType::DHCID());
  360. EXPECT_THROW(encoder_.addRdata(*rp_rdata), isc::BadValue);
  361. // Likewise. The text RDATA (2 bytes) will be treated as MX preference,
  362. // and the encoder will still expect to see a domain name.
  363. const ConstRdataPtr txt_rdata = createRdata(RRType::TXT(), RRClass::IN(),
  364. "a");
  365. encoder_.start(RRClass::IN(), RRType::MX());
  366. EXPECT_THROW(encoder_.addRdata(*txt_rdata), isc::BadValue);
  367. // Similar to the previous one, but in this case there's no data field
  368. // in the spec.
  369. encoder_.start(RRClass::IN(), RRType::NS());
  370. EXPECT_THROW(encoder_.addRdata(*txt_rdata), isc::BadValue);
  371. // Likewise. Inconsistent name compression policy.
  372. const ConstRdataPtr ns_rdata =
  373. createRdata(RRType::NS(), RRClass::IN(), "ns.example");
  374. encoder_.start(RRClass::IN(), RRType::DNAME());
  375. EXPECT_THROW(encoder_.addRdata(*ns_rdata), isc::BadValue);
  376. // Same as the previous one, opposite inconsistency.
  377. const ConstRdataPtr dname_rdata =
  378. createRdata(RRType::DNAME(), RRClass::IN(), "dname.example");
  379. encoder_.start(RRClass::IN(), RRType::NS());
  380. EXPECT_THROW(encoder_.addRdata(*dname_rdata), isc::BadValue);
  381. // RDATA len exceeds the 16-bit range. Technically not invalid, but
  382. // we don't support that (and it's practically useless anyway).
  383. encoded_data_.resize(65536); // use encoded_data_ for placeholder
  384. isc::util::InputBuffer buffer(&encoded_data_[0], encoded_data_.size());
  385. encoder_.start(RRClass::IN(), RRType::DHCID());
  386. EXPECT_THROW(encoder_.addRdata(in::DHCID(buffer, encoded_data_.size())),
  387. RdataEncodingError);
  388. // RRSIG cannot be used as the main RDATA type (can only be added as
  389. // a signature for some other type of RDATAs).
  390. EXPECT_THROW(encoder_.start(RRClass::IN(), RRType::RRSIG()),
  391. isc::BadValue);
  392. }
  393. TEST_F(RdataEncoderTest, addSIGRdataOnly) {
  394. // Encoded data that only contain RRSIGs. Mostly useless, but can happen
  395. // (in a partially broken zone) and it's accepted.
  396. encoder_.start(RRClass::IN(), RRType::A());
  397. encoder_.addSIGRdata(*rrsig_rdata_);
  398. encodeWrapper(encoder_.getStorageLength());
  399. ASSERT_LT(sizeof(uint16_t), encoder_.getStorageLength());
  400. // The encoded data should be identical to the given one.
  401. isc::util::InputBuffer ib(&encoded_data_[2], encoded_data_.size() - 2);
  402. const generic::RRSIG encoded_sig(ib, ib.getLength());
  403. EXPECT_EQ(0, encoded_sig.compare(*rrsig_rdata_));
  404. }
  405. TEST_F(RdataEncoderTest, badAddSIGRdata) {
  406. // try adding SIG before start
  407. EXPECT_THROW(encoder_.addSIGRdata(*rrsig_rdata_), isc::InvalidOperation);
  408. // Very big RRSIG. This implementation rejects it.
  409. isc::util::OutputBuffer ob(0);
  410. rrsig_rdata_->toWire(ob);
  411. // append dummy trailing signature to make it too big
  412. vector<uint8_t> dummy_sig(65536 - ob.getLength());
  413. ob.writeData(&dummy_sig[0], dummy_sig.size());
  414. ASSERT_EQ(65536, ob.getLength());
  415. isc::util::InputBuffer ib(ob.getData(), ob.getLength());
  416. const generic::RRSIG big_sigrdata(ib, ob.getLength());
  417. encoder_.start(RRClass::IN(), RRType::A());
  418. EXPECT_THROW(encoder_.addSIGRdata(big_sigrdata), RdataEncodingError);
  419. }
  420. }