Browse Source

[2382] Merge branch 'trac2497' into trac2382

JINMEI Tatuya 12 years ago
parent
commit
6226330df8

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

@@ -120,6 +120,7 @@ libb10_dns___la_SOURCES += tsigkey.h tsigkey.cc
 libb10_dns___la_SOURCES += tsigrecord.h tsigrecord.cc
 libb10_dns___la_SOURCES += character_string.h character_string.cc
 libb10_dns___la_SOURCES += master_loader_callbacks.h
+libb10_dns___la_SOURCES += master_loader.h
 libb10_dns___la_SOURCES += rdata/generic/detail/nsec_bitmap.h
 libb10_dns___la_SOURCES += rdata/generic/detail/nsec_bitmap.cc
 libb10_dns___la_SOURCES += rdata/generic/detail/nsec3param_common.cc

+ 12 - 2
src/lib/dns/gen-rdatacode.py.in

@@ -28,6 +28,7 @@ re_typecode = re.compile('([\da-z]+)_(\d+)')
 classcode2txt = {}
 typecode2txt = {}
 typeandclass = []
+new_rdatafactory_users = []
 generic_code = 65536            # something larger than any code value
 rdata_declarations = ''
 class_definitions = ''
@@ -271,15 +272,24 @@ def generate_rrparam(fileprefix, basemtime):
         class_utxt = class_tuple[1].upper()
         indent = ' ' * 8
         typeandclassparams += indent
+
+        # By default, we use OldRdataFactory (see bug #2497). If you
+        # want to pick RdataFactory for a particular type, add it to
+        # new_rdatafactory_users.
+        if type_txt in new_rdatafactory_users:
+            rdf_class = 'RdataFactory'
+        else:
+            rdf_class = 'OldRdataFactory'
+
         if class_tuple[1] != 'generic':
             typeandclassparams += 'add("' + type_utxt + '", '
             typeandclassparams += str(type_code) + ', "' + class_utxt
             typeandclassparams += '", ' + str(class_code)
-            typeandclassparams += ', RdataFactoryPtr(new RdataFactory<'
+            typeandclassparams += ', RdataFactoryPtr(new ' + rdf_class + '<'
             typeandclassparams += class_txt + '::' + type_utxt + '>()));\n'
         else:
             typeandclassparams += 'add("' + type_utxt + '", ' + str(type_code)
-            typeandclassparams += ', RdataFactoryPtr(new RdataFactory<'
+            typeandclassparams += ', RdataFactoryPtr(new ' + rdf_class + '<'
             typeandclassparams += class_txt + '::' + type_utxt + '>()));\n'
 
     rrparam_temp = open(placeholder, 'r')

+ 34 - 0
src/lib/dns/master_loader.h

@@ -0,0 +1,34 @@
+// Copyright (C) 2012  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 MASTER_LOADER_H
+#define MASTER_LOADER_H
+
+namespace isc {
+namespace dns {
+
+// Placeholder introduced by #2497. The real class should be updated in
+// #2377.
+class MasterLoader {
+public:
+    enum Options {
+         MANY_ERRORS, // lenient mode
+         // also eventually some check policies like "check NS name"
+    };
+};
+
+}
+}
+
+#endif // MASTER_LOADER_H

+ 1 - 1
src/lib/dns/master_loader_callbacks.h

@@ -119,4 +119,4 @@ private:
 }
 }
 
-#endif // LOADER_CALLBACKS_H
+#endif // MASTER_LOADER_CALLBACKS_H

+ 41 - 2
src/lib/dns/rdata.cc

@@ -65,7 +65,7 @@ createRdata(const RRType& rrtype, const RRClass& rrclass,
     RdataPtr rdata =
         RRParamRegistry::getRegistry().createRdata(rrtype, rrclass, buffer,
                                                    len);
-                                                   
+
     if (buffer.getPosition() - old_pos != len) {
         isc_throw(InvalidRdataLength, "RDLENGTH mismatch: " <<
                   buffer.getPosition() - old_pos << " != " << len);
@@ -81,6 +81,17 @@ createRdata(const RRType& rrtype, const RRClass& rrclass, const Rdata& source)
                                                        source));
 }
 
+RdataPtr
+createRdata(const RRType& rrtype, const RRClass& rrclass,
+            MasterLexer& lexer, const Name* origin,
+            MasterLoader::Options options,
+            MasterLoaderCallbacks& callbacks)
+{
+     return (RRParamRegistry::getRegistry().createRdata(rrtype, rrclass,
+                                                        lexer, origin,
+                                                        options, callbacks));
+}
+
 int
 compareNames(const Name& n1, const Name& n2) {
     size_t len1 = n1.getLength();
@@ -119,7 +130,8 @@ Generic::Generic(isc::util::InputBuffer& buffer, size_t rdata_len) {
     impl_ = new GenericImpl(data);
 }
 
-Generic::Generic(const std::string& rdata_string) {
+void
+Generic::constructHelper(const std::string& rdata_string) {
     istringstream iss(rdata_string);
     string unknown_mark;
     iss >> unknown_mark;
@@ -180,6 +192,33 @@ Generic::Generic(const std::string& rdata_string) {
     impl_ = new GenericImpl(data);
 }
 
+Generic::Generic(const std::string& rdata_string) {
+    constructHelper(rdata_string);
+}
+
+Generic::Generic(MasterLexer& lexer, const Name*,
+                 MasterLoader::Options,
+                 MasterLoaderCallbacks&)
+{
+    std::string s;
+
+    while (true) {
+        const MasterLexer::Token& token = lexer.getNextToken();
+        if ((token.getType() == MasterLexer::Token::END_OF_FILE) ||
+            (token.getType() == MasterLexer::Token::END_OF_LINE)) {
+            break;
+        }
+
+        if (!s.empty()) {
+            s += " ";
+        }
+
+        s += token.getString();
+    }
+
+    constructHelper(s);
+}
+
 Generic::~Generic() {
     delete impl_;
 }

+ 24 - 4
src/lib/dns/rdata.h

@@ -15,11 +15,15 @@
 #ifndef RDATA_H
 #define RDATA_H 1
 
-#include <stdint.h>
+#include <dns/master_lexer.h>
+#include <dns/master_loader.h>
+#include <dns/master_loader_callbacks.h>
+
+#include <exceptions/exceptions.h>
 
 #include <boost/shared_ptr.hpp>
 
-#include <exceptions/exceptions.h>
+#include <stdint.h>
 
 namespace isc {
 namespace util {
@@ -279,6 +283,11 @@ public:
     /// \param rdata_len The length in buffer of the \c Rdata.  In bytes.
     Generic(isc::util::InputBuffer& buffer, size_t rdata_len);
 
+    /// \brief Constructor from master lexer.
+    ///
+    Generic(MasterLexer& lexer, const Name* name,
+            MasterLoader::Options options, MasterLoaderCallbacks& callbacks);
+
     ///
     /// \brief The destructor.
     virtual ~Generic();
@@ -367,7 +376,10 @@ public:
     /// \return > 0 if \c this would be sorted after \c other.
     virtual int compare(const Rdata& other) const;
     //@}
+
 private:
+    void constructHelper(const std::string& rdata_string);
+
     GenericImpl* impl_;
 };
 
@@ -472,6 +484,14 @@ RdataPtr createRdata(const RRType& rrtype, const RRClass& rrclass,
 /// \c Rdata object.
 RdataPtr createRdata(const RRType& rrtype, const RRClass& rrclass,
                      const Rdata& source);
+
+/// \brief Create RDATA of a given pair of RR type and class from the
+/// master lexer.
+RdataPtr createRdata(const RRType& rrtype, const RRClass& rrclass,
+                     MasterLexer& lexer, const Name* origin,
+                     MasterLoader::Options options,
+                     MasterLoaderCallbacks& callbacks);
+
 //@}
 
 ///
@@ -511,6 +531,6 @@ int compareNames(const Name& n1, const Name& n2);
 }
 #endif  // RDATA_H
 
-// Local Variables: 
+// Local Variables:
 // mode: c++
-// End: 
+// End:

+ 67 - 3
src/lib/dns/rrparamregistry-placeholder.cc

@@ -37,10 +37,39 @@ using namespace std;
 using namespace boost;
 
 using namespace isc::util;
-using namespace isc::dns::rdata; 
+using namespace isc::dns::rdata;
 
 namespace isc {
 namespace dns {
+
+namespace rdata {
+
+RdataPtr
+AbstractRdataFactory::create(MasterLexer& lexer, const Name*,
+                             MasterLoader::Options,
+                             MasterLoaderCallbacks&) const
+{
+    std::string s;
+
+    while (true) {
+        const MasterLexer::Token& token = lexer.getNextToken();
+        if ((token.getType() == MasterLexer::Token::END_OF_FILE) ||
+            (token.getType() == MasterLexer::Token::END_OF_LINE)) {
+            break;
+        }
+
+        if (!s.empty()) {
+            s += " ";
+        }
+
+        s += token.getString();
+    }
+
+    return (create(s));
+}
+
+} // end of namespace isc::dns::rdata
+
 namespace {
 ///
 /// The following function and class are a helper to define case-insensitive
@@ -161,8 +190,10 @@ typedef map<RRTypeClass, RdataFactoryPtr> RdataFactoryMap;
 typedef map<RRType, RdataFactoryPtr> GenericRdataFactoryMap;
 
 template <typename T>
-class RdataFactory : public AbstractRdataFactory {
+class OldRdataFactory : public AbstractRdataFactory {
 public:
+    using AbstractRdataFactory::create;
+
     virtual RdataPtr create(const string& rdata_str) const
     {
         return (RdataPtr(new T(rdata_str)));
@@ -179,6 +210,18 @@ public:
     }
 };
 
+template <typename T>
+class RdataFactory : public OldRdataFactory<T> {
+public:
+    using OldRdataFactory<T>::create;
+
+    virtual RdataPtr create(MasterLexer& lexer, const Name* origin,
+                            MasterLoader::Options options,
+                            MasterLoaderCallbacks& callbacks) const {
+        return (RdataPtr(new T(lexer, origin, options, callbacks)));
+    }
+};
+
 ///
 /// \brief The \c RRParamRegistryImpl class is the actual implementation of
 /// \c RRParamRegistry.
@@ -305,7 +348,7 @@ namespace {
 /// This could be simplified using strncasecmp(), but unfortunately it's not
 /// included in <cstring>.  To be as much as portable within the C++ standard
 /// we take the "in house" approach here.
-/// 
+///
 bool CICharEqual(char c1, char c2) {
     return (tolower(static_cast<unsigned char>(c1)) ==
             tolower(static_cast<unsigned char>(c2)));
@@ -528,5 +571,26 @@ RRParamRegistry::createRdata(const RRType& rrtype, const RRClass& rrclass,
     return (RdataPtr(new rdata::generic::Generic(
                          dynamic_cast<const generic::Generic&>(source))));
 }
+
+RdataPtr
+RRParamRegistry::createRdata(const RRType& rrtype, const RRClass& rrclass,
+                             MasterLexer& lexer, const Name* name,
+                             MasterLoader::Options options,
+                             MasterLoaderCallbacks& callbacks)
+{
+    RdataFactoryMap::const_iterator found =
+        impl_->rdata_factories.find(RRTypeClass(rrtype, rrclass));
+    if (found != impl_->rdata_factories.end()) {
+        return (found->second->create(lexer, name, options, callbacks));
+    }
+
+    GenericRdataFactoryMap::const_iterator genfound =
+        impl_->genericrdata_factories.find(rrtype);
+    if (genfound != impl_->genericrdata_factories.end()) {
+        return (genfound->second->create(lexer, name, options, callbacks));
+    }
+
+    return (RdataPtr(new generic::Generic(lexer, name, options, callbacks)));
+}
 }
 }

+ 16 - 5
src/lib/dns/rrparamregistry.h

@@ -82,7 +82,7 @@ public:
     /// \name Factory methods for polymorphic creation.
     ///
     //@{
-    ///
+
     /// \brief Create RDATA from a string.
     ///
     /// This method creates from a string an \c Rdata object of specific class
@@ -91,7 +91,7 @@ public:
     /// \param rdata_str A string of textual representation of the \c Rdata.
     /// \return An \c RdataPtr object pointing to the created \c Rdata object.
     virtual RdataPtr create(const std::string& rdata_str) const = 0;
-    ///
+
     /// \brief Create RDATA from wire-format data.
     ///
     /// This method creates from wire-format binary data an \c Rdata object
@@ -103,7 +103,7 @@ public:
     /// \param rdata_len The length in buffer of the \c Rdata.  In bytes.
     /// \return An \c RdataPtr object pointing to the created \c Rdata object.
     virtual RdataPtr create(isc::util::InputBuffer& buffer, size_t rdata_len) const = 0;
-    ///
+
     /// \brief Create RDATA from another \c Rdata object of the same type.
     ///
     /// This method creates an \c Rdata object of specific class corresponding
@@ -118,6 +118,11 @@ public:
     /// be copied to the created \c Rdata object.
     /// \return An \c RdataPtr object pointing to the created \c Rdata object.
     virtual RdataPtr create(const rdata::Rdata& source) const = 0;
+
+    /// \brief Create RDATA from MasterLexer
+    virtual RdataPtr create(MasterLexer& lexer, const Name*,
+                            MasterLoader::Options,
+                            MasterLoaderCallbacks&) const;
     //@}
 };
 
@@ -498,6 +503,12 @@ public:
     /// \c rdata::Rdata object.
     rdata::RdataPtr createRdata(const RRType& rrtype, const RRClass& rrclass,
                                 const rdata::Rdata& source);
+
+    /// \brief Create RDATA from MasterLexer
+    rdata::RdataPtr createRdata(const RRType& rrtype, const RRClass& rrclass,
+                                MasterLexer& lexer, const Name* name,
+                                MasterLoader::Options options,
+                                MasterLoaderCallbacks& callbacks);
     //@}
 
 private:
@@ -508,6 +519,6 @@ private:
 }
 #endif  // RRPARAMREGISTRY_H
 
-// Local Variables: 
+// Local Variables:
 // mode: c++
-// End: 
+// End:

+ 12 - 0
src/lib/dns/tests/rdata_afsdb_unittest.cc

@@ -114,6 +114,18 @@ TEST_F(Rdata_AFSDB_Test, createFromWire) {
                  DNSMessageFORMERR);
 }
 
+TEST_F(Rdata_AFSDB_Test, createFromLexer) {
+    EXPECT_EQ(0, rdata_afsdb.compare(
+        *test::createRdataUsingLexer(RRType::AFSDB(), RRClass::IN(),
+                                     afsdb_text)));
+
+    // Check that bad input throws as usual
+    EXPECT_THROW({
+        *test::createRdataUsingLexer(RRType::AFSDB(), RRClass::IN(),
+                                     "1root.example.com.");
+    }, InvalidRdataText);
+}
+
 TEST_F(Rdata_AFSDB_Test, toWireBuffer) {
     // construct actual data
     rdata_afsdb.toWire(obuffer);

+ 6 - 0
src/lib/dns/tests/rdata_cname_unittest.cc

@@ -87,6 +87,12 @@ TEST_F(Rdata_CNAME_Test, createFromWire) {
                  InvalidRdataLength);
 }
 
+TEST_F(Rdata_CNAME_Test, createFromLexer) {
+    EXPECT_EQ(0, rdata_cname.compare(
+        *test::createRdataUsingLexer(RRType::CNAME(), RRClass::IN(),
+                                     "cn.example.com")));
+}
+
 TEST_F(Rdata_CNAME_Test, toWireBuffer) {
     rdata_cname.toWire(obuffer);
     EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,

+ 11 - 0
src/lib/dns/tests/rdata_dhcid_unittest.cc

@@ -63,6 +63,17 @@ TEST_F(Rdata_DHCID_Test, createFromWire) {
     // TBD: more tests
 }
 
+TEST_F(Rdata_DHCID_Test, createFromLexer) {
+    EXPECT_EQ(0, rdata_dhcid.compare(
+        *test::createRdataUsingLexer(RRType::DHCID(), RRClass::IN(),
+                                     string_dhcid)));
+
+    // Check that bad input throws as usual
+    EXPECT_THROW({
+        *test::createRdataUsingLexer(RRType::DHCID(), RRClass::IN(), "00");
+    }, isc::BadValue);
+}
+
 TEST_F(Rdata_DHCID_Test, toWireRenderer) {
     rdata_dhcid.toWire(renderer);
 

+ 6 - 0
src/lib/dns/tests/rdata_dname_unittest.cc

@@ -89,6 +89,12 @@ TEST_F(Rdata_DNAME_Test, createFromWire) {
                  InvalidRdataLength);
 }
 
+TEST_F(Rdata_DNAME_Test, createFromLexer) {
+    EXPECT_EQ(0, rdata_dname.compare(
+        *test::createRdataUsingLexer(RRType::DNAME(), RRClass::IN(),
+                                     "dn.example.com")));
+}
+
 TEST_F(Rdata_DNAME_Test, toWireBuffer) {
     rdata_dname.toWire(obuffer);
     EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,

+ 13 - 0
src/lib/dns/tests/rdata_dnskey_unittest.cc

@@ -82,6 +82,19 @@ TEST_F(Rdata_DNSKEY_Test, DISABLED_badText) {
                  InvalidRdataText);
 }
 
+TEST_F(Rdata_DNSKEY_Test, createFromLexer) {
+    generic::DNSKEY rdata_dnskey(dnskey_txt);
+    EXPECT_EQ(0, rdata_dnskey.compare(
+        *test::createRdataUsingLexer(RRType::DNSKEY(), RRClass::IN(),
+                                     dnskey_txt)));
+
+    // Check that bad input throws as usual
+    EXPECT_THROW({
+        *test::createRdataUsingLexer(RRType::DNSKEY(), RRClass::IN(),
+                                     "257 3 5");
+    }, InvalidRdataText);
+}
+
 TEST_F(Rdata_DNSKEY_Test, toWireRenderer) {
     renderer.skip(2);
     generic::DNSKEY rdata_dnskey(dnskey_txt);

+ 13 - 0
src/lib/dns/tests/rdata_hinfo_unittest.cc

@@ -77,6 +77,19 @@ TEST_F(Rdata_HINFO_Test, createFromWire) {
     EXPECT_EQ(string("Linux"), hinfo.getOS());
 }
 
+TEST_F(Rdata_HINFO_Test, createFromLexer) {
+    HINFO rdata_hinfo(hinfo_str);
+    EXPECT_EQ(0, rdata_hinfo.compare(
+        *test::createRdataUsingLexer(RRType::HINFO(), RRClass::IN(),
+                                     hinfo_str)));
+
+    // Check that bad input throws as usual
+    EXPECT_THROW({
+        *test::createRdataUsingLexer(RRType::HINFO(), RRClass::IN(),
+                                     "\"Pentium\"\"Linux\"");
+    }, InvalidRdataText);
+}
+
 TEST_F(Rdata_HINFO_Test, toText) {
     HINFO hinfo(hinfo_str);
     EXPECT_EQ(hinfo_str, hinfo.toText());

+ 5 - 0
src/lib/dns/tests/rdata_in_a_unittest.cc

@@ -68,6 +68,11 @@ TEST_F(Rdata_IN_A_Test, createFromWire) {
                  DNSMessageFORMERR);
 }
 
+TEST_F(Rdata_IN_A_Test, createFromLexer) {
+    EXPECT_EQ(0, rdata_in_a.compare(
+        *test::createRdataUsingLexer(RRType::A(), RRClass::IN(), "192.0.2.1")));
+}
+
 TEST_F(Rdata_IN_A_Test, toWireBuffer) {
     rdata_in_a.toWire(obuffer);
     EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,

+ 6 - 0
src/lib/dns/tests/rdata_in_aaaa_unittest.cc

@@ -66,6 +66,12 @@ TEST_F(Rdata_IN_AAAA_Test, createFromWire) {
                  DNSMessageFORMERR);
 }
 
+TEST_F(Rdata_IN_AAAA_Test, createFromLexer) {
+    EXPECT_EQ(0, rdata_in_aaaa.compare(
+        *test::createRdataUsingLexer(RRType::AAAA(), RRClass::IN(),
+                                     "2001:db8::1234")));
+}
+
 TEST_F(Rdata_IN_AAAA_Test, toWireBuffer) {
     rdata_in_aaaa.toWire(obuffer);
     EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,

+ 6 - 0
src/lib/dns/tests/rdata_minfo_unittest.cc

@@ -103,6 +103,12 @@ TEST_F(Rdata_MINFO_Test, createFromWire) {
                  DNSMessageFORMERR);
 }
 
+TEST_F(Rdata_MINFO_Test, createFromLexer) {
+    EXPECT_EQ(0, rdata_minfo.compare(
+        *test::createRdataUsingLexer(RRType::MINFO(), RRClass::IN(),
+                                     minfo_txt)));
+}
+
 TEST_F(Rdata_MINFO_Test, assignment) {
     generic::MINFO copy((string(minfo_txt2)));
     copy = rdata_minfo;

+ 11 - 0
src/lib/dns/tests/rdata_mx_unittest.cc

@@ -62,6 +62,17 @@ TEST_F(Rdata_MX_Test, createFromWire) {
     // TBD: more tests
 }
 
+TEST_F(Rdata_MX_Test, createFromLexer) {
+    EXPECT_EQ(0, rdata_mx.compare(
+        *test::createRdataUsingLexer(RRType::MX(), RRClass::IN(),
+                                     "10 mx.example.com")));
+
+    EXPECT_THROW({
+        test::createRdataUsingLexer(RRType::MX(), RRClass::IN(),
+                                    "10 mx. example.com");
+    }, InvalidRdataText);
+}
+
 TEST_F(Rdata_MX_Test, toWireRenderer) {
     renderer.writeName(Name("example.com"));
     rdata_mx.toWire(renderer);

+ 15 - 0
src/lib/dns/tests/rdata_naptr_unittest.cc

@@ -128,6 +128,21 @@ TEST_F(Rdata_NAPTR_Test, createFromWire) {
     EXPECT_EQ(Name("_sip._udp.example.com."), naptr.getReplacement());
 }
 
+TEST_F(Rdata_NAPTR_Test, createFromLexer) {
+    NAPTR rdata_naptr(naptr_str);
+
+    EXPECT_EQ(0, rdata_naptr.compare(
+        *test::createRdataUsingLexer(RRType::NAPTR(), RRClass::IN(),
+                                     naptr_str)));
+
+    // Check that bad input throws as usual (order > 65535)
+    EXPECT_THROW({
+        *test::createRdataUsingLexer(RRType::NAPTR(), RRClass::IN(),
+                                     "65536 10 S SIP \"\" "
+                                     "_sip._udp.example.com.");
+    }, InvalidRdataText);
+}
+
 TEST_F(Rdata_NAPTR_Test, toWire) {
     NAPTR naptr(naptr_str);
     naptr.toWire(obuffer);

+ 11 - 0
src/lib/dns/tests/rdata_ns_unittest.cc

@@ -86,6 +86,17 @@ TEST_F(Rdata_NS_Test, createFromWire) {
                  InvalidRdataLength);
 }
 
+TEST_F(Rdata_NS_Test, createFromLexer) {
+    EXPECT_EQ(0, rdata_ns.compare(
+        *test::createRdataUsingLexer(RRType::NS(), RRClass::IN(),
+                                     "ns.example.com")));
+
+    EXPECT_THROW({
+        test::createRdataUsingLexer(RRType::NS(), RRClass::IN(),
+                                    "");
+    }, IncompleteName);
+}
+
 TEST_F(Rdata_NS_Test, toWireBuffer) {
     rdata_ns.toWire(obuffer);
     EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,

+ 8 - 0
src/lib/dns/tests/rdata_opt_unittest.cc

@@ -56,6 +56,14 @@ TEST_F(Rdata_OPT_Test, createFromWire) {
                  InvalidRdataLength);
 }
 
+TEST_F(Rdata_OPT_Test, createFromLexer) {
+    // OPT RR cannot be created from text.
+    EXPECT_THROW({
+        *test::createRdataUsingLexer(RRType::OPT(), RRClass::IN(),
+                                     "this does not matter");
+    }, InvalidRdataText);
+}
+
 TEST_F(Rdata_OPT_Test, toWireBuffer) {
     rdata_opt.toWire(obuffer);
     EXPECT_EQ(0, obuffer.getLength());

+ 6 - 0
src/lib/dns/tests/rdata_ptr_unittest.cc

@@ -90,6 +90,12 @@ TEST_F(Rdata_PTR_Test, createFromWire) {
                  InvalidRdataLength);
 }
 
+TEST_F(Rdata_PTR_Test, createFromLexer) {
+    EXPECT_EQ(0, rdata_ptr.compare(
+        *test::createRdataUsingLexer(RRType::PTR(), RRClass::IN(),
+                                     "ns.example.com")));
+}
+
 TEST_F(Rdata_PTR_Test, toWireBuffer) {
     rdata_ptr.toWire(obuffer);
     EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,

+ 13 - 0
src/lib/dns/tests/rdata_rp_unittest.cc

@@ -106,6 +106,19 @@ TEST_F(Rdata_RP_Test, createFromParams) {
     EXPECT_EQ(text_name, generic::RP(mailbox_name, text_name).getText());
 }
 
+TEST_F(Rdata_RP_Test, createFromLexer) {
+    EXPECT_EQ(0, rdata_rp.compare(
+        *test::createRdataUsingLexer(RRType::RP(), RRClass::IN(),
+                                     "root.example.com. "
+                                     "rp-text.example.com.")));
+
+    // Check that bad input throws as usual
+    EXPECT_THROW({
+        *test::createRdataUsingLexer(RRType::RP(), RRClass::IN(),
+                                     "mailbox.example.com.");
+    }, InvalidRdataText);
+}
+
 TEST_F(Rdata_RP_Test, toWireBuffer) {
     // construct expected data
     UnitTestUtil::readWireData("rdata_rp_toWire1.wire", expected_wire);

+ 32 - 24
src/lib/dns/tests/rdata_rrsig_unittest.cc

@@ -36,16 +36,21 @@ using namespace isc::dns::rdata;
 
 namespace {
 class Rdata_RRSIG_Test : public RdataTest {
-    // there's nothing to specialize
+public:
+    Rdata_RRSIG_Test() :
+        rrsig_txt("A 5 4 43200 20100223214617 20100222214617 8496 isc.org. "
+                  "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz"
+                  "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/"
+                  "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU"
+                  "f49t+sXKPzbipN9g+s1ZPiIyofc="),
+        rdata_rrsig(rrsig_txt)
+    {}
+
+    string rrsig_txt;
+    generic::RRSIG rdata_rrsig;
 };
 
 TEST_F(Rdata_RRSIG_Test, fromText) {
-    string rrsig_txt("A 5 4 43200 20100223214617 20100222214617 8496 isc.org. "
-                     "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz"
-                     "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/"
-                     "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU"
-                     "f49t+sXKPzbipN9g+s1ZPiIyofc=");
-    generic::RRSIG rdata_rrsig(rrsig_txt);
     EXPECT_EQ(rrsig_txt, rdata_rrsig.toText());
     EXPECT_EQ(isc::dns::RRType::A(), rdata_rrsig.typeCovered());
 }
@@ -96,35 +101,38 @@ TEST_F(Rdata_RRSIG_Test, DISABLED_badText) {
                                 "8496isc.org. ofc="), InvalidRdataText);
 }
 
+TEST_F(Rdata_RRSIG_Test, createFromLexer) {
+    EXPECT_EQ(0, rdata_rrsig.compare(
+        *test::createRdataUsingLexer(RRType::RRSIG(), RRClass::IN(),
+                                     rrsig_txt)));
+
+    // Check that bad input throws as usual
+    EXPECT_THROW({
+        *test::createRdataUsingLexer(RRType::RRSIG(), RRClass::IN(),
+                                     "INVALIDINPUT");
+    }, InvalidRdataText);
+}
+
 TEST_F(Rdata_RRSIG_Test, toWireRenderer) {
-    string rrsig_txt("A 5 4 43200 20100223214617 20100222214617 8496 isc.org. "
-                     "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz"
-                     "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/"
-                     "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU"
-                     "f49t+sXKPzbipN9g+s1ZPiIyofc=");
-    generic::RRSIG rdata_rrsig(rrsig_txt);
+    // FIXME: This doesn't check the result.
     rdata_rrsig.toWire(renderer);
 }
 
 TEST_F(Rdata_RRSIG_Test, toWireBuffer) {
-    string rrsig_txt("A 5 4 43200 20100223214617 20100222214617 8496 isc.org. "
-                     "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz"
-                     "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/"
-                     "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU"
-                     "f49t+sXKPzbipN9g+s1ZPiIyofc=");
-    generic::RRSIG rdata_rrsig(rrsig_txt);
+    // FIXME: This doesn't check the result.
     rdata_rrsig.toWire(obuffer);
 }
 
 TEST_F(Rdata_RRSIG_Test, createFromWire) {
-    string rrsig_txt("A 5 2 43200 20100327070149 20100225070149 2658 isc.org. "
+    string rrsig_txt2("A 5 2 43200 20100327070149 20100225070149 2658 isc.org. "
                 "HkJk/xZTvzePU8NENl/ley8bbUumhk1hXciyqhLnz1VQFzkDooej6neX"
                 "ZgWZzQKeTKPOYWrnYtdZW4PnPQFeUl3orgLev7F8J6FZlDn0y/J/ThR5"
                 "m36Mo2/Gdxjj8lJ/IjPVkdpKyBpcnYND8KEIma5MyNCNeyO1UkfPQZGHNSQ=");
-    EXPECT_EQ(rrsig_txt, rdataFactoryFromFile(RRType("RRSIG"), RRClass("IN"),
-                             "rdata_rrsig_fromWire1")->toText());
-    generic::RRSIG rdata_rrsig(rrsig_txt);
-    EXPECT_EQ(0, rdata_rrsig.compare(
+    EXPECT_EQ(rrsig_txt2,
+              rdataFactoryFromFile(RRType("RRSIG"), RRClass("IN"),
+                                   "rdata_rrsig_fromWire1")->toText());
+    generic::RRSIG rdata_rrsig2(rrsig_txt2);
+    EXPECT_EQ(0, rdata_rrsig2.compare(
                       *rdataFactoryFromFile(RRType("RRSIG"), RRClass("IN"),
                                           "rdata_rrsig_fromWire1")));
 

+ 7 - 0
src/lib/dns/tests/rdata_soa_unittest.cc

@@ -49,6 +49,13 @@ TEST_F(Rdata_SOA_Test, createFromWire) {
     // TBD: more tests
 }
 
+TEST_F(Rdata_SOA_Test, createFromLexer) {
+    EXPECT_EQ(0, rdata_soa.compare(
+        *test::createRdataUsingLexer(RRType::SOA(), RRClass::IN(),
+                                     "ns.example.com. root.example.com. "
+                                     "2010012601 3600 300 3600000 1200")));
+}
+
 TEST_F(Rdata_SOA_Test, toWireRenderer) {
     renderer.skip(2);
     rdata_soa.toWire(renderer);

+ 11 - 0
src/lib/dns/tests/rdata_srv_unittest.cc

@@ -119,6 +119,17 @@ TEST_F(Rdata_SRV_Test, createFromWire) {
                                       "rdata_srv_fromWire", 89)));
 }
 
+TEST_F(Rdata_SRV_Test, createFromLexer) {
+    EXPECT_EQ(0, rdata_srv.compare(
+        *test::createRdataUsingLexer(RRType::SRV(), RRClass::IN(),
+                                     "1 5 1500 a.example.com.")));
+    // port is too large
+    EXPECT_THROW({
+        *test::createRdataUsingLexer(RRType::SRV(), RRClass::IN(),
+                                     "1 5 281474976710656 a.example.com.");
+    }, InvalidRdataText);
+}
+
 TEST_F(Rdata_SRV_Test, toWireBuffer) {
     rdata_srv.toWire(obuffer);
     EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,

+ 6 - 0
src/lib/dns/tests/rdata_sshfp_unittest.cc

@@ -68,6 +68,12 @@ TEST_F(Rdata_SSHFP_Test, createFromText) {
     EXPECT_EQ(0, rdata_sshfp4.compare(rdata_sshfp));
 }
 
+TEST_F(Rdata_SSHFP_Test, createFromLexer) {
+    EXPECT_EQ(0, rdata_sshfp.compare(
+        *test::createRdataUsingLexer(RRType::SSHFP(), RRClass::IN(),
+                                     "2 1 123456789abcdef67890123456789abcdef67890")));
+}
+
 TEST_F(Rdata_SSHFP_Test, algorithmTypes) {
     // Some of these may not be RFC conformant, but we relax the check
     // in our code to work with algorithm and fingerprint types that may

+ 28 - 0
src/lib/dns/tests/rdata_unittest.cc

@@ -28,6 +28,8 @@
 #include <dns/tests/unittest_util.h>
 #include <dns/tests/rdata_unittest.h>
 
+#include <boost/bind.hpp>
+
 using isc::UnitTestUtil;
 using namespace std;
 using namespace isc::dns;
@@ -54,6 +56,32 @@ RdataTest::rdataFactoryFromFile(const RRType& rrtype, const RRClass& rrclass,
     uint16_t rdlen = buffer.readUint16();
     return (createRdata(rrtype, rrclass, buffer, rdlen));
 }
+
+namespace test {
+
+void
+dummyCallback(const string&, size_t, const string&) {
+}
+
+RdataPtr
+createRdataUsingLexer(const RRType& rrtype, const RRClass& rrclass,
+                      const std::string& str)
+{
+    std::stringstream ss(str);
+    MasterLexer lexer;
+    lexer.pushSource(ss);
+
+    const MasterLoaderCallbacks::IssueCallback callback
+        (boost::bind(&dummyCallback, _1, _2, _3));
+    MasterLoaderCallbacks callbacks(callback, callback);
+    Name origin("example.org.");
+
+    return (createRdata(rrtype, rrclass, lexer, &origin,
+                        MasterLoader::MANY_ERRORS, callbacks));
+}
+
+} // end of namespace isc::dns::rdata::test
+
 }
 }
 }

+ 9 - 2
src/lib/dns/tests/rdata_unittest.h

@@ -41,11 +41,18 @@ protected:
     /// used to test the compare() method against a well-known RR type.
     RdataPtr rdata_nomatch;
 };
+
+namespace test {
+RdataPtr
+createRdataUsingLexer(const RRType& rrtype, const RRClass& rrclass,
+                      const std::string& str);
+}
+
 }
 }
 }
 #endif // RDATA_UNITTEST_H
 
-// Local Variables: 
+// Local Variables:
 // mode: c++
-// End: 
+// End:

+ 40 - 0
src/lib/dns/tests/rrparamregistry_unittest.cc

@@ -24,6 +24,10 @@
 #include <dns/rdataclass.h>
 #include <dns/rrparamregistry.h>
 #include <dns/rrtype.h>
+#include <dns/master_loader.h>
+
+#include <boost/scoped_ptr.hpp>
+#include <boost/bind.hpp>
 
 using namespace std;
 using namespace isc::dns;
@@ -104,6 +108,7 @@ TEST_F(RRParamRegistryTest, addError) {
 
 class TestRdataFactory : public AbstractRdataFactory {
 public:
+    using AbstractRdataFactory::create;
     virtual RdataPtr create(const string& rdata_str) const
     { return (RdataPtr(new in::A(rdata_str))); }
     virtual RdataPtr create(InputBuffer& buffer, size_t rdata_len) const
@@ -152,4 +157,39 @@ TEST_F(RRParamRegistryTest, addRemoveFactory) {
                      RRType(test_type_code)));
 }
 
+void
+dummyCallback(const string&, size_t, const string&) {
+}
+
+RdataPtr
+createRdataHelper(const std::string& str) {
+    boost::scoped_ptr<AbstractRdataFactory> rdf(new TestRdataFactory);
+
+    std::stringstream ss(str);
+    MasterLexer lexer;
+    lexer.pushSource(ss);
+
+    const MasterLoaderCallbacks::IssueCallback callback
+        (boost::bind(&dummyCallback, _1, _2, _3));
+    MasterLoaderCallbacks callbacks(callback, callback);
+    Name origin("example.org.");
+
+    return (rdf->create(lexer, &origin,
+                        MasterLoader::MANY_ERRORS,
+                        callbacks));
+}
+
+TEST_F(RRParamRegistryTest, createFromLexer) {
+    // This test basically checks that the string version of
+    // AbstractRdataFactory::create() is called by the MasterLexer
+    // variant of create().
+    EXPECT_EQ(0, in::A("192.168.0.1").compare(
+              *createRdataHelper("192.168.0.1")));
+
+    // This should parse only up to the end of line. Everything that
+    // comes afterwards is not parsed.
+    EXPECT_EQ(0, in::A("192.168.0.42").compare(
+              *createRdataHelper("192.168.0.42\na b c d e f")));
+}
+
 }