Convert ComponentManager into an interface and create a mock This will help to mock out ComponentManager's functionality for unit tests in the future. Change-Id: Ie74c49c6b31b00b0c4d38bf0db715a62a9532bc7 Reviewed-on: https://weave-review.googlesource.com/1785 Reviewed-by: Vitaly Buka <vitalybuka@google.com>
diff --git a/libweave.gypi b/libweave.gypi index f74a9bf..dc2e6f0 100644 --- a/libweave.gypi +++ b/libweave.gypi
@@ -12,7 +12,7 @@ 'src/commands/command_manager.cc', 'src/commands/command_queue.cc', 'src/commands/schema_constants.cc', - 'src/component_manager.cc', + 'src/component_manager_impl.cc', 'src/config.cc', 'src/data_encoding.cc', 'src/device_manager.cc',
diff --git a/src/component_manager.h b/src/component_manager.h index 031b88a..426a4cc 100644 --- a/src/component_manager.h +++ b/src/component_manager.h
@@ -15,7 +15,6 @@ #include "src/commands/command_dictionary.h" #include "src/commands/command_queue.h" -#include "src/states/state_change_queue.h" namespace weave { @@ -36,7 +35,7 @@ std::unique_ptr<base::DictionaryValue> changed_properties; }; -class ComponentManager final { +class ComponentManager { public: using UpdateID = uint64_t; using Token = @@ -46,128 +45,134 @@ std::vector<ComponentStateChange> state_changes; }; - ComponentManager(); - explicit ComponentManager(base::Clock* clock); - ~ComponentManager(); + ComponentManager() {} + virtual ~ComponentManager() {} // Loads trait definition schema. - bool LoadTraits(const base::DictionaryValue& dict, ErrorPtr* error); + virtual bool LoadTraits(const base::DictionaryValue& dict, + ErrorPtr* error) = 0; // Same as the overload above, but takes a json string to read the trait // definitions from. - bool LoadTraits(const std::string& json, ErrorPtr* error); + virtual bool LoadTraits(const std::string& json, ErrorPtr* error) = 0; // Sets callback which is called when new trait definitions are added. - void AddTraitDefChangedCallback(const base::Closure& callback); + virtual void AddTraitDefChangedCallback(const base::Closure& callback) = 0; // Adds a new component instance to device. // |path| is a path to the parent component (or empty string if a root-level // component is being added). // |name| is a component name being added. // |traits| is a list of trait names this component supports. - bool AddComponent(const std::string& path, - const std::string& name, - const std::vector<std::string>& traits, - ErrorPtr* error); + virtual bool AddComponent(const std::string& path, + const std::string& name, + const std::vector<std::string>& traits, + ErrorPtr* error) = 0; // Adds a new component instance to device, as a part of component array. // |path| is a path to the parent component. // |name| is an array root element inside the child components. // |traits| is a list of trait names this component supports. - bool AddComponentArrayItem(const std::string& path, - const std::string& name, - const std::vector<std::string>& traits, - ErrorPtr* error); + virtual bool AddComponentArrayItem(const std::string& path, + const std::string& name, + const std::vector<std::string>& traits, + ErrorPtr* error) = 0; // Sets callback which is called when new components are added. - void AddComponentTreeChangedCallback(const base::Closure& callback); + virtual void AddComponentTreeChangedCallback( + const base::Closure& callback) = 0; // Adds a new command instance to the command queue. The command specified in // |command_instance| must be fully initialized and have its name, component, // id populated. - void AddCommand(std::unique_ptr<CommandInstance> command_instance); + virtual void AddCommand( + std::unique_ptr<CommandInstance> command_instance) = 0; // Parses the command definition from a json dictionary and adds it to the // command queue. The new command ID is returned through optional |id| param. - bool AddCommand(const base::DictionaryValue& command, - UserRole role, - std::string* id, - ErrorPtr* error); + virtual bool AddCommand(const base::DictionaryValue& command, + UserRole role, + std::string* id, + ErrorPtr* error) = 0; // Find a command instance with the given ID in the command queue. - CommandInstance* FindCommand(const std::string& id); + virtual CommandInstance* FindCommand(const std::string& id) = 0; // Command queue monitoring callbacks (called when a new command is added to // or removed from the queue). - void AddCommandAddedCallback(const CommandQueue::CommandCallback& callback); - void AddCommandRemovedCallback(const CommandQueue::CommandCallback& callback); + virtual void AddCommandAddedCallback( + const CommandQueue::CommandCallback& callback) = 0; + virtual void AddCommandRemovedCallback( + const CommandQueue::CommandCallback& callback) = 0; // Adds a command handler for specific component's command. // |component_path| is a path to target component (e.g. "stove.burners[2]"). // |command_name| is a full path of the command, including trait name and // command name (e.g. "burner.setPower"). - void AddCommandHandler(const std::string& component_path, - const std::string& command_name, - const Device::CommandHandlerCallback& callback); + virtual void AddCommandHandler( + const std::string& component_path, + const std::string& command_name, + const Device::CommandHandlerCallback& callback) = 0; // Finds a component instance by its full path. - const base::DictionaryValue* FindComponent(const std::string& path, - ErrorPtr* error) const; + virtual const base::DictionaryValue* FindComponent( + const std::string& path, + ErrorPtr* error) const = 0; // Finds a definition of trait with the given |name|. - const base::DictionaryValue* FindTraitDefinition( - const std::string& name) const; + virtual const base::DictionaryValue* FindTraitDefinition( + const std::string& name) const = 0; // Finds a command definition, where |command_name| is in the form of // "trait.command". - const base::DictionaryValue* FindCommandDefinition( - const std::string& command_name) const; + virtual const base::DictionaryValue* FindCommandDefinition( + const std::string& command_name) const = 0; // Checks the minimum required user role for a given command. - bool GetMinimalRole(const std::string& command_name, - UserRole* minimal_role, - ErrorPtr* error) const; + virtual bool GetMinimalRole(const std::string& command_name, + UserRole* minimal_role, + ErrorPtr* error) const = 0; // Returns the full JSON dictionary containing trait definitions. - const base::DictionaryValue& GetTraits() const { return traits_; } + virtual const base::DictionaryValue& GetTraits() const = 0; // Returns the full JSON dictionary containing component instances. - const base::DictionaryValue& GetComponents() const { return components_; } + virtual const base::DictionaryValue& GetComponents() const = 0; // Component state manipulation methods. - bool SetStateProperties(const std::string& component_path, - const base::DictionaryValue& dict, - ErrorPtr* error); - bool SetStatePropertiesFromJson(const std::string& component_path, - const std::string& json, - ErrorPtr* error); - const base::Value* GetStateProperty(const std::string& component_path, - const std::string& name, - ErrorPtr* error) const; - bool SetStateProperty(const std::string& component_path, - const std::string& name, - const base::Value& value, - ErrorPtr* error); + virtual bool SetStateProperties(const std::string& component_path, + const base::DictionaryValue& dict, + ErrorPtr* error) = 0; + virtual bool SetStatePropertiesFromJson(const std::string& component_path, + const std::string& json, + ErrorPtr* error) = 0; + virtual const base::Value* GetStateProperty(const std::string& component_path, + const std::string& name, + ErrorPtr* error) const = 0; + virtual bool SetStateProperty(const std::string& component_path, + const std::string& name, + const base::Value& value, + ErrorPtr* error) = 0; - void AddStateChangedCallback(const base::Closure& callback); + virtual void AddStateChangedCallback(const base::Closure& callback) = 0; // Returns the recorded state changes since last time this method was called. - StateSnapshot GetAndClearRecordedStateChanges(); + virtual StateSnapshot GetAndClearRecordedStateChanges() = 0; // Called to notify that the state patch with |id| has been successfully sent // to the server and processed. - void NotifyStateUpdatedOnServer(UpdateID id); + virtual void NotifyStateUpdatedOnServer(UpdateID id) = 0; // Returns an ID of last state change update. Each SetStatePropertyNNN() // invocation increments this value by 1. - UpdateID GetLastStateChangeId() const { return last_state_change_id_; } + virtual UpdateID GetLastStateChangeId() const = 0; // Subscribes for device state update notifications from cloud server. // The |callback| will be called every time a state patch with given ID is // successfully received and processed by Weave server. // Returns a subscription token. As soon as this token is destroyed, the // respective callback is removed from the callback list. - Token AddServerStateUpdatedCallback( - const base::Callback<void(UpdateID)>& callback); + virtual Token AddServerStateUpdatedCallback( + const base::Callback<void(UpdateID)>& callback) = 0; // Helper method for legacy API to obtain first component that implements // the given trait. This is useful for routing commands that have no component @@ -175,38 +180,8 @@ // Returns empty string if no components are found. // This method only searches for component on the top level of components // tree. No sub-components are searched. - std::string FindComponentWithTrait(const std::string& trait) const; - - private: - // A helper method to find a JSON element of component at |path| to add new - // sub-components to. - base::DictionaryValue* FindComponentGraftNode(const std::string& path, - ErrorPtr* error); - base::DictionaryValue* FindMutableComponent(const std::string& path, - ErrorPtr* error); - - // Helper method to find a sub-component given a root node and a relative path - // from the root to the target component. - static const base::DictionaryValue* FindComponentAt( - const base::DictionaryValue* root, - const std::string& path, - ErrorPtr* error); - - base::Clock* clock_{nullptr}; - base::DictionaryValue traits_; // Trait definitions. - base::DictionaryValue components_; // Component instances. - CommandQueue command_queue_; // Command queue containing command instances. - std::vector<base::Closure> on_trait_changed_; - std::vector<base::Closure> on_componet_tree_changed_; - std::vector<base::Closure> on_state_changed_; - uint32_t next_command_id_{0}; - - std::map<std::string, std::unique_ptr<StateChangeQueue>> state_change_queues_; - // An ID of last state change update. Each NotifyPropertiesUpdated() - // invocation increments this value by 1. - UpdateID last_state_change_id_{0}; - // Callback list for state change queue event sinks. - base::CallbackList<void(UpdateID)> on_server_state_updated_; + virtual std::string FindComponentWithTrait( + const std::string& trait) const = 0; DISALLOW_COPY_AND_ASSIGN(ComponentManager); };
diff --git a/src/component_manager.cc b/src/component_manager_impl.cc similarity index 85% rename from src/component_manager.cc rename to src/component_manager_impl.cc index 98001bb..6950969 100644 --- a/src/component_manager.cc +++ b/src/component_manager_impl.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "src/component_manager.h" +#include "src/component_manager_impl.h" #include <base/strings/stringprintf.h> #include <base/strings/string_number_conversions.h> @@ -20,14 +20,17 @@ const size_t kMaxStateChangeQueueSize = 100; } // namespace -ComponentManager::ComponentManager() {} -ComponentManager::ComponentManager(base::Clock* clock) : clock_{clock} {} -ComponentManager::~ComponentManager() {} +ComponentManagerImpl::ComponentManagerImpl() {} -bool ComponentManager::AddComponent(const std::string& path, - const std::string& name, - const std::vector<std::string>& traits, - ErrorPtr* error) { +ComponentManagerImpl::ComponentManagerImpl(base::Clock* clock) : clock_{clock} { +} + +ComponentManagerImpl::~ComponentManagerImpl() {} + +bool ComponentManagerImpl::AddComponent(const std::string& path, + const std::string& name, + const std::vector<std::string>& traits, + ErrorPtr* error) { base::DictionaryValue* root = &components_; if (!path.empty()) { root = FindComponentGraftNode(path, error); @@ -61,7 +64,7 @@ return true; } -bool ComponentManager::AddComponentArrayItem( +bool ComponentManagerImpl::AddComponentArrayItem( const std::string& path, const std::string& name, const std::vector<std::string>& traits, @@ -87,14 +90,14 @@ return true; } -void ComponentManager::AddComponentTreeChangedCallback( +void ComponentManagerImpl::AddComponentTreeChangedCallback( const base::Closure& callback) { on_componet_tree_changed_.push_back(callback); callback.Run(); } -bool ComponentManager::LoadTraits(const base::DictionaryValue& dict, - ErrorPtr* error) { +bool ComponentManagerImpl::LoadTraits(const base::DictionaryValue& dict, + ErrorPtr* error) { bool modified = false; bool result = true; // Check if any of the new traits are already defined. If so, make sure the @@ -130,28 +133,29 @@ return result; } -bool ComponentManager::LoadTraits(const std::string& json, ErrorPtr* error) { +bool ComponentManagerImpl::LoadTraits(const std::string& json, + ErrorPtr* error) { std::unique_ptr<const base::DictionaryValue> dict = LoadJsonDict(json, error); if (!dict) return false; return LoadTraits(*dict, error); } -void ComponentManager::AddTraitDefChangedCallback( +void ComponentManagerImpl::AddTraitDefChangedCallback( const base::Closure& callback) { on_trait_changed_.push_back(callback); callback.Run(); } -void ComponentManager::AddCommand( +void ComponentManagerImpl::AddCommand( std::unique_ptr<CommandInstance> command_instance) { command_queue_.Add(std::move(command_instance)); } -bool ComponentManager::AddCommand(const base::DictionaryValue& command, - UserRole role, - std::string* id, - ErrorPtr* error) { +bool ComponentManagerImpl::AddCommand(const base::DictionaryValue& command, + UserRole role, + std::string* id, + ErrorPtr* error) { auto command_instance = CommandInstance::FromJson( &command, Command::Origin::kLocal, nullptr, error); if (!command_instance) @@ -222,21 +226,21 @@ return true; } -CommandInstance* ComponentManager::FindCommand(const std::string& id) { +CommandInstance* ComponentManagerImpl::FindCommand(const std::string& id) { return command_queue_.Find(id); } -void ComponentManager::AddCommandAddedCallback( +void ComponentManagerImpl::AddCommandAddedCallback( const CommandQueue::CommandCallback& callback) { command_queue_.AddCommandAddedCallback(callback); } -void ComponentManager::AddCommandRemovedCallback( +void ComponentManagerImpl::AddCommandRemovedCallback( const CommandQueue::CommandCallback& callback) { command_queue_.AddCommandRemovedCallback(callback); } -void ComponentManager::AddCommandHandler( +void ComponentManagerImpl::AddCommandHandler( const std::string& component_path, const std::string& command_name, const Device::CommandHandlerCallback& callback) { @@ -245,19 +249,19 @@ command_queue_.AddCommandHandler(component_path, command_name, callback); } -const base::DictionaryValue* ComponentManager::FindComponent( +const base::DictionaryValue* ComponentManagerImpl::FindComponent( const std::string& path, ErrorPtr* error) const { return FindComponentAt(&components_, path, error); } -const base::DictionaryValue* ComponentManager::FindTraitDefinition( +const base::DictionaryValue* ComponentManagerImpl::FindTraitDefinition( const std::string& name) const { const base::DictionaryValue* trait = nullptr; traits_.GetDictionaryWithoutPathExpansion(name, &trait); return trait; } -const base::DictionaryValue* ComponentManager::FindCommandDefinition( +const base::DictionaryValue* ComponentManagerImpl::FindCommandDefinition( const std::string& command_name) const { const base::DictionaryValue* definition = nullptr; std::vector<std::string> components = Split(command_name, ".", true, false); @@ -270,9 +274,9 @@ return definition; } -bool ComponentManager::GetMinimalRole(const std::string& command_name, - UserRole* minimal_role, - ErrorPtr* error) const { +bool ComponentManagerImpl::GetMinimalRole(const std::string& command_name, + UserRole* minimal_role, + ErrorPtr* error) const { const base::DictionaryValue* command = FindCommandDefinition(command_name); if (!command) { Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain, @@ -289,14 +293,15 @@ return true; } -void ComponentManager::AddStateChangedCallback(const base::Closure& callback) { +void ComponentManagerImpl::AddStateChangedCallback( + const base::Closure& callback) { on_state_changed_.push_back(callback); callback.Run(); // Force to read current state. } -bool ComponentManager::SetStateProperties(const std::string& component_path, - const base::DictionaryValue& dict, - ErrorPtr* error) { +bool ComponentManagerImpl::SetStateProperties(const std::string& component_path, + const base::DictionaryValue& dict, + ErrorPtr* error) { base::DictionaryValue* component = FindMutableComponent(component_path, error); if (!component) @@ -319,7 +324,7 @@ return true; } -bool ComponentManager::SetStatePropertiesFromJson( +bool ComponentManagerImpl::SetStatePropertiesFromJson( const std::string& component_path, const std::string& json, ErrorPtr* error) { @@ -327,7 +332,7 @@ return dict && SetStateProperties(component_path, *dict, error); } -const base::Value* ComponentManager::GetStateProperty( +const base::Value* ComponentManagerImpl::GetStateProperty( const std::string& component_path, const std::string& name, ErrorPtr* error) const { @@ -359,10 +364,10 @@ return value; } -bool ComponentManager::SetStateProperty(const std::string& component_path, - const std::string& name, - const base::Value& value, - ErrorPtr* error) { +bool ComponentManagerImpl::SetStateProperty(const std::string& component_path, + const std::string& name, + const base::Value& value, + ErrorPtr* error) { base::DictionaryValue dict; auto pair = SplitAtFirst(name, ".", true); if (pair.first.empty()) { @@ -383,7 +388,7 @@ } ComponentManager::StateSnapshot -ComponentManager::GetAndClearRecordedStateChanges() { +ComponentManagerImpl::GetAndClearRecordedStateChanges() { StateSnapshot snapshot; snapshot.update_id = GetLastStateChangeId(); for (auto& pair : state_change_queues_) { @@ -407,18 +412,18 @@ return snapshot; } -void ComponentManager::NotifyStateUpdatedOnServer(UpdateID id) { +void ComponentManagerImpl::NotifyStateUpdatedOnServer(UpdateID id) { on_server_state_updated_.Notify(id); } -ComponentManager::Token ComponentManager::AddServerStateUpdatedCallback( +ComponentManager::Token ComponentManagerImpl::AddServerStateUpdatedCallback( const base::Callback<void(UpdateID)>& callback) { if (state_change_queues_.empty()) callback.Run(GetLastStateChangeId()); return Token{on_server_state_updated_.Add(callback).release()}; } -std::string ComponentManager::FindComponentWithTrait( +std::string ComponentManagerImpl::FindComponentWithTrait( const std::string& trait) const { for (base::DictionaryValue::Iterator it(components_); !it.IsAtEnd(); it.Advance()) { @@ -437,7 +442,7 @@ return std::string{}; } -base::DictionaryValue* ComponentManager::FindComponentGraftNode( +base::DictionaryValue* ComponentManagerImpl::FindComponentGraftNode( const std::string& path, ErrorPtr* error) { base::DictionaryValue* root = nullptr; base::DictionaryValue* component = FindMutableComponent(path, error); @@ -448,14 +453,14 @@ return root; } -base::DictionaryValue* ComponentManager::FindMutableComponent( +base::DictionaryValue* ComponentManagerImpl::FindMutableComponent( const std::string& path, ErrorPtr* error) { return const_cast<base::DictionaryValue*>( FindComponentAt(&components_, path, error)); } -const base::DictionaryValue* ComponentManager::FindComponentAt( +const base::DictionaryValue* ComponentManagerImpl::FindComponentAt( const base::DictionaryValue* root, const std::string& path, ErrorPtr* error) {
diff --git a/src/component_manager_impl.h b/src/component_manager_impl.h new file mode 100644 index 0000000..f4f25a3 --- /dev/null +++ b/src/component_manager_impl.h
@@ -0,0 +1,190 @@ +// Copyright 2015 The Weave Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef LIBWEAVE_SRC_COMPONENT_MANAGER_IMPL_H_ +#define LIBWEAVE_SRC_COMPONENT_MANAGER_IMPL_H_ + +#include "src/commands/command_queue.h" +#include "src/component_manager.h" +#include "src/states/state_change_queue.h" + +namespace weave { + +class ComponentManagerImpl final : public ComponentManager { + public: + ComponentManagerImpl(); + explicit ComponentManagerImpl(base::Clock* clock); + ~ComponentManagerImpl() override; + + // Loads trait definition schema. + bool LoadTraits(const base::DictionaryValue& dict, ErrorPtr* error) override; + + // Same as the overload above, but takes a json string to read the trait + // definitions from. + bool LoadTraits(const std::string& json, ErrorPtr* error) override; + + // Sets callback which is called when new trait definitions are added. + void AddTraitDefChangedCallback(const base::Closure& callback) override; + + // Adds a new component instance to device. + // |path| is a path to the parent component (or empty string if a root-level + // component is being added). + // |name| is a component name being added. + // |traits| is a list of trait names this component supports. + bool AddComponent(const std::string& path, + const std::string& name, + const std::vector<std::string>& traits, + ErrorPtr* error) override; + + // Adds a new component instance to device, as a part of component array. + // |path| is a path to the parent component. + // |name| is an array root element inside the child components. + // |traits| is a list of trait names this component supports. + bool AddComponentArrayItem(const std::string& path, + const std::string& name, + const std::vector<std::string>& traits, + ErrorPtr* error) override; + + // Sets callback which is called when new components are added. + void AddComponentTreeChangedCallback(const base::Closure& callback) override; + + // Adds a new command instance to the command queue. The command specified in + // |command_instance| must be fully initialized and have its name, component, + // id populated. + void AddCommand(std::unique_ptr<CommandInstance> command_instance) override; + + // Parses the command definition from a json dictionary and adds it to the + // command queue. The new command ID is returned through optional |id| param. + bool AddCommand(const base::DictionaryValue& command, + UserRole role, + std::string* id, + ErrorPtr* error) override; + + // Find a command instance with the given ID in the command queue. + CommandInstance* FindCommand(const std::string& id) override; + + // Command queue monitoring callbacks (called when a new command is added to + // or removed from the queue). + void AddCommandAddedCallback( + const CommandQueue::CommandCallback& callback) override; + void AddCommandRemovedCallback( + const CommandQueue::CommandCallback& callback) override; + + // Adds a command handler for specific component's command. + // |component_path| is a path to target component (e.g. "stove.burners[2]"). + // |command_name| is a full path of the command, including trait name and + // command name (e.g. "burner.setPower"). + void AddCommandHandler( + const std::string& component_path, + const std::string& command_name, + const Device::CommandHandlerCallback& callback) override; + + // Finds a component instance by its full path. + const base::DictionaryValue* FindComponent(const std::string& path, + ErrorPtr* error) const override; + // Finds a definition of trait with the given |name|. + const base::DictionaryValue* FindTraitDefinition( + const std::string& name) const override; + + // Finds a command definition, where |command_name| is in the form of + // "trait.command". + const base::DictionaryValue* FindCommandDefinition( + const std::string& command_name) const override; + + // Checks the minimum required user role for a given command. + bool GetMinimalRole(const std::string& command_name, + UserRole* minimal_role, + ErrorPtr* error) const override; + + // Returns the full JSON dictionary containing trait definitions. + const base::DictionaryValue& GetTraits() const override { return traits_; } + + // Returns the full JSON dictionary containing component instances. + const base::DictionaryValue& GetComponents() const override { + return components_; + } + + // Component state manipulation methods. + bool SetStateProperties(const std::string& component_path, + const base::DictionaryValue& dict, + ErrorPtr* error) override; + bool SetStatePropertiesFromJson(const std::string& component_path, + const std::string& json, + ErrorPtr* error) override; + const base::Value* GetStateProperty(const std::string& component_path, + const std::string& name, + ErrorPtr* error) const override; + bool SetStateProperty(const std::string& component_path, + const std::string& name, + const base::Value& value, + ErrorPtr* error) override; + + void AddStateChangedCallback(const base::Closure& callback) override; + + // Returns the recorded state changes since last time this method was called. + StateSnapshot GetAndClearRecordedStateChanges() override; + + // Called to notify that the state patch with |id| has been successfully sent + // to the server and processed. + void NotifyStateUpdatedOnServer(UpdateID id) override; + + // Returns an ID of last state change update. Each SetStatePropertyNNN() + // invocation increments this value by 1. + UpdateID GetLastStateChangeId() const override { + return last_state_change_id_; + } + + // Subscribes for device state update notifications from cloud server. + // The |callback| will be called every time a state patch with given ID is + // successfully received and processed by Weave server. + // Returns a subscription token. As soon as this token is destroyed, the + // respective callback is removed from the callback list. + Token AddServerStateUpdatedCallback( + const base::Callback<void(UpdateID)>& callback) override; + + // Helper method for legacy API to obtain first component that implements + // the given trait. This is useful for routing commands that have no component + // path specified. + // Returns empty string if no components are found. + // This method only searches for component on the top level of components + // tree. No sub-components are searched. + std::string FindComponentWithTrait(const std::string& trait) const override; + + private: + // A helper method to find a JSON element of component at |path| to add new + // sub-components to. + base::DictionaryValue* FindComponentGraftNode(const std::string& path, + ErrorPtr* error); + base::DictionaryValue* FindMutableComponent(const std::string& path, + ErrorPtr* error); + + // Helper method to find a sub-component given a root node and a relative path + // from the root to the target component. + static const base::DictionaryValue* FindComponentAt( + const base::DictionaryValue* root, + const std::string& path, + ErrorPtr* error); + + base::Clock* clock_{nullptr}; + base::DictionaryValue traits_; // Trait definitions. + base::DictionaryValue components_; // Component instances. + CommandQueue command_queue_; // Command queue containing command instances. + std::vector<base::Closure> on_trait_changed_; + std::vector<base::Closure> on_componet_tree_changed_; + std::vector<base::Closure> on_state_changed_; + uint32_t next_command_id_{0}; + + std::map<std::string, std::unique_ptr<StateChangeQueue>> state_change_queues_; + // An ID of last state change update. Each NotifyPropertiesUpdated() + // invocation increments this value by 1. + UpdateID last_state_change_id_{0}; + // Callback list for state change queue event sinks. + base::CallbackList<void(UpdateID)> on_server_state_updated_; + + DISALLOW_COPY_AND_ASSIGN(ComponentManagerImpl); +}; + +} // namespace weave + +#endif // LIBWEAVE_SRC_COMPONENT_MANAGER_IMPL_H_
diff --git a/src/component_manager_unittest.cc b/src/component_manager_unittest.cc index 31949d7..0c34041 100644 --- a/src/component_manager_unittest.cc +++ b/src/component_manager_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "src/component_manager.h" +#include "src/component_manager_impl.h" #include <map> @@ -11,6 +11,7 @@ #include "src/bind_lambda.h" #include "src/commands/schema_constants.h" +#include "src/mock_component_manager.h" namespace weave { @@ -98,13 +99,13 @@ } // anonymous namespace TEST(ComponentManager, Empty) { - ComponentManager manager; + ComponentManagerImpl manager; EXPECT_TRUE(manager.GetTraits().empty()); EXPECT_TRUE(manager.GetComponents().empty()); } TEST(ComponentManager, LoadTraits) { - ComponentManager manager; + ComponentManagerImpl manager; const char kTraits[] = R"({ "trait1": { "commands": { @@ -130,7 +131,7 @@ } TEST(ComponentManager, LoadTraitsDuplicateIdentical) { - ComponentManager manager; + ComponentManagerImpl manager; const char kTraits1[] = R"({ "trait1": { "commands": { @@ -198,7 +199,7 @@ } TEST(ComponentManager, LoadTraitsDuplicateOverride) { - ComponentManager manager; + ComponentManagerImpl manager; const char kTraits1[] = R"({ "trait1": { "commands": { @@ -242,7 +243,7 @@ } TEST(ComponentManager, AddTraitDefChangedCallback) { - ComponentManager manager; + ComponentManagerImpl manager; int count = 0; int count2 = 0; manager.AddTraitDefChangedCallback(base::Bind([&count]() { count++; })); @@ -299,7 +300,7 @@ } TEST(ComponentManager, LoadTraitsNotAnObject) { - ComponentManager manager; + ComponentManagerImpl manager; const char kTraits1[] = R"({"trait1": 0})"; auto json = CreateDictionaryValue(kTraits1); ErrorPtr error; @@ -308,7 +309,7 @@ } TEST(ComponentManager, FindTraitDefinition) { - ComponentManager manager; + ComponentManagerImpl manager; const char kTraits[] = R"({ "trait1": { "commands": { @@ -358,7 +359,7 @@ } TEST(ComponentManager, FindCommandDefinition) { - ComponentManager manager; + ComponentManagerImpl manager; const char kTraits[] = R"({ "trait1": { "commands": { @@ -411,7 +412,7 @@ } TEST(ComponentManager, GetMinimalRole) { - ComponentManager manager; + ComponentManagerImpl manager; const char kTraits[] = R"({ "trait1": { "commands": { @@ -446,7 +447,7 @@ } TEST(ComponentManager, AddComponent) { - ComponentManager manager; + ComponentManagerImpl manager; const char kTraits[] = R"({"trait1": {}, "trait2": {}, "trait3": {}})"; auto json = CreateDictionaryValue(kTraits); ASSERT_TRUE(manager.LoadTraits(*json, nullptr)); @@ -467,7 +468,7 @@ } TEST(ComponentManager, AddSubComponent) { - ComponentManager manager; + ComponentManagerImpl manager; EXPECT_TRUE(manager.AddComponent("", "comp1", {}, nullptr)); EXPECT_TRUE(manager.AddComponent("comp1", "comp2", {}, nullptr)); EXPECT_TRUE(manager.AddComponent("comp1", "comp3", {}, nullptr)); @@ -494,7 +495,7 @@ } TEST(ComponentManager, AddComponentArrayItem) { - ComponentManager manager; + ComponentManagerImpl manager; const char kTraits[] = R"({"foo": {}, "bar": {}})"; auto json = CreateDictionaryValue(kTraits); ASSERT_TRUE(manager.LoadTraits(*json, nullptr)); @@ -536,7 +537,7 @@ } TEST(ComponentManager, AddComponentExist) { - ComponentManager manager; + ComponentManagerImpl manager; EXPECT_TRUE(manager.AddComponent("", "comp1", {}, nullptr)); EXPECT_FALSE(manager.AddComponent("", "comp1", {}, nullptr)); EXPECT_TRUE(manager.AddComponent("comp1", "comp2", {}, nullptr)); @@ -544,12 +545,12 @@ } TEST(ComponentManager, AddComponentDoesNotExist) { - ComponentManager manager; + ComponentManagerImpl manager; EXPECT_FALSE(manager.AddComponent("comp1", "comp2", {}, nullptr)); } TEST(ComponentManager, AddComponentTreeChangedCallback) { - ComponentManager manager; + ComponentManagerImpl manager; int count = 0; int count2 = 0; manager.AddComponentTreeChangedCallback(base::Bind([&count]() { count++; })); @@ -572,7 +573,7 @@ } TEST(ComponentManager, FindComponent) { - ComponentManager manager; + ComponentManagerImpl manager; CreateTestComponentTree(&manager); const base::DictionaryValue* comp = manager.FindComponent("comp1", nullptr); @@ -621,7 +622,7 @@ } TEST(ComponentManager, AddCommand) { - ComponentManager manager; + ComponentManagerImpl manager; const char kTraits[] = R"({ "trait1": { "commands": { @@ -693,7 +694,7 @@ } TEST(ComponentManager, AddCommandHandler) { - ComponentManager manager; + ComponentManagerImpl manager; const char kTraits[] = R"({ "trait1": { "commands": { @@ -753,7 +754,7 @@ } TEST(ComponentManager, SetStateProperties) { - ComponentManager manager; + ComponentManagerImpl manager; CreateTestComponentTree(&manager); const char kState1[] = R"({"t1": {"p1": 0, "p2": "foo"}})"; @@ -855,7 +856,7 @@ } TEST(ComponentManager, SetStatePropertiesFromJson) { - ComponentManager manager; + ComponentManagerImpl manager; CreateTestComponentTree(&manager); ASSERT_TRUE(manager.SetStatePropertiesFromJson( @@ -895,7 +896,7 @@ } TEST(ComponentManager, SetGetStateProperty) { - ComponentManager manager; + ComponentManagerImpl manager; const char kTraits[] = R"({ "trait1": { "state": { @@ -961,7 +962,7 @@ TEST(ComponentManager, AddStateChangedCallback) { SimpleTestClock clock; - ComponentManager manager{&clock}; + ComponentManagerImpl manager{&clock}; const char kTraits[] = R"({ "trait1": { "state": { @@ -1002,7 +1003,7 @@ TEST(ComponentManager, ComponentStateUpdates) { SimpleTestClock clock; - ComponentManager manager{&clock}; + ComponentManagerImpl manager{&clock}; const char kTraits[] = R"({ "trait1": { "state": { @@ -1096,7 +1097,7 @@ } TEST(ComponentManager, FindComponentWithTrait) { - ComponentManager manager; + ComponentManagerImpl manager; const char kTraits[] = R"({ "trait1": {}, "trait2": {}, @@ -1113,4 +1114,9 @@ EXPECT_EQ("", manager.FindComponentWithTrait("trait4")); } +TEST(ComponentManager, TestMockComponentManager) { + // Check that all the virtual methods are mocked out. + MockComponentManager mock; +} + } // namespace weave
diff --git a/src/device_manager.cc b/src/device_manager.cc index 64a8093..a44f0db 100644 --- a/src/device_manager.cc +++ b/src/device_manager.cc
@@ -10,7 +10,7 @@ #include "src/base_api_handler.h" #include "src/commands/command_manager.h" -#include "src/component_manager.h" +#include "src/component_manager_impl.h" #include "src/config.h" #include "src/device_registration_info.h" #include "src/privet/privet_manager.h" @@ -34,7 +34,7 @@ provider::HttpServer* http_server, provider::Wifi* wifi, provider::Bluetooth* bluetooth) { - component_manager_.reset(new ComponentManager); + component_manager_.reset(new ComponentManagerImpl); command_manager_ = std::make_shared<CommandManager>(); state_change_queue_.reset(new StateChangeQueue(kMaxStateChangeQueueSize)); state_manager_ = std::make_shared<StateManager>(state_change_queue_.get());
diff --git a/src/mock_component_manager.h b/src/mock_component_manager.h new file mode 100644 index 0000000..66b32d5 --- /dev/null +++ b/src/mock_component_manager.h
@@ -0,0 +1,99 @@ +// Copyright 2015 The Weave Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef LIBWEAVE_SRC_MOCK_COMPONENT_MANAGER_H_ +#define LIBWEAVE_SRC_MOCK_COMPONENT_MANAGER_H_ + +#include "src/component_manager.h" + +#include <gmock/gmock.h> + +namespace weave { + +class MockComponentManager : public ComponentManager { + public: + ~MockComponentManager() override {} + MOCK_METHOD2(LoadTraits, bool(const base::DictionaryValue& dict, + ErrorPtr* error)); + MOCK_METHOD2(LoadTraits, bool(const std::string& json, ErrorPtr* error)); + MOCK_METHOD1(AddTraitDefChangedCallback, void(const base::Closure& callback)); + MOCK_METHOD4(AddComponent, bool(const std::string& path, + const std::string& name, + const std::vector<std::string>& traits, + ErrorPtr* error)); + MOCK_METHOD4(AddComponentArrayItem, + bool(const std::string& path, + const std::string& name, + const std::vector<std::string>& traits, + ErrorPtr* error)); + MOCK_METHOD1(AddComponentTreeChangedCallback, + void(const base::Closure& callback)); + MOCK_METHOD1(MockAddCommand, void(CommandInstance* command_instance)); + MOCK_METHOD4(AddCommand, bool(const base::DictionaryValue& command, + UserRole role, + std::string* id, + ErrorPtr* error)); + MOCK_METHOD1(FindCommand, CommandInstance*(const std::string& id)); + MOCK_METHOD1(AddCommandAddedCallback, + void(const CommandQueue::CommandCallback& callback)); + MOCK_METHOD1(AddCommandRemovedCallback, + void(const CommandQueue::CommandCallback& callback)); + MOCK_METHOD3(AddCommandHandler, + void(const std::string& component_path, + const std::string& command_name, + const Device::CommandHandlerCallback& callback)); + MOCK_CONST_METHOD2(FindComponent, + const base::DictionaryValue*(const std::string& path, + ErrorPtr* error)); + MOCK_CONST_METHOD1(FindTraitDefinition, + const base::DictionaryValue*(const std::string& name)); + MOCK_CONST_METHOD1( + FindCommandDefinition, + const base::DictionaryValue*(const std::string& command_name)); + MOCK_CONST_METHOD3(GetMinimalRole, bool(const std::string& command_name, + UserRole* minimal_role, + ErrorPtr* error)); + MOCK_CONST_METHOD0(GetTraits, const base::DictionaryValue&()); + MOCK_CONST_METHOD0(GetComponents, const base::DictionaryValue&()); + MOCK_METHOD3(SetStateProperties, bool(const std::string& component_path, + const base::DictionaryValue& dict, + ErrorPtr* error)); + MOCK_METHOD3(SetStatePropertiesFromJson, + bool(const std::string& component_path, + const std::string& json, + ErrorPtr* error)); + MOCK_CONST_METHOD3(GetStateProperty, + const base::Value*(const std::string& component_path, + const std::string& name, + ErrorPtr* error)); + MOCK_METHOD4(SetStateProperty, bool(const std::string& component_path, + const std::string& name, + const base::Value& value, + ErrorPtr* error)); + MOCK_METHOD1(AddStateChangedCallback, void(const base::Closure& callback)); + MOCK_METHOD0(MockGetAndClearRecordedStateChanges, StateSnapshot&()); + MOCK_METHOD1(NotifyStateUpdatedOnServer, void(UpdateID id)); + MOCK_CONST_METHOD0(GetLastStateChangeId, UpdateID()); + MOCK_METHOD1(MockAddServerStateUpdatedCallback, + base::CallbackList<void(UpdateID)>::Subscription*( + const base::Callback<void(UpdateID)>& callback)); + MOCK_CONST_METHOD1(FindComponentWithTrait, + std::string(const std::string& trait)); + + private: + void AddCommand(std::unique_ptr<CommandInstance> command_instance) override { + MockAddCommand(command_instance.get()); + } + StateSnapshot GetAndClearRecordedStateChanges() override { + return std::move(MockGetAndClearRecordedStateChanges()); + } + Token AddServerStateUpdatedCallback( + const base::Callback<void(UpdateID)>& callback) override { + return Token{MockAddServerStateUpdatedCallback(callback)}; + } +}; + +} // namespace weave + +#endif // LIBWEAVE_SRC_COMPONENT_MANAGER_H_