libweave: Re-factor dbus_command_proxy_unittest.cc to public libweave

Now dbus references could be moved out from libweave.

BUG=brillo:1245
TEST='FEATURES=test emerge-gizmo buffet'

Change-Id: I77b862895bc9a742586b3c24cbc4a223cffbbb11
Reviewed-on: https://chromium-review.googlesource.com/288805
Tested-by: Vitaly Buka <vitalybuka@chromium.org>
Reviewed-by: Alex Vakulenko <avakulenko@chromium.org>
Commit-Queue: Vitaly Buka <vitalybuka@chromium.org>
diff --git a/buffet/buffet.gyp b/buffet/buffet.gyp
index 2e6cd91..d6fb0ad 100644
--- a/buffet/buffet.gyp
+++ b/buffet/buffet.gyp
@@ -195,6 +195,7 @@
             '../libweave/src/commands/command_queue_unittest.cc',
             '../libweave/src/commands/dbus_command_proxy_unittest.cc',
             '../libweave/src/commands/dbus_conversion_unittest.cc',
+            '../libweave/src/commands/mock_command.cc',
             '../libweave/src/commands/object_schema_unittest.cc',
             '../libweave/src/commands/schema_utils_unittest.cc',
             '../libweave/src/commands/unittest_utils.cc',
diff --git a/libweave/include/weave/mock_command.h b/libweave/include/weave/mock_command.h
new file mode 100644
index 0000000..6298f99
--- /dev/null
+++ b/libweave/include/weave/mock_command.h
@@ -0,0 +1,49 @@
+// Copyright 2015 The Chromium OS 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_INCLUDE_WEAVE_MOCK_COMMAND_H_
+#define LIBWEAVE_INCLUDE_WEAVE_MOCK_COMMAND_H_
+
+#include "weave/command.h"
+
+#include <memory>
+#include <string>
+
+#include <base/values.h>
+
+#include <gmock/gmock.h>
+
+namespace weave {
+
+class MockCommand : public Command {
+ public:
+  ~MockCommand() override = default;
+
+  MOCK_METHOD1(AddObserver, void(Observer*));
+  MOCK_CONST_METHOD0(GetID, const std::string&());
+  MOCK_CONST_METHOD0(GetName, const std::string&());
+  MOCK_CONST_METHOD0(GetCategory, const std::string&());
+  MOCK_CONST_METHOD0(GetStatus, CommandStatus());
+  MOCK_CONST_METHOD0(GetOrigin, CommandOrigin());
+  MOCK_CONST_METHOD0(MockGetParameters, const std::string&());
+  MOCK_CONST_METHOD0(MockGetProgress, const std::string&());
+  MOCK_CONST_METHOD0(MockGetResults, const std::string&());
+  MOCK_METHOD2(SetProgress,
+               bool(const base::DictionaryValue&, chromeos::ErrorPtr*));
+  MOCK_METHOD2(SetResults,
+               bool(const base::DictionaryValue&, chromeos::ErrorPtr*));
+  MOCK_METHOD0(Abort, void());
+  MOCK_METHOD0(Cancel, void());
+  MOCK_METHOD0(Done, void());
+  MOCK_CONST_METHOD0(MockToJson, const std::string&());
+
+  std::unique_ptr<base::DictionaryValue> GetParameters() const override;
+  std::unique_ptr<base::DictionaryValue> GetProgress() const override;
+  std::unique_ptr<base::DictionaryValue> GetResults() const override;
+  std::unique_ptr<base::DictionaryValue> ToJson() const override;
+};
+
+}  // namespace weave
+
+#endif  // LIBWEAVE_INCLUDE_WEAVE_MOCK_COMMAND_H_
diff --git a/libweave/include/weave/mock_commands.h b/libweave/include/weave/mock_commands.h
new file mode 100644
index 0000000..12514c5
--- /dev/null
+++ b/libweave/include/weave/mock_commands.h
@@ -0,0 +1,32 @@
+// Copyright 2015 The Chromium OS 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_INCLUDE_WEAVE_MOCK_COMMANDS_H_
+#define LIBWEAVE_INCLUDE_WEAVE_MOCK_COMMANDS_H_
+
+#include "weave/commands.h"
+
+#include <string>
+
+#include <gmock/gmock.h>
+
+namespace weave {
+
+class MockCommands : public Commands {
+ public:
+  ~MockCommands() override = default;
+
+  MOCK_METHOD1(AddOnCommandAddedCallback, void(const OnCommandCallback&));
+  MOCK_METHOD1(AddOnCommandRemovedCallback, void(const OnCommandCallback&));
+  MOCK_METHOD4(AddCommand,
+               bool(const base::DictionaryValue&,
+                    UserRole,
+                    std::string*,
+                    chromeos::ErrorPtr*));
+  MOCK_METHOD1(FindCommand, Command*(const std::string&));
+};
+
+}  // namespace weave
+
+#endif  // LIBWEAVE_INCLUDE_WEAVE_MOCK_COMMANDS_H_
diff --git a/libweave/src/commands/dbus_command_proxy_unittest.cc b/libweave/src/commands/dbus_command_proxy_unittest.cc
index 7ae2b32..e8fa9ec 100644
--- a/libweave/src/commands/dbus_command_proxy_unittest.cc
+++ b/libweave/src/commands/dbus_command_proxy_unittest.cc
@@ -16,17 +16,18 @@
 #include <gtest/gtest.h>
 
 #include "buffet/dbus_constants.h"
-#include "libweave/src/commands/command_dictionary.h"
-#include "libweave/src/commands/command_instance.h"
 #include "libweave/src/commands/unittest_utils.h"
+#include "weave/command.h"
 
 #include "weave/enum_to_string.h"
+#include "weave/mock_command.h"
+#include "weave/mock_commands.h"
 
 namespace weave {
 
 using ::testing::AnyNumber;
-using ::testing::Invoke;
 using ::testing::Return;
+using ::testing::ReturnRefOfCopy;
 using ::testing::_;
 
 using chromeos::VariantDictionary;
@@ -38,6 +39,11 @@
 const char kTestCommandCategoty[] = "test_command_category";
 const char kTestCommandId[] = "cmd_1";
 
+MATCHER_P(EqualToJson, json, "") {
+  auto json_value = CreateDictionaryValue(json);
+  return unittests::IsEqualValue(*json_value, arg);
+}
+
 }  // namespace
 
 class DBusCommandProxyTest : public ::testing::Test {
@@ -51,59 +57,24 @@
     EXPECT_CALL(*bus_, AssertOnOriginThread()).Times(AnyNumber());
     EXPECT_CALL(*bus_, AssertOnDBusThread()).Times(AnyNumber());
 
-    // Command instance.
-    // TODO(antonm): Test results.
-    auto json = CreateDictionaryValue(R"({
-      'robot': {
-        'jump': {
-          'parameters': {
-            'height': {
-              'type': 'integer',
-              'minimum': 0,
-              'maximum': 100
-            },
-            '_jumpType': {
-              'type': 'string',
-              'enum': ['_withAirFlip', '_withSpin', '_withKick']
-            }
-          },
-          'results': {
-            'foo': {
-              'type': 'integer'
-            },
-            'bar': {
-              'type': 'string'
-            },
-            'resultList': {
-              'type': 'array',
-              'items': {
-                'type': 'integer'
-              }
-            }
-          },
-          'progress': {
-            'progress': {
-              'type': 'integer',
-              'minimum': 0,
-              'maximum': 100
-            }
-          }
-        }
-      }
-    })");
-    CHECK(dict_.LoadCommands(*json, kTestCommandCategoty, nullptr, nullptr))
-        << "Failed to parse test command dictionary";
-
-    json = CreateDictionaryValue(R"({
-      'name': 'robot.jump',
-      'parameters': {
-        'height': 53,
-        '_jumpType': '_withKick'
-      }
-    })");
-    command_instance_ = CommandInstance::FromJson(
-        json.get(), CommandOrigin::kLocal, dict_, nullptr, nullptr);
-    command_instance_->SetID(kTestCommandId);
+    EXPECT_CALL(command_, GetID())
+        .WillOnce(ReturnRefOfCopy<std::string>(kTestCommandId));
+    // Use WillRepeatedly becase GetName is used for logging.
+    EXPECT_CALL(command_, GetName())
+        .WillRepeatedly(ReturnRefOfCopy<std::string>("robot.jump"));
+    EXPECT_CALL(command_, GetCategory())
+        .WillOnce(ReturnRefOfCopy<std::string>(kTestCommandCategoty));
+    EXPECT_CALL(command_, GetStatus()).WillOnce(Return(CommandStatus::kQueued));
+    EXPECT_CALL(command_, GetOrigin()).WillOnce(Return(CommandOrigin::kLocal));
+    EXPECT_CALL(command_, MockGetParameters())
+        .WillOnce(ReturnRefOfCopy<std::string>(R"({
+          'height': 53,
+          '_jumpType': '_withKick'
+        })"));
+    EXPECT_CALL(command_, MockGetProgress())
+        .WillOnce(ReturnRefOfCopy<std::string>("{}"));
+    EXPECT_CALL(command_, MockGetResults())
+        .WillOnce(ReturnRefOfCopy<std::string>("{}"));
 
     // Set up a mock ExportedObject to be used with the DBus command proxy.
     std::string cmd_path = buffet::kCommandServicePathPrefix;
@@ -118,24 +89,17 @@
     EXPECT_CALL(*mock_exported_object_command_, ExportMethod(_, _, _, _))
         .Times(AnyNumber());
 
-    std::unique_ptr<Command::Observer> command_proxy(
-        new DBusCommandProxy(nullptr, bus_, command_instance_.get(), cmd_path));
-    command_instance_->AddObserver(command_proxy.release());
+    proxy_.reset(new DBusCommandProxy(nullptr, bus_, &command_, cmd_path));
     GetCommandProxy()->RegisterAsync(
         AsyncEventSequencer::GetDefaultCompletionAction());
   }
 
   void TearDown() override {
     EXPECT_CALL(*mock_exported_object_command_, Unregister()).Times(1);
-    command_instance_.reset();
-    dict_.Clear();
     bus_ = nullptr;
   }
 
-  DBusCommandProxy* GetCommandProxy() const {
-    CHECK_EQ(command_instance_->observers_.size(), 1U);
-    return static_cast<DBusCommandProxy*>(command_instance_->observers_[0]);
-  }
+  DBusCommandProxy* GetCommandProxy() const { return proxy_.get(); }
 
   org::chromium::Buffet::CommandAdaptor* GetCommandAdaptor() const {
     return &GetCommandProxy()->dbus_adaptor_;
@@ -152,11 +116,11 @@
     return status;
   }
 
-  std::unique_ptr<CommandInstance> command_instance_;
-  CommandDictionary dict_;
-
   scoped_refptr<dbus::MockExportedObject> mock_exported_object_command_;
   scoped_refptr<dbus::MockBus> bus_;
+
+  MockCommand command_;
+  std::unique_ptr<DBusCommandProxy> proxy_;
 };
 
 TEST_F(DBusCommandProxyTest, Init) {
@@ -172,72 +136,69 @@
   EXPECT_EQ(kTestCommandId, GetCommandAdaptor()->GetId());
 }
 
-TEST_F(DBusCommandProxyTest, SetProgress) {
-  EXPECT_CALL(*mock_exported_object_command_, SendSignal(_)).Times(2);
-  EXPECT_TRUE(
-      GetCommandInterface()->SetProgress(nullptr, {{"progress", int32_t{10}}}));
-  EXPECT_EQ(CommandStatus::kInProgress, GetCommandStatus());
-
-  VariantDictionary progress{{"progress", int32_t{10}}};
-  EXPECT_EQ(progress, GetCommandAdaptor()->GetProgress());
+TEST_F(DBusCommandProxyTest, OnProgressChanged) {
+  EXPECT_CALL(*mock_exported_object_command_, SendSignal(_)).Times(1);
+  EXPECT_CALL(command_, MockGetProgress())
+      .WillOnce(ReturnRefOfCopy<std::string>("{'progress': 10}"));
+  proxy_->OnProgressChanged();
+  EXPECT_EQ((VariantDictionary{{"progress", int32_t{10}}}),
+            GetCommandAdaptor()->GetProgress());
 }
 
-TEST_F(DBusCommandProxyTest, SetProgress_OutOfRange) {
-  EXPECT_FALSE(GetCommandInterface()->SetProgress(
-      nullptr, {{"progress", int32_t{110}}}));
-  EXPECT_EQ(CommandStatus::kQueued, GetCommandStatus());
-  EXPECT_EQ(VariantDictionary{}, GetCommandAdaptor()->GetProgress());
+TEST_F(DBusCommandProxyTest, OnResultsChanged) {
+  EXPECT_CALL(*mock_exported_object_command_, SendSignal(_)).Times(1);
+  EXPECT_CALL(command_, MockGetResults())
+      .WillOnce(ReturnRefOfCopy<std::string>(
+          "{'foo': 42, 'bar': 'foobar', 'resultList': [1, 2, 3]}"));
+  proxy_->OnResultsChanged();
+
+  EXPECT_EQ((VariantDictionary{{"foo", int32_t{42}},
+                               {"bar", std::string{"foobar"}},
+                               {"resultList", std::vector<int>{1, 2, 3}}}),
+            GetCommandAdaptor()->GetResults());
+}
+
+TEST_F(DBusCommandProxyTest, OnStatusChanged) {
+  EXPECT_CALL(*mock_exported_object_command_, SendSignal(_)).Times(1);
+  EXPECT_CALL(command_, GetStatus())
+      .WillOnce(Return(CommandStatus::kInProgress));
+  proxy_->OnStatusChanged();
+  EXPECT_EQ(CommandStatus::kInProgress, GetCommandStatus());
+}
+
+TEST_F(DBusCommandProxyTest, SetProgress) {
+  EXPECT_CALL(command_, SetProgress(EqualToJson("{'progress': 10}"), _))
+      .WillOnce(Return(true));
+  EXPECT_TRUE(
+      GetCommandInterface()->SetProgress(nullptr, {{"progress", int32_t{10}}}));
 }
 
 TEST_F(DBusCommandProxyTest, SetResults) {
-  EXPECT_CALL(*mock_exported_object_command_, SendSignal(_)).Times(1);
-  VariantDictionary results = {{"foo", int32_t{42}},
-                               {"bar", std::string{"foobar"}},
-                               {"resultList", std::vector<int>{1, 2, 3}}};
-  EXPECT_TRUE(GetCommandInterface()->SetResults(nullptr, results));
-  EXPECT_EQ(results, GetCommandAdaptor()->GetResults());
-  auto list = chromeos::GetVariantValueOrDefault<std::vector<int>>(
-      GetCommandAdaptor()->GetResults(), "resultList");
-  EXPECT_EQ((std::vector<int>{1, 2, 3}), list);
-}
-
-TEST_F(DBusCommandProxyTest, SetResults_WithEmptyList) {
-  EXPECT_CALL(*mock_exported_object_command_, SendSignal(_)).Times(1);
-  VariantDictionary results = {{"foo", int32_t{42}},
-                               {"bar", std::string{"foobar"}},
-                               {"resultList", std::vector<int>{}}};
-  EXPECT_TRUE(GetCommandInterface()->SetResults(nullptr, results));
-  auto list = chromeos::GetVariantValueOrDefault<std::vector<int>>(
-      GetCommandAdaptor()->GetResults(), "resultList");
-  EXPECT_EQ(std::vector<int>(), list);
-}
-
-TEST_F(DBusCommandProxyTest, SetResults_UnknownProperty) {
-  EXPECT_CALL(*mock_exported_object_command_, SendSignal(_)).Times(0);
-  const VariantDictionary results = {
-      {"quux", int32_t{42}},
-  };
-  EXPECT_FALSE(GetCommandInterface()->SetResults(nullptr, results));
+  EXPECT_CALL(
+      command_,
+      SetResults(
+          EqualToJson("{'foo': 42, 'bar': 'foobar', 'resultList': [1, 2, 3]}"),
+          _))
+      .WillOnce(Return(true));
+  EXPECT_TRUE(GetCommandInterface()->SetResults(
+      nullptr, VariantDictionary{{"foo", int32_t{42}},
+                                 {"bar", std::string{"foobar"}},
+                                 {"resultList", std::vector<int>{1, 2, 3}}}));
 }
 
 TEST_F(DBusCommandProxyTest, Abort) {
-  EXPECT_CALL(*mock_exported_object_command_, SendSignal(_)).Times(1);
+  EXPECT_CALL(command_, Abort());
   GetCommandInterface()->Abort();
-  EXPECT_EQ(CommandStatus::kAborted, GetCommandStatus());
 }
 
 TEST_F(DBusCommandProxyTest, Cancel) {
-  EXPECT_CALL(*mock_exported_object_command_, SendSignal(_)).Times(1);
+  EXPECT_CALL(command_, Cancel());
   GetCommandInterface()->Cancel();
-  EXPECT_EQ(CommandStatus::kCancelled, GetCommandStatus());
 }
 
 TEST_F(DBusCommandProxyTest, Done) {
-  // 1 property update:
-  // status: queued -> done
-  EXPECT_CALL(*mock_exported_object_command_, SendSignal(_)).Times(1);
+  EXPECT_CALL(command_, Done());
   GetCommandInterface()->Done();
-  EXPECT_EQ(CommandStatus::kDone, GetCommandStatus());
 }
 
 }  // namespace weave
diff --git a/libweave/src/commands/mock_command.cc b/libweave/src/commands/mock_command.cc
new file mode 100644
index 0000000..6b52b99
--- /dev/null
+++ b/libweave/src/commands/mock_command.cc
@@ -0,0 +1,34 @@
+// Copyright 2015 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "weave/mock_command.h"
+
+#include <memory>
+#include <string>
+
+#include <base/values.h>
+
+#include "libweave/src/commands/unittest_utils.h"
+
+namespace weave {
+
+using unittests::CreateDictionaryValue;
+
+std::unique_ptr<base::DictionaryValue> MockCommand::GetParameters() const {
+  return CreateDictionaryValue(MockGetParameters());
+}
+
+std::unique_ptr<base::DictionaryValue> MockCommand::GetProgress() const {
+  return CreateDictionaryValue(MockGetProgress());
+}
+
+std::unique_ptr<base::DictionaryValue> MockCommand::GetResults() const {
+  return CreateDictionaryValue(MockGetResults());
+}
+
+std::unique_ptr<base::DictionaryValue> MockCommand::ToJson() const {
+  return CreateDictionaryValue(MockToJson());
+}
+
+}  // namespace weave
diff --git a/libweave/src/commands/unittest_utils.cc b/libweave/src/commands/unittest_utils.cc
index 85e63fc..18a7108 100644
--- a/libweave/src/commands/unittest_utils.cc
+++ b/libweave/src/commands/unittest_utils.cc
@@ -10,7 +10,7 @@
 namespace weave {
 namespace unittests {
 
-std::unique_ptr<base::Value> CreateValue(const char* json) {
+std::unique_ptr<base::Value> CreateValue(const std::string& json) {
   std::string json2(json);
   // Convert apostrophes to double-quotes so JSONReader can parse the string.
   std::replace(json2.begin(), json2.end(), '\'', '"');
@@ -24,7 +24,8 @@
   return value;
 }
 
-std::unique_ptr<base::DictionaryValue> CreateDictionaryValue(const char* json) {
+std::unique_ptr<base::DictionaryValue> CreateDictionaryValue(
+    const std::string& json) {
   std::unique_ptr<base::Value> value = CreateValue(json);
   base::DictionaryValue* dict = nullptr;
   value->GetAsDictionary(&dict);
diff --git a/libweave/src/commands/unittest_utils.h b/libweave/src/commands/unittest_utils.h
index 0e685d1..345e92d 100644
--- a/libweave/src/commands/unittest_utils.h
+++ b/libweave/src/commands/unittest_utils.h
@@ -20,10 +20,11 @@
 // Helper method to create base::Value from a string as a smart pointer.
 // For ease of definition in C++ code, double-quotes in the source definition
 // are replaced with apostrophes.
-std::unique_ptr<base::Value> CreateValue(const char* json);
+std::unique_ptr<base::Value> CreateValue(const std::string& json);
 
 // Helper method to create a JSON dictionary object from a string.
-std::unique_ptr<base::DictionaryValue> CreateDictionaryValue(const char* json);
+std::unique_ptr<base::DictionaryValue> CreateDictionaryValue(
+    const std::string& json);
 
 inline bool IsEqualValue(const base::Value& val1, const base::Value& val2) {
   return val1.Equals(&val2);