rdata_nsec3param_like_unittest.cc 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  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 <dns/exceptions.h>
  15. #include <dns/rdata.h>
  16. #include <dns/rdataclass.h>
  17. #include <dns/rrclass.h>
  18. #include <dns/rrtype.h>
  19. #include <gtest/gtest.h>
  20. #include <dns/tests/unittest_util.h>
  21. #include <dns/tests/rdata_unittest.h>
  22. #include <string>
  23. #include <vector>
  24. using namespace std;
  25. using isc::UnitTestUtil;
  26. using namespace isc::dns;
  27. using namespace isc::dns::rdata;
  28. namespace {
  29. // Template for shared tests for NSEC3 and NSEC3PARAM
  30. template <typename RDATA_TYPE>
  31. class NSEC3PARAMLikeTest : public RdataTest {
  32. protected:
  33. NSEC3PARAMLikeTest() :
  34. salt_txt("1 1 1 D399EAAB" + getCommonText()),
  35. nosalt_txt("1 1 1 -" + getCommonText()),
  36. obuffer(0)
  37. {}
  38. RDATA_TYPE fromText(const string& rdata_text) {
  39. return (RDATA_TYPE(rdata_text));
  40. }
  41. void compareCheck() const {
  42. typename vector<RDATA_TYPE>::const_iterator it;
  43. typename vector<RDATA_TYPE>::const_iterator const it_end =
  44. compare_set.end();
  45. for (it = compare_set.begin(); it != it_end - 1; ++it) {
  46. SCOPED_TRACE("compare " + it->toText() + " to " +
  47. (it + 1)->toText());
  48. EXPECT_GT(0, (*it).compare(*(it + 1)));
  49. EXPECT_LT(0, (*(it + 1)).compare(*it));
  50. }
  51. }
  52. const string salt_txt; // RDATA text with salt
  53. const string nosalt_txt; // RDATA text without salt
  54. OutputBuffer obuffer; // used in toWire() tests
  55. MessageRenderer renderer; // ditto
  56. vector<RDATA_TYPE> compare_set; // used in compare() tests
  57. // Convert generic Rdata to the corresponding derived Rdata class object.
  58. // Defined here because it depends on the template parameter.
  59. static const RDATA_TYPE& convert(const Rdata& rdata) {
  60. return (dynamic_cast<const RDATA_TYPE&>(rdata));
  61. }
  62. // These depend on the specific RR type. We use specialized methods
  63. // for them.
  64. static RRType getType(); // return either RRType::NSEC3() or NSEC3PARAM()
  65. static string getWireFilePrefix();
  66. static string getCommonText(); // commonly used part of textual form
  67. };
  68. // Instantiate specific typed tests
  69. typedef ::testing::Types<generic::NSEC3, generic::NSEC3PARAM> TestRdataTypes;
  70. TYPED_TEST_CASE(NSEC3PARAMLikeTest, TestRdataTypes);
  71. template <>
  72. RRType
  73. NSEC3PARAMLikeTest<generic::NSEC3>::getType() {
  74. return (RRType::NSEC3());
  75. }
  76. template <>
  77. RRType
  78. NSEC3PARAMLikeTest<generic::NSEC3PARAM>::getType() {
  79. return (RRType::NSEC3PARAM());
  80. }
  81. template <>
  82. string
  83. NSEC3PARAMLikeTest<generic::NSEC3>::getWireFilePrefix() {
  84. return ("rdata_nsec3_");
  85. }
  86. template <>
  87. string
  88. NSEC3PARAMLikeTest<generic::NSEC3PARAM>::getWireFilePrefix() {
  89. return ("rdata_nsec3param_");
  90. }
  91. template <>
  92. string
  93. NSEC3PARAMLikeTest<generic::NSEC3>::getCommonText() {
  94. // next hash + RR type bitmap
  95. return (" H9RSFB7FPF2L8HG35CMPC765TDK23RP6 "
  96. "NS SOA RRSIG DNSKEY NSEC3PARAM");
  97. }
  98. template <>
  99. string
  100. NSEC3PARAMLikeTest<generic::NSEC3PARAM>::getCommonText() {
  101. // there's no more text for NSEC3PARAM
  102. return ("");
  103. }
  104. TYPED_TEST(NSEC3PARAMLikeTest, fromText) {
  105. // Numeric parameters have possible maximum values. Unusual, but must
  106. // be accepted.
  107. EXPECT_NO_THROW(this->fromText("255 255 65535 D399EAAB" +
  108. this->getCommonText()));
  109. // 0-length salt
  110. EXPECT_EQ(0, this->fromText(this->nosalt_txt).getSalt().size());
  111. // salt that has the possible max length
  112. EXPECT_EQ(255, this->fromText("1 1 1 " + string(255 * 2, '0') +
  113. this->getCommonText()).getSalt().size());
  114. }
  115. TYPED_TEST(NSEC3PARAMLikeTest, badText) {
  116. // Bad salt hex
  117. EXPECT_THROW(this->fromText("1 1 1 SPORK0" + this->getCommonText()),
  118. isc::BadValue);
  119. EXPECT_THROW(this->fromText("1 1 1 ADDAFEE" + this->getCommonText()),
  120. isc::BadValue);
  121. // Space within salt
  122. EXPECT_THROW(this->fromText("1 1 1 ADDAFE ADDAFEEE" +
  123. this->getCommonText()),
  124. InvalidRdataText);
  125. // Similar to empty salt, but not really. This shouldn't cause confusion.
  126. EXPECT_THROW(this->fromText("1 1 1 --" + this->getCommonText()),
  127. isc::BadValue);
  128. // Too large algorithm
  129. EXPECT_THROW(this->fromText("1000000 1 1 ADDAFEEE" + this->getCommonText()),
  130. InvalidRdataText);
  131. // Too large flags
  132. EXPECT_THROW(this->fromText("1 1000000 1 ADDAFEEE" + this->getCommonText()),
  133. InvalidRdataText);
  134. // Too large iterations
  135. EXPECT_THROW(this->fromText("1 1 65536 ADDAFEEE" + this->getCommonText()),
  136. InvalidRdataText);
  137. // There should be a space between "1" and "D399EAAB" (salt)
  138. EXPECT_THROW(this->fromText("1 1 1D399EAAB" + this->getCommonText()),
  139. InvalidRdataText);
  140. // Salt is too long (possible max + 1 bytes)
  141. EXPECT_THROW(this->fromText("1 1 1 " + string(256 * 2, '0') +
  142. this->getCommonText()),
  143. InvalidRdataText);
  144. }
  145. TYPED_TEST(NSEC3PARAMLikeTest, toText) {
  146. // normal case
  147. EXPECT_EQ(this->salt_txt, this->fromText(this->salt_txt).toText());
  148. // empty salt case
  149. EXPECT_EQ(this->nosalt_txt, this->fromText(this->nosalt_txt).toText());
  150. }
  151. TYPED_TEST(NSEC3PARAMLikeTest, createFromWire) {
  152. // Normal case
  153. EXPECT_EQ(0, this->fromText(this->salt_txt).compare(
  154. *this->rdataFactoryFromFile(this->getType(), RRClass::IN(),
  155. (this->getWireFilePrefix() +
  156. "fromWire1").c_str())));
  157. // Too short RDLENGTH: it doesn't even contain the first 5 octets.
  158. EXPECT_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(),
  159. (this->getWireFilePrefix() +
  160. "fromWire2.wire").c_str()),
  161. DNSMessageFORMERR);
  162. // salt length is too large
  163. EXPECT_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(),
  164. (this->getWireFilePrefix() +
  165. "fromWire11.wire").c_str()),
  166. DNSMessageFORMERR);
  167. // empty salt. not so usual, but valid.
  168. ConstRdataPtr rdata =
  169. this->rdataFactoryFromFile(this->getType(), RRClass::IN(),
  170. (this->getWireFilePrefix() +
  171. "fromWire13.wire").c_str());
  172. EXPECT_EQ(0, this->convert(*rdata).getSalt().size());
  173. }
  174. template <typename OUTPUT_TYPE>
  175. void
  176. toWireCheck(RRType rrtype, OUTPUT_TYPE& output, const string& data_file) {
  177. vector<uint8_t> data;
  178. UnitTestUtil::readWireData(data_file.c_str(), data);
  179. InputBuffer buffer(&data[0], data.size());
  180. const uint16_t rdlen = buffer.readUint16();
  181. output.clear();
  182. output.writeUint16(rdlen);
  183. createRdata(rrtype, RRClass::IN(), buffer, rdlen)->toWire(output);
  184. EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, output.getData(),
  185. output.getLength(), &data[0], data.size());
  186. }
  187. TYPED_TEST(NSEC3PARAMLikeTest, toWire) {
  188. // normal case
  189. toWireCheck(this->getType(), this->renderer,
  190. this->getWireFilePrefix() + "fromWire1");
  191. toWireCheck(this->getType(), this->obuffer,
  192. this->getWireFilePrefix() + "fromWire1");
  193. // empty salt
  194. toWireCheck(this->getType(), this->renderer,
  195. this->getWireFilePrefix() + "fromWire13.wire");
  196. toWireCheck(this->getType(), this->obuffer,
  197. this->getWireFilePrefix() + "fromWire13.wire");
  198. }
  199. TYPED_TEST(NSEC3PARAMLikeTest, compare) {
  200. // test RDATAs, sorted in the ascendent order.
  201. this->compare_set.push_back(this->fromText("0 0 0 D399EAAB" +
  202. this->getCommonText()));
  203. this->compare_set.push_back(this->fromText("1 0 0 D399EAAB" +
  204. this->getCommonText()));
  205. this->compare_set.push_back(this->fromText("1 1 0 D399EAAB" +
  206. this->getCommonText()));
  207. this->compare_set.push_back(this->fromText("1 1 1 -" +
  208. this->getCommonText()));
  209. this->compare_set.push_back(this->fromText("1 1 1 D399EAAB" +
  210. this->getCommonText()));
  211. this->compare_set.push_back(this->fromText("1 1 1 FF99EAAB" +
  212. this->getCommonText()));
  213. this->compare_set.push_back(this->fromText("1 1 1 FF99EA0000" +
  214. this->getCommonText()));
  215. this->compareCheck();
  216. }
  217. }