BIND 10 trac2375, updated. 09d3147c6a9279aea80cd8fd67705dcc4ee90a18 [2375] Tests for ungetting tokens

BIND 10 source code commits bind10-changes at lists.isc.org
Wed Nov 14 10:01:46 UTC 2012


The branch, trac2375 has been updated
       via  09d3147c6a9279aea80cd8fd67705dcc4ee90a18 (commit)
      from  ab274f6e1401c8ec716ae0ff4b720830809aa278 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 09d3147c6a9279aea80cd8fd67705dcc4ee90a18
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date:   Wed Nov 14 11:01:33 2012 +0100

    [2375] Tests for ungetting tokens

-----------------------------------------------------------------------

Summary of changes:
 src/lib/dns/master_lexer.cc                |   29 +++++---
 src/lib/dns/master_lexer_state.h           |   11 ++-
 src/lib/dns/tests/master_lexer_unittest.cc |  100 ++++++++++++++++++++++++++++
 3 files changed, 128 insertions(+), 12 deletions(-)

-----------------------------------------------------------------------
diff --git a/src/lib/dns/master_lexer.cc b/src/lib/dns/master_lexer.cc
index afe7c33..d5ad77a 100644
--- a/src/lib/dns/master_lexer.cc
+++ b/src/lib/dns/master_lexer.cc
@@ -319,23 +319,30 @@ namespace {
 class FakeState : public State {
 public:
     FakeState(const State* next, size_t eat_chars,
-              MasterLexer::Token* token = NULL,
-              const boost::function<void ()>& callback =
-              boost::function<void ()>()) :
+              MasterLexer::Token* token,
+              int paren_change, const bool* set_eol,
+              const boost::function<void (const std::string&)>& callback) :
         next_(next),
         eat_chars_(eat_chars),
         token_(token),
+        paren_change_(paren_change),
+        set_eol_(set_eol),
         callback_(callback)
     {}
     virtual const State* handle(MasterLexer& lexer) const {
+        std::string input;
         for (size_t i = 0; i < eat_chars_; ++i) {
-            getLexerImpl(lexer)->source_->getChar();
+            input += getLexerImpl(lexer)->source_->getChar();
+        }
+        if (!callback_.empty()) {
+            callback_(input);
         }
         if (token_ != NULL) {
             getLexerImpl(lexer)->token_ = *token_;
         }
-        if (!callback_.empty()) {
-            callback_();
+        getLexerImpl(lexer)->paren_count_ += paren_change_;
+        if (set_eol_ != NULL) {
+            getLexerImpl(lexer)->last_was_eol_ = *set_eol_;
         }
         return (next_);
     }
@@ -343,7 +350,9 @@ private:
     const State* const next_;
     size_t eat_chars_;
     MasterLexer::Token* const token_;
-    const boost::function<void ()> callback_;
+    const int paren_change_;
+    const bool* const set_eol_;
+    const boost::function<void (const std::string&)> callback_;
 };
 
 }
@@ -351,10 +360,12 @@ private:
 State*
 State::getFakeState(const State* next, size_t eat_chars,
                     MasterLexer::Token* token,
-                    const boost::function<void ()>& callback)
+                    int paren_change, const bool* set_eol,
+                    const boost::function<void (const std::string&)>& callback)
 {
     // Just allocate new FakeState with the parameters.
-    return (new FakeState(next, eat_chars, token, callback));
+    return (new FakeState(next, eat_chars, token, paren_change, set_eol,
+                          callback));
 }
 
 } // namespace master_lexer_internal
diff --git a/src/lib/dns/master_lexer_state.h b/src/lib/dns/master_lexer_state.h
index fc6b262..33ac13f 100644
--- a/src/lib/dns/master_lexer_state.h
+++ b/src/lib/dns/master_lexer_state.h
@@ -112,7 +112,9 @@ public:
     ///
     /// The returned State will eat eat_chars from the input source,
     /// it'll set the given token if not NULL, call the given callback
-    /// and return the next state when its handle() is called.
+    /// and return the next state when its handle() is called. Also, the
+    /// parentheses count is changed accordingly a the last EOL condition
+    /// set if provided.
     ///
     /// This is provided only for testing purposes. MasterLexer shouldn't
     /// need this method.
@@ -120,8 +122,11 @@ public:
     /// The caller is responsible for deleting the State.
     static State* getFakeState(const State* next, size_t eat_chars,
                                MasterLexer::Token* token = NULL,
-                               const boost::function<void ()>& callback =
-                               boost::function<void ()>());
+                               int paren_change = 0,
+                               const bool* set_eol = NULL,
+                               const boost::function<void
+                                   (const std::string&)>& callback =
+                               boost::function<void (const std::string&)>());
 
     /// \name Read-only accessors for testing purposes.
     ///
diff --git a/src/lib/dns/tests/master_lexer_unittest.cc b/src/lib/dns/tests/master_lexer_unittest.cc
index 5a9448e..d028923 100644
--- a/src/lib/dns/tests/master_lexer_unittest.cc
+++ b/src/lib/dns/tests/master_lexer_unittest.cc
@@ -22,6 +22,7 @@
 #include <boost/lexical_cast.hpp>
 #include <boost/function.hpp>
 #include <boost/scoped_ptr.hpp>
+#include <boost/bind.hpp>
 
 #include <string>
 #include <sstream>
@@ -269,4 +270,103 @@ TEST_F(MasterLexerTest, eof) {
     EXPECT_THROW(lexer.getNextToken(), isc::InvalidOperation);
 }
 
+void
+checkInput(const std::string& expected, const std::string& received) {
+    EXPECT_EQ(expected, received);
+}
+
+// Check ungetting a token, which should get to the previous state. We do
+// so with changing the state a little bit.
+TEST_F(MasterLexerTest, ungetSimple) {
+    ss << "12345";
+    lexer.pushSource(ss);
+
+    const bool true_value = true, false_value = false;
+    // Make sure we change the state to non-default, so we return to previous
+    // not default state.
+    MasterLexer::Token t0(MasterLexer::Token::INITIAL_WS);
+    scoped_ptr<State> s0(State::getFakeState(NULL, 1, &t0, 1, &true_value));
+    lexer.pushFakeStart(s0.get());
+    EXPECT_EQ(MasterLexer::Token::INITIAL_WS, lexer.getNextToken().getType());
+
+    // Prepare the token to get and return
+    const std::string expected = "234";
+    MasterLexer::Token token(MasterLexer::Token::END_OF_LINE);
+    // Change the internal state with it too. So we can check it is retured.
+    scoped_ptr<State> state(State::getFakeState(NULL, 3, &token, 1,
+                                                &false_value,
+                                                boost::bind(&checkInput,
+                                                            expected, _1)));
+    lexer.pushFakeStart(state.get());
+
+    // Check the internal state before getting the token
+    // We access the lexer through any state, so use the one we have.
+    EXPECT_EQ(1, state->getParenCount(lexer));
+    EXPECT_TRUE(state->wasLastEOL(lexer));
+    EXPECT_EQ(MasterLexer::Token::INITIAL_WS,
+              state->getToken(lexer).getType());
+
+    // Now get the token and check the state changed
+    EXPECT_EQ(MasterLexer::Token::END_OF_LINE, lexer.getNextToken().getType());
+    EXPECT_EQ(2, state->getParenCount(lexer));
+    EXPECT_FALSE(state->wasLastEOL(lexer));
+    EXPECT_EQ(MasterLexer::Token::END_OF_LINE,
+              state->getToken(lexer).getType());
+
+    // Return the token back. Check the state is as it was before.
+    lexer.ungetToken();
+    EXPECT_EQ(1, state->getParenCount(lexer));
+    EXPECT_TRUE(state->wasLastEOL(lexer));
+    EXPECT_EQ(MasterLexer::Token::INITIAL_WS,
+              state->getToken(lexer).getType());
+    // By calling getToken again, we verify even the source got back to
+    // original. We must push it as a fake start again so it is picked.
+    lexer.pushFakeStart(state.get());
+    EXPECT_EQ(MasterLexer::Token::END_OF_LINE, lexer.getNextToken().getType());
+    EXPECT_EQ(2, state->getParenCount(lexer));
+    EXPECT_FALSE(state->wasLastEOL(lexer));
+    EXPECT_EQ(MasterLexer::Token::END_OF_LINE,
+              state->getToken(lexer).getType());
+}
+
+// Check ungetting token without overriding the start method. We also
+// check it works well with changing options between the calls.
+TEST_F(MasterLexerTest, ungetRealOptions) {
+    ss << "    \n";
+    lexer.pushSource(ss);
+
+    // If we call it the usual way, it skips up to the newline and returns
+    // it
+    EXPECT_EQ(MasterLexer::Token::END_OF_LINE, lexer.getNextToken().getType());
+
+    // Now we return it. If we call it again, but with different options,
+    // we get the initial whitespace.
+    EXPECT_EQ(MasterLexer::Token::INITIAL_WS,
+              lexer.getNextToken(MasterLexer::INITIAL_WS).getType());
+}
+
+// Test we can't unget a token before we get one
+TEST_F(MasterLexerTest, ungetBeforeGet) {
+    lexer.pushSource(ss); // Just to eliminate the missing source problem
+    EXPECT_THROW(lexer.ungetToken(), isc::InvalidOperation);
+}
+
+// Test we can't unget a token after a source switch, even when we got
+// something before.
+TEST_F(MasterLexerTest, ungetAfterSwitch) {
+    ss << "\n\n";
+    lexer.pushSource(ss);
+    EXPECT_EQ(MasterLexer::Token::END_OF_LINE, lexer.getNextToken().getType());
+    // Switch the source
+    std::stringstream ss2;
+    ss2 << "\n\n";
+    lexer.pushSource(ss2);
+    EXPECT_THROW(lexer.ungetToken(), isc::InvalidOperation);
+    // We can get from the new source
+    EXPECT_EQ(MasterLexer::Token::END_OF_LINE, lexer.getNextToken().getType());
+    // And when we drop the current source, we can't unget again
+    lexer.popSource();
+    EXPECT_THROW(lexer.ungetToken(), isc::InvalidOperation);
+}
+
 }



More information about the bind10-changes mailing list