BIND 10 track1914, updated. 4bdecaadf9b845af3c2b2b11213539a4a0226284 [1914] Basic tests for groupRecvMsgAsync

BIND 10 source code commits bind10-changes at lists.isc.org
Thu May 17 13:14:11 UTC 2012


The branch, track1914 has been updated
       via  4bdecaadf9b845af3c2b2b11213539a4a0226284 (commit)
      from  a43b1b6641de54cc27e7abbf40f0a49c2d9d617a (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 4bdecaadf9b845af3c2b2b11213539a4a0226284
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date:   Thu May 17 15:04:54 2012 +0200

    [1914] Basic tests for groupRecvMsgAsync
    
    * Needed to extend the FakeSession::addMessage to hold the sequence
      number for representing answers.
    * Clarified the recipient parameter - it is the group, instance is
      ignored, since it is not used anywhere in the code anyway.
    * The tests simply register a callback and check it is called. More
      complex tests to come later.

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

Summary of changes:
 src/lib/config/ccsession.h                  |   10 ++-
 src/lib/config/tests/ccsession_unittests.cc |  118 ++++++++++++++++++++++++++-
 src/lib/config/tests/fake_session.cc        |    3 +-
 src/lib/config/tests/fake_session.h         |    2 +-
 4 files changed, 125 insertions(+), 8 deletions(-)

-----------------------------------------------------------------------
diff --git a/src/lib/config/ccsession.h b/src/lib/config/ccsession.h
index 22f4e63..66b8896 100644
--- a/src/lib/config/ccsession.h
+++ b/src/lib/config/ccsession.h
@@ -420,10 +420,11 @@ public:
     /// In case the is_reply is false, the function looks for command messages.
     /// The seq parameter is ignored, but the recipient one is considered. If
     /// it is an empty string, any command is taken. If it is non-empty, only
-    /// commands addressed to the recipient channel are taken. This can be used
-    /// to receive foreign commands or notifications. In such case, it might
-    /// be desirable to call the groupRecvMsgAsync again from within the
-    /// callback, to receive any future commands or events of the same type.
+    /// commands addressed to the recipient channel (eg. group - instance is
+    /// ignored for now)are taken. This can be used to receive foreign commands
+    /// or notifications. In such case, it might be desirable to call the
+    /// groupRecvMsgAsync again from within the callback, to receive any future
+    /// commands or events of the same type.
     ///
     /// The interaction with other receiving functions is slightly complicated.
     /// The groupRecvMsg call takes precedence. If the message matches its
@@ -448,6 +449,7 @@ public:
     ///     command is good one.
     /// \return An identifier of the request. This will be passed to the
     ///     callback or can be used to cancel the request by cancelAsyncRecv.
+    /// \todo Decide what to do with instance and what was it meant for anyway.
     AsyncRecvRequestID groupRecvMsgAsync(const AsyncRecvCallback& callback,
                                          bool is_reply = true, int seq = -1,
                                          const std::string& recipient =
diff --git a/src/lib/config/tests/ccsession_unittests.cc b/src/lib/config/tests/ccsession_unittests.cc
index 55f1f0d..4238731 100644
--- a/src/lib/config/tests/ccsession_unittests.cc
+++ b/src/lib/config/tests/ccsession_unittests.cc
@@ -27,11 +27,13 @@
 #include <log/logger_name.h>
 
 #include <boost/scoped_ptr.hpp>
+#include <boost/bind.hpp>
 
 using namespace isc::data;
 using namespace isc::config;
 using namespace isc::cc;
 using namespace std;
+using namespace boost;
 
 namespace {
 std::string
@@ -497,10 +499,10 @@ TEST_F(CCSessionTest, remoteConfig) {
         const size_t qsize(session.getMsgQueue()->size());
         EXPECT_TRUE(session.getMsgQueue()->get(qsize - 2)->equals(*el(
             "[ \"ConfigManager\", \"*\", { \"command\": ["
-            "\"get_module_spec\", { \"module_name\": \"Spec2\" } ] } ]")));
+            "\"get_module_spec\", { \"module_name\": \"Spec2\" } ] }, -1 ]")));
         EXPECT_TRUE(session.getMsgQueue()->get(qsize - 1)->equals(*el(
             "[ \"ConfigManager\", \"*\", { \"command\": [ \"get_config\","
-            "{ \"module_name\": \"Spec2\" } ] } ]")));
+            "{ \"module_name\": \"Spec2\" } ] }, -1 ]")));
         EXPECT_EQ("Spec2", module_name);
         // Since we returned an empty local config above, the default value
         // for "item1", which is 1, should be used.
@@ -709,6 +711,118 @@ TEST_F(CCSessionTest, doubleStartWithAddRemoteConfig) {
                  FakeSession::DoubleRead);
 }
 
+/// \brief Test fixture for asynchronous receiving of messages.
+///
+/// This is extension to the CCSessionTest. It would be possible to add
+/// the functionality to the CCSessionTest, but it is going to be used
+/// only by few tests and is non-trivial, so it is placed to a separate
+/// sub-class.
+class AsyncReceiveCCSessionTest : public CCSessionTest {
+protected:
+    AsyncReceiveCCSessionTest() :
+        mccs_(ccspecfile("spec29.spec"), session, NULL, NULL, false, false),
+        next_flag_(0)
+    {}
+    /// \brief Convenience function to queue a request to get a command
+    ///     message.
+    ModuleCCSession::AsyncRecvRequestID
+        registerCommand(const string& recipient)
+    {
+        return (mccs_.groupRecvMsgAsync(
+            bind(&AsyncReceiveCCSessionTest::callback, this, next_flag_ ++, _1,
+                 _2, _3), false, -1, recipient));
+    }
+    /// \brief Convenience function to queue a request to get a reply
+    ///     message.
+    ModuleCCSession::AsyncRecvRequestID
+        registerReply(int seq)
+    {
+        return (mccs_.groupRecvMsgAsync(
+            bind(&AsyncReceiveCCSessionTest::callback, this, next_flag_ ++, _1,
+                 _2, _3), false, seq));
+    }
+    /// \brief Check the next called callback was with this flag
+    void called(int flag) {
+        ASSERT_FALSE(called_.empty());
+        EXPECT_EQ(flag, *called_.begin());
+        called_.pop_front();
+    }
+    /// \brief Checks that no more callbacks were called.
+    void nothingCalled() {
+        EXPECT_TRUE(called_.empty());
+    }
+    /// \brief The testet session.
+    ModuleCCSession mccs_;
+    /// \brief The value of message on the last called callback.
+    ConstElementPtr last_msg_;
+private:
+    /// \brief The next flag to be handed out
+    int next_flag_;
+    /// \brief Flags of callbacks already called (as FIFO)
+    list<int> called_;
+    /// \brief This is the callback registered to the tested groupRecvMsgAsync
+    ///     function.
+    void callback(int store_flag, const ConstElementPtr&,
+                  const ConstElementPtr& msg,
+                  const ModuleCCSession::AsyncRecvRequestID&)
+    {
+        called_.push_back(store_flag);
+        last_msg_ = msg;
+    }
+};
+
+// Test we can receive a command, without anything fancy yet
+TEST_F(AsyncReceiveCCSessionTest, simpleCommand) {
+    // Push the message inside
+    ConstElementPtr msg(el("{}"));
+    session.addMessage(msg, "test group", "<unused>");
+    EXPECT_TRUE(mccs_.hasQueuedMsgs());
+    // Register the callback
+    registerCommand("test group");
+    // But the callback should not be called yet
+    // (even if the message is there).
+    nothingCalled();
+    // But when we call the checkCommand(), it should be called.
+    mccs_.checkCommand();
+    called(0);
+    EXPECT_EQ(msg, last_msg_);
+    // But only once
+    nothingCalled();
+    // And the message should be eaten
+    EXPECT_FALSE(mccs_.hasQueuedMsgs());
+    // The callback should have been eaten as well, inserting another
+    // message will not invoke it again
+    session.addMessage(msg, "test group", "<unused>");
+    mccs_.checkCommand();
+    nothingCalled();
+}
+
+// Very similar to simpleCommand, but with a response message
+TEST_F(AsyncReceiveCCSessionTest, simpleResponse) {
+    // Push the message inside
+    ConstElementPtr msg(el("{}"));
+    session.addMessage(msg, "<ignored>", "<unused>", 1);
+    EXPECT_TRUE(mccs_.hasQueuedMsgs());
+    // Register the callback
+    registerReply(1);
+    // But the callback should not be called yet
+    // (even if the message is there).
+    nothingCalled();
+    // But when we call the checkCommand(), it should be called.
+    mccs_.checkCommand();
+    called(0);
+    EXPECT_EQ(msg, last_msg_);
+    // But only once
+    nothingCalled();
+    // And the message should be eaten
+    EXPECT_FALSE(mccs_.hasQueuedMsgs());
+    // The callback should have been eaten as well, inserting another
+    // message will not invoke it again
+    session.addMessage(msg, "test group", "<unused>");
+    mccs_.checkCommand();
+    nothingCalled();
+}
+
 void doRelatedLoggersTest(const char* input, const char* expected) {
     ConstElementPtr all_conf = isc::data::Element::fromJSON(input);
     ConstElementPtr expected_conf = isc::data::Element::fromJSON(expected);
diff --git a/src/lib/config/tests/fake_session.cc b/src/lib/config/tests/fake_session.cc
index 177e629..bf4471d 100644
--- a/src/lib/config/tests/fake_session.cc
+++ b/src/lib/config/tests/fake_session.cc
@@ -228,12 +228,13 @@ FakeSession::getFirstMessage(std::string& group, std::string& to) const {
 
 void
 FakeSession::addMessage(ConstElementPtr msg, const std::string& group,
-                        const std::string& to)
+                        const std::string& to, int seq)
 {
     ElementPtr m_el = Element::createList();
     m_el->add(Element::create(group));
     m_el->add(Element::create(to));
     m_el->add(msg);
+    m_el->add(Element::create(seq));
     if (!msg_queue_) {
         msg_queue_ = Element::createList();
     }
diff --git a/src/lib/config/tests/fake_session.h b/src/lib/config/tests/fake_session.h
index 79ff174..c91b519 100644
--- a/src/lib/config/tests/fake_session.h
+++ b/src/lib/config/tests/fake_session.h
@@ -74,7 +74,7 @@ public:
     isc::data::ConstElementPtr getFirstMessage(std::string& group,
                                                std::string& to) const;
     void addMessage(isc::data::ConstElementPtr, const std::string& group,
-                    const std::string& to);
+                    const std::string& to, int seq = -1);
     bool haveSubscription(const std::string& group,
                           const std::string& instance);
     bool haveSubscription(const isc::data::ConstElementPtr group,



More information about the bind10-changes mailing list