Commit 1b1b49fa authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

ported RRset/Question/RR classes from experimental code with some test cases.


git-svn-id: svn://bind10.isc.org/svn/bind10/branches/f2f200910@132 e5f2f494-b856-4b98-b285-d166d9295462
parent 85aa4ad6
......@@ -31,6 +31,9 @@ using ISC::DNS::TTL;
using ISC::DNS::Rdata::IN::A;
using ISC::DNS::Rdata::IN::AAAA;
using ISC::DNS::Rdata::Generic::NS;
using ISC::DNS::RRset;
using ISC::DNS::Question;
using ISC::DNS::RR;
RRClass::RRClass(const std::string& classstr)
{
......@@ -188,79 +191,52 @@ NS::to_text() const
return (nsname_.to_text());
}
#ifdef notyet
void
RdataSet::add_rdata(rdataptr_t rdata)
{
if (rdata->get_type() != _rdtype)
throw DNSRdtypeMismatch();
_rdatalist.push_back(rdata);
}
std::string
RdataSet::to_text() const
{
std::string s;
for (vector<rdataptr_t>::const_iterator it = _rdatalist.begin();
it != _rdatalist.end();
++it)
{
if (!s.empty())
s.push_back('\n');
s += _ttl.to_text() + " " + _rdclass.to_text() + " " +
_rdtype.to_text() + " " + (**it).to_text();
}
return (s);
}
std::string
RRSet::to_text() const
RRset::to_text() const
{
std::string s;
for (vector<rdataptr_t>::const_iterator it = _rdatalist.begin();
it != _rdatalist.end();
for (std::vector<Rdata::RDATAPTR>::const_iterator it = rdatalist_.begin();
it != rdatalist_.end();
++it)
{
if (!s.empty())
s.push_back('\n');
s += _name.to_text() + " ";
s += _ttl.to_text() + " " + _rdclass.to_text() + " " +
_rdtype.to_text() + " " + (**it).to_text();
s += name_.to_text() + " ";
s += ttl_.to_text() + " " + rdclass_.to_text() + " " +
rdtype_.to_text() + " " + (**it).to_text();
}
return (s);
}
void
RRSet::add_rdata(rdataptr_t rdata)
RRset::add_rdata(Rdata::RDATAPTR rdata)
{
if (rdata->get_type() != _rdtype)
if (rdata->get_type() != rdtype_)
throw DNSRdtypeMismatch();
_rdatalist.push_back(rdata);
rdatalist_.push_back(rdata);
}
int
RRSet::to_wire(Message& message, section_t section)
RRset::to_wire(Buffer& buffer, NameCompressor& compressor, section_t section)
{
int num_rrs = 0;
// sort Rdata list based on rrset-order and sortlist, and possible
// other options. Details to be considered.
// section is not currently used. will be, when we implement rrset-order
// etc.
Buffer& b = message.get_iobuffer();
NameCompressor& c = message.get_compressor();
for (vector<rdataptr_t>::iterator it = _rdatalist.begin();
it != _rdatalist.end();
for (std::vector<Rdata::RDATAPTR>::iterator it = rdatalist_.begin();
it != rdatalist_.end();
++it, ++num_rrs)
{
_name.to_wire(b, c);
_rdtype.to_wire(b);
_rdclass.to_wire(b);
_ttl.to_wire(b);
(**it).to_wire(b, c);
name_.to_wire(buffer, compressor);
rdtype_.to_wire(buffer);
rdclass_.to_wire(buffer);
ttl_.to_wire(buffer);
(**it).to_wire(buffer, compressor);
// TBD: handle truncation case
}
......@@ -273,21 +249,35 @@ Question::to_text() const
{
// return in dig-style format. note that in the wire format class follows
// type.
return (_name.to_text() + " " + _rdclass.to_text() + " " +
_rdtype.to_text());
return (name_.to_text() + " " + rdclass_.to_text() + " " +
rdtype_.to_text());
}
int
Question::to_wire(Message& message, section_t section)
Question::to_wire(Buffer& buffer, NameCompressor& compressor, section_t section)
{
Buffer& b = message.get_iobuffer();
NameCompressor& c = message.get_compressor();
_name.to_wire(b, c);
_rdtype.to_wire(b);
_rdclass.to_wire(b);
name_.to_wire(buffer, compressor);
rdtype_.to_wire(buffer);
rdclass_.to_wire(buffer);
return (1);
}
#endif // notyet
RR::RR(const Name& name, const RRClass& rrclass, const RRType& rrtype,
const TTL& ttl, const Rdata::Rdata& rdata) :
rrset_(name, rrclass, rrtype, ttl)
{
// XXX: this implementation is BAD. we took the ugly bad fastest approach
// for rapid experiment. should rewrite it.
if (rrtype == RRType::A) {
rrset_.add_rdata(Rdata::RDATAPTR(new A(rdata.to_text())));
} else if (rrtype == RRType::AAAA) {
rrset_.add_rdata(Rdata::RDATAPTR(new AAAA(rdata.to_text())));
} else if (rrtype == RRType::NS) {
rrset_.add_rdata(Rdata::RDATAPTR(new NS(rdata.to_text())));
} else {
// XXX
throw std::runtime_error("RR constructor encountered "
"an unsupported type");
}
}
......@@ -110,10 +110,10 @@ namespace Rdata {
// if we worry about data copy, we may have to use
// shared pointers at the cost of depending on boost.
class Rdata;
typedef boost::shared_ptr<Rdata> rdataptr_t;
typedef boost::shared_ptr<Rdata> RDATAPTR;
// if we want to avoid the dependency, use this; but we'll have
// to care much more about resource leak.
//typedef Rdata * rdataptr_t;
//typedef Rdata * RDATAPTR;
// Abstract RDATA class
class Rdata {
......@@ -195,8 +195,8 @@ private:
}
}
// An RRSet. Conceptually it's a named RdataSet. A (section
// of) DNS message would consist of a list of RRSets.
// An RRset. Conceptually it's a named RdataSet. A (section
// of) DNS message would consist of a list of RRsets.
// This is a primary class internally used in our major software such as name
// servers.
//
......@@ -211,28 +211,29 @@ private:
// by one)? ldns has ldns_rr_list_compare(), which takes
// the latter approach (assuming the caller sorts the lists
// beforehand?).
class AbstractRRSet {
class AbstractRRset {
public:
virtual ~AbstractRRSet() {}
virtual ~AbstractRRset() {}
virtual std::string to_text() const = 0;
virtual int to_wire(Message& message, section_t section) = 0;
virtual int to_wire(Buffer& buffer, NameCompressor& compressor,
section_t section) = 0;
virtual unsigned int count_rdata() const = 0;
virtual const Name& get_name() const = 0;
virtual const RRClass& get_class() const = 0;
virtual const RRType& get_type() const = 0;
};
class RRSet : public AbstractRRSet {
class RRset : public AbstractRRset {
public:
RRSet() {}
explicit RRSet(const Name &name, const RRClass &rdclass,
RRset() {}
explicit RRset(const Name &name, const RRClass &rdclass,
const RRType &rdtype, const TTL &ttl) :
name_(name), rdclass_(rdclass), rdtype_(rdtype), ttl_(ttl) {}
unsigned int count_rdata() const { return (rdatalist_.size()); }
void add_rdata(Rdata::rdataptr_t rdata);
void add_rdata(Rdata::RDATAPTR rdata);
void remove_rdata(const Rdata::Rdata& rdata);
std::string to_text() const;
int to_wire(Message& message, section_t section);
int to_wire(Buffer& buffer, NameCompressor& compressor, section_t section);
const Name& get_name() const { return (name_); }
const RRClass& get_class() const { return (rdclass_); }
const RRType& get_type() const { return (rdtype_); }
......@@ -243,24 +244,23 @@ private:
RRClass rdclass_;
RRType rdtype_;
TTL ttl_;
std::vector<Rdata::rdataptr_t> rdatalist_;
std::vector<Rdata::RDATAPTR> rdatalist_;
};
//
// Generic Question section entry
//
class Question : public AbstractRRSet {
class Question : public AbstractRRset {
public:
explicit Question(const Name& name, const RRClass& rdclass,
const RRType& rdtype) :
name_(name), rdclass_(rdclass), rdtype_(rdtype) {}
std::string to_text() const;
int to_wire(Message& message, section_t section);
int to_wire(Buffer& buffer, NameCompressor& compressor, section_t section);
unsigned int count_rdata() const { return (0); }
const Name& get_name() const { return (name_); }
const RRClass& get_class() const { return (rdclass_); }
const RRType& get_type() const { return (rdtype_); }
private:
Name name_;
RRClass rdclass_;
......@@ -270,9 +270,9 @@ private:
// TBD: this interface should be revisited.
template <typename T>
void
RRSet::get_rdatalist(std::vector<T>& v) const
RRset::get_rdatalist(std::vector<T>& v) const
{
std::vector<Rdata::rdataptr_t>::const_iterator it;
std::vector<Rdata::RDATAPTR>::const_iterator it;
for (it = rdatalist_.begin(); it != rdatalist_.end(); ++it) {
const T& concreteRdata = static_cast<const T&>(**it); // XXX
if (T::get_type_static() != (**it).get_type()) {
......@@ -291,18 +291,18 @@ class RR {
public:
RR() {}
explicit RR(const std::string& rrstr);
explicit RR(const Name &name, const RRClass &rdclass,
const RRType &rdtype, const TTL &ttl,
const Rdata::Rdata &rdata);
explicit RR(const Name& name, const RRClass& rdclass,
const RRType& rdtype, const TTL& ttl,
const Rdata::Rdata& rdata);
std::string to_text() const { return (rrset_.to_text()); }
const Name& get_name() const { return (rrset_.get_name()); }
const RRClass& get_class() const { return (rrset_.get_class()); }
const RRType& get_type() const { return (rrset_.get_type()); }
const TTL& get_ttl() const { return (rrset_.get_ttl()); }
private:
// An RR is (could be) actually implemented as an RRSet
// containing at most one RR.
RRSet rrset_;
// An RR is (could be) actually implemented as an RRset containing at most
// one RR.
RRset rrset_;
};
}
}
......
......@@ -21,12 +21,17 @@
namespace {
using ISC::DNS::Name;
using ISC::DNS::RRClass;
using ISC::DNS::RRType;
using ISC::DNS::TTL;
using ISC::DNS::Rdata::RDATAPTR;
using ISC::DNS::Rdata::IN::A;
using ISC::DNS::Rdata::IN::AAAA;
using ISC::DNS::Rdata::Generic::NS;
using ISC::DNS::RRset;
using ISC::DNS::RR;
using ISC::DNS::Question;
// The fixture for testing class RRClass.
class RRClassTest : public ::testing::Test {
......@@ -116,4 +121,80 @@ TEST_F(Rdata_Generic_NS_Test, from_to_text)
{
EXPECT_EQ("ns.example.com.", rdata.to_text());
}
// The fixture for testing class RRset
class RRsetTest : public ::testing::Test {
protected:
RRsetTest() :
rrset_a(Name("www.example.com"), RRClass::IN, RRType::A, TTL(3600)),
rrset_aaaa(Name("ns.example.net"), RRClass::IN, RRType::AAAA, TTL(60))
{
rrset_a.add_rdata(RDATAPTR(new A("192.0.2.1")));
rrset_a.add_rdata(RDATAPTR(new A("192.0.2.255")));
rrset_aaaa.add_rdata(RDATAPTR(new AAAA("2001:db8::1234")));
}
RRset rrset_a;
RRset rrset_aaaa;
};
TEST_F(RRsetTest, to_text)
{
EXPECT_EQ("www.example.com. 3600 IN A 192.0.2.1\n"
"www.example.com. 3600 IN A 192.0.2.255",
rrset_a.to_text());
EXPECT_EQ("ns.example.net. 60 IN AAAA 2001:db8::1234",
rrset_aaaa.to_text());
}
TEST_F(RRsetTest, count_rdata)
{
EXPECT_EQ(2, rrset_a.count_rdata());
EXPECT_EQ(1, rrset_aaaa.count_rdata());
}
// The fixture for testing class Question
class QuestionTest : public ::testing::Test {
protected:
QuestionTest() :
question_a(Name("www.example.com"), RRClass::IN, RRType::A),
question_aaaa(Name("ns.example.net"), RRClass::IN, RRType::AAAA) {}
Question question_a;
Question question_aaaa;
};
TEST_F(QuestionTest, to_text)
{
EXPECT_EQ("www.example.com. IN A", question_a.to_text());
EXPECT_EQ("ns.example.net. IN AAAA", question_aaaa.to_text());
}
TEST_F(QuestionTest, count_rdata)
{
EXPECT_EQ(0, question_a.count_rdata());
EXPECT_EQ(0, question_aaaa.count_rdata());
}
// The fixture for testing class RR
class RRTest : public ::testing::Test {
protected:
RRTest() :
rr_a(Name("www.example.com"), RRClass::IN, RRType::A, TTL(3600),
A("192.0.2.1")),
rr_aaaa(Name("ns.example.net"), RRClass::IN, RRType::AAAA, TTL(60),
AAAA("2001:db8::1234")),
rr_ns(Name("example.net"), RRClass::IN, RRType::NS, TTL(1800),
NS("ns.example.net"))
{}
RR rr_a;
RR rr_aaaa;
RR rr_ns;
};
TEST_F(RRTest, to_text)
{
EXPECT_EQ("www.example.com. 3600 IN A 192.0.2.1", rr_a.to_text());
EXPECT_EQ("ns.example.net. 60 IN AAAA 2001:db8::1234", rr_aaaa.to_text());
EXPECT_EQ("example.net. 1800 IN NS ns.example.net.", rr_ns.to_text());
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment