Browse Source

[2522] add MasterLexer constructor for RP

Paul Selkirk 12 years ago
parent
commit
3d234878c7

+ 50 - 21
src/lib/dns/rdata/generic/rp_17.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2013  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
@@ -21,14 +21,22 @@
 #include <dns/name.h>
 #include <dns/rdata.h>
 #include <dns/rdataclass.h>
+#include <dns/rdata/generic/detail/lexer_util.h>
 
 using namespace std;
 using namespace isc::dns;
 using namespace isc::util;
+using isc::dns::rdata::generic::detail::createNameFromLexer;
 
 // BEGIN_ISC_NAMESPACE
 // BEGIN_RDATA_NAMESPACE
 
+// helper function for string and lexer constructors
+void RP::constructFromLexer(MasterLexer& lexer, const Name* origin) {
+    mailbox_ = createNameFromLexer(lexer, origin);
+    text_ = createNameFromLexer(lexer, origin);
+}
+
 /// \brief Constructor from string.
 ///
 /// \c rp_str must be formatted as follows:
@@ -36,32 +44,53 @@ using namespace isc::util;
 /// \endcode
 /// where both fields must represent a valid domain name.
 ///
-/// \exception InvalidRdataText The number of RDATA fields (must be 2) is
+/// \throw InvalidRdataText The number of RDATA fields (must be 2) is
 /// incorrect.
-/// \exception Other The constructor of the \c Name class will throw if the
+/// \throw Other The constructor of the \c Name class will throw if the
 /// given name is invalid.
-/// \exception std::bad_alloc Memory allocation for names fails.
+/// \throw std::bad_alloc Memory allocation for names fails.
 RP::RP(const std::string& rp_str) :
     // We cannot construct both names in the initialization list due to the
     // necessary text processing, so we have to initialize them with a dummy
     // name and replace them later.
     mailbox_(Name::ROOT_NAME()), text_(Name::ROOT_NAME())
 {
-    istringstream iss(rp_str);
-    string mailbox_str, text_str;
-    iss >> mailbox_str >> text_str;
-
-    // Validation: A valid RP RR must have exactly two fields.
-    if (iss.bad() || iss.fail()) {
-        isc_throw(InvalidRdataText, "Invalid RP text: " << rp_str);
-    }
-    if (!iss.eof()) {
-        isc_throw(InvalidRdataText, "Invalid RP text (redundant field): "
-                  << rp_str);
+    try {
+        std::istringstream ss(rp_str);
+        MasterLexer lexer;
+        lexer.pushSource(ss);
+
+        constructFromLexer(lexer, NULL);
+
+        if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+            isc_throw(InvalidRdataText, "extra input text for RP: "
+                      << rp_str);
+        }
+    } catch (const MasterLexer::LexerError& ex) {
+        isc_throw(InvalidRdataText, "Failed to construct RP from '" <<
+                  rp_str << "': " << ex.what());
     }
+}
 
-    mailbox_ = Name(mailbox_str);
-    text_ = Name(text_str);
+/// \brief Constructor with a context of MasterLexer.
+///
+/// The \c lexer should point to the beginning of valid textual representation
+/// of an RP RDATA.  The MAILBOX and TEXT fields can be non-absolute if \c
+/// origin is non-NULL, in which case \c origin is used to make them absolute.
+///
+/// \throw MasterLexer::LexerError General parsing error such as missing field.
+/// \throw Other Exceptions from the Name and constructors if construction of
+/// textual fields as these objects fail.
+///
+/// \param lexer A \c MasterLexer object parsing a master file for the
+/// RDATA to be created
+/// \param origin If non NULL, specifies the origin of SERVER when it
+/// is non-absolute.
+RP::RP(MasterLexer& lexer, const Name* origin,
+       MasterLoader::Options, MasterLoaderCallbacks&) :
+    mailbox_(Name::ROOT_NAME()), text_(Name::ROOT_NAME())
+{
+    constructFromLexer(lexer, origin);
 }
 
 /// \brief Constructor from wire-format data.
@@ -70,15 +99,15 @@ RP::RP(const std::string& rp_str) :
 /// length) for parsing.
 /// If necessary, the caller will check consistency.
 ///
-/// \exception std::bad_alloc Memory allocation for names fails.
-/// \exception Other The constructor of the \c Name class will throw if the
+/// \throw std::bad_alloc Memory allocation for names fails.
+/// \throw Other The constructor of the \c Name class will throw if the
 /// names in the wire is invalid.
 RP::RP(InputBuffer& buffer, size_t) : mailbox_(buffer), text_(buffer) {
 }
 
 /// \brief Copy constructor.
 ///
-/// \exception std::bad_alloc Memory allocation fails in copying internal
+/// \throw std::bad_alloc Memory allocation fails in copying internal
 /// member variables (this should be very rare).
 RP::RP(const RP& other) :
     Rdata(), mailbox_(other.mailbox_), text_(other.text_)
@@ -89,7 +118,7 @@ RP::RP(const RP& other) :
 /// The output of this method is formatted as described in the "from string"
 /// constructor (\c RP(const std::string&))).
 ///
-/// \exception std::bad_alloc Internal resource allocation fails.
+/// \throw std::bad_alloc Internal resource allocation fails.
 ///
 /// \return A \c string object that represents the \c RP object.
 std::string

+ 4 - 1
src/lib/dns/rdata/generic/rp_17.h

@@ -1,4 +1,4 @@
-// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2013  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
@@ -75,6 +75,9 @@ public:
     Name getText() const { return (text_); }
 
 private:
+    // helper function for string and lexer constructors
+    void constructFromLexer(MasterLexer& lexer, const Name* origin);
+
     Name mailbox_;
     Name text_;
 };

+ 36 - 6
src/lib/dns/tests/rdata_rp_unittest.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2013  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
@@ -41,6 +41,23 @@ protected:
         obuffer(0)
     {}
 
+    void checkFromText_LexerError(const string& rdata_str) {
+        checkFromText
+            <generic::RP, InvalidRdataText, MasterLexer::LexerError>(
+                rdata_str, rdata_rp, true, true);
+    }
+
+    void checkFromText_MissingOrigin(const string& rdata_str) {
+        checkFromText
+            <generic::RP, MissingNameOrigin, MissingNameOrigin>(
+                rdata_str, rdata_rp, true, true);
+    }
+
+    void checkFromText_EmptyLabel(const string& rdata_str) {
+        checkFromText<generic::RP, EmptyLabel, EmptyLabel>(
+            rdata_str, rdata_rp, true, true);
+    }
+
     const Name mailbox_name, text_name;
     const generic::RP rdata_rp; // commonly used test RDATA
     OutputBuffer obuffer;
@@ -54,14 +71,15 @@ TEST_F(Rdata_RP_Test, createFromText) {
 
     // Invalid textual input cases follow:
     // names are invalid
-    EXPECT_THROW(generic::RP("bad..name. rp-text.example.com"), EmptyLabel);
-    EXPECT_THROW(generic::RP("mailbox.example.com. bad..name"), EmptyLabel);
+    checkFromText_EmptyLabel("bad..name. rp-text.example.com.");
+    checkFromText_EmptyLabel("root.example.com. bad..name.");
+    checkFromText_MissingOrigin("root.example.com rp-text.example.com");
 
     // missing field
-    EXPECT_THROW(generic::RP("mailbox.example.com."), InvalidRdataText);
+    checkFromText_LexerError("root.example.com.");
 
     // redundant field
-    EXPECT_THROW(generic::RP("mailbox.example.com. rp-text.example.com. "
+    EXPECT_THROW(generic::RP("root.example.com. rp-text.example.com. "
                              "redundant.example."), InvalidRdataText);
 }
 
@@ -112,9 +130,21 @@ TEST_F(Rdata_RP_Test, createFromLexer) {
                                      "root.example.com. "
                                      "rp-text.example.com.")));
 
+    // test::createRdataUsingLexer() constructs relative to
+    // "example.org." origin.
+    EXPECT_EQ(0, generic::RP("root.example.org. rp-text.example.org.").compare(
+        *test::createRdataUsingLexer(RRType::RP(), RRClass::IN(),
+                                     "root rp-text")));
+
     // Exceptions cause NULL to be returned.
     EXPECT_FALSE(test::createRdataUsingLexer(RRType::RP(), RRClass::IN(),
-                                             "mailbox.example.com."));
+                                             "root.example.com."));
+
+    // acceptable??
+    EXPECT_NO_THROW(test::createRdataUsingLexer(RRType::RP(), RRClass::IN(),
+                                                "root.example.com. "
+                                                "rp-text.example.com. "
+                                                "redundant.example.com."));
 }
 
 TEST_F(Rdata_RP_Test, toWireBuffer) {