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_