rrset_unittest.cc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  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 <stdexcept>
  15. #include <iostream>
  16. #include <util/buffer.h>
  17. #include <dns/messagerenderer.h>
  18. #include <dns/name.h>
  19. #include <dns/rdata.h>
  20. #include <dns/rdataclass.h>
  21. #include <dns/rrclass.h>
  22. #include <dns/rrtype.h>
  23. #include <dns/rrttl.h>
  24. #include <dns/rrset.h>
  25. #include <gtest/gtest.h>
  26. #include <dns/tests/unittest_util.h>
  27. using isc::UnitTestUtil;
  28. using namespace std;
  29. using namespace isc::dns;
  30. using namespace isc::util;
  31. using namespace isc::dns::rdata;
  32. namespace {
  33. class RRsetTest : public ::testing::Test {
  34. protected:
  35. RRsetTest() : buffer(0),
  36. test_name("test.example.com"),
  37. test_domain("example.com"),
  38. test_nsname("ns.example.com"),
  39. rrset_a(test_name, RRClass::IN(), RRType::A(), RRTTL(3600)),
  40. rrset_a_empty(test_name, RRClass::IN(), RRType::A(),
  41. RRTTL(3600)),
  42. rrset_ns(test_domain, RRClass::IN(), RRType::NS(),
  43. RRTTL(86400)),
  44. rrset_ch_txt(test_domain, RRClass::CH(), RRType::TXT(),
  45. RRTTL(0))
  46. {
  47. rrset_a.addRdata(in::A("192.0.2.1"));
  48. rrset_a.addRdata(in::A("192.0.2.2"));
  49. }
  50. OutputBuffer buffer;
  51. MessageRenderer renderer;
  52. Name test_name;
  53. Name test_domain;
  54. Name test_nsname;
  55. RRset rrset_a;
  56. RRset rrset_a_empty;
  57. RRset rrset_ns;
  58. RRset rrset_ch_txt;
  59. std::vector<unsigned char> wiredata;
  60. // max number of Rdata objects added to a test RRset object.
  61. // this is an arbitrary chosen limit, but should be sufficiently large
  62. // in practice and reasonable even as an extreme test case.
  63. static const int MAX_RDATA_COUNT = 100;
  64. };
  65. TEST_F(RRsetTest, getRdataCount) {
  66. for (int i = 0; i < MAX_RDATA_COUNT; ++i) {
  67. EXPECT_EQ(i, rrset_a_empty.getRdataCount());
  68. rrset_a_empty.addRdata(in::A("192.0.2.1"));
  69. }
  70. }
  71. TEST_F(RRsetTest, getName) {
  72. EXPECT_EQ(test_name, rrset_a.getName());
  73. EXPECT_EQ(test_domain, rrset_ns.getName());
  74. }
  75. TEST_F(RRsetTest, getClass) {
  76. EXPECT_EQ(RRClass("IN"), rrset_a.getClass());
  77. EXPECT_EQ(RRClass("CH"), rrset_ch_txt.getClass());
  78. }
  79. TEST_F(RRsetTest, getType) {
  80. EXPECT_EQ(RRType("A"), rrset_a.getType());
  81. EXPECT_EQ(RRType("NS"), rrset_ns.getType());
  82. EXPECT_EQ(RRType("TXT"), rrset_ch_txt.getType());
  83. }
  84. TEST_F(RRsetTest, getTTL) {
  85. EXPECT_EQ(RRTTL(3600), rrset_a.getTTL());
  86. EXPECT_EQ(RRTTL(86400), rrset_ns.getTTL());
  87. EXPECT_EQ(RRTTL(0), rrset_ch_txt.getTTL());
  88. }
  89. TEST_F(RRsetTest, setTTL) {
  90. rrset_a.setTTL(RRTTL(86400));
  91. EXPECT_EQ(RRTTL(86400), rrset_a.getTTL());
  92. rrset_a.setTTL(RRTTL(0));
  93. EXPECT_EQ(RRTTL(0), rrset_a.getTTL());
  94. }
  95. TEST_F(RRsetTest, setName) {
  96. rrset_a.setName(test_nsname);
  97. EXPECT_EQ(test_nsname, rrset_a.getName());
  98. }
  99. TEST_F(RRsetTest, isSameKind) {
  100. RRset rrset_w(test_name, RRClass::IN(), RRType::A(), RRTTL(3600));
  101. RRset rrset_x(test_name, RRClass::IN(), RRType::A(), RRTTL(3600));
  102. RRset rrset_y(test_name, RRClass::IN(), RRType::NS(), RRTTL(3600));
  103. RRset rrset_z(test_name, RRClass::CH(), RRType::A(), RRTTL(3600));
  104. RRset rrset_p(test_nsname, RRClass::IN(), RRType::A(), RRTTL(3600));
  105. EXPECT_TRUE(rrset_w.isSameKind(rrset_w));
  106. EXPECT_TRUE(rrset_w.isSameKind(rrset_x));
  107. EXPECT_FALSE(rrset_w.isSameKind(rrset_y));
  108. EXPECT_FALSE(rrset_w.isSameKind(rrset_z));
  109. EXPECT_FALSE(rrset_w.isSameKind(rrset_p));
  110. }
  111. // Utility function to create an add an RRset to a vector of RRsets for the
  112. // "less" test. It's only purpose is to allow the RRset creation to be
  113. // written with arguments in an order that reflects the RRset ordering.
  114. void
  115. addRRset(std::vector<ConstRRsetPtr>& vec, const RRType& rrtype,
  116. const RRClass& rrclass, const char* rrname)
  117. {
  118. vec.push_back(ConstRRsetPtr(new RRset(Name(rrname), rrclass, rrtype,
  119. RRTTL(3600))));
  120. }
  121. TEST_F(RRsetTest, lthan) {
  122. // Check values of type codes: this effectively documents the expected
  123. // order of the rrsets created.
  124. ASSERT_EQ(1, RRType::A().getCode());
  125. ASSERT_EQ(2, RRType::NS().getCode());
  126. ASSERT_EQ(1, RRClass::IN().getCode());
  127. ASSERT_EQ(3, RRClass::CH().getCode());
  128. // Create a vector of RRsets in ascending sort order.
  129. std::vector<ConstRRsetPtr> rrsets;
  130. addRRset(rrsets, RRType::A(), RRClass::IN(), "alpha.com");
  131. addRRset(rrsets, RRType::A(), RRClass::IN(), "beta.com");
  132. addRRset(rrsets, RRType::A(), RRClass::CH(), "alpha.com");
  133. addRRset(rrsets, RRType::A(), RRClass::CH(), "beta.com");
  134. addRRset(rrsets, RRType::NS(), RRClass::IN(), "alpha.com");
  135. addRRset(rrsets, RRType::NS(), RRClass::IN(), "beta.com");
  136. addRRset(rrsets, RRType::NS(), RRClass::CH(), "alpha.com");
  137. addRRset(rrsets, RRType::NS(), RRClass::CH(), "beta.com");
  138. // ... and do the checks. The ASSERT_ form is used to avoid a plethora
  139. // of messages if there is an error. And if there is an error, supply
  140. // a more informative message.
  141. for (int i = 0; i < rrsets.size(); ++i) {
  142. // Check that an RRset is not less than itself
  143. ostringstream ossi;
  144. ossi << "i = ("
  145. << rrsets[i]->getType().toText() << ", "
  146. << rrsets[i]->getClass().toText() << ", "
  147. << rrsets[i]->getName().toText()
  148. << ")";
  149. ASSERT_FALSE(rrsets[i]->lthan(*rrsets[i])) << ossi.str();
  150. for (int j = i + 1; j < rrsets.size(); ++j) {
  151. // Check it against the remaining RRsets.
  152. ostringstream ossj;
  153. ossj << ", j = ("
  154. << rrsets[j]->getType().toText() << ", "
  155. << rrsets[j]->getClass().toText() << ", "
  156. << rrsets[j]->getName().toText()
  157. << ")";
  158. ASSERT_TRUE(rrsets[i]->lthan(*rrsets[j]))
  159. << ossi.str() << ossj.str();
  160. ASSERT_FALSE(rrsets[j]->lthan(*rrsets[i]))
  161. << ossi.str() << ossj.str();
  162. }
  163. }
  164. }
  165. void
  166. addRdataTestCommon(const RRset& rrset) {
  167. EXPECT_EQ(2, rrset.getRdataCount());
  168. RdataIteratorPtr it = rrset.getRdataIterator(); // cursor is set to the 1st
  169. EXPECT_FALSE(it->isLast());
  170. EXPECT_EQ(0, it->getCurrent().compare(in::A("192.0.2.1")));
  171. it->next();
  172. EXPECT_FALSE(it->isLast());
  173. EXPECT_EQ(0, it->getCurrent().compare(in::A("192.0.2.2")));
  174. it->next();
  175. EXPECT_TRUE(it->isLast());
  176. }
  177. TEST_F(RRsetTest, addRdata) {
  178. addRdataTestCommon(rrset_a);
  179. // Reference version of addRdata() doesn't allow to add a different
  180. // type of Rdata.
  181. EXPECT_THROW(rrset_a.addRdata(generic::NS(test_nsname)), std::bad_cast);
  182. }
  183. TEST_F(RRsetTest, addRdataPtr) {
  184. rrset_a_empty.addRdata(createRdata(rrset_a_empty.getType(),
  185. rrset_a_empty.getClass(),
  186. "192.0.2.1"));
  187. rrset_a_empty.addRdata(createRdata(rrset_a_empty.getType(),
  188. rrset_a_empty.getClass(),
  189. "192.0.2.2"));
  190. addRdataTestCommon(rrset_a);
  191. // Pointer version of addRdata() doesn't type check and does allow to
  192. //add a different type of Rdata as a result.
  193. rrset_a_empty.addRdata(createRdata(RRType::NS(), RRClass::IN(),
  194. "ns.example.com"));
  195. EXPECT_EQ(3, rrset_a_empty.getRdataCount());
  196. }
  197. TEST_F(RRsetTest, iterator) {
  198. // Iterator for an empty RRset.
  199. RdataIteratorPtr it = rrset_a_empty.getRdataIterator();
  200. EXPECT_TRUE(it->isLast());
  201. // Normal case (already tested, but do it again just in case)
  202. rrset_a_empty.addRdata(in::A("192.0.2.1"));
  203. rrset_a_empty.addRdata(in::A("192.0.2.2"));
  204. addRdataTestCommon(rrset_a_empty);
  205. // Rewind test: should be repeat the iteration by calling first().
  206. for (int i = 0; i < 2; ++i) {
  207. it = rrset_a_empty.getRdataIterator();
  208. it->first();
  209. EXPECT_FALSE(it->isLast());
  210. it->next();
  211. EXPECT_FALSE(it->isLast());
  212. it->next();
  213. EXPECT_TRUE(it->isLast());
  214. }
  215. }
  216. TEST_F(RRsetTest, toText) {
  217. EXPECT_EQ("test.example.com. 3600 IN A 192.0.2.1\n"
  218. "test.example.com. 3600 IN A 192.0.2.2\n",
  219. rrset_a.toText());
  220. // toText() cannot be performed for an empty RRset.
  221. EXPECT_THROW(rrset_a_empty.toText(), EmptyRRset);
  222. }
  223. TEST_F(RRsetTest, toWireBuffer) {
  224. rrset_a.toWire(buffer);
  225. UnitTestUtil::readWireData("rrset_toWire1", wiredata);
  226. EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, buffer.getData(),
  227. buffer.getLength(), &wiredata[0], wiredata.size());
  228. // toWire() cannot be performed for an empty RRset.
  229. buffer.clear();
  230. EXPECT_THROW(rrset_a_empty.toWire(buffer), EmptyRRset);
  231. }
  232. TEST_F(RRsetTest, toWireRenderer) {
  233. rrset_ns.addRdata(generic::NS(test_nsname));
  234. rrset_a.toWire(renderer);
  235. rrset_ns.toWire(renderer);
  236. UnitTestUtil::readWireData("rrset_toWire2", wiredata);
  237. EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(),
  238. renderer.getLength(), &wiredata[0], wiredata.size());
  239. // toWire() cannot be performed for an empty RRset.
  240. renderer.clear();
  241. EXPECT_THROW(rrset_a_empty.toWire(renderer), EmptyRRset);
  242. }
  243. // test operator<<. We simply confirm it appends the result of toText().
  244. TEST_F(RRsetTest, LeftShiftOperator) {
  245. ostringstream oss;
  246. oss << rrset_a;
  247. EXPECT_EQ(rrset_a.toText(), oss.str());
  248. }
  249. }