rdata_unittest.cc 17 KB

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