Add a unit tests for deleting CloudCommandProxy along with CommandInstance When CommandInstance is deleted, it should trigger destruction of associated CloudCommandProxy. Add a unit test to confirm this is the case. BUG: 25707196 Change-Id: I95cadf60e99302d236f1bc67782b7315efcec6d6 Reviewed-on: https://weave-review.googlesource.com/2427 Reviewed-by: Vitaly Buka <vitalybuka@google.com>
diff --git a/src/commands/cloud_command_proxy.h b/src/commands/cloud_command_proxy.h index 13f4654..80efd70 100644 --- a/src/commands/cloud_command_proxy.h +++ b/src/commands/cloud_command_proxy.h
@@ -29,7 +29,7 @@ } // Command proxy which publishes command updates to the cloud. -class CloudCommandProxy final : public CommandInstance::Observer { +class CloudCommandProxy : public CommandInstance::Observer { public: CloudCommandProxy(CommandInstance* command_instance, CloudCommandUpdateInterface* cloud_command_updater,
diff --git a/src/commands/cloud_command_proxy_unittest.cc b/src/commands/cloud_command_proxy_unittest.cc index 013769d..0de67fe 100644 --- a/src/commands/cloud_command_proxy_unittest.cc +++ b/src/commands/cloud_command_proxy_unittest.cc
@@ -7,6 +7,7 @@ #include <memory> #include <queue> +#include <base/bind.h> #include <gmock/gmock.h> #include <gtest/gtest.h> #include <weave/provider/test/fake_task_runner.h> @@ -16,6 +17,7 @@ #include "src/mock_component_manager.h" using testing::_; +using testing::AnyNumber; using testing::DoAll; using testing::Invoke; using testing::Return; @@ -62,6 +64,27 @@ base::Time creation_time_; }; +class CloudCommandProxyWrapper : public CloudCommandProxy { + public: + CloudCommandProxyWrapper(CommandInstance* command_instance, + CloudCommandUpdateInterface* cloud_command_updater, + ComponentManager* component_manager, + std::unique_ptr<BackoffEntry> backoff_entry, + provider::TaskRunner* task_runner, + const base::Closure& destruct_callback) + : CloudCommandProxy{command_instance, cloud_command_updater, + component_manager, std::move(backoff_entry), + task_runner}, + destruct_callback_{destruct_callback} {} + + ~CloudCommandProxyWrapper() { + destruct_callback_.Run(); + } + + private: + base::Closure destruct_callback_; +}; + class CloudCommandProxyTest : public ::testing::Test { protected: void SetUp() override { @@ -100,15 +123,21 @@ new TestBackoffEntry{&policy, task_runner_.GetClock()}}; // Finally construct the CloudCommandProxy we are going to test here. - std::unique_ptr<CloudCommandProxy> proxy{new CloudCommandProxy{ + std::unique_ptr<CloudCommandProxy> proxy{new CloudCommandProxyWrapper{ command_instance_.get(), &cloud_updater_, &component_manager_, - std::move(backoff), &task_runner_}}; + std::move(backoff), &task_runner_, + base::Bind(&CloudCommandProxyTest::OnProxyDestroyed, + base::Unretained(this))}}; // CloudCommandProxy::CloudCommandProxy() subscribe itself to weave::Command // notifications. When weave::Command is being destroyed it sends // ::OnCommandDestroyed() and CloudCommandProxy deletes itself. proxy.release(); + + EXPECT_CALL(*this, OnProxyDestroyed()).Times(AnyNumber()); } + MOCK_METHOD0(OnProxyDestroyed, void()); + ComponentManager::UpdateID current_state_update_id_{0}; base::CallbackList<void(ComponentManager::UpdateID)> callbacks_; testing::StrictMock<MockCloudCommandUpdateInterface> cloud_updater_; @@ -120,6 +149,14 @@ } // anonymous namespace +TEST_F(CloudCommandProxyTest, EnsureDestroyed) { + EXPECT_CALL(*this, OnProxyDestroyed()).Times(1); + command_instance_.reset(); + // Verify that CloudCommandProxy has been destroyed already and not at some + // point during the destruction of CloudCommandProxyTest class. + testing::Mock::VerifyAndClearExpectations(this); +} + TEST_F(CloudCommandProxyTest, ImmediateUpdate) { const char expected[] = "{'state':'done'}"; EXPECT_CALL(cloud_updater_, UpdateCommand(kCmdID, MatchJson(expected), _));