Vitaly Buka | 4615e0d | 2015-10-14 15:35:12 -0700 | [diff] [blame] | 1 | // Copyright 2015 The Weave Authors. All rights reserved. |
Vitaly Buka | 72410b2 | 2015-05-13 13:48:59 -0700 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
Stefan Sauer | 2d16dfa | 2015-09-25 17:08:35 +0200 | [diff] [blame] | 5 | #include "src/base_api_handler.h" |
Vitaly Buka | 72410b2 | 2015-05-13 13:48:59 -0700 | [diff] [blame] | 6 | |
| 7 | #include <base/strings/string_number_conversions.h> |
Vitaly Buka | ece713e | 2015-12-09 10:59:33 -0800 | [diff] [blame] | 8 | #include <base/time/default_clock.h> |
Vitaly Buka | 72410b2 | 2015-05-13 13:48:59 -0700 | [diff] [blame] | 9 | #include <base/values.h> |
Vitaly Buka | 72410b2 | 2015-05-13 13:48:59 -0700 | [diff] [blame] | 10 | #include <gtest/gtest.h> |
Vitaly Buka | 1e36367 | 2015-09-25 14:01:16 -0700 | [diff] [blame] | 11 | #include <weave/provider/test/mock_config_store.h> |
| 12 | #include <weave/provider/test/mock_http_client.h> |
Vitaly Buka | 266e88b | 2015-10-06 11:33:00 -0700 | [diff] [blame] | 13 | #include <weave/test/mock_device.h> |
Alex Vakulenko | 8a05beb | 2015-11-24 17:13:20 -0800 | [diff] [blame] | 14 | #include <weave/test/unittest_utils.h> |
Vitaly Buka | 72410b2 | 2015-05-13 13:48:59 -0700 | [diff] [blame] | 15 | |
Alex Vakulenko | d91d625 | 2015-12-05 17:14:39 -0800 | [diff] [blame] | 16 | #include "src/component_manager_impl.h" |
Stefan Sauer | 2d16dfa | 2015-09-25 17:08:35 +0200 | [diff] [blame] | 17 | #include "src/config.h" |
| 18 | #include "src/device_registration_info.h" |
Vitaly Buka | 72410b2 | 2015-05-13 13:48:59 -0700 | [diff] [blame] | 19 | |
Vitaly Buka | 6b61e57 | 2015-08-05 23:16:13 -0700 | [diff] [blame] | 20 | using testing::_; |
Vitaly Buka | 695a5fb | 2015-10-06 16:26:08 -0700 | [diff] [blame] | 21 | using testing::AnyOf; |
| 22 | using testing::Eq; |
Vitaly Buka | 9acf8aa | 2015-08-16 01:55:41 -0700 | [diff] [blame] | 23 | using testing::Invoke; |
Vitaly Buka | 6b61e57 | 2015-08-05 23:16:13 -0700 | [diff] [blame] | 24 | using testing::Return; |
Vitaly Buka | 68af387 | 2015-10-27 16:19:00 -0700 | [diff] [blame] | 25 | using testing::ReturnRef; |
Vitaly Buka | 9acf8aa | 2015-08-16 01:55:41 -0700 | [diff] [blame] | 26 | using testing::StrictMock; |
Vitaly Buka | 6b61e57 | 2015-08-05 23:16:13 -0700 | [diff] [blame] | 27 | |
Vitaly Buka | b6f015a | 2015-07-09 14:59:23 -0700 | [diff] [blame] | 28 | namespace weave { |
Vitaly Buka | 72410b2 | 2015-05-13 13:48:59 -0700 | [diff] [blame] | 29 | |
| 30 | class BaseApiHandlerTest : public ::testing::Test { |
| 31 | protected: |
| 32 | void SetUp() override { |
Alex Vakulenko | d91d625 | 2015-12-05 17:14:39 -0800 | [diff] [blame] | 33 | EXPECT_CALL(device_, AddTraitDefinitionsFromJson(_)) |
Vitaly Buka | 68af387 | 2015-10-27 16:19:00 -0700 | [diff] [blame] | 34 | .WillRepeatedly(Invoke([this](const std::string& json) { |
Alex Vakulenko | d91d625 | 2015-12-05 17:14:39 -0800 | [diff] [blame] | 35 | EXPECT_TRUE(component_manager_.LoadTraits(json, nullptr)); |
Vitaly Buka | 68af387 | 2015-10-27 16:19:00 -0700 | [diff] [blame] | 36 | })); |
Alex Vakulenko | d91d625 | 2015-12-05 17:14:39 -0800 | [diff] [blame] | 37 | EXPECT_CALL(device_, SetStateProperties(_, _, _)) |
Vitaly Buka | 34668e7 | 2015-12-15 14:46:47 -0800 | [diff] [blame] | 38 | .WillRepeatedly( |
| 39 | Invoke(&component_manager_, &ComponentManager::SetStateProperties)); |
Alex Vakulenko | d91d625 | 2015-12-05 17:14:39 -0800 | [diff] [blame] | 40 | EXPECT_CALL(device_, SetStateProperty(_, _, _, _)) |
Vitaly Buka | 34668e7 | 2015-12-15 14:46:47 -0800 | [diff] [blame] | 41 | .WillRepeatedly( |
| 42 | Invoke(&component_manager_, &ComponentManager::SetStateProperty)); |
Alex Vakulenko | d91d625 | 2015-12-05 17:14:39 -0800 | [diff] [blame] | 43 | EXPECT_CALL(device_, AddComponent(_, _, _)) |
| 44 | .WillRepeatedly(Invoke([this](const std::string& name, |
| 45 | const std::vector<std::string>& traits, |
| 46 | ErrorPtr* error) { |
| 47 | return component_manager_.AddComponent("", name, traits, error); |
Vitaly Buka | 3110deb | 2015-10-06 19:54:09 -0700 | [diff] [blame] | 48 | })); |
| 49 | |
Vitaly Buka | 34668e7 | 2015-12-15 14:46:47 -0800 | [diff] [blame] | 50 | EXPECT_CALL(device_, |
| 51 | AddCommandHandler(_, AnyOf("base.updateBaseConfiguration", |
| 52 | "base.updateDeviceInfo"), |
| 53 | _)) |
| 54 | .WillRepeatedly( |
| 55 | Invoke(&component_manager_, &ComponentManager::AddCommandHandler)); |
Vitaly Buka | 266e88b | 2015-10-06 11:33:00 -0700 | [diff] [blame] | 56 | |
Vitaly Buka | 666b43e | 2015-12-08 16:35:47 -0800 | [diff] [blame] | 57 | config_.Load(); |
| 58 | dev_reg_.reset(new DeviceRegistrationInfo(&config_, &component_manager_, |
| 59 | nullptr, &http_client_, nullptr, |
| 60 | nullptr)); |
Vitaly Buka | 68af387 | 2015-10-27 16:19:00 -0700 | [diff] [blame] | 61 | |
| 62 | EXPECT_CALL(device_, GetSettings()) |
| 63 | .WillRepeatedly(ReturnRef(dev_reg_->GetSettings())); |
| 64 | |
Vitaly Buka | 266e88b | 2015-10-06 11:33:00 -0700 | [diff] [blame] | 65 | handler_.reset(new BaseApiHandler{dev_reg_.get(), &device_}); |
Vitaly Buka | 72410b2 | 2015-05-13 13:48:59 -0700 | [diff] [blame] | 66 | } |
| 67 | |
Vitaly Buka | 72410b2 | 2015-05-13 13:48:59 -0700 | [diff] [blame] | 68 | void AddCommand(const std::string& command) { |
Alex Vakulenko | d91d625 | 2015-12-05 17:14:39 -0800 | [diff] [blame] | 69 | std::string id; |
| 70 | auto command_instance = component_manager_.ParseCommandInstance( |
| 71 | *test::CreateDictionaryValue(command.c_str()), Command::Origin::kLocal, |
| 72 | UserRole::kOwner, &id, nullptr); |
| 73 | ASSERT_NE(nullptr, command_instance.get()); |
| 74 | component_manager_.AddCommand(std::move(command_instance)); |
Vitaly Buka | 0209da4 | 2015-10-08 00:07:18 -0700 | [diff] [blame] | 75 | EXPECT_EQ(Command::State::kDone, |
Alex Vakulenko | d91d625 | 2015-12-05 17:14:39 -0800 | [diff] [blame] | 76 | component_manager_.FindCommand(id)->GetState()); |
Vitaly Buka | 72410b2 | 2015-05-13 13:48:59 -0700 | [diff] [blame] | 77 | } |
| 78 | |
Vitaly Buka | 68af387 | 2015-10-27 16:19:00 -0700 | [diff] [blame] | 79 | std::unique_ptr<base::DictionaryValue> GetBaseState() { |
Alex Vakulenko | d91d625 | 2015-12-05 17:14:39 -0800 | [diff] [blame] | 80 | std::unique_ptr<base::DictionaryValue> state; |
| 81 | std::string path = component_manager_.FindComponentWithTrait("base"); |
| 82 | EXPECT_FALSE(path.empty()); |
| 83 | const auto* component = component_manager_.FindComponent(path, nullptr); |
| 84 | CHECK(component); |
| 85 | const base::DictionaryValue* base_state = nullptr; |
| 86 | if (component->GetDictionary("state.base", &base_state)) |
| 87 | state.reset(base_state->DeepCopy()); |
| 88 | else |
| 89 | state.reset(new base::DictionaryValue); |
Vitaly Buka | 68af387 | 2015-10-27 16:19:00 -0700 | [diff] [blame] | 90 | return state; |
| 91 | } |
| 92 | |
Vitaly Buka | 1e36367 | 2015-09-25 14:01:16 -0700 | [diff] [blame] | 93 | provider::test::MockConfigStore config_store_; |
Vitaly Buka | 666b43e | 2015-12-08 16:35:47 -0800 | [diff] [blame] | 94 | Config config_{&config_store_}; |
Vitaly Buka | 1e36367 | 2015-09-25 14:01:16 -0700 | [diff] [blame] | 95 | StrictMock<provider::test::MockHttpClient> http_client_; |
Vitaly Buka | 72410b2 | 2015-05-13 13:48:59 -0700 | [diff] [blame] | 96 | std::unique_ptr<DeviceRegistrationInfo> dev_reg_; |
Alex Vakulenko | d91d625 | 2015-12-05 17:14:39 -0800 | [diff] [blame] | 97 | ComponentManagerImpl component_manager_; |
Vitaly Buka | 72410b2 | 2015-05-13 13:48:59 -0700 | [diff] [blame] | 98 | std::unique_ptr<BaseApiHandler> handler_; |
Vitaly Buka | 266e88b | 2015-10-06 11:33:00 -0700 | [diff] [blame] | 99 | StrictMock<test::MockDevice> device_; |
Vitaly Buka | 72410b2 | 2015-05-13 13:48:59 -0700 | [diff] [blame] | 100 | }; |
| 101 | |
Vitaly Buka | 80d6653 | 2015-10-27 23:06:11 -0700 | [diff] [blame] | 102 | TEST_F(BaseApiHandlerTest, Initialization) { |
Alex Vakulenko | d91d625 | 2015-12-05 17:14:39 -0800 | [diff] [blame] | 103 | const base::DictionaryValue* trait = nullptr; |
| 104 | ASSERT_TRUE(component_manager_.GetTraits().GetDictionary("base", &trait)); |
Vitaly Buka | 80d6653 | 2015-10-27 23:06:11 -0700 | [diff] [blame] | 105 | |
| 106 | auto expected = R"({ |
Alex Vakulenko | d91d625 | 2015-12-05 17:14:39 -0800 | [diff] [blame] | 107 | "commands": { |
Vitaly Buka | 80d6653 | 2015-10-27 23:06:11 -0700 | [diff] [blame] | 108 | "updateBaseConfiguration": { |
Alex Vakulenko | 7e894da | 2015-11-23 11:47:49 -0800 | [diff] [blame] | 109 | "minimalRole": "manager", |
| 110 | "parameters": { |
| 111 | "localAnonymousAccessMaxRole": { |
| 112 | "enum": [ "none", "viewer", "user" ], |
| 113 | "type": "string" |
| 114 | }, |
| 115 | "localDiscoveryEnabled": { |
| 116 | "type": "boolean" |
| 117 | }, |
| 118 | "localPairingEnabled": { |
| 119 | "type": "boolean" |
| 120 | } |
| 121 | } |
Vitaly Buka | 80d6653 | 2015-10-27 23:06:11 -0700 | [diff] [blame] | 122 | }, |
| 123 | "updateDeviceInfo": { |
Alex Vakulenko | 7e894da | 2015-11-23 11:47:49 -0800 | [diff] [blame] | 124 | "minimalRole": "manager", |
| 125 | "parameters": { |
| 126 | "description": { |
| 127 | "type": "string" |
| 128 | }, |
| 129 | "location": { |
| 130 | "type": "string" |
| 131 | }, |
| 132 | "name": { |
| 133 | "type": "string" |
| 134 | } |
| 135 | } |
Alex Vakulenko | 8d0cfef | 2015-12-15 18:40:05 -0800 | [diff] [blame] | 136 | }, |
| 137 | "reboot": { |
| 138 | "minimalRole": "user", |
| 139 | "parameters": {}, |
| 140 | "errors": ["notEnoughBattery"] |
| 141 | }, |
| 142 | "identify": { |
| 143 | "minimalRole": "user", |
| 144 | "parameters": {} |
Vitaly Buka | 80d6653 | 2015-10-27 23:06:11 -0700 | [diff] [blame] | 145 | } |
Alex Vakulenko | d91d625 | 2015-12-05 17:14:39 -0800 | [diff] [blame] | 146 | }, |
Alex Vakulenko | 8d0cfef | 2015-12-15 18:40:05 -0800 | [diff] [blame] | 147 | "state": { |
| 148 | "firmwareVersion": { |
| 149 | "type": "string", |
| 150 | "isRequired": true |
| 151 | }, |
| 152 | "localDiscoveryEnabled": { |
| 153 | "type": "boolean", |
| 154 | "isRequired": true |
| 155 | }, |
| 156 | "localAnonymousAccessMaxRole": { |
| 157 | "type": "string", |
| 158 | "enum": [ "none", "viewer", "user" ], |
| 159 | "isRequired": true |
| 160 | }, |
| 161 | "localPairingEnabled": { |
| 162 | "type": "boolean", |
| 163 | "isRequired": true |
| 164 | }, |
| 165 | "connectionStatus": { |
| 166 | "type": "string" |
| 167 | }, |
| 168 | "network": { |
| 169 | "type": "object", |
| 170 | "additionalProperties": false, |
| 171 | "properties": { |
| 172 | "name": { "type": "string" } |
| 173 | } |
| 174 | } |
| 175 | } |
Vitaly Buka | 80d6653 | 2015-10-27 23:06:11 -0700 | [diff] [blame] | 176 | })"; |
Alex Vakulenko | d91d625 | 2015-12-05 17:14:39 -0800 | [diff] [blame] | 177 | EXPECT_JSON_EQ(expected, *trait); |
Vitaly Buka | 80d6653 | 2015-10-27 23:06:11 -0700 | [diff] [blame] | 178 | } |
| 179 | |
Vitaly Buka | 2f7efdb | 2015-05-27 16:00:21 -0700 | [diff] [blame] | 180 | TEST_F(BaseApiHandlerTest, UpdateBaseConfiguration) { |
Vitaly Buka | 5cf12a3 | 2015-09-15 21:25:48 -0700 | [diff] [blame] | 181 | const Settings& settings = dev_reg_->GetSettings(); |
Vitaly Buka | 2f7efdb | 2015-05-27 16:00:21 -0700 | [diff] [blame] | 182 | |
| 183 | AddCommand(R"({ |
| 184 | 'name' : 'base.updateBaseConfiguration', |
Alex Vakulenko | 8d0cfef | 2015-12-15 18:40:05 -0800 | [diff] [blame] | 185 | 'component': 'base', |
Vitaly Buka | 2f7efdb | 2015-05-27 16:00:21 -0700 | [diff] [blame] | 186 | 'parameters': { |
| 187 | 'localDiscoveryEnabled': false, |
| 188 | 'localAnonymousAccessMaxRole': 'none', |
| 189 | 'localPairingEnabled': false |
| 190 | } |
| 191 | })"); |
Vitaly Buka | b624bc4 | 2015-09-29 19:13:55 -0700 | [diff] [blame] | 192 | EXPECT_EQ(AuthScope::kNone, settings.local_anonymous_access_role); |
Vitaly Buka | 5cf12a3 | 2015-09-15 21:25:48 -0700 | [diff] [blame] | 193 | EXPECT_FALSE(settings.local_discovery_enabled); |
| 194 | EXPECT_FALSE(settings.local_pairing_enabled); |
Vitaly Buka | 2f7efdb | 2015-05-27 16:00:21 -0700 | [diff] [blame] | 195 | |
| 196 | auto expected = R"({ |
Alex Vakulenko | d91d625 | 2015-12-05 17:14:39 -0800 | [diff] [blame] | 197 | 'firmwareVersion': 'TEST_FIRMWARE', |
| 198 | 'localAnonymousAccessMaxRole': 'none', |
| 199 | 'localDiscoveryEnabled': false, |
| 200 | 'localPairingEnabled': false |
Vitaly Buka | 2f7efdb | 2015-05-27 16:00:21 -0700 | [diff] [blame] | 201 | })"; |
Vitaly Buka | 68af387 | 2015-10-27 16:19:00 -0700 | [diff] [blame] | 202 | EXPECT_JSON_EQ(expected, *GetBaseState()); |
Vitaly Buka | 2f7efdb | 2015-05-27 16:00:21 -0700 | [diff] [blame] | 203 | |
| 204 | AddCommand(R"({ |
| 205 | 'name' : 'base.updateBaseConfiguration', |
Alex Vakulenko | 8d0cfef | 2015-12-15 18:40:05 -0800 | [diff] [blame] | 206 | 'component': 'base', |
Vitaly Buka | 2f7efdb | 2015-05-27 16:00:21 -0700 | [diff] [blame] | 207 | 'parameters': { |
| 208 | 'localDiscoveryEnabled': true, |
| 209 | 'localAnonymousAccessMaxRole': 'user', |
| 210 | 'localPairingEnabled': true |
| 211 | } |
| 212 | })"); |
Vitaly Buka | b624bc4 | 2015-09-29 19:13:55 -0700 | [diff] [blame] | 213 | EXPECT_EQ(AuthScope::kUser, settings.local_anonymous_access_role); |
Vitaly Buka | 5cf12a3 | 2015-09-15 21:25:48 -0700 | [diff] [blame] | 214 | EXPECT_TRUE(settings.local_discovery_enabled); |
| 215 | EXPECT_TRUE(settings.local_pairing_enabled); |
Vitaly Buka | 2f7efdb | 2015-05-27 16:00:21 -0700 | [diff] [blame] | 216 | expected = R"({ |
Alex Vakulenko | d91d625 | 2015-12-05 17:14:39 -0800 | [diff] [blame] | 217 | 'firmwareVersion': 'TEST_FIRMWARE', |
| 218 | 'localAnonymousAccessMaxRole': 'user', |
| 219 | 'localDiscoveryEnabled': true, |
| 220 | 'localPairingEnabled': true |
Vitaly Buka | 2f7efdb | 2015-05-27 16:00:21 -0700 | [diff] [blame] | 221 | })"; |
Vitaly Buka | 68af387 | 2015-10-27 16:19:00 -0700 | [diff] [blame] | 222 | EXPECT_JSON_EQ(expected, *GetBaseState()); |
Vitaly Buka | 4c808b2 | 2015-08-02 13:44:52 -0700 | [diff] [blame] | 223 | |
| 224 | { |
Vitaly Buka | 5cf12a3 | 2015-09-15 21:25:48 -0700 | [diff] [blame] | 225 | Config::Transaction change{dev_reg_->GetMutableConfig()}; |
Vitaly Buka | b624bc4 | 2015-09-29 19:13:55 -0700 | [diff] [blame] | 226 | change.set_local_anonymous_access_role(AuthScope::kViewer); |
Vitaly Buka | 4c808b2 | 2015-08-02 13:44:52 -0700 | [diff] [blame] | 227 | } |
| 228 | expected = R"({ |
Alex Vakulenko | d91d625 | 2015-12-05 17:14:39 -0800 | [diff] [blame] | 229 | 'firmwareVersion': 'TEST_FIRMWARE', |
| 230 | 'localAnonymousAccessMaxRole': 'viewer', |
| 231 | 'localDiscoveryEnabled': true, |
| 232 | 'localPairingEnabled': true |
Vitaly Buka | 4c808b2 | 2015-08-02 13:44:52 -0700 | [diff] [blame] | 233 | })"; |
Vitaly Buka | 68af387 | 2015-10-27 16:19:00 -0700 | [diff] [blame] | 234 | EXPECT_JSON_EQ(expected, *GetBaseState()); |
Vitaly Buka | 2f7efdb | 2015-05-27 16:00:21 -0700 | [diff] [blame] | 235 | } |
| 236 | |
Vitaly Buka | 72410b2 | 2015-05-13 13:48:59 -0700 | [diff] [blame] | 237 | TEST_F(BaseApiHandlerTest, UpdateDeviceInfo) { |
Vitaly Buka | 72410b2 | 2015-05-13 13:48:59 -0700 | [diff] [blame] | 238 | AddCommand(R"({ |
| 239 | 'name' : 'base.updateDeviceInfo', |
Alex Vakulenko | 8d0cfef | 2015-12-15 18:40:05 -0800 | [diff] [blame] | 240 | 'component': 'base', |
Vitaly Buka | 72410b2 | 2015-05-13 13:48:59 -0700 | [diff] [blame] | 241 | 'parameters': { |
| 242 | 'name': 'testName', |
| 243 | 'description': 'testDescription', |
| 244 | 'location': 'testLocation' |
| 245 | } |
| 246 | })"); |
| 247 | |
Vitaly Buka | 5cf12a3 | 2015-09-15 21:25:48 -0700 | [diff] [blame] | 248 | const Settings& config = dev_reg_->GetSettings(); |
| 249 | EXPECT_EQ("testName", config.name); |
| 250 | EXPECT_EQ("testDescription", config.description); |
| 251 | EXPECT_EQ("testLocation", config.location); |
Alex Vakulenko | 7e8df46 | 2015-07-07 10:59:20 -0700 | [diff] [blame] | 252 | |
| 253 | AddCommand(R"({ |
| 254 | 'name' : 'base.updateDeviceInfo', |
Alex Vakulenko | 8d0cfef | 2015-12-15 18:40:05 -0800 | [diff] [blame] | 255 | 'component': 'base', |
Alex Vakulenko | 7e8df46 | 2015-07-07 10:59:20 -0700 | [diff] [blame] | 256 | 'parameters': { |
| 257 | 'location': 'newLocation' |
| 258 | } |
| 259 | })"); |
| 260 | |
Vitaly Buka | 5cf12a3 | 2015-09-15 21:25:48 -0700 | [diff] [blame] | 261 | EXPECT_EQ("testName", config.name); |
| 262 | EXPECT_EQ("testDescription", config.description); |
| 263 | EXPECT_EQ("newLocation", config.location); |
Vitaly Buka | 72410b2 | 2015-05-13 13:48:59 -0700 | [diff] [blame] | 264 | } |
| 265 | |
Vitaly Buka | b6f015a | 2015-07-09 14:59:23 -0700 | [diff] [blame] | 266 | } // namespace weave |