rdata_caa_unittest.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. // Copyright (C) 2014 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 <algorithm>
  15. #include <string>
  16. #include <util/buffer.h>
  17. #include <dns/messagerenderer.h>
  18. #include <dns/rdata.h>
  19. #include <dns/rdataclass.h>
  20. #include <dns/rrclass.h>
  21. #include <dns/rrtype.h>
  22. #include <gtest/gtest.h>
  23. #include <dns/tests/unittest_util.h>
  24. #include <dns/tests/rdata_unittest.h>
  25. #include <util/unittests/wiredata.h>
  26. #include <boost/algorithm/string.hpp>
  27. using namespace std;
  28. using namespace isc;
  29. using namespace isc::dns;
  30. using namespace isc::util;
  31. using namespace isc::dns::rdata;
  32. using isc::UnitTestUtil;
  33. using isc::util::unittests::matchWireData;
  34. namespace {
  35. class Rdata_CAA_Test : public RdataTest {
  36. protected:
  37. Rdata_CAA_Test() :
  38. caa_txt("0 issue \"ca.example.net\""),
  39. rdata_caa(caa_txt)
  40. {}
  41. void checkFromText_None(const string& rdata_str) {
  42. checkFromText<generic::CAA, isc::Exception, isc::Exception>(
  43. rdata_str, rdata_caa, false, false);
  44. }
  45. void checkFromText_InvalidText(const string& rdata_str) {
  46. checkFromText<generic::CAA, InvalidRdataText, InvalidRdataText>(
  47. rdata_str, rdata_caa, true, true);
  48. }
  49. void checkFromText_LexerError(const string& rdata_str) {
  50. checkFromText
  51. <generic::CAA, InvalidRdataText, MasterLexer::LexerError>(
  52. rdata_str, rdata_caa, true, true);
  53. }
  54. void checkFromText_BadString(const string& rdata_str) {
  55. checkFromText
  56. <generic::CAA, InvalidRdataText, isc::Exception>(
  57. rdata_str, rdata_caa, true, false);
  58. }
  59. const string caa_txt;
  60. const generic::CAA rdata_caa;
  61. };
  62. const uint8_t rdata_caa_wiredata[] = {
  63. // flags
  64. 0x00,
  65. // tag length
  66. 0x5,
  67. // tag
  68. 'i', 's', 's', 'u', 'e',
  69. // value
  70. 'c', 'a', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e',
  71. '.', 'n', 'e', 't'
  72. };
  73. TEST_F(Rdata_CAA_Test, createFromText) {
  74. // Basic test
  75. checkFromText_None(caa_txt);
  76. // With different spacing
  77. checkFromText_None("0 issue \"ca.example.net\"");
  78. // Combination of lowercase and uppercase
  79. checkFromText_None("0 IssUE \"ca.example.net\"");
  80. // string constructor throws if there's extra text,
  81. // but lexer constructor doesn't
  82. checkFromText_BadString(caa_txt + "\n" + caa_txt);
  83. // Missing value field
  84. EXPECT_NO_THROW(const generic::CAA rdata_caa2("0 issue"));
  85. }
  86. TEST_F(Rdata_CAA_Test, fields) {
  87. // Some of these may not be RFC conformant, but we relax the check
  88. // in our code to work with other field values that may show up in
  89. // the future.
  90. EXPECT_NO_THROW(const generic::CAA rdata_caa2("1 issue \"ca.example.net\""));
  91. EXPECT_NO_THROW(const generic::CAA rdata_caa2("2 issue \"ca.example.net\""));
  92. EXPECT_NO_THROW(const generic::CAA rdata_caa2("3 issue \"ca.example.net\""));
  93. EXPECT_NO_THROW(const generic::CAA rdata_caa2("128 issue \"ca.example.net\""));
  94. EXPECT_NO_THROW(const generic::CAA rdata_caa2("255 issue \"ca.example.net\""));
  95. EXPECT_NO_THROW(const generic::CAA rdata_caa2("0 foo \"ca.example.net\""));
  96. EXPECT_NO_THROW(const generic::CAA rdata_caa2("0 bar \"ca.example.net\""));
  97. EXPECT_NO_THROW(const generic::CAA rdata_caa2("0 12345 \"ca.example.net\""));
  98. EXPECT_NO_THROW(const generic::CAA rdata_caa2("0 w0x1y2z3 \"ca.example.net\""));
  99. EXPECT_NO_THROW(const generic::CAA rdata_caa2("0 relaxed-too \"ca.example.net\""));
  100. EXPECT_NO_THROW(const generic::CAA rdata_caa2("0 RELAXED.too \"ca.example.net\""));
  101. // No value (this is redundant to the last test case in the
  102. // .createFromText test
  103. EXPECT_NO_THROW(const generic::CAA rdata_caa2("0 issue"));
  104. // > 255 would be broken
  105. EXPECT_THROW(const generic::CAA rdata_caa2("256 issue \"ca.example.net\""),
  106. InvalidRdataText);
  107. // Missing tag causes the value to be parsed as the tag field. As
  108. // the tag field does not allow quoted strings, this throws.
  109. EXPECT_THROW(const generic::CAA rdata_caa2("0 \"ca.example.net\""),
  110. InvalidRdataText);
  111. // Tag is too long
  112. const std::string tag(256, 'a');
  113. const std::string rdata_txt("0 " + tag + " \"ca.example.net\"");
  114. EXPECT_THROW(const generic::CAA rdata_caa2(rdata_txt), InvalidRdataText);
  115. }
  116. TEST_F(Rdata_CAA_Test, characterStringValue) {
  117. const generic::CAA rdata_caa_unquoted("0 issue ca.example.net");
  118. EXPECT_EQ(0, rdata_caa_unquoted.compare(rdata_caa));
  119. const generic::CAA rdata_caa_escape_X("0 issue ca.e\\xample.net");
  120. EXPECT_EQ(0, rdata_caa_escape_X.compare(rdata_caa));
  121. const generic::CAA rdata_caa_escape_DDD("0 issue ca.e\\120ample.net");
  122. EXPECT_EQ(0, rdata_caa_escape_DDD.compare(rdata_caa));
  123. const generic::CAA rdata_caa_multiline("0 issue (\nca.example.net)");
  124. EXPECT_EQ(0, rdata_caa_multiline.compare(rdata_caa));
  125. }
  126. TEST_F(Rdata_CAA_Test, badText) {
  127. checkFromText_LexerError("0");
  128. checkFromText_LexerError("ZERO issue \"ca.example.net\"");
  129. EXPECT_THROW(const generic::CAA rdata_caa2(caa_txt + " extra text"),
  130. InvalidRdataText);
  131. // Yes, this is redundant to the last test cases in the .fields test
  132. checkFromText_InvalidText("2345 issue \"ca.example.net\"");
  133. // negative values are trapped in the lexer rather than the
  134. // constructor
  135. checkFromText_LexerError("-2 issue \"ca.example.net\"");
  136. }
  137. TEST_F(Rdata_CAA_Test, copyAndAssign) {
  138. // Copy construct
  139. generic::CAA rdata_caa2(rdata_caa);
  140. EXPECT_EQ(0, rdata_caa.compare(rdata_caa2));
  141. // Assignment, mainly to confirm it doesn't cause disruption.
  142. rdata_caa2 = rdata_caa;
  143. EXPECT_EQ(0, rdata_caa.compare(rdata_caa2));
  144. }
  145. TEST_F(Rdata_CAA_Test, createFromWire) {
  146. // Basic test
  147. EXPECT_EQ(0, rdata_caa.compare(
  148. *rdataFactoryFromFile(RRType("CAA"), RRClass("IN"),
  149. "rdata_caa_fromWire1.wire")));
  150. // Combination of lowercase and uppercase
  151. EXPECT_EQ(0, rdata_caa.compare(
  152. *rdataFactoryFromFile(RRType("CAA"), RRClass("IN"),
  153. "rdata_caa_fromWire2.wire")));
  154. // Value field is empty
  155. EXPECT_NO_THROW(rdataFactoryFromFile(RRType("CAA"), RRClass("IN"),
  156. "rdata_caa_fromWire3.wire"));
  157. // Tag field is empty
  158. EXPECT_THROW(rdataFactoryFromFile(RRType("CAA"), RRClass("IN"),
  159. "rdata_caa_fromWire4.wire"),
  160. InvalidRdataText);
  161. // Value field is shorter than rdata len
  162. EXPECT_THROW(rdataFactoryFromFile(RRType("CAA"), RRClass("IN"),
  163. "rdata_caa_fromWire5"),
  164. InvalidBufferPosition);
  165. // all RDATA is missing
  166. EXPECT_THROW(rdataFactoryFromFile(RRType("CAA"), RRClass("IN"),
  167. "rdata_caa_fromWire6"),
  168. InvalidBufferPosition);
  169. }
  170. TEST_F(Rdata_CAA_Test, createFromParams) {
  171. const generic::CAA rdata_caa2(0, "issue", "ca.example.net");
  172. EXPECT_EQ(0, rdata_caa2.compare(rdata_caa));
  173. const generic::CAA rdata_caa4(0, "issue", "ca.e\\xample.net");
  174. EXPECT_EQ(0, rdata_caa4.compare(rdata_caa));
  175. const generic::CAA rdata_caa5(0, "issue", "ca.e\\120ample.net");
  176. EXPECT_EQ(0, rdata_caa5.compare(rdata_caa));
  177. // Tag is empty
  178. EXPECT_THROW(const generic::CAA rdata_caa3(0, "", "ca.example.net"),
  179. isc::InvalidParameter);
  180. // Tag is too long
  181. const std::string tag(256, 'a');
  182. EXPECT_THROW(const generic::CAA rdata_caa3(0, tag, "ca.example.net"),
  183. isc::InvalidParameter);
  184. // Value is too long
  185. const std::string value(65536, 'a');
  186. EXPECT_THROW(const generic::CAA rdata_caa3(0, "issue", value),
  187. InvalidRdataLength);
  188. }
  189. TEST_F(Rdata_CAA_Test, toText) {
  190. EXPECT_TRUE(boost::iequals(caa_txt, rdata_caa.toText()));
  191. const string caa_txt2("1 issue \"\"");
  192. const generic::CAA rdata_caa2(caa_txt2);
  193. EXPECT_TRUE(boost::iequals(caa_txt2, rdata_caa2.toText()));
  194. }
  195. TEST_F(Rdata_CAA_Test, toWire) {
  196. obuffer.clear();
  197. rdata_caa.toWire(obuffer);
  198. matchWireData(rdata_caa_wiredata, sizeof(rdata_caa_wiredata),
  199. obuffer.getData(), obuffer.getLength());
  200. }
  201. TEST_F(Rdata_CAA_Test, compare) {
  202. // Equality test is repeated from createFromWire tests above.
  203. EXPECT_EQ(0, rdata_caa.compare(
  204. *rdataFactoryFromFile(RRType("CAA"), RRClass("IN"),
  205. "rdata_caa_fromWire1.wire")));
  206. const generic::CAA rdata_caa2("1 issue \"ca.example.net\"");
  207. EXPECT_EQ(1, rdata_caa2.compare(rdata_caa));
  208. EXPECT_EQ(-1, rdata_caa.compare(rdata_caa2));
  209. }
  210. TEST_F(Rdata_CAA_Test, getFlags) {
  211. EXPECT_EQ(0, rdata_caa.getFlags());
  212. }
  213. TEST_F(Rdata_CAA_Test, getTag) {
  214. EXPECT_EQ("issue", rdata_caa.getTag());
  215. }
  216. TEST_F(Rdata_CAA_Test, getValue) {
  217. const uint8_t value_data[] = {
  218. 'c', 'a', '.',
  219. 'e', 'x', 'a', 'm', 'p', 'l', 'e', '.',
  220. 'n', 'e', 't'
  221. };
  222. const std::vector<uint8_t>& value = rdata_caa.getValue();
  223. matchWireData(value_data, sizeof(value_data),
  224. &value[0], value.size());
  225. }
  226. TEST_F(Rdata_CAA_Test, emptyValueFromWire) {
  227. const uint8_t rdf_wiredata[] = {
  228. // flags
  229. 0x00,
  230. // tag length
  231. 0x5,
  232. // tag
  233. 'i', 's', 's', 'u', 'e'
  234. };
  235. const generic::CAA rdf =
  236. dynamic_cast<const generic::CAA&>
  237. (*rdataFactoryFromFile(RRType("CAA"), RRClass("IN"),
  238. "rdata_caa_fromWire3.wire"));
  239. EXPECT_EQ(0, rdf.getFlags());
  240. EXPECT_EQ("issue", rdf.getTag());
  241. obuffer.clear();
  242. rdf.toWire(obuffer);
  243. matchWireData(rdf_wiredata, sizeof(rdf_wiredata),
  244. obuffer.getData(), obuffer.getLength());
  245. }
  246. TEST_F(Rdata_CAA_Test, emptyValueFromString) {
  247. const generic::CAA rdata_caa2("0 issue");
  248. const uint8_t rdata_caa2_wiredata[] = {
  249. // flags
  250. 0x00,
  251. // tag length
  252. 0x5,
  253. // tag
  254. 'i', 's', 's', 'u', 'e'
  255. };
  256. EXPECT_EQ(0, rdata_caa2.getFlags());
  257. EXPECT_EQ("issue", rdata_caa2.getTag());
  258. obuffer.clear();
  259. rdata_caa2.toWire(obuffer);
  260. matchWireData(rdata_caa2_wiredata, sizeof(rdata_caa2_wiredata),
  261. obuffer.getData(), obuffer.getLength());
  262. }
  263. }