nameserver_entry_unittest.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  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 <iostream>
  16. #include <algorithm>
  17. #include <limits.h>
  18. #include <boost/foreach.hpp>
  19. #include <boost/shared_ptr.hpp>
  20. #include <gtest/gtest.h>
  21. #include <dns/rdata.h>
  22. #include <dns/rrset.h>
  23. #include <dns/rrclass.h>
  24. #include <dns/rdataclass.h>
  25. #include <dns/rrttl.h>
  26. #include <dns/name.h>
  27. #include <exceptions/exceptions.h>
  28. #include "../asiolink.h"
  29. #include "../address_entry.h"
  30. #include "../nameserver_entry.h"
  31. #include "../zone_entry.h"
  32. #include "nsas_test.h"
  33. using namespace isc::nsas;
  34. using namespace asiolink;
  35. using namespace std;
  36. using namespace isc::dns;
  37. using namespace rdata;
  38. using namespace boost;
  39. namespace {
  40. /// \brief Test Fixture Class
  41. class NameserverEntryTest : public TestWithRdata {
  42. protected:
  43. /// \short Just a really stupid callback counting times called
  44. struct Callback : public NameserverEntry::Callback {
  45. size_t count;
  46. virtual void operator()(shared_ptr<NameserverEntry>) {
  47. count ++;
  48. }
  49. Callback() : count(0) { }
  50. };
  51. };
  52. /// \brief Compare Vectors of String
  53. ///
  54. /// Compares two vectors of strings. A GoogleTest check is done on the results.
  55. ///
  56. /// \param vec1 First vector. This may be reordered in the comparison.
  57. /// \param vec2 Second vector. This may be reordered in the comparison
  58. static void CompareStringVectors(vector<string>& vec1, vector<string>& vec2)
  59. {
  60. // Check that the vectors are the same size.
  61. EXPECT_EQ(vec1.size(), vec2.size());
  62. // Get into canonical order
  63. sort(vec1.begin(), vec1.end());
  64. sort(vec2.begin(), vec2.end());
  65. // ... and look for a mismatch.
  66. EXPECT_TRUE(equal(vec1.begin(), vec1.end(), vec2.begin()));
  67. }
  68. /// \brief Compare Ranges of Addresses
  69. ///
  70. /// Compares the addresses held in an address vector with those held in the
  71. /// RRset from which it was dervived and checks that there is a 1:1
  72. /// mapping between the two.
  73. ///
  74. /// \param av AddressVector retrieved from NameserverEntry object
  75. /// \param rrs BasicRRSet from which the vector was created
  76. static void CompareAddresses(NameserverEntry::AddressVector& av,
  77. BasicRRset& rrs)
  78. {
  79. // Extract addresses from address vector into strings
  80. vector<string> avs;
  81. BOOST_FOREACH(AddressEntry addr, av) {
  82. avs.push_back(addr.getAddress().toText());
  83. }
  84. // Do the same for the Basic RRset
  85. vector<string> rrstr;
  86. RdataIteratorPtr i = rrs.getRdataIterator();
  87. // TODO Remove at merge with #410
  88. i->first();
  89. while (! i->isLast()) {
  90. rrstr.push_back(i->getCurrent().toText());
  91. i->next();
  92. }
  93. // ... and compare the results
  94. CompareStringVectors(avs, rrstr);
  95. }
  96. /// \brief Compare Address Vectors
  97. ///
  98. /// Compares two address vectors by converting the addresses to string form
  99. /// and comparing the strings. Any mismatch will be reported.
  100. ///
  101. /// \param vec1 First address vector
  102. /// \param vec2 Second address vector
  103. static void CompareAddressVectors(NameserverEntry::AddressVector& vec1,
  104. NameserverEntry::AddressVector& vec2) {
  105. // Extract addresses from address vectors into strings
  106. vector<string> strvec1;
  107. BOOST_FOREACH(AddressEntry addr, vec1) {
  108. strvec1.push_back(addr.getAddress().toText());
  109. }
  110. vector<string> strvec2;
  111. BOOST_FOREACH(AddressEntry addr, vec2) {
  112. strvec2.push_back(addr.getAddress().toText());
  113. }
  114. CompareStringVectors(strvec1, strvec2);
  115. }
  116. /// Tests of the default constructor
  117. TEST_F(NameserverEntryTest, DefaultConstructor) {
  118. // Default constructor should not create any RRsets
  119. NameserverEntry alpha(EXAMPLE_CO_UK, RRClass::IN().getCode());
  120. EXPECT_EQ(EXAMPLE_CO_UK, alpha.getName());
  121. EXPECT_EQ(RRClass::IN().getCode(), alpha.getClass());
  122. // Also check that no addresses have been created.
  123. NameserverEntry::AddressVector addresses;
  124. alpha.getAddresses(addresses);
  125. EXPECT_TRUE(addresses.empty());
  126. }
  127. /// Tests of constructor passed a list of addresses.
  128. TEST_F(NameserverEntryTest, AddressListConstructor) {
  129. // Initialize with no addresses and check that data returned has size of
  130. // zero and knows it did not ask for the address yet
  131. NameserverEntry alpha(NULL, NULL);
  132. NameserverEntry::AddressVector av;
  133. EXPECT_EQ(Fetchable::NOT_ASKED, alpha.getAddresses(av));
  134. EXPECT_EQ(0, av.size());
  135. NameserverEntry::AddressVector av4;
  136. EXPECT_EQ(Fetchable::NOT_ASKED, alpha.getAddresses(av4, V4_ONLY));
  137. EXPECT_EQ(0, av4.size());
  138. NameserverEntry::AddressVector av6;
  139. EXPECT_EQ(Fetchable::NOT_ASKED, alpha.getAddresses(av6, V6_ONLY));
  140. EXPECT_EQ(0, av6.size());
  141. // Initialize with V4 addresses only.
  142. EXPECT_GT(rrv4_.getRdataCount(), 0);
  143. NameserverEntry beta(&rrv4_, NULL);
  144. NameserverEntry::AddressVector bv;
  145. EXPECT_EQ(Fetchable::READY, beta.getAddresses(bv));
  146. EXPECT_EQ(rrv4_.getRdataCount(), bv.size());
  147. NameserverEntry::AddressVector bv4;
  148. EXPECT_EQ(Fetchable::READY, beta.getAddresses(bv4, V4_ONLY));
  149. EXPECT_EQ(rrv4_.getRdataCount(), bv4.size());
  150. NameserverEntry::AddressVector bv6;
  151. EXPECT_EQ(Fetchable::UNREACHABLE, beta.getAddresses(bv6, V6_ONLY));
  152. EXPECT_EQ(0, bv6.size());
  153. // Check that the addresses received are unique.
  154. SCOPED_TRACE("Checking V4 addresses");
  155. CompareAddresses(bv4, rrv4_);
  156. // Initialize with V6 addresses only
  157. EXPECT_TRUE(rrv6_.getRdataCount() > 0);
  158. NameserverEntry gamma(NULL, &rrv6_);
  159. NameserverEntry::AddressVector cv;
  160. EXPECT_EQ(Fetchable::READY, gamma.getAddresses(cv));
  161. EXPECT_EQ(rrv6_.getRdataCount(), cv.size());
  162. NameserverEntry::AddressVector cv4;
  163. EXPECT_EQ(Fetchable::UNREACHABLE, gamma.getAddresses(cv4, V4_ONLY));
  164. EXPECT_EQ(0, cv4.size());
  165. NameserverEntry::AddressVector cv6;
  166. EXPECT_EQ(Fetchable::READY, gamma.getAddresses(cv6, V6_ONLY));
  167. EXPECT_EQ(rrv6_.getRdataCount(), cv6.size());
  168. SCOPED_TRACE("Checking V6 addresses");
  169. CompareAddresses(cv6, rrv6_);
  170. // Initialize with both sets of addresses
  171. NameserverEntry delta(&rrv4_, &rrv6_);
  172. NameserverEntry::AddressVector dv;
  173. EXPECT_EQ(Fetchable::READY, delta.getAddresses(dv));
  174. EXPECT_EQ((rrv4_.getRdataCount() + rrv6_.getRdataCount()), dv.size());
  175. NameserverEntry::AddressVector dv4;
  176. EXPECT_EQ(Fetchable::READY, delta.getAddresses(dv4, V4_ONLY));
  177. EXPECT_EQ(rrv4_.getRdataCount(), dv4.size());
  178. SCOPED_TRACE("Checking V4 addresses after dual-address family constructor");
  179. CompareAddresses(dv4, rrv4_);
  180. NameserverEntry::AddressVector dv6;
  181. EXPECT_EQ(Fetchable::READY, delta.getAddresses(dv6, V6_ONLY));
  182. EXPECT_EQ(rrv6_.getRdataCount(), dv6.size());
  183. SCOPED_TRACE("Checking V6 addresses after dual-address family constructor");
  184. CompareAddresses(dv6, rrv6_);
  185. // ... and check that the composite of the v4 and v6 addresses is the same
  186. // as that returned by the get without a filter.
  187. NameserverEntry::AddressVector dvcomponent;
  188. EXPECT_EQ(Fetchable::READY, delta.getAddresses(dvcomponent, V4_ONLY));
  189. EXPECT_EQ(Fetchable::READY, delta.getAddresses(dvcomponent, V6_ONLY));
  190. SCOPED_TRACE("Checking V4+V6 addresses same as composite return");
  191. CompareAddressVectors(dv, dvcomponent);
  192. }
  193. // Test the the RTT on tthe created addresses is not 0 and is different
  194. TEST_F(NameserverEntryTest, InitialRTT) {
  195. // Get the RTT for the different addresses
  196. NameserverEntry alpha(&rrv4_, &rrv6_);
  197. NameserverEntry::AddressVector vec;
  198. alpha.getAddresses(vec);
  199. // Copy into a vector of time_t.
  200. vector<uint32_t> rtt;
  201. for (NameserverEntry::AddressVectorIterator i = vec.begin();
  202. i != vec.end(); ++i) {
  203. rtt.push_back(i->getRTT());
  204. }
  205. // Ensure that the addresses are sorted and note how many RTTs we have.
  206. sort(rtt.begin(), rtt.end());
  207. int oldcount = rtt.size();
  208. // Remove duplicates and notw the new size.
  209. vector<uint32_t>::iterator newend = unique(rtt.begin(), rtt.end());
  210. rtt.erase(newend, rtt.end());
  211. int newcount = rtt.size();
  212. // .. and we don't expect to have lost anything.
  213. EXPECT_EQ(oldcount, newcount);
  214. }
  215. // Set an address RTT to a given value
  216. TEST_F(NameserverEntryTest, SetRTT) {
  217. // Get the RTT for the different addresses
  218. NameserverEntry alpha(&rrv4_, &rrv6_);
  219. NameserverEntry::AddressVector vec;
  220. alpha.getAddresses(vec);
  221. ASSERT_TRUE(vec.size() > 0);
  222. // Take the first address and change the RTT.
  223. IOAddress first_address = vec[0].getAddress();
  224. uint32_t first_rtt = vec[0].getRTT();
  225. uint32_t new_rtt = first_rtt + 42;
  226. alpha.setAddressRTT(first_address, new_rtt);
  227. // Now see if it has changed
  228. NameserverEntry::AddressVector newvec;
  229. alpha.getAddresses(newvec);
  230. int matchcount = 0;
  231. for (NameserverEntry::AddressVectorIterator i = newvec.begin();
  232. i != newvec.end(); ++i) {
  233. if (i->getAddress().equal(first_address)) {
  234. ++matchcount;
  235. EXPECT_EQ(i->getRTT(), new_rtt);
  236. }
  237. }
  238. // ... and make sure there was only one match in the set we retrieved
  239. EXPECT_EQ(1, matchcount);
  240. }
  241. // Set an address RTT to be unreachable
  242. TEST_F(NameserverEntryTest, Unreachable) {
  243. // Get the RTT for the different addresses
  244. NameserverEntry alpha(&rrv4_, &rrv6_);
  245. NameserverEntry::AddressVector vec;
  246. alpha.getAddresses(vec);
  247. ASSERT_TRUE(vec.size() > 0);
  248. // Take the first address and mark as unreachable.
  249. IOAddress first_address = vec[0].getAddress();
  250. EXPECT_FALSE(vec[0].isUnreachable());
  251. alpha.setAddressUnreachable(first_address);
  252. // Now see if it has changed
  253. NameserverEntry::AddressVector newvec;
  254. alpha.getAddresses(newvec);
  255. int matchcount = 0;
  256. for (NameserverEntry::AddressVectorIterator i = newvec.begin();
  257. i != newvec.end(); ++i) {
  258. if (i->getAddress().equal(first_address)) {
  259. ++matchcount;
  260. EXPECT_TRUE(i->isUnreachable());
  261. }
  262. }
  263. // ... and make sure there was only one match in the set we retrieved
  264. EXPECT_EQ(1, matchcount);
  265. }
  266. // Test that the expiration time of records is set correctly.
  267. //
  268. // Note that for testing purposes we use the three-argument NameserverEntry
  269. // constructor (where we supply the time). It eliminates intermittent errors
  270. // cause when this test is run just as the clock "ticks over" to another second.
  271. TEST_F(NameserverEntryTest, ExpirationTime) {
  272. time_t curtime = time(NULL);
  273. time_t expiration = 0;
  274. // Test where there is a single TTL
  275. NameserverEntry alpha(&rrv4_, NULL, curtime);
  276. expiration = alpha.getExpiration();
  277. EXPECT_EQ(expiration, curtime + rrv4_.getTTL().getValue());
  278. NameserverEntry beta(NULL, &rrv6_, curtime);
  279. expiration = beta.getExpiration();
  280. EXPECT_EQ(expiration, curtime + rrv6_.getTTL().getValue());
  281. // Test where there are two different TTLs
  282. EXPECT_NE(rrv4_.getTTL().getValue(), rrv6_.getTTL().getValue());
  283. NameserverEntry gamma(&rrv4_, &rrv6_, curtime);
  284. uint32_t minttl = min(rrv4_.getTTL().getValue(), rrv6_.getTTL().getValue());
  285. EXPECT_EQ(expiration, curtime + minttl);
  286. // Finally check where we don't specify a current time. All we know is
  287. // that the expiration time should be greater than the TTL (as the current
  288. // time is greater than zero).
  289. NameserverEntry delta(&rrv4_, NULL);
  290. EXPECT_GT(delta.getExpiration(), rrv4_.getTTL().getValue());
  291. }
  292. // Test that the name of this nameserver is set correctly.
  293. TEST_F(NameserverEntryTest, CheckName) {
  294. // Default constructor
  295. NameserverEntry alpha(EXAMPLE_CO_UK, RRClass::IN().getCode());
  296. EXPECT_EQ(EXAMPLE_CO_UK, alpha.getName());
  297. // Address constructor
  298. NameserverEntry beta(&rrv4_, NULL);
  299. EXPECT_EQ(EXAMPLE_CO_UK, beta.getName());
  300. NameserverEntry gamma(NULL, &rrv6_);
  301. EXPECT_EQ(EXAMPLE_CO_UK, gamma.getName());
  302. NameserverEntry delta(&rrv4_, &rrv6_);
  303. EXPECT_EQ(EXAMPLE_CO_UK, delta.getName());
  304. // Check that the name is not canonicalised
  305. NameserverEntry epsilon(&rrcase_, NULL);
  306. EXPECT_EQ(MIXED_EXAMPLE_CO_UK, epsilon.getName());
  307. // Check that inconsistent names mean that an exception is generated.
  308. EXPECT_THROW(NameserverEntry zeta(&rrnet_, &rrv6_),
  309. isc::nsas::InconsistentOwnerNames);
  310. }
  311. // Check that it can cope with non-IN classes.
  312. TEST_F(NameserverEntryTest, CheckClass) {
  313. // Default constructor
  314. NameserverEntry alpha(EXAMPLE_CO_UK, RRClass::CH().getCode());
  315. EXPECT_EQ(RRClass::CH().getCode(), alpha.getClass());
  316. // Address constructor
  317. NameserverEntry beta(&rrch_, NULL);
  318. EXPECT_EQ(RRClass::CH().getCode(), beta.getClass());
  319. // Ensure that inconsistent class throws an exception
  320. EXPECT_THROW(NameserverEntry gamma(&rrch_, &rrv6_),
  321. isc::nsas::InconsistentClass);
  322. }
  323. // Tests if it asks the IP addresses and calls callbacks when it comes
  324. // including the right addresses are returned and that they expire
  325. TEST_F(NameserverEntryTest, IPCallbacks) {
  326. shared_ptr<NameserverEntry> entry(new NameserverEntry(EXAMPLE_CO_UK,
  327. RRClass::IN().getCode()));
  328. shared_ptr<Callback> callback(new Callback);
  329. shared_ptr<TestResolver> resolver(new TestResolver);
  330. entry->askIP(resolver, callback, ANY_OK, entry);
  331. // Ensure it becomes IN_PROGRESS
  332. EXPECT_EQ(Fetchable::IN_PROGRESS, entry->getState());
  333. // Now, there should be two queries in the resolver
  334. ASSERT_EQ(2, resolver->requests.size());
  335. resolver->asksIPs(Name(EXAMPLE_CO_UK), 0, 1);
  336. // Another one might ask
  337. entry->askIP(resolver, callback, V4_ONLY, entry);
  338. // There should still be only two queries in the resolver
  339. ASSERT_EQ(2, resolver->requests.size());
  340. // Another one, with need of IPv6 address
  341. entry->askIP(resolver, callback, V6_ONLY, entry);
  342. // Answer one and see that the callbacks are called
  343. resolver->answer(0, Name(EXAMPLE_CO_UK), RRType::A(),
  344. rdata::in::A("192.0.2.1"));
  345. // Both callbacks that want IPv4 should be called by now
  346. EXPECT_EQ(2, callback->count);
  347. // It should contain one IP address
  348. NameserverEntry::AddressVector addresses;
  349. // Still in progress, waiting for the other address
  350. EXPECT_EQ(Fetchable::IN_PROGRESS, entry->getAddresses(addresses));
  351. EXPECT_EQ(1, addresses.size());
  352. // Answer IPv6 address
  353. // It is with zero TTL, so it should expire right away
  354. resolver->answer(1, Name(EXAMPLE_CO_UK), RRType::AAAA(),
  355. rdata::in::AAAA("2001:db8::1"), 0);
  356. // The other callback should appear
  357. EXPECT_EQ(3, callback->count);
  358. // It should return the one address. It should be expired, but
  359. // we ignore it for now
  360. EXPECT_EQ(Fetchable::READY, entry->getAddresses(addresses, V6_ONLY, true));
  361. // Another address should appear
  362. EXPECT_EQ(2, addresses.size());
  363. // But when we do not ignore it, it should not appear
  364. EXPECT_EQ(Fetchable::EXPIRED, entry->getAddresses(addresses, V6_ONLY));
  365. EXPECT_EQ(2, addresses.size());
  366. }
  367. // Test the callback is called even when the address is unreachable
  368. TEST_F(NameserverEntryTest, IPCallbacksUnreachable) {
  369. shared_ptr<NameserverEntry> entry(new NameserverEntry(EXAMPLE_CO_UK,
  370. RRClass::IN().getCode()));
  371. shared_ptr<Callback> callback(new Callback);
  372. shared_ptr<TestResolver> resolver(new TestResolver);
  373. // Ask for its IP
  374. entry->askIP(resolver, callback, ANY_OK, entry);
  375. // Check it asks the resolver
  376. ASSERT_EQ(2, resolver->requests.size());
  377. resolver->asksIPs(Name(EXAMPLE_CO_UK), 0, 1);
  378. resolver->requests[0].second->failure();
  379. // It should still wait for the second one
  380. EXPECT_EQ(0, callback->count);
  381. EXPECT_EQ(Fetchable::IN_PROGRESS, entry->getState());
  382. // It should call the callback now and be unrechable
  383. resolver->requests[1].second->failure();
  384. EXPECT_EQ(1, callback->count);
  385. EXPECT_EQ(Fetchable::UNREACHABLE, entry->getState());
  386. NameserverEntry::AddressVector addresses;
  387. EXPECT_EQ(Fetchable::UNREACHABLE, entry->getAddresses(addresses));
  388. EXPECT_EQ(0, addresses.size());
  389. }
  390. } // namespace