2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-08-30 21:45:37 +00:00

catch up to trunk

git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac470@4156 e5f2f494-b856-4b98-b285-d166d9295462
This commit is contained in:
Jeremy C. Reed
2011-01-04 18:40:58 +00:00
22 changed files with 705 additions and 365 deletions

View File

@@ -1,3 +1,7 @@
143. [build] jinmei
Fixed build problems with clang++ in unit tests due to recent
changes. No behavior change. (Trac #448, svn r4133)
142. [func] jinmei
b10-auth: updated query benchmark so that it can test in memory
data source. Also fixed a bug that the output buffer isn't

View File

@@ -597,6 +597,8 @@ AC_CONFIG_FILES([Makefile
src/lib/Makefile
src/lib/asiolink/Makefile
src/lib/asiolink/tests/Makefile
src/lib/asiolink/internal/Makefile
src/lib/asiolink/internal/tests/Makefile
src/lib/bench/Makefile
src/lib/bench/example/Makefile
src/lib/bench/tests/Makefile

View File

@@ -14,6 +14,7 @@
#include <dns/message.h>
#include <dns/rcode.h>
#include <dns/rdataclass.h>
#include <datasrc/memory_datasrc.h>
@@ -21,10 +22,51 @@
using namespace isc::dns;
using namespace isc::datasrc;
using namespace isc::dns::rdata;
namespace isc {
namespace auth {
void
Query::getAdditional(const isc::datasrc::Zone& zone,
const isc::dns::RRset& rrset) const
{
if (rrset.getType() == RRType::NS()) {
// Need to perform the search in the "GLUE OK" mode.
RdataIteratorPtr rdata_iterator = rrset.getRdataIterator();
for (; !rdata_iterator->isLast(); rdata_iterator->next()) {
const Rdata& rdata(rdata_iterator->getCurrent());
const generic::NS& ns = dynamic_cast<const generic::NS&>(rdata);
findAddrs(zone, ns.getNSName(), Zone::FIND_GLUE_OK);
}
}
}
void
Query::findAddrs(const isc::datasrc::Zone& zone,
const isc::dns::Name& qname,
const isc::datasrc::Zone::FindOptions options) const
{
// Out of zone name
NameComparisonResult result = zone.getOrigin().compare(qname);
if ((result.getRelation() != NameComparisonResult::SUPERDOMAIN) &&
(result.getRelation() != NameComparisonResult::EQUAL))
return;
// Find A rrset
Zone::FindResult a_result = zone.find(qname, RRType::A(), options);
if (a_result.code == Zone::SUCCESS) {
response_.addRRset(Message::SECTION_ADDITIONAL,
boost::const_pointer_cast<RRset>(a_result.rrset));
}
// Find AAAA rrset
Zone::FindResult aaaa_result = zone.find(qname, RRType::AAAA(), options);
if (aaaa_result.code == Zone::SUCCESS) {
response_.addRRset(Message::SECTION_ADDITIONAL,
boost::const_pointer_cast<RRset>(aaaa_result.rrset));
}
}
void
Query::putSOA(const Zone& zone) const {
Zone::FindResult soa_result(zone.find(zone.getOrigin(),
@@ -74,7 +116,11 @@ Query::process() const {
// TODO : fill in authority and addtional sections.
break;
case Zone::DELEGATION:
// TODO : add NS to authority section, fill in additional section.
response_.setHeaderFlag(Message::HEADERFLAG_AA, false);
response_.setRcode(Rcode::NOERROR());
response_.addRRset(Message::SECTION_AUTHORITY,
boost::const_pointer_cast<RRset>(db_result.rrset));
getAdditional(*result.zone, *db_result.rrset);
break;
case Zone::NXDOMAIN:
// Just empty answer with SOA in authority section

View File

@@ -15,17 +15,18 @@
*/
#include <exceptions/exceptions.h>
#include <datasrc/zone.h>
namespace isc {
namespace dns {
class Message;
class Name;
class RRType;
class RRset;
}
namespace datasrc {
class MemoryDataSrc;
class Zone;
}
namespace auth {
@@ -63,6 +64,48 @@ namespace auth {
/// accidentally, and since it's considered a temporary development state,
/// we keep this name at the moment.
class Query {
private:
/// \short Adds a SOA.
///
/// Adds a SOA of the zone into the authority zone of response_.
/// Can throw NoSOA.
///
void putSOA(const isc::datasrc::Zone& zone) const;
/// Look up additional data (i.e., address records for the names included
/// in NS or MX records).
///
/// This method may throw a exception because its underlying methods may
/// throw exceptions.
///
/// \param zone The Zone wherein the additional data to the query is bo be
/// found.
/// \param rrset The RRset (i.e., NS or MX rrset) which require additional
/// processing.
void getAdditional(const isc::datasrc::Zone& zone,
const isc::dns::RRset& rrset) const;
/// Find address records for a specified name.
///
/// Search the specified zone for AAAA/A RRs of each of the NS/MX RDATA
/// (domain name), and insert the found ones into the additional section
/// if address records are available. By default the search will stop
/// once it encounters a zone cut.
///
/// Note: we need to perform the search in the "GLUE OK" mode for NS RDATA,
/// which means that we should include A/AAAA RRs under a zone cut.
/// The glue records must exactly match the name in the NS RDATA, without
/// CNAME or wildcard processing.
///
/// \param zone The Zone wherein the address records is to be found.
/// \param qname The name in rrset RDATA.
/// \param options The search options.
void findAddrs(const isc::datasrc::Zone& zone,
const isc::dns::Name& qname,
const isc::datasrc::Zone::FindOptions options
= isc::datasrc::Zone::FIND_DEFAULT) const;
public:
/// Constructor from query parameters.
///
@@ -135,14 +178,6 @@ private:
const isc::dns::Name& qname_;
const isc::dns::RRType& qtype_;
isc::dns::Message& response_;
/**
* \short Adds a SOA.
*
* Adds a SOA of the zone into the authority zone of response_.
* Can throw NoSOA.
*/
void putSOA(const isc::datasrc::Zone& zone) const;
};
}

View File

@@ -33,6 +33,7 @@ run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
run_unittests_LDADD = $(GTEST_LDADD)
run_unittests_LDADD += $(SQLITE_LIBS)
run_unittests_LDADD += $(top_builddir)/src/lib/testutils/libtestutils.la
run_unittests_LDADD += $(top_builddir)/src/lib/datasrc/libdatasrc.la
run_unittests_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
run_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la

View File

@@ -30,15 +30,19 @@
#include <datasrc/memory_datasrc.h>
#include <auth/auth_srv.h>
#include <testutils/srv_unittest.h>
#include <auth/statistics.h>
#include <dns/tests/unittest_util.h>
#include <testutils/srv_test.h>
using namespace std;
using namespace isc::cc;
using namespace isc::dns;
using namespace isc::dns::rdata;
using namespace isc::data;
using namespace isc::xfr;
using namespace asiolink;
using namespace isc::testutils;
using isc::UnitTestUtil;
namespace {
@@ -55,6 +59,10 @@ protected:
server.setXfrinSession(&notify_session);
server.setStatisticsSession(&statistics_session);
}
virtual void processMessage() {
server.processMessage(*io_message, parse_message, response_obuffer,
&dnsserv);
}
MockSession statistics_session;
MockXfroutClient xfrout;
AuthSrv server;
@@ -159,48 +167,52 @@ TEST_F(AuthSrvTest, iqueryViaDNSServer) {
// Unsupported requests. Should result in NOTIMP.
TEST_F(AuthSrvTest, unsupportedRequest) {
UNSUPPORTED_REQUEST_TEST;
unsupportedRequest();
}
// Simple API check
TEST_F(AuthSrvTest, verbose) {
VERBOSE_TEST;
EXPECT_FALSE(server.getVerbose());
server.setVerbose(true);
EXPECT_TRUE(server.getVerbose());
server.setVerbose(false);
EXPECT_FALSE(server.getVerbose());
}
// Multiple questions. Should result in FORMERR.
TEST_F(AuthSrvTest, multiQuestion) {
MULTI_QUESTION_TEST;
multiQuestion();
}
// Incoming data doesn't even contain the complete header. Must be silently
// dropped.
TEST_F(AuthSrvTest, shortMessage) {
SHORT_MESSAGE_TEST;
shortMessage();
}
// Response messages. Must be silently dropped, whether it's a valid response
// or malformed or could otherwise cause a protocol error.
TEST_F(AuthSrvTest, response) {
RESPONSE_TEST;
response();
}
// Query with a broken question
TEST_F(AuthSrvTest, shortQuestion) {
SHORT_QUESTION_TEST;
shortQuestion();
}
// Query with a broken answer section
TEST_F(AuthSrvTest, shortAnswer) {
SHORT_ANSWER_TEST;
shortAnswer();
}
// Query with unsupported version of EDNS.
TEST_F(AuthSrvTest, ednsBadVers) {
EDNS_BADVERS_TEST;
ednsBadVers();
}
TEST_F(AuthSrvTest, AXFROverUDP) {
AXFR_OVER_UDP_TEST;
axfrOverUDP();
}
TEST_F(AuthSrvTest, AXFRSuccess) {

View File

@@ -17,6 +17,7 @@
#include <dns/rcode.h>
#include <dns/rrttl.h>
#include <dns/rrtype.h>
#include <dns/rdataclass.h>
#include <datasrc/memory_datasrc.h>
@@ -36,19 +37,48 @@ RRsetPtr a_rrset = RRsetPtr(new RRset(Name("www.example.com"),
RRsetPtr soa_rrset = RRsetPtr(new RRset(Name("example.com"),
RRClass::IN(), RRType::SOA(),
RRTTL(3600)));
RRsetPtr ns_rrset(RRsetPtr(new RRset(Name("ns.example.com"),
RRClass::IN(), RRType::NS(),
RRTTL(3600))));
RRsetPtr glue_a_rrset(RRsetPtr(new RRset(Name("glue.ns.example.com"),
RRClass::IN(), RRType::A(),
RRTTL(3600))));
RRsetPtr glue_aaaa_rrset(RRsetPtr(new RRset(Name("glue.ns.example.com"),
RRClass::IN(), RRType::AAAA(),
RRTTL(3600))));
RRsetPtr noglue_a_rrset(RRsetPtr(new RRset(Name("noglue.example.com"),
RRClass::IN(), RRType::A(),
RRTTL(3600))));
// This is a mock Zone class for testing.
// It is a derived class of Zone, and simply hardcode the results of find()
// return SUCCESS for "www.example.com",
// return NXDOMAIN for "nxdomain.example.com",
// return NXRRSET for "nxrrset.example.com",
// return CNAME for "cname.example.com",
// else return DNAME
// otherwise return DNAME
class MockZone : public Zone {
public:
MockZone(bool has_SOA = true) :
origin_(Name("example.com")),
has_SOA_(has_SOA)
{}
has_SOA_(has_SOA),
delegation_rrset(RRsetPtr(new RRset(Name("delegation.example.com"),
RRClass::IN(), RRType::NS(),
RRTTL(3600)))),
cname_rrset(RRsetPtr(new RRset(Name("cname.example.com"),
RRClass::IN(), RRType::CNAME(),
RRTTL(3600))))
{
delegation_rrset->addRdata(rdata::generic::NS(
Name("glue.ns.example.com")));
delegation_rrset->addRdata(rdata::generic::NS(
Name("noglue.example.com")));
delegation_rrset->addRdata(rdata::generic::NS(
Name("cname.example.com")));
delegation_rrset->addRdata(rdata::generic::NS(
Name("example.org")));
cname_rrset->addRdata(rdata::generic::CNAME(
Name("www.example.com")));
}
virtual const isc::dns::Name& getOrigin() const;
virtual const isc::dns::RRClass& getClass() const;
@@ -59,6 +89,8 @@ public:
private:
Name origin_;
bool has_SOA_;
RRsetPtr delegation_rrset;
RRsetPtr cname_rrset;
};
const Name&
@@ -72,22 +104,34 @@ MockZone::getClass() const {
}
Zone::FindResult
MockZone::find(const Name& name, const RRType& type, const FindOptions) const {
MockZone::find(const Name& name, const RRType& type,
const FindOptions options) const
{
// hardcode the find results
if (name == Name("www.example.com")) {
return (FindResult(SUCCESS, a_rrset));
} else if (name == Name("glue.ns.example.com") && type == RRType::A() &&
options == FIND_GLUE_OK) {
return (FindResult(SUCCESS, glue_a_rrset));
} else if (name == Name("noglue.example.com") && type == RRType::A()) {
return (FindResult(SUCCESS, noglue_a_rrset));
} else if (name == Name("glue.ns.example.com") && type == RRType::AAAA() &&
options == FIND_GLUE_OK) {
return (FindResult(SUCCESS, glue_aaaa_rrset));
} else if (name == Name("example.com") && type == RRType::SOA() &&
has_SOA_)
{
return (FindResult(SUCCESS, soa_rrset));
} else if (name == Name("delegation.example.com")) {
return (FindResult(DELEGATION, RRsetPtr()));
return (FindResult(DELEGATION, delegation_rrset));
} else if (name == Name("ns.example.com")) {
return (FindResult(DELEGATION, ns_rrset));
} else if (name == Name("nxdomain.example.com")) {
return (FindResult(NXDOMAIN, RRsetPtr()));
} else if (name == Name("nxrrset.example.com")) {
return (FindResult(NXRRSET, RRsetPtr()));
} else if (name == Name("cname.example.com")) {
return (FindResult(CNAME, RRsetPtr()));
} else if ((name == Name("cname.example.com"))) {
return (FindResult(CNAME, cname_rrset));
} else {
return (FindResult(DNAME, RRsetPtr()));
}
@@ -121,11 +165,41 @@ TEST_F(QueryTest, matchZone) {
// add a matching zone.
memory_datasrc.addZone(ZonePtr(new MockZone()));
query.process();
EXPECT_TRUE(response.getHeaderFlag(Message::HEADERFLAG_AA));
EXPECT_EQ(Rcode::NOERROR(), response.getRcode());
EXPECT_TRUE(response.hasRRset(Message::SECTION_ANSWER,
Name("www.example.com"), RRClass::IN(),
RRType::A()));
// Delegation
const Name delegation_name(Name("delegation.example.com"));
Query delegation_query(memory_datasrc, delegation_name, qtype, response);
delegation_query.process();
EXPECT_FALSE(response.getHeaderFlag(Message::HEADERFLAG_AA));
EXPECT_EQ(Rcode::NOERROR(), response.getRcode());
EXPECT_TRUE(response.hasRRset(Message::SECTION_AUTHORITY,
Name("delegation.example.com"),
RRClass::IN(), RRType::NS()));
// glue address records
EXPECT_TRUE(response.hasRRset(Message::SECTION_ADDITIONAL,
Name("glue.ns.example.com"),
RRClass::IN(), RRType::A()));
EXPECT_TRUE(response.hasRRset(Message::SECTION_ADDITIONAL,
Name("glue.ns.example.com"),
RRClass::IN(), RRType::AAAA()));
// noglue address records
EXPECT_TRUE(response.hasRRset(Message::SECTION_ADDITIONAL,
Name("noglue.example.com"),
RRClass::IN(), RRType::A()));
// NS name has a CNAME
EXPECT_FALSE(response.hasRRset(Message::SECTION_ADDITIONAL,
Name("www.example.com"),
RRClass::IN(), RRType::A()));
// NS name is out of zone
EXPECT_FALSE(response.hasRRset(Message::SECTION_ADDITIONAL,
Name("example.org"),
RRClass::IN(), RRType::A()));
// NXDOMAIN
const Name nxdomain_name(Name("nxdomain.example.com"));
Query nxdomain_query(memory_datasrc, nxdomain_name, qtype, response);

View File

@@ -1,4 +1,4 @@
SUBDIRS = . tests
SUBDIRS = . tests internal
AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
AM_CPPFLAGS += $(BOOST_INCLUDES)

View File

@@ -0,0 +1 @@
SUBDIRS = tests

View File

@@ -0,0 +1,37 @@
AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
AM_CPPFLAGS += $(BOOST_INCLUDES)
AM_CXXFLAGS = $(B10_CXXFLAGS)
if USE_STATIC_LINK
AM_LDFLAGS = -static
endif
CLEANFILES = *.gcno *.gcda
TESTS =
if HAVE_GTEST
TESTS += run_unittests
run_unittests_SOURCES = udpdns_unittest.cc
run_unittests_SOURCES += run_unittests.cc
run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
run_unittests_LDADD = $(GTEST_LDADD)
run_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
run_unittests_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
run_unittests_LDADD += $(top_builddir)/src/lib/log/liblog.la
# Note: the ordering matters: -Wno-... must follow -Wextra (defined in
# B10_CXXFLAGS)
run_unittests_CXXFLAGS = $(AM_CXXFLAGS)
if USE_GXX
run_unittests_CXXFLAGS += -Wno-unused-parameter
endif
if USE_CLANGPP
# We need to disable -Werror for any test that uses internal definitions of
# ASIO when using clang++
run_unittests_CXXFLAGS += -Wno-error
endif
endif
noinst_PROGRAMS = $(TESTS)

View File

@@ -0,0 +1,21 @@
// Copyright (C) 2010 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.
#include <gtest/gtest.h>
int
main(int argc, char* argv[]) {
::testing::InitGoogleTest(&argc, argv);
return (RUN_ALL_TESTS());
}

View File

@@ -18,7 +18,6 @@ TESTS += run_unittests
run_unittests_SOURCES = $(top_srcdir)/src/lib/dns/tests/unittest_util.h
run_unittests_SOURCES += $(top_srcdir)/src/lib/dns/tests/unittest_util.cc
run_unittests_SOURCES += asiolink_unittest.cc
run_unittests_SOURCES += udpdns_unittest.cc
run_unittests_SOURCES += run_unittests.cc
run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)

View File

@@ -17,6 +17,9 @@
#include <config.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <string.h>
#include <boost/lexical_cast.hpp>
@@ -32,19 +35,21 @@
#include <dns/buffer.h>
#include <dns/message.h>
// IMPORTANT: We shouldn't directly use ASIO definitions in this test.
// In particular, we must not include asio.hpp in this file.
// The asiolink module is primarily intended to be a wrapper that hide the
// details of the underlying implementations. We need to test the wrapper
// level behaviors. In addition, some compilers reject to compile this file
// if we include asio.hpp unless we specify a special compiler option.
// If we need to test something at the level of underlying ASIO and need
// their definition, that test should go to asiolink/internal/tests.
#include <asiolink/asiolink.h>
#include <asiolink/iosocket.h>
#include <asiolink/internal/tcpdns.h>
#include <asiolink/internal/udpdns.h>
#include <asio.hpp>
using isc::UnitTestUtil;
using namespace std;
using namespace asiolink;
using namespace isc::dns;
using namespace asio;
using asio::ip::udp;
namespace {
const char* const TEST_SERVER_PORT = "53535";
@@ -330,10 +335,30 @@ protected:
// ... and this one will block until the send has completed
io_service_->run_one();
// Now we attempt to recv() whatever was sent
const int ret = recv(sock_, buffer, size, MSG_DONTWAIT);
// Now we attempt to recv() whatever was sent.
// XXX: there's no guarantee the receiving socket can immediately get
// the packet. Normally we can perform blocking recv to wait for it,
// but in theory it's even possible that the packet is lost.
// In order to prevent the test from hanging in such a worst case
// we add an ad hoc timeout.
const struct timeval timeo = { 10, 0 };
int recv_options = 0;
if (setsockopt(sock_, SOL_SOCKET, SO_RCVTIMEO, &timeo,
sizeof(timeo))) {
if (errno == ENOPROTOOPT) {
// Workaround for Solaris: it doesn't accept SO_RCVTIMEO
// with the error of ENOPROTOOPT. Since this is a workaround
// for rare error cases anyway, we simply switch to the
// "don't wait" mode. If we still find an error in recv()
// can happen often we'll consider a more complete solution.
recv_options = MSG_DONTWAIT;
} else {
isc_throw(IOError, "set RCVTIMEO failed: " << strerror(errno));
}
}
const int ret = recv(sock_, buffer, size, recv_options);
if (ret < 0) {
isc_throw(IOError, "recvfrom failed");
isc_throw(IOError, "recvfrom failed: " << strerror(errno));
}
// Pass the message size back via the size parameter
@@ -411,8 +436,7 @@ protected:
// has completed.
class MockServer : public DNSServer {
public:
explicit MockServer(asio::io_service& io_service,
const asio::ip::address& addr, const uint16_t port,
explicit MockServer(IOService& io_service,
SimpleCallback* checkin = NULL,
DNSLookup* lookup = NULL,
DNSAnswer* answer = NULL) :
@@ -426,9 +450,7 @@ protected:
size_t length = 0)
{}
void resume(const bool done) {
done_ = done;
io_.post(*this);
void resume(const bool) { // in our test this shouldn't be called
}
DNSServer* clone() {
@@ -443,7 +465,7 @@ protected:
}
protected:
asio::io_service& io_;
IOService& io_;
bool done_;
private:
@@ -462,8 +484,8 @@ protected:
// This version of mock server just stops the io_service when it is resumed
class MockServerStop : public MockServer {
public:
explicit MockServerStop(asio::io_service& io_service, bool* done) :
MockServer(io_service, asio::ip::address(), 0),
explicit MockServerStop(IOService& io_service, bool* done) :
MockServer(io_service),
done_(done)
{}
@@ -511,7 +533,6 @@ protected:
string callback_address_;
vector<uint8_t> callback_data_;
int sock_;
private:
struct addrinfo* res_;
};
@@ -640,14 +661,12 @@ TEST_F(ASIOLinkTest, recursiveSetupV6) {
// full code coverage including error cases.
TEST_F(ASIOLinkTest, recursiveSend) {
setDNSService(true, false);
asio::io_service& io = io_service_->get_io_service();
// Note: We use the test prot plus one to ensure we aren't binding
// to the same port as the actual server
uint16_t port = boost::lexical_cast<uint16_t>(TEST_CLIENT_PORT);
asio::ip::address addr = asio::ip::address::from_string(TEST_IPV4_ADDR);
MockServer server(io, addr, port, NULL, NULL, NULL);
MockServer server(*io_service_);
RecursiveQuery rq(*dns_service_, singleAddress(TEST_IPV4_ADDR, port));
Question q(Name("example.com"), RRClass::IN(), RRType::TXT());
@@ -656,7 +675,7 @@ TEST_F(ASIOLinkTest, recursiveSend) {
char data[4096];
size_t size = sizeof(data);
EXPECT_NO_THROW(recvUDP(AF_INET, data, size));
ASSERT_NO_THROW(recvUDP(AF_INET, data, size));
Message m(Message::PARSE);
InputBuffer ibuf(data, size);
@@ -672,34 +691,27 @@ TEST_F(ASIOLinkTest, recursiveSend) {
EXPECT_EQ(q.getClass(), q2->getClass());
}
void
receive_and_inc(udp::socket* socket, int* num) {
(*num) ++;
static char inbuff[512];
socket->async_receive(asio::buffer(inbuff, 512),
boost::bind(receive_and_inc, socket, num));
}
// Test it tries the correct amount of times before giving up
TEST_F(ASIOLinkTest, recursiveTimeout) {
// Prepare the service (we do not use the common setup, we do not answer
setDNSService();
asio::io_service& service = io_service_->get_io_service();
// Prepare the socket
uint16_t port = boost::lexical_cast<uint16_t>(TEST_CLIENT_PORT);
udp::socket socket(service, udp::v4());
socket.set_option(socket_base::reuse_address(true));
socket.bind(udp::endpoint(ip::address::from_string(TEST_IPV4_ADDR), port));
// And count the answers
int num = -1; // One is counted before the receipt of the first one
receive_and_inc(&socket, &num);
res_ = resolveAddress(AF_INET, IPPROTO_UDP, true);
sock_ = socket(res_->ai_family, res_->ai_socktype, res_->ai_protocol);
if (sock_ < 0) {
isc_throw(IOError, "failed to open test socket");
}
if (bind(sock_, res_->ai_addr, res_->ai_addrlen) < 0) {
isc_throw(IOError, "failed to bind test socket");
}
// Prepare the server
bool done(true);
MockServerStop server(service, &done);
MockServerStop server(*io_service_, &done);
// Do the answer
const uint16_t port = boost::lexical_cast<uint16_t>(TEST_CLIENT_PORT);
RecursiveQuery query(*dns_service_, singleAddress(TEST_IPV4_ADDR, port),
10, 2);
Question question(Name("example.net"), RRClass::IN(), RRType::A());
@@ -707,7 +719,27 @@ TEST_F(ASIOLinkTest, recursiveTimeout) {
query.sendQuery(question, buffer, &server);
// Run the test
service.run();
io_service_->run();
// Read up to 3 packets. Use some ad hoc timeout to prevent an infinite
// block (see also recvUDP()).
const struct timeval timeo = { 10, 0 };
int recv_options = 0;
if (setsockopt(sock_, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo))) {
if (errno == ENOPROTOOPT) { // see ASIOLinkTest::recvUDP()
recv_options = MSG_DONTWAIT;
} else {
isc_throw(IOError, "set RCVTIMEO failed: " << strerror(errno));
}
}
int num = 0;
do {
char inbuff[512];
if (recv(sock_, inbuff, sizeof(inbuff), recv_options) < 0) {
num = -1;
break;
}
} while (++num < 3);
// The query should fail
EXPECT_FALSE(done);

View File

@@ -81,7 +81,7 @@ class HotCacheImpl;
/// from the tail of the list. This operation is not locked. BIND 10
/// does not currently use threads, but if it ever does (or if libdatasrc
/// is ever used by a threaded application), this will need to be
//revisited.
/// revisited.
class HotCache {
private:
/// \name Static definitions
@@ -164,7 +164,7 @@ public:
///
/// Retrieves a record from the cache matching the given
/// query-tuple. Returns true if one is found. If it is a
/// posiitve cache entry, then 'rrset' is set to the cached
/// positive cache entry, then 'rrset' is set to the cached
/// RRset. For both positive and negative cache entries, 'flags'
/// is set to the query response flags. The cache entry is
/// then promoted to the head of the LRU queue. (NOTE: Because

View File

@@ -103,14 +103,14 @@ getAdditional(Query& q, ConstRRsetPtr rrset) {
new QueryTask(q, ns.getNSName(),
Message::SECTION_ADDITIONAL,
QueryTask::GLUE_QUERY,
QueryTask::GETADDITIONAL)));
QueryTask::GETADDITIONAL)));
} else if (rrset->getType() == RRType::MX()) {
const generic::MX& mx = dynamic_cast<const generic::MX&>(rd);
q.tasks().push(QueryTaskPtr(
new QueryTask(q, mx.getMXName(),
Message::SECTION_ADDITIONAL,
QueryTask::NOGLUE_QUERY,
QueryTask::GETADDITIONAL)));
QueryTask::GETADDITIONAL)));
}
}
}

View File

@@ -672,7 +672,7 @@ void
RBTree<T>::nodeFission(RBNode<T>& node, const isc::dns::Name& base_name) {
using namespace helper;
const isc::dns::Name sub_name = node.name_ - base_name;
// using auto_ptr here is to avoid memory leak in case of exceptoin raised
// using auto_ptr here is to avoid memory leak in case of exception raised
// after the RBNode creation
std::auto_ptr<RBNode<T> > down_node(new RBNode<T>(sub_name));
std::swap(node.data_, down_node->data_);
@@ -680,7 +680,7 @@ RBTree<T>::nodeFission(RBNode<T>& node, const isc::dns::Name& base_name) {
down_node->down_ = node.down_;
node.name_ = base_name;
node.down_ = down_node.get();
//root node of sub tree, the initial color is BLACK
// root node of sub tree, the initial color is BLACK
down_node->color_ = RBNode<T>::BLACK;
++node_count_;
down_node.release();

View File

@@ -1,5 +1,13 @@
SUBDIRS = testdata
SUBDIRS = . testdata
EXTRA_DIST = srv_test.h
EXTRA_DIST += srv_unittest.h
EXTRA_DIST += mockups.h
AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
AM_CPPFLAGS += $(BOOST_INCLUDES)
AM_CXXFLAGS=$(B10_CXXFLAGS)
if HAVE_GTEST
lib_LTLIBRARIES = libtestutils.la
libtestutils_la_SOURCES = srv_test.h srv_test.cc
libtestutils_la_SOURCES += mockups.h
libtestutils_la_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
endif

View File

@@ -1,4 +1,2 @@
Here is some code used by more than one test. No code is used for bind10
itself, only for testing.
As it contains headers only currently, it does not compile here.

View File

@@ -0,0 +1,272 @@
// Copyright (C) 2010 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.
#include <netinet/in.h>
#include <dns/message.h>
#include <dns/rcode.h>
#include <asiolink/asiolink.h>
#include <dns/tests/unittest_util.h>
#include <testutils/srv_test.h>
using namespace isc::dns;
using namespace asiolink;
namespace isc {
namespace testutils {
const char* const DEFAULT_REMOTE_ADDRESS = "192.0.2.1";
const unsigned int QR_FLAG = 0x1;
const unsigned int AA_FLAG = 0x2;
const unsigned int TC_FLAG = 0x4;
const unsigned int RD_FLAG = 0x8;
const unsigned int RA_FLAG = 0x10;
const unsigned int AD_FLAG = 0x20;
const unsigned int CD_FLAG = 0x40;
SrvTestBase::SrvTestBase() : request_message(Message::RENDER),
parse_message(new Message(Message::PARSE)),
default_qid(0x1035),
opcode(Opcode(Opcode::QUERY())),
qname("www.example.com"),
qclass(RRClass::IN()),
qtype(RRType::A()), io_sock(NULL),
io_message(NULL), endpoint(NULL),
request_obuffer(0),
request_renderer(request_obuffer),
response_obuffer(new OutputBuffer(0))
{}
SrvTestBase::~SrvTestBase() {
delete io_message;
delete endpoint;
}
void
SrvTestBase::createDataFromFile(const char* const datafile,
const int protocol)
{
delete io_message;
data.clear();
delete endpoint;
endpoint = IOEndpoint::create(protocol,
IOAddress(DEFAULT_REMOTE_ADDRESS), 5300);
UnitTestUtil::readWireData(datafile, data);
io_sock = (protocol == IPPROTO_UDP) ? &IOSocket::getDummyUDPSocket() :
&IOSocket::getDummyTCPSocket();
io_message = new IOMessage(&data[0], data.size(), *io_sock, *endpoint);
}
void
SrvTestBase::createRequestPacket(Message& message,
const int protocol)
{
message.toWire(request_renderer);
delete io_message;
endpoint = IOEndpoint::create(protocol,
IOAddress(DEFAULT_REMOTE_ADDRESS), 5300);
io_sock = (protocol == IPPROTO_UDP) ? &IOSocket::getDummyUDPSocket() :
&IOSocket::getDummyTCPSocket();
io_message = new IOMessage(request_renderer.getData(),
request_renderer.getLength(),
*io_sock, *endpoint);
}
// Unsupported requests. Should result in NOTIMP.
void
SrvTestBase::unsupportedRequest() {
for (unsigned int i = 0; i < 16; ++i) {
// set Opcode to 'i', which iterators over all possible codes except
// the standard query and notify
if (i == isc::dns::Opcode::QUERY().getCode() ||
i == isc::dns::Opcode::NOTIFY().getCode()) {
continue;
}
createDataFromFile("simplequery_fromWire.wire");
data[2] = ((i << 3) & 0xff);
parse_message->clear(isc::dns::Message::PARSE);
processMessage();
EXPECT_TRUE(dnsserv.hasAnswer());
headerCheck(*parse_message, default_qid, isc::dns::Rcode::NOTIMP(), i,
QR_FLAG, 0, 0, 0, 0);
}
}
// Multiple questions. Should result in FORMERR.
void
SrvTestBase::multiQuestion() {
createDataFromFile("multiquestion_fromWire.wire");
processMessage();
EXPECT_TRUE(dnsserv.hasAnswer());
headerCheck(*parse_message, default_qid, isc::dns::Rcode::FORMERR(),
opcode.getCode(), QR_FLAG, 2, 0, 0, 0);
isc::dns::QuestionIterator qit = parse_message->beginQuestion();
EXPECT_EQ(isc::dns::Name("example.com"), (*qit)->getName());
EXPECT_EQ(isc::dns::RRClass::IN(), (*qit)->getClass());
EXPECT_EQ(isc::dns::RRType::A(), (*qit)->getType());
++qit;
EXPECT_EQ(isc::dns::Name("example.com"), (*qit)->getName());
EXPECT_EQ(isc::dns::RRClass::IN(), (*qit)->getClass());
EXPECT_EQ(isc::dns::RRType::AAAA(), (*qit)->getType());
++qit;
EXPECT_TRUE(qit == parse_message->endQuestion());
}
// Incoming data doesn't even contain the complete header. Must be silently
// dropped.
void
SrvTestBase::shortMessage() {
createDataFromFile("shortmessage_fromWire");
processMessage();
EXPECT_FALSE(dnsserv.hasAnswer());
}
// Response messages. Must be silently dropped, whether it's a valid response
// or malformed or could otherwise cause a protocol error.
void
SrvTestBase::response() {
// A valid (although unusual) response
createDataFromFile("simpleresponse_fromWire.wire");
processMessage();
EXPECT_FALSE(dnsserv.hasAnswer());
// A response with a broken question section. must be dropped rather than
//returning FORMERR.
createDataFromFile("shortresponse_fromWire");
processMessage();
EXPECT_FALSE(dnsserv.hasAnswer());
// A response to iquery. must be dropped rather than returning NOTIMP.
createDataFromFile("iqueryresponse_fromWire.wire");
processMessage();
EXPECT_FALSE(dnsserv.hasAnswer());
}
// Query with a broken question
void
SrvTestBase::shortQuestion() {
createDataFromFile("shortquestion_fromWire");
processMessage();
EXPECT_TRUE(dnsserv.hasAnswer());
// Since the query's question is broken, the question section of the
// response should be empty.
headerCheck(*parse_message, default_qid, isc::dns::Rcode::FORMERR(),
opcode.getCode(), QR_FLAG, 0, 0, 0, 0);
}
// Query with a broken answer section
void
SrvTestBase::shortAnswer() {
createDataFromFile("shortanswer_fromWire.wire");
processMessage();
EXPECT_TRUE(dnsserv.hasAnswer());
// This is a bogus query, but question section is valid. So the response
// should copy the question section.
headerCheck(*parse_message, default_qid, isc::dns::Rcode::FORMERR(),
opcode.getCode(), QR_FLAG, 1, 0, 0, 0);
isc::dns::QuestionIterator qit = parse_message->beginQuestion();
EXPECT_EQ(isc::dns::Name("example.com"), (*qit)->getName());
EXPECT_EQ(isc::dns::RRClass::IN(), (*qit)->getClass());
EXPECT_EQ(isc::dns::RRType::A(), (*qit)->getType());
++qit;
EXPECT_TRUE(qit == parse_message->endQuestion());
}
// Query with unsupported version of EDNS.
void
SrvTestBase::ednsBadVers() {
createDataFromFile("queryBadEDNS_fromWire.wire");
processMessage();
EXPECT_TRUE(dnsserv.hasAnswer());
// The response must have an EDNS OPT RR in the additional section,
// it will be added automatically at the render time.
// Note that the DNSSEC DO bit is cleared even if this bit in the query
// is set. This is a limitation of the current implementation.
headerCheck(*parse_message, default_qid, isc::dns::Rcode::BADVERS(),
opcode.getCode(), QR_FLAG, 1, 0, 0, 1);
EXPECT_FALSE(parse_message->getEDNS()); // EDNS isn't added at this point
isc::dns::InputBuffer ib(response_obuffer->getData(),
response_obuffer->getLength());
isc::dns::Message parsed(isc::dns::Message::PARSE);
parsed.fromWire(ib);
EXPECT_EQ(isc::dns::Rcode::BADVERS(), parsed.getRcode());
isc::dns::ConstEDNSPtr edns(parsed.getEDNS());
ASSERT_TRUE(edns);
EXPECT_FALSE(edns->getDNSSECAwareness());
}
void
SrvTestBase::axfrOverUDP() {
// AXFR over UDP is invalid and should result in FORMERR.
UnitTestUtil::createRequestMessage(request_message, opcode, default_qid,
isc::dns::Name("example.com"),
isc::dns::RRClass::IN(),
isc::dns::RRType::AXFR());
createRequestPacket(request_message, IPPROTO_UDP);
processMessage();
EXPECT_TRUE(dnsserv.hasAnswer());
headerCheck(*parse_message, default_qid, isc::dns::Rcode::FORMERR(),
opcode.getCode(), QR_FLAG, 1, 0, 0, 0);
}
void
headerCheck(const Message& message, const qid_t qid, const Rcode& rcode,
const uint16_t opcodeval, const unsigned int flags,
const unsigned int qdcount,
const unsigned int ancount, const unsigned int nscount,
const unsigned int arcount)
{
EXPECT_EQ(qid, message.getQid());
EXPECT_EQ(rcode, message.getRcode());
EXPECT_EQ(opcodeval, message.getOpcode().getCode());
EXPECT_EQ((flags & QR_FLAG) != 0,
message.getHeaderFlag(Message::HEADERFLAG_QR));
EXPECT_EQ((flags & AA_FLAG) != 0,
message.getHeaderFlag(Message::HEADERFLAG_AA));
EXPECT_EQ((flags & TC_FLAG) != 0,
message.getHeaderFlag(Message::HEADERFLAG_TC));
EXPECT_EQ((flags & RA_FLAG) != 0,
message.getHeaderFlag(Message::HEADERFLAG_RA));
EXPECT_EQ((flags & RD_FLAG) != 0,
message.getHeaderFlag(Message::HEADERFLAG_RD));
EXPECT_EQ((flags & AD_FLAG) != 0,
message.getHeaderFlag(Message::HEADERFLAG_AD));
EXPECT_EQ((flags & CD_FLAG) != 0,
message.getHeaderFlag(Message::HEADERFLAG_CD));
EXPECT_EQ(qdcount, message.getRRCount(Message::SECTION_QUESTION));
EXPECT_EQ(ancount, message.getRRCount(Message::SECTION_ANSWER));
EXPECT_EQ(nscount, message.getRRCount(Message::SECTION_AUTHORITY));
EXPECT_EQ(arcount, message.getRRCount(Message::SECTION_ADDITIONAL));
}
} // end of namespace testutils
} // end of namespace isc
// Local Variables:
// mode: c++
// End:

View File

@@ -12,10 +12,6 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
// $Id: auth_srv_unittest.cc 3310 2010-10-21 23:10:24Z each $
#include <config.h>
#include <gtest/gtest.h>
#include <dns/buffer.h>
@@ -27,139 +23,99 @@
#include <dns/rrclass.h>
#include <dns/rrtype.h>
#include <cc/data.h>
#include <cc/session.h>
#include <xfr/xfrout_client.h>
#include <auth/auth_srv.h>
#include <asiolink/asiolink.h>
#include <dns/tests/unittest_util.h>
#include "mockups.h"
using namespace std;
using namespace isc::cc;
using namespace isc::dns;
using namespace isc::data;
using namespace isc::xfr;
using namespace asiolink;
using isc::UnitTestUtil;
namespace {
const char* const DEFAULT_REMOTE_ADDRESS = "192.0.2.1";
// The base class for Auth and Resolver test case
class SrvTestBase : public ::testing::Test {
protected:
SrvTestBase() : request_message(Message::RENDER),
parse_message(new Message(Message::PARSE)),
default_qid(0x1035), opcode(Opcode(Opcode::QUERY())),
qname("www.example.com"), qclass(RRClass::IN()),
qtype(RRType::A()), io_sock(NULL),
io_message(NULL), endpoint(NULL),
request_obuffer(0), request_renderer(request_obuffer),
response_obuffer(new OutputBuffer(0))
{}
~SrvTestBase() {
delete io_message;
delete endpoint;
}
MockSession notify_session;
MockServer dnsserv;
Message request_message;
MessagePtr parse_message;
const qid_t default_qid;
const Opcode opcode;
const Name qname;
const RRClass qclass;
const RRType qtype;
IOSocket* io_sock;
IOMessage* io_message;
const IOEndpoint* endpoint;
OutputBuffer request_obuffer;
MessageRenderer request_renderer;
OutputBufferPtr response_obuffer;
vector<uint8_t> data;
void createDataFromFile(const char* const datafile, int protocol);
void createRequestPacket(Message& message, const int protocol);
};
void
SrvTestBase::createDataFromFile(const char* const datafile,
const int protocol = IPPROTO_UDP)
{
delete io_message;
data.clear();
delete endpoint;
endpoint = IOEndpoint::create(protocol,
IOAddress(DEFAULT_REMOTE_ADDRESS), 5300);
UnitTestUtil::readWireData(datafile, data);
io_sock = (protocol == IPPROTO_UDP) ? &IOSocket::getDummyUDPSocket() :
&IOSocket::getDummyTCPSocket();
io_message = new IOMessage(&data[0], data.size(), *io_sock, *endpoint);
namespace asiolink {
class IOSocket;
class IOMessage;
class IOEndpoint;
}
void
SrvTestBase::createRequestPacket(Message& message,
const int protocol = IPPROTO_UDP)
{
message.toWire(request_renderer);
delete io_message;
endpoint = IOEndpoint::create(protocol,
IOAddress(DEFAULT_REMOTE_ADDRESS), 5300);
io_sock = (protocol == IPPROTO_UDP) ? &IOSocket::getDummyUDPSocket() :
&IOSocket::getDummyTCPSocket();
io_message = new IOMessage(request_renderer.getData(),
request_renderer.getLength(),
*io_sock, *endpoint);
}
namespace isc {
namespace testutils {
extern const char* const DEFAULT_REMOTE_ADDRESS;
// These are flags to indicate whether the corresponding flag bit of the
// DNS header is to be set in the test cases. (Note that the flag values
// DNS header is to be set in the test cases. (The flag values
// is irrelevant to their wire-format values)
const unsigned int QR_FLAG = 0x1;
const unsigned int AA_FLAG = 0x2;
const unsigned int TC_FLAG = 0x4;
const unsigned int RD_FLAG = 0x8;
const unsigned int RA_FLAG = 0x10;
const unsigned int AD_FLAG = 0x20;
const unsigned int CD_FLAG = 0x40;
extern const unsigned int QR_FLAG;
extern const unsigned int AA_FLAG;
extern const unsigned int TC_FLAG;
extern const unsigned int RD_FLAG;
extern const unsigned int RA_FLAG;
extern const unsigned int AD_FLAG;
extern const unsigned int CD_FLAG;
void
headerCheck(const Message& message, const qid_t qid, const Rcode& rcode,
headerCheck(const isc::dns::Message& message, const isc::dns::qid_t qid,
const isc::dns::Rcode& rcode,
const uint16_t opcodeval, const unsigned int flags,
const unsigned int qdcount,
const unsigned int ancount, const unsigned int nscount,
const unsigned int arcount)
{
EXPECT_EQ(qid, message.getQid());
EXPECT_EQ(rcode, message.getRcode());
EXPECT_EQ(opcodeval, message.getOpcode().getCode());
EXPECT_EQ((flags & QR_FLAG) != 0,
message.getHeaderFlag(Message::HEADERFLAG_QR));
EXPECT_EQ((flags & AA_FLAG) != 0,
message.getHeaderFlag(Message::HEADERFLAG_AA));
EXPECT_EQ((flags & TC_FLAG) != 0,
message.getHeaderFlag(Message::HEADERFLAG_TC));
EXPECT_EQ((flags & RA_FLAG) != 0,
message.getHeaderFlag(Message::HEADERFLAG_RA));
EXPECT_EQ((flags & RD_FLAG) != 0,
message.getHeaderFlag(Message::HEADERFLAG_RD));
EXPECT_EQ((flags & AD_FLAG) != 0,
message.getHeaderFlag(Message::HEADERFLAG_AD));
EXPECT_EQ((flags & CD_FLAG) != 0,
message.getHeaderFlag(Message::HEADERFLAG_CD));
const unsigned int arcount);
EXPECT_EQ(qdcount, message.getRRCount(Message::SECTION_QUESTION));
EXPECT_EQ(ancount, message.getRRCount(Message::SECTION_ANSWER));
EXPECT_EQ(nscount, message.getRRCount(Message::SECTION_AUTHORITY));
EXPECT_EQ(arcount, message.getRRCount(Message::SECTION_ADDITIONAL));
}
// The base class for Auth and Recurse test case
class SrvTestBase : public ::testing::Test {
protected:
SrvTestBase();
virtual ~SrvTestBase();
}
/// Let the server process a DNS message.
///
/// The derived class implementation is expected to pass \c io_message,
/// \c parse_message, \c response_obuffer, and \c dnsserv to the server
/// implementation it is testing.
virtual void processMessage() = 0;
/// The following methods implement server independent test logic using
/// the template method pattern. Each test calls \c processMessage()
/// to delegate the server-dependent behavior to the actual implementation
/// classes.
void unsupportedRequest();
void multiQuestion();
void shortMessage();
void response();
void shortQuestion();
void shortAnswer();
void ednsBadVers();
void axfrOverUDP();
/// Create DNS packet data from a file.
///
/// It constructs wire-format DNS packet data from \c datafile in the
/// form of \c IOMessage in \c io_message.
/// The existing content of \c io_message, if any, will be deleted.
void createDataFromFile(const char* const datafile,
int protocol = IPPROTO_UDP);
/// Create DNS packet data from a message.
///
/// It constructs wire-format DNS packet data from \c message in the
/// form of \c IOMessage in \c io_message.
/// The existing content of \c io_message, if any, will be deleted.
void createRequestPacket(isc::dns::Message& message,
const int protocol = IPPROTO_UDP);
MockSession notify_session;
MockServer dnsserv;
isc::dns::Message request_message;
isc::dns::MessagePtr parse_message;
const isc::dns::qid_t default_qid;
const isc::dns::Opcode opcode;
const isc::dns::Name qname;
const isc::dns::RRClass qclass;
const isc::dns::RRType qtype;
asiolink::IOSocket* io_sock;
asiolink::IOMessage* io_message;
const asiolink::IOEndpoint* endpoint;
isc::dns::OutputBuffer request_obuffer;
isc::dns::MessageRenderer request_renderer;
isc::dns::OutputBufferPtr response_obuffer;
std::vector<uint8_t> data;
};
} // end of namespace testutils
} // end of namespace isc
// Local Variables:
// mode: c++
// End:

View File

@@ -1,158 +0,0 @@
// Copyright (C) 2010 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.
// $Id: auth_srv_unittest.cc 3310 2010-10-21 23:10:24Z each $
#include "srv_test.h"
namespace {
// Unsupported requests. Should result in NOTIMP.
#define UNSUPPORTED_REQUEST_TEST \
for (unsigned int i = 0; i < 16; ++i) { \
/* set Opcode to 'i', which iterators over all possible codes except \
the standard query and notify */ \
if (i == Opcode::QUERY().getCode() || \
i == Opcode::NOTIFY().getCode()) { \
continue; \
} \
createDataFromFile("simplequery_fromWire.wire"); \
data[2] = ((i << 3) & 0xff); \
\
parse_message->clear(Message::PARSE); \
server.processMessage(*io_message, parse_message, response_obuffer, \
&dnsserv); \
EXPECT_TRUE(dnsserv.hasAnswer()); \
headerCheck(*parse_message, default_qid, Rcode::NOTIMP(), i, QR_FLAG, \
0, 0, 0, 0); \
}
// Simple API check
#define VERBOSE_TEST \
EXPECT_FALSE(server.getVerbose()); \
server.setVerbose(true); \
EXPECT_TRUE(server.getVerbose()); \
server.setVerbose(false); \
EXPECT_FALSE(server.getVerbose()); \
// Multiple questions. Should result in FORMERR.
#define MULTI_QUESTION_TEST \
createDataFromFile("multiquestion_fromWire.wire"); \
server.processMessage(*io_message, parse_message, response_obuffer, &dnsserv); \
EXPECT_TRUE(dnsserv.hasAnswer()); \
headerCheck(*parse_message, default_qid, Rcode::FORMERR(), opcode.getCode(), \
QR_FLAG, 2, 0, 0, 0); \
\
QuestionIterator qit = parse_message->beginQuestion(); \
EXPECT_EQ(Name("example.com"), (*qit)->getName()); \
EXPECT_EQ(RRClass::IN(), (*qit)->getClass()); \
EXPECT_EQ(RRType::A(), (*qit)->getType()); \
++qit; \
EXPECT_EQ(Name("example.com"), (*qit)->getName()); \
EXPECT_EQ(RRClass::IN(), (*qit)->getClass()); \
EXPECT_EQ(RRType::AAAA(), (*qit)->getType()); \
++qit; \
EXPECT_TRUE(qit == parse_message->endQuestion());
// Incoming data doesn't even contain the complete header. Must be silently
// dropped.
#define SHORT_MESSAGE_TEST \
createDataFromFile("shortmessage_fromWire"); \
server.processMessage(*io_message, parse_message, response_obuffer, &dnsserv); \
EXPECT_FALSE(dnsserv.hasAnswer());
// Response messages. Must be silently dropped, whether it's a valid response
// or malformed or could otherwise cause a protocol error.
#define RESPONSE_TEST \
/* A valid (although unusual) response */\
createDataFromFile("simpleresponse_fromWire.wire"); \
server.processMessage(*io_message, parse_message, response_obuffer, &dnsserv); \
EXPECT_FALSE(dnsserv.hasAnswer()); \
\
/* A response with a broken question section. must be dropped rather than \
returning FORMERR. */\
createDataFromFile("shortresponse_fromWire"); \
server.processMessage(*io_message, parse_message, response_obuffer, &dnsserv); \
EXPECT_FALSE(dnsserv.hasAnswer()); \
\
/* A response to iquery. must be dropped rather than returning NOTIMP. */\
createDataFromFile("iqueryresponse_fromWire.wire"); \
server.processMessage(*io_message, parse_message, response_obuffer, &dnsserv); \
EXPECT_FALSE(dnsserv.hasAnswer());
// Query with a broken question
#define SHORT_QUESTION_TEST \
createDataFromFile("shortquestion_fromWire"); \
server.processMessage(*io_message, parse_message, response_obuffer, &dnsserv); \
EXPECT_TRUE(dnsserv.hasAnswer()); \
/* Since the query's question is broken, the question section of the \
response should be empty. */\
headerCheck(*parse_message, default_qid, Rcode::FORMERR(), opcode.getCode(), \
QR_FLAG, 0, 0, 0, 0);
// Query with a broken answer section
#define SHORT_ANSWER_TEST \
createDataFromFile("shortanswer_fromWire.wire"); \
server.processMessage(*io_message, parse_message, response_obuffer, &dnsserv); \
EXPECT_TRUE(dnsserv.hasAnswer()); \
\
/* This is a bogus query, but question section is valid. So the response \
should copy the question section. */ \
headerCheck(*parse_message, default_qid, Rcode::FORMERR(), opcode.getCode(), \
QR_FLAG, 1, 0, 0, 0); \
\
QuestionIterator qit = parse_message->beginQuestion(); \
EXPECT_EQ(Name("example.com"), (*qit)->getName()); \
EXPECT_EQ(RRClass::IN(), (*qit)->getClass()); \
EXPECT_EQ(RRType::A(), (*qit)->getType()); \
++qit; \
EXPECT_TRUE(qit == parse_message->endQuestion());
// Query with unsupported version of EDNS.
#define EDNS_BADVERS_TEST \
createDataFromFile("queryBadEDNS_fromWire.wire"); \
server.processMessage(*io_message, parse_message, response_obuffer, &dnsserv); \
EXPECT_TRUE(dnsserv.hasAnswer()); \
\
/* The response must have an EDNS OPT RR in the additional section, \
it will be added automatically at the render time.
Note that the DNSSEC DO bit is cleared even if this bit in the query \
is set. This is a limitation of the current implementation. */ \
headerCheck(*parse_message, default_qid, Rcode::BADVERS(), opcode.getCode(), \
QR_FLAG, 1, 0, 0, 1); \
EXPECT_FALSE(parse_message->getEDNS()); /* EDNS isn't added at this point */ \
\
InputBuffer ib(response_obuffer->getData(), response_obuffer->getLength()); \
Message parsed(Message::PARSE); \
parsed.fromWire(ib); \
EXPECT_EQ(Rcode::BADVERS(), parsed.getRcode()); \
ConstEDNSPtr edns(parsed.getEDNS()); \
ASSERT_TRUE(edns); \
EXPECT_FALSE(edns->getDNSSECAwareness());
#define AXFR_OVER_UDP_TEST \
/* AXFR over UDP is invalid and should result in FORMERR. */\
UnitTestUtil::createRequestMessage(request_message, opcode, default_qid, \
Name("example.com"), RRClass::IN(), \
RRType::AXFR()); \
createRequestPacket(request_message, IPPROTO_UDP); \
server.processMessage(*io_message, parse_message, response_obuffer, &dnsserv); \
EXPECT_TRUE(dnsserv.hasAnswer()); \
headerCheck(*parse_message, default_qid, Rcode::FORMERR(), opcode.getCode(), \
QR_FLAG, 1, 0, 0, 0);
}