Browse Source

[trac859] Make TestResolver reusable by other libs

Michal 'vorner' Vaner 14 years ago
parent
commit
ffbe8a099b

+ 2 - 1
src/lib/nsas/tests/nameserver_address_unittest.cc

@@ -51,7 +51,8 @@ public:
         ns_.reset(new NameserverEntry(name_.toText(), RRClass::IN()));
         ns_->askIP(resolver_.get(), boost::shared_ptr<Callback>(new Callback), ANY_OK);
         resolver_->asksIPs(name_, 0, 1);
-        resolver_->requests[0].second->success(createResponseMessage(rrv4_));
+        resolver_->requests[0].second->success(
+            isc::util::unittests::createResponseMessage(rrv4_));
     }
 
     // Return the sample NameserverEntry

+ 2 - 1
src/lib/nsas/tests/nameserver_entry_unittest.cc

@@ -72,7 +72,8 @@ private:
         RRsetPtr set)
     {
         if (set) {
-            resolver->requests[index].second->success(createResponseMessage(set));
+            resolver->requests[index].second->success(
+                isc::util::unittests::createResponseMessage(set));
         } else {
             resolver->requests[index].second->failure();
         }

+ 2 - 146
src/lib/nsas/tests/nsas_test.h

@@ -27,6 +27,7 @@
 #include <config.h>
 
 #include <util/buffer.h>
+#include <util/unittests/resolver.h>
 #include <dns/message.h>
 #include <dns/rdata.h>
 #include <dns/rrtype.h>
@@ -35,24 +36,12 @@
 #include <dns/rcode.h>
 #include <dns/messagerenderer.h>
 #include <dns/rdataclass.h>
-#include <resolve/resolver_interface.h>
 #include "../nsas_entry.h"
 
 using namespace isc::dns::rdata;
 using namespace isc::dns;
 using namespace isc::util;
-
-namespace {
-    MessagePtr
-    createResponseMessage(RRsetPtr answer_rrset)
-    {
-        MessagePtr response(new Message(Message::RENDER));
-        response->setOpcode(Opcode::QUERY());
-        response->setRcode(Rcode::NOERROR());
-        response->addRRset(Message::SECTION_ANSWER, answer_rrset);
-        return response;
-    }
-}
+using isc::util::unittests::TestResolver;
 
 namespace isc {
 namespace dns {
@@ -223,139 +212,6 @@ private:
 
 static const uint32_t HASHTABLE_DEFAULT_SIZE = 1009; ///< First prime above 1000
 
-using namespace std;
-
-/*
- * This pretends to be a resolver. It stores the queries and
- * they can be answered.
- */
-class TestResolver : public isc::resolve::ResolverInterface {
-    private:
-        bool checkIndex(size_t index) {
-            return (requests.size() > index);
-        }
-
-        typedef std::map<isc::dns::Question, RRsetPtr >
-            PresetAnswers;
-        PresetAnswers answers_;
-    public:
-        typedef pair<QuestionPtr, CallbackPtr> Request;
-        vector<Request> requests;
-
-        /// \brief Destructor
-        ///
-        /// This is important.  All callbacks in the requests vector must be
-        /// called to remove them from internal loops.  Without this, destroying
-        /// the NSAS object will leave memory assigned.
-        ~TestResolver() {
-            for (size_t i = 0; i < requests.size(); ++i) {
-                requests[i].second->failure();
-            }
-        }
-
-        virtual void resolve(const QuestionPtr& q, const CallbackPtr& c) {
-            PresetAnswers::iterator it(answers_.find(*q));
-            if (it == answers_.end()) {
-                requests.push_back(Request(q, c));
-            } else {
-                if (it->second) {
-                    c->success(createResponseMessage(it->second));
-                } else {
-                    c->failure();
-                }
-            }
-        }
-
-        /*
-         * Add a preset answer. If shared_ptr() is passed (eg. NULL),
-         * it will generate failure. If the question is not preset,
-         * it goes to requests and you can answer later.
-         */
-        void addPresetAnswer(const isc::dns::Question& question,
-            RRsetPtr answer)
-        {
-            answers_[question] = answer;
-        }
-
-        // Thrown if the query at the given index does not exist.
-        class NoSuchRequest : public std::exception { };
-
-        // Thrown if the answer does not match the query
-        class DifferentRequest : public std::exception { };
-
-        QuestionPtr operator[](size_t index) {
-            if (index >= requests.size()) {
-                throw NoSuchRequest();
-            }
-            return (requests[index].first);
-        }
-        /*
-         * Looks if the two provided requests in resolver are A and AAAA.
-         * Sorts them so index1 is A.
-         *
-         * Returns false if there aren't enough elements
-         */
-        bool asksIPs(const Name& name, size_t index1, size_t index2) {
-            size_t max = (index1 < index2) ? index2 : index1;
-            if (!checkIndex(max)) {
-                return false;
-            }
-            EXPECT_EQ(name, (*this)[index1]->getName());
-            EXPECT_EQ(name, (*this)[index2]->getName());
-            EXPECT_EQ(RRClass::IN(), (*this)[index1]->getClass());
-            EXPECT_EQ(RRClass::IN(), (*this)[index2]->getClass());
-            // If they are the other way around, swap
-            if ((*this)[index1]->getType() == RRType::AAAA() &&
-                (*this)[index2]->getType() == RRType::A())
-            {
-                TestResolver::Request tmp((*this).requests[index1]);
-                (*this).requests[index1] =
-                    (*this).requests[index2];
-                (*this).requests[index2] = tmp;
-            }
-            // Check the correct addresses
-            EXPECT_EQ(RRType::A(), (*this)[index1]->getType());
-            EXPECT_EQ(RRType::AAAA(), (*this)[index2]->getType());
-            return (true);
-        }
-
-        /*
-         * Sends a simple answer to a query.
-         * 1) Provide index of a query and the address(es) to pass.
-         * 2) Provide index of query and components of address to pass.
-         */
-        void answer(size_t index, RRsetPtr& set) {
-            if (index >= requests.size()) {
-                throw NoSuchRequest();
-            }
-            requests[index].second->success(createResponseMessage(set));
-        }
-
-        void answer(size_t index, const Name& name, const RRType& type,
-            const rdata::Rdata& rdata, size_t TTL = 100)
-        {
-            RRsetPtr set(new RRset(name, RRClass::IN(),
-                type, RRTTL(TTL)));
-            set->addRdata(rdata);
-            answer(index, set);
-        }
-
-
-        void provideNS(size_t index,
-            RRsetPtr nameservers)
-        {
-            if (index >= requests.size()) {
-                throw NoSuchRequest();
-            }
-            if (requests[index].first->getName() != nameservers->getName() ||
-                requests[index].first->getType() != RRType::NS())
-            {
-                throw DifferentRequest();
-            }
-            requests[index].second->success(createResponseMessage(nameservers));
-        }
-};
-
 // String constants.  These should end in a dot.
 static const std::string EXAMPLE_CO_UK("example.co.uk.");
 static const std::string EXAMPLE_NET("example.net.");

+ 2 - 0
src/lib/resolve/tests/recursive_query_unittest.cc

@@ -860,4 +860,6 @@ TEST_F(RecursiveQueryTest, DISABLED_recursiveSendNXDOMAIN) {
 // TODO: add tests that check whether the cache is updated on succesfull
 // responses, and not updated on failures.
 
+
+
 }

+ 1 - 1
src/lib/util/unittests/Makefile.am

@@ -2,6 +2,6 @@ AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
 AM_CXXFLAGS = $(B10_CXXFLAGS)
 
 lib_LTLIBRARIES = libutil_unittests.la
-libutil_unittests_la_SOURCES = fork.h fork.cc
+libutil_unittests_la_SOURCES = fork.h fork.cc resolver.h
 
 CLEANFILES = *.gcno *.gcda

+ 193 - 0
src/lib/util/unittests/resolver.h

@@ -0,0 +1,193 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef UTIL_UNITTEST_RESOLVER_H
+#define UTIL_UNITTEST_RESOLVER_H
+
+/// \file resolver.h
+/// \brief Fake resolver
+
+#include <map>
+#include <dns/rrset.h>
+#include <dns/question.h>
+#include <dns/message.h>
+#include <dns/opcode.h>
+#include <dns/rcode.h>
+#include <dns/rrttl.h>
+#include <resolve/resolver_interface.h>
+#include <gtest/gtest.h>
+
+namespace isc {
+namespace util {
+namespace unittests {
+
+/// \brief Put rrset into a message as an answer
+inline static isc::dns::MessagePtr
+createResponseMessage(isc::dns::RRsetPtr answer_rrset)
+{
+    isc::dns::MessagePtr response(new isc::dns::Message(
+        isc::dns::Message::RENDER));
+    response->setOpcode(isc::dns::Opcode::QUERY());
+    response->setRcode(isc::dns::Rcode::NOERROR());
+    response->addRRset(isc::dns::Message::SECTION_ANSWER, answer_rrset);
+    return response;
+}
+
+/// \brief Mock resolver
+///
+/// This class pretends to be a resolver. However, it only stores the
+/// requests and can answer them right away by prepared answers. It doesn't
+/// do any real work and is intended for testing purposes.
+class TestResolver : public isc::resolve::ResolverInterface {
+    private:
+        bool checkIndex(size_t index) {
+            return (requests.size() > index);
+        }
+
+        typedef std::map<isc::dns::Question, isc::dns::RRsetPtr>
+            PresetAnswers;
+        PresetAnswers answers_;
+    public:
+        typedef std::pair<isc::dns::QuestionPtr, CallbackPtr> Request;
+        /// \brief List of requests the tested class sent trough resolve
+        std::vector<Request> requests;
+
+        /// \brief Destructor
+        ///
+        /// This is important.  All callbacks in the requests vector must be
+        /// called to remove them from internal loops.  Without this, destroying
+        /// the NSAS object will leave memory assigned.
+        ~TestResolver() {
+            for (size_t i = 0; i < requests.size(); ++i) {
+                requests[i].second->failure();
+            }
+        }
+
+        /// \brief Testing version of resolve
+        ///
+        /// If there's a prepared answer (provided by addPresetAnswer), it
+        /// answers it right away. Otherwise it just stores the request in
+        /// the requests member so it can be examined later.
+        virtual void resolve(const isc::dns::QuestionPtr& q,
+                             const CallbackPtr& c)
+        {
+            PresetAnswers::iterator it(answers_.find(*q));
+            if (it == answers_.end()) {
+                requests.push_back(Request(q, c));
+            } else {
+                if (it->second) {
+                    c->success(createResponseMessage(it->second));
+                } else {
+                    c->failure();
+                }
+            }
+        }
+
+        /// \brief Add a preset answer.
+        ///
+        /// Add a preset answer. If shared_ptr() is passed (eg. NULL),
+        /// it will generate failure. If the question is not preset,
+        /// it goes to requests and you can answer later.
+        void addPresetAnswer(const isc::dns::Question& question,
+            isc::dns::RRsetPtr answer)
+        {
+            answers_[question] = answer;
+        }
+
+        /// \brief Thrown if the query at the given index does not exist.
+        class NoSuchRequest : public std::exception { };
+
+        /// \brief Thrown if the answer does not match the query
+        class DifferentRequest : public std::exception { };
+
+        /// \brief Provides the question of request on given answer
+        isc::dns::QuestionPtr operator[](size_t index) {
+            if (index >= requests.size()) {
+                throw NoSuchRequest();
+            }
+            return (requests[index].first);
+        }
+        /// \brief Test it asks for IP addresses
+        /// Looks if the two provided requests in resolver are A and AAAA.
+        /// Sorts them so index1 is A.
+        ///
+        /// Returns false if there aren't enough elements
+        bool asksIPs(const isc::dns::Name& name, size_t index1,
+                     size_t index2)
+        {
+            size_t max = (index1 < index2) ? index2 : index1;
+            if (!checkIndex(max)) {
+                return false;
+            }
+            EXPECT_EQ(name, (*this)[index1]->getName());
+            EXPECT_EQ(name, (*this)[index2]->getName());
+            EXPECT_EQ(isc::dns::RRClass::IN(), (*this)[index1]->getClass());
+            EXPECT_EQ(isc::dns::RRClass::IN(), (*this)[index2]->getClass());
+            // If they are the other way around, swap
+            if ((*this)[index1]->getType() == isc::dns::RRType::AAAA() &&
+                (*this)[index2]->getType() == isc::dns::RRType::A())
+            {
+                TestResolver::Request tmp((*this).requests[index1]);
+                (*this).requests[index1] =
+                    (*this).requests[index2];
+                (*this).requests[index2] = tmp;
+            }
+            // Check the correct addresses
+            EXPECT_EQ(isc::dns::RRType::A(), (*this)[index1]->getType());
+            EXPECT_EQ(isc::dns::RRType::AAAA(), (*this)[index2]->getType());
+            return (true);
+        }
+
+        /// \brief Answer a request
+        /// Sends a simple answer to a query.
+        /// 1) Provide index of a query and the address(es) to pass.
+        /// 2) Provide index of query and components of address to pass.
+        void answer(size_t index, isc::dns::RRsetPtr& set) {
+            if (index >= requests.size()) {
+                throw NoSuchRequest();
+            }
+            requests[index].second->success(createResponseMessage(set));
+        }
+
+        void answer(size_t index, const isc::dns::Name& name,
+                    const isc::dns::RRType& type,
+                    const isc::dns::rdata::Rdata& rdata, size_t TTL = 100)
+        {
+            isc::dns::RRsetPtr set(new isc::dns::RRset(name,
+                                                       isc::dns::RRClass::IN(),
+                                                       type,
+                                                       isc::dns::RRTTL(TTL)));
+            set->addRdata(rdata);
+            answer(index, set);
+        }
+        /// \Answer the query at index by list of nameservers
+        void provideNS(size_t index, isc::dns::RRsetPtr nameservers)
+        {
+            if (index >= requests.size()) {
+                throw NoSuchRequest();
+            }
+            if (requests[index].first->getName() != nameservers->getName() ||
+                requests[index].first->getType() != isc::dns::RRType::NS())
+            {
+                throw DifferentRequest();
+            }
+            requests[index].second->success(createResponseMessage(nameservers));
+        }
+};
+
+}
+}
+}
+
+#endif