Browse Source

[1612] finish tests and update code

catch exceptions in processMessage
tests now do full proxy implementation (proxying inmemory client)
Jelte Jansen 13 years ago
parent
commit
48b2af87d9

+ 42 - 27
src/bin/auth/auth_srv.cc

@@ -479,36 +479,51 @@ AuthSrv::processMessage(const IOMessage& io_message, MessagePtr message,
         return;
     }
 
-    // update per opcode statistics counter.  This can only be reliable after
-    // TSIG check succeeds.
-    impl_->counters_.inc(message->getOpcode());
-
-    bool send_answer = true;
-    if (message->getOpcode() == Opcode::NOTIFY()) {
-        send_answer = impl_->processNotify(io_message, message, buffer,
-                                           tsig_context);
-    } else if (message->getOpcode() != Opcode::QUERY()) {
-        LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_UNSUPPORTED_OPCODE)
-                  .arg(message->getOpcode().toText());
-        makeErrorMessage(message, buffer, Rcode::NOTIMP(), tsig_context);
-    } else if (message->getRRCount(Message::SECTION_QUESTION) != 1) {
-        makeErrorMessage(message, buffer, Rcode::FORMERR(), tsig_context);
-    } else {
-        ConstQuestionPtr question = *message->beginQuestion();
-        const RRType &qtype = question->getType();
-        if (qtype == RRType::AXFR()) {
-            send_answer = impl_->processXfrQuery(io_message, message, buffer,
-                                                 tsig_context);
-        } else if (qtype == RRType::IXFR()) {
-            send_answer = impl_->processXfrQuery(io_message, message, buffer,
-                                                 tsig_context);
+    try {
+        // update per opcode statistics counter.  This can only be reliable
+        // after TSIG check succeeds.
+        impl_->counters_.inc(message->getOpcode());
+
+        bool send_answer = true;
+        if (message->getOpcode() == Opcode::NOTIFY()) {
+            send_answer = impl_->processNotify(io_message, message, buffer,
+                                               tsig_context);
+        } else if (message->getOpcode() != Opcode::QUERY()) {
+            LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_UNSUPPORTED_OPCODE)
+                      .arg(message->getOpcode().toText());
+            makeErrorMessage(message, buffer, Rcode::NOTIMP(), tsig_context);
+        } else if (message->getRRCount(Message::SECTION_QUESTION) != 1) {
+            makeErrorMessage(message, buffer, Rcode::FORMERR(), tsig_context);
         } else {
-            send_answer = impl_->processNormalQuery(io_message, message,
-                                                    buffer, tsig_context);
+            ConstQuestionPtr question = *message->beginQuestion();
+            const RRType &qtype = question->getType();
+            if (qtype == RRType::AXFR()) {
+                send_answer = impl_->processXfrQuery(io_message, message,
+                                                     buffer, tsig_context);
+            } else if (qtype == RRType::IXFR()) {
+                send_answer = impl_->processXfrQuery(io_message, message,
+                                                     buffer, tsig_context);
+            } else {
+                send_answer = impl_->processNormalQuery(io_message, message,
+                                                        buffer, tsig_context);
+            }
         }
-    }
 
-    impl_->resumeServer(server, message, send_answer);
+        impl_->resumeServer(server, message, send_answer);
+    } catch (const isc::Unexpected&) {
+        // If the error was unexpected protocol, don't even bother responding
+        // (If we see other Unexpected's here, we should probably change to
+        // a specific exception for unknown protocol)
+        impl_->resumeServer(server, message, false);
+    } catch (const isc::Exception&) {
+        // For ISC Exceptions, respond with servfail
+        makeErrorMessage(message, buffer, Rcode::SERVFAIL());
+        impl_->resumeServer(server, message, true);
+    } catch (...) {
+        // Drop the query on any other exceptions (do we want servfail here
+        // too?)
+        impl_->resumeServer(server, message, false);
+    }
 }
 
 bool

+ 160 - 86
src/bin/auth/tests/auth_srv_unittest.cc

@@ -121,15 +121,14 @@ protected:
         }
     }
 
-    void processAndCheckSERVFAIL(bool expect_answer) {
+    // Convenience method for tests that expect to return SERVFAIL
+    // It calls processMessage, checks if there is an answer, and
+    // check the header for default SERVFAIL data
+    void processAndCheckSERVFAIL() {
         processMessage();
-        if (expect_answer) {
-            EXPECT_TRUE(dnsserv.hasAnswer());
-            headerCheck(*parse_message, default_qid, Rcode::SERVFAIL(),
-                        opcode.getCode(), QR_FLAG, 1, 0, 0, 0);
-        } else {
-            EXPECT_FALSE(dnsserv.hasAnswer());
-        }
+        EXPECT_TRUE(dnsserv.hasAnswer());
+        headerCheck(*parse_message, default_qid, Rcode::SERVFAIL(),
+                    opcode.getCode(), QR_FLAG, 1, 0, 0, 0);
     }
 
     IOService ios_;
@@ -492,17 +491,17 @@ TEST_F(AuthSrvTest, AXFRSendFail) {
 }
 
 TEST_F(AuthSrvTest, AXFRDisconnectFail) {
-    // In our usage disconnect() shouldn't fail.  So we'll see the exception
-    // should it be thrown.
+    // In our usage disconnect() shouldn't fail. But even if it does,
+    // it should not disrupt service (so processMessage should have caught it)
     xfrout.disableSend();
     xfrout.disableDisconnect();
     UnitTestUtil::createRequestMessage(request_message, opcode, default_qid,
                                        Name("example.com"), RRClass::IN(),
                                        RRType::AXFR());
     createRequestPacket(request_message, IPPROTO_TCP);
-    EXPECT_THROW(server.processMessage(*io_message, parse_message,
-                                       response_obuffer, &dnsserv),
-                 XfroutError);
+    EXPECT_NO_THROW(server.processMessage(*io_message, parse_message,
+                                          response_obuffer, &dnsserv));
+    // Since the disconnect failed, we should still be 'connected'
     EXPECT_TRUE(xfrout.isConnected());
     // XXX: we need to re-enable disconnect.  otherwise an exception would be
     // thrown via the destructor of the server.
@@ -550,17 +549,16 @@ TEST_F(AuthSrvTest, IXFRSendFail) {
 }
 
 TEST_F(AuthSrvTest, IXFRDisconnectFail) {
-    // In our usage disconnect() shouldn't fail.  So we'll see the exception
-    // should it be thrown.
+    // In our usage disconnect() shouldn't fail, but even if it does,
+    // procesMessage() should catch it.
     xfrout.disableSend();
     xfrout.disableDisconnect();
     UnitTestUtil::createRequestMessage(request_message, opcode, default_qid,
                                        Name("example.com"), RRClass::IN(),
                                        RRType::IXFR());
     createRequestPacket(request_message, IPPROTO_TCP);
-    EXPECT_THROW(server.processMessage(*io_message, parse_message,
-                                       response_obuffer, &dnsserv),
-                 XfroutError);
+    EXPECT_NO_THROW(server.processMessage(*io_message, parse_message,
+                                          response_obuffer, &dnsserv));
     EXPECT_TRUE(xfrout.isConnected());
     // XXX: we need to re-enable disconnect.  otherwise an exception would be
     // thrown via the destructor of the server.
@@ -760,7 +758,8 @@ updateConfig(AuthSrv* server, const char* const config_data,
 
     ConstElementPtr result = config_answer->get("result");
     EXPECT_EQ(Element::list, result->getType());
-    EXPECT_EQ(expect_success ? 0 : 1, result->get(0)->intValue());
+    EXPECT_EQ(expect_success ? 0 : 1, result->get(0)->intValue()) <<
+        "Bad result from updateConfig: " << result->str();
 }
 
 // Install a Sqlite3 data source with testing data.
@@ -1001,11 +1000,10 @@ getDummyUnknownSocket() {
     return (socket);
 }
 
-// Submit unexpected type of query and check it throws isc::Unexpected
+// Submit unexpected type of query and check it is ignored
 TEST_F(AuthSrvTest, queryCounterUnexpected) {
     // This code isn't exception safe, but we'd rather keep the code
-    // simpler and more readable as this is only for tests and if it throws
-    // the program would immediately terminate anyway.
+    // simpler and more readable as this is only for tests
 
     // Create UDP query packet.
     UnitTestUtil::createRequestMessage(request_message, Opcode::QUERY(),
@@ -1021,9 +1019,7 @@ TEST_F(AuthSrvTest, queryCounterUnexpected) {
                                request_renderer.getLength(),
                                getDummyUnknownSocket(), *endpoint);
 
-    EXPECT_THROW(server.processMessage(*io_message, parse_message,
-                                       response_obuffer, &dnsserv),
-                 isc::Unexpected);
+    EXPECT_FALSE(dnsserv.hasAnswer());
 }
 
 TEST_F(AuthSrvTest, stop) {
@@ -1056,10 +1052,12 @@ TEST_F(AuthSrvTest, listenAddresses) {
 // Tests for catching exceptions in various stages of the query processing
 //
 // These tests work by defining two proxy classes, that act as an in-memory
-// client by default, but can throw exceptions at various points
+// client by default, but can throw exceptions at various points.
 //
 namespace {
 
+/// A the possible methods to throw in, either in FakeInMemoryClient or
+/// FakeZoneFinder
 enum ThrowWhen {
     throw_never,
     throw_at_find_zone,
@@ -1067,10 +1065,10 @@ enum ThrowWhen {
     throw_at_get_class,
     throw_at_find,
     throw_at_find_all,
-    throw_at_find_nsec3,
-    throw_at_find_previous_name
+    throw_at_find_nsec3
 };
 
+/// convenience function to check whether and what to throw
 void
 checkThrow(ThrowWhen method, ThrowWhen throw_at, bool isc_exception) {
     if (method == throw_at) {
@@ -1082,6 +1080,12 @@ checkThrow(ThrowWhen method, ThrowWhen throw_at, bool isc_exception) {
     }
 }
 
+/// \brief proxy class for the ZoneFinder returned by the InMemoryClient
+///        proxied by FakeInMemoryClient
+///
+/// See the documentation for FakeInMemoryClient for more information,
+/// all methods simply check whether they should throw, and if not, call
+/// their proxied equivalent.
 class FakeZoneFinder : public isc::datasrc::ZoneFinder {
 public:
     FakeZoneFinder(isc::datasrc::ZoneFinderPtr zone_finder,
@@ -1091,38 +1095,47 @@ public:
         throw_when_(throw_when),
         isc_exception_(isc_exception)
     {}
-    virtual isc::dns::Name getOrigin() const {
-        checkThrow(throw_at_find_zone, throw_when_, isc_exception_);
-        return real_zone_finder_->getOrigin();
+
+    virtual isc::dns::Name
+    getOrigin() const {
+        checkThrow(throw_at_get_origin, throw_when_, isc_exception_);
+        return (real_zone_finder_->getOrigin());
     }
 
-    virtual isc::dns::RRClass getClass() const {
+    virtual isc::dns::RRClass
+    getClass() const {
+        assert(false);
         checkThrow(throw_at_get_class, throw_when_, isc_exception_);
-        return real_zone_finder_->getClass();
+        return (real_zone_finder_->getClass());
     }
 
-    virtual isc::datasrc::ZoneFinder::FindResult find(const isc::dns::Name& name,
-                                                      const isc::dns::RRType& type,
-                                                      isc::datasrc::ZoneFinder::FindOptions options) {
+    virtual isc::datasrc::ZoneFinder::FindResult
+    find(const isc::dns::Name& name,
+         const isc::dns::RRType& type,
+         isc::datasrc::ZoneFinder::FindOptions options)
+    {
         checkThrow(throw_at_find, throw_when_, isc_exception_);
-        return real_zone_finder_->find(name, type, options);
+        return (real_zone_finder_->find(name, type, options));
     }
 
-    virtual FindResult findAll(const isc::dns::Name& name,
+    virtual FindResult
+    findAll(const isc::dns::Name& name,
                                std::vector<isc::dns::ConstRRsetPtr> &target,
-                               const FindOptions options = FIND_DEFAULT) {
+                               const FindOptions options = FIND_DEFAULT)
+    {
         checkThrow(throw_at_find_all, throw_when_, isc_exception_);
-        return real_zone_finder_->findAll(name, target, options);
+        return (real_zone_finder_->findAll(name, target, options));
     };
 
-    virtual FindNSEC3Result findNSEC3(const isc::dns::Name& name, bool recursive) {
+    virtual FindNSEC3Result
+    findNSEC3(const isc::dns::Name& name,bool recursive) {
         checkThrow(throw_at_find_nsec3, throw_when_, isc_exception_);
-        return real_zone_finder_->findNSEC3(name, recursive);
+        return (real_zone_finder_->findNSEC3(name, recursive));
     };
 
-    virtual isc::dns::Name findPreviousName(const isc::dns::Name& query) const {
-        checkThrow(throw_at_find_previous_name, throw_when_, isc_exception_);
-        return real_zone_finder_->findPreviousName(query);
+    virtual isc::dns::Name
+    findPreviousName(const isc::dns::Name& query) const {
+        return (real_zone_finder_->findPreviousName(query));
     }
 
 private:
@@ -1131,9 +1144,20 @@ private:
     bool isc_exception_;
 };
 
-// Mock Auth Server that can throw exceptions at specified times
+/// \brief Proxy InMemoryClient that can throw exceptions at specified times
+///
+/// It is based on the memory client since that one is easy to override
+/// (with setInMemoryClient) with the current design of AuthSrv.
 class FakeInMemoryClient : public isc::datasrc::InMemoryClient {
 public:
+    /// \brief Create a proxy memory client
+    ///
+    /// \param real_client The real in-memory client to proxy
+    /// \param throw_when if set to any value other than never, that is
+    ///        the method that will throw an exception (either in this
+    ///        class or the related FakeZoneFinder)
+    /// \param isc_exception if true, throw isc::Exception, otherwise,
+    ///                      throw std::exception
     FakeInMemoryClient(AuthSrv::InMemoryClientPtr real_client,
                        ThrowWhen throw_when,
                        bool isc_exception) :
@@ -1142,10 +1166,20 @@ public:
         isc_exception_(isc_exception)
     {}
 
-    virtual FindResult findZone(const isc::dns::Name& name) const {
+    /// \brief proxy call for findZone
+    ///
+    /// if this instance was constructed with throw_shen set to find_zone,
+    /// this method will throw. Otherwise, it will return a FakeZoneFinder
+    /// instance which will throw at the method specified at the
+    /// construction of this instance.
+    virtual FindResult
+    findZone(const isc::dns::Name& name) const {
         checkThrow(throw_at_find_zone, throw_when_, isc_exception_);
         const FindResult result = real_client_->findZone(name);
-        return FindResult(result.code, isc::datasrc::ZoneFinderPtr(new FakeZoneFinder(result.zone_finder, throw_when_, isc_exception_)));
+        return (FindResult(result.code, isc::datasrc::ZoneFinderPtr(
+                                        new FakeZoneFinder(result.zone_finder,
+                                        throw_when_,
+                                        isc_exception_))));
     }
 
 private:
@@ -1154,15 +1188,16 @@ private:
     bool isc_exception_;
 };
 
-} // end namespace for throwing proxy classes
+} // end anonymous namespace for throwing proxy classes
 
+// Test for the tests
+//
+// Set the proxies to never throw, this should have the same result as
+// queryWithInMemoryClientNoDNSSEC, and serves to test the two proxy classes
 TEST_F(AuthSrvTest, queryWithInMemoryClientProxy) {
     // Set real inmem client to proxy
     updateConfig(&server, CONFIG_INMEMORY_EXAMPLE, true);
 
-    // Set it to never throw, this should have the same result as
-    // queryWithInMemoryClientNoDNSSEC, and serves to test the
-    // two proxy classes
     AuthSrv::InMemoryClientPtr fake_client(
         new FakeInMemoryClient(server.getInMemoryClient(rrclass),
                                throw_never,
@@ -1180,77 +1215,116 @@ TEST_F(AuthSrvTest, queryWithInMemoryClientProxy) {
                 opcode.getCode(), QR_FLAG | AA_FLAG, 1, 1, 2, 1);
 }
 
-// convenience function for setup
+// Convenience function for the rest of the tests, set up a proxy
+// to throw in the given method
+// If isc_exception is true, it will throw isc::Exception, otherwise
+// it will throw std::exception
 void
-setupThrowServfail(AuthSrv* server, ThrowWhen throw_when, bool isc_exception)
+setupThrow(AuthSrv* server, const char *config, ThrowWhen throw_when,
+                   bool isc_exception)
 {
     // Set real inmem client to proxy
-    updateConfig(server, CONFIG_INMEMORY_EXAMPLE, true);
+    updateConfig(server, config, true);
 
     // Set it to throw on findZone(), this should result in
     // SERVFAIL on any exception
     AuthSrv::InMemoryClientPtr fake_client(
-        new FakeInMemoryClient(server->getInMemoryClient(isc::dns::RRClass::IN()),
-                               throw_when,
-                               isc_exception));
+        new FakeInMemoryClient(
+            server->getInMemoryClient(isc::dns::RRClass::IN()),
+            throw_when,
+            isc_exception));
 
     ASSERT_NE(AuthSrv::InMemoryClientPtr(),
               server->getInMemoryClient(isc::dns::RRClass::IN()));
     server->setInMemoryClient(isc::dns::RRClass::IN(), fake_client);
 }
 
+// Throw isc::Exception at findZone(), should result in SERVFAIL
 TEST_F(AuthSrvTest, queryWithInMemoryClientProxyFindZone) {
     createDataFromFile("nsec3query_nodnssec_fromWire.wire");
 
-    setupThrowServfail(&server, throw_at_find_zone, true);
-    processAndCheckSERVFAIL(true);
+    setupThrow(&server, CONFIG_INMEMORY_EXAMPLE, throw_at_find_zone,
+                       true);
+    processAndCheckSERVFAIL();
 }
 
-/*
+// Throw std::exception at findZone(), should result in no answer
+TEST_F(AuthSrvTest, queryWithInMemoryClientProxyFindZoneStdException) {
+    createDataFromFile("nsec3query_nodnssec_fromWire.wire");
+
+    setupThrow(&server, CONFIG_INMEMORY_EXAMPLE, throw_at_find_zone,
+                       false);
+    EXPECT_FALSE(dnsserv.hasAnswer());
+}
+
+// Throw isc::Exception at getOrigin(), should result in SERVFAIL
 TEST_F(AuthSrvTest, queryWithInMemoryClientProxyGetOrigin) {
     createDataFromFile("nsec3query_nodnssec_fromWire.wire");
-    setupThrowServfail(&server, throw_at_get_origin, true);
-    processAndCheckSERVFAIL(true);
+    setupThrow(&server, CONFIG_INMEMORY_EXAMPLE, throw_at_get_origin,
+                       true);
+    processAndCheckSERVFAIL();
+}
+
+// Throw std::exception at findZone(), should result in SERVFAIL
+TEST_F(AuthSrvTest, queryWithInMemoryClientProxyGetOriginStdException) {
+    createDataFromFile("nsec3query_nodnssec_fromWire.wire");
+    setupThrow(&server, CONFIG_INMEMORY_EXAMPLE, throw_at_get_origin,
+                       true);
+    processAndCheckSERVFAIL();
 }
 
+// Throw isc::Exception in getClass(). (Currently?) getClass is not called
+// in the processMessage path, so this should result in a normal answer
 TEST_F(AuthSrvTest, queryWithInMemoryClientProxyGetClass) {
     createDataFromFile("nsec3query_nodnssec_fromWire.wire");
-    setupThrowServfail(&server, throw_at_get_class, true);
-    processAndCheckSERVFAIL(true);
+    setupThrow(&server, CONFIG_INMEMORY_EXAMPLE, throw_at_get_class,
+                       true);
+
+    // getClass is not called so it should just answer
+    server.processMessage(*io_message, parse_message, response_obuffer,
+                          &dnsserv);
+
+    EXPECT_TRUE(dnsserv.hasAnswer());
+    headerCheck(*parse_message, default_qid, Rcode::NOERROR(),
+                opcode.getCode(), QR_FLAG | AA_FLAG, 1, 1, 2, 1);
 }
-*/
 
+// Throw isc::Exception in find(), should result in SERVFAIL
 TEST_F(AuthSrvTest, queryWithInMemoryClientProxyFind) {
     createDataFromFile("nsec3query_nodnssec_fromWire.wire");
-    setupThrowServfail(&server, throw_at_find, true);
-    processAndCheckSERVFAIL(true);
+    setupThrow(&server, CONFIG_INMEMORY_EXAMPLE, throw_at_find,
+                       true);
+    processAndCheckSERVFAIL();
 }
 
-/*
+// Throw std::exception at find(), should result in no answer
 TEST_F(AuthSrvTest, queryWithInMemoryClientProxyFindStdException) {
     createDataFromFile("nsec3query_nodnssec_fromWire.wire");
-    setupThrowServfail(&server, throw_at_find, false);
-    processAndCheckSERVFAIL(true);
-}
-*/
-/*
-TEST_F(AuthSrvTest, queryWithInMemoryClientProxyFindAll) {
-    createDataFromFile("nsec3query_nodnssec_fromWire.wire");
-    setupThrowServfail(&server, throw_at_find_all, true);
-    processAndCheckSERVFAIL(true);
+    setupThrow(&server, CONFIG_INMEMORY_EXAMPLE, throw_at_find,
+                       false);
+    EXPECT_FALSE(dnsserv.hasAnswer());
 }
 
+// Throw isc::Exception in findNSEC3(), should result in SERVFAIL
 TEST_F(AuthSrvTest, queryWithInMemoryClientProxyFindNSEC3) {
-    createDataFromFile("nsec3query_nodnssec_fromWire.wire");
-    setupThrowServfail(&server, throw_at_find_nsec3, true);
-    processAndCheckSERVFAIL(true);
+    UnitTestUtil::createDNSSECRequestMessage(request_message, opcode,
+                                             default_qid, Name("foo.example."),
+                                             RRClass::IN(), RRType::TXT());
+    createRequestPacket(request_message, IPPROTO_UDP);
+    setupThrow(&server, CONFIG_INMEMORY_EXAMPLE, throw_at_find_nsec3,
+                       true);
+    processAndCheckSERVFAIL();
 }
 
-TEST_F(AuthSrvTest, queryWithInMemoryClientProxyFindPreviousName) {
-    createDataFromFile("nsec3query_nodnssec_fromWire.wire");
-    setupThrowServfail(&server, throw_at_find_previous_name, true);
-    processAndCheckSERVFAIL(true);
+// Throw std::exception at findNSEC3(), should result in no answer
+TEST_F(AuthSrvTest, queryWithInMemoryClientProxyFindNSEC3StdException) {
+    UnitTestUtil::createDNSSECRequestMessage(request_message, opcode,
+                                             default_qid, Name("foo.example."),
+                                             RRClass::IN(), RRType::TXT());
+    createRequestPacket(request_message, IPPROTO_UDP);
+    setupThrow(&server, CONFIG_INMEMORY_EXAMPLE, throw_at_find_nsec3,
+                       false);
+    EXPECT_FALSE(dnsserv.hasAnswer());
 }
-*/
 
 }

+ 18 - 0
src/lib/dns/tests/unittest_util.cc

@@ -191,3 +191,21 @@ UnitTestUtil::createRequestMessage(Message& message,
     message.addQuestion(Question(name, rrclass, rrtype));
 }
 
+void
+UnitTestUtil::createDNSSECRequestMessage(Message& message,
+                                         const Opcode& opcode,
+                                         const uint16_t qid,
+                                         const Name& name,
+                                         const RRClass& rrclass,
+                                         const RRType& rrtype)
+{
+    message.clear(Message::RENDER);
+    message.setOpcode(opcode);
+    message.setRcode(Rcode::NOERROR());
+    message.setQid(qid);
+    message.addQuestion(Question(name, rrclass, rrtype));
+    EDNSPtr edns(new EDNS());
+    edns->setUDPSize(4096);
+    edns->setDNSSECAwareness(true);
+    message.setEDNS(edns);
+}

+ 16 - 0
src/lib/dns/tests/unittest_util.h

@@ -93,6 +93,22 @@ public:
                          const isc::dns::Name& name,
                          const isc::dns::RRClass& rrclass,
                          const isc::dns::RRType& rrtype);
+
+    ///
+    /// Populate a DNSSEC request message
+    ///
+    /// Create a request message in 'request_message' using the
+    /// opcode 'opcode' and the name/class/type query tuple specified in
+    /// 'name', 'rrclass' and 'rrtype.
+    /// EDNS will be added with DO=1 and bufsize 4096
+    static void
+    createDNSSECRequestMessage(isc::dns::Message& request_message,
+                               const isc::dns::Opcode& opcode,
+                               const uint16_t qid,
+                               const isc::dns::Name& name,
+                               const isc::dns::RRClass& rrclass,
+                               const isc::dns::RRType& rrtype);
+
 };
 }
 #endif // __UNITTEST_UTIL_H