buffet: Add command ID to CommandInstance class
Rather than passing command ID along with CommandInstance class,
make it to be part of CommandInstance itself. When a command
instance is added to CommandQueue, the command queue will generate
a new ID and set it to the command instance.
Because CommandInstance, when saved in CommandQueue, is now mutable,
remove 'const' in a bunch of places to allow the command instance
to be modifiable.
BUG=chromium:374864
TEST=USE=buffet P2_TEST_FILTER="buffet::*" FEATURES=test emerge-link platform2
Change-Id: Ia30dd4c9bd86b51694d9345dd91f6ed2ae0cb138
Reviewed-on: https://chromium-review.googlesource.com/213266
Reviewed-by: Chris Sosa <sosa@chromium.org>
Tested-by: Alex Vakulenko <avakulenko@chromium.org>
Commit-Queue: Alex Vakulenko <avakulenko@chromium.org>
diff --git a/buffet/commands/command_dispatch_interface.h b/buffet/commands/command_dispatch_interface.h
index b09c6ec..d1a727d 100644
--- a/buffet/commands/command_dispatch_interface.h
+++ b/buffet/commands/command_dispatch_interface.h
@@ -18,12 +18,10 @@
public:
virtual ~CommandDispachInterface() = default;
// Callback invoked by CommandQueue when a new command is added to the queue.
- virtual void OnCommandAdded(const std::string& command_id,
- const CommandInstance* command_instance) = 0;
+ virtual void OnCommandAdded(CommandInstance* command_instance) = 0;
// Callback invoked by CommandQueue when a new command is removed from
// the queue.
- virtual void OnCommandRemoved(const std::string& command_id,
- const CommandInstance* command_instance) = 0;
+ virtual void OnCommandRemoved(CommandInstance* command_instance) = 0;
};
} // namespace buffet
diff --git a/buffet/commands/command_instance.cc b/buffet/commands/command_instance.cc
index 04b08ab..7c1502c 100644
--- a/buffet/commands/command_instance.cc
+++ b/buffet/commands/command_instance.cc
@@ -72,11 +72,11 @@
} // anonymous namespace
-std::unique_ptr<const CommandInstance> CommandInstance::FromJson(
+std::unique_ptr<CommandInstance> CommandInstance::FromJson(
const base::Value* value,
const CommandDictionary& dictionary,
chromeos::ErrorPtr* error) {
- std::unique_ptr<const CommandInstance> instance;
+ std::unique_ptr<CommandInstance> instance;
// Get the command JSON object from the value.
const base::DictionaryValue* json = nullptr;
if (!value->GetAsDictionary(&json)) {
@@ -114,7 +114,8 @@
return instance;
}
- instance.reset(new CommandInstance(command_name, command_def->GetCategory(),
+ instance.reset(new CommandInstance(command_name,
+ command_def->GetCategory(),
parameters));
return instance;
}
diff --git a/buffet/commands/command_instance.h b/buffet/commands/command_instance.h
index a901380..ebc43ad 100644
--- a/buffet/commands/command_instance.h
+++ b/buffet/commands/command_instance.h
@@ -32,6 +32,8 @@
const std::string& category,
const native_types::Object& parameters);
+ // Returns the full command ID.
+ const std::string& GetID() const { return id_; }
// Returns the full name of the command.
const std::string& GetName() const { return name_; }
// Returns the command category.
@@ -46,12 +48,18 @@
// object, checking the JSON |value| against the command definition schema
// found in command |dictionary|. On error, returns null unique_ptr and
// fills in error details in |error|.
- static std::unique_ptr<const CommandInstance> FromJson(
+ static std::unique_ptr<CommandInstance> FromJson(
const base::Value* value,
const CommandDictionary& dictionary,
chromeos::ErrorPtr* error);
+ // Sets the command ID (normally done by CommandQueue when the command
+ // instance is added to it).
+ void SetID(const std::string& id) { id_ = id; }
+
private:
+ // Unique command ID within a command queue.
+ std::string id_;
// Full command name as "<package_name>.<command_name>".
std::string name_;
// Command category. See comments for CommandDefinitions::LoadCommands for the
diff --git a/buffet/commands/command_instance_unittest.cc b/buffet/commands/command_instance_unittest.cc
index ace0738..844ac92 100644
--- a/buffet/commands/command_instance_unittest.cc
+++ b/buffet/commands/command_instance_unittest.cc
@@ -69,6 +69,7 @@
params.insert(std::make_pair("volume", int_prop.CreateValue(100)));
buffet::CommandInstance instance("robot._beep", "robotd", params);
+ EXPECT_EQ("", instance.GetID());
EXPECT_EQ("robot._beep", instance.GetName());
EXPECT_EQ("robotd", instance.GetCategory());
EXPECT_EQ(params, instance.GetParameters());
@@ -78,6 +79,12 @@
EXPECT_EQ(nullptr, instance.FindParameter("blah").get());
}
+TEST(CommandInstance, SetID) {
+ buffet::CommandInstance instance("robot._beep", "robotd", {});
+ instance.SetID("command_id");
+ EXPECT_EQ("command_id", instance.GetID());
+}
+
TEST_F(CommandInstanceTest, FromJson) {
auto json = CreateDictionaryValue(R"({
'name': 'robot.jump',
diff --git a/buffet/commands/command_queue.cc b/buffet/commands/command_queue.cc
index 671db6d..557a303 100644
--- a/buffet/commands/command_queue.cc
+++ b/buffet/commands/command_queue.cc
@@ -7,31 +7,32 @@
namespace buffet {
-std::string CommandQueue::Add(std::unique_ptr<const CommandInstance> instance) {
+std::string CommandQueue::Add(std::unique_ptr<CommandInstance> instance) {
std::string id = std::to_string(++next_id_);
+ instance->SetID(id);
auto pair = map_.insert(std::make_pair(id, std::move(instance)));
LOG_IF(FATAL, !pair.second) << "Command with ID '" << id
<< "' is already in the queue";
if (dispatch_interface_)
- dispatch_interface_->OnCommandAdded(id, pair.first->second.get());
+ dispatch_interface_->OnCommandAdded(pair.first->second.get());
return id;
}
-std::unique_ptr<const CommandInstance> CommandQueue::Remove(
+std::unique_ptr<CommandInstance> CommandQueue::Remove(
const std::string& id) {
- std::unique_ptr<const CommandInstance> instance;
+ std::unique_ptr<CommandInstance> instance;
auto p = map_.find(id);
if (p != map_.end()) {
instance = std::move(p->second);
map_.erase(p);
if (dispatch_interface_)
- dispatch_interface_->OnCommandRemoved(id, instance.get());
+ dispatch_interface_->OnCommandRemoved(instance.get());
}
return instance;
}
-const CommandInstance* CommandQueue::Find(const std::string& id) const {
+CommandInstance* CommandQueue::Find(const std::string& id) const {
auto p = map_.find(id);
return (p != map_.end()) ? p->second.get() : nullptr;
}
diff --git a/buffet/commands/command_queue.h b/buffet/commands/command_queue.h
index e70fb8d..4e2706b 100644
--- a/buffet/commands/command_queue.h
+++ b/buffet/commands/command_queue.h
@@ -39,21 +39,21 @@
// has no relation to any GCD command identifiers or anything else. Just a
// unique key in this queue class.
// The ID string of the added command is returned by this method.
- std::string Add(std::unique_ptr<const CommandInstance> instance);
+ std::string Add(std::unique_ptr<CommandInstance> instance);
// Removes a command identified by |id| from the queue. Returns a unique
// pointer to the command instance if removed successfully, or an empty
// unique_ptr if the command with the given ID doesn't exist in the queue.
- std::unique_ptr<const CommandInstance> Remove(const std::string& id);
+ std::unique_ptr<CommandInstance> Remove(const std::string& id);
// Finds a command instance in the queue by the instance |id|. Returns
// nullptr if the command with the given |id| is not found. The returned
// pointer should not be persisted for a long period of time.
- const CommandInstance* Find(const std::string& id) const;
+ CommandInstance* Find(const std::string& id) const;
private:
// ID-to-CommandInstance map.
- std::map<std::string, std::unique_ptr<const CommandInstance>> map_;
+ std::map<std::string, std::unique_ptr<CommandInstance>> map_;
// Counter for generating unique command IDs.
int next_id_ = 0;
// Callback interface for command dispatch, if provided.
diff --git a/buffet/commands/command_queue_unittest.cc b/buffet/commands/command_queue_unittest.cc
index a9d5ad9..ce81ea4 100644
--- a/buffet/commands/command_queue_unittest.cc
+++ b/buffet/commands/command_queue_unittest.cc
@@ -14,9 +14,9 @@
namespace {
-std::unique_ptr<const buffet::CommandInstance> CreateDummyCommandInstance(
+std::unique_ptr<buffet::CommandInstance> CreateDummyCommandInstance(
const std::string& name = "base.reboot") {
- return std::unique_ptr<const buffet::CommandInstance>(
+ return std::unique_ptr<buffet::CommandInstance>(
new buffet::CommandInstance(name, "powerd", {}));
}
@@ -25,20 +25,16 @@
// Aborts if duplicate commands are added or non-existent commands are removed.
class FakeDispatchInterface : public buffet::CommandDispachInterface {
public:
- 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;
+ void OnCommandAdded(buffet::CommandInstance* command_instance) override {
+ CHECK(ids_.insert(command_instance->GetID()).second)
+ << "Command ID already exists: " << command_instance->GetID();
CHECK(commands_.insert(command_instance).second)
<< "Command instance already exists";
}
- 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;
+ void OnCommandRemoved(buffet::CommandInstance* command_instance) override {
+ CHECK_EQ(1, ids_.erase(command_instance->GetID()))
+ << "Command ID not found: " << command_instance->GetID();
CHECK_EQ(1, commands_.erase(command_instance))
<< "Command instance not found";
}
@@ -52,7 +48,7 @@
private:
std::set<std::string> ids_;
- std::set<const buffet::CommandInstance*> commands_;
+ std::set<buffet::CommandInstance*> commands_;
};
} // anonymous namespace
@@ -116,7 +112,9 @@
auto cmd1 = queue.Find(id1);
EXPECT_NE(nullptr, cmd1);
EXPECT_EQ("base.reboot", cmd1->GetName());
+ EXPECT_EQ(id1, cmd1->GetID());
auto cmd2 = queue.Find(id2);
EXPECT_NE(nullptr, cmd2);
EXPECT_EQ("base.shutdown", cmd2->GetName());
+ EXPECT_EQ(id2, cmd2->GetID());
}