rdatafields_unittest.cc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  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 <vector>
  15. #include <exceptions/exceptions.h>
  16. #include <util/buffer.h>
  17. #include <dns/messagerenderer.h>
  18. #include <dns/name.h>
  19. #include <dns/rdata.h>
  20. #include <dns/rdataclass.h>
  21. #include <dns/rdatafields.h>
  22. #include <dns/tests/unittest_util.h>
  23. #include <gtest/gtest.h>
  24. using isc::UnitTestUtil;
  25. using namespace std;
  26. using namespace isc::dns;
  27. using namespace isc::dns::rdata;
  28. using isc::util::OutputBuffer;
  29. using isc::util::InputBuffer;
  30. namespace {
  31. class RdataFieldsTest : public ::testing::Test {
  32. protected:
  33. RdataFieldsTest() : obuffer(0), ns_name("example.com"),
  34. other_name("www.example.com")
  35. {}
  36. void constructCommonTests(const RdataFields& fields,
  37. const uint8_t* const expected_data,
  38. const size_t expected_data_len);
  39. void constructCommonTestsNS(const RdataFields& fields);
  40. void constructCommonTestsTXT(const RdataFields& fields);
  41. void constructCommonTestsRRSIG(const RdataFields& fields);
  42. void constructCommonTestsOPT(const RdataFields& fields);
  43. OutputBuffer obuffer;
  44. MessageRenderer renderer;
  45. const Name ns_name;
  46. const Name other_name;
  47. vector<unsigned char> expected_wire;
  48. vector<unsigned char> fields_wire;
  49. };
  50. const uint8_t in_a_data[] = { 192, 0, 2, 1 };
  51. // binary representation of example.com.
  52. const uint8_t ns_data[] = { 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65,
  53. 0x03, 0x63, 0x6f, 0x6d, 0x00 };
  54. //
  55. // IN/A RDATA: fixed length, single data field
  56. //
  57. void
  58. RdataFieldsTest::constructCommonTests(const RdataFields& fields,
  59. const uint8_t* const expected_data,
  60. const size_t expected_data_len)
  61. {
  62. EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, expected_data,
  63. expected_data_len, fields.getData(),
  64. fields.getDataLength());
  65. EXPECT_EQ(sizeof(RdataFields::FieldSpec), fields.getFieldSpecDataSize());
  66. EXPECT_EQ(1, fields.getFieldCount());
  67. EXPECT_EQ(RdataFields::DATA, fields.getFieldSpec(0).type);
  68. EXPECT_EQ(4, fields.getFieldSpec(0).len);
  69. fields.toWire(obuffer);
  70. EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, expected_data,
  71. expected_data_len, obuffer.getData(),
  72. obuffer.getLength());
  73. fields.toWire(renderer);
  74. EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, expected_data,
  75. expected_data_len, renderer.getData(),
  76. renderer.getLength());
  77. }
  78. TEST_F(RdataFieldsTest, constructFromRdata) {
  79. const RdataFields fields(in::A("192.0.2.1"));
  80. constructCommonTests(fields, in_a_data, sizeof(in_a_data));
  81. }
  82. TEST_F(RdataFieldsTest, constructFromParams) {
  83. const RdataFields::FieldSpec spec(RdataFields::DATA, 4);
  84. const RdataFields fields(&spec, sizeof(spec), in_a_data,
  85. sizeof(in_a_data));
  86. constructCommonTests(fields, in_a_data, sizeof(in_a_data));
  87. }
  88. //
  89. // NS RDATA: containing a compressible name.
  90. //
  91. void
  92. RdataFieldsTest::constructCommonTestsNS(const RdataFields& fields) {
  93. EXPECT_EQ(sizeof(RdataFields::FieldSpec), fields.getFieldSpecDataSize());
  94. EXPECT_EQ(1, fields.getFieldCount());
  95. EXPECT_EQ(RdataFields::COMPRESSIBLE_NAME, fields.getFieldSpec(0).type);
  96. EXPECT_EQ(ns_name.getLength(), fields.getFieldSpec(0).len);
  97. expected_wire.clear();
  98. UnitTestUtil::readWireData("rdatafields1.wire", expected_wire);
  99. other_name.toWire(obuffer);
  100. fields.toWire(obuffer);
  101. EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, &expected_wire[0],
  102. expected_wire.size(), obuffer.getData(),
  103. obuffer.getLength());
  104. expected_wire.clear();
  105. UnitTestUtil::readWireData("rdatafields2.wire", expected_wire);
  106. other_name.toWire(renderer);
  107. fields.toWire(renderer);
  108. EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, &expected_wire[0],
  109. expected_wire.size(), renderer.getData(),
  110. renderer.getLength());
  111. }
  112. TEST_F(RdataFieldsTest, constructFromRdataNS) {
  113. const RdataFields fields_ns((generic::NS(ns_name)));
  114. constructCommonTestsNS(fields_ns);
  115. }
  116. TEST_F(RdataFieldsTest, constructFromParamsNS) {
  117. const RdataFields::FieldSpec spec(RdataFields::COMPRESSIBLE_NAME,
  118. sizeof(ns_data));
  119. const RdataFields fields_ns(&spec, sizeof(spec), ns_data, sizeof(ns_data));
  120. constructCommonTestsNS(fields_ns);
  121. }
  122. //
  123. // TXT RDATA: multiple fields, lengths vary
  124. //
  125. void
  126. RdataFieldsTest::constructCommonTestsTXT(const RdataFields& fields) {
  127. // Since all fields are plain data, they are handled as a single data
  128. // field.
  129. EXPECT_EQ(sizeof(RdataFields::FieldSpec), fields.getFieldSpecDataSize());
  130. EXPECT_EQ(1, fields.getFieldCount());
  131. EXPECT_EQ(RdataFields::DATA, fields.getFieldSpec(0).type);
  132. EXPECT_EQ(expected_wire.size(), fields.getFieldSpec(0).len);
  133. fields.toWire(obuffer);
  134. EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, &expected_wire[0],
  135. expected_wire.size(), obuffer.getData(),
  136. obuffer.getLength());
  137. fields.toWire(renderer);
  138. EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, &expected_wire[0],
  139. expected_wire.size(), renderer.getData(),
  140. renderer.getLength());
  141. }
  142. TEST_F(RdataFieldsTest, constructFromRdataTXT) {
  143. UnitTestUtil::readWireData("rdatafields3.wire", expected_wire);
  144. InputBuffer ibuffer(&expected_wire[0], expected_wire.size());
  145. const uint16_t rdlen = ibuffer.readUint16();
  146. const RdataFields fields(generic::TXT(ibuffer, rdlen));
  147. // drop the RDLEN part
  148. expected_wire.erase(expected_wire.begin(), expected_wire.begin() + 2);
  149. constructCommonTestsTXT(fields);
  150. }
  151. TEST_F(RdataFieldsTest, constructFromParamsTXT) {
  152. UnitTestUtil::readWireData("rdatafields3.wire", expected_wire);
  153. expected_wire.erase(expected_wire.begin(), expected_wire.begin() + 2);
  154. const RdataFields::FieldSpec spec(RdataFields::DATA, expected_wire.size());
  155. const RdataFields fields(&spec, sizeof(spec), &expected_wire[0],
  156. expected_wire.size());
  157. constructCommonTestsTXT(fields);
  158. }
  159. //
  160. // RRSIG: multiple fields, with an incompressible name
  161. //
  162. void
  163. RdataFieldsTest::constructCommonTestsRRSIG(const RdataFields& fields) {
  164. // In terms of RdataFields RRSIG RDATA consists of 3 fields:
  165. // - 18-byte data field (from the "type covered" field to "key tag" field)
  166. // - an incompressible name field (for the signer's name field).
  167. // this is a variable length field. In this test it's a 13-byte field.
  168. // - a variable-length data field for the signature. In this tests
  169. // it's a 15-byte field.
  170. EXPECT_EQ(3 * sizeof(RdataFields::FieldSpec),
  171. fields.getFieldSpecDataSize());
  172. EXPECT_EQ(3, fields.getFieldCount());
  173. EXPECT_EQ(RdataFields::DATA, fields.getFieldSpec(0).type);
  174. EXPECT_EQ(18, fields.getFieldSpec(0).len);
  175. EXPECT_EQ(RdataFields::INCOMPRESSIBLE_NAME, fields.getFieldSpec(1).type);
  176. EXPECT_EQ(13, fields.getFieldSpec(1).len);
  177. EXPECT_EQ(RdataFields::DATA, fields.getFieldSpec(2).type);
  178. EXPECT_EQ(15, fields.getFieldSpec(2).len);
  179. expected_wire.clear();
  180. UnitTestUtil::readWireData("rdatafields5.wire", expected_wire);
  181. Name("com").toWire(obuffer);
  182. obuffer.writeUint16(fields.getDataLength());
  183. fields.toWire(obuffer);
  184. other_name.toWire(obuffer);
  185. EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, &expected_wire[0],
  186. expected_wire.size(), obuffer.getData(),
  187. obuffer.getLength());
  188. expected_wire.clear();
  189. UnitTestUtil::readWireData("rdatafields6.wire", expected_wire);
  190. Name("com").toWire(renderer);
  191. renderer.writeUint16(fields.getDataLength());
  192. fields.toWire(renderer); // the signer field won't be compressed
  193. other_name.toWire(renderer); // but will be used as a compression target
  194. EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, &expected_wire[0],
  195. expected_wire.size(), renderer.getData(),
  196. renderer.getLength());
  197. }
  198. TEST_F(RdataFieldsTest, constructFromRdataRRSIG) {
  199. UnitTestUtil::readWireData("rdatafields4.wire", expected_wire);
  200. InputBuffer ibuffer(&expected_wire[0], expected_wire.size());
  201. const uint16_t rdlen = ibuffer.readUint16();
  202. const RdataFields fields(generic::RRSIG(ibuffer, rdlen));
  203. // drop the RDLEN part
  204. expected_wire.erase(expected_wire.begin(), expected_wire.begin() + 2);
  205. constructCommonTestsRRSIG(fields);
  206. }
  207. TEST_F(RdataFieldsTest, constructFromParamsRRSIG) {
  208. UnitTestUtil::readWireData("rdatafields4.wire", fields_wire);
  209. fields_wire.erase(fields_wire.begin(), fields_wire.begin() + 2);
  210. const RdataFields::FieldSpec specs[] = {
  211. RdataFields::FieldSpec(RdataFields::DATA, 18),
  212. RdataFields::FieldSpec(RdataFields::INCOMPRESSIBLE_NAME, 13),
  213. RdataFields::FieldSpec(RdataFields::DATA, 15)
  214. };
  215. const RdataFields fields(specs, sizeof(specs), &fields_wire[0],
  216. fields_wire.size());
  217. constructCommonTestsRRSIG(fields);
  218. }
  219. TEST_F(RdataFieldsTest, convertRdatatoParams) {
  220. // Confirm we can restore the original data from the serialized data.
  221. // We use RRSIG as a relatively complicated field structure.
  222. UnitTestUtil::readWireData("rdatafields4.wire", expected_wire);
  223. InputBuffer ibuffer(&expected_wire[0], expected_wire.size());
  224. const uint16_t rdlen = ibuffer.readUint16();
  225. const RdataFields fields(generic::RRSIG(ibuffer, rdlen));
  226. expected_wire.erase(expected_wire.begin(), expected_wire.begin() + 2);
  227. // Copy the data in separate storage
  228. vector<uint8_t> spec_store(fields.getFieldSpecDataSize());
  229. void* cp_spec = &spec_store[0];
  230. memcpy(cp_spec, fields.getFieldSpecData(), spec_store.size());
  231. vector<uint8_t> data_store(fields.getDataLength());
  232. memcpy(&data_store[0], fields.getData(), fields.getDataLength());
  233. // Restore the data in the form of RdataFields
  234. const RdataFields fields_byparams(cp_spec, fields.getFieldSpecDataSize(),
  235. &data_store[0], fields.getDataLength());
  236. // Check it's valid
  237. constructCommonTestsRRSIG(fields_byparams);
  238. }
  239. //
  240. // OPT: an empty RDATA
  241. //
  242. void
  243. RdataFieldsTest::constructCommonTestsOPT(const RdataFields& fields) {
  244. EXPECT_EQ(0, fields.getFieldSpecDataSize());
  245. EXPECT_EQ(0, fields.getFieldCount());
  246. EXPECT_EQ(0, fields.getDataLength());
  247. EXPECT_EQ((const uint8_t*) NULL, fields.getData());
  248. fields.toWire(obuffer);
  249. EXPECT_EQ(0, obuffer.getLength());
  250. fields.toWire(renderer);
  251. EXPECT_EQ(0, renderer.getLength());
  252. }
  253. TEST_F(RdataFieldsTest, constructFromRdataOPT) {
  254. InputBuffer ibuffer(NULL, 0);
  255. const RdataFields fields(generic::OPT(ibuffer, 0));
  256. constructCommonTestsOPT(fields);
  257. }
  258. TEST_F(RdataFieldsTest, constructFromParamsOPT) {
  259. const RdataFields fields(NULL, 0, NULL, 0);
  260. constructCommonTestsOPT(fields);
  261. }
  262. // Invalid input to the "from parameter" constructor: sum of the field lengths
  263. // is not equal to the data length.
  264. TEST_F(RdataFieldsTest, invalidFieldLength) {
  265. UnitTestUtil::readWireData("rdatafields4.wire", fields_wire);
  266. fields_wire.erase(fields_wire.begin(), fields_wire.begin() + 2);
  267. const RdataFields::FieldSpec specs[] = {
  268. RdataFields::FieldSpec(RdataFields::DATA, 18),
  269. RdataFields::FieldSpec(RdataFields::INCOMPRESSIBLE_NAME, 13),
  270. RdataFields::FieldSpec(RdataFields::DATA, 14)
  271. };
  272. // sum of field len < data len
  273. EXPECT_THROW(RdataFields(specs, 3, &fields_wire[0], fields_wire.size()),
  274. isc::InvalidParameter);
  275. // sum of field len > data len
  276. EXPECT_THROW(RdataFields(specs, 3, &fields_wire[0],
  277. fields_wire.size() - 2),
  278. isc::InvalidParameter);
  279. }
  280. // Invalid input to the "from parameter" constructor: NULL vs length mismatch
  281. TEST_F(RdataFieldsTest, mismatchFieldLengthAndData) {
  282. const unsigned char dummy_data = 0;
  283. const RdataFields::FieldSpec dummy_spec(RdataFields::DATA, 1);
  284. EXPECT_THROW(RdataFields(NULL, 1, &dummy_data, 1), isc::InvalidParameter);
  285. EXPECT_THROW(RdataFields(&dummy_spec, 0, NULL, 0), isc::InvalidParameter);
  286. EXPECT_THROW(RdataFields(&dummy_spec, 1, NULL, 1), isc::InvalidParameter);
  287. EXPECT_THROW(RdataFields(NULL, 0, &dummy_data, 0), isc::InvalidParameter);
  288. }
  289. // Bogus input to getFieldSpec()
  290. TEST_F(RdataFieldsTest, getFieldSpecWithBadFieldId) {
  291. const RdataFields fields_in_a(in::A("192.0.2.1"));
  292. EXPECT_THROW(fields_in_a.getFieldSpec(1), isc::OutOfRange);
  293. }
  294. // Tests for unexpected methods in RdataFieldComposerTest. Confirm
  295. // a call to these methods triggers an exception. Expected methods are
  296. // tested via other tests above.
  297. class DummyRdata : public Rdata {
  298. public:
  299. enum Mode { CLEAR, SKIP, TRIM };
  300. explicit DummyRdata(Mode mode) : mode_(mode) {}
  301. DummyRdata(const DummyRdata& source) : Rdata(), mode_(source.mode_) {}
  302. virtual ~DummyRdata() {}
  303. virtual void toWire(AbstractMessageRenderer& renderer) const {
  304. // call the unexpected method corresponding to the test mode.
  305. // method parameters don't matter.
  306. switch (mode_) {
  307. case CLEAR:
  308. renderer.clear();
  309. break;
  310. case SKIP:
  311. renderer.skip(2);
  312. break;
  313. case TRIM:
  314. renderer.trim(2);
  315. break;
  316. }
  317. }
  318. // These are defined only to make the compiler happy. We don't use them
  319. // for the test.
  320. virtual string toText() const { return (""); }
  321. virtual void toWire(OutputBuffer&) const {}
  322. virtual int compare(const Rdata&) const { return (0); }
  323. private:
  324. const int mode_;
  325. };
  326. TEST(RdataFieldComposerTest, unusedMethods) {
  327. EXPECT_THROW(RdataFields(DummyRdata(DummyRdata::CLEAR)), isc::Unexpected);
  328. }
  329. }