rdata_txt_like_unittest.cc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. // Copyright (C) 2011 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. // This is the common code for TXT and SPF tests.
  15. #include <util/buffer.h>
  16. #include <dns/exceptions.h>
  17. #include <dns/rdataclass.h>
  18. #include <gtest/gtest.h>
  19. #include <dns/tests/unittest_util.h>
  20. #include <dns/tests/rdata_unittest.h>
  21. using isc::UnitTestUtil;
  22. using namespace std;
  23. using namespace isc::dns;
  24. using namespace isc::util;
  25. using namespace isc::dns::rdata;
  26. template<class T>
  27. class RRTYPE : public RRType {
  28. public:
  29. RRTYPE();
  30. };
  31. template<> RRTYPE<generic::TXT>::RRTYPE() : RRType(RRType::TXT()) {}
  32. template<> RRTYPE<generic::SPF>::RRTYPE() : RRType(RRType::SPF()) {}
  33. namespace {
  34. const uint8_t wiredata_txt_like[] = {
  35. sizeof("Test String") - 1,
  36. 'T', 'e', 's', 't', ' ', 'S', 't', 'r', 'i', 'n', 'g'
  37. };
  38. const uint8_t wiredata_nulltxt[] = { 0 };
  39. vector<uint8_t> wiredata_longesttxt(256, 'a');
  40. template<class TXT_LIKE>
  41. class Rdata_TXT_LIKE_Test : public RdataTest {
  42. protected:
  43. Rdata_TXT_LIKE_Test() {
  44. wiredata_longesttxt[0] = 255; // adjust length
  45. }
  46. static const TXT_LIKE rdata_txt_like;
  47. static const TXT_LIKE rdata_txt_like_empty;
  48. static const TXT_LIKE rdata_txt_like_quoted;
  49. };
  50. template<class TXT_LIKE>
  51. const TXT_LIKE Rdata_TXT_LIKE_Test<TXT_LIKE>::rdata_txt_like("Test String");
  52. template<class TXT_LIKE>
  53. const TXT_LIKE Rdata_TXT_LIKE_Test<TXT_LIKE>::rdata_txt_like_empty("");
  54. template<class TXT_LIKE>
  55. const TXT_LIKE Rdata_TXT_LIKE_Test<TXT_LIKE>::rdata_txt_like_quoted
  56. ("\"Test String\"");
  57. // The list of types we want to test.
  58. typedef testing::Types<generic::TXT, generic::SPF> Implementations;
  59. TYPED_TEST_CASE(Rdata_TXT_LIKE_Test, Implementations);
  60. TYPED_TEST(Rdata_TXT_LIKE_Test, createFromText) {
  61. // normal case is covered in toWireBuffer.
  62. // surrounding double-quotes shouldn't change the result.
  63. EXPECT_EQ(0, this->rdata_txt_like.compare(this->rdata_txt_like_quoted));
  64. // Null character-string.
  65. this->obuffer.clear();
  66. TypeParam(string("")).toWire(this->obuffer);
  67. EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
  68. this->obuffer.getData(),
  69. this->obuffer.getLength(),
  70. wiredata_nulltxt, sizeof(wiredata_nulltxt));
  71. // Longest possible character-string.
  72. this->obuffer.clear();
  73. TypeParam(string(255, 'a')).toWire(this->obuffer);
  74. EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
  75. this->obuffer.getData(),
  76. this->obuffer.getLength(),
  77. &wiredata_longesttxt[0], wiredata_longesttxt.size());
  78. // Too long text for a valid character-string.
  79. EXPECT_THROW(TypeParam(string(256, 'a')), CharStringTooLong);
  80. // The escape character makes the double quote a part of character-string,
  81. // so this is invalid input and should be rejected.
  82. EXPECT_THROW(TypeParam("\"Test String\\\""), InvalidRdataText);
  83. // Terminating double-quote is provided, so this is valid, but in this
  84. // version of implementation we reject escaped characters.
  85. EXPECT_THROW(TypeParam("\"Test String\\\"\""), InvalidRdataText);
  86. }
  87. void
  88. makeLargest(vector<uint8_t>& data) {
  89. uint8_t ch = 0;
  90. // create 255 sets of character-strings, each of which has the longest
  91. // length (255bytes string + 1-byte length field)
  92. for (int i = 0; i < 255; ++i, ++ch) {
  93. data.push_back(255);
  94. data.insert(data.end(), 255, ch);
  95. }
  96. // the last character-string should be 255 bytes (including the one-byte
  97. // length field) in length so that the total length should be in the range
  98. // of 16-bit integers.
  99. data.push_back(254);
  100. data.insert(data.end(), 254, ch);
  101. assert(data.size() == 65535);
  102. }
  103. TYPED_TEST(Rdata_TXT_LIKE_Test, createFromWire) {
  104. EXPECT_EQ(0, this->rdata_txt_like.compare(
  105. *this->rdataFactoryFromFile(RRTYPE<TypeParam>(), RRClass("IN"),
  106. "rdata_txt_fromWire1")));
  107. // Empty character string
  108. EXPECT_EQ(0, this->rdata_txt_like_empty.compare(
  109. *this->rdataFactoryFromFile(RRTYPE<TypeParam>(), RRClass("IN"),
  110. "rdata_txt_fromWire2.wire")));
  111. // Multiple character strings
  112. this->obuffer.clear();
  113. this->rdataFactoryFromFile(RRTYPE<TypeParam>(), RRClass("IN"),
  114. "rdata_txt_fromWire3.wire")->toWire(this->obuffer);
  115. // the result should be 'wiredata_txt' repeated twice
  116. vector<uint8_t> expected_data(wiredata_txt_like, wiredata_txt_like +
  117. sizeof(wiredata_txt_like));
  118. expected_data.insert(expected_data.end(), wiredata_txt_like,
  119. wiredata_txt_like + sizeof(wiredata_txt_like));
  120. EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
  121. this->obuffer.getData(),
  122. this->obuffer.getLength(),
  123. &expected_data[0], expected_data.size());
  124. // Largest length of data. There's nothing special, but should be
  125. // constructed safely, and the content should be identical to the original
  126. // data.
  127. vector<uint8_t> largest_txt_like_data;
  128. makeLargest(largest_txt_like_data);
  129. InputBuffer ibuffer(&largest_txt_like_data[0],
  130. largest_txt_like_data.size());
  131. TypeParam largest_txt_like(ibuffer, largest_txt_like_data.size());
  132. this->obuffer.clear();
  133. largest_txt_like.toWire(this->obuffer);
  134. EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
  135. this->obuffer.getData(),
  136. this->obuffer.getLength(),
  137. &largest_txt_like_data[0],
  138. largest_txt_like_data.size());
  139. // rdlen parameter is out of range. This is a rare event because we'd
  140. // normally call the constructor via a polymorphic wrapper, where the
  141. // length is validated. But this should be checked explicitly.
  142. InputBuffer ibuffer2(&largest_txt_like_data[0],
  143. largest_txt_like_data.size());
  144. EXPECT_THROW(TypeParam(ibuffer2, 65536), InvalidRdataLength);
  145. // RDATA is empty, which is invalid for TXT_LIKE.
  146. EXPECT_THROW(this->rdataFactoryFromFile(RRTYPE<TypeParam>(), RRClass("IN"),
  147. "rdata_txt_fromWire4.wire"),
  148. DNSMessageFORMERR);
  149. // character-string length is too large, which could cause overrun.
  150. EXPECT_THROW(this->rdataFactoryFromFile(RRTYPE<TypeParam>(), RRClass("IN"),
  151. "rdata_txt_fromWire5.wire"),
  152. DNSMessageFORMERR);
  153. }
  154. TYPED_TEST(Rdata_TXT_LIKE_Test, createFromLexer) {
  155. EXPECT_EQ(0, this->rdata_txt_like.compare(
  156. *test::createRdataUsingLexer(RRTYPE<TypeParam>(), RRClass::IN(),
  157. "Test String")));
  158. EXPECT_EQ(0, this->rdata_txt_like_empty.compare(
  159. *test::createRdataUsingLexer(RRTYPE<TypeParam>(), RRClass::IN(),
  160. "")));
  161. EXPECT_EQ(0, this->rdata_txt_like_quoted.compare(
  162. *test::createRdataUsingLexer(RRTYPE<TypeParam>(), RRClass::IN(),
  163. "\"Test String\"")));
  164. }
  165. TYPED_TEST(Rdata_TXT_LIKE_Test, toWireBuffer) {
  166. this->rdata_txt_like.toWire(this->obuffer);
  167. EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
  168. this->obuffer.getData(),
  169. this->obuffer.getLength(),
  170. wiredata_txt_like, sizeof(wiredata_txt_like));
  171. }
  172. TYPED_TEST(Rdata_TXT_LIKE_Test, toWireRenderer) {
  173. this->rdata_txt_like.toWire(this->renderer);
  174. EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
  175. this->renderer.getData(),
  176. this->renderer.getLength(),
  177. wiredata_txt_like, sizeof(wiredata_txt_like));
  178. }
  179. TYPED_TEST(Rdata_TXT_LIKE_Test, toText) {
  180. EXPECT_EQ("\"Test String\"", this->rdata_txt_like.toText());
  181. }
  182. TYPED_TEST(Rdata_TXT_LIKE_Test, assignment) {
  183. TypeParam rdata1("assignment1");
  184. TypeParam rdata2("assignment2");
  185. rdata1 = rdata2;
  186. EXPECT_EQ(0, rdata2.compare(rdata1));
  187. // Check if the copied data is valid even after the original is deleted
  188. TypeParam* rdata3 = new TypeParam(rdata1);
  189. TypeParam rdata4("assignment3");
  190. rdata4 = *rdata3;
  191. delete rdata3;
  192. EXPECT_EQ(0, rdata4.compare(rdata1));
  193. // Self assignment
  194. rdata2 = rdata2;
  195. EXPECT_EQ(0, rdata2.compare(rdata1));
  196. }
  197. TYPED_TEST(Rdata_TXT_LIKE_Test, compare) {
  198. string const txt1("aaaaaaaa");
  199. string const txt2("aaaaaaaaaa");
  200. string const txt3("bbbbbbbb");
  201. string const txt4(129, 'a');
  202. string const txt5(128, 'b');
  203. EXPECT_EQ(TypeParam(txt1).compare(TypeParam(txt1)), 0);
  204. EXPECT_LT(TypeParam("").compare(TypeParam(txt1)), 0);
  205. EXPECT_GT(TypeParam(txt1).compare(TypeParam("")), 0);
  206. EXPECT_LT(TypeParam(txt1).compare(TypeParam(txt2)), 0);
  207. EXPECT_GT(TypeParam(txt2).compare(TypeParam(txt1)), 0);
  208. EXPECT_LT(TypeParam(txt1).compare(TypeParam(txt3)), 0);
  209. EXPECT_GT(TypeParam(txt3).compare(TypeParam(txt1)), 0);
  210. // we're comparing the data raw, starting at the length octet, so a shorter
  211. // string sorts before a longer one no matter the lexicopraphical order
  212. EXPECT_LT(TypeParam(txt3).compare(TypeParam(txt2)), 0);
  213. EXPECT_GT(TypeParam(txt2).compare(TypeParam(txt3)), 0);
  214. // to make sure the length octet compares unsigned
  215. EXPECT_LT(TypeParam(txt1).compare(TypeParam(txt4)), 0);
  216. EXPECT_GT(TypeParam(txt4).compare(TypeParam(txt1)), 0);
  217. EXPECT_LT(TypeParam(txt5).compare(TypeParam(txt4)), 0);
  218. EXPECT_GT(TypeParam(txt4).compare(TypeParam(txt5)), 0);
  219. // comparison attempt between incompatible RR types should be rejected
  220. EXPECT_THROW(TypeParam(txt1).compare(*this->rdata_nomatch),
  221. bad_cast);
  222. }
  223. }