nsas_test.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  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. #ifndef __NSAS_TEST_H
  16. #define __NSAS_TEST_H
  17. /// \file nsas_test.h
  18. ///
  19. /// Contains miscellaneous classes and other stuff to help with the nameserver
  20. /// address store tests.
  21. #include <string>
  22. #include <vector>
  23. #include <config.h>
  24. #include <dns/buffer.h>
  25. #include <dns/rdata.h>
  26. #include <dns/rrtype.h>
  27. #include <dns/rrttl.h>
  28. #include <dns/messagerenderer.h>
  29. #include <dns/rdataclass.h>
  30. #include "../nsas_entry.h"
  31. #include "../resolver_interface.h"
  32. using namespace isc::dns::rdata;
  33. using namespace isc::dns;
  34. namespace isc {
  35. namespace dns {
  36. /// \brief Class Types
  37. ///
  38. /// Very simple classes to provide a type for the RdataTest class below.
  39. /// All they do is return the type code associated with the record type.
  40. class A {
  41. public:
  42. uint16_t getType() const
  43. {return RRType::A().getCode();}
  44. };
  45. class AAAA {
  46. public:
  47. uint16_t getType() const
  48. {return RRType::AAAA().getCode();}
  49. };
  50. class MX {
  51. public:
  52. uint16_t getType() const
  53. {return RRType::MX().getCode();}
  54. };
  55. /// \brief Hold Rdata
  56. ///
  57. /// A concrete implementation of the Rdata class, this holds data for the
  58. /// tests. All RRs in the tests are either A, AAAA, NS or MX records, and
  59. /// as a result the text form of the Rdata is a single uninterpreted string.
  60. /// For this reason, a single class definition
  61. template <typename T>
  62. class RdataTest: public Rdata {
  63. public:
  64. /// \brief Constructor
  65. ///
  66. /// Set the data in the object.
  67. ///
  68. /// \param v4address IPV4 address to store. (The format of this address is
  69. /// not checked.)
  70. RdataTest(const std::string& data) : data_(data)
  71. {}
  72. /// \brief Convert Rdata to string
  73. ///
  74. /// This is the convenient interface to extract the information stored
  75. /// in this object into a form that can be used by the tests.
  76. virtual std::string toText() const {
  77. return (data_);
  78. }
  79. /// \brief Return type of Rdata
  80. ///
  81. /// Returns the type of the data. May be useful in the tests, although this
  82. /// will not appear in the main code as this interface is not defined.
  83. virtual uint16_t getType() const {
  84. return (type_.getType());
  85. }
  86. /// \name Unused Methods
  87. ///
  88. /// These methods are not used in the tests.
  89. ///
  90. //@{
  91. /// \brief Render the \c Rdata in the wire format to a buffer
  92. virtual void toWire(OutputBuffer& buffer) const;
  93. /// \brief render the \Rdata in the wire format to a \c MessageRenderer
  94. virtual void toWire(MessageRenderer& renderer) const;
  95. /// \brief Comparison Method
  96. virtual int compare(const Rdata& other) const;
  97. //@}
  98. private:
  99. std::string data_; ///< Rdata itself
  100. T type_; ///< Identifies type of the Rdata
  101. };
  102. template <typename T>
  103. void RdataTest<T>::toWire(OutputBuffer&) const {
  104. }
  105. template <typename T>
  106. void RdataTest<T>::toWire(MessageRenderer&) const {
  107. }
  108. template <typename T>
  109. int RdataTest<T>::compare(const Rdata&) const {
  110. return 0;
  111. }
  112. } // namespace dns
  113. } // namespace isc
  114. namespace isc {
  115. namespace nsas {
  116. /// \brief Test Entry Class
  117. ///
  118. /// This is an element that can be stored in both the hash table and the
  119. /// LRU list.
  120. class TestEntry : public NsasEntry<TestEntry> {
  121. public:
  122. /// \brief Constructor
  123. ///
  124. /// \param name Name that will be used for the object. This will form
  125. /// part of the key.
  126. /// \param class_code Class associated with the object.
  127. TestEntry(std::string name, const isc::dns::RRClass& class_code) :
  128. name_(name), class_code_(class_code)
  129. {}
  130. /// \brief Virtual Destructor
  131. virtual ~TestEntry()
  132. {}
  133. /// \brief Return Hash Key
  134. ///
  135. /// This must be overridden in all classes derived from NsasEntry, and
  136. /// returns the hash key corresponding to the name and class.
  137. virtual HashKey hashKey() const {
  138. return HashKey(name_, class_code_);
  139. }
  140. /// \brief Get the Name
  141. ///
  142. /// \return Name given to this object
  143. virtual std::string getName() const {
  144. return name_;
  145. }
  146. /// \brief Set the Name
  147. ///
  148. /// \param name New name of the object
  149. virtual void setName(const std::string& name) {
  150. name_ = name;
  151. }
  152. /// \brief Get the Class
  153. ///
  154. /// \return Class code assigned to this object
  155. virtual const isc::dns::RRClass& getClass() const {
  156. return class_code_;
  157. }
  158. /// \brief Set the Class
  159. ///
  160. /// \param class_code New class code of the object
  161. virtual void setClass(const isc::dns::RRClass& class_code) {
  162. class_code_ = class_code;
  163. }
  164. private:
  165. std::string name_; ///< Name of the object
  166. isc::dns::RRClass class_code_; ///< Class of the object
  167. };
  168. /// \brief isc::nsas Constants
  169. ///
  170. /// Some constants used in the various tests.
  171. static const uint32_t HASHTABLE_DEFAULT_SIZE = 1009; ///< First prime above 1000
  172. } // namespace nsas
  173. } // namespace isc
  174. namespace {
  175. using namespace std;
  176. /*
  177. * This pretends to be a resolver. It stores the queries and
  178. * they can be answered.
  179. */
  180. class TestResolver : public isc::nsas::ResolverInterface {
  181. private:
  182. bool checkIndex(size_t index) {
  183. return (requests.size() > index);
  184. }
  185. typedef std::map<isc::dns::Question, boost::shared_ptr<AbstractRRset> >
  186. PresetAnswers;
  187. PresetAnswers answers_;
  188. public:
  189. typedef pair<QuestionPtr, CallbackPtr> Request;
  190. vector<Request> requests;
  191. virtual void resolve(const QuestionPtr& q, const CallbackPtr& c) {
  192. PresetAnswers::iterator it(answers_.find(*q));
  193. if (it == answers_.end()) {
  194. requests.push_back(Request(q, c));
  195. } else {
  196. if (it->second) {
  197. c->success(it->second);
  198. } else {
  199. c->failure();
  200. }
  201. }
  202. }
  203. /*
  204. * Add a preset answer. If shared_ptr() is passed (eg. NULL),
  205. * it will generate failure. If the question is not preset,
  206. * it goes to requests and you can answer later.
  207. */
  208. void addPresetAnswer(const isc::dns::Question& question,
  209. boost::shared_ptr<AbstractRRset> answer)
  210. {
  211. answers_[question] = answer;
  212. }
  213. // Thrown if the query at the given index does not exist.
  214. class NoSuchRequest : public std::exception { };
  215. // Thrown if the answer does not match the query
  216. class DifferentRequest : public std::exception { };
  217. QuestionPtr operator[](size_t index) {
  218. if (index >= requests.size()) {
  219. throw NoSuchRequest();
  220. }
  221. return (requests[index].first);
  222. }
  223. /*
  224. * Looks if the two provided requests in resolver are A and AAAA.
  225. * Sorts them so index1 is A.
  226. *
  227. * Returns false if there aren't enough elements
  228. */
  229. bool asksIPs(const Name& name, size_t index1, size_t index2) {
  230. size_t max = (index1 < index2) ? index2 : index1;
  231. if (!checkIndex(max)) {
  232. return false;
  233. }
  234. EXPECT_EQ(name, (*this)[index1]->getName());
  235. EXPECT_EQ(name, (*this)[index2]->getName());
  236. EXPECT_EQ(RRClass::IN(), (*this)[index1]->getClass());
  237. EXPECT_EQ(RRClass::IN(), (*this)[index2]->getClass());
  238. // If they are the other way around, swap
  239. if ((*this)[index1]->getType() == RRType::AAAA() &&
  240. (*this)[index2]->getType() == RRType::A())
  241. {
  242. TestResolver::Request tmp((*this).requests[index1]);
  243. (*this).requests[index1] =
  244. (*this).requests[index2];
  245. (*this).requests[index2] = tmp;
  246. }
  247. // Check the correct addresses
  248. EXPECT_EQ(RRType::A(), (*this)[index1]->getType());
  249. EXPECT_EQ(RRType::AAAA(), (*this)[index2]->getType());
  250. return (true);
  251. }
  252. /*
  253. * Sends a simple answer to a query.
  254. * Provide index of a query and the address to pass.
  255. */
  256. void answer(size_t index, const Name& name, const RRType& type,
  257. const rdata::Rdata& rdata, size_t TTL = 100)
  258. {
  259. if (index >= requests.size()) {
  260. throw NoSuchRequest();
  261. }
  262. RRsetPtr set(new RRset(name, RRClass::IN(),
  263. type, RRTTL(TTL)));
  264. set->addRdata(rdata);
  265. requests[index].second->success(set);
  266. }
  267. void provideNS(size_t index,
  268. boost::shared_ptr<AbstractRRset> nameservers)
  269. {
  270. if (index >= requests.size()) {
  271. throw NoSuchRequest();
  272. }
  273. if (requests[index].first->getName() != nameservers->getName() ||
  274. requests[index].first->getType() != RRType::NS())
  275. {
  276. throw DifferentRequest();
  277. }
  278. requests[index].second->success(nameservers);
  279. }
  280. };
  281. // String constants. These should end in a dot.
  282. static const std::string EXAMPLE_CO_UK("example.co.uk.");
  283. static const std::string EXAMPLE_NET("example.net.");
  284. static const std::string MIXED_EXAMPLE_CO_UK("EXAmple.co.uk.");
  285. class TestWithRdata : public ::testing::Test {
  286. protected:
  287. typedef boost::shared_ptr<RRset> RRsetPtr;
  288. /// \brief Constructor
  289. ///
  290. /// Initializes the RRsets used in the tests. The RRsets themselves have to
  291. /// be initialized with the basic data on their construction. The Rdata for
  292. /// them is added in SetUp().
  293. TestWithRdata() :
  294. rrv4_(new RRset(Name(EXAMPLE_CO_UK), RRClass::IN(), RRType::A(),
  295. RRTTL(1200))),
  296. rrcase_(new RRset(Name(MIXED_EXAMPLE_CO_UK), RRClass::IN(),
  297. RRType::A(), RRTTL(1200))),
  298. rrch_(new RRset(Name(EXAMPLE_CO_UK), RRClass::CH(), RRType::A(),
  299. RRTTL(1200))),
  300. rrns_(new RRset(Name(EXAMPLE_CO_UK), RRClass::IN(), RRType::NS(),
  301. RRTTL(1200))),
  302. rr_single_(new RRset(Name(EXAMPLE_CO_UK), RRClass::IN(),
  303. RRType::NS(), RRTTL(600))),
  304. rr_empty_(new RRset(Name(EXAMPLE_CO_UK), RRClass::IN(),
  305. RRType::NS(), RRTTL(600))),
  306. rrv6_(new RRset(Name(EXAMPLE_CO_UK), RRClass::IN(),
  307. RRType::AAAA(), RRTTL(900))),
  308. rrnet_(new RRset(Name(EXAMPLE_NET), RRClass::IN(), RRType::A(),
  309. RRTTL(600))),
  310. ns_name_("ns.example.net.")
  311. {}
  312. /// \brief Add Rdata to RRsets
  313. ///
  314. /// The data are added as const pointers to avoid the stricter type checking
  315. /// applied by the Rdata code. There is no need for it in these tests.
  316. virtual void SetUp() {
  317. // A records
  318. rrv4_->addRdata(ConstRdataPtr(new RdataTest<A>("1.2.3.4")));
  319. rrv4_->addRdata(ConstRdataPtr(new RdataTest<A>("5.6.7.8")));
  320. rrv4_->addRdata(ConstRdataPtr(new RdataTest<A>("9.10.11.12")));
  321. // A records
  322. rrcase_->addRdata(ConstRdataPtr(new RdataTest<A>("13.14.15.16")));
  323. // No idea what Chaosnet address look like other than they are 16 bits
  324. // The fact that they are type A is probably also incorrect.
  325. rrch_->addRdata(ConstRdataPtr(new RdataTest<A>("1324")));
  326. // NS records take a single name
  327. rrns_->addRdata(rdata::generic::NS("example.fr"));
  328. rrns_->addRdata(rdata::generic::NS("example.de"));
  329. // Single NS record with 0 TTL
  330. rr_single_->addRdata(rdata::generic::NS(ns_name_));
  331. // AAAA records
  332. rrv6_->addRdata(ConstRdataPtr(new RdataTest<AAAA>("2001::1002")));
  333. rrv6_->addRdata(ConstRdataPtr(new RdataTest<AAAA>("dead:beef:feed::")));
  334. // A record for example.net
  335. rrnet_->addRdata(ConstRdataPtr(new RdataTest<A>("17.18.18.20")));
  336. }
  337. /// \brief Data for the tests
  338. RRsetPtr rrv4_; ///< Standard RRSet - IN, A, lowercase name
  339. RRsetPtr rrcase_; ///< Mixed-case name
  340. RRsetPtr rrch_; ///< Non-IN RRset (Chaos in this case)
  341. RRsetPtr rrns_; ///< NS RRset
  342. RRsetPtr rr_single_; ///< NS RRset with single NS
  343. RRsetPtr rr_empty_; ///< NS RRset without any nameservers
  344. RRsetPtr rrv6_; ///< Standard RRset, IN, AAAA, lowercase name
  345. RRsetPtr rrnet_; ///< example.net A RRset
  346. Name ns_name_; ///< Nameserver name of ns.example.net
  347. };
  348. } // Empty namespace
  349. #endif // __NSAS_TEST_H