rdata_nsec3param_like_unittest.cc 9.8 KB

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