Parcourir la source

[2371] catch an error in opening a source file and gives feedback to caller.

JINMEI Tatuya il y a 12 ans
Parent
commit
7a72794ffa

+ 12 - 3
src/lib/dns/master_lexer.cc

@@ -46,13 +46,22 @@ MasterLexer::~MasterLexer() {
     delete impl_;
 }
 
-void
-MasterLexer::pushSource(const char* filename) {
+bool
+MasterLexer::pushSource(const char* filename, std::string* error) {
     if (filename == NULL) {
         isc_throw(InvalidParameter,
                   "NULL filename for MasterLexer::pushSource");
     }
-    impl_->sources_.push_back(InputSourcePtr(new InputSource(filename)));
+    try {
+        impl_->sources_.push_back(InputSourcePtr(new InputSource(filename)));
+    } catch (const InputSource::OpenError& ex) {
+        if (error != NULL) {
+            *error = ex.what();
+        }
+        return (false);
+    }
+
+    return (true);
 }
 
 void

+ 12 - 2
src/lib/dns/master_lexer.h

@@ -62,10 +62,20 @@ public:
     /// if \c popSource() is not called within the lifetime of the
     /// \c MasterLexer, it will be closed in the destructor.
     ///
+    /// In the case possible system errors in opening the file (most likely
+    /// because of specifying a non-existent or unreadable file), it returns
+    /// false, and if the optional \c error parameter is non NULL, it will be
+    /// set to a description of the error (any existing content of the string
+    /// will be discarded).  If opening the file succeeds, the given
+    /// \c error parameter will be intact.
+    ///
     /// \throw InvalidParameter filename is NULL
-    /// \throw some_other The specified cannot be opened
     /// \param filename A non NULL string specifying a master file
-    void pushSource(const char* filename);
+    /// \param error If non null, a placeholder to set error description in
+    /// case of failure.
+    ///
+    /// \return true if pushing the file succeeds; false otherwise.
+    bool pushSource(const char* filename, std::string* error = NULL);
 
     /// \brief Make the given stream the current input source of MasterLexer.
     ///

+ 22 - 1
src/lib/dns/tests/master_lexer_unittest.cc

@@ -70,18 +70,39 @@ TEST_F(MasterLexerTest, pushStream) {
 TEST_F(MasterLexerTest, pushFile) {
     // We use zone file (-like) data, but in this test that actually doesn't
     // matter.
-    lexer.pushSource(TEST_DATA_SRCDIR "/masterload.txt");
+    EXPECT_TRUE(lexer.pushSource(TEST_DATA_SRCDIR "/masterload.txt"));
     EXPECT_EQ(TEST_DATA_SRCDIR "/masterload.txt", lexer.getSourceName());
     EXPECT_EQ(1, lexer.getSourceLine());
 
     lexer.popSource();
     checkEmptySource(lexer);
+
+    // If we give a non NULL string pointer, its content will be intact
+    // if pushSource succeeds.
+    std::string error_txt = "dummy";
+    EXPECT_TRUE(lexer.pushSource(TEST_DATA_SRCDIR "/masterload.txt",
+                                 &error_txt));
+    EXPECT_EQ("dummy", error_txt);
 }
 
 TEST_F(MasterLexerTest, pushBadFileName) {
     EXPECT_THROW(lexer.pushSource(NULL), isc::InvalidParameter);
 }
 
+TEST_F(MasterLexerTest, pushFileFail) {
+    // The file to be pushed doesn't exist.  pushSource() fails and
+    // some non empty error string should be set.
+    std::string error_txt;
+    EXPECT_TRUE(error_txt.empty());
+    EXPECT_FALSE(lexer.pushSource("no-such-file", &error_txt));
+    EXPECT_FALSE(error_txt.empty());
+
+    // It's safe to pass NULL error_txt (either explicitly or implicitly as
+    // the default)
+    EXPECT_FALSE(lexer.pushSource("no-such-file", NULL));
+    EXPECT_FALSE(lexer.pushSource("no-such-file"));
+}
+
 TEST_F(MasterLexerTest, nestedPush) {
     lexer.pushSource(ss);
     EXPECT_EQ(expected_stream_name, lexer.getSourceName());