Browse Source

[1144] Merge branch 'trac1144'

Dima Volodin 13 years ago
parent
commit
d267c0511a

+ 4 - 0
ChangeLog

@@ -1,3 +1,7 @@
+292.	[func]		dvv
+	Implement the DLV rrtype according to RFC4431.
+	(Trac #1144, git TBD)
+
 291.    [func]          naokikambe
 	Statistics items are specified by each module's spec file.
 	Stats module can read these through the config manager. Stats

+ 4 - 0
src/lib/dns/Makefile.am

@@ -24,6 +24,9 @@ EXTRA_DIST += rdata/generic/cname_5.h
 EXTRA_DIST += rdata/generic/detail/nsec_bitmap.cc
 EXTRA_DIST += rdata/generic/detail/nsec_bitmap.h
 EXTRA_DIST += rdata/generic/detail/txt_like.h
+EXTRA_DIST += rdata/generic/detail/ds_like.h
+EXTRA_DIST += rdata/generic/dlv_32769.cc
+EXTRA_DIST += rdata/generic/dlv_32769.h
 EXTRA_DIST += rdata/generic/dname_39.cc
 EXTRA_DIST += rdata/generic/dname_39.h
 EXTRA_DIST += rdata/generic/dnskey_48.cc
@@ -107,6 +110,7 @@ libdns___la_SOURCES += character_string.h character_string.cc
 libdns___la_SOURCES += rdata/generic/detail/nsec_bitmap.h
 libdns___la_SOURCES += rdata/generic/detail/nsec_bitmap.cc
 libdns___la_SOURCES += rdata/generic/detail/txt_like.h
+libdns___la_SOURCES += rdata/generic/detail/ds_like.h
 
 libdns___la_CPPFLAGS = $(AM_CPPFLAGS)
 # Most applications of libdns++ will only implicitly rely on libcryptolink,

+ 225 - 0
src/lib/dns/rdata/generic/detail/ds_like.h

@@ -0,0 +1,225 @@
+// 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 __DS_LIKE_H
+#define __DS_LIKE_H 1
+
+#include <stdint.h>
+
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include <boost/lexical_cast.hpp>
+
+#include <exceptions/exceptions.h>
+
+#include <dns/messagerenderer.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace generic {
+namespace detail {
+
+/// \brief \c rdata::DSLikeImpl class represents the DS-like RDATA for DS
+/// and DLV types.
+///
+/// This class implements the basic interfaces inherited by the DS and DLV
+/// classes from the abstract \c rdata::Rdata class, and provides trivial
+/// accessors to DS-like RDATA.
+template <class Type, uint16_t typeCode> class DSLikeImpl {
+    // Common sequence of toWire() operations used for the two versions of
+    // toWire().
+    template <typename Output>
+    void
+    toWireCommon(Output& output) const {
+        output.writeUint16(tag_);
+        output.writeUint8(algorithm_);
+        output.writeUint8(digest_type_);
+        output.writeData(&digest_[0], digest_.size());
+    }
+
+public:
+    /// \brief Constructor from string.
+    ///
+    /// <b>Exceptions</b>
+    ///
+    /// \c InvalidRdataText is thrown if the method cannot process the
+    /// parameter data for any of the number of reasons.
+    DSLikeImpl(const std::string& ds_str) {
+        std::istringstream iss(ds_str);
+        // peekc should be of iss's char_type for isspace to work
+        std::istringstream::char_type peekc;
+        std::stringbuf digestbuf;
+        uint32_t tag, algorithm, digest_type;
+
+        iss >> tag >> algorithm >> digest_type;
+        if (iss.bad() || iss.fail()) {
+            isc_throw(InvalidRdataText,
+                      "Invalid " << RRType(typeCode) << " text");
+        }
+        if (tag > 0xffff) {
+            isc_throw(InvalidRdataText,
+                      RRType(typeCode) << " tag out of range");
+        }
+        if (algorithm > 0xff) {
+            isc_throw(InvalidRdataText,
+                      RRType(typeCode) << " algorithm out of range");
+        }
+        if (digest_type > 0xff) {
+            isc_throw(InvalidRdataText,
+                      RRType(typeCode) << " digest type out of range");
+        }
+
+        iss.read(&peekc, 1);
+        if (!iss.good() || !isspace(peekc, iss.getloc())) {
+            isc_throw(InvalidRdataText,
+                      RRType(typeCode) << " presentation format error");
+        }
+
+        iss >> &digestbuf;
+
+        tag_ = tag;
+        algorithm_ = algorithm;
+        digest_type_ = digest_type;
+        decodeHex(digestbuf.str(), digest_);
+    }
+
+    /// \brief Constructor from wire-format data.
+    ///
+    /// \param buffer A buffer storing the wire format data.
+    /// \param rdata_len The length of the RDATA in bytes, normally expected
+    /// to be the value of the RDLENGTH field of the corresponding RR.
+    ///
+    /// <b>Exceptions</b>
+    ///
+    /// \c InvalidRdataLength is thrown if the input data is too short for the
+    /// type.
+    DSLikeImpl(InputBuffer& buffer, size_t rdata_len) {
+        if (rdata_len < 4) {
+            isc_throw(InvalidRdataLength, RRType(typeCode) << " too short");
+        }
+
+        tag_ = buffer.readUint16();
+        algorithm_ = buffer.readUint8();
+        digest_type_ = buffer.readUint8();
+
+        rdata_len -= 4;
+        digest_.resize(rdata_len);
+        buffer.readData(&digest_[0], rdata_len);
+    }
+
+    /// \brief The copy constructor.
+    ///
+    /// Trivial for now, we could've used the default one.
+    DSLikeImpl(const DSLikeImpl& source) {
+        digest_ = source.digest_;
+        tag_ = source.tag_;
+        algorithm_ = source.algorithm_;
+        digest_type_ = source.digest_type_;
+    }
+
+    /// \brief Convert the DS-like data to a string.
+    ///
+    /// \return A \c string object that represents the DS-like data.
+    std::string
+    toText() const {
+        using namespace boost;
+        return (lexical_cast<string>(static_cast<int>(tag_)) +
+            " " + lexical_cast<string>(static_cast<int>(algorithm_)) +
+            " " + lexical_cast<string>(static_cast<int>(digest_type_)) +
+            " " + encodeHex(digest_));
+    }
+
+    /// \brief Render the DS-like data in the wire format to an OutputBuffer
+    /// object.
+    ///
+    /// \param buffer An output buffer to store the wire data.
+    void
+    toWire(OutputBuffer& buffer) const {
+        toWireCommon(buffer);
+    }
+
+    /// \brief Render the DS-like data in the wire format to an
+    /// AbstractMessageRenderer object.
+    ///
+    /// \param renderer A renderer object to send the wire data to.
+    void
+    toWire(AbstractMessageRenderer& renderer) const {
+        toWireCommon(renderer);
+    }
+
+    /// \brief Compare two instances of DS-like RDATA.
+    ///
+    /// It is up to the caller to make sure that \c other is an object of the
+    /// same \c DSLikeImpl class.
+    ///
+    /// \param other the right-hand operand to compare against.
+    /// \return < 0 if \c this would be sorted before \c other.
+    /// \return 0 if \c this is identical to \c other in terms of sorting
+    /// order.
+    /// \return > 0 if \c this would be sorted after \c other.
+    int
+    compare(const DSLikeImpl& other_ds) const {
+        if (tag_ != other_ds.tag_) {
+            return (tag_ < other_ds.tag_ ? -1 : 1);
+        }
+        if (algorithm_ != other_ds.algorithm_) {
+            return (algorithm_ < other_ds.algorithm_ ? -1 : 1);
+        }
+        if (digest_type_ != other_ds.digest_type_) {
+            return (digest_type_ < other_ds.digest_type_ ? -1 : 1);
+        }
+
+        size_t this_len = digest_.size();
+        size_t other_len = other_ds.digest_.size();
+        size_t cmplen = min(this_len, other_len);
+        int cmp = memcmp(&digest_[0], &other_ds.digest_[0], cmplen);
+        if (cmp != 0) {
+            return (cmp);
+        } else {
+            return ((this_len == other_len)
+                    ? 0 : (this_len < other_len) ? -1 : 1);
+        }
+    }
+
+    /// \brief Accessors
+    uint16_t
+    getTag() const {
+        return (tag_);
+    }
+
+private:
+    // straightforward representation of DS RDATA fields
+    uint16_t tag_;
+    uint8_t algorithm_;
+    uint8_t digest_type_;
+    std::vector<uint8_t> digest_;
+};
+
+}
+}
+}
+}
+}
+#endif //  __DS_LIKE_H
+
+// Local Variables: 
+// mode: c++
+// End: 

+ 121 - 0
src/lib/dns/rdata/generic/dlv_32769.cc

@@ -0,0 +1,121 @@
+// 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 <string>
+
+#include <util/buffer.h>
+#include <util/encode/hex.h>
+
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+
+#include <dns/rdata/generic/detail/ds_like.h>
+
+using namespace std;
+using namespace isc::util;
+using namespace isc::util::encode;
+using namespace isc::dns::rdata::generic::detail;
+
+// BEGIN_ISC_NAMESPACE
+// BEGIN_RDATA_NAMESPACE
+
+/// \brief Constructor from string.
+///
+/// A copy of the implementation object is allocated and constructed.
+DLV::DLV(const string& ds_str) :
+    impl_(new DLVImpl(ds_str))
+{}
+
+/// \brief Constructor from wire-format data.
+///
+/// A copy of the implementation object is allocated and constructed.
+DLV::DLV(InputBuffer& buffer, size_t rdata_len) :
+    impl_(new DLVImpl(buffer, rdata_len))
+{}
+
+/// \brief Copy constructor
+///
+/// A copy of the implementation object is allocated and constructed.
+DLV::DLV(const DLV& source) :
+    Rdata(), impl_(new DLVImpl(*source.impl_))
+{}
+
+/// \brief Assignment operator
+///
+/// PIMPL-induced logic
+DLV&
+DLV::operator=(const DLV& source) {
+    if (impl_ == source.impl_) {
+        return (*this);
+    }
+
+    DLVImpl* newimpl = new DLVImpl(*source.impl_);
+    delete impl_;
+    impl_ = newimpl;
+
+    return (*this);
+}
+
+/// \brief Destructor
+///
+/// Deallocates an internal resource.
+DLV::~DLV() {
+    delete impl_;
+}
+
+/// \brief Convert the \c DLV to a string.
+///
+/// A pass-thru to the corresponding implementation method.
+string
+DLV::toText() const {
+    return (impl_->toText());
+}
+
+/// \brief Render the \c DLV in the wire format to a OutputBuffer object
+///
+/// A pass-thru to the corresponding implementation method.
+void
+DLV::toWire(OutputBuffer& buffer) const {
+    impl_->toWire(buffer);
+}
+
+/// \brief Render the \c DLV in the wire format to a AbstractMessageRenderer
+/// object
+///
+/// A pass-thru to the corresponding implementation method.
+void
+DLV::toWire(AbstractMessageRenderer& renderer) const {
+    impl_->toWire(renderer);
+}
+
+/// \brief Compare two instances of \c DLV RDATA.
+///
+/// The type check is performed here. Otherwise, a pass-thru to the
+/// corresponding implementation method.
+int
+DLV::compare(const Rdata& other) const {
+    const DLV& other_ds = dynamic_cast<const DLV&>(other);
+
+    return (impl_->compare(*other_ds.impl_));
+}
+
+/// \brief Tag accessor
+uint16_t
+DLV::getTag() const {
+    return (impl_->getTag());
+}
+
+// END_RDATA_NAMESPACE
+// END_ISC_NAMESPACE

+ 77 - 0
src/lib/dns/rdata/generic/dlv_32769.h

@@ -0,0 +1,77 @@
+// 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.
+
+// BEGIN_HEADER_GUARD
+
+#include <stdint.h>
+
+#include <string>
+
+#include <dns/name.h>
+#include <dns/rrtype.h>
+#include <dns/rrttl.h>
+#include <dns/rdata.h>
+
+// BEGIN_ISC_NAMESPACE
+
+// BEGIN_COMMON_DECLARATIONS
+// END_COMMON_DECLARATIONS
+
+// BEGIN_RDATA_NAMESPACE
+
+namespace detail {
+template <class Type, uint16_t typeCode> class DSLikeImpl;
+}
+
+/// \brief \c rdata::generic::DLV class represents the DLV RDATA as defined in
+/// RFC4431.
+///
+/// This class implements the basic interfaces inherited from the abstract
+/// \c rdata::Rdata class, and provides trivial accessors specific to the
+/// DLV RDATA.
+class DLV : public Rdata {
+public:
+    // BEGIN_COMMON_MEMBERS
+    // END_COMMON_MEMBERS
+
+    /// \brief Assignment operator.
+    ///
+    /// It internally allocates a resource, and if it fails a corresponding
+    /// standard exception will be thrown.
+    /// This operator never throws an exception otherwise.
+    ///
+    /// This operator provides the strong exception guarantee: When an
+    /// exception is thrown the content of the assignment target will be
+    /// intact.
+    DLV& operator=(const DLV& source);
+
+    /// \brief The destructor.
+    ~DLV();
+
+    /// \brief Return the value of the Tag field.
+    ///
+    /// This method never throws an exception.
+    uint16_t getTag() const;
+private:
+    typedef detail::DSLikeImpl<DLV, 32769> DLVImpl;
+    DLVImpl* impl_;
+};
+
+// END_RDATA_NAMESPACE
+// END_ISC_NAMESPACE
+// END_HEADER_GUARD
+
+// Local Variables: 
+// mode: c++
+// End: 

+ 13 - 96
src/lib/dns/rdata/generic/ds_43.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2010  Internet Systems Consortium, Inc. ("ISC")
+// 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
@@ -12,87 +12,32 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
-#include <iostream>
 #include <string>
-#include <sstream>
-#include <vector>
-
-#include <boost/lexical_cast.hpp>
 
 #include <util/buffer.h>
 #include <util/encode/hex.h>
 
 #include <dns/messagerenderer.h>
-#include <dns/name.h>
 #include <dns/rdata.h>
 #include <dns/rdataclass.h>
 
-#include <stdio.h>
-#include <time.h>
+#include <dns/rdata/generic/detail/ds_like.h>
 
 using namespace std;
 using namespace isc::util;
 using namespace isc::util::encode;
+using namespace isc::dns::rdata::generic::detail;
 
 // BEGIN_ISC_NAMESPACE
 // BEGIN_RDATA_NAMESPACE
 
-struct DSImpl {
-    // straightforward representation of DS RDATA fields
-    DSImpl(uint16_t tag, uint8_t algorithm, uint8_t digest_type,
-           const vector<uint8_t>& digest) :
-        tag_(tag), algorithm_(algorithm), digest_type_(digest_type),
-        digest_(digest)
-    {}
-
-    uint16_t tag_;
-    uint8_t algorithm_;
-    uint8_t digest_type_;
-    const vector<uint8_t> digest_;
-};
-
 DS::DS(const string& ds_str) :
-    impl_(NULL)
-{
-    istringstream iss(ds_str);
-    unsigned int tag, algorithm, digest_type;
-    stringbuf digestbuf;
-
-    iss >> tag >> algorithm >> digest_type >> &digestbuf;
-    if (iss.bad() || iss.fail()) {
-        isc_throw(InvalidRdataText, "Invalid DS text");
-    }
-    if (tag > 0xffff) {
-        isc_throw(InvalidRdataText, "DS tag out of range");
-    }
-    if (algorithm > 0xff) {
-        isc_throw(InvalidRdataText, "DS algorithm out of range");
-    }
-    if (digest_type > 0xff) {
-        isc_throw(InvalidRdataText, "DS digest type out of range");
-    }
-
-    vector<uint8_t> digest;
-    decodeHex(digestbuf.str(), digest);
-
-    impl_ = new DSImpl(tag, algorithm, digest_type, digest);
-}
-
-DS::DS(InputBuffer& buffer, size_t rdata_len) {
-    if (rdata_len < 4) {
-        isc_throw(InvalidRdataLength, "DS too short");
-    }
-
-    uint16_t tag = buffer.readUint16();
-    uint16_t algorithm = buffer.readUint8();
-    uint16_t digest_type = buffer.readUint8();
-
-    rdata_len -= 4;
-    vector<uint8_t> digest(rdata_len);
-    buffer.readData(&digest[0], rdata_len);
+    impl_(new DSImpl(ds_str))
+{}
 
-    impl_ = new DSImpl(tag, algorithm, digest_type, digest);
-}
+DS::DS(InputBuffer& buffer, size_t rdata_len) :
+    impl_(new DSImpl(buffer, rdata_len))
+{}
 
 DS::DS(const DS& source) :
     Rdata(), impl_(new DSImpl(*source.impl_))
@@ -117,57 +62,29 @@ DS::~DS() {
 
 string
 DS::toText() const {
-    using namespace boost;
-    return (lexical_cast<string>(static_cast<int>(impl_->tag_)) +
-        " " + lexical_cast<string>(static_cast<int>(impl_->algorithm_)) +
-        " " + lexical_cast<string>(static_cast<int>(impl_->digest_type_)) +
-        " " + encodeHex(impl_->digest_));
+    return (impl_->toText());
 }
 
 void
 DS::toWire(OutputBuffer& buffer) const {
-    buffer.writeUint16(impl_->tag_);
-    buffer.writeUint8(impl_->algorithm_);
-    buffer.writeUint8(impl_->digest_type_);
-    buffer.writeData(&impl_->digest_[0], impl_->digest_.size());
+    impl_->toWire(buffer);
 }
 
 void
 DS::toWire(AbstractMessageRenderer& renderer) const {
-    renderer.writeUint16(impl_->tag_);
-    renderer.writeUint8(impl_->algorithm_);
-    renderer.writeUint8(impl_->digest_type_);
-    renderer.writeData(&impl_->digest_[0], impl_->digest_.size());
+    impl_->toWire(renderer);
 }
 
 int
 DS::compare(const Rdata& other) const {
     const DS& other_ds = dynamic_cast<const DS&>(other);
 
-    if (impl_->tag_ != other_ds.impl_->tag_) {
-        return (impl_->tag_ < other_ds.impl_->tag_ ? -1 : 1);
-    }
-    if (impl_->algorithm_ != other_ds.impl_->algorithm_) {
-        return (impl_->algorithm_ < other_ds.impl_->algorithm_ ? -1 : 1);
-    }
-    if (impl_->digest_type_ != other_ds.impl_->digest_type_) {
-        return (impl_->digest_type_ < other_ds.impl_->digest_type_ ? -1 : 1);
-    }
-
-    size_t this_len = impl_->digest_.size();
-    size_t other_len = other_ds.impl_->digest_.size();
-    size_t cmplen = min(this_len, other_len);
-    int cmp = memcmp(&impl_->digest_[0], &other_ds.impl_->digest_[0], cmplen);
-    if (cmp != 0) {
-        return (cmp);
-    } else {
-        return ((this_len == other_len) ? 0 : (this_len < other_len) ? -1 : 1);
-    }
+    return (impl_->compare(*other_ds.impl_));
 }
 
 uint16_t
 DS::getTag() const {
-    return (impl_->tag_);
+    return (impl_->getTag());
 }
 
 // END_RDATA_NAMESPACE

+ 27 - 6
src/lib/dns/rdata/generic/ds_43.h

@@ -1,4 +1,4 @@
-// Copyright (C) 2010  Internet Systems Consortium, Inc. ("ISC")
+// 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
@@ -12,6 +12,8 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
+// BEGIN_HEADER_GUARD
+
 #include <stdint.h>
 
 #include <string>
@@ -21,8 +23,6 @@
 #include <dns/rrttl.h>
 #include <dns/rdata.h>
 
-// BEGIN_HEADER_GUARD
-
 // BEGIN_ISC_NAMESPACE
 
 // BEGIN_COMMON_DECLARATIONS
@@ -30,20 +30,41 @@
 
 // BEGIN_RDATA_NAMESPACE
 
-struct DSImpl;
+namespace detail {
+template <class Type, uint16_t typeCode> class DSLikeImpl;
+}
 
+/// \brief \c rdata::generic::DS class represents the DS RDATA as defined in
+/// RFC3658.
+///
+/// This class implements the basic interfaces inherited from the abstract
+/// \c rdata::Rdata class, and provides trivial accessors specific to the
+/// DS RDATA.
 class DS : public Rdata {
 public:
     // BEGIN_COMMON_MEMBERS
     // END_COMMON_MEMBERS
+
+    /// \brief Assignment operator.
+    ///
+    /// It internally allocates a resource, and if it fails a corresponding
+    /// standard exception will be thrown.
+    /// This operator never throws an exception otherwise.
+    ///
+    /// This operator provides the strong exception guarantee: When an
+    /// exception is thrown the content of the assignment target will be
+    /// intact.
     DS& operator=(const DS& source);
+
+    /// \brief The destructor.
     ~DS();
 
+    /// \brief Return the value of the Tag field.
     ///
-    /// Specialized methods
-    ///
+    /// This method never throws an exception.
     uint16_t getTag() const;
 private:
+    typedef detail::DSLikeImpl<DS, 43> DSImpl;
     DSImpl* impl_;
 };
 

+ 1 - 1
src/lib/dns/tests/Makefile.am

@@ -35,7 +35,7 @@ run_unittests_SOURCES += rdata_dname_unittest.cc
 run_unittests_SOURCES += rdata_afsdb_unittest.cc
 run_unittests_SOURCES += rdata_opt_unittest.cc
 run_unittests_SOURCES += rdata_dnskey_unittest.cc
-run_unittests_SOURCES += rdata_ds_unittest.cc
+run_unittests_SOURCES += rdata_ds_like_unittest.cc
 run_unittests_SOURCES += rdata_nsec_unittest.cc
 run_unittests_SOURCES += rdata_nsec3_unittest.cc
 run_unittests_SOURCES += rdata_nsecbitmap_unittest.cc

+ 171 - 0
src/lib/dns/tests/rdata_ds_like_unittest.cc

@@ -0,0 +1,171 @@
+// 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 <algorithm>
+#include <string>
+
+#include <util/buffer.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
+
+using isc::UnitTestUtil;
+using namespace std;
+using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::dns::rdata;
+
+namespace {
+// hacks to make templates work
+template <class T>
+class RRTYPE : public RRType {
+public:
+    RRTYPE();
+};
+
+template<> RRTYPE<generic::DS>::RRTYPE() : RRType(RRType::DS()) {}
+template<> RRTYPE<generic::DLV>::RRTYPE() : RRType(RRType::DLV()) {}
+
+template <class DS_LIKE>
+class Rdata_DS_LIKE_Test : public RdataTest {
+protected:
+    static DS_LIKE const rdata_ds_like;
+};
+
+string ds_like_txt("12892 5 2 F1E184C0E1D615D20EB3C223ACED3B03C773DD952D"
+                   "5F0EB5C777586DE18DA6B5");
+
+template <class DS_LIKE>
+DS_LIKE const Rdata_DS_LIKE_Test<DS_LIKE>::rdata_ds_like(ds_like_txt);
+
+// The list of types we want to test.
+typedef testing::Types<generic::DS, generic::DLV> Implementations;
+
+TYPED_TEST_CASE(Rdata_DS_LIKE_Test, Implementations);
+
+TYPED_TEST(Rdata_DS_LIKE_Test, toText_DS_LIKE) {
+    EXPECT_EQ(ds_like_txt, this->rdata_ds_like.toText());
+}
+
+TYPED_TEST(Rdata_DS_LIKE_Test, badText_DS_LIKE) {
+    EXPECT_THROW(const TypeParam ds_like2("99999 5 2 BEEF"), InvalidRdataText);
+    EXPECT_THROW(const TypeParam ds_like2("11111 555 2 BEEF"),
+                 InvalidRdataText);
+    EXPECT_THROW(const TypeParam ds_like2("11111 5 22222 BEEF"),
+                 InvalidRdataText);
+    EXPECT_THROW(const TypeParam ds_like2("11111 5 2"), InvalidRdataText);
+    EXPECT_THROW(const TypeParam ds_like2("GARBAGE IN"), InvalidRdataText);
+    // no space between the digest type and the digest.
+    EXPECT_THROW(const TypeParam ds_like2(
+                     "12892 5 2F1E184C0E1D615D20EB3C223ACED3B03C773DD952D"
+                     "5F0EB5C777586DE18DA6B5"), InvalidRdataText);
+}
+
+TYPED_TEST(Rdata_DS_LIKE_Test, createFromWire_DS_LIKE) {
+    EXPECT_EQ(0, this->rdata_ds_like.compare(
+              *this->rdataFactoryFromFile(RRTYPE<TypeParam>(), RRClass::IN(),
+                                          "rdata_ds_fromWire")));
+}
+
+TYPED_TEST(Rdata_DS_LIKE_Test, assignment_DS_LIKE) {
+    TypeParam copy((string(ds_like_txt)));
+    copy = this->rdata_ds_like;
+    EXPECT_EQ(0, copy.compare(this->rdata_ds_like));
+
+    // Check if the copied data is valid even after the original is deleted
+    TypeParam* copy2 = new TypeParam(this->rdata_ds_like);
+    TypeParam copy3((string(ds_like_txt)));
+    copy3 = *copy2;
+    delete copy2;
+    EXPECT_EQ(0, copy3.compare(this->rdata_ds_like));
+
+    // Self assignment
+    copy = copy;
+    EXPECT_EQ(0, copy.compare(this->rdata_ds_like));
+}
+
+TYPED_TEST(Rdata_DS_LIKE_Test, getTag_DS_LIKE) {
+    EXPECT_EQ(12892, this->rdata_ds_like.getTag());
+}
+
+TYPED_TEST(Rdata_DS_LIKE_Test, toWireRenderer) {
+    Rdata_DS_LIKE_Test<TypeParam>::renderer.skip(2);
+    TypeParam rdata_ds_like(ds_like_txt);
+    rdata_ds_like.toWire(this->renderer);
+
+    vector<unsigned char> data;
+    UnitTestUtil::readWireData("rdata_ds_fromWire", data);
+    EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
+                        static_cast<const uint8_t*>
+                        (this->obuffer.getData()) + 2,
+                        this->obuffer.getLength() - 2,
+                        &data[2], data.size() - 2);
+}
+
+TYPED_TEST(Rdata_DS_LIKE_Test, toWireBuffer) {
+    TypeParam rdata_ds_like(ds_like_txt);
+    rdata_ds_like.toWire(this->obuffer);
+}
+
+string ds_like_txt1("12892 5 2 F1E184C0E1D615D20EB3C223ACED3B03C773DD952D"
+                   "5F0EB5C777586DE18DA6B5");
+// different tag
+string ds_like_txt2("12893 5 2 F1E184C0E1D615D20EB3C223ACED3B03C773DD952D"
+                   "5F0EB5C777586DE18DA6B5");
+// different algorithm
+string ds_like_txt3("12892 6 2 F1E184C0E1D615D20EB3C223ACED3B03C773DD952D"
+                   "5F0EB5C777586DE18DA6B5");
+// different digest type
+string ds_like_txt4("12892 5 3 F1E184C0E1D615D20EB3C223ACED3B03C773DD952D"
+                   "5F0EB5C777586DE18DA6B5");
+// different digest
+string ds_like_txt5("12892 5 2 F2E184C0E1D615D20EB3C223ACED3B03C773DD952D"
+                   "5F0EB5C777586DE18DA6B5");
+// different digest length
+string ds_like_txt6("12892 5 2 F2E184C0E1D615D20EB3C223ACED3B03C773DD952D"
+                   "5F0EB5C777586DE18DA6B555");
+
+TYPED_TEST(Rdata_DS_LIKE_Test, compare) {
+    // trivial case: self equivalence
+    EXPECT_EQ(0, TypeParam(ds_like_txt).compare(TypeParam(ds_like_txt)));
+
+    // non-equivalence tests
+    EXPECT_LT(TypeParam(ds_like_txt1).compare(TypeParam(ds_like_txt2)), 0);
+    EXPECT_GT(TypeParam(ds_like_txt2).compare(TypeParam(ds_like_txt1)), 0);
+
+    EXPECT_LT(TypeParam(ds_like_txt1).compare(TypeParam(ds_like_txt3)), 0);
+    EXPECT_GT(TypeParam(ds_like_txt3).compare(TypeParam(ds_like_txt1)), 0);
+
+    EXPECT_LT(TypeParam(ds_like_txt1).compare(TypeParam(ds_like_txt4)), 0);
+    EXPECT_GT(TypeParam(ds_like_txt4).compare(TypeParam(ds_like_txt1)), 0);
+
+    EXPECT_LT(TypeParam(ds_like_txt1).compare(TypeParam(ds_like_txt5)), 0);
+    EXPECT_GT(TypeParam(ds_like_txt5).compare(TypeParam(ds_like_txt1)), 0);
+
+    EXPECT_LT(TypeParam(ds_like_txt1).compare(TypeParam(ds_like_txt6)), 0);
+    EXPECT_GT(TypeParam(ds_like_txt6).compare(TypeParam(ds_like_txt1)), 0);
+
+    // comparison attempt between incompatible RR types should be rejected
+    EXPECT_THROW(this->rdata_ds_like.compare(*RdataTest::rdata_nomatch),
+                 bad_cast);
+}
+
+}

+ 0 - 99
src/lib/dns/tests/rdata_ds_unittest.cc

@@ -1,99 +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 <string>
-
-#include <util/buffer.h>
-#include <dns/messagerenderer.h>
-#include <dns/rdata.h>
-#include <dns/rdataclass.h>
-#include <dns/rrclass.h>
-#include <dns/rrtype.h>
-
-#include <gtest/gtest.h>
-
-#include <dns/tests/unittest_util.h>
-#include <dns/tests/rdata_unittest.h>
-
-using isc::UnitTestUtil;
-using namespace std;
-using namespace isc::dns;
-using namespace isc::util;
-using namespace isc::dns::rdata;
-
-namespace {
-class Rdata_DS_Test : public RdataTest {
-    // there's nothing to specialize
-};
-
-string ds_txt("12892 5 2 F1E184C0E1D615D20EB3C223ACED3B03C773DD952D"
-              "5F0EB5C777586DE18DA6B5");
-const generic::DS rdata_ds(ds_txt);
-
-TEST_F(Rdata_DS_Test, toText_DS) {
-    EXPECT_EQ(ds_txt, rdata_ds.toText());
-}
-
-TEST_F(Rdata_DS_Test, badText_DS) {
-    EXPECT_THROW(const generic::DS ds2("99999 5 2 BEEF"), InvalidRdataText);
-    EXPECT_THROW(const generic::DS ds2("11111 555 2 BEEF"), InvalidRdataText);
-    EXPECT_THROW(const generic::DS ds2("11111 5 22222 BEEF"), InvalidRdataText);
-    EXPECT_THROW(const generic::DS ds2("11111 5 2"), InvalidRdataText);
-    EXPECT_THROW(const generic::DS ds2("GARBAGE IN"), InvalidRdataText);
-}
-
-// this test currently fails; we must fix it, and then migrate the test to
-// badText_DS
-TEST_F(Rdata_DS_Test, DISABLED_badText_DS) {
-    // no space between the digest type and the digest.
-    EXPECT_THROW(const generic::DS ds2(
-                     "12892 5 2F1E184C0E1D615D20EB3C223ACED3B03C773DD952D"
-                     "5F0EB5C777586DE18DA6B5"), InvalidRdataText);
-}
-
-TEST_F(Rdata_DS_Test, createFromWire_DS) {
-    EXPECT_EQ(0, rdata_ds.compare(
-                  *rdataFactoryFromFile(RRType::DS(), RRClass::IN(),
-                                        "rdata_ds_fromWire")));
-}
-
-TEST_F(Rdata_DS_Test, getTag_DS) {
-    EXPECT_EQ(12892, rdata_ds.getTag());
-}
-
-TEST_F(Rdata_DS_Test, toWireRenderer) {
-    renderer.skip(2);
-    generic::DS rdata_ds(ds_txt);
-    rdata_ds.toWire(renderer);
-
-    vector<unsigned char> data;
-    UnitTestUtil::readWireData("rdata_ds_fromWire", data);
-    EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
-                        static_cast<const uint8_t *>(obuffer.getData()) + 2,
-                        obuffer.getLength() - 2, &data[2], data.size() - 2);
-}
-
-TEST_F(Rdata_DS_Test, toWireBuffer) {
-    generic::DS rdata_ds(ds_txt);
-    rdata_ds.toWire(obuffer);
-}
-
-TEST_F(Rdata_DS_Test, compare) {
-    // trivial case: self equivalence
-    EXPECT_EQ(0, generic::DS(ds_txt).compare(generic::DS(ds_txt)));
-
-    // TODO: need more tests
-}
-
-}

+ 4 - 1
tests/system/cleanall.sh

@@ -27,7 +27,10 @@ find . -type f \( \
 
 status=0
 
-for d in `find . -type d -maxdepth 1 -mindepth 1 -print`
+for d in ./.* ./*
 do
+   case $d in ./.|./..) continue ;; esac
+   test -d $d || continue
+
    test ! -f $d/clean.sh || ( cd $d && sh clean.sh )
 done