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