static_unittest.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  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 <stdint.h>
  15. #include <string>
  16. #include <vector>
  17. #include <config.h>
  18. #include <gtest/gtest.h>
  19. #include <dns/name.h>
  20. #include <dns/message.h>
  21. #include <dns/rdata.h>
  22. #include <dns/rrclass.h>
  23. #include <dns/rrtype.h>
  24. #include <dns/rdataclass.h>
  25. #include <dns/rrsetlist.h>
  26. #include <cc/data.h>
  27. #include <datasrc/query.h>
  28. #include <datasrc/data_source.h>
  29. #include <datasrc/static_datasrc.h>
  30. using namespace std;
  31. using namespace isc::dns;
  32. using namespace isc::dns::rdata;
  33. using namespace isc::datasrc;
  34. namespace {
  35. class StaticDataSourceTest : public ::testing::Test {
  36. protected:
  37. StaticDataSourceTest() : version_name("version.bind"),
  38. authors_name("authors.bind"),
  39. nomatch_name("example.com"),
  40. rrclass(RRClass::CH()), rrtype(RRType::TXT()),
  41. rrttl(RRTTL(0)), find_flags(0), matched_rdata(0)
  42. {
  43. // version.bind is answered with package name+version
  44. // (defined as PACKAGE_STRING in config.h)
  45. version_data.push_back(PACKAGE_STRING);
  46. // NOTE: in addition, the order of the following items matter.
  47. authors_data.push_back("Chen Zhengzhang");
  48. authors_data.push_back("Dmitriy Volodin");
  49. authors_data.push_back("Evan Hunt");
  50. authors_data.push_back("Haidong Wang");
  51. authors_data.push_back("Haikuo Zhang");
  52. authors_data.push_back("Han Feng");
  53. authors_data.push_back("Jelte Jansen");
  54. authors_data.push_back("Jeremy C. Reed");
  55. authors_data.push_back("Xie Jiagui");
  56. authors_data.push_back("Jin Jian");
  57. authors_data.push_back("JINMEI Tatuya");
  58. authors_data.push_back("Kazunori Fujiwara");
  59. authors_data.push_back("Michael Graff");
  60. authors_data.push_back("Michal Vaner");
  61. authors_data.push_back("Mukund Sivaraman");
  62. authors_data.push_back("Naoki Kambe");
  63. authors_data.push_back("Shane Kerr");
  64. authors_data.push_back("Shen Tingting");
  65. authors_data.push_back("Stephen Morris");
  66. authors_data.push_back("Yoshitaka Aharen");
  67. authors_data.push_back("Zhang Likun");
  68. version_ns_data.push_back("version.bind.");
  69. authors_ns_data.push_back("authors.bind.");
  70. version_soa_data.push_back("version.bind. hostmaster.version.bind. "
  71. "0 28800 7200 604800 86400");
  72. authors_soa_data.push_back("authors.bind. hostmaster.authors.bind. "
  73. "0 28800 7200 604800 86400");
  74. }
  75. StaticDataSrc data_source;
  76. const Name version_name;
  77. const Name authors_name;
  78. const Name nomatch_name;
  79. const RRClass rrclass;
  80. RRType rrtype; // we allow this to be modified in the test
  81. RRTTL rrttl;
  82. RRsetList result_sets;
  83. uint32_t find_flags;
  84. unsigned matched_rdata;
  85. vector<RRType> types;
  86. vector<RRTTL> ttls;
  87. vector<const vector<string>* > answers;
  88. vector<string> version_data;
  89. vector<string> authors_data;
  90. vector<string> version_ns_data;
  91. vector<string> authors_ns_data;
  92. vector<string> version_soa_data;
  93. vector<string> authors_soa_data;
  94. };
  95. void
  96. checkRRset(ConstRRsetPtr rrset, const Name& expected_name,
  97. const RRClass& expected_class, const RRType& expected_type,
  98. const RRTTL& rrttl, const vector<string>& expected_data)
  99. {
  100. EXPECT_EQ(expected_name, rrset->getName());
  101. EXPECT_EQ(expected_class, rrset->getClass());
  102. EXPECT_EQ(expected_type, rrset->getType());
  103. EXPECT_EQ(rrttl, rrset->getTTL());
  104. RdataIteratorPtr rdata_iterator = rrset->getRdataIterator();
  105. vector<string>::const_iterator data_it = expected_data.begin();
  106. for (; data_it != expected_data.end(); ++data_it) {
  107. EXPECT_FALSE(rdata_iterator->isLast());
  108. if (rdata_iterator->isLast()) {
  109. // buggy case, should stop here
  110. break;
  111. }
  112. EXPECT_EQ(0, (rdata_iterator->getCurrent()).compare(
  113. *createRdata(expected_type,
  114. expected_class,
  115. *data_it)));
  116. rdata_iterator->next();
  117. }
  118. EXPECT_TRUE(rdata_iterator->isLast());
  119. }
  120. void
  121. checkFind(const DataSrc& data_source,
  122. const Name& qname, const Name* zone_name,
  123. const RRClass& qclass, const RRClass& expected_class,
  124. const RRType& qtype, const vector<RRTTL>& expected_ttls,
  125. const uint32_t expected_flags, const vector<RRType>& expected_types,
  126. const vector<const vector<string>* >& expected_answers)
  127. {
  128. RRsetList result_sets;
  129. uint32_t find_flags;
  130. unsigned int rrset_matched = 0;
  131. unsigned int rrset_count = 0;
  132. EXPECT_EQ(DataSrc::SUCCESS,
  133. data_source.findRRset(qname, qclass, qtype, result_sets,
  134. find_flags, zone_name));
  135. EXPECT_EQ(expected_flags, find_flags);
  136. if ((find_flags & (DataSrc::NO_SUCH_ZONE | DataSrc::NAME_NOT_FOUND |
  137. DataSrc::TYPE_NOT_FOUND)) != 0) {
  138. EXPECT_TRUE(result_sets.begin() == result_sets.end());
  139. return;
  140. }
  141. RRsetList::iterator it = result_sets.begin();
  142. for (; it != result_sets.end(); ++it) {
  143. vector<RRType>::const_iterator found_type =
  144. find(expected_types.begin(), expected_types.end(),
  145. (*it)->getType());
  146. // there should be a match
  147. EXPECT_TRUE(found_type != expected_types.end());
  148. if (found_type != expected_types.end()) {
  149. unsigned int index = distance(expected_types.begin(), found_type);
  150. checkRRset(*it, qname, expected_class, (*it)->getType(),
  151. expected_ttls[index], *expected_answers[index]);
  152. ++rrset_matched;
  153. }
  154. ++rrset_count;
  155. }
  156. EXPECT_EQ(expected_types.size(), rrset_count);
  157. EXPECT_EQ(expected_types.size(), rrset_matched);
  158. }
  159. void
  160. checkFind(const DataSrc& data_source,
  161. const Name& qname, const Name* zone_name,
  162. const RRClass& qclass, const RRClass& expected_class,
  163. const RRType& qtype, // == expected RRType
  164. const RRTTL& expected_ttl, const uint32_t expected_flags,
  165. const vector<string>& expected_answers)
  166. {
  167. vector<RRType> types;
  168. vector<RRTTL> ttls;
  169. vector<const vector<string>* > answers;
  170. types.push_back(qtype);
  171. ttls.push_back(expected_ttl);
  172. answers.push_back(&expected_answers);
  173. checkFind(data_source, qname, zone_name, qclass, expected_class, qtype,
  174. ttls, expected_flags, types, answers);
  175. }
  176. TEST_F(StaticDataSourceTest, init) {
  177. EXPECT_EQ(DataSrc::SUCCESS, data_source.init());
  178. }
  179. TEST_F(StaticDataSourceTest, close) {
  180. EXPECT_EQ(DataSrc::SUCCESS, data_source.init());
  181. }
  182. TEST_F(StaticDataSourceTest, findClosestEnclosureForVersion) {
  183. DataSrcMatch match(version_name, rrclass);
  184. data_source.findClosestEnclosure(match);
  185. EXPECT_EQ(version_name, *match.getEnclosingZone());
  186. EXPECT_EQ(&data_source, match.getDataSource());
  187. }
  188. // Class Any query should result in the same answer.
  189. TEST_F(StaticDataSourceTest, findClosestEnclosureForVersionClassAny) {
  190. DataSrcMatch match(version_name, RRClass::ANY());
  191. data_source.findClosestEnclosure(match);
  192. EXPECT_EQ(version_name, *match.getEnclosingZone());
  193. EXPECT_EQ(&data_source, match.getDataSource());
  194. }
  195. // If class doesn't match the lookup should fail.
  196. TEST_F(StaticDataSourceTest, findClosestEnclosureForVersionClassMismatch) {
  197. DataSrcMatch match(version_name, RRClass::IN());
  198. data_source.findClosestEnclosure(match);
  199. EXPECT_EQ(static_cast<void*>(NULL), match.getEnclosingZone());
  200. EXPECT_EQ(static_cast<void*>(NULL), match.getDataSource());
  201. }
  202. TEST_F(StaticDataSourceTest, findClosestEnclosureForVersionPartial) {
  203. DataSrcMatch match(Name("foo").concatenate(version_name), rrclass);
  204. data_source.findClosestEnclosure(match);
  205. EXPECT_EQ(version_name, *match.getEnclosingZone());
  206. EXPECT_EQ(&data_source, match.getDataSource());
  207. }
  208. TEST_F(StaticDataSourceTest, findClosestEnclosureForAuthors) {
  209. DataSrcMatch match(authors_name, rrclass);
  210. data_source.findClosestEnclosure(match);
  211. EXPECT_EQ(authors_name, *match.getEnclosingZone());
  212. EXPECT_EQ(&data_source, match.getDataSource());
  213. }
  214. TEST_F(StaticDataSourceTest, findClosestEnclosureForAuthorsPartial) {
  215. DataSrcMatch match(Name("foo").concatenate(authors_name), rrclass);
  216. data_source.findClosestEnclosure(match);
  217. EXPECT_EQ(authors_name, *match.getEnclosingZone());
  218. EXPECT_EQ(&data_source, match.getDataSource());
  219. }
  220. TEST_F(StaticDataSourceTest, findClosestEnclosureNoMatch) {
  221. DataSrcMatch match(nomatch_name, rrclass);
  222. data_source.findClosestEnclosure(match);
  223. EXPECT_EQ(static_cast<void*>(NULL), match.getEnclosingZone());
  224. EXPECT_EQ(static_cast<void*>(NULL), match.getDataSource());
  225. }
  226. TEST_F(StaticDataSourceTest, findRRsetVersionTXT) {
  227. checkFind(data_source, version_name, NULL, rrclass, rrclass,
  228. rrtype, rrttl, 0, version_data);
  229. checkFind(data_source, version_name, &version_name, rrclass, rrclass,
  230. rrtype, rrttl, 0, version_data);
  231. }
  232. TEST_F(StaticDataSourceTest, findRRsetVersionNS) {
  233. rrtype = RRType::NS();
  234. checkFind(data_source, version_name, NULL, rrclass, rrclass,
  235. rrtype, rrttl, 0, version_ns_data);
  236. checkFind(data_source, version_name, &version_name, rrclass, rrclass,
  237. rrtype, rrttl, 0, version_ns_data);
  238. }
  239. TEST_F(StaticDataSourceTest, findRRsetVersionSOA) {
  240. rrtype = RRType::SOA();
  241. checkFind(data_source, version_name, NULL, rrclass, rrclass,
  242. rrtype, rrttl, 0, version_soa_data);
  243. checkFind(data_source, version_name, &version_name, rrclass, rrclass,
  244. rrtype, rrttl, 0, version_soa_data);
  245. }
  246. TEST_F(StaticDataSourceTest, findRRsetVersionANY) {
  247. rrtype = RRType::ANY();
  248. types.push_back(RRType::TXT());
  249. types.push_back(RRType::NS());
  250. types.push_back(RRType::SOA());
  251. ttls.push_back(rrttl);
  252. ttls.push_back(rrttl);
  253. ttls.push_back(rrttl);
  254. answers.push_back(&version_data);
  255. answers.push_back(&version_ns_data);
  256. answers.push_back(&version_soa_data);
  257. checkFind(data_source, version_name, NULL, rrclass, rrclass, rrtype, ttls,
  258. 0, types, answers);
  259. checkFind(data_source, version_name, &version_name, rrclass, rrclass,
  260. rrtype, ttls, 0, types, answers);
  261. }
  262. TEST_F(StaticDataSourceTest, findRRsetAuthorsTXT) {
  263. checkFind(data_source, authors_name, NULL, rrclass, rrclass,
  264. rrtype, rrttl, 0, authors_data);
  265. checkFind(data_source, authors_name, &authors_name, rrclass, rrclass,
  266. rrtype, rrttl, 0, authors_data);
  267. }
  268. TEST_F(StaticDataSourceTest, findRRsetAuthorsNS) {
  269. rrtype = RRType::NS();
  270. checkFind(data_source, authors_name, NULL, rrclass, rrclass,
  271. rrtype, rrttl, 0, authors_ns_data);
  272. checkFind(data_source, authors_name, &authors_name, rrclass, rrclass,
  273. rrtype, rrttl, 0, authors_ns_data);
  274. }
  275. TEST_F(StaticDataSourceTest, findRRsetAuthorsSOA) {
  276. rrtype = RRType::SOA();
  277. checkFind(data_source, authors_name, NULL, rrclass, rrclass,
  278. rrtype, rrttl, 0, authors_soa_data);
  279. checkFind(data_source, authors_name, &authors_name, rrclass, rrclass,
  280. rrtype, rrttl, 0, authors_soa_data);
  281. }
  282. TEST_F(StaticDataSourceTest, findRRsetAuthorsANY) {
  283. rrtype = RRType::ANY();
  284. types.push_back(RRType::TXT());
  285. types.push_back(RRType::NS());
  286. types.push_back(RRType::SOA());
  287. ttls.push_back(rrttl);
  288. ttls.push_back(rrttl);
  289. ttls.push_back(rrttl);
  290. answers.push_back(&authors_data);
  291. answers.push_back(&authors_ns_data);
  292. answers.push_back(&authors_soa_data);
  293. checkFind(data_source, authors_name, NULL, rrclass, rrclass, rrtype, ttls,
  294. 0, types, answers);
  295. checkFind(data_source, authors_name, &authors_name, rrclass, rrclass,
  296. rrtype, ttls, 0, types, answers);
  297. }
  298. // Class ANY lookup should result in the same answer.
  299. TEST_F(StaticDataSourceTest, findRRsetVersionClassAny) {
  300. checkFind(data_source, version_name, NULL, RRClass::ANY(), rrclass,
  301. rrtype, rrttl, 0, version_data);
  302. checkFind(data_source, version_name, &version_name, RRClass::ANY(), rrclass,
  303. rrtype, rrttl, 0, version_data);
  304. }
  305. // If the class doesn't match, it should simply fail.
  306. TEST_F(StaticDataSourceTest, findRRsetVersionClassMismatch) {
  307. EXPECT_EQ(DataSrc::ERROR,
  308. data_source.findRRset(version_name, RRClass::IN(), rrtype,
  309. result_sets, find_flags, &version_name));
  310. }
  311. TEST_F(StaticDataSourceTest, findRRsetOutOfZone) {
  312. // If the qname doesn't match any of the static zones, the result should
  313. // be "no such zone", regardless of whether the zone is explicitly
  314. // specified. Other "expected" result parameters will be ignored.
  315. checkFind(data_source, nomatch_name, NULL, rrclass, rrclass,
  316. rrtype, rrttl, DataSrc::NO_SUCH_ZONE, authors_ns_data);
  317. checkFind(data_source, nomatch_name, &version_name, rrclass, rrclass,
  318. rrtype, rrttl, DataSrc::NO_SUCH_ZONE, authors_ns_data);
  319. checkFind(data_source, nomatch_name, &authors_name, rrclass, rrclass,
  320. rrtype, rrttl, DataSrc::NO_SUCH_ZONE, authors_ns_data);
  321. }
  322. // If a zone name is given but doesn't match any of the static zones,
  323. // the result should be "no such zone"
  324. TEST_F(StaticDataSourceTest, findRRsetZoneMismatch) {
  325. const Name& short_zonename(Name("bind"));
  326. checkFind(data_source, version_name, &short_zonename, rrclass, rrclass,
  327. rrtype, rrttl, DataSrc::NO_SUCH_ZONE, authors_ns_data);
  328. checkFind(data_source, authors_name, &short_zonename, rrclass, rrclass,
  329. rrtype, rrttl, DataSrc::NO_SUCH_ZONE, authors_ns_data);
  330. }
  331. // Zone matches, but name doesn't exist in the zone
  332. TEST_F(StaticDataSourceTest, findRRsetNoName) {
  333. checkFind(data_source, Name("foo").concatenate(version_name), NULL, rrclass,
  334. rrclass, rrtype, rrttl, DataSrc::NAME_NOT_FOUND, authors_ns_data);
  335. checkFind(data_source, Name("foo").concatenate(version_name), &version_name,
  336. rrclass, rrclass, rrtype, rrttl, DataSrc::NAME_NOT_FOUND,
  337. authors_ns_data);
  338. checkFind(data_source, Name("foo").concatenate(authors_name), NULL, rrclass,
  339. rrclass, rrtype, rrttl, DataSrc::NAME_NOT_FOUND, authors_ns_data);
  340. checkFind(data_source, Name("foo").concatenate(authors_name), &authors_name,
  341. rrclass, rrclass, rrtype, rrttl, DataSrc::NAME_NOT_FOUND,
  342. authors_ns_data);
  343. }
  344. // Zone matches and qname exists, but type doesn't exist for the name.
  345. TEST_F(StaticDataSourceTest, findRRsetNoType) {
  346. const RRType& nomatch_type = RRType::A();
  347. checkFind(data_source, version_name, NULL, rrclass,
  348. rrclass, nomatch_type, rrttl, DataSrc::TYPE_NOT_FOUND,
  349. authors_ns_data);
  350. checkFind(data_source, version_name, &version_name, rrclass,
  351. rrclass, nomatch_type, rrttl, DataSrc::TYPE_NOT_FOUND,
  352. authors_ns_data);
  353. checkFind(data_source, authors_name, NULL, rrclass,
  354. rrclass, nomatch_type, rrttl, DataSrc::TYPE_NOT_FOUND,
  355. authors_ns_data);
  356. checkFind(data_source, authors_name, &authors_name, rrclass,
  357. rrclass, nomatch_type, rrttl, DataSrc::TYPE_NOT_FOUND,
  358. authors_ns_data);
  359. }
  360. // Simple tests for "unsupported" tests.
  361. TEST_F(StaticDataSourceTest, notImplemented) {
  362. Name target_name(version_name);
  363. EXPECT_EQ(DataSrc::NOT_IMPLEMENTED,
  364. data_source.findPreviousName(version_name, target_name,
  365. &version_name));
  366. string target_hash;
  367. EXPECT_EQ(DataSrc::NOT_IMPLEMENTED,
  368. data_source.findCoveringNSEC3(version_name, target_hash,
  369. result_sets));
  370. }
  371. }