mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-30 05:27:55 +00:00
[4029] Cleanup testutils code too
This commit is contained in:
parent
3cb881a156
commit
bee3f1c2a0
@ -9,10 +9,7 @@ noinst_SCRIPTS = dhcp_test_lib.sh
|
|||||||
if HAVE_GTEST
|
if HAVE_GTEST
|
||||||
noinst_LTLIBRARIES = libkea-testutils.la
|
noinst_LTLIBRARIES = libkea-testutils.la
|
||||||
|
|
||||||
libkea_testutils_la_SOURCES = srv_test.h srv_test.cc
|
libkea_testutils_la_SOURCES = unix_control_client.h unix_control_client.cc
|
||||||
libkea_testutils_la_SOURCES += dnsmessage_test.h dnsmessage_test.cc
|
|
||||||
libkea_testutils_la_SOURCES += unix_control_client.h unix_control_client.cc
|
|
||||||
libkea_testutils_la_SOURCES += mockups.h
|
|
||||||
libkea_testutils_la_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
|
libkea_testutils_la_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
|
||||||
libkea_testutils_la_LIBADD = $(top_builddir)/src/lib/asiolink/libkea-asiolink.la
|
libkea_testutils_la_LIBADD = $(top_builddir)/src/lib/asiolink/libkea-asiolink.la
|
||||||
libkea_testutils_la_LIBADD += $(top_builddir)/src/lib/dns/libkea-dns++.la
|
libkea_testutils_la_LIBADD += $(top_builddir)/src/lib/dns/libkea-dns++.la
|
||||||
|
@ -1,150 +0,0 @@
|
|||||||
// 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.
|
|
||||||
|
|
||||||
#include <dns/message.h>
|
|
||||||
#include <dns/opcode.h>
|
|
||||||
#include <dns/rdata.h>
|
|
||||||
#include <dns/rcode.h>
|
|
||||||
#include <dns/rrset.h>
|
|
||||||
#include <dns/rrttl.h>
|
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
|
||||||
|
|
||||||
#include <testutils/dnsmessage_test.h>
|
|
||||||
|
|
||||||
#include <boost/bind.hpp>
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace isc::dns;
|
|
||||||
|
|
||||||
namespace isc {
|
|
||||||
namespace testutils {
|
|
||||||
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;
|
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
::testing::AssertionResult
|
|
||||||
matchRdata(const char*, const char*,
|
|
||||||
const rdata::Rdata& expected, const rdata::Rdata& actual)
|
|
||||||
{
|
|
||||||
if (expected.compare(actual) != 0) {
|
|
||||||
::testing::Message msg;
|
|
||||||
msg << "Two RDATAs are expected to be equal but not:\n"
|
|
||||||
<< " Actual: " << actual.toText() << "\n"
|
|
||||||
<< "Expected: " << expected.toText();
|
|
||||||
return (::testing::AssertionFailure(msg));
|
|
||||||
}
|
|
||||||
return (::testing::AssertionSuccess());
|
|
||||||
}
|
|
||||||
|
|
||||||
// A helper callback of masterLoad() used by textToRRset() below.
|
|
||||||
void
|
|
||||||
setRRset(RRsetPtr rrset, RRsetPtr* rrsetp) {
|
|
||||||
if (*rrsetp) {
|
|
||||||
// may be a sig
|
|
||||||
if (rrset->getType() == RRType::RRSIG()) {
|
|
||||||
(*rrsetp)->addRRsig(rrset);
|
|
||||||
} else {
|
|
||||||
isc_throw(isc::Unexpected,
|
|
||||||
"multiple RRsets are given to textToRRset");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
*rrsetp = rrset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RRsetPtr
|
|
||||||
textToRRset(const string& text_rrset, const RRClass& rrclass,
|
|
||||||
const Name& origin)
|
|
||||||
{
|
|
||||||
stringstream ss(text_rrset);
|
|
||||||
RRsetPtr rrset;
|
|
||||||
masterLoad(ss, origin, rrclass, boost::bind(setRRset, _1, &rrset));
|
|
||||||
return (rrset);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
rrsetCheck(isc::dns::ConstRRsetPtr expected_rrset,
|
|
||||||
isc::dns::ConstRRsetPtr actual_rrset)
|
|
||||||
{
|
|
||||||
SCOPED_TRACE("Comparing RRsets\n"
|
|
||||||
" Actual: " + actual_rrset->toText() +
|
|
||||||
" Expected: " + expected_rrset->toText());
|
|
||||||
EXPECT_EQ(expected_rrset->getName(), actual_rrset->getName());
|
|
||||||
EXPECT_EQ(expected_rrset->getClass(), actual_rrset->getClass());
|
|
||||||
EXPECT_EQ(expected_rrset->getType(), actual_rrset->getType());
|
|
||||||
EXPECT_EQ(expected_rrset->getTTL(), actual_rrset->getTTL());
|
|
||||||
|
|
||||||
isc::dns::RdataIteratorPtr rdata_it = actual_rrset->getRdataIterator();
|
|
||||||
isc::dns::RdataIteratorPtr expected_rdata_it =
|
|
||||||
expected_rrset->getRdataIterator();
|
|
||||||
while (!expected_rdata_it->isLast()) {
|
|
||||||
EXPECT_FALSE(rdata_it->isLast());
|
|
||||||
if (rdata_it->isLast()) {
|
|
||||||
// buggy case, should stop here
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPECT_PRED_FORMAT2(matchRdata, expected_rdata_it->getCurrent(),
|
|
||||||
rdata_it->getCurrent());
|
|
||||||
|
|
||||||
expected_rdata_it->next();
|
|
||||||
rdata_it->next();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure we have examined all sets of rrset RDATA
|
|
||||||
EXPECT_TRUE(rdata_it->isLast());
|
|
||||||
}
|
|
||||||
} // end of namespace testutils
|
|
||||||
} // end of namespace isc
|
|
@ -1,397 +0,0 @@
|
|||||||
// 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 ISC_TESTUTILS_DNSMESSAGETEST_H
|
|
||||||
#define ISC_TESTUTILS_DNSMESSAGETEST_H 1
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <functional>
|
|
||||||
#include <iosfwd>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include <dns/message.h>
|
|
||||||
#include <dns/name.h>
|
|
||||||
#include <dns/masterload.h>
|
|
||||||
#include <dns/rdataclass.h>
|
|
||||||
#include <dns/rrclass.h>
|
|
||||||
#include <dns/rrset.h>
|
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
|
||||||
|
|
||||||
namespace isc {
|
|
||||||
namespace testutils {
|
|
||||||
///
|
|
||||||
/// \name Header flags
|
|
||||||
///
|
|
||||||
/// These are flags to indicate whether the corresponding flag bit of the
|
|
||||||
/// DNS header is to be set in the test cases using \c headerCheck().
|
|
||||||
/// (The flag values is irrelevant to their wire-format values).
|
|
||||||
/// The meaning of the flags should be obvious from the variable names.
|
|
||||||
//@{
|
|
||||||
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;
|
|
||||||
//@}
|
|
||||||
|
|
||||||
/// Set of unit tests to examine a DNS message header.
|
|
||||||
///
|
|
||||||
/// This function takes a dns::Message object and performs various tests
|
|
||||||
/// to confirm if the header fields of the message have the given specified
|
|
||||||
/// value. The \c message parameter is the Message object to be tested,
|
|
||||||
/// and the remaining parameters specify the expected values of the fields.
|
|
||||||
///
|
|
||||||
/// If all fields have the expected values the test will be considered
|
|
||||||
/// successful. Otherwise, some of the tests will indicate a failure, which
|
|
||||||
/// will make the test case that calls this function fail.
|
|
||||||
///
|
|
||||||
/// The meaning of the parameters should be obvious, but here are some notes
|
|
||||||
/// that may not be so trivial:
|
|
||||||
/// - \c opcode is an integer, not an \c dns::Opcode object. This is because
|
|
||||||
/// we can easily iterate over all possible OPCODEs in a test.
|
|
||||||
/// - \c flags is a bitmask so that we can specify a set of header flags
|
|
||||||
/// via a single parameter. For example, when we expect the message has
|
|
||||||
/// QR and AA flags are on and others are off, we'd set this parameter to
|
|
||||||
/// <code>(QR_FLAG | AA_FLAG)</code>.
|
|
||||||
///
|
|
||||||
/// \param message The DNS message to be tested.
|
|
||||||
/// \param qid The expected QID
|
|
||||||
/// \param rcode The expected RCODE
|
|
||||||
/// \param opcodeval The code value of the expected OPCODE
|
|
||||||
/// \param flags Bit flags specifying header flags that are expected to be set
|
|
||||||
/// \param qdcount The expected value of QDCOUNT
|
|
||||||
/// \param ancount The expected value of ANCOUNT
|
|
||||||
/// \param nscount The expected value of NSCOUNT
|
|
||||||
/// \param arcount The expected value of ARCOUNT
|
|
||||||
void
|
|
||||||
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);
|
|
||||||
|
|
||||||
/// Set of unit tests to check equality of two RRsets
|
|
||||||
///
|
|
||||||
/// This function takes two RRset objects and performs detailed tests to
|
|
||||||
/// check if these two are "equal", where equal means:
|
|
||||||
/// - The owner name, RR class, RR type and TTL are all equal. Names are
|
|
||||||
/// compared in case-insensitive manner.
|
|
||||||
/// - The number of RRs (more accurately RDATAs) is the same.
|
|
||||||
/// - RDATAs are equal as a sequence. That is, the first RDATA of
|
|
||||||
/// \c expected_rrset is equal to the first RDATA of \c actual_rrset,
|
|
||||||
/// the second RDATA of \c expected_rrset is equal to the second RDATA
|
|
||||||
/// of \c actual_rrset, and so on. Two RDATAs are equal iff they have
|
|
||||||
/// the same DNSSEC sorting order as defined in RFC4034.
|
|
||||||
///
|
|
||||||
/// Some of the tests will fail if any of the above isn't met.
|
|
||||||
///
|
|
||||||
/// \note In future we may want to allow more flexible matching for RDATAs.
|
|
||||||
/// For example, we may want to allow comparison as "sets", i.e., comparing
|
|
||||||
/// RDATAs regardless of the ordering; we may also want to support suppressing
|
|
||||||
/// duplicate RDATA. For now, it's caller's responsibility to match the
|
|
||||||
/// ordering (and any duplicates) between the expected and actual sets.
|
|
||||||
/// Even if and when we support the flexible behavior, this "strict mode"
|
|
||||||
/// will still be useful.
|
|
||||||
///
|
|
||||||
/// \param expected_rrset The expected RRset
|
|
||||||
/// \param actual_rrset The RRset to be tested
|
|
||||||
void rrsetCheck(isc::dns::ConstRRsetPtr expected_rrset,
|
|
||||||
isc::dns::ConstRRsetPtr actual_rrset);
|
|
||||||
|
|
||||||
/// The definitions in this name space are not supposed to be used publicly,
|
|
||||||
/// but are given here because they are used in templated functions.
|
|
||||||
namespace detail {
|
|
||||||
// Helper matching class used in rrsetsCheck(). Basically we only have to
|
|
||||||
// check the equality of name, RR type and RR class, but for RRSIGs we need
|
|
||||||
// special additional checks because they are essentially different if their
|
|
||||||
// 'type covered' are different. For simplicity, we only compare the types
|
|
||||||
// of the first RRSIG RDATAs (and only check when they exist); if there's
|
|
||||||
// further difference in the RDATA, the main comparison checks will detect it.
|
|
||||||
struct RRsetMatch : public std::unary_function<isc::dns::ConstRRsetPtr, bool> {
|
|
||||||
RRsetMatch(isc::dns::ConstRRsetPtr target) : target_(target) {}
|
|
||||||
bool operator()(isc::dns::ConstRRsetPtr rrset) const {
|
|
||||||
if (rrset->getType() != target_->getType() ||
|
|
||||||
rrset->getClass() != target_->getClass() ||
|
|
||||||
rrset->getName() != target_->getName()) {
|
|
||||||
return (false);
|
|
||||||
}
|
|
||||||
if (rrset->getType() != isc::dns::RRType::RRSIG()) {
|
|
||||||
return (true);
|
|
||||||
}
|
|
||||||
if (rrset->getRdataCount() == 0 || target_->getRdataCount() == 0) {
|
|
||||||
return (true);
|
|
||||||
}
|
|
||||||
isc::dns::RdataIteratorPtr rdit = rrset->getRdataIterator();
|
|
||||||
isc::dns::RdataIteratorPtr targetit = target_->getRdataIterator();
|
|
||||||
return (dynamic_cast<const isc::dns::rdata::generic::RRSIG&>(
|
|
||||||
rdit->getCurrent()).typeCovered() ==
|
|
||||||
dynamic_cast<const isc::dns::rdata::generic::RRSIG&>(
|
|
||||||
targetit->getCurrent()).typeCovered());
|
|
||||||
}
|
|
||||||
const isc::dns::ConstRRsetPtr target_;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Helper callback functor for masterLoad() used in rrsetsCheck (stream
|
|
||||||
// version)
|
|
||||||
class RRsetInserter {
|
|
||||||
public:
|
|
||||||
RRsetInserter(std::vector<isc::dns::ConstRRsetPtr>& rrsets) :
|
|
||||||
rrsets_(rrsets)
|
|
||||||
{}
|
|
||||||
void operator()(isc::dns::ConstRRsetPtr rrset) const {
|
|
||||||
rrsets_.push_back(rrset);
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
std::vector<isc::dns::ConstRRsetPtr>& rrsets_;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief A converter from a string to RRset.
|
|
||||||
///
|
|
||||||
/// This is a convenient shortcut for tests that need to create an RRset
|
|
||||||
/// from textual representation with a single call to a function.
|
|
||||||
///
|
|
||||||
/// An RRset consisting of multiple RRs can be constructed, but only one
|
|
||||||
/// RRset is allowed. If the given string contains mixed types of RRs
|
|
||||||
/// it throws an \c isc::Unexpected exception.
|
|
||||||
///
|
|
||||||
/// \param text_rrset A complete textual representation of an RRset.
|
|
||||||
/// It must meets the assumption of the \c dns::masterLoad() function.
|
|
||||||
/// \param rrclass The RR class of the RRset. Note that \c text_rrset should
|
|
||||||
/// contain the RR class, but it's needed for \c dns::masterLoad().
|
|
||||||
/// \param origin The zone origin where the RR is expected to belong. This
|
|
||||||
/// parameter normally doesn't have to be specified, but for an SOA RR it
|
|
||||||
/// must be set to its owner name, due to the internal check of
|
|
||||||
/// \c dns::masterLoad().
|
|
||||||
isc::dns::RRsetPtr textToRRset(const std::string& text_rrset,
|
|
||||||
const isc::dns::RRClass& rrclass =
|
|
||||||
isc::dns::RRClass::IN(),
|
|
||||||
const isc::dns::Name& origin =
|
|
||||||
isc::dns::Name::ROOT_NAME());
|
|
||||||
|
|
||||||
/// \brief Pull out signatures and convert to text
|
|
||||||
///
|
|
||||||
/// This is a helper function for rrsetsCheck.
|
|
||||||
///
|
|
||||||
/// It adds all the rrsets to the given vector. It also adds the
|
|
||||||
/// signatures of those rrsets as separate rrsets into the vector
|
|
||||||
/// (but does not modify the original rrset; i.e. technically the
|
|
||||||
/// signatures are in the resulting vector twice).
|
|
||||||
///
|
|
||||||
/// Additionally, it adds the string representation of all rrsets
|
|
||||||
/// and their signatures to the given string (for use in scoped_trace).
|
|
||||||
///
|
|
||||||
/// \param rrsets A vector to add the rrsets and signatures to
|
|
||||||
/// \param text A string to add the rrsets string representations to
|
|
||||||
/// \param begin The beginning of the rrsets iterator
|
|
||||||
/// \param end The end of the rrsets iterator
|
|
||||||
template <typename ITERATOR>
|
|
||||||
void
|
|
||||||
pullSigs(std::vector<isc::dns::ConstRRsetPtr>& rrsets,
|
|
||||||
std::string& text, ITERATOR begin, ITERATOR end)
|
|
||||||
{
|
|
||||||
for (ITERATOR it = begin; it != end; ++it) {
|
|
||||||
rrsets.push_back(*it);
|
|
||||||
text += (*it)->toText(); // this will include RRSIG, if attached.
|
|
||||||
if ((*it)->getRRsig()) {
|
|
||||||
rrsets.push_back((*it)->getRRsig());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set of unit tests to check if two sets of RRsets are identical.
|
|
||||||
///
|
|
||||||
/// This templated function takes two sets of sequences, each defined by
|
|
||||||
/// two input iterators pointing to \c ConstRRsetPtr (begin and end).
|
|
||||||
/// This function compares these two sets of RRsets as "sets", and considers
|
|
||||||
/// they are equal when:
|
|
||||||
/// - The number of RRsets are the same.
|
|
||||||
/// - For any RRset in one set, there is an equivalent RRset in the other set,
|
|
||||||
/// and vice versa, where the equivalence of two RRsets is tested using
|
|
||||||
/// \c rrsetCheck().
|
|
||||||
///
|
|
||||||
/// Note that the sets of RRsets are compared as "sets", i.e, they don't have
|
|
||||||
/// to be listed in the same order.
|
|
||||||
///
|
|
||||||
/// The entire tests will pass if the two sets are identical. Otherwise
|
|
||||||
/// some of the tests will indicate a failure.
|
|
||||||
///
|
|
||||||
/// \note
|
|
||||||
/// - There is one known restriction: each set of RRsets must not have more
|
|
||||||
/// than one RRsets for the same name, RR type and RR class. If this
|
|
||||||
/// condition isn't met, some of the tests will fail either against an
|
|
||||||
/// explicit duplication check or as a result of counter mismatch.
|
|
||||||
/// - This function uses linear searches on the expected and actual sequences,
|
|
||||||
/// and won't be scalable for large input. For the purpose of testing it
|
|
||||||
/// should be acceptable, but be aware of the size of test data.
|
|
||||||
///
|
|
||||||
/// \param expected_begin The beginning of the expected set of RRsets
|
|
||||||
/// \param expected_end The end of the expected set of RRsets
|
|
||||||
/// \param actual_begin The beginning of the set of RRsets to be tested
|
|
||||||
/// \param actual_end The end of the set of RRsets to be tested
|
|
||||||
template<typename EXPECTED_ITERATOR, typename ACTUAL_ITERATOR>
|
|
||||||
void
|
|
||||||
rrsetsCheck(EXPECTED_ITERATOR expected_begin, EXPECTED_ITERATOR expected_end,
|
|
||||||
ACTUAL_ITERATOR actual_begin, ACTUAL_ITERATOR actual_end)
|
|
||||||
{
|
|
||||||
// Iterators can have their RRsig sets as separate RRsets,
|
|
||||||
// or they can have them attached to the RRset they cover.
|
|
||||||
// For ease of use of this method, we first flatten out both
|
|
||||||
// iterators, and pull out the signature sets, and add them as
|
|
||||||
// separate RRsets (rrsetCheck() later does not check signatures
|
|
||||||
// attached to rrsets)
|
|
||||||
std::vector<isc::dns::ConstRRsetPtr> expected_rrsets, actual_rrsets;
|
|
||||||
std::string expected_text, actual_text;
|
|
||||||
|
|
||||||
pullSigs(expected_rrsets, expected_text, expected_begin, expected_end);
|
|
||||||
pullSigs(actual_rrsets, actual_text, actual_begin, actual_end);
|
|
||||||
|
|
||||||
SCOPED_TRACE(std::string("Comparing two RRset lists:\n") +
|
|
||||||
"Actual:\n" + actual_text +
|
|
||||||
"Expected:\n" + expected_text);
|
|
||||||
|
|
||||||
// The vectors should have the same number of sets
|
|
||||||
ASSERT_EQ(expected_rrsets.size(), actual_rrsets.size());
|
|
||||||
|
|
||||||
// Now we check if all RRsets from the actual_rrsets are in
|
|
||||||
// expected_rrsets, and that actual_rrsets has no duplicates.
|
|
||||||
std::vector<isc::dns::ConstRRsetPtr> checked_rrsets; // for duplicate check
|
|
||||||
|
|
||||||
std::vector<isc::dns::ConstRRsetPtr>::const_iterator it;
|
|
||||||
for (it = actual_rrsets.begin(); it != actual_rrsets.end(); ++it) {
|
|
||||||
// Make sure there's no duplicate RRset in actual (using a naive
|
|
||||||
// search). By guaranteeing the actual set is unique, and the
|
|
||||||
// size of both vectors is the same, we can conclude that
|
|
||||||
// the two sets are identical after this loop.
|
|
||||||
// Note: we cannot use EXPECT_EQ for iterators
|
|
||||||
EXPECT_TRUE(checked_rrsets.end() ==
|
|
||||||
std::find_if(checked_rrsets.begin(), checked_rrsets.end(),
|
|
||||||
detail::RRsetMatch(*it)));
|
|
||||||
checked_rrsets.push_back(*it);
|
|
||||||
|
|
||||||
std::vector<isc::dns::ConstRRsetPtr>::const_iterator found_rrset_it =
|
|
||||||
std::find_if(expected_rrsets.begin(), expected_rrsets.end(),
|
|
||||||
detail::RRsetMatch(*it));
|
|
||||||
if (found_rrset_it != expected_rrsets.end()) {
|
|
||||||
rrsetCheck(*found_rrset_it, *it);
|
|
||||||
} else {
|
|
||||||
FAIL() << (*it)->toText() << " not found in expected rrsets";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set of unit tests to check if two sets of RRsets are identical using
|
|
||||||
/// streamed expected data.
|
|
||||||
///
|
|
||||||
/// This templated function takes a standard input stream that produces
|
|
||||||
/// a sequence of textural RRs and compares the entire set of RRsets
|
|
||||||
/// with the range of RRsets specified by two input iterators.
|
|
||||||
///
|
|
||||||
/// This function is actually a convenient wrapper for the other version
|
|
||||||
/// of function; it internally builds a standard vector of RRsets
|
|
||||||
/// from the input stream and uses iterators of the vector as the expected
|
|
||||||
/// input iterators for the backend function.
|
|
||||||
/// Expected data in the form of input stream would be useful for testing
|
|
||||||
/// as it can be easily hardcoded in test cases using string streams or
|
|
||||||
/// given from a data source file.
|
|
||||||
///
|
|
||||||
/// One common use case of this function is to test whether a particular
|
|
||||||
/// section of a DNS message contains an expected set of RRsets.
|
|
||||||
/// For example, when \c message is an \c dns::Message object, the following
|
|
||||||
/// test code will check if the additional section of \c message contains
|
|
||||||
/// the hardcoded two RRsets (2 A RRs and 1 AAAA RR) and only contains these
|
|
||||||
/// RRsets:
|
|
||||||
/// \code std::stringstream expected;
|
|
||||||
/// expected << "foo.example.com. 3600 IN A 192.0.2.1\n"
|
|
||||||
/// << "foo.example.com. 3600 IN A 192.0.2.2\n"
|
|
||||||
/// << "foo.example.com. 7200 IN AAAA 2001:db8::1\n"
|
|
||||||
/// rrsetsCheck(expected, message.beginSection(Message::SECTION_ADDITIONAL),
|
|
||||||
/// message.endSection(Message::SECTION_ADDITIONAL));
|
|
||||||
/// \endcode
|
|
||||||
///
|
|
||||||
/// The input stream is parsed using the \c dns::masterLoad() function,
|
|
||||||
/// and notes and restrictions of that function apply.
|
|
||||||
/// This is also the reason why this function takes \c origin and \c rrclass
|
|
||||||
/// parameters. The default values of these parameters should just work
|
|
||||||
/// in many cases for usual tests, but due to a validity check on the SOA RR
|
|
||||||
/// in \c dns::masterLoad(), if the input stream contains an SOA RR, the
|
|
||||||
/// \c origin parameter will have to be set to the owner name of the SOA
|
|
||||||
/// explicitly. Likewise, all RRsets must have the same RR class.
|
|
||||||
/// (We may have to modify \c dns::masterLoad() so that it can
|
|
||||||
/// have an option to be more generous about these points if it turns out
|
|
||||||
/// to be too restrictive).
|
|
||||||
///
|
|
||||||
/// \param expected_stream An input stream object that is to emit expected set
|
|
||||||
/// of RRsets
|
|
||||||
/// \param actual_begin The beginning of the set of RRsets to be tested
|
|
||||||
/// \param actual_end The end of the set of RRsets to be tested
|
|
||||||
/// \param origin A domain name that is a super domain of the owner name
|
|
||||||
/// of all RRsets contained in the stream.
|
|
||||||
/// \param rrclass The RR class of the RRsets contained in the stream.
|
|
||||||
template<typename ACTUAL_ITERATOR>
|
|
||||||
void
|
|
||||||
rrsetsCheck(std::istream& expected_stream,
|
|
||||||
ACTUAL_ITERATOR actual_begin, ACTUAL_ITERATOR actual_end,
|
|
||||||
const isc::dns::Name& origin = isc::dns::Name::ROOT_NAME(),
|
|
||||||
const isc::dns::RRClass& rrclass = isc::dns::RRClass::IN())
|
|
||||||
{
|
|
||||||
std::vector<isc::dns::ConstRRsetPtr> expected;
|
|
||||||
isc::dns::masterLoad(expected_stream, origin, rrclass,
|
|
||||||
detail::RRsetInserter(expected));
|
|
||||||
rrsetsCheck(expected.begin(), expected.end(), actual_begin, actual_end);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set of unit tests to check if two sets of RRsets are identical using
|
|
||||||
/// expected data as string.
|
|
||||||
///
|
|
||||||
/// This function is a wrapper for the input stream version:
|
|
||||||
/// \c rrsetsCheck(std::istream&, ACTUAL_ITERATOR, ACTUAL_ITERATOR, const isc::dns::Name&, const isc::dns::RRClass&)(),
|
|
||||||
/// and takes a string object instead of a stream.
|
|
||||||
/// While the stream version is more generic, this version would be more
|
|
||||||
/// convenient for tests using hardcoded expected data. Using this version,
|
|
||||||
/// the example test case shown for the stream version would look as follows:
|
|
||||||
/// \code
|
|
||||||
/// rrsetsCheck("foo.example.com. 3600 IN A 192.0.2.1\n"
|
|
||||||
/// "foo.example.com. 3600 IN A 192.0.2.2\n"
|
|
||||||
/// "foo.example.com. 7200 IN AAAA 2001:db8::1\n",
|
|
||||||
/// message.beginSection(Message::SECTION_ADDITIONAL),
|
|
||||||
/// message.endSection(Message::SECTION_ADDITIONAL));
|
|
||||||
/// \endcode
|
|
||||||
///
|
|
||||||
/// The semantics of parameters is the same as that of the stream version
|
|
||||||
/// except that \c expected is a string of expected sets of RRsets.
|
|
||||||
template<typename ACTUAL_ITERATOR>
|
|
||||||
void
|
|
||||||
rrsetsCheck(const std::string& expected,
|
|
||||||
ACTUAL_ITERATOR actual_begin, ACTUAL_ITERATOR actual_end,
|
|
||||||
const isc::dns::Name& origin = isc::dns::Name::ROOT_NAME(),
|
|
||||||
const isc::dns::RRClass& rrclass = isc::dns::RRClass::IN())
|
|
||||||
{
|
|
||||||
std::stringstream expected_stream(expected);
|
|
||||||
rrsetsCheck(expected_stream, actual_begin, actual_end, origin,
|
|
||||||
rrclass);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end of namespace testutils
|
|
||||||
} // end of namespace isc
|
|
||||||
#endif // ISC_TESTUTILS_DNSMESSAGETEST_H
|
|
||||||
|
|
||||||
// Local Variables:
|
|
||||||
// mode: c++
|
|
||||||
// End:
|
|
@ -1,145 +0,0 @@
|
|||||||
// Copyright (C) 2010, 2015 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 ISC_TESTUTILS_MOCKUPS_H
|
|
||||||
#define ISC_TESTUTILS_MOCKUPS_H 1
|
|
||||||
|
|
||||||
#include <exceptions/exceptions.h>
|
|
||||||
|
|
||||||
#include <cc/data.h>
|
|
||||||
|
|
||||||
#include <asiodns/asiodns.h>
|
|
||||||
|
|
||||||
#include <utility>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace isc {
|
|
||||||
namespace testutils {
|
|
||||||
|
|
||||||
// This mock object does nothing except for recording passed parameters
|
|
||||||
// to addServerXXX methods so the test code subsequently checks the parameters.
|
|
||||||
class MockDNSService : public isc::asiodns::DNSServiceBase {
|
|
||||||
public:
|
|
||||||
MockDNSService() : tcp_recv_timeout_(0) {}
|
|
||||||
|
|
||||||
// A helper tuple of parameters passed to addServerUDPFromFD().
|
|
||||||
struct UDPFdParams {
|
|
||||||
int fd;
|
|
||||||
int af;
|
|
||||||
ServerFlag options;
|
|
||||||
};
|
|
||||||
|
|
||||||
virtual void addServerTCPFromFD(int fd, int af) {
|
|
||||||
tcp_fd_params_.push_back(std::pair<int, int>(fd, af));
|
|
||||||
}
|
|
||||||
virtual void addServerUDPFromFD(int fd, int af, ServerFlag options) {
|
|
||||||
UDPFdParams params = { fd, af, options };
|
|
||||||
udp_fd_params_.push_back(params);
|
|
||||||
}
|
|
||||||
virtual void clearServers() {}
|
|
||||||
|
|
||||||
virtual asiolink::IOService& getIOService() {
|
|
||||||
isc_throw(isc::Unexpected,
|
|
||||||
"MockDNSService::getIOService() shouldn't be called");
|
|
||||||
}
|
|
||||||
|
|
||||||
// These two allow the tests to check how the servers have been created
|
|
||||||
// through this object.
|
|
||||||
const std::vector<std::pair<int, int> >& getTCPFdParams() const {
|
|
||||||
return (tcp_fd_params_);
|
|
||||||
}
|
|
||||||
const std::vector<UDPFdParams>& getUDPFdParams() const {
|
|
||||||
return (udp_fd_params_);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void setTCPRecvTimeout(size_t timeout) {
|
|
||||||
tcp_recv_timeout_ = timeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t getTCPRecvTimeout() {
|
|
||||||
return tcp_recv_timeout_;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<std::pair<int, int> > tcp_fd_params_;
|
|
||||||
std::vector<UDPFdParams> udp_fd_params_;
|
|
||||||
size_t tcp_recv_timeout_;
|
|
||||||
};
|
|
||||||
|
|
||||||
// A nonoperative DNSServer object to be used in calls to processMessage().
|
|
||||||
class MockServer : public isc::asiodns::DNSServer {
|
|
||||||
public:
|
|
||||||
MockServer() : done_(false) {}
|
|
||||||
void operator()(asio::error_code, size_t) {}
|
|
||||||
virtual void resume(const bool done) { done_ = done; }
|
|
||||||
virtual bool hasAnswer() { return (done_); }
|
|
||||||
virtual int value() { return (0); }
|
|
||||||
private:
|
|
||||||
bool done_;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Commenting out this class as it is not used anyware. The removal of this class
|
|
||||||
// allows for removal of the lib/xfr.
|
|
||||||
|
|
||||||
// Mock Xfrout client
|
|
||||||
/*class MockXfroutClient : public isc::xfr::AbstractXfroutClient {
|
|
||||||
public:
|
|
||||||
MockXfroutClient() :
|
|
||||||
is_connected_(false), connect_ok_(true), send_ok_(true),
|
|
||||||
disconnect_ok_(true)
|
|
||||||
{}
|
|
||||||
|
|
||||||
virtual void connect() {
|
|
||||||
if (!connect_ok_) {
|
|
||||||
isc_throw(isc::xfr::XfroutError,
|
|
||||||
"xfrout connection disabled for test");
|
|
||||||
}
|
|
||||||
is_connected_ = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void disconnect() {
|
|
||||||
if (!disconnect_ok_) {
|
|
||||||
isc_throw(isc::xfr::XfroutError,
|
|
||||||
"closing xfrout connection is disabled for test");
|
|
||||||
}
|
|
||||||
is_connected_ = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual int sendXfroutRequestInfo(int, const void*, uint16_t) {
|
|
||||||
if (!send_ok_) {
|
|
||||||
isc_throw(isc::xfr::XfroutError,
|
|
||||||
"xfrout connection send is disabled for test");
|
|
||||||
}
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isConnected() const { return (is_connected_); }
|
|
||||||
void disableConnect() { connect_ok_ = false; }
|
|
||||||
void disableDisconnect() { disconnect_ok_ = false; }
|
|
||||||
void enableDisconnect() { disconnect_ok_ = true; }
|
|
||||||
void disableSend() { send_ok_ = false; }
|
|
||||||
private:
|
|
||||||
bool is_connected_;
|
|
||||||
bool connect_ok_;
|
|
||||||
bool send_ok_;
|
|
||||||
bool disconnect_ok_;
|
|
||||||
}; */
|
|
||||||
|
|
||||||
} // end of testutils
|
|
||||||
} // end of isc
|
|
||||||
#endif // ISC_TESTUTILS_MOCKUPS_H
|
|
||||||
|
|
||||||
// Local Variables:
|
|
||||||
// mode: c++
|
|
||||||
// End:
|
|
@ -1,235 +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.
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
|
|
||||||
#include <dns/message.h>
|
|
||||||
#include <dns/rcode.h>
|
|
||||||
|
|
||||||
#include <asiolink/asiolink.h>
|
|
||||||
|
|
||||||
#include <dns/tests/unittest_util.h>
|
|
||||||
|
|
||||||
#include <testutils/dnsmessage_test.h>
|
|
||||||
#include <testutils/srv_test.h>
|
|
||||||
|
|
||||||
#include <boost/scoped_ptr.hpp>
|
|
||||||
|
|
||||||
using namespace isc::dns;
|
|
||||||
using namespace isc::util;
|
|
||||||
using namespace isc::asiolink;
|
|
||||||
|
|
||||||
namespace isc {
|
|
||||||
namespace testutils {
|
|
||||||
const char* const DEFAULT_REMOTE_ADDRESS = "192.0.2.1";
|
|
||||||
const uint16_t DEFAULT_REMOTE_PORT = 53210;
|
|
||||||
|
|
||||||
SrvTestBase::SrvTestBase() : request_message(Message::RENDER),
|
|
||||||
parse_message(new Message(Message::PARSE)),
|
|
||||||
response_message(new Message(Message::RENDER)),
|
|
||||||
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),
|
|
||||||
response_obuffer(new OutputBuffer(0))
|
|
||||||
{}
|
|
||||||
|
|
||||||
void
|
|
||||||
SrvTestBase::createDataFromFile(const char* const datafile,
|
|
||||||
const int protocol)
|
|
||||||
{
|
|
||||||
data.clear();
|
|
||||||
|
|
||||||
endpoint.reset(IOEndpoint::create(protocol,
|
|
||||||
IOAddress(DEFAULT_REMOTE_ADDRESS),
|
|
||||||
DEFAULT_REMOTE_PORT));
|
|
||||||
UnitTestUtil::readWireData(datafile, data);
|
|
||||||
io_sock = (protocol == IPPROTO_UDP) ? &IOSocket::getDummyUDPSocket() :
|
|
||||||
&IOSocket::getDummyTCPSocket();
|
|
||||||
io_message.reset(new IOMessage(&data[0], data.size(), *io_sock,
|
|
||||||
*endpoint));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
SrvTestBase::createRequestPacket(Message& message,
|
|
||||||
const int protocol, TSIGContext* context,
|
|
||||||
const char* const remote_address,
|
|
||||||
uint16_t remote_port)
|
|
||||||
{
|
|
||||||
message.toWire(request_renderer, context);
|
|
||||||
endpoint.reset(IOEndpoint::create(protocol, IOAddress(remote_address),
|
|
||||||
remote_port));
|
|
||||||
io_sock = (protocol == IPPROTO_UDP) ? &IOSocket::getDummyUDPSocket() :
|
|
||||||
&IOSocket::getDummyTCPSocket();
|
|
||||||
|
|
||||||
io_message.reset(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 opcodes we support.
|
|
||||||
if (i == isc::dns::Opcode::QUERY().getCode() ||
|
|
||||||
i == isc::dns::Opcode::NOTIFY().getCode() ||
|
|
||||||
i == isc::dns::Opcode::UPDATE().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
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
} // end of namespace testutils
|
|
||||||
} // end of namespace isc
|
|
||||||
|
|
||||||
|
|
||||||
// Local Variables:
|
|
||||||
// mode: c++
|
|
||||||
// End:
|
|
@ -1,118 +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.
|
|
||||||
|
|
||||||
#ifndef ISC_TESTUTILS_SRVTEST_H
|
|
||||||
#define ISC_TESTUTILS_SRVTEST_H 1
|
|
||||||
|
|
||||||
#include <util/buffer.h>
|
|
||||||
#include <dns/name.h>
|
|
||||||
#include <dns/message.h>
|
|
||||||
#include <dns/messagerenderer.h>
|
|
||||||
#include <dns/opcode.h>
|
|
||||||
#include <dns/rcode.h>
|
|
||||||
#include <dns/rrclass.h>
|
|
||||||
#include <dns/rrtype.h>
|
|
||||||
|
|
||||||
#include "mockups.h"
|
|
||||||
#include <boost/scoped_ptr.hpp>
|
|
||||||
|
|
||||||
namespace asiolink {
|
|
||||||
class IOSocket;
|
|
||||||
class IOMessage;
|
|
||||||
class IOEndpoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace isc {
|
|
||||||
namespace testutils {
|
|
||||||
extern const char* const DEFAULT_REMOTE_ADDRESS;
|
|
||||||
extern const uint16_t DEFAULT_REMOTE_PORT;
|
|
||||||
|
|
||||||
// These are flags to indicate whether the corresponding flag bit of the
|
|
||||||
// DNS header is to be set in the test cases. (The flag values
|
|
||||||
// is irrelevant to their wire-format values)
|
|
||||||
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;
|
|
||||||
|
|
||||||
/// \brief The base class for Auth and Recurse test case
|
|
||||||
class SrvTestBase : public ::testing::Test {
|
|
||||||
protected:
|
|
||||||
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,
|
|
||||||
isc::dns::TSIGContext* context = NULL,
|
|
||||||
const char* const address = DEFAULT_REMOTE_ADDRESS,
|
|
||||||
uint16_t port = DEFAULT_REMOTE_PORT);
|
|
||||||
|
|
||||||
MockServer dnsserv;
|
|
||||||
isc::dns::Message request_message;
|
|
||||||
isc::dns::MessagePtr parse_message;
|
|
||||||
isc::dns::MessagePtr response_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;
|
|
||||||
boost::scoped_ptr<asiolink::IOMessage> io_message;
|
|
||||||
boost::scoped_ptr<const asiolink::IOEndpoint> endpoint;
|
|
||||||
isc::dns::MessageRenderer request_renderer;
|
|
||||||
isc::util::OutputBufferPtr response_obuffer;
|
|
||||||
std::vector<uint8_t> data;
|
|
||||||
};
|
|
||||||
} // end of namespace testutils
|
|
||||||
} // end of namespace isc
|
|
||||||
#endif // ISC_TESTUTILS_SRVTEST_H
|
|
||||||
|
|
||||||
// Local Variables:
|
|
||||||
// mode: c++
|
|
||||||
// End:
|
|
Loading…
x
Reference in New Issue
Block a user