labelsequence_unittest.cc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. // Copyright (C) 2012 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 <dns/labelsequence.h>
  15. #include <dns/name.h>
  16. #include <exceptions/exceptions.h>
  17. #include <gtest/gtest.h>
  18. #include <boost/functional/hash.hpp>
  19. #include <string>
  20. #include <set>
  21. using namespace isc::dns;
  22. using namespace std;
  23. namespace {
  24. class LabelSequenceTest : public ::testing::Test {
  25. public:
  26. LabelSequenceTest() : n1("example.org"), n2("example.com"),
  27. n3("example.org"), n4("foo.bar.test.example"),
  28. n5("example.ORG"), n6("ExAmPlE.org"),
  29. n7("."), n8("foo.example.org.bar"),
  30. n9("\\000xample.org"),
  31. n10("\\000xample.org"),
  32. n11("\\000xample.com"),
  33. n12("\\000xamplE.com"),
  34. ls1(n1), ls2(n2), ls3(n3), ls4(n4), ls5(n5),
  35. ls6(n6), ls7(n7), ls8(n8),
  36. ls9(n9), ls10(n10), ls11(n11), ls12(n12)
  37. {};
  38. // Need to keep names in scope for at least the lifetime of
  39. // the labelsequences
  40. Name n1, n2, n3, n4, n5, n6, n7, n8;
  41. Name n9, n10, n11, n12;
  42. LabelSequence ls1, ls2, ls3, ls4, ls5, ls6, ls7, ls8;
  43. LabelSequence ls9, ls10, ls11, ls12;
  44. };
  45. // Basic equality tests
  46. TEST_F(LabelSequenceTest, equals_sensitive) {
  47. EXPECT_TRUE(ls1.equals(ls1, true));
  48. EXPECT_FALSE(ls1.equals(ls2, true));
  49. EXPECT_TRUE(ls1.equals(ls3, true));
  50. EXPECT_FALSE(ls1.equals(ls4, true));
  51. EXPECT_FALSE(ls1.equals(ls5, true));
  52. EXPECT_FALSE(ls1.equals(ls6, true));
  53. EXPECT_FALSE(ls1.equals(ls7, true));
  54. EXPECT_FALSE(ls1.equals(ls8, true));
  55. EXPECT_FALSE(ls2.equals(ls1, true));
  56. EXPECT_TRUE(ls2.equals(ls2, true));
  57. EXPECT_FALSE(ls2.equals(ls3, true));
  58. EXPECT_FALSE(ls2.equals(ls4, true));
  59. EXPECT_FALSE(ls2.equals(ls5, true));
  60. EXPECT_FALSE(ls2.equals(ls6, true));
  61. EXPECT_FALSE(ls2.equals(ls7, true));
  62. EXPECT_FALSE(ls2.equals(ls8, true));
  63. EXPECT_FALSE(ls4.equals(ls1, true));
  64. EXPECT_FALSE(ls4.equals(ls2, true));
  65. EXPECT_FALSE(ls4.equals(ls3, true));
  66. EXPECT_TRUE(ls4.equals(ls4, true));
  67. EXPECT_FALSE(ls4.equals(ls5, true));
  68. EXPECT_FALSE(ls4.equals(ls6, true));
  69. EXPECT_FALSE(ls4.equals(ls7, true));
  70. EXPECT_FALSE(ls4.equals(ls8, true));
  71. EXPECT_FALSE(ls5.equals(ls1, true));
  72. EXPECT_FALSE(ls5.equals(ls2, true));
  73. EXPECT_FALSE(ls5.equals(ls3, true));
  74. EXPECT_FALSE(ls5.equals(ls4, true));
  75. EXPECT_TRUE(ls5.equals(ls5, true));
  76. EXPECT_FALSE(ls5.equals(ls6, true));
  77. EXPECT_FALSE(ls5.equals(ls7, true));
  78. EXPECT_FALSE(ls5.equals(ls8, true));
  79. EXPECT_TRUE(ls9.equals(ls10, true));
  80. EXPECT_FALSE(ls9.equals(ls11, true));
  81. EXPECT_FALSE(ls9.equals(ls12, true));
  82. EXPECT_FALSE(ls11.equals(ls12, true));
  83. }
  84. TEST_F(LabelSequenceTest, equals_insensitive) {
  85. EXPECT_TRUE(ls1.equals(ls1));
  86. EXPECT_FALSE(ls1.equals(ls2));
  87. EXPECT_TRUE(ls1.equals(ls3));
  88. EXPECT_FALSE(ls1.equals(ls4));
  89. EXPECT_TRUE(ls1.equals(ls5));
  90. EXPECT_TRUE(ls1.equals(ls6));
  91. EXPECT_FALSE(ls1.equals(ls7));
  92. EXPECT_FALSE(ls2.equals(ls1));
  93. EXPECT_TRUE(ls2.equals(ls2));
  94. EXPECT_FALSE(ls2.equals(ls3));
  95. EXPECT_FALSE(ls2.equals(ls4));
  96. EXPECT_FALSE(ls2.equals(ls5));
  97. EXPECT_FALSE(ls2.equals(ls6));
  98. EXPECT_FALSE(ls2.equals(ls7));
  99. EXPECT_TRUE(ls3.equals(ls1));
  100. EXPECT_FALSE(ls3.equals(ls2));
  101. EXPECT_TRUE(ls3.equals(ls3));
  102. EXPECT_FALSE(ls3.equals(ls4));
  103. EXPECT_TRUE(ls3.equals(ls5));
  104. EXPECT_TRUE(ls3.equals(ls6));
  105. EXPECT_FALSE(ls3.equals(ls7));
  106. EXPECT_FALSE(ls4.equals(ls1));
  107. EXPECT_FALSE(ls4.equals(ls2));
  108. EXPECT_FALSE(ls4.equals(ls3));
  109. EXPECT_TRUE(ls4.equals(ls4));
  110. EXPECT_FALSE(ls4.equals(ls5));
  111. EXPECT_FALSE(ls4.equals(ls6));
  112. EXPECT_FALSE(ls4.equals(ls7));
  113. EXPECT_TRUE(ls5.equals(ls1));
  114. EXPECT_FALSE(ls5.equals(ls2));
  115. EXPECT_TRUE(ls5.equals(ls3));
  116. EXPECT_FALSE(ls5.equals(ls4));
  117. EXPECT_TRUE(ls5.equals(ls5));
  118. EXPECT_TRUE(ls5.equals(ls6));
  119. EXPECT_FALSE(ls5.equals(ls7));
  120. EXPECT_TRUE(ls9.equals(ls10));
  121. EXPECT_FALSE(ls9.equals(ls11));
  122. EXPECT_FALSE(ls9.equals(ls12));
  123. EXPECT_TRUE(ls11.equals(ls12));
  124. }
  125. void
  126. getDataCheck(const uint8_t* expected_data, size_t expected_len,
  127. const LabelSequence& ls)
  128. {
  129. size_t len;
  130. const uint8_t* data = ls.getData(&len);
  131. ASSERT_EQ(expected_len, len) << "Expected data: " << expected_data <<
  132. " name: " << ls.getName().toText();
  133. EXPECT_EQ(expected_len, ls.getDataLength()) <<
  134. "Expected data: " << expected_data <<
  135. " name: " << ls.getName().toText();
  136. for (size_t i = 0; i < len; ++i) {
  137. EXPECT_EQ(expected_data[i], data[i]) <<
  138. "Difference at pos " << i << ": Expected data: " << expected_data <<
  139. " name: " << ls.getName().toText();;
  140. }
  141. }
  142. // Convenient data converter for expected data. Label data must be of
  143. // uint8_t*, while it's convenient if we can specify some test data in
  144. // plain string (which is of char*). This wrapper converts the latter to
  145. // the former in a safer way.
  146. void
  147. getDataCheck(const char* expected_char_data, size_t expected_len,
  148. const LabelSequence& ls)
  149. {
  150. const vector<uint8_t> expected_data(expected_char_data,
  151. expected_char_data + expected_len);
  152. getDataCheck(&expected_data[0], expected_len, ls);
  153. }
  154. TEST_F(LabelSequenceTest, getData) {
  155. getDataCheck("\007example\003org\000", 13, ls1);
  156. getDataCheck("\007example\003com\000", 13, ls2);
  157. getDataCheck("\007example\003org\000", 13, ls3);
  158. getDataCheck("\003foo\003bar\004test\007example\000", 22, ls4);
  159. getDataCheck("\007example\003ORG\000", 13, ls5);
  160. getDataCheck("\007ExAmPlE\003org\000", 13, ls6);
  161. getDataCheck("\000", 1, ls7);
  162. };
  163. TEST_F(LabelSequenceTest, stripLeft) {
  164. EXPECT_TRUE(ls1.equals(ls3));
  165. ls1.stripLeft(0);
  166. getDataCheck("\007example\003org\000", 13, ls1);
  167. EXPECT_TRUE(ls1.equals(ls3));
  168. ls1.stripLeft(1);
  169. getDataCheck("\003org\000", 5, ls1);
  170. EXPECT_FALSE(ls1.equals(ls3));
  171. ls1.stripLeft(1);
  172. getDataCheck("\000", 1, ls1);
  173. EXPECT_TRUE(ls1.equals(ls7));
  174. ls2.stripLeft(2);
  175. getDataCheck("\000", 1, ls2);
  176. EXPECT_TRUE(ls2.equals(ls7));
  177. }
  178. TEST_F(LabelSequenceTest, stripRight) {
  179. EXPECT_TRUE(ls1.equals(ls3));
  180. ls1.stripRight(1);
  181. getDataCheck("\007example\003org", 12, ls1);
  182. EXPECT_FALSE(ls1.equals(ls3));
  183. ls1.stripRight(1);
  184. getDataCheck("\007example", 8, ls1);
  185. EXPECT_FALSE(ls1.equals(ls3));
  186. ASSERT_FALSE(ls1.equals(ls2));
  187. ls2.stripRight(2);
  188. getDataCheck("\007example", 8, ls2);
  189. EXPECT_TRUE(ls1.equals(ls2));
  190. }
  191. TEST_F(LabelSequenceTest, stripOutOfRange) {
  192. EXPECT_THROW(ls1.stripLeft(100), isc::OutOfRange);
  193. EXPECT_THROW(ls1.stripLeft(5), isc::OutOfRange);
  194. EXPECT_THROW(ls1.stripLeft(4), isc::OutOfRange);
  195. EXPECT_THROW(ls1.stripLeft(3), isc::OutOfRange);
  196. getDataCheck("\007example\003org\000", 13, ls1);
  197. EXPECT_THROW(ls1.stripRight(100), isc::OutOfRange);
  198. EXPECT_THROW(ls1.stripRight(5), isc::OutOfRange);
  199. EXPECT_THROW(ls1.stripRight(4), isc::OutOfRange);
  200. EXPECT_THROW(ls1.stripRight(3), isc::OutOfRange);
  201. getDataCheck("\007example\003org\000", 13, ls1);
  202. }
  203. TEST_F(LabelSequenceTest, getLabelCount) {
  204. EXPECT_EQ(3, ls1.getLabelCount());
  205. ls1.stripLeft(0);
  206. EXPECT_EQ(3, ls1.getLabelCount());
  207. ls1.stripLeft(1);
  208. EXPECT_EQ(2, ls1.getLabelCount());
  209. ls1.stripLeft(1);
  210. EXPECT_EQ(1, ls1.getLabelCount());
  211. EXPECT_EQ(3, ls2.getLabelCount());
  212. ls2.stripRight(1);
  213. EXPECT_EQ(2, ls2.getLabelCount());
  214. ls2.stripRight(1);
  215. EXPECT_EQ(1, ls2.getLabelCount());
  216. EXPECT_EQ(3, ls3.getLabelCount());
  217. ls3.stripRight(2);
  218. EXPECT_EQ(1, ls3.getLabelCount());
  219. EXPECT_EQ(5, ls4.getLabelCount());
  220. ls4.stripRight(3);
  221. EXPECT_EQ(2, ls4.getLabelCount());
  222. EXPECT_EQ(3, ls5.getLabelCount());
  223. ls5.stripLeft(2);
  224. EXPECT_EQ(1, ls5.getLabelCount());
  225. }
  226. TEST_F(LabelSequenceTest, comparePart) {
  227. EXPECT_FALSE(ls1.equals(ls8));
  228. // strip root label from example.org.
  229. ls1.stripRight(1);
  230. // strip foo from foo.example.org.bar.
  231. ls8.stripLeft(1);
  232. // strip bar. (i.e. bar and root) too
  233. ls8.stripRight(2);
  234. EXPECT_TRUE(ls1.equals(ls8));
  235. // Data comparison
  236. size_t len;
  237. const uint8_t* data = ls1.getData(&len);
  238. getDataCheck(data, len, ls8);
  239. }
  240. TEST_F(LabelSequenceTest, isAbsolute) {
  241. ASSERT_TRUE(ls1.isAbsolute());
  242. ls1.stripLeft(1);
  243. ASSERT_TRUE(ls1.isAbsolute());
  244. ls1.stripRight(1);
  245. ASSERT_FALSE(ls1.isAbsolute());
  246. ASSERT_TRUE(ls2.isAbsolute());
  247. ls2.stripRight(1);
  248. ASSERT_FALSE(ls2.isAbsolute());
  249. ASSERT_TRUE(ls3.isAbsolute());
  250. ls3.stripLeft(2);
  251. ASSERT_TRUE(ls3.isAbsolute());
  252. }
  253. TEST_F(LabelSequenceTest, toText) {
  254. EXPECT_EQ("example.org.", ls1.toText());
  255. ls1.stripLeft(1);
  256. EXPECT_EQ("org.", ls1.toText());
  257. ls1.stripLeft(1);
  258. EXPECT_EQ(".", ls1.toText());
  259. EXPECT_EQ("example.com.", ls2.toText());
  260. ls2.stripRight(1);
  261. EXPECT_EQ("example", ls2.toText());
  262. ls2.stripRight(1);
  263. EXPECT_EQ("", ls2.toText());
  264. EXPECT_EQ("foo.example.org.bar.", ls8.toText());
  265. ls8.stripRight(2);
  266. EXPECT_EQ("foo.example", ls8.toText());
  267. EXPECT_EQ(".", ls7.toText());
  268. EXPECT_THROW(ls7.stripLeft(1), isc::OutOfRange);
  269. }
  270. // The following are test data used in the getHash test below. Normally
  271. // we use example/documentation domain names for testing, but in this case
  272. // we'd specifically like to use more realistic data, and are intentionally
  273. // using real-world samples: They are the NS names of root and some top level
  274. // domains as of this test.
  275. const char* const root_servers[] = {
  276. "a.root-servers.net", "b.root-servers.net", "c.root-servers.net",
  277. "d.root-servers.net", "e.root-servers.net", "f.root-servers.net",
  278. "g.root-servers.net", "h.root-servers.net", "i.root-servers.net",
  279. "j.root-servers.net", "k.root-servers.net", "l.root-servers.net",
  280. "m.root-servers.net", NULL
  281. };
  282. const char* const gtld_servers[] = {
  283. "a.gtld-servers.net", "b.gtld-servers.net", "c.gtld-servers.net",
  284. "d.gtld-servers.net", "e.gtld-servers.net", "f.gtld-servers.net",
  285. "g.gtld-servers.net", "h.gtld-servers.net", "i.gtld-servers.net",
  286. "j.gtld-servers.net", "k.gtld-servers.net", "l.gtld-servers.net",
  287. "m.gtld-servers.net", NULL
  288. };
  289. const char* const jp_servers[] = {
  290. "a.dns.jp", "b.dns.jp", "c.dns.jp", "d.dns.jp", "e.dns.jp",
  291. "f.dns.jp", "g.dns.jp", NULL
  292. };
  293. const char* const cn_servers[] = {
  294. "a.dns.cn", "b.dns.cn", "c.dns.cn", "d.dns.cn", "e.dns.cn",
  295. "ns.cernet.net", NULL
  296. };
  297. const char* const ca_servers[] = {
  298. "k.ca-servers.ca", "e.ca-servers.ca", "a.ca-servers.ca", "z.ca-servers.ca",
  299. "tld.isc-sns.net", "c.ca-servers.ca", "j.ca-servers.ca", "l.ca-servers.ca",
  300. "sns-pb.isc.org", "f.ca-servers.ca", NULL
  301. };
  302. // A helper function used in the getHash test below.
  303. void
  304. hashDistributionCheck(const char* const* servers) {
  305. const size_t BUCKETS = 64; // constant used in the MessageRenderer
  306. set<Name> names;
  307. vector<size_t> hash_counts(BUCKETS);
  308. // Store all test names and their super domain names (excluding the
  309. // "root" label) in the set, calculates their hash values, and increments
  310. // the counter for the corresponding hash "bucket".
  311. for (size_t i = 0; servers[i] != NULL; ++i) {
  312. const Name name(servers[i]);
  313. for (size_t l = 0; l < name.getLabelCount() - 1; ++l) {
  314. pair<set<Name>::const_iterator, bool> ret =
  315. names.insert(name.split(l));
  316. if (ret.second) {
  317. hash_counts[LabelSequence((*ret.first)).getHash(false) %
  318. BUCKETS]++;
  319. }
  320. }
  321. }
  322. // See how many conflicts we have in the buckets. For the testing purpose
  323. // we expect there's at most 2 conflicts in each set, which is an
  324. // arbitrary choice (it should happen to succeed with the hash function
  325. // and data we are using; if it's not the case, maybe with an update to
  326. // the hash implementation, we should revise the test).
  327. for (size_t i = 0; i < BUCKETS; ++i) {
  328. EXPECT_GE(3, hash_counts[i]);
  329. }
  330. }
  331. TEST_F(LabelSequenceTest, getHash) {
  332. // Trivial case. The same sequence should have the same hash.
  333. EXPECT_EQ(ls1.getHash(true), ls1.getHash(true));
  334. // Check the case-insensitive mode behavior.
  335. EXPECT_EQ(ls1.getHash(false), ls5.getHash(false));
  336. // Check that the distribution of hash values is "not too bad" (such as
  337. // everything has the same hash value due to a stupid bug). It's
  338. // difficult to check such things reliably. We do some ad hoc tests here.
  339. hashDistributionCheck(root_servers);
  340. hashDistributionCheck(jp_servers);
  341. hashDistributionCheck(cn_servers);
  342. hashDistributionCheck(ca_servers);
  343. }
  344. // test operator<<. We simply confirm it appends the result of toText().
  345. TEST_F(LabelSequenceTest, LeftShiftOperator) {
  346. ostringstream oss;
  347. oss << ls1;
  348. EXPECT_EQ(ls1.toText(), oss.str());
  349. }
  350. }