Fix a crash when adding a default command handler
It is allowed to call ComponentManager::AddCommandHandler with
empty component and command name to indicate that we are installing
a default command handler. The CHECK() condition should be only
verified if a specific command handler is specified.
Change-Id: Ib4c0f633e5e4ddc396a4f5030a6ebd4e411f911e
Reviewed-on: https://weave-review.googlesource.com/1820
Reviewed-by: Vitaly Buka <vitalybuka@google.com>
diff --git a/src/component_manager_impl.cc b/src/component_manager_impl.cc
index 8f685b3..a23f34d 100644
--- a/src/component_manager_impl.cc
+++ b/src/component_manager_impl.cc
@@ -266,8 +266,12 @@
const std::string& component_path,
const std::string& command_name,
const Device::CommandHandlerCallback& callback) {
- CHECK(FindCommandDefinition(command_name))
- << "Command undefined: " << command_name;
+ // If both component_path and command_name are empty, we are adding the
+ // default handler for all commands.
+ if (!component_path.empty() || !command_name.empty()) {
+ CHECK(FindCommandDefinition(command_name))
+ << "Command undefined: " << command_name;
+ }
command_queue_.AddCommandHandler(component_path, command_name, callback);
}
diff --git a/src/component_manager_unittest.cc b/src/component_manager_unittest.cc
index b35e16a..902ee15 100644
--- a/src/component_manager_unittest.cc
+++ b/src/component_manager_unittest.cc
@@ -819,6 +819,55 @@
last_tags.clear();
}
+TEST(ComponentManager, AddDefaultCommandHandler) {
+ ComponentManagerImpl manager;
+ const char kTraits[] = R"({
+ "trait1": {
+ "commands": {
+ "command1": { "minimalRole": "user" }
+ }
+ },
+ "trait2": {
+ "commands": {
+ "command2": { "minimalRole": "user" }
+ }
+ }
+ })";
+ auto traits = CreateDictionaryValue(kTraits);
+ ASSERT_TRUE(manager.LoadTraits(*traits, nullptr));
+ ASSERT_TRUE(manager.AddComponent("", "comp", {"trait1", "trait2"}, nullptr));
+
+ int count = 0;
+ auto handler = [&count](int tag, const std::weak_ptr<Command>& command) {
+ count++;
+ };
+
+ manager.AddCommandHandler("", "", base::Bind(handler, 1));
+ EXPECT_EQ(0, count);
+
+ const char kCommand1[] = R"({
+ "name": "trait1.command1",
+ "component": "comp"
+ })";
+ auto command1 = CreateDictionaryValue(kCommand1);
+ auto command_instance = manager.ParseCommandInstance(
+ *command1, Command::Origin::kCloud, UserRole::kUser, nullptr, nullptr);
+ ASSERT_NE(nullptr, command_instance.get());
+ manager.AddCommand(std::move(command_instance));
+ EXPECT_EQ(1, count);
+
+ const char kCommand2[] = R"({
+ "name": "trait2.command2",
+ "component": "comp"
+ })";
+ auto command2 = CreateDictionaryValue(kCommand2);
+ command_instance = manager.ParseCommandInstance(
+ *command2, Command::Origin::kCloud, UserRole::kUser, nullptr, nullptr);
+ ASSERT_NE(nullptr, command_instance.get());
+ manager.AddCommand(std::move(command_instance));
+ EXPECT_EQ(2, count);
+}
+
TEST(ComponentManager, SetStateProperties) {
ComponentManagerImpl manager;
CreateTestComponentTree(&manager);