zone_entry_unittest.cc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  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. // $Id$
  15. #include <gtest/gtest.h>
  16. #include <boost/shared_ptr.hpp>
  17. #include <dns/rrclass.h>
  18. #include <dns/rdataclass.h>
  19. #include "../asiolink.h"
  20. #include "../zone_entry.h"
  21. #include "../nameserver_entry.h"
  22. #include "../address_request_callback.h"
  23. #include "../nsas_entry_compare.h"
  24. #include "../hash_deleter.h"
  25. #include "nsas_test.h"
  26. using namespace isc::nsas;
  27. using namespace asiolink;
  28. using namespace std;
  29. using namespace boost;
  30. using namespace isc::dns;
  31. namespace {
  32. /// \brief Inherited version with access into its internals for tests
  33. class InheritedZoneEntry : public ZoneEntry {
  34. public:
  35. InheritedZoneEntry(shared_ptr<ResolverInterface> resolver,
  36. const std::string& name, const RRClass& class_code,
  37. shared_ptr<HashTable<NameserverEntry> > nameserver_table,
  38. shared_ptr<LruList<NameserverEntry> > nameserver_lru) :
  39. ZoneEntry(resolver, name, class_code, nameserver_table,
  40. nameserver_lru)
  41. { }
  42. NameserverVector& nameservers() { return nameservers_; }
  43. };
  44. /// \brief Test Fixture Class
  45. class ZoneEntryTest : public TestWithRdata {
  46. protected:
  47. /// \brief Constructor
  48. ZoneEntryTest() :
  49. nameserver_table_(new HashTable<NameserverEntry>(
  50. new NsasEntryCompare<NameserverEntry>)),
  51. nameserver_lru_(new LruList<NameserverEntry>(
  52. (3 * nameserver_table_->tableSize()),
  53. new HashDeleter<NameserverEntry>(*nameserver_table_))),
  54. resolver_(new TestResolver),
  55. callback_(new Callback)
  56. { }
  57. /// \brief Tables of nameservers to pass into zone entry constructor
  58. shared_ptr<HashTable<NameserverEntry> > nameserver_table_;
  59. shared_ptr<LruList<NameserverEntry> > nameserver_lru_;
  60. /// \brief The resolver
  61. shared_ptr<TestResolver> resolver_;
  62. struct Callback : public AddressRequestCallback {
  63. Callback() : unreachable_count_(0) {}
  64. size_t unreachable_count_;
  65. vector<IOAddress> successes_;
  66. virtual void unreachable() { unreachable_count_ ++; }
  67. virtual void success(const IOAddress& address) {
  68. successes_.push_back(address);
  69. }
  70. };
  71. shared_ptr<Callback> callback_;
  72. /**
  73. * \short Function returning a new zone.
  74. *
  75. * Convenience funcion, just creating a new zone, to shorten the code.
  76. */
  77. shared_ptr<InheritedZoneEntry> getZone() {
  78. return (shared_ptr<InheritedZoneEntry>(new InheritedZoneEntry(
  79. resolver_, EXAMPLE_CO_UK, RRClass::IN(), nameserver_table_,
  80. nameserver_lru_)));
  81. }
  82. };
  83. /// Tests of the default constructor
  84. TEST_F(ZoneEntryTest, DefaultConstructor) {
  85. // Default constructor should not create any RRsets
  86. InheritedZoneEntry alpha(resolver_, EXAMPLE_CO_UK,
  87. RRClass::IN(), nameserver_table_, nameserver_lru_);
  88. EXPECT_EQ(EXAMPLE_CO_UK, alpha.getName());
  89. EXPECT_EQ(RRClass::IN(), alpha.getClass());
  90. EXPECT_TRUE(alpha.nameservers().empty());
  91. }
  92. // It should answer negatively right away if there are no nameservers
  93. TEST_F(ZoneEntryTest, CallbackNoNS) {
  94. shared_ptr<InheritedZoneEntry> zone(getZone());
  95. EXPECT_EQ(Fetchable::NOT_ASKED, zone->getState());
  96. // It should accept the callback
  97. zone->addCallback(callback_, ANY_OK);
  98. EXPECT_EQ(Fetchable::IN_PROGRESS, zone->getState());
  99. // Ask for the nameservers
  100. EXPECT_NO_THROW(resolver_->provideNS(0, rr_empty_));
  101. // And tell imediatelly that it is unreachable (when it has no nameservers)
  102. EXPECT_TRUE(callback_->successes_.empty());
  103. EXPECT_EQ(1, callback_->unreachable_count_);
  104. }
  105. // Check it accepts the first callback with 0 TTL
  106. TEST_F(ZoneEntryTest, CallbackZeroTTL) {
  107. // Make it zero TTL, so it expires right away
  108. rr_single_->setTTL(RRTTL(0));
  109. shared_ptr<InheritedZoneEntry> zone(getZone());
  110. EXPECT_EQ(Fetchable::NOT_ASKED, zone->getState());
  111. // It should accept the callback
  112. zone->addCallback(callback_, ANY_OK);
  113. EXPECT_EQ(Fetchable::IN_PROGRESS, zone->getState());
  114. EXPECT_NO_THROW(resolver_->provideNS(0, rr_single_));
  115. // It should not be answered yet, it should ask for the IP addresses
  116. EXPECT_TRUE(callback_->successes_.empty());
  117. EXPECT_EQ(0, callback_->unreachable_count_);
  118. resolver_->asksIPs(ns_name_, 1, 2);
  119. // It should request the NSs again, as TTL is 0
  120. zone->addCallback(callback_, ANY_OK);
  121. EXPECT_EQ(4, resolver_->requests.size());
  122. }
  123. // Check it answers callbacks when we give it addresses
  124. TEST_F(ZoneEntryTest, CallbacksAnswered) {
  125. shared_ptr<InheritedZoneEntry> zone(getZone());
  126. // It should be in NOT_ASKED state
  127. EXPECT_EQ(Fetchable::NOT_ASKED, zone->getState());
  128. // It should accept the callback
  129. zone->addCallback(callback_, ANY_OK);
  130. EXPECT_EQ(Fetchable::IN_PROGRESS, zone->getState());
  131. EXPECT_NO_THROW(resolver_->provideNS(0, rr_single_));
  132. // It should not be answered yet, it should ask for the IP addresses
  133. EXPECT_TRUE(callback_->successes_.empty());
  134. EXPECT_EQ(0, callback_->unreachable_count_);
  135. resolver_->asksIPs(ns_name_, 1, 2);
  136. // We should be READY, as it marks we have nameservers
  137. // (not that they are ready)
  138. EXPECT_EQ(Fetchable::READY, zone->getState());
  139. // Give two more callbacks, with different address families
  140. zone->addCallback(callback_, V4_ONLY);
  141. zone->addCallback(callback_, V6_ONLY);
  142. // Nothing more is asked
  143. EXPECT_EQ(3, resolver_->requests.size());
  144. EXPECT_NO_THROW(resolver_->answer(1, ns_name_, RRType::A(),
  145. rdata::in::A("192.0.2.1")));
  146. // Two are answered (ANY and V4)
  147. ASSERT_EQ(2, callback_->successes_.size());
  148. EXPECT_TRUE(IOAddress("192.0.2.1").equal(callback_->successes_[0]));
  149. EXPECT_TRUE(IOAddress("192.0.2.1").equal(callback_->successes_[1]));
  150. // None are rejected
  151. EXPECT_EQ(0, callback_->unreachable_count_);
  152. EXPECT_NO_THROW(resolver_->answer(2, ns_name_, RRType::AAAA(),
  153. rdata::in::AAAA("2001:db8::1")));
  154. // This should answer the third callback
  155. EXPECT_EQ(0, callback_->unreachable_count_);
  156. ASSERT_EQ(3, callback_->successes_.size());
  157. EXPECT_TRUE(IOAddress("2001:db8::1").equal(callback_->successes_[2]));
  158. // It should think it is ready
  159. EXPECT_EQ(Fetchable::READY, zone->getState());
  160. // When we ask something more, it should be answered right away
  161. zone->addCallback(callback_, V4_ONLY);
  162. EXPECT_EQ(3, resolver_->requests.size());
  163. ASSERT_EQ(4, callback_->successes_.size());
  164. EXPECT_TRUE(IOAddress("192.0.2.1").equal(callback_->successes_[3]));
  165. EXPECT_EQ(0, callback_->unreachable_count_);
  166. }
  167. // Pretend the server can be reached only by IPv4
  168. TEST_F(ZoneEntryTest, CallbacksAOnly) {
  169. shared_ptr<InheritedZoneEntry> zone(getZone());
  170. // It should be in NOT_ASKED state
  171. EXPECT_EQ(Fetchable::NOT_ASKED, zone->getState());
  172. // It should accept the callback
  173. zone->addCallback(callback_, ANY_OK);
  174. EXPECT_EQ(Fetchable::IN_PROGRESS, zone->getState());
  175. EXPECT_NO_THROW(resolver_->provideNS(0, rr_single_));
  176. // It should not be answered yet, it should ask for the IP addresses
  177. EXPECT_TRUE(callback_->successes_.empty());
  178. EXPECT_EQ(0, callback_->unreachable_count_);
  179. resolver_->asksIPs(ns_name_, 1, 2);
  180. EXPECT_EQ(Fetchable::READY, zone->getState());
  181. // Give two more callbacks, with different address families
  182. zone->addCallback(callback_, V4_ONLY);
  183. zone->addCallback(callback_, V6_ONLY);
  184. ASSERT_GE(resolver_->requests.size(), 3);
  185. resolver_->requests[2].second->failure();
  186. // One should be rejected, but two still stay, they have chance
  187. EXPECT_EQ(0, callback_->successes_.size());
  188. EXPECT_EQ(1, callback_->unreachable_count_);
  189. // Answer the A one and see it answers what can be answered
  190. EXPECT_NO_THROW(resolver_->answer(1, ns_name_, RRType::A(),
  191. rdata::in::A("192.0.2.1")));
  192. ASSERT_EQ(2, callback_->successes_.size());
  193. EXPECT_TRUE(IOAddress("192.0.2.1").equal(callback_->successes_[0]));
  194. EXPECT_TRUE(IOAddress("192.0.2.1").equal(callback_->successes_[1]));
  195. EXPECT_EQ(1, callback_->unreachable_count_);
  196. // Everything arriwed, so we are ready
  197. EXPECT_EQ(Fetchable::READY, zone->getState());
  198. // Try asking something more
  199. zone->addCallback(callback_, V4_ONLY);
  200. EXPECT_EQ(3, resolver_->requests.size());
  201. ASSERT_EQ(3, callback_->successes_.size());
  202. EXPECT_TRUE(IOAddress("192.0.2.1").equal(callback_->successes_[2]));
  203. EXPECT_EQ(1, callback_->unreachable_count_);
  204. zone->addCallback(callback_, V6_ONLY);
  205. EXPECT_EQ(3, resolver_->requests.size());
  206. EXPECT_EQ(3, callback_->successes_.size());
  207. EXPECT_EQ(2, callback_->unreachable_count_);
  208. }
  209. // See it tries hard enough to get address and tries both nameservers
  210. TEST_F(ZoneEntryTest, CallbackTwoNS) {
  211. shared_ptr<InheritedZoneEntry> zone(getZone());
  212. // It should be in NOT_ASKED state
  213. EXPECT_EQ(Fetchable::NOT_ASKED, zone->getState());
  214. // It should accept the callback
  215. zone->addCallback(callback_, V4_ONLY);
  216. EXPECT_EQ(Fetchable::IN_PROGRESS, zone->getState());
  217. EXPECT_NO_THROW(resolver_->provideNS(0, rrns_));
  218. EXPECT_EQ(Fetchable::READY, zone->getState());
  219. // It asks a question (we do not know which nameserver)
  220. shared_ptr<Name> name;
  221. ASSERT_NO_THROW(name.reset(new Name((*resolver_)[1]->getName())));
  222. ASSERT_TRUE(resolver_->asksIPs(*name, 1, 2));
  223. resolver_->requests[1].second->failure();
  224. // Nothing should be answered or failed yet
  225. EXPECT_EQ(0, callback_->unreachable_count_);
  226. EXPECT_EQ(0, callback_->successes_.size());
  227. ASSERT_TRUE(resolver_->asksIPs((*resolver_)[3]->getName(), 3, 4));
  228. // Fail the second one
  229. resolver_->requests[3].second->failure();
  230. // The callback should be failed now, as there is no chance of getting
  231. // v4 address
  232. EXPECT_EQ(1, callback_->unreachable_count_);
  233. EXPECT_EQ(0, callback_->successes_.size());
  234. // And question for v6 or any should still wait while v4 should be failed
  235. // right away
  236. zone->addCallback(callback_, V6_ONLY);
  237. EXPECT_EQ(1, callback_->unreachable_count_);
  238. EXPECT_EQ(0, callback_->successes_.size());
  239. zone->addCallback(callback_, ANY_OK);
  240. EXPECT_EQ(1, callback_->unreachable_count_);
  241. EXPECT_EQ(0, callback_->successes_.size());
  242. zone->addCallback(callback_, V4_ONLY);
  243. EXPECT_EQ(2, callback_->unreachable_count_);
  244. EXPECT_EQ(0, callback_->successes_.size());
  245. // Answer the IPv6 one
  246. EXPECT_NO_THROW(resolver_->answer(2, (*resolver_)[2]->getName(),
  247. RRType::AAAA(), rdata::in::AAAA("2001:db8::1")));
  248. // Ready, as we have at last some address
  249. EXPECT_EQ(Fetchable::READY, zone->getState());
  250. // The other callbacks should be answered now
  251. EXPECT_EQ(2, callback_->unreachable_count_);
  252. ASSERT_EQ(2, callback_->successes_.size());
  253. EXPECT_TRUE(IOAddress("2001:db8::1").equal(callback_->successes_[0]));
  254. EXPECT_TRUE(IOAddress("2001:db8::1").equal(callback_->successes_[1]));
  255. }
  256. // Test if it works when the response comes right away from the resolve call
  257. TEST_F(ZoneEntryTest, DirectAnswer) {
  258. shared_ptr<InheritedZoneEntry> zone(getZone());
  259. EXPECT_EQ(Fetchable::NOT_ASKED, zone->getState());
  260. // One unsuccessfull attempt, nameservers fail
  261. resolver_->addPresetAnswer(Question(Name(EXAMPLE_CO_UK), RRClass::IN(),
  262. RRType::NS()), shared_ptr<AbstractRRset>());
  263. zone->addCallback(callback_, ANY_OK);
  264. EXPECT_EQ(0, callback_->successes_.size());
  265. EXPECT_EQ(1, callback_->unreachable_count_);
  266. EXPECT_EQ(0, resolver_->requests.size());
  267. EXPECT_EQ(Fetchable::UNREACHABLE, zone->getState());
  268. // Successfull attempt now
  269. zone = getZone();
  270. // First, fill the answers to all the questions it should ask
  271. EXPECT_EQ(Fetchable::NOT_ASKED, zone->getState());
  272. resolver_->addPresetAnswer(Question(Name(EXAMPLE_CO_UK), RRClass::IN(),
  273. RRType::NS()), rr_single_);
  274. Name ns_name("ns.example.net");
  275. rrv4_->setName(ns_name);
  276. resolver_->addPresetAnswer(Question(ns_name, RRClass::IN(), RRType::A()),
  277. rrv4_);
  278. rrv6_->setName(ns_name);
  279. resolver_->addPresetAnswer(Question(ns_name, RRClass::IN(),
  280. RRType::AAAA()), rrv6_);
  281. // Reset the results
  282. callback_->unreachable_count_ = 0;
  283. // Ask for the IP address
  284. zone->addCallback(callback_, ANY_OK);
  285. // It should be answered right away, positively
  286. EXPECT_EQ(1, callback_->successes_.size());
  287. EXPECT_EQ(0, callback_->unreachable_count_);
  288. EXPECT_EQ(0, resolver_->requests.size());
  289. EXPECT_EQ(Fetchable::READY, zone->getState());
  290. // Reset the results
  291. callback_->successes_.clear();
  292. // Now, pretend we do not have IP addresses
  293. resolver_->addPresetAnswer(Question(ns_name, RRClass::IN(), RRType::A()),
  294. shared_ptr<AbstractRRset>());
  295. resolver_->addPresetAnswer(Question(ns_name, RRClass::IN(),
  296. RRType::AAAA()), shared_ptr<AbstractRRset>());
  297. // Get another zone and ask it again. It should fail.
  298. // Clean the table first, though, so it does not find the old nameserver
  299. nameserver_table_->remove(HashKey(ns_name.toText(), RRClass::IN()));
  300. zone = getZone();
  301. EXPECT_EQ(Fetchable::NOT_ASKED, zone->getState());
  302. zone->addCallback(callback_, ANY_OK);
  303. EXPECT_EQ(0, callback_->successes_.size());
  304. EXPECT_EQ(1, callback_->unreachable_count_);
  305. EXPECT_EQ(0, resolver_->requests.size());
  306. // It should be ready, but have no IP addresses on the nameservers
  307. EXPECT_EQ(Fetchable::READY, zone->getState());
  308. }
  309. /*
  310. * TODO: There should be more tests for sure. Some ideas:
  311. * - What happens when some things start timing out.
  312. * - What happens if they are different after the timeout.
  313. * - What happens if they return to previous state (changes and changes back).
  314. * - Combine this direct answering.
  315. * - Look what happens when the nameservers are already in some different
  316. * states and not just newly created.
  317. */
  318. } // namespace