Commit 06cfe323 authored by Jeremy C. Reed's avatar Jeremy C. Reed
Browse files

catch up to trunk


git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac470@4156 e5f2f494-b856-4b98-b285-d166d9295462
parents 87428d78 3f51d6ed
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
......
......@@ -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
......
......@@ -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
......
......@@ -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;
};
}
......
......@@ -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
......
......@@ -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) {
......
......@@ -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);
......
SUBDIRS = . tests
SUBDIRS = . tests internal
AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
AM_CPPFLAGS += $(BOOST_INCLUDES)
......
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)
// 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());
}
......@@ -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)
......
......@@ -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) :