buffet: Add an abstract command dispatch interface
Added simple framework for implementing command dispatch from
buffet to command-handling daemons which concrete delivery
layers, such as D-Bus, can use to actually implement the command
delivery.
Also changed some CommandQueue unit tests to remove the
implementation detail knowledge of how the command IDs are generated.
BUG=chromium:374864
TEST=USE=buffet P2_TEST_FILTER="buffet::*" FEATURES=test emerge-link platform2
Change-Id: Ic7a719a09e924fefedc72cc0bb675adf1acd3713
Reviewed-on: https://chromium-review.googlesource.com/211485
Tested-by: Alex Vakulenko <avakulenko@chromium.org>
Reviewed-by: Christopher Wiley <wiley@chromium.org>
Commit-Queue: Alex Vakulenko <avakulenko@chromium.org>
diff --git a/buffet/commands/command_queue_unittest.cc b/buffet/commands/command_queue_unittest.cc
index d116e96..117d7bc 100644
--- a/buffet/commands/command_queue_unittest.cc
+++ b/buffet/commands/command_queue_unittest.cc
@@ -2,11 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <set>
#include <string>
+#include <vector>
#include <gtest/gtest.h>
+#include "buffet/commands/command_dispatch_interface.h"
#include "buffet/commands/command_queue.h"
+#include "buffet/string_utils.h"
namespace {
@@ -16,6 +20,41 @@
new buffet::CommandInstance(name, "powerd", {}));
}
+// Fake implementation of CommandDispachInterface.
+// Just keeps track of commands being added to and removed from the queue.
+// Aborts if duplicate commands are added or non-existent commands are removed.
+class FakeDispatchInterface : public buffet::CommandDispachInterface {
+ public:
+ virtual void OnCommandAdded(
+ const std::string& command_id,
+ const buffet::CommandInstance* command_instance) override {
+ CHECK(ids_.insert(command_id).second)
+ << "Command ID already exists: " << command_id;
+ CHECK(commands_.insert(command_instance).second)
+ << "Command instance already exists";
+ }
+
+ virtual void OnCommandRemoved(
+ const std::string& command_id,
+ const buffet::CommandInstance* command_instance) override {
+ CHECK_EQ(1, ids_.erase(command_id))
+ << "Command ID not found: " << command_id;
+ CHECK_EQ(1, commands_.erase(command_instance))
+ << "Command instance not found";
+ }
+
+ // Get the comma-separated list of command IDs currently accumulated in the
+ // command queue.
+ std::string GetIDs() const {
+ using buffet::string_utils::Join;
+ return Join(',', std::vector<std::string>(ids_.begin(), ids_.end()));
+ }
+
+ private:
+ std::set<std::string> ids_;
+ std::set<const buffet::CommandInstance*> commands_;
+};
+
} // anonymous namespace
TEST(CommandQueue, Empty) {
@@ -26,10 +65,12 @@
TEST(CommandQueue, Add) {
buffet::CommandQueue queue;
- EXPECT_EQ("1", queue.Add(CreateDummyCommandInstance()));
- EXPECT_EQ("2", queue.Add(CreateDummyCommandInstance()));
- EXPECT_EQ("3", queue.Add(CreateDummyCommandInstance()));
+ std::set<std::string> ids; // Using set<> to check that IDs are unique.
+ ids.insert(queue.Add(CreateDummyCommandInstance()));
+ ids.insert(queue.Add(CreateDummyCommandInstance()));
+ ids.insert(queue.Add(CreateDummyCommandInstance()));
EXPECT_EQ(3, queue.GetCount());
+ EXPECT_EQ(3, ids.size());
EXPECT_FALSE(queue.IsEmpty());
}
@@ -51,6 +92,22 @@
EXPECT_TRUE(queue.IsEmpty());
}
+TEST(CommandQueue, Dispatch) {
+ FakeDispatchInterface dispatch;
+ buffet::CommandQueue queue;
+ queue.SetCommandDispachInterface(&dispatch);
+ std::string id1 = queue.Add(CreateDummyCommandInstance());
+ std::string id2 = queue.Add(CreateDummyCommandInstance());
+ std::set<std::string> ids{id1, id2}; // Make sure they are sorted properly.
+ std::string expected_set = buffet::string_utils::Join(
+ ',', std::vector<std::string>(ids.begin(), ids.end()));
+ EXPECT_EQ(expected_set, dispatch.GetIDs());
+ queue.Remove(id1);
+ EXPECT_EQ(id2, dispatch.GetIDs());
+ queue.Remove(id2);
+ EXPECT_EQ("", dispatch.GetIDs());
+}
+
TEST(CommandQueue, Find) {
buffet::CommandQueue queue;
std::string id1 = queue.Add(CreateDummyCommandInstance("base.reboot"));