Browse Source

[2382] supported extra token case and callback calls on error.

JINMEI Tatuya 12 years ago
parent
commit
f7f3060b97
2 changed files with 81 additions and 16 deletions
  1. 24 3
      src/lib/dns/rdata.cc
  2. 57 13
      src/lib/dns/tests/rdata_unittest.cc

+ 24 - 3
src/lib/dns/rdata.cc

@@ -82,6 +82,24 @@ createRdata(const RRType& rrtype, const RRClass& rrclass, const Rdata& source)
                                                        source));
 }
 
+namespace {
+void
+fromtextError(const MasterLexer& lexer, MasterLoaderCallbacks& callbacks,
+              const MasterToken& token, const char* reason)
+{
+    switch (token.getType()) {
+    case MasterToken::STRING:
+    case MasterToken::QSTRING:
+        callbacks.error(lexer.getSourceName(), lexer.getSourceLine(),
+                        "createRdata from text failed near '" +
+                        token.getString() + "': " + string(reason));
+        break;
+    default:
+        assert(false);
+    }
+}
+}
+
 RdataPtr
 createRdata(const RRType& rrtype, const RRClass& rrclass,
             MasterLexer& lexer, const Name* origin,
@@ -93,10 +111,13 @@ createRdata(const RRType& rrtype, const RRClass& rrclass,
 
     // Consume to end of line / file.
     // If not at end of line initially set error code.
-    // Call callback via fromtext_error once if there was an error.
+    // Call callback via fromtextError once if there was an error.
     const MasterToken& token = lexer.getNextToken();
-    assert(token.getType() == MasterToken::END_OF_LINE ||
-           token.getType() == MasterToken::END_OF_FILE);
+    if (token.getType() != MasterToken::END_OF_LINE &&
+        token.getType() != MasterToken::END_OF_FILE) {
+        fromtextError(lexer, callbacks, token, "extra input text");
+        return (RdataPtr());
+    }
 
     return (rdata);
 }

+ 57 - 13
src/lib/dns/tests/rdata_unittest.cc

@@ -29,6 +29,7 @@
 #include <dns/tests/rdata_unittest.h>
 
 #include <boost/bind.hpp>
+#include <boost/lexical_cast.hpp>
 
 using isc::UnitTestUtil;
 using namespace std;
@@ -82,28 +83,71 @@ createRdataUsingLexer(const RRType& rrtype, const RRClass& rrclass,
 
 } // end of namespace isc::dns::rdata::test
 
+// A mock class to check parameters passed via loader callbacks.  Its callback
+// records the passed parameters, allowing the test to check them later via
+// the check() method.
+class CreateRdataCallback {
+public:
+    enum CallbackType { NONE, ERROR, WARN };
+    CreateRdataCallback() : type_(NONE), line_(0) {}
+    void callback(CallbackType type, const string& source, size_t line,
+                  const string& reason_txt) {
+        type_ = type;
+        source_ = source;
+        line_ = line;
+        reason_txt_ = reason_txt;
+    }
+
+    void clear() {
+        type_ = NONE;
+        source_.clear();
+        line_ = 0;
+        reason_txt_.clear();
+    }
+
+    void check(const string& expected_srcname, size_t expected_line,
+               CallbackType expected_type, const string& expected_reason)
+    {
+        EXPECT_EQ(expected_srcname, source_);
+        EXPECT_EQ(expected_line, line_);
+        EXPECT_EQ(expected_type, type_);
+        EXPECT_EQ(expected_reason, reason_txt_);
+    }
+
+private:
+    CallbackType type_;
+    string source_;
+    size_t line_;
+    string reason_txt_;
+};
+
 // Test class/type-independent behavior of createRdata().
 TEST_F(RdataTest, createRdataWithLexer) {
-    const generic::NS ns_rdata("ns.example.com.");
     const in::AAAA aaaa_rdata("2001:db8::1");
 
     stringstream ss;
-    ss << ns_rdata.toText() << "\n"; // valid case
+    const string src_name = "stream-" + boost::lexical_cast<string>(&ss);
+    ss << aaaa_rdata.toText() << "\n"; // valid case
     ss << aaaa_rdata.toText() << " extra-token\n"; // extra token
     lexer.pushSource(ss);
 
-    const MasterLoaderCallbacks::IssueCallback callback
-        (boost::bind(&test::dummyCallback, _1, _2, _3));
-    MasterLoaderCallbacks callbacks(callback, callback);
-    ConstRdataPtr rdata = createRdata(RRType::NS(), RRClass::IN(), lexer, NULL,
-                                      MasterLoader::MANY_ERRORS, callbacks);
-    EXPECT_EQ(0, ns_rdata.compare(*rdata));
-
-#ifdef notyet
-    rdata = createRdata(RRType::AAAA(), RRClass::IN(), lexer, NULL,
-                        MasterLoader::MANY_ERRORS, callbacks);
+    CreateRdataCallback callback;
+    MasterLoaderCallbacks callbacks(
+        boost::bind(&CreateRdataCallback::callback, &callback,
+                    CreateRdataCallback::ERROR, _1, _2, _3),
+        boost::bind(&CreateRdataCallback::callback, &callback,
+                    CreateRdataCallback::WARN,  _1, _2, _3));
+    ConstRdataPtr rdata = createRdata(RRType::AAAA(), RRClass::IN(), lexer,
+                                      NULL, MasterLoader::MANY_ERRORS,
+                                      callbacks);
     EXPECT_EQ(0, aaaa_rdata.compare(*rdata));
-#endif
+
+    callback.clear();
+    EXPECT_FALSE(createRdata(RRType::AAAA(), RRClass::IN(), lexer, NULL,
+                             MasterLoader::MANY_ERRORS, callbacks));
+    callback.check(src_name, 2, CreateRdataCallback::ERROR,
+                   "createRdata from text failed near 'extra-token': "
+                   "extra input text");
 }
 
 }