Browse Source

[2506] handled the case a number is expected but not found

JINMEI Tatuya 12 years ago
parent
commit
ae3a1e5d17

+ 8 - 2
src/lib/dns/master_lexer.cc

@@ -225,8 +225,13 @@ MasterLexer::getNextToken(MasterToken::Type expect, bool eol_ok) {
     }
     if (impl_->token_.getType() != expect) {
         ungetToken();
+        if (is_eol_like) {
+            throw LexerError(__FILE__, __LINE__,
+                             MasterToken(MasterToken::UNEXPECTED_END));
+        }
+        assert(expect == MasterToken::NUMBER);
         throw LexerError(__FILE__, __LINE__,
-                         MasterToken(MasterToken::UNEXPECTED_END));
+                         MasterToken(MasterToken::BAD_NUMBER));
     }
 
     return (impl_->token_);
@@ -251,7 +256,8 @@ const char* const error_text[] = {
     "unexpected end of input",  // UNEXPECTED_END
     "unbalanced quotes",        // UNBALANCED_QUOTES
     "no token produced",        // NO_TOKEN_PRODUCED
-    "number out of range"       // NUMBER_OUT_OF_RANGE
+    "number out of range",      // NUMBER_OUT_OF_RANGE
+    "not a valid number"        // BAD_NUMBER
 };
 const size_t error_text_max_count = sizeof(error_text) / sizeof(error_text[0]);
 } // end unnamed namespace

+ 1 - 0
src/lib/dns/master_lexer.h

@@ -74,6 +74,7 @@ public:
         NO_TOKEN_PRODUCED, ///< No token was produced. This means programmer
                            /// error and should never get out of the lexer.
         NUMBER_OUT_OF_RANGE, ///< Number was out of range
+        BAD_NUMBER,    ///< Number is expected but not recognized
         MAX_ERROR_CODE ///< Max integer corresponding to valid error codes.
                        /// (excluding this one). Mainly for internal use.
     };

+ 4 - 2
src/lib/dns/tests/master_lexer_token_unittest.cc

@@ -141,15 +141,17 @@ TEST_F(MasterLexerTokenTest, errors) {
     EXPECT_EQ("number out of range",
               MasterToken(MasterToken::NUMBER_OUT_OF_RANGE).
               getErrorText());
+    EXPECT_EQ("not a valid number",
+              MasterToken(MasterToken::BAD_NUMBER).getErrorText());
 
     // getErrorCode/Text() isn't allowed for non number types
     EXPECT_THROW(token_num.getErrorCode(), isc::InvalidOperation);
     EXPECT_THROW(token_num.getErrorText(), isc::InvalidOperation);
 
-    // Only the pre-defined error code is accepted.  Hardcoding '6' (max code
+    // Only the pre-defined error code is accepted.  Hardcoding '7' (max code
     // + 1) is intentional; it'd be actually better if we notice it when we
     // update the enum list (which shouldn't happen too often).
-    EXPECT_THROW(MasterToken(MasterToken::ErrorCode(6)),
+    EXPECT_THROW(MasterToken(MasterToken::ErrorCode(7)),
                  isc::InvalidParameter);
 
     // Check the coexistence of "from number" and "from error-code"

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

@@ -359,6 +359,7 @@ TEST_F(MasterLexerTest, getNextTokenQString) {
 TEST_F(MasterLexerTest, getNextTokenNumber) {
     ss << "3600\n";
     ss << "\n";
+    ss << "not-a-number ";
     ss << "86400";
     lexer.pushSource(ss);
 
@@ -370,6 +371,18 @@ TEST_F(MasterLexerTest, getNextTokenNumber) {
     // Skip the 2nd '\n'
     EXPECT_EQ(MasterToken::END_OF_LINE, lexer.getNextToken().getType());
 
+    // Expecting a number, but see a string.
+    bool thrown = false;
+    try {
+        lexer.getNextToken(MasterToken::NUMBER);
+    } catch (const MasterLexer::LexerError& error) {
+        EXPECT_EQ(MasterToken::BAD_NUMBER, error.token_.getErrorCode());
+        thrown = true;
+    }
+    EXPECT_TRUE(thrown);
+    // The unexpected string should have been "ungotten".  Re-read and skip it.
+    EXPECT_EQ(MasterToken::STRING, lexer.getNextToken().getType());
+
     // Unless we specify NUMBER, decimal number string should be recognized
     // as a string.
     EXPECT_EQ("86400",