zone_entry_unittest.cc 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619
  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. /**
  63. * \short A callback we use into the zone.
  64. *
  65. * It counts failures and stores successufll results.
  66. */
  67. struct Callback : public AddressRequestCallback {
  68. Callback() : unreachable_count_(0) {}
  69. size_t unreachable_count_;
  70. vector<IOAddress> successes_;
  71. virtual void unreachable() { unreachable_count_ ++; }
  72. virtual void success(const IOAddress& address) {
  73. successes_.push_back(address);
  74. }
  75. };
  76. shared_ptr<Callback> callback_;
  77. // Empty callback to pass to nameserver entry, to do injection of them
  78. struct NseCallback : public NameserverEntry::Callback {
  79. virtual void operator()(shared_ptr<NameserverEntry>) { }
  80. };
  81. shared_ptr<NseCallback> nseCallback() {
  82. return (shared_ptr<NseCallback>(new NseCallback));
  83. }
  84. /**
  85. * \short Function returning a new zone.
  86. *
  87. * Convenience funcion, just creating a new zone, to shorten the code.
  88. */
  89. shared_ptr<InheritedZoneEntry> getZone() {
  90. return (shared_ptr<InheritedZoneEntry>(new InheritedZoneEntry(
  91. resolver_, EXAMPLE_CO_UK, RRClass::IN(), nameserver_table_,
  92. nameserver_lru_)));
  93. }
  94. /**
  95. * \short Creates and injects a NameserverEntry
  96. *
  97. * This is used by few tests checking it works when the nameserver
  98. * hash table already contains the NameserverEntry. This function
  99. * creates one and puts it into the hash table.
  100. */
  101. shared_ptr<NameserverEntry> injectEntry() {
  102. shared_ptr<NameserverEntry> nse(new NameserverEntry(ns_name_.toText(),
  103. RRClass::IN()));
  104. nameserver_table_->add(nse, HashKey(ns_name_.toText(), RRClass::IN()));
  105. EXPECT_EQ(Fetchable::NOT_ASKED, nse->getState());
  106. return (nse);
  107. }
  108. /**
  109. * \short Common part of few tests.
  110. *
  111. * All the tests NameserverEntryReady, NameserverEntryNotAsked,
  112. * NameserverEntryInProgress, NameserverEntryExpired,
  113. * NameserverEntryUnreachable check that it does not break
  114. * when the nameserver hash table already contains the nameserver
  115. * in one of the Fetchable::State.
  116. *
  117. * All the tests prepare the NameserverEntry and then call this
  118. * to see if the zone really works. This asks and checks if it
  119. * asks for the IP addresses or not and if it succeeds or fails.
  120. *
  121. * \param answer Should it ask for IP addresses of the nameserver?
  122. * If not, it expects it already asked during the preparation
  123. * (therefore the request count in resolver is 2).
  124. * \param success_count How many callbacks to the zone should
  125. * succeed.
  126. * \param failure_count How many callbacks to the zone should
  127. * fail.
  128. */
  129. void checkInjected(bool answer, size_t success_count = 1,
  130. size_t failure_count = 0)
  131. {
  132. // Create the zone and check it acts correctly
  133. shared_ptr<InheritedZoneEntry> zone(getZone());
  134. resolver_->addPresetAnswer(Question(Name(EXAMPLE_CO_UK), RRClass::IN(),
  135. RRType::NS()), rr_single_);
  136. zone->addCallback(callback_, ANY_OK);
  137. EXPECT_EQ(2, resolver_->requests.size());
  138. EXPECT_TRUE(resolver_->asksIPs(ns_name_, 0, 1));
  139. if (answer) {
  140. EXPECT_NO_THROW(resolver_->answer(0, ns_name_, RRType::A(),
  141. rdata::in::A("192.0.2.1")));
  142. EXPECT_NO_THROW(resolver_->answer(1, ns_name_, RRType::AAAA(),
  143. rdata::in::AAAA("2001:db8::1")));
  144. }
  145. // Check the answers
  146. EXPECT_EQ(Fetchable::READY, zone->getState());
  147. EXPECT_EQ(failure_count, callback_->unreachable_count_);
  148. EXPECT_EQ(success_count, callback_->successes_.size());
  149. for (size_t i = 0; i < callback_->successes_.size(); ++ i) {
  150. EXPECT_TRUE(IOAddress("192.0.2.1").equal(
  151. callback_->successes_[i]) || IOAddress("2001:db8::1").equal(
  152. callback_->successes_[i]));
  153. }
  154. }
  155. };
  156. /// Tests of the default constructor
  157. TEST_F(ZoneEntryTest, DefaultConstructor) {
  158. // Default constructor should not create any RRsets
  159. InheritedZoneEntry alpha(resolver_, EXAMPLE_CO_UK,
  160. RRClass::IN(), nameserver_table_, nameserver_lru_);
  161. EXPECT_EQ(EXAMPLE_CO_UK, alpha.getName());
  162. EXPECT_EQ(RRClass::IN(), alpha.getClass());
  163. EXPECT_TRUE(alpha.nameservers().empty());
  164. }
  165. /**
  166. * \short Test with no nameservers.
  167. *
  168. * When we create a zone that does not have any nameservers,
  169. * it should return failures right away (eg. no queries to nameservers
  170. * should be generated anywhere and the failure should be provided).
  171. */
  172. TEST_F(ZoneEntryTest, CallbackNoNS) {
  173. shared_ptr<InheritedZoneEntry> zone(getZone());
  174. EXPECT_EQ(Fetchable::NOT_ASKED, zone->getState());
  175. // feed it with a callback
  176. zone->addCallback(callback_, ANY_OK);
  177. EXPECT_EQ(Fetchable::IN_PROGRESS, zone->getState());
  178. // Give it the (empty) nameserver list
  179. EXPECT_NO_THROW(resolver_->provideNS(0, rr_empty_));
  180. // It should tell us it is unreachable.
  181. EXPECT_TRUE(callback_->successes_.empty());
  182. EXPECT_EQ(1, callback_->unreachable_count_);
  183. }
  184. /**
  185. * \short Test how the zone behaves when the list of nameserves change.
  186. *
  187. * We use TTL of 0, so it asks every time for new list of nameservers.
  188. * This allows us to pass a different list each time.
  189. *
  190. * So, this implicitly tests that it behaves correctly with 0 TTL as well,
  191. * it means that it answers even with 0 TTL and that it answers only
  192. * one query (or, all queries queued at that time).
  193. *
  194. * We change the list twice, to see it can ask for another nameserver and
  195. * then to see if it can return to the previous (already cached) nameserver.
  196. */
  197. TEST_F(ZoneEntryTest, ChangedNS) {
  198. // Make it zero TTL, so it expires right away
  199. rr_single_->setTTL(RRTTL(0));
  200. shared_ptr<InheritedZoneEntry> zone(getZone());
  201. EXPECT_EQ(Fetchable::NOT_ASKED, zone->getState());
  202. // Feed it with callback
  203. zone->addCallback(callback_, ANY_OK);
  204. EXPECT_EQ(Fetchable::IN_PROGRESS, zone->getState());
  205. EXPECT_NO_THROW(resolver_->provideNS(0, rr_single_));
  206. // It should not be answered yet, it should ask for the IP addresses
  207. // (trough the NameserverEntry there)
  208. EXPECT_TRUE(callback_->successes_.empty());
  209. EXPECT_EQ(0, callback_->unreachable_count_);
  210. EXPECT_TRUE(resolver_->asksIPs(ns_name_, 1, 2));
  211. EXPECT_NO_THROW(resolver_->answer(1, ns_name_, RRType::A(),
  212. rdata::in::A("192.0.2.1")));
  213. ASSERT_EQ(1, callback_->successes_.size());
  214. EXPECT_TRUE(IOAddress("192.0.2.1").equal(callback_->successes_[0]));
  215. EXPECT_NO_THROW(resolver_->answer(2, ns_name_, RRType::AAAA(),
  216. rdata::in::AAAA("2001:db8::1")));
  217. EXPECT_EQ(1, callback_->successes_.size());
  218. // It should request the NSs again, as TTL is 0
  219. zone->addCallback(callback_, ANY_OK);
  220. EXPECT_EQ(4, resolver_->requests.size());
  221. EXPECT_EQ(Fetchable::IN_PROGRESS, zone->getState());
  222. Name different_name("ns.example.com");
  223. // Create a different answer
  224. RRsetPtr different_ns(new RRset(Name(EXAMPLE_CO_UK), RRClass::IN(),
  225. RRType::NS(), RRTTL(0)));
  226. different_ns->addRdata(rdata::generic::NS(different_name));
  227. EXPECT_NO_THROW(resolver_->provideNS(3, different_ns));
  228. // It should become ready and ask for the new nameserver addresses
  229. EXPECT_EQ(Fetchable::READY, zone->getState());
  230. // Answer one of the IP addresses, we should get an address now
  231. EXPECT_TRUE(resolver_->asksIPs(different_name, 4, 5));
  232. EXPECT_NO_THROW(resolver_->answer(4, different_name, RRType::A(),
  233. rdata::in::A("192.0.2.2")));
  234. ASSERT_EQ(2, callback_->successes_.size());
  235. EXPECT_TRUE(IOAddress("192.0.2.2").equal(callback_->successes_[1]));
  236. // And now, switch back, as it timed out again
  237. zone->addCallback(callback_, ANY_OK);
  238. EXPECT_EQ(7, resolver_->requests.size());
  239. EXPECT_EQ(Fetchable::IN_PROGRESS, zone->getState());
  240. // When we answer with the original, it should still be cached and
  241. // we should get the answer
  242. EXPECT_NO_THROW(resolver_->provideNS(0, rr_single_));
  243. EXPECT_EQ(7, resolver_->requests.size());
  244. EXPECT_EQ(Fetchable::READY, zone->getState());
  245. ASSERT_EQ(3, callback_->successes_.size());
  246. EXPECT_TRUE(IOAddress("192.0.2.1").equal(callback_->successes_[0]));
  247. }
  248. /**
  249. * \short Check it works when everything is answered.
  250. *
  251. * This test emulates a situation when all queries for NS rrsets and
  252. * IP addresses (of the NameserverEntry objects inside) are answered
  253. * positively. All the callbacks should be called and answer to them
  254. * provided.
  255. */
  256. TEST_F(ZoneEntryTest, CallbacksAnswered) {
  257. shared_ptr<InheritedZoneEntry> zone(getZone());
  258. EXPECT_EQ(Fetchable::NOT_ASKED, zone->getState());
  259. // Feed it with a callback
  260. zone->addCallback(callback_, ANY_OK);
  261. EXPECT_EQ(Fetchable::IN_PROGRESS, zone->getState());
  262. EXPECT_NO_THROW(resolver_->provideNS(0, rr_single_));
  263. // It should not be answered yet, its NameserverEntry should ask for the
  264. // IP addresses
  265. EXPECT_TRUE(callback_->successes_.empty());
  266. EXPECT_EQ(0, callback_->unreachable_count_);
  267. EXPECT_TRUE(resolver_->asksIPs(ns_name_, 1, 2));
  268. // We should be READY, as it marks we have nameservers
  269. // (not that they are ready)
  270. EXPECT_EQ(Fetchable::READY, zone->getState());
  271. // Give two more callbacks, with different address families
  272. zone->addCallback(callback_, V4_ONLY);
  273. zone->addCallback(callback_, V6_ONLY);
  274. // Nothing more is asked
  275. EXPECT_EQ(3, resolver_->requests.size());
  276. EXPECT_NO_THROW(resolver_->answer(1, ns_name_, RRType::A(),
  277. rdata::in::A("192.0.2.1")));
  278. // Two are answered (ANY and V4)
  279. ASSERT_EQ(2, callback_->successes_.size());
  280. EXPECT_TRUE(IOAddress("192.0.2.1").equal(callback_->successes_[0]));
  281. EXPECT_TRUE(IOAddress("192.0.2.1").equal(callback_->successes_[1]));
  282. // None are rejected
  283. EXPECT_EQ(0, callback_->unreachable_count_);
  284. // Answer the IPv6 one as well
  285. EXPECT_NO_THROW(resolver_->answer(2, ns_name_, RRType::AAAA(),
  286. rdata::in::AAAA("2001:db8::1")));
  287. // This should answer the third callback
  288. EXPECT_EQ(0, callback_->unreachable_count_);
  289. ASSERT_EQ(3, callback_->successes_.size());
  290. EXPECT_TRUE(IOAddress("2001:db8::1").equal(callback_->successes_[2]));
  291. // It should think it is ready
  292. EXPECT_EQ(Fetchable::READY, zone->getState());
  293. // When we ask something more, it should be answered right away
  294. zone->addCallback(callback_, V4_ONLY);
  295. EXPECT_EQ(3, resolver_->requests.size());
  296. ASSERT_EQ(4, callback_->successes_.size());
  297. EXPECT_TRUE(IOAddress("192.0.2.1").equal(callback_->successes_[3]));
  298. EXPECT_EQ(0, callback_->unreachable_count_);
  299. }
  300. /**
  301. * \short Test zone reachable only on IPv4.
  302. *
  303. * This test simulates a zone with its nameservers reachable only
  304. * over IPv4. It means we answer the NS query, the A query, but
  305. * we generate a failure for AAAA.
  306. *
  307. * The callbacks asking for any address and IPv4 address should be
  308. * called successfully, while the ones asking for IPv6 addresses should
  309. * fail.
  310. */
  311. TEST_F(ZoneEntryTest, CallbacksAOnly) {
  312. shared_ptr<InheritedZoneEntry> zone(getZone());
  313. EXPECT_EQ(Fetchable::NOT_ASKED, zone->getState());
  314. zone->addCallback(callback_, ANY_OK);
  315. EXPECT_EQ(Fetchable::IN_PROGRESS, zone->getState());
  316. EXPECT_NO_THROW(resolver_->provideNS(0, rr_single_));
  317. // It should not be answered yet, it should ask for the IP addresses
  318. EXPECT_TRUE(callback_->successes_.empty());
  319. EXPECT_EQ(0, callback_->unreachable_count_);
  320. EXPECT_TRUE(resolver_->asksIPs(ns_name_, 1, 2));
  321. EXPECT_EQ(Fetchable::READY, zone->getState());
  322. // Give two more callbacks, with different address families
  323. zone->addCallback(callback_, V4_ONLY);
  324. zone->addCallback(callback_, V6_ONLY);
  325. ASSERT_GE(resolver_->requests.size(), 3);
  326. // We tell its NameserverEntry we can't get IPv6 address
  327. resolver_->requests[2].second->failure();
  328. // One should be rejected (V6_ONLY one), but two still stay
  329. EXPECT_EQ(0, callback_->successes_.size());
  330. EXPECT_EQ(1, callback_->unreachable_count_);
  331. // Answer the A one and see it answers what can be answered
  332. EXPECT_NO_THROW(resolver_->answer(1, ns_name_, RRType::A(),
  333. rdata::in::A("192.0.2.1")));
  334. ASSERT_EQ(2, callback_->successes_.size());
  335. EXPECT_TRUE(IOAddress("192.0.2.1").equal(callback_->successes_[0]));
  336. EXPECT_TRUE(IOAddress("192.0.2.1").equal(callback_->successes_[1]));
  337. EXPECT_EQ(1, callback_->unreachable_count_);
  338. // Everything arriwed, so we are ready
  339. EXPECT_EQ(Fetchable::READY, zone->getState());
  340. // Try asking something more and see it asks no more
  341. zone->addCallback(callback_, V4_ONLY);
  342. EXPECT_EQ(3, resolver_->requests.size());
  343. ASSERT_EQ(3, callback_->successes_.size());
  344. EXPECT_TRUE(IOAddress("192.0.2.1").equal(callback_->successes_[2]));
  345. EXPECT_EQ(1, callback_->unreachable_count_);
  346. zone->addCallback(callback_, V6_ONLY);
  347. EXPECT_EQ(3, resolver_->requests.size());
  348. EXPECT_EQ(3, callback_->successes_.size());
  349. EXPECT_EQ(2, callback_->unreachable_count_);
  350. }
  351. /**
  352. * \short Test with unreachable and v6-reachable nameserver.
  353. *
  354. * In this test we have a zone with two nameservers. The first one of them
  355. * is unreachable, it will not have any addresses. We check that the ZoneEntry
  356. * is patient and asks and waits for the second one and then returns the
  357. * (successful) answers to us.
  358. */
  359. TEST_F(ZoneEntryTest, CallbackTwoNS) {
  360. shared_ptr<InheritedZoneEntry> zone(getZone());
  361. EXPECT_EQ(Fetchable::NOT_ASKED, zone->getState());
  362. zone->addCallback(callback_, V4_ONLY);
  363. EXPECT_EQ(Fetchable::IN_PROGRESS, zone->getState());
  364. EXPECT_NO_THROW(resolver_->provideNS(0, rrns_));
  365. EXPECT_EQ(Fetchable::READY, zone->getState());
  366. // It asks a question (we do not know which nameserver)
  367. shared_ptr<Name> name;
  368. ASSERT_NO_THROW(name.reset(new Name((*resolver_)[1]->getName())));
  369. ASSERT_TRUE(resolver_->asksIPs(*name, 1, 2));
  370. resolver_->requests[1].second->failure();
  371. // Nothing should be answered or failed yet, there's second one
  372. EXPECT_EQ(0, callback_->unreachable_count_);
  373. EXPECT_EQ(0, callback_->successes_.size());
  374. ASSERT_TRUE(resolver_->asksIPs((*resolver_)[3]->getName(), 3, 4));
  375. // Fail the second one
  376. resolver_->requests[3].second->failure();
  377. // The callback should be failed now, as there is no chance of getting
  378. // v4 address
  379. EXPECT_EQ(1, callback_->unreachable_count_);
  380. EXPECT_EQ(0, callback_->successes_.size());
  381. // And question for v6 or any should still wait while v4 should be failed
  382. // right away
  383. zone->addCallback(callback_, V6_ONLY);
  384. EXPECT_EQ(1, callback_->unreachable_count_);
  385. EXPECT_EQ(0, callback_->successes_.size());
  386. zone->addCallback(callback_, ANY_OK);
  387. EXPECT_EQ(1, callback_->unreachable_count_);
  388. EXPECT_EQ(0, callback_->successes_.size());
  389. zone->addCallback(callback_, V4_ONLY);
  390. EXPECT_EQ(2, callback_->unreachable_count_);
  391. EXPECT_EQ(0, callback_->successes_.size());
  392. // Answer the IPv6 one
  393. EXPECT_NO_THROW(resolver_->answer(2, (*resolver_)[2]->getName(),
  394. RRType::AAAA(), rdata::in::AAAA("2001:db8::1")));
  395. // Ready, as we have at last some address
  396. EXPECT_EQ(Fetchable::READY, zone->getState());
  397. // The other callbacks should be answered now
  398. EXPECT_EQ(2, callback_->unreachable_count_);
  399. ASSERT_EQ(2, callback_->successes_.size());
  400. EXPECT_TRUE(IOAddress("2001:db8::1").equal(callback_->successes_[0]));
  401. EXPECT_TRUE(IOAddress("2001:db8::1").equal(callback_->successes_[1]));
  402. }
  403. /**
  404. * \short This test checks it works with answers from cache.
  405. *
  406. * The resolver might provide the answer by calling the callback both sometime
  407. * later or directly from its resolve method, causing recursion back inside
  408. * the ZoneEntry. This test checks it works even in the second case (eg. that
  409. * the ZoneEntry is able to handle callback called directly from the
  410. * resolve). Tries checking both positive and negative answers.
  411. */
  412. TEST_F(ZoneEntryTest, DirectAnswer) {
  413. shared_ptr<InheritedZoneEntry> zone(getZone());
  414. EXPECT_EQ(Fetchable::NOT_ASKED, zone->getState());
  415. // One unsuccessfull attempt, nameservers fail
  416. resolver_->addPresetAnswer(Question(Name(EXAMPLE_CO_UK), RRClass::IN(),
  417. RRType::NS()), shared_ptr<AbstractRRset>());
  418. zone->addCallback(callback_, ANY_OK);
  419. EXPECT_EQ(0, callback_->successes_.size());
  420. EXPECT_EQ(1, callback_->unreachable_count_);
  421. EXPECT_EQ(0, resolver_->requests.size());
  422. EXPECT_EQ(Fetchable::UNREACHABLE, zone->getState());
  423. // Successfull attempt now
  424. zone = getZone();
  425. // First, fill the answers to all the questions it should ask
  426. EXPECT_EQ(Fetchable::NOT_ASKED, zone->getState());
  427. resolver_->addPresetAnswer(Question(Name(EXAMPLE_CO_UK), RRClass::IN(),
  428. RRType::NS()), rr_single_);
  429. Name ns_name("ns.example.net");
  430. rrv4_->setName(ns_name);
  431. resolver_->addPresetAnswer(Question(ns_name, RRClass::IN(), RRType::A()),
  432. rrv4_);
  433. rrv6_->setName(ns_name);
  434. resolver_->addPresetAnswer(Question(ns_name, RRClass::IN(),
  435. RRType::AAAA()), rrv6_);
  436. // Reset the results
  437. callback_->unreachable_count_ = 0;
  438. // Ask for the IP address
  439. zone->addCallback(callback_, ANY_OK);
  440. // It should be answered right away, positively
  441. EXPECT_EQ(1, callback_->successes_.size());
  442. EXPECT_EQ(0, callback_->unreachable_count_);
  443. EXPECT_EQ(0, resolver_->requests.size());
  444. EXPECT_EQ(Fetchable::READY, zone->getState());
  445. // Reset the results
  446. callback_->successes_.clear();
  447. // Now, pretend we do not have IP addresses
  448. resolver_->addPresetAnswer(Question(ns_name, RRClass::IN(), RRType::A()),
  449. shared_ptr<AbstractRRset>());
  450. resolver_->addPresetAnswer(Question(ns_name, RRClass::IN(),
  451. RRType::AAAA()), shared_ptr<AbstractRRset>());
  452. // Get another zone and ask it again. It should fail.
  453. // Clean the table first, though, so it does not find the old nameserver
  454. nameserver_table_->remove(HashKey(ns_name.toText(), RRClass::IN()));
  455. zone = getZone();
  456. EXPECT_EQ(Fetchable::NOT_ASKED, zone->getState());
  457. zone->addCallback(callback_, ANY_OK);
  458. EXPECT_EQ(0, callback_->successes_.size());
  459. EXPECT_EQ(1, callback_->unreachable_count_);
  460. EXPECT_EQ(0, resolver_->requests.size());
  461. // It should be ready, but have no IP addresses on the nameservers
  462. EXPECT_EQ(Fetchable::READY, zone->getState());
  463. }
  464. /**
  465. * \short Test it works with timeouting NameserverEntries.
  466. *
  467. * In this test we have a zone with nameserver addresses at TTL 0.
  468. * So, the NameserverEntry expires each time the ZoneEntry tries to get
  469. * its addresses and must ask it again.
  470. */
  471. TEST_F(ZoneEntryTest, AddressTimeout) {
  472. shared_ptr<InheritedZoneEntry> zone(getZone());
  473. EXPECT_EQ(Fetchable::NOT_ASKED, zone->getState());
  474. zone->addCallback(callback_, ANY_OK);
  475. EXPECT_EQ(Fetchable::IN_PROGRESS, zone->getState());
  476. EXPECT_NO_THROW(resolver_->provideNS(0, rr_single_));
  477. // It should not be answered yet, it should ask for the IP addresses
  478. EXPECT_TRUE(callback_->successes_.empty());
  479. EXPECT_EQ(0, callback_->unreachable_count_);
  480. EXPECT_TRUE(resolver_->asksIPs(ns_name_, 1, 2));
  481. // We should be READY, as it marks we have nameservers
  482. // (not that they are ready)
  483. EXPECT_EQ(Fetchable::READY, zone->getState());
  484. EXPECT_NO_THROW(resolver_->answer(1, ns_name_, RRType::A(),
  485. rdata::in::A("192.0.2.1"), 0));
  486. // It answers, not rejects
  487. ASSERT_EQ(1, callback_->successes_.size());
  488. EXPECT_TRUE(IOAddress("192.0.2.1").equal(callback_->successes_[0]));
  489. EXPECT_EQ(0, callback_->unreachable_count_);
  490. // As well with IPv6
  491. EXPECT_NO_THROW(resolver_->answer(2, ns_name_, RRType::AAAA(),
  492. rdata::in::AAAA("2001:db8::1"), 0));
  493. EXPECT_EQ(1, callback_->successes_.size());
  494. EXPECT_EQ(Fetchable::READY, zone->getState());
  495. // When we ask for another one, it should ask for the addresses again
  496. zone->addCallback(callback_, ANY_OK);
  497. EXPECT_TRUE(resolver_->asksIPs(ns_name_, 3, 4));
  498. EXPECT_EQ(0, callback_->unreachable_count_);
  499. EXPECT_EQ(1, callback_->successes_.size());
  500. EXPECT_NO_THROW(resolver_->answer(3, ns_name_, RRType::A(),
  501. rdata::in::A("192.0.2.1"), 0));
  502. EXPECT_EQ(0, callback_->unreachable_count_);
  503. ASSERT_EQ(2, callback_->successes_.size());
  504. EXPECT_TRUE(IOAddress("192.0.2.1").equal(callback_->successes_[1]));
  505. }
  506. /**
  507. * \short Injection tests.
  508. *
  509. * These tests check the ZoneEntry does not break when the nameserver hash
  510. * table already contains a NameserverEntry in some given state. Each test
  511. * for a different state.
  512. */
  513. //@{
  514. /// \short Test how the zone reacts to a nameserver entry in ready state
  515. TEST_F(ZoneEntryTest, NameserverEntryReady) {
  516. // Inject the entry
  517. shared_ptr<NameserverEntry> nse(injectEntry());
  518. // Fill it with data
  519. nse->askIP(resolver_, nseCallback(), ANY_OK);
  520. EXPECT_EQ(Fetchable::IN_PROGRESS, nse->getState());
  521. EXPECT_TRUE(resolver_->asksIPs(ns_name_, 0, 1));
  522. EXPECT_NO_THROW(resolver_->answer(0, ns_name_, RRType::A(),
  523. rdata::in::A("192.0.2.1")));
  524. EXPECT_NO_THROW(resolver_->answer(1, ns_name_, RRType::AAAA(),
  525. rdata::in::AAAA("2001:db8::1")));
  526. EXPECT_EQ(Fetchable::READY, nse->getState());
  527. checkInjected(false);
  528. }
  529. /// \short Test how the zone reacts to a nameserver in not asked state
  530. TEST_F(ZoneEntryTest, NameserverEntryNotAsked) {
  531. // Inject the entry
  532. injectEntry();
  533. // We do not need it, nothing to modify on it
  534. checkInjected(true);
  535. }
  536. /// \short What if the zone finds a nameserver in progress?
  537. TEST_F(ZoneEntryTest, NameserverEntryInProgress) {
  538. // Prepare the nameserver entry
  539. shared_ptr<NameserverEntry> nse(injectEntry());
  540. nse->askIP(resolver_, nseCallback(), ANY_OK);
  541. EXPECT_EQ(Fetchable::IN_PROGRESS, nse->getState());
  542. EXPECT_TRUE(resolver_->asksIPs(ns_name_, 0, 1));
  543. checkInjected(true);
  544. }
  545. /// \short Check Zone's reaction to found expired nameserver
  546. TEST_F(ZoneEntryTest, NameserverEntryExpired) {
  547. shared_ptr<NameserverEntry> nse(injectEntry());
  548. nse->askIP(resolver_, nseCallback(), ANY_OK);
  549. EXPECT_EQ(Fetchable::IN_PROGRESS, nse->getState());
  550. EXPECT_TRUE(resolver_->asksIPs(ns_name_, 0, 1));
  551. EXPECT_NO_THROW(resolver_->answer(0, ns_name_, RRType::A(),
  552. rdata::in::A("192.0.2.1"), 0));
  553. EXPECT_NO_THROW(resolver_->answer(1, ns_name_, RRType::AAAA(),
  554. rdata::in::AAAA("2001:db8::1"), 0));
  555. EXPECT_EQ(Fetchable::READY, nse->getState());
  556. NameserverEntry::AddressVector addresses;
  557. EXPECT_EQ(Fetchable::EXPIRED, nse->getAddresses(addresses));
  558. EXPECT_EQ(Fetchable::EXPIRED, nse->getState());
  559. resolver_->requests.clear();
  560. checkInjected(true);
  561. }
  562. /// \short Check how it reacts to an unreachable zone already in the table
  563. TEST_F(ZoneEntryTest, NameserverEntryUnreachable) {
  564. shared_ptr<NameserverEntry> nse(injectEntry());
  565. nse->askIP(resolver_, nseCallback(), ANY_OK);
  566. ASSERT_EQ(2, resolver_->requests.size());
  567. resolver_->requests[0].second->failure();
  568. resolver_->requests[1].second->failure();
  569. EXPECT_EQ(Fetchable::UNREACHABLE, nse->getState());
  570. checkInjected(false, 0, 1);
  571. }
  572. //@}
  573. } // namespace