rdata_unittest.cc 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  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 <string>
  16. #include <sstream>
  17. #include <util/buffer.h>
  18. #include <dns/messagerenderer.h>
  19. #include <dns/rdata.h>
  20. #include <dns/rdataclass.h>
  21. #include <dns/rrclass.h>
  22. #include <dns/rrtype.h>
  23. #include <gtest/gtest.h>
  24. #include <dns/tests/unittest_util.h>
  25. #include <dns/tests/rdata_unittest.h>
  26. #include <boost/bind.hpp>
  27. #include <boost/lexical_cast.hpp>
  28. using isc::UnitTestUtil;
  29. using namespace std;
  30. using namespace isc::dns;
  31. using namespace isc::util;
  32. using namespace isc::dns::rdata;
  33. namespace isc {
  34. namespace dns {
  35. namespace rdata {
  36. RdataTest::RdataTest() :
  37. obuffer(0), rdata_nomatch(createRdata(RRType(0), RRClass(1), "\\# 0"))
  38. {}
  39. RdataPtr
  40. RdataTest::rdataFactoryFromFile(const RRType& rrtype, const RRClass& rrclass,
  41. const char* datafile, size_t position)
  42. {
  43. std::vector<unsigned char> data;
  44. UnitTestUtil::readWireData(datafile, data);
  45. InputBuffer buffer(&data[0], data.size());
  46. buffer.setPosition(position);
  47. uint16_t rdlen = buffer.readUint16();
  48. return (createRdata(rrtype, rrclass, buffer, rdlen));
  49. }
  50. namespace test {
  51. RdataPtr
  52. createRdataUsingLexer(const RRType& rrtype, const RRClass& rrclass,
  53. const std::string& str)
  54. {
  55. std::stringstream ss(str);
  56. MasterLexer lexer;
  57. lexer.pushSource(ss);
  58. MasterLoaderCallbacks callbacks =
  59. MasterLoaderCallbacks::getNullCallbacks();
  60. const Name origin("example.org.");
  61. return (createRdata(rrtype, rrclass, lexer, &origin,
  62. MasterLoader::MANY_ERRORS, callbacks));
  63. }
  64. } // end of namespace isc::dns::rdata::test
  65. // A mock class to check parameters passed via loader callbacks. Its callback
  66. // records the passed parameters, allowing the test to check them later via
  67. // the check() method.
  68. class CreateRdataCallback {
  69. public:
  70. enum CallbackType { NONE, ERROR, WARN };
  71. CreateRdataCallback() : type_(NONE), line_(0) {}
  72. void callback(CallbackType type, const string& source, size_t line,
  73. const string& reason_txt) {
  74. type_ = type;
  75. source_ = source;
  76. line_ = line;
  77. reason_txt_ = reason_txt;
  78. }
  79. void clear() {
  80. type_ = NONE;
  81. source_.clear();
  82. line_ = 0;
  83. reason_txt_.clear();
  84. }
  85. // Return if callback is called since the previous call to clear().
  86. bool isCalled() const { return (type_ != NONE); }
  87. void check(const string& expected_srcname, size_t expected_line,
  88. CallbackType expected_type, const string& expected_reason)
  89. const
  90. {
  91. EXPECT_EQ(expected_srcname, source_);
  92. EXPECT_EQ(expected_line, line_);
  93. EXPECT_EQ(expected_type, type_);
  94. EXPECT_EQ(expected_reason, reason_txt_);
  95. }
  96. private:
  97. CallbackType type_;
  98. string source_;
  99. size_t line_;
  100. string reason_txt_;
  101. };
  102. // Test class/type-independent behavior of createRdata().
  103. TEST_F(RdataTest, createRdataWithLexer) {
  104. const in::AAAA aaaa_rdata("2001:db8::1");
  105. stringstream ss;
  106. const string src_name = "stream-" + boost::lexical_cast<string>(&ss);
  107. ss << aaaa_rdata.toText() << "\n"; // valid case
  108. ss << aaaa_rdata.toText() << "; comment, should be ignored\n";
  109. ss << aaaa_rdata.toText() << " extra-token\n"; // extra token
  110. ss << aaaa_rdata.toText() << " extra token\n"; // 2 extra tokens
  111. ss << ")\n"; // causing lexer error in parsing the RDATA text
  112. ss << "192.0.2.1\n"; // semantics error: IPv4 address is given for AAAA
  113. ss << aaaa_rdata.toText(); // valid, but end with EOF, not EOL
  114. lexer.pushSource(ss);
  115. CreateRdataCallback callback;
  116. MasterLoaderCallbacks callbacks(
  117. boost::bind(&CreateRdataCallback::callback, &callback,
  118. CreateRdataCallback::ERROR, _1, _2, _3),
  119. boost::bind(&CreateRdataCallback::callback, &callback,
  120. CreateRdataCallback::WARN, _1, _2, _3));
  121. size_t line = 0;
  122. // Valid case.
  123. ++line;
  124. ConstRdataPtr rdata = createRdata(RRType::AAAA(), RRClass::IN(), lexer,
  125. NULL, MasterLoader::MANY_ERRORS,
  126. callbacks);
  127. EXPECT_EQ(0, aaaa_rdata.compare(*rdata));
  128. EXPECT_FALSE(callback.isCalled());
  129. // Similar to the previous case, but RDATA is followed by a comment.
  130. // It should cause any confusion.
  131. ++line;
  132. callback.clear();
  133. rdata = createRdata(RRType::AAAA(), RRClass::IN(), lexer, NULL,
  134. MasterLoader::MANY_ERRORS, callbacks);
  135. EXPECT_EQ(0, aaaa_rdata.compare(*rdata));
  136. EXPECT_FALSE(callback.isCalled());
  137. // Broken RDATA text: extra token. createRdata() returns NULL, error
  138. // callback is called.
  139. ++line;
  140. callback.clear();
  141. EXPECT_FALSE(createRdata(RRType::AAAA(), RRClass::IN(), lexer, NULL,
  142. MasterLoader::MANY_ERRORS, callbacks));
  143. callback.check(src_name, line, CreateRdataCallback::ERROR,
  144. "createRdata from text failed near 'extra-token': "
  145. "extra input text");
  146. // Similar to the previous case, but only the first extra token triggers
  147. // callback.
  148. ++line;
  149. callback.clear();
  150. EXPECT_FALSE(createRdata(RRType::AAAA(), RRClass::IN(), lexer, NULL,
  151. MasterLoader::MANY_ERRORS, callbacks));
  152. callback.check(src_name, line, CreateRdataCallback::ERROR,
  153. "createRdata from text failed near 'extra': "
  154. "extra input text");
  155. // Lexer error will happen, corresponding error callback will be triggered.
  156. ++line;
  157. callback.clear();
  158. EXPECT_FALSE(createRdata(RRType::AAAA(), RRClass::IN(), lexer, NULL,
  159. MasterLoader::MANY_ERRORS, callbacks));
  160. callback.check(src_name, line, CreateRdataCallback::ERROR,
  161. "createRdata from text failed: unbalanced parentheses");
  162. // Semantics level error will happen, corresponding error callback will be
  163. // triggered.
  164. ++line;
  165. callback.clear();
  166. EXPECT_FALSE(createRdata(RRType::AAAA(), RRClass::IN(), lexer, NULL,
  167. MasterLoader::MANY_ERRORS, callbacks));
  168. callback.check(src_name, line, CreateRdataCallback::ERROR,
  169. "createRdata from text failed: Failed to convert "
  170. "'192.0.2.1' to IN/AAAA RDATA");
  171. // Input is valid and parse will succeed, but with a warning that the
  172. // file is not ended with a newline.
  173. ++line;
  174. callback.clear();
  175. rdata = createRdata(RRType::AAAA(), RRClass::IN(), lexer, NULL,
  176. MasterLoader::MANY_ERRORS, callbacks);
  177. EXPECT_EQ(0, aaaa_rdata.compare(*rdata));
  178. callback.check(src_name, line, CreateRdataCallback::WARN,
  179. "file does not end with newline");
  180. }
  181. }
  182. }
  183. }
  184. namespace {
  185. class Rdata_Unknown_Test : public RdataTest {
  186. protected:
  187. static string getLongestRdataTxt();
  188. static void getLongestRdataWire(vector<uint8_t>& v);
  189. };
  190. string
  191. Rdata_Unknown_Test::getLongestRdataTxt() {
  192. ostringstream oss;
  193. oss << "\\# " << MAX_RDLENGTH << " ";
  194. oss.fill('0');
  195. oss << right << hex;
  196. for (int i = 0; i < MAX_RDLENGTH; i++) {
  197. oss << setw(2) << (i & 0xff);
  198. }
  199. return (oss.str());
  200. }
  201. void
  202. Rdata_Unknown_Test::getLongestRdataWire(vector<uint8_t>& v) {
  203. unsigned char ch = 0;
  204. for (int i = 0; i < MAX_RDLENGTH; ++i, ++ch) {
  205. v.push_back(ch);
  206. }
  207. }
  208. const string rdata_unknowntxt("\\# 4 a1b2c30d");
  209. const generic::Generic rdata_unknown(rdata_unknowntxt);
  210. // Wire-format data correspond to rdata_unknown. Note that it doesn't include
  211. // RDLENGTH
  212. const uint8_t wiredata_unknown[] = { 0xa1, 0xb2, 0xc3, 0x0d };
  213. // "Unknown" RR Type used for the test cases below. If/when we use this
  214. // type number as a "well-known" (probably experimental) type, we'll need to
  215. // renumber it.
  216. const RRType unknown_rrtype = RRType(65000);
  217. TEST_F(Rdata_Unknown_Test, createFromText) {
  218. // valid construction. This also tests a normal case of "FromWire".
  219. EXPECT_EQ(0, generic::Generic("\\# 4 a1b2c30d").compare(
  220. *rdataFactoryFromFile(unknown_rrtype, RRClass::IN(),
  221. "rdata_unknown_fromWire")));
  222. // upper case hexadecimal digits should also be okay.
  223. EXPECT_EQ(0, generic::Generic("\\# 4 A1B2C30D").compare(
  224. *rdataFactoryFromFile(unknown_rrtype, RRClass::IN(),
  225. "rdata_unknown_fromWire")));
  226. // 0-length RDATA should be accepted
  227. EXPECT_EQ(0, generic::Generic("\\# 0").compare(
  228. *rdataFactoryFromFile(unknown_rrtype, RRClass::IN(),
  229. "rdata_unknown_fromWire", 6)));
  230. // hex encoding can be space-separated
  231. EXPECT_EQ(0, generic::Generic("\\# 4 a1 b2c30d").compare(rdata_unknown));
  232. EXPECT_EQ(0, generic::Generic("\\# 4 a1b2 c30d").compare(rdata_unknown));
  233. EXPECT_EQ(0, generic::Generic("\\# 4 a1 b2 c3 0d").compare(rdata_unknown));
  234. EXPECT_EQ(0, generic::Generic("\\# 4 a1\tb2c3 0d").compare(rdata_unknown));
  235. // Max-length RDATA
  236. vector<uint8_t> v;
  237. getLongestRdataWire(v);
  238. InputBuffer ibuffer(&v[0], v.size());
  239. EXPECT_EQ(0, generic::Generic(getLongestRdataTxt()).compare(
  240. generic::Generic(ibuffer, v.size())));
  241. // the length field must match the encoding data length.
  242. EXPECT_THROW(generic::Generic("\\# 4 1080c0ff00"), InvalidRdataLength);
  243. EXPECT_THROW(generic::Generic("\\# 5 1080c0ff"), InvalidRdataLength);
  244. // RDATA encoding part must consist of an even number of hex digits.
  245. EXPECT_THROW(generic::Generic("\\# 1 1"), InvalidRdataText);
  246. EXPECT_THROW(generic::Generic("\\# 1 ax"), InvalidRdataText);
  247. // the length should be 16-bit unsigned integer
  248. EXPECT_THROW(generic::Generic("\\# 65536 a1b2c30d"), InvalidRdataLength);
  249. EXPECT_THROW(generic::Generic("\\# -1 a1b2c30d"), InvalidRdataLength);
  250. EXPECT_THROW(generic::Generic("\\# 1.1 a1"), InvalidRdataText);
  251. EXPECT_THROW(generic::Generic("\\# 0a 00010203040506070809"),
  252. InvalidRdataText);
  253. // should reject if the special token is missing.
  254. EXPECT_THROW(generic::Generic("4 a1b2c30d"), InvalidRdataText);
  255. // the special token, the RDLENGTH and the data must be space separated.
  256. EXPECT_THROW(generic::Generic("\\#0"), InvalidRdataText);
  257. EXPECT_THROW(generic::Generic("\\# 1ff"), InvalidRdataText);
  258. }
  259. TEST_F(Rdata_Unknown_Test, createFromWire) {
  260. // normal case (including 0-length data) is covered in createFromText.
  261. // buffer too short. the error should be detected in buffer read
  262. EXPECT_THROW(rdataFactoryFromFile(unknown_rrtype, RRClass::IN(),
  263. "rdata_unknown_fromWire", 8),
  264. InvalidBufferPosition);
  265. // too large data
  266. vector<uint8_t> v;
  267. getLongestRdataWire(v);
  268. v.push_back(0); // making it too long
  269. InputBuffer ibuffer(&v[0], v.size());
  270. EXPECT_THROW(generic::Generic(ibuffer, v.size()), InvalidRdataLength);
  271. }
  272. // The following 3 sets of tests check the behavior of createRdata() variants
  273. // with the "unknown" RRtype. The result should be RRclass independent.
  274. TEST_F(Rdata_Unknown_Test, createRdataFromString) {
  275. EXPECT_EQ(0, rdata_unknown.compare(
  276. *createRdata(unknown_rrtype, RRClass::IN(),
  277. rdata_unknowntxt)));
  278. EXPECT_EQ(0, rdata_unknown.compare(
  279. *createRdata(unknown_rrtype, RRClass::CH(),
  280. rdata_unknowntxt)));
  281. EXPECT_EQ(0, rdata_unknown.compare(
  282. *createRdata(unknown_rrtype, RRClass("CLASS65000"),
  283. rdata_unknowntxt)));
  284. }
  285. TEST_F(Rdata_Unknown_Test, createRdataFromWire) {
  286. InputBuffer ibuffer(wiredata_unknown, sizeof(wiredata_unknown));
  287. EXPECT_EQ(0, rdata_unknown.compare(
  288. *createRdata(unknown_rrtype, RRClass::IN(),
  289. ibuffer, sizeof(wiredata_unknown))));
  290. InputBuffer ibuffer2(wiredata_unknown, sizeof(wiredata_unknown));
  291. EXPECT_EQ(0, rdata_unknown.compare(
  292. *createRdata(unknown_rrtype, RRClass::CH(),
  293. ibuffer2, sizeof(wiredata_unknown))));
  294. InputBuffer ibuffer3(wiredata_unknown, sizeof(wiredata_unknown));
  295. EXPECT_EQ(0, rdata_unknown.compare(
  296. *createRdata(unknown_rrtype, RRClass(65000),
  297. ibuffer3, sizeof(wiredata_unknown))));
  298. }
  299. TEST_F(Rdata_Unknown_Test, createRdataByCopy) {
  300. EXPECT_EQ(0, rdata_unknown.compare(
  301. *createRdata(unknown_rrtype, RRClass::IN(), rdata_unknown)));
  302. EXPECT_EQ(0, rdata_unknown.compare(
  303. *createRdata(unknown_rrtype, RRClass::CH(), rdata_unknown)));
  304. EXPECT_EQ(0, rdata_unknown.compare(
  305. *createRdata(unknown_rrtype, RRClass(65000),
  306. rdata_unknown)));
  307. }
  308. TEST_F(Rdata_Unknown_Test, copyConstruct) {
  309. generic::Generic copy(rdata_unknown);
  310. EXPECT_EQ(0, copy.compare(rdata_unknown));
  311. // Check the copied data is valid even after the original is deleted
  312. generic::Generic* copy2 = new generic::Generic(rdata_unknown);
  313. generic::Generic copy3(*copy2);
  314. delete copy2;
  315. EXPECT_EQ(0, copy3.compare(rdata_unknown));
  316. }
  317. TEST_F(Rdata_Unknown_Test, assignment) {
  318. generic::Generic copy("\\# 1 10");
  319. copy = rdata_unknown;
  320. EXPECT_EQ(0, copy.compare(rdata_unknown));
  321. // Check if the copied data is valid even after the original is deleted
  322. generic::Generic* copy2 = new generic::Generic(rdata_unknown);
  323. generic::Generic copy3("\\# 1 10");
  324. copy3 = *copy2;
  325. delete copy2;
  326. EXPECT_EQ(0, copy3.compare(rdata_unknown));
  327. // Self assignment
  328. copy = copy;
  329. EXPECT_EQ(0, copy.compare(rdata_unknown));
  330. }
  331. TEST_F(Rdata_Unknown_Test, toText) {
  332. EXPECT_EQ(rdata_unknowntxt, rdata_unknown.toText());
  333. EXPECT_EQ(getLongestRdataTxt(),
  334. generic::Generic(getLongestRdataTxt()).toText());
  335. }
  336. TEST_F(Rdata_Unknown_Test, toWireBuffer) {
  337. rdata_unknown.toWire(obuffer);
  338. EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
  339. obuffer.getData(), obuffer.getLength(),
  340. wiredata_unknown, sizeof(wiredata_unknown));
  341. }
  342. TEST_F(Rdata_Unknown_Test, toWireRenderer) {
  343. rdata_unknown.toWire(renderer);
  344. EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
  345. renderer.getData(), renderer.getLength(),
  346. wiredata_unknown, sizeof(wiredata_unknown));
  347. }
  348. TEST_F(Rdata_Unknown_Test, compare) {
  349. // comparison as left-justified unsigned octet sequences:
  350. // cppcheck-suppress uselessCallsCompare
  351. EXPECT_EQ(0, rdata_unknown.compare(rdata_unknown));
  352. generic::Generic rdata_unknown_small("\\# 4 00b2c3ff");
  353. EXPECT_GT(0, rdata_unknown_small.compare(rdata_unknown));
  354. EXPECT_LT(0, rdata_unknown.compare(rdata_unknown_small));
  355. generic::Generic rdata_unknown_large("\\# 4 ffb2c300");
  356. EXPECT_LT(0, rdata_unknown_large.compare(rdata_unknown));
  357. EXPECT_GT(0, rdata_unknown.compare(rdata_unknown_large));
  358. // the absence of an octet sorts before a zero octet.
  359. generic::Generic rdata_unknown_short("\\# 3 a1b2c3");
  360. EXPECT_GT(0, rdata_unknown_short.compare(rdata_unknown));
  361. EXPECT_LT(0, rdata_unknown.compare(rdata_unknown_short));
  362. }
  363. TEST_F(Rdata_Unknown_Test, LeftShiftOperator) {
  364. ostringstream oss;
  365. oss << rdata_unknown;
  366. EXPECT_EQ(rdata_unknown.toText(), oss.str());
  367. }
  368. //
  369. // Tests for global utility functions
  370. //
  371. TEST_F(RdataTest, compareNames) {
  372. Name small("a.example");
  373. Name large("example");
  374. // Check the case where the order is different from the owner name
  375. // comparison:
  376. EXPECT_TRUE(small > large);
  377. EXPECT_EQ(-1, compareNames(small, large));
  378. EXPECT_EQ(1, compareNames(large, small));
  379. // Check case insensitive comparison:
  380. Name small_upper("A.EXAMPLE");
  381. EXPECT_EQ(0, compareNames(small, small_upper));
  382. // the absence of an octet sorts before a zero octet.
  383. Name large2("a.example2");
  384. EXPECT_EQ(-1, compareNames(small, large2));
  385. EXPECT_EQ(1, compareNames(large2, small));
  386. }
  387. }