|
@@ -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);
|