Vitaly Buka | cad20f0 | 2015-10-16 17:27:15 -0700 | [diff] [blame] | 1 | // Copyright 2015 The Android Open Source Project |
| 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
Vitaly Buka | a0305d3 | 2015-07-27 16:08:51 -0700 | [diff] [blame] | 14 | |
| 15 | #include "buffet/dbus_command_proxy.h" |
| 16 | |
| 17 | #include <functional> |
| 18 | #include <memory> |
| 19 | #include <vector> |
| 20 | |
| 21 | #include <dbus/mock_bus.h> |
| 22 | #include <dbus/mock_exported_object.h> |
| 23 | #include <dbus/property.h> |
Alex Vakulenko | 4170585 | 2015-10-13 10:12:06 -0700 | [diff] [blame] | 24 | #include <brillo/dbus/dbus_object.h> |
| 25 | #include <brillo/dbus/dbus_object_test_helpers.h> |
Vitaly Buka | a0305d3 | 2015-07-27 16:08:51 -0700 | [diff] [blame] | 26 | #include <gtest/gtest.h> |
Vitaly Buka | e2713ac | 2015-08-03 13:50:01 -0700 | [diff] [blame] | 27 | #include <weave/command.h> |
| 28 | #include <weave/enum_to_string.h> |
Vitaly Buka | ea2f1e2 | 2015-08-20 15:35:19 -0700 | [diff] [blame] | 29 | #include <weave/test/mock_command.h> |
Vitaly Buka | ea2f1e2 | 2015-08-20 15:35:19 -0700 | [diff] [blame] | 30 | #include <weave/test/unittest_utils.h> |
Vitaly Buka | a0305d3 | 2015-07-27 16:08:51 -0700 | [diff] [blame] | 31 | |
| 32 | #include "buffet/dbus_constants.h" |
Vitaly Buka | a0305d3 | 2015-07-27 16:08:51 -0700 | [diff] [blame] | 33 | |
| 34 | namespace buffet { |
| 35 | |
Vitaly Buka | 3a58bb9 | 2015-08-05 23:16:13 -0700 | [diff] [blame] | 36 | using ::testing::_; |
Vitaly Buka | a0305d3 | 2015-07-27 16:08:51 -0700 | [diff] [blame] | 37 | using ::testing::AnyNumber; |
| 38 | using ::testing::Return; |
Alex Vakulenko | bae6c02 | 2015-12-08 13:22:07 -0800 | [diff] [blame^] | 39 | using ::testing::ReturnRef; |
Vitaly Buka | a0305d3 | 2015-07-27 16:08:51 -0700 | [diff] [blame] | 40 | using ::testing::ReturnRefOfCopy; |
Vitaly Buka | 3a58bb9 | 2015-08-05 23:16:13 -0700 | [diff] [blame] | 41 | using ::testing::StrictMock; |
Vitaly Buka | a0305d3 | 2015-07-27 16:08:51 -0700 | [diff] [blame] | 42 | |
Alex Vakulenko | 4170585 | 2015-10-13 10:12:06 -0700 | [diff] [blame] | 43 | using brillo::VariantDictionary; |
| 44 | using brillo::dbus_utils::AsyncEventSequencer; |
Vitaly Buka | ea2f1e2 | 2015-08-20 15:35:19 -0700 | [diff] [blame] | 45 | using weave::test::CreateDictionaryValue; |
| 46 | using weave::test::IsEqualValue; |
Vitaly Buka | a0305d3 | 2015-07-27 16:08:51 -0700 | [diff] [blame] | 47 | |
| 48 | namespace { |
| 49 | |
Vitaly Buka | a0305d3 | 2015-07-27 16:08:51 -0700 | [diff] [blame] | 50 | const char kTestCommandId[] = "cmd_1"; |
| 51 | |
| 52 | MATCHER_P(EqualToJson, json, "") { |
| 53 | auto json_value = CreateDictionaryValue(json); |
| 54 | return IsEqualValue(*json_value, arg); |
| 55 | } |
| 56 | |
Alex Vakulenko | be39e93 | 2015-10-09 08:10:36 -0700 | [diff] [blame] | 57 | MATCHER_P2(ExpectError, code, message, "") { |
| 58 | return arg->GetCode() == code && arg->GetMessage() == message; |
| 59 | } |
| 60 | |
Vitaly Buka | a0305d3 | 2015-07-27 16:08:51 -0700 | [diff] [blame] | 61 | } // namespace |
| 62 | |
| 63 | class DBusCommandProxyTest : public ::testing::Test { |
| 64 | public: |
| 65 | void SetUp() override { |
Alex Vakulenko | 2915a7b | 2015-10-07 17:04:00 -0700 | [diff] [blame] | 66 | command_ = std::make_shared<StrictMock<weave::test::MockCommand>>(); |
Vitaly Buka | a0305d3 | 2015-07-27 16:08:51 -0700 | [diff] [blame] | 67 | // Set up a mock DBus bus object. |
| 68 | dbus::Bus::Options options; |
| 69 | options.bus_type = dbus::Bus::SYSTEM; |
| 70 | bus_ = new dbus::MockBus(options); |
| 71 | // By default, don't worry about threading assertions. |
| 72 | EXPECT_CALL(*bus_, AssertOnOriginThread()).Times(AnyNumber()); |
| 73 | EXPECT_CALL(*bus_, AssertOnDBusThread()).Times(AnyNumber()); |
| 74 | |
Alex Vakulenko | bae6c02 | 2015-12-08 13:22:07 -0800 | [diff] [blame^] | 75 | expected_result_dict_.SetInteger("height", 53); |
| 76 | expected_result_dict_.SetString("_jumpType", "_withKick"); |
Alex Vakulenko | 2915a7b | 2015-10-07 17:04:00 -0700 | [diff] [blame] | 77 | EXPECT_CALL(*command_, GetID()) |
Vitaly Buka | a0305d3 | 2015-07-27 16:08:51 -0700 | [diff] [blame] | 78 | .WillOnce(ReturnRefOfCopy<std::string>(kTestCommandId)); |
Alex Vakulenko | 2915a7b | 2015-10-07 17:04:00 -0700 | [diff] [blame] | 79 | // Use WillRepeatedly because GetName is used for logging. |
| 80 | EXPECT_CALL(*command_, GetName()) |
Vitaly Buka | a0305d3 | 2015-07-27 16:08:51 -0700 | [diff] [blame] | 81 | .WillRepeatedly(ReturnRefOfCopy<std::string>("robot.jump")); |
Alex Vakulenko | be39e93 | 2015-10-09 08:10:36 -0700 | [diff] [blame] | 82 | EXPECT_CALL(*command_, GetState()) |
| 83 | .WillRepeatedly(Return(weave::Command::State::kQueued)); |
Alex Vakulenko | 2915a7b | 2015-10-07 17:04:00 -0700 | [diff] [blame] | 84 | EXPECT_CALL(*command_, GetOrigin()) |
Alex Vakulenko | be39e93 | 2015-10-09 08:10:36 -0700 | [diff] [blame] | 85 | .WillOnce(Return(weave::Command::Origin::kLocal)); |
Alex Vakulenko | bae6c02 | 2015-12-08 13:22:07 -0800 | [diff] [blame^] | 86 | EXPECT_CALL(*command_, GetParameters()) |
| 87 | .WillOnce(ReturnRef(expected_result_dict_)); |
| 88 | EXPECT_CALL(*command_, GetProgress()) |
| 89 | .WillRepeatedly(ReturnRef(empty_dict_)); |
| 90 | EXPECT_CALL(*command_, GetResults()) |
| 91 | .WillRepeatedly(ReturnRef(empty_dict_)); |
Vitaly Buka | a0305d3 | 2015-07-27 16:08:51 -0700 | [diff] [blame] | 92 | |
| 93 | // Set up a mock ExportedObject to be used with the DBus command proxy. |
Robert Ginda | cf92c66 | 2015-08-20 09:30:11 -0700 | [diff] [blame] | 94 | std::string cmd_path = buffet::dbus_constants::kCommandServicePathPrefix; |
Vitaly Buka | a0305d3 | 2015-07-27 16:08:51 -0700 | [diff] [blame] | 95 | cmd_path += kTestCommandId; |
| 96 | const dbus::ObjectPath kCmdObjPath(cmd_path); |
| 97 | // Use a mock exported object for the exported object manager. |
| 98 | mock_exported_object_command_ = |
| 99 | new dbus::MockExportedObject(bus_.get(), kCmdObjPath); |
| 100 | EXPECT_CALL(*bus_, GetExportedObject(kCmdObjPath)) |
| 101 | .Times(AnyNumber()) |
| 102 | .WillRepeatedly(Return(mock_exported_object_command_.get())); |
| 103 | EXPECT_CALL(*mock_exported_object_command_, ExportMethod(_, _, _, _)) |
| 104 | .Times(AnyNumber()); |
| 105 | |
Alex Vakulenko | 2915a7b | 2015-10-07 17:04:00 -0700 | [diff] [blame] | 106 | proxy_.reset(new DBusCommandProxy{ |
| 107 | nullptr, bus_, std::weak_ptr<weave::Command>{command_}, cmd_path}); |
Vitaly Buka | a0305d3 | 2015-07-27 16:08:51 -0700 | [diff] [blame] | 108 | GetCommandProxy()->RegisterAsync( |
| 109 | AsyncEventSequencer::GetDefaultCompletionAction()); |
| 110 | } |
| 111 | |
| 112 | void TearDown() override { |
| 113 | EXPECT_CALL(*mock_exported_object_command_, Unregister()).Times(1); |
| 114 | bus_ = nullptr; |
| 115 | } |
| 116 | |
| 117 | DBusCommandProxy* GetCommandProxy() const { return proxy_.get(); } |
| 118 | |
Alex Vakulenko | 63bdf08 | 2015-08-21 09:27:12 -0700 | [diff] [blame] | 119 | com::android::Weave::CommandAdaptor* GetCommandAdaptor() const { |
Vitaly Buka | a0305d3 | 2015-07-27 16:08:51 -0700 | [diff] [blame] | 120 | return &GetCommandProxy()->dbus_adaptor_; |
| 121 | } |
| 122 | |
Alex Vakulenko | 63bdf08 | 2015-08-21 09:27:12 -0700 | [diff] [blame] | 123 | com::android::Weave::CommandInterface* GetCommandInterface() const { |
Vitaly Buka | a0305d3 | 2015-07-27 16:08:51 -0700 | [diff] [blame] | 124 | // DBusCommandProxy also implements CommandInterface. |
| 125 | return GetCommandProxy(); |
| 126 | } |
| 127 | |
Alex Vakulenko | be39e93 | 2015-10-09 08:10:36 -0700 | [diff] [blame] | 128 | weave::Command::State GetCommandState() const { |
| 129 | weave::Command::State state; |
| 130 | EXPECT_TRUE(StringToEnum(GetCommandAdaptor()->GetState(), &state)); |
| 131 | return state; |
Vitaly Buka | a0305d3 | 2015-07-27 16:08:51 -0700 | [diff] [blame] | 132 | } |
| 133 | |
| 134 | scoped_refptr<dbus::MockExportedObject> mock_exported_object_command_; |
| 135 | scoped_refptr<dbus::MockBus> bus_; |
Alex Vakulenko | bae6c02 | 2015-12-08 13:22:07 -0800 | [diff] [blame^] | 136 | base::DictionaryValue empty_dict_; |
| 137 | base::DictionaryValue expected_result_dict_; |
Vitaly Buka | a0305d3 | 2015-07-27 16:08:51 -0700 | [diff] [blame] | 138 | |
Alex Vakulenko | 2915a7b | 2015-10-07 17:04:00 -0700 | [diff] [blame] | 139 | std::shared_ptr<StrictMock<weave::test::MockCommand>> command_; |
Vitaly Buka | a0305d3 | 2015-07-27 16:08:51 -0700 | [diff] [blame] | 140 | std::unique_ptr<DBusCommandProxy> proxy_; |
| 141 | }; |
| 142 | |
| 143 | TEST_F(DBusCommandProxyTest, Init) { |
| 144 | VariantDictionary params = { |
| 145 | {"height", int32_t{53}}, {"_jumpType", std::string{"_withKick"}}, |
| 146 | }; |
Alex Vakulenko | be39e93 | 2015-10-09 08:10:36 -0700 | [diff] [blame] | 147 | EXPECT_EQ(weave::Command::State::kQueued, GetCommandState()); |
Vitaly Buka | a0305d3 | 2015-07-27 16:08:51 -0700 | [diff] [blame] | 148 | EXPECT_EQ(params, GetCommandAdaptor()->GetParameters()); |
| 149 | EXPECT_EQ(VariantDictionary{}, GetCommandAdaptor()->GetProgress()); |
| 150 | EXPECT_EQ(VariantDictionary{}, GetCommandAdaptor()->GetResults()); |
| 151 | EXPECT_EQ("robot.jump", GetCommandAdaptor()->GetName()); |
Vitaly Buka | a0305d3 | 2015-07-27 16:08:51 -0700 | [diff] [blame] | 152 | EXPECT_EQ(kTestCommandId, GetCommandAdaptor()->GetId()); |
| 153 | } |
| 154 | |
Vitaly Buka | a0305d3 | 2015-07-27 16:08:51 -0700 | [diff] [blame] | 155 | TEST_F(DBusCommandProxyTest, SetProgress) { |
Alex Vakulenko | 2915a7b | 2015-10-07 17:04:00 -0700 | [diff] [blame] | 156 | EXPECT_CALL(*command_, SetProgress(EqualToJson("{'progress': 10}"), _)) |
Vitaly Buka | a0305d3 | 2015-07-27 16:08:51 -0700 | [diff] [blame] | 157 | .WillOnce(Return(true)); |
| 158 | EXPECT_TRUE( |
| 159 | GetCommandInterface()->SetProgress(nullptr, {{"progress", int32_t{10}}})); |
| 160 | } |
| 161 | |
Alex Vakulenko | be39e93 | 2015-10-09 08:10:36 -0700 | [diff] [blame] | 162 | TEST_F(DBusCommandProxyTest, Complete) { |
Vitaly Buka | a0305d3 | 2015-07-27 16:08:51 -0700 | [diff] [blame] | 163 | EXPECT_CALL( |
Alex Vakulenko | 2915a7b | 2015-10-07 17:04:00 -0700 | [diff] [blame] | 164 | *command_, |
Alex Vakulenko | be39e93 | 2015-10-09 08:10:36 -0700 | [diff] [blame] | 165 | Complete( |
Vitaly Buka | a0305d3 | 2015-07-27 16:08:51 -0700 | [diff] [blame] | 166 | EqualToJson("{'foo': 42, 'bar': 'foobar', 'resultList': [1, 2, 3]}"), |
| 167 | _)) |
| 168 | .WillOnce(Return(true)); |
Alex Vakulenko | be39e93 | 2015-10-09 08:10:36 -0700 | [diff] [blame] | 169 | EXPECT_TRUE(GetCommandInterface()->Complete( |
Vitaly Buka | a0305d3 | 2015-07-27 16:08:51 -0700 | [diff] [blame] | 170 | nullptr, VariantDictionary{{"foo", int32_t{42}}, |
| 171 | {"bar", std::string{"foobar"}}, |
| 172 | {"resultList", std::vector<int>{1, 2, 3}}})); |
| 173 | } |
| 174 | |
| 175 | TEST_F(DBusCommandProxyTest, Abort) { |
Alex Vakulenko | be39e93 | 2015-10-09 08:10:36 -0700 | [diff] [blame] | 176 | EXPECT_CALL(*command_, Abort(ExpectError("foo", "bar"), _)) |
| 177 | .WillOnce(Return(true)); |
| 178 | EXPECT_TRUE(GetCommandInterface()->Abort(nullptr, "foo", "bar")); |
Vitaly Buka | a0305d3 | 2015-07-27 16:08:51 -0700 | [diff] [blame] | 179 | } |
| 180 | |
| 181 | TEST_F(DBusCommandProxyTest, Cancel) { |
Alex Vakulenko | be39e93 | 2015-10-09 08:10:36 -0700 | [diff] [blame] | 182 | EXPECT_CALL(*command_, Cancel(_)).WillOnce(Return(true)); |
Alex Vakulenko | 2915a7b | 2015-10-07 17:04:00 -0700 | [diff] [blame] | 183 | EXPECT_TRUE(GetCommandInterface()->Cancel(nullptr)); |
Vitaly Buka | a0305d3 | 2015-07-27 16:08:51 -0700 | [diff] [blame] | 184 | } |
| 185 | |
Vitaly Buka | a0305d3 | 2015-07-27 16:08:51 -0700 | [diff] [blame] | 186 | } // namespace buffet |