blob: c609aa76b7715d5828a35474857b2fcc813d41e7 [file] [log] [blame]
Vitaly Buka4615e0d2015-10-14 15:35:12 -07001// Copyright 2015 The Weave Authors. All rights reserved.
Vitaly Buka11b2f232015-08-20 13:55:41 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <weave/device.h>
6
7#include <gmock/gmock.h>
8#include <gtest/gtest.h>
Vitaly Buka727f3e62015-09-25 17:33:43 -07009#include <weave/provider/test/fake_task_runner.h>
Vitaly Buka1e363672015-09-25 14:01:16 -070010#include <weave/provider/test/mock_bluetooth.h>
11#include <weave/provider/test/mock_config_store.h>
12#include <weave/provider/test/mock_dns_service_discovery.h>
13#include <weave/provider/test/mock_http_client.h>
14#include <weave/provider/test/mock_http_server.h>
15#include <weave/provider/test/mock_network.h>
Vitaly Buka1e363672015-09-25 14:01:16 -070016#include <weave/provider/test/mock_wifi.h>
Vitaly Bukaef213d72015-10-07 15:54:58 -070017#include <weave/test/mock_command.h>
Vitaly Bukaa8ece8f2015-10-05 13:30:23 -070018#include <weave/test/mock_device.h>
Vitaly Buka0f6b2ec2015-08-20 15:35:19 -070019#include <weave/test/unittest_utils.h>
Vitaly Buka11b2f232015-08-20 13:55:41 -070020
Stefan Sauer2d16dfa2015-09-25 17:08:35 +020021#include "src/bind_lambda.h"
Vitaly Buka11b2f232015-08-20 13:55:41 -070022
23using testing::_;
Vitaly Buka65e1f212015-11-05 15:54:05 -080024using testing::AtLeast;
Vitaly Buka11b2f232015-08-20 13:55:41 -070025using testing::AtMost;
26using testing::HasSubstr;
Vitaly Buka65e1f212015-11-05 15:54:05 -080027using testing::InSequence;
Vitaly Buka11b2f232015-08-20 13:55:41 -070028using testing::Invoke;
29using testing::InvokeWithoutArgs;
30using testing::MatchesRegex;
31using testing::Mock;
Vitaly Buka11b2f232015-08-20 13:55:41 -070032using testing::Return;
33using testing::ReturnRefOfCopy;
34using testing::StartsWith;
35using testing::StrictMock;
36using testing::WithArgs;
37
38namespace weave {
39
Vitaly Bukae69e4ee2015-10-26 18:30:14 -070040namespace {
41
Vitaly Buka1a42e142015-10-10 18:15:15 -070042using provider::HttpClient;
43using provider::Network;
44using provider::test::MockHttpClientResponse;
Vitaly Buka0f6b2ec2015-08-20 15:35:19 -070045using test::CreateDictionaryValue;
46using test::ValueToString;
Vitaly Buka11b2f232015-08-20 13:55:41 -070047
Alex Vakulenko551a82b2015-12-07 14:46:12 -080048const char kTraitDefs[] = R"({
49 "trait1": {
50 "commands": {
51 "reboot": {
52 "minimalRole": "user"
53 },
54 "shutdown": {
55 "minimalRole": "user",
56 "parameters": {},
57 "results": {}
58 }
Alex Vakulenko2c7740a2015-11-30 08:51:29 -080059 },
Alex Vakulenko551a82b2015-12-07 14:46:12 -080060 "state": {
61 "firmwareVersion": {"type": "string"}
62 }
63 },
64 "trait2": {
65 "state": {
66 "battery_level": {"type": "integer"}
Vitaly Buka11b2f232015-08-20 13:55:41 -070067 }
68 }
69})";
70
Vitaly Buka11b2f232015-08-20 13:55:41 -070071const char kDeviceResource[] = R"({
Vitaly Buka88272d52015-11-17 17:04:01 -080072 "kind": "weave#device",
Johan Euphrosine0b7bb9f2015-09-29 01:11:21 -070073 "id": "CLOUD_ID",
Vitaly Buka11b2f232015-08-20 13:55:41 -070074 "channel": {
75 "supportedType": "pull"
76 },
77 "deviceKind": "vendor",
78 "modelManifestId": "ABCDE",
79 "systemName": "",
Vitaly Bukaa05eadb2015-09-29 16:38:24 -070080 "name": "TEST_NAME",
Vitaly Buka11b2f232015-08-20 13:55:41 -070081 "displayName": "",
82 "description": "Developer device",
83 "stateValidationEnabled": true,
84 "commandDefs":{
Alex Vakulenko551a82b2015-12-07 14:46:12 -080085 "trait1": {
Vitaly Buka11b2f232015-08-20 13:55:41 -070086 "reboot": {
87 "minimalRole": "user",
Alex Vakulenko7e894da2015-11-23 11:47:49 -080088 "parameters": {"delay": {"type": "integer"}},
Vitaly Buka11b2f232015-08-20 13:55:41 -070089 "results": {}
90 },
91 "shutdown": {
92 "minimalRole": "user",
93 "parameters": {},
94 "results": {}
95 }
96 }
97 },
98 "state":{
Alex Vakulenko551a82b2015-12-07 14:46:12 -080099 "trait1": {"firmwareVersion":"FIRMWARE_VERSION"},
100 "trait2": {"battery_level":44}
101 },
102 "traits": {
103 "trait1": {
104 "commands": {
105 "reboot": {
106 "minimalRole": "user"
107 },
108 "shutdown": {
109 "minimalRole": "user",
110 "parameters": {},
111 "results": {}
112 }
113 },
114 "state": {
115 "firmwareVersion": {"type": "string"}
Vitaly Buka11b2f232015-08-20 13:55:41 -0700116 }
117 },
Alex Vakulenko551a82b2015-12-07 14:46:12 -0800118 "trait2": {
119 "state": {
120 "battery_level": {"type": "integer"}
121 }
122 }
123 },
124 "components": {
125 "myComponent": {
126 "traits": ["trait1", "trait2"],
127 "state": {
128 "trait1": {"firmwareVersion":"FIRMWARE_VERSION"},
129 "trait2": {"battery_level":44}
130 }
131 }
Vitaly Buka11b2f232015-08-20 13:55:41 -0700132 }
133})";
134
135const char kRegistrationResponse[] = R"({
Vitaly Buka88272d52015-11-17 17:04:01 -0800136 "kind": "weave#registrationTicket",
Johan Euphrosine0b7bb9f2015-09-29 01:11:21 -0700137 "id": "TICKET_ID",
138 "deviceId": "CLOUD_ID",
Vitaly Buka11b2f232015-08-20 13:55:41 -0700139 "oauthClientId": "CLIENT_ID",
140 "userEmail": "USER@gmail.com",
141 "creationTimeMs": "1440087183738",
142 "expirationTimeMs": "1440087423738"
143})";
144
145const char kRegistrationFinalResponse[] = R"({
Vitaly Buka88272d52015-11-17 17:04:01 -0800146 "kind": "weave#registrationTicket",
Johan Euphrosine0b7bb9f2015-09-29 01:11:21 -0700147 "id": "TICKET_ID",
148 "deviceId": "CLOUD_ID",
Vitaly Buka11b2f232015-08-20 13:55:41 -0700149 "oauthClientId": "CLIENT_ID",
150 "userEmail": "USER@gmail.com",
151 "robotAccountEmail": "ROBO@gmail.com",
152 "robotAccountAuthorizationCode": "AUTH_CODE",
153 "creationTimeMs": "1440087183738",
154 "expirationTimeMs": "1440087423738"
155})";
156
157const char kAuthTokenResponse[] = R"({
158 "access_token" : "ACCESS_TOKEN",
159 "token_type" : "Bearer",
160 "expires_in" : 3599,
161 "refresh_token" : "REFRESH_TOKEN"
162})";
163
Vitaly Buka3dc2f532015-09-08 18:01:32 -0700164MATCHER_P(MatchTxt, txt, "") {
165 std::vector<std::string> txt_copy = txt;
166 std::sort(txt_copy.begin(), txt_copy.end());
167 std::vector<std::string> arg_copy = arg;
168 std::sort(arg_copy.begin(), arg_copy.end());
169 return (arg_copy == txt_copy);
170}
171
Vitaly Bukae69e4ee2015-10-26 18:30:14 -0700172template <class Map>
173std::set<typename Map::key_type> GetKeys(const Map& map) {
174 std::set<typename Map::key_type> result;
175 for (const auto& pair : map)
176 result.insert(pair.first);
177 return result;
178}
179
180} // namespace
181
Vitaly Buka11b2f232015-08-20 13:55:41 -0700182class WeaveTest : public ::testing::Test {
183 protected:
Vitaly Buka6a1ba842016-02-01 14:41:45 -0800184 void SetUp() override {
185 EXPECT_CALL(wifi_, IsWifi24Supported()).WillRepeatedly(Return(true));
186 EXPECT_CALL(wifi_, IsWifi50Supported()).WillRepeatedly(Return(false));
187 }
Vitaly Buka11b2f232015-08-20 13:55:41 -0700188
Vitaly Buka72d8d162015-12-09 18:39:36 -0800189 template <class UrlMatcher>
Vitaly Buka1a42e142015-10-10 18:15:15 -0700190 void ExpectRequest(HttpClient::Method method,
Vitaly Buka72d8d162015-12-09 18:39:36 -0800191 const UrlMatcher& url_matcher,
Vitaly Buka11b2f232015-08-20 13:55:41 -0700192 const std::string& json_response) {
Vitaly Buka72d8d162015-12-09 18:39:36 -0800193 EXPECT_CALL(http_client_, SendRequest(method, url_matcher, _, _, _))
Vitaly Buka34668e72015-12-15 14:46:47 -0800194 .WillOnce(WithArgs<4>(Invoke(
195 [json_response](const HttpClient::SendRequestCallback& callback) {
196 std::unique_ptr<provider::test::MockHttpClientResponse> response{
197 new StrictMock<provider::test::MockHttpClientResponse>};
198 EXPECT_CALL(*response, GetStatusCode())
199 .Times(AtLeast(1))
200 .WillRepeatedly(Return(200));
201 EXPECT_CALL(*response, GetContentType())
202 .Times(AtLeast(1))
203 .WillRepeatedly(Return("application/json; charset=utf-8"));
204 EXPECT_CALL(*response, GetData())
205 .WillRepeatedly(Return(json_response));
206 callback.Run(std::move(response), nullptr);
207 })));
Vitaly Buka11b2f232015-08-20 13:55:41 -0700208 }
209
Vitaly Buka11b2f232015-08-20 13:55:41 -0700210 void InitNetwork() {
Vitaly Buka3ab6f6e2015-09-24 13:16:16 -0700211 EXPECT_CALL(network_, AddConnectionChangedCallback(_))
212 .WillRepeatedly(Invoke(
Vitaly Buka1e363672015-09-25 14:01:16 -0700213 [this](const provider::Network::ConnectionChangedCallback& cb) {
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700214 network_callbacks_.push_back(cb);
215 }));
Vitaly Buka11b2f232015-08-20 13:55:41 -0700216 EXPECT_CALL(network_, GetConnectionState())
Vitaly Buka35f317d2015-09-27 22:54:39 -0700217 .WillRepeatedly(Return(Network::State::kOffline));
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700218 }
219
Vitaly Bukabeddc602015-09-24 15:28:03 -0700220 void InitDnsSd() {
Vitaly Bukabeddc602015-09-24 15:28:03 -0700221 EXPECT_CALL(dns_sd_, PublishService(_, _, _)).WillRepeatedly(Return());
222 EXPECT_CALL(dns_sd_, StopPublishing("_privet._tcp")).WillOnce(Return());
Vitaly Buka11b2f232015-08-20 13:55:41 -0700223 }
224
Vitaly Bukabeddc602015-09-24 15:28:03 -0700225 void InitDnsSdPublishing(bool registered, const std::string& flags) {
Vitaly Buka87eb7882015-10-27 22:23:49 -0700226 std::vector<std::string> txt{
227 {"id=TEST_DEVICE_ID"}, {"flags=" + flags}, {"mmid=ABCDE"},
228 {"services=developmentBoard"}, {"txtvers=3"}, {"ty=TEST_NAME"}};
Vitaly Buka11b2f232015-08-20 13:55:41 -0700229 if (registered) {
Johan Euphrosine0b7bb9f2015-09-29 01:11:21 -0700230 txt.push_back("gcd_id=CLOUD_ID");
Vitaly Buka11b2f232015-08-20 13:55:41 -0700231
232 // During registration device may announce itself twice:
233 // 1. with GCD ID but not connected (DB)
234 // 2. with GCD ID and connected (BB)
Vitaly Bukabeddc602015-09-24 15:28:03 -0700235 EXPECT_CALL(dns_sd_, PublishService("_privet._tcp", 11, MatchTxt(txt)))
Vitaly Buka11b2f232015-08-20 13:55:41 -0700236 .Times(AtMost(1))
237 .WillOnce(Return());
238
Vitaly Buka3dc2f532015-09-08 18:01:32 -0700239 txt[1] = "flags=BB";
Vitaly Buka11b2f232015-08-20 13:55:41 -0700240 }
241
Vitaly Bukabeddc602015-09-24 15:28:03 -0700242 EXPECT_CALL(dns_sd_, PublishService("_privet._tcp", 11, MatchTxt(txt)))
Vitaly Bukabced5af2015-10-12 17:42:30 -0700243 .Times(AtMost(1))
Vitaly Buka3dc2f532015-09-08 18:01:32 -0700244 .WillOnce(Return());
Vitaly Buka11b2f232015-08-20 13:55:41 -0700245 }
246
247 void InitHttpServer() {
248 EXPECT_CALL(http_server_, GetHttpPort()).WillRepeatedly(Return(11));
249 EXPECT_CALL(http_server_, GetHttpsPort()).WillRepeatedly(Return(12));
Alex Vakulenkoefee3a22015-11-17 15:08:38 -0800250 EXPECT_CALL(http_server_, GetRequestTimeout())
251 .WillRepeatedly(Return(base::TimeDelta::Max()));
Vitaly Buka11b2f232015-08-20 13:55:41 -0700252 EXPECT_CALL(http_server_, GetHttpsCertificateFingerprint())
Vitaly Buka138aec42015-10-08 10:17:48 -0700253 .WillRepeatedly(Return(std::vector<uint8_t>{1, 2, 3}));
Vitaly Buka1a39c812015-10-08 21:20:58 -0700254 EXPECT_CALL(http_server_, AddHttpRequestHandler(_, _))
255 .WillRepeatedly(Invoke(
256 [this](const std::string& path_prefix,
257 const provider::HttpServer::RequestHandlerCallback& cb) {
Vitaly Bukae69e4ee2015-10-26 18:30:14 -0700258 http_handlers_[path_prefix] = cb;
Vitaly Buka1a39c812015-10-08 21:20:58 -0700259 }));
260 EXPECT_CALL(http_server_, AddHttpsRequestHandler(_, _))
Vitaly Buka01893cc2015-10-08 19:58:00 -0700261 .WillRepeatedly(Invoke(
262 [this](const std::string& path_prefix,
263 const provider::HttpServer::RequestHandlerCallback& cb) {
Vitaly Bukae69e4ee2015-10-26 18:30:14 -0700264 https_handlers_[path_prefix] = cb;
Vitaly Buka1e363672015-09-25 14:01:16 -0700265 }));
Vitaly Buka978e7122016-03-04 17:32:23 -0800266 EXPECT_CALL(http_server_, RemoveHttpRequestHandler(_))
267 .WillRepeatedly(Invoke([this](const std::string& path_prefix) {
268 http_handlers_.erase(path_prefix);
269 }));
270 EXPECT_CALL(http_server_, RemoveHttpsRequestHandler(_))
271 .WillRepeatedly(Invoke([this](const std::string& path_prefix) {
272 https_handlers_.erase(path_prefix);
273 }));
Vitaly Buka11b2f232015-08-20 13:55:41 -0700274 }
275
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700276 void InitDefaultExpectations() {
Vitaly Buka11b2f232015-08-20 13:55:41 -0700277 InitNetwork();
Vitaly Bukaa05eadb2015-09-29 16:38:24 -0700278 EXPECT_CALL(wifi_, StartAccessPoint(MatchesRegex("TEST_NAME.*prv")))
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700279 .WillOnce(Return());
Vitaly Buka11b2f232015-08-20 13:55:41 -0700280 InitHttpServer();
Vitaly Bukabeddc602015-09-24 15:28:03 -0700281 InitDnsSd();
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700282 }
Vitaly Buka11b2f232015-08-20 13:55:41 -0700283
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700284 void StartDevice() {
Vitaly Bukac5bdd172015-10-01 19:48:51 -0700285 device_ = weave::Device::Create(&config_store_, &task_runner_,
286 &http_client_, &network_, &dns_sd_,
287 &http_server_, &wifi_, &bluetooth_);
Vitaly Buka11b2f232015-08-20 13:55:41 -0700288
Vitaly Bukae69e4ee2015-10-26 18:30:14 -0700289 EXPECT_EQ((std::set<std::string>{
Vitaly Buka34668e72015-12-15 14:46:47 -0800290 // clang-format off
291 "/privet/info",
292 "/privet/v3/pairing/cancel",
293 "/privet/v3/pairing/confirm",
294 "/privet/v3/pairing/start",
295 // clang-format on
296 }),
Vitaly Bukae69e4ee2015-10-26 18:30:14 -0700297 GetKeys(http_handlers_));
298 EXPECT_EQ((std::set<std::string>{
Vitaly Buka34668e72015-12-15 14:46:47 -0800299 // clang-format off
300 "/privet/info",
Vitaly Buka2d24e0e2015-12-10 14:56:37 -0800301 "/privet/v3/accessControl/claim",
302 "/privet/v3/accessControl/confirm",
Vitaly Buka34668e72015-12-15 14:46:47 -0800303 "/privet/v3/auth",
304 "/privet/v3/checkForUpdates",
Vitaly Buka34668e72015-12-15 14:46:47 -0800305 "/privet/v3/commands/cancel",
306 "/privet/v3/commands/execute",
307 "/privet/v3/commands/list",
308 "/privet/v3/commands/status",
309 "/privet/v3/components",
310 "/privet/v3/pairing/cancel",
311 "/privet/v3/pairing/confirm",
312 "/privet/v3/pairing/start",
313 "/privet/v3/setup/start",
314 "/privet/v3/setup/status",
Vitaly Buka34668e72015-12-15 14:46:47 -0800315 "/privet/v3/traits",
316 // clang-format on
317 }),
Vitaly Bukae69e4ee2015-10-26 18:30:14 -0700318 GetKeys(https_handlers_));
319
Alex Vakulenko551a82b2015-12-07 14:46:12 -0800320 device_->AddTraitDefinitionsFromJson(kTraitDefs);
Vitaly Buka34668e72015-12-15 14:46:47 -0800321 EXPECT_TRUE(
322 device_->AddComponent("myComponent", {"trait1", "trait2"}, nullptr));
Alex Vakulenko551a82b2015-12-07 14:46:12 -0800323 EXPECT_TRUE(device_->SetStatePropertiesFromJson(
324 "myComponent", R"({"trait2": {"battery_level":44}})", nullptr));
Vitaly Buka0ac6ca62015-10-06 19:16:29 -0700325
Vitaly Buka11b2f232015-08-20 13:55:41 -0700326 task_runner_.Run();
327 }
328
Vitaly Buka35f317d2015-09-27 22:54:39 -0700329 void NotifyNetworkChanged(provider::Network::State state,
Vitaly Buka1e363672015-09-25 14:01:16 -0700330 base::TimeDelta delay) {
Luis Hector Chavez17f710e2016-07-18 16:08:56 -0700331 auto task = [](decltype(this) test, provider::Network::State state) {
332 EXPECT_CALL(test->network_, GetConnectionState())
333 .WillRepeatedly(Return(state));
334 for (const auto& cb : test->network_callbacks_)
Vitaly Buka65e1f212015-11-05 15:54:05 -0800335 cb.Run();
336 };
337
Luis Hector Chavez17f710e2016-07-18 16:08:56 -0700338 task_runner_.PostDelayedTask(
339 FROM_HERE, base::Bind(task, base::Unretained(this), state), delay);
Vitaly Buka3884ce12015-09-21 13:48:48 -0700340 }
341
Vitaly Bukae69e4ee2015-10-26 18:30:14 -0700342 std::map<std::string, provider::HttpServer::RequestHandlerCallback>
343 http_handlers_;
344 std::map<std::string, provider::HttpServer::RequestHandlerCallback>
345 https_handlers_;
Vitaly Buka11b2f232015-08-20 13:55:41 -0700346
Vitaly Buka1e363672015-09-25 14:01:16 -0700347 StrictMock<provider::test::MockConfigStore> config_store_;
Vitaly Buka727f3e62015-09-25 17:33:43 -0700348 StrictMock<provider::test::FakeTaskRunner> task_runner_;
Vitaly Buka1e363672015-09-25 14:01:16 -0700349 StrictMock<provider::test::MockHttpClient> http_client_;
350 StrictMock<provider::test::MockNetwork> network_;
351 StrictMock<provider::test::MockDnsServiceDiscovery> dns_sd_;
352 StrictMock<provider::test::MockHttpServer> http_server_;
353 StrictMock<provider::test::MockWifi> wifi_;
354 StrictMock<provider::test::MockBluetooth> bluetooth_;
Vitaly Buka11b2f232015-08-20 13:55:41 -0700355
Vitaly Buka1e363672015-09-25 14:01:16 -0700356 std::vector<provider::Network::ConnectionChangedCallback> network_callbacks_;
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700357
Vitaly Buka11b2f232015-08-20 13:55:41 -0700358 std::unique_ptr<weave::Device> device_;
359};
360
Vitaly Bukaef213d72015-10-07 15:54:58 -0700361TEST_F(WeaveTest, Mocks) {
Vitaly Bukaa8ece8f2015-10-05 13:30:23 -0700362 // Test checks if mock implements entire interface and mock can be
363 // instantiated.
364 test::MockDevice device;
Vitaly Bukaef213d72015-10-07 15:54:58 -0700365 test::MockCommand command;
Vitaly Bukaa8ece8f2015-10-05 13:30:23 -0700366}
367
Vitaly Buka11b2f232015-08-20 13:55:41 -0700368TEST_F(WeaveTest, StartMinimal) {
Vitaly Bukac5bdd172015-10-01 19:48:51 -0700369 device_ = weave::Device::Create(&config_store_, &task_runner_, &http_client_,
370 &network_, nullptr, nullptr, &wifi_, nullptr);
Vitaly Bukab1041e72015-09-21 15:26:51 -0700371}
372
373TEST_F(WeaveTest, StartNoWifi) {
Vitaly Bukab1041e72015-09-21 15:26:51 -0700374 InitNetwork();
375 InitHttpServer();
Vitaly Bukabeddc602015-09-24 15:28:03 -0700376 InitDnsSd();
377 InitDnsSdPublishing(false, "CB");
Vitaly Bukab1041e72015-09-21 15:26:51 -0700378
Vitaly Bukac5bdd172015-10-01 19:48:51 -0700379 device_ = weave::Device::Create(&config_store_, &task_runner_, &http_client_,
380 &network_, &dns_sd_, &http_server_, nullptr,
381 &bluetooth_);
Alex Vakulenko551a82b2015-12-07 14:46:12 -0800382 device_->AddTraitDefinitionsFromJson(kTraitDefs);
Vitaly Buka34668e72015-12-15 14:46:47 -0800383 EXPECT_TRUE(
384 device_->AddComponent("myComponent", {"trait1", "trait2"}, nullptr));
Vitaly Bukab1041e72015-09-21 15:26:51 -0700385
Vitaly Bukab1041e72015-09-21 15:26:51 -0700386 task_runner_.Run();
Vitaly Buka11b2f232015-08-20 13:55:41 -0700387}
388
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700389class WeaveBasicTest : public WeaveTest {
390 public:
391 void SetUp() override {
392 WeaveTest::SetUp();
Vitaly Buka3884ce12015-09-21 13:48:48 -0700393
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700394 InitDefaultExpectations();
Vitaly Bukabeddc602015-09-24 15:28:03 -0700395 InitDnsSdPublishing(false, "DB");
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700396 }
397};
398
399TEST_F(WeaveBasicTest, Start) {
Vitaly Buka11b2f232015-08-20 13:55:41 -0700400 StartDevice();
401}
402
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700403TEST_F(WeaveBasicTest, Register) {
Vitaly Buka74763422015-10-11 00:39:52 -0700404 EXPECT_CALL(network_, OpenSslSocket(_, _, _)).WillRepeatedly(Return());
Vitaly Buka11b2f232015-08-20 13:55:41 -0700405 StartDevice();
406
407 auto draft = CreateDictionaryValue(kDeviceResource);
408 auto response = CreateDictionaryValue(kRegistrationResponse);
Alex Vakulenko38a2aef2016-03-28 15:41:49 -0700409 response->Set("deviceDraft", draft->CreateDeepCopy());
Vitaly Buka0d7aac82015-11-16 23:02:24 -0800410 ExpectRequest(HttpClient::Method::kPatch,
411 "https://www.googleapis.com/weave/v1/registrationTickets/"
412 "TICKET_ID?key=TEST_API_KEY",
413 ValueToString(*response));
Vitaly Buka11b2f232015-08-20 13:55:41 -0700414
415 response = CreateDictionaryValue(kRegistrationFinalResponse);
Alex Vakulenko38a2aef2016-03-28 15:41:49 -0700416 response->Set("deviceDraft", draft->CreateDeepCopy());
Vitaly Buka0d7aac82015-11-16 23:02:24 -0800417 ExpectRequest(HttpClient::Method::kPost,
418 "https://www.googleapis.com/weave/v1/registrationTickets/"
419 "TICKET_ID/finalize?key=TEST_API_KEY",
420 ValueToString(*response));
Vitaly Buka11b2f232015-08-20 13:55:41 -0700421
Vitaly Buka1a42e142015-10-10 18:15:15 -0700422 ExpectRequest(HttpClient::Method::kPost,
423 "https://accounts.google.com/o/oauth2/token",
Vitaly Buka11b2f232015-08-20 13:55:41 -0700424 kAuthTokenResponse);
425
Vitaly Buka72d8d162015-12-09 18:39:36 -0800426 ExpectRequest(HttpClient::Method::kPost, HasSubstr("upsertLocalAuthInfo"),
427 {});
428
Vitaly Bukabeddc602015-09-24 15:28:03 -0700429 InitDnsSdPublishing(true, "DB");
Vitaly Buka11b2f232015-08-20 13:55:41 -0700430
Vitaly Buka12870bd2015-10-08 23:49:39 -0700431 bool done = false;
Vitaly Buka03ee8ac2016-02-05 11:40:33 -0800432 device_->Register(RegistrationData{"TICKET_ID"},
Luis Hector Chavez17f710e2016-07-18 16:08:56 -0700433 base::Bind(
434 [](decltype(this) test, bool* done, ErrorPtr error) {
435 EXPECT_FALSE(error);
436 *done = true;
437 test->task_runner_.Break();
438 EXPECT_EQ("CLOUD_ID",
439 test->device_->GetSettings().cloud_id);
440 },
441 base::Unretained(this), base::Unretained(&done)));
Vitaly Buka12870bd2015-10-08 23:49:39 -0700442 task_runner_.Run();
443 EXPECT_TRUE(done);
Vitaly Buka0a8ab992016-01-11 14:01:20 -0800444
445 done = false;
Luis Hector Chavez17f710e2016-07-18 16:08:56 -0700446 device_->Register(
447 RegistrationData{"TICKET_ID2"},
448 base::Bind([](decltype(this) test, bool* done, ErrorPtr error) {
449 EXPECT_TRUE(error->HasError("already_registered"));
450 *done = true;
451 test->task_runner_.Break();
452 EXPECT_EQ("CLOUD_ID", test->device_->GetSettings().cloud_id);
453 }, base::Unretained(this), base::Unretained(&done)));
Vitaly Buka0a8ab992016-01-11 14:01:20 -0800454 task_runner_.Run();
455 EXPECT_TRUE(done);
Vitaly Buka11b2f232015-08-20 13:55:41 -0700456}
457
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700458class WeaveWiFiSetupTest : public WeaveTest {
459 public:
460 void SetUp() override {
461 WeaveTest::SetUp();
462
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700463 InitHttpServer();
464 InitNetwork();
Vitaly Bukabeddc602015-09-24 15:28:03 -0700465 InitDnsSd();
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700466
467 EXPECT_CALL(network_, GetConnectionState())
Vitaly Bukaefad5b22015-10-08 10:02:14 -0700468 .WillRepeatedly(Return(provider::Network::State::kOnline));
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700469 }
470};
471
472TEST_F(WeaveWiFiSetupTest, StartOnlineNoPrevSsid) {
473 StartDevice();
474
475 // Short disconnect.
Vitaly Buka35f317d2015-09-27 22:54:39 -0700476 NotifyNetworkChanged(provider::Network::State::kOffline, {});
Vitaly Bukaefad5b22015-10-08 10:02:14 -0700477 NotifyNetworkChanged(provider::Network::State::kOnline,
Vitaly Buka3884ce12015-09-21 13:48:48 -0700478 base::TimeDelta::FromSeconds(10));
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700479 task_runner_.Run();
480
481 // Long disconnect.
Vitaly Buka35f317d2015-09-27 22:54:39 -0700482 NotifyNetworkChanged(Network::State::kOffline, {});
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700483 auto offline_from = task_runner_.GetClock()->Now();
Vitaly Bukaa05eadb2015-09-29 16:38:24 -0700484 EXPECT_CALL(wifi_, StartAccessPoint(MatchesRegex("TEST_NAME.*prv")))
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700485 .WillOnce(InvokeWithoutArgs([this, offline_from]() {
486 EXPECT_GT(task_runner_.GetClock()->Now() - offline_from,
487 base::TimeDelta::FromMinutes(1));
Vitaly Bukacaf42bd2015-09-16 11:23:23 -0700488 task_runner_.Break();
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700489 }));
490 task_runner_.Run();
491}
492
493// If device has previously configured WiFi it will run AP for limited time
494// after which it will try to re-connect.
495TEST_F(WeaveWiFiSetupTest, StartOnlineWithPrevSsid) {
496 EXPECT_CALL(config_store_, LoadSettings())
497 .WillRepeatedly(Return(R"({"last_configured_ssid": "TEST_ssid"})"));
498 StartDevice();
499
500 // Long disconnect.
Vitaly Buka35f317d2015-09-27 22:54:39 -0700501 NotifyNetworkChanged(Network::State::kOffline, {});
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700502
503 for (int i = 0; i < 5; ++i) {
504 auto offline_from = task_runner_.GetClock()->Now();
505 // Temporarily offline mode.
Vitaly Bukaa05eadb2015-09-29 16:38:24 -0700506 EXPECT_CALL(wifi_, StartAccessPoint(MatchesRegex("TEST_NAME.*prv")))
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700507 .WillOnce(InvokeWithoutArgs([this, &offline_from]() {
508 EXPECT_GT(task_runner_.GetClock()->Now() - offline_from,
509 base::TimeDelta::FromMinutes(1));
510 task_runner_.Break();
511 }));
512 task_runner_.Run();
513
514 // Try to reconnect again.
515 offline_from = task_runner_.GetClock()->Now();
Vitaly Buka1fd619a2015-09-24 11:46:05 -0700516 EXPECT_CALL(wifi_, StopAccessPoint())
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700517 .WillOnce(InvokeWithoutArgs([this, offline_from]() {
518 EXPECT_GT(task_runner_.GetClock()->Now() - offline_from,
519 base::TimeDelta::FromMinutes(5));
520 task_runner_.Break();
521 }));
522 task_runner_.Run();
523 }
524
Vitaly Bukaefad5b22015-10-08 10:02:14 -0700525 NotifyNetworkChanged(Network::State::kOnline, {});
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700526 task_runner_.Run();
527}
528
Vitaly Bukacaf42bd2015-09-16 11:23:23 -0700529TEST_F(WeaveWiFiSetupTest, StartOfflineWithSsid) {
530 EXPECT_CALL(config_store_, LoadSettings())
531 .WillRepeatedly(Return(R"({"last_configured_ssid": "TEST_ssid"})"));
532 EXPECT_CALL(network_, GetConnectionState())
Vitaly Buka35f317d2015-09-27 22:54:39 -0700533 .WillRepeatedly(Return(Network::State::kOffline));
Vitaly Bukacaf42bd2015-09-16 11:23:23 -0700534
535 auto offline_from = task_runner_.GetClock()->Now();
Vitaly Bukaa05eadb2015-09-29 16:38:24 -0700536 EXPECT_CALL(wifi_, StartAccessPoint(MatchesRegex("TEST_NAME.*prv")))
Vitaly Bukacaf42bd2015-09-16 11:23:23 -0700537 .WillOnce(InvokeWithoutArgs([this, &offline_from]() {
538 EXPECT_GT(task_runner_.GetClock()->Now() - offline_from,
539 base::TimeDelta::FromMinutes(1));
540 task_runner_.Break();
541 }));
542
543 StartDevice();
544}
545
Vitaly Buka65e1f212015-11-05 15:54:05 -0800546TEST_F(WeaveWiFiSetupTest, OfflineLongTimeWithNoSsid) {
547 EXPECT_CALL(network_, GetConnectionState())
548 .WillRepeatedly(Return(Network::State::kOffline));
549 NotifyNetworkChanged(provider::Network::State::kOnline,
550 base::TimeDelta::FromHours(15));
551
552 {
553 InSequence s;
554 auto time_stamp = task_runner_.GetClock()->Now();
555
556 EXPECT_CALL(wifi_, StartAccessPoint(MatchesRegex("TEST_NAME.*prv")))
557 .WillOnce(InvokeWithoutArgs([this, &time_stamp]() {
558 EXPECT_LE(task_runner_.GetClock()->Now() - time_stamp,
559 base::TimeDelta::FromMinutes(1));
560 time_stamp = task_runner_.GetClock()->Now();
561 }));
562
563 EXPECT_CALL(wifi_, StopAccessPoint())
564 .WillOnce(InvokeWithoutArgs([this, &time_stamp]() {
565 EXPECT_GT(task_runner_.GetClock()->Now() - time_stamp,
566 base::TimeDelta::FromMinutes(5));
567 time_stamp = task_runner_.GetClock()->Now();
568 task_runner_.Break();
569 }));
570 }
571
572 StartDevice();
573}
574
575TEST_F(WeaveWiFiSetupTest, OfflineLongTimeWithSsid) {
576 EXPECT_CALL(config_store_, LoadSettings())
577 .WillRepeatedly(Return(R"({"last_configured_ssid": "TEST_ssid"})"));
578 EXPECT_CALL(network_, GetConnectionState())
579 .WillRepeatedly(Return(Network::State::kOffline));
580 NotifyNetworkChanged(provider::Network::State::kOnline,
581 base::TimeDelta::FromHours(15));
582
583 {
584 InSequence s;
585 auto time_stamp = task_runner_.GetClock()->Now();
586 for (size_t i = 0; i < 10; ++i) {
587 EXPECT_CALL(wifi_, StartAccessPoint(MatchesRegex("TEST_NAME.*prv")))
588 .WillOnce(InvokeWithoutArgs([this, &time_stamp]() {
589 EXPECT_GT(task_runner_.GetClock()->Now() - time_stamp,
590 base::TimeDelta::FromMinutes(1));
591 time_stamp = task_runner_.GetClock()->Now();
592 }));
593
594 EXPECT_CALL(wifi_, StopAccessPoint())
595 .WillOnce(InvokeWithoutArgs([this, &time_stamp]() {
596 EXPECT_GT(task_runner_.GetClock()->Now() - time_stamp,
597 base::TimeDelta::FromMinutes(5));
598 time_stamp = task_runner_.GetClock()->Now();
599 }));
600 }
601
602 EXPECT_CALL(wifi_, StartAccessPoint(MatchesRegex("TEST_NAME.*prv")))
603 .WillOnce(InvokeWithoutArgs([this]() { task_runner_.Break(); }));
604 }
605
606 StartDevice();
607}
608
Vitaly Buka11b2f232015-08-20 13:55:41 -0700609} // namespace weave