rdata_unittest.cc 17 KB

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