Browse Source

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
JINMEI Tatuya 15 years ago
parent
commit
1b1b49fa1b
3 changed files with 151 additions and 80 deletions
  1. 46 56
      src/lib/dns/rrset.cc
  2. 24 24
      src/lib/dns/rrset.h
  3. 81 0
      src/lib/dns/rrset_unittest.cc

+ 46 - 56
src/lib/dns/rrset.cc

@@ -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");
+    }
+}

+ 24 - 24
src/lib/dns/rrset.h

@@ -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_;
 };
 }
 }

+ 81 - 0
src/lib/dns/rrset_unittest.cc

@@ -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());
+}
 }