blob: 66850cf73ce1bcd12056205f9b11396897aaf3e7 [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 Bukac5bdd172015-10-01 19:48:51 -0700184 void SetUp() override {}
Vitaly Buka11b2f232015-08-20 13:55:41 -0700185
Vitaly Buka1a42e142015-10-10 18:15:15 -0700186 void ExpectRequest(HttpClient::Method method,
Vitaly Buka11b2f232015-08-20 13:55:41 -0700187 const std::string& url,
188 const std::string& json_response) {
Vitaly Buka74763422015-10-11 00:39:52 -0700189 EXPECT_CALL(http_client_, SendRequest(method, url, _, _, _))
Vitaly Buka17280372015-10-10 17:11:47 -0700190 .WillOnce(WithArgs<4>(Invoke([json_response](
Vitaly Buka74763422015-10-11 00:39:52 -0700191 const HttpClient::SendRequestCallback& callback) {
Vitaly Buka17280372015-10-10 17:11:47 -0700192 std::unique_ptr<provider::test::MockHttpClientResponse> response{
193 new StrictMock<provider::test::MockHttpClientResponse>};
Vitaly Buka11b2f232015-08-20 13:55:41 -0700194 EXPECT_CALL(*response, GetStatusCode())
195 .Times(AtLeast(1))
196 .WillRepeatedly(Return(200));
197 EXPECT_CALL(*response, GetContentType())
198 .Times(AtLeast(1))
199 .WillRepeatedly(Return("application/json; charset=utf-8"));
200 EXPECT_CALL(*response, GetData())
Vitaly Buka4774df22015-10-09 12:36:22 -0700201 .WillRepeatedly(Return(json_response));
Vitaly Buka74763422015-10-11 00:39:52 -0700202 callback.Run(std::move(response), nullptr);
Vitaly Buka17280372015-10-10 17:11:47 -0700203 })));
Vitaly Buka11b2f232015-08-20 13:55:41 -0700204 }
205
206 void InitConfigStore() {
Vitaly Buka11b2f232015-08-20 13:55:41 -0700207 EXPECT_CALL(config_store_, SaveSettings("")).WillRepeatedly(Return());
Vitaly Buka11b2f232015-08-20 13:55:41 -0700208 }
209
210 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 Buka11b2f232015-08-20 13:55:41 -0700266 }
267
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700268 void InitDefaultExpectations() {
Vitaly Buka11b2f232015-08-20 13:55:41 -0700269 InitConfigStore();
270 InitNetwork();
Vitaly Bukaa05eadb2015-09-29 16:38:24 -0700271 EXPECT_CALL(wifi_, StartAccessPoint(MatchesRegex("TEST_NAME.*prv")))
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700272 .WillOnce(Return());
Vitaly Buka11b2f232015-08-20 13:55:41 -0700273 InitHttpServer();
Vitaly Bukabeddc602015-09-24 15:28:03 -0700274 InitDnsSd();
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700275 }
Vitaly Buka11b2f232015-08-20 13:55:41 -0700276
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700277 void StartDevice() {
Vitaly Bukac5bdd172015-10-01 19:48:51 -0700278 device_ = weave::Device::Create(&config_store_, &task_runner_,
279 &http_client_, &network_, &dns_sd_,
280 &http_server_, &wifi_, &bluetooth_);
Vitaly Buka11b2f232015-08-20 13:55:41 -0700281
Vitaly Bukae69e4ee2015-10-26 18:30:14 -0700282 EXPECT_EQ((std::set<std::string>{
283 "/privet/info", "/privet/v3/pairing/cancel",
284 "/privet/v3/pairing/confirm", "/privet/v3/pairing/start"}),
285 GetKeys(http_handlers_));
286 EXPECT_EQ((std::set<std::string>{
Alex Vakulenkoefee3a22015-11-17 15:08:38 -0800287 "/privet/info", "/privet/v3/auth",
288 "/privet/v3/checkForUpdates", "/privet/v3/commandDefs",
Vitaly Bukae69e4ee2015-10-26 18:30:14 -0700289 "/privet/v3/commands/cancel", "/privet/v3/commands/execute",
290 "/privet/v3/commands/list", "/privet/v3/commands/status",
Alex Vakulenko551a82b2015-12-07 14:46:12 -0800291 "/privet/v3/components", "/privet/v3/pairing/cancel",
292 "/privet/v3/pairing/confirm", "/privet/v3/pairing/start",
293 "/privet/v3/setup/start", "/privet/v3/setup/status",
294 "/privet/v3/state", "/privet/v3/traits"}),
Vitaly Bukae69e4ee2015-10-26 18:30:14 -0700295 GetKeys(https_handlers_));
296
Alex Vakulenko551a82b2015-12-07 14:46:12 -0800297 device_->AddTraitDefinitionsFromJson(kTraitDefs);
298 EXPECT_TRUE(device_->AddComponent("myComponent", {"trait1", "trait2"},
299 nullptr));
300 EXPECT_TRUE(device_->SetStatePropertiesFromJson(
301 "myComponent", R"({"trait2": {"battery_level":44}})", nullptr));
Vitaly Buka0ac6ca62015-10-06 19:16:29 -0700302
Vitaly Buka11b2f232015-08-20 13:55:41 -0700303 task_runner_.Run();
304 }
305
Vitaly Buka35f317d2015-09-27 22:54:39 -0700306 void NotifyNetworkChanged(provider::Network::State state,
Vitaly Buka1e363672015-09-25 14:01:16 -0700307 base::TimeDelta delay) {
Vitaly Buka65e1f212015-11-05 15:54:05 -0800308 auto task = [this, state] {
309 EXPECT_CALL(network_, GetConnectionState()).WillRepeatedly(Return(state));
310 for (const auto& cb : network_callbacks_)
311 cb.Run();
312 };
313
314 task_runner_.PostDelayedTask(FROM_HERE, base::Bind(task), delay);
Vitaly Buka3884ce12015-09-21 13:48:48 -0700315 }
316
Vitaly Bukae69e4ee2015-10-26 18:30:14 -0700317 std::map<std::string, provider::HttpServer::RequestHandlerCallback>
318 http_handlers_;
319 std::map<std::string, provider::HttpServer::RequestHandlerCallback>
320 https_handlers_;
Vitaly Buka11b2f232015-08-20 13:55:41 -0700321
Vitaly Buka1e363672015-09-25 14:01:16 -0700322 StrictMock<provider::test::MockConfigStore> config_store_;
Vitaly Buka727f3e62015-09-25 17:33:43 -0700323 StrictMock<provider::test::FakeTaskRunner> task_runner_;
Vitaly Buka1e363672015-09-25 14:01:16 -0700324 StrictMock<provider::test::MockHttpClient> http_client_;
325 StrictMock<provider::test::MockNetwork> network_;
326 StrictMock<provider::test::MockDnsServiceDiscovery> dns_sd_;
327 StrictMock<provider::test::MockHttpServer> http_server_;
328 StrictMock<provider::test::MockWifi> wifi_;
329 StrictMock<provider::test::MockBluetooth> bluetooth_;
Vitaly Buka11b2f232015-08-20 13:55:41 -0700330
Vitaly Buka1e363672015-09-25 14:01:16 -0700331 std::vector<provider::Network::ConnectionChangedCallback> network_callbacks_;
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700332
Vitaly Buka11b2f232015-08-20 13:55:41 -0700333 std::unique_ptr<weave::Device> device_;
334};
335
Vitaly Bukaef213d72015-10-07 15:54:58 -0700336TEST_F(WeaveTest, Mocks) {
Vitaly Bukaa8ece8f2015-10-05 13:30:23 -0700337 // Test checks if mock implements entire interface and mock can be
338 // instantiated.
339 test::MockDevice device;
Vitaly Bukaef213d72015-10-07 15:54:58 -0700340 test::MockCommand command;
Vitaly Bukaa8ece8f2015-10-05 13:30:23 -0700341}
342
Vitaly Buka11b2f232015-08-20 13:55:41 -0700343TEST_F(WeaveTest, StartMinimal) {
Vitaly Buka11b2f232015-08-20 13:55:41 -0700344 InitConfigStore();
Vitaly Bukac5bdd172015-10-01 19:48:51 -0700345 device_ = weave::Device::Create(&config_store_, &task_runner_, &http_client_,
346 &network_, nullptr, nullptr, &wifi_, nullptr);
Vitaly Bukab1041e72015-09-21 15:26:51 -0700347}
348
349TEST_F(WeaveTest, StartNoWifi) {
350 InitConfigStore();
351 InitNetwork();
352 InitHttpServer();
Vitaly Bukabeddc602015-09-24 15:28:03 -0700353 InitDnsSd();
354 InitDnsSdPublishing(false, "CB");
Vitaly Bukab1041e72015-09-21 15:26:51 -0700355
Vitaly Bukac5bdd172015-10-01 19:48:51 -0700356 device_ = weave::Device::Create(&config_store_, &task_runner_, &http_client_,
357 &network_, &dns_sd_, &http_server_, nullptr,
358 &bluetooth_);
Alex Vakulenko551a82b2015-12-07 14:46:12 -0800359 device_->AddTraitDefinitionsFromJson(kTraitDefs);
360 EXPECT_TRUE(device_->AddComponent("myComponent", {"trait1", "trait2"},
361 nullptr));
Vitaly Bukab1041e72015-09-21 15:26:51 -0700362
Vitaly Bukab1041e72015-09-21 15:26:51 -0700363 task_runner_.Run();
Vitaly Buka11b2f232015-08-20 13:55:41 -0700364}
365
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700366class WeaveBasicTest : public WeaveTest {
367 public:
368 void SetUp() override {
369 WeaveTest::SetUp();
Vitaly Buka3884ce12015-09-21 13:48:48 -0700370
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700371 InitDefaultExpectations();
Vitaly Bukabeddc602015-09-24 15:28:03 -0700372 InitDnsSdPublishing(false, "DB");
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700373 }
374};
375
376TEST_F(WeaveBasicTest, Start) {
Vitaly Buka11b2f232015-08-20 13:55:41 -0700377 StartDevice();
378}
379
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700380TEST_F(WeaveBasicTest, Register) {
Vitaly Buka74763422015-10-11 00:39:52 -0700381 EXPECT_CALL(network_, OpenSslSocket(_, _, _)).WillRepeatedly(Return());
Vitaly Buka11b2f232015-08-20 13:55:41 -0700382 StartDevice();
383
384 auto draft = CreateDictionaryValue(kDeviceResource);
385 auto response = CreateDictionaryValue(kRegistrationResponse);
386 response->Set("deviceDraft", draft->DeepCopy());
Vitaly Buka0d7aac82015-11-16 23:02:24 -0800387 ExpectRequest(HttpClient::Method::kPatch,
388 "https://www.googleapis.com/weave/v1/registrationTickets/"
389 "TICKET_ID?key=TEST_API_KEY",
390 ValueToString(*response));
Vitaly Buka11b2f232015-08-20 13:55:41 -0700391
392 response = CreateDictionaryValue(kRegistrationFinalResponse);
393 response->Set("deviceDraft", draft->DeepCopy());
Vitaly Buka0d7aac82015-11-16 23:02:24 -0800394 ExpectRequest(HttpClient::Method::kPost,
395 "https://www.googleapis.com/weave/v1/registrationTickets/"
396 "TICKET_ID/finalize?key=TEST_API_KEY",
397 ValueToString(*response));
Vitaly Buka11b2f232015-08-20 13:55:41 -0700398
Vitaly Buka1a42e142015-10-10 18:15:15 -0700399 ExpectRequest(HttpClient::Method::kPost,
400 "https://accounts.google.com/o/oauth2/token",
Vitaly Buka11b2f232015-08-20 13:55:41 -0700401 kAuthTokenResponse);
402
Vitaly Bukabeddc602015-09-24 15:28:03 -0700403 InitDnsSdPublishing(true, "DB");
Vitaly Buka11b2f232015-08-20 13:55:41 -0700404
Vitaly Buka12870bd2015-10-08 23:49:39 -0700405 bool done = false;
Vitaly Buka74763422015-10-11 00:39:52 -0700406 device_->Register("TICKET_ID", base::Bind([this, &done](ErrorPtr error) {
407 EXPECT_FALSE(error);
Vitaly Buka12870bd2015-10-08 23:49:39 -0700408 done = true;
409 task_runner_.Break();
410 EXPECT_EQ("CLOUD_ID", device_->GetSettings().cloud_id);
Vitaly Buka74763422015-10-11 00:39:52 -0700411 }));
Vitaly Buka12870bd2015-10-08 23:49:39 -0700412 task_runner_.Run();
413 EXPECT_TRUE(done);
Vitaly Buka11b2f232015-08-20 13:55:41 -0700414}
415
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700416class WeaveWiFiSetupTest : public WeaveTest {
417 public:
418 void SetUp() override {
419 WeaveTest::SetUp();
420
421 InitConfigStore();
422 InitHttpServer();
423 InitNetwork();
Vitaly Bukabeddc602015-09-24 15:28:03 -0700424 InitDnsSd();
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700425
426 EXPECT_CALL(network_, GetConnectionState())
Vitaly Bukaefad5b22015-10-08 10:02:14 -0700427 .WillRepeatedly(Return(provider::Network::State::kOnline));
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700428 }
429};
430
431TEST_F(WeaveWiFiSetupTest, StartOnlineNoPrevSsid) {
432 StartDevice();
433
434 // Short disconnect.
Vitaly Buka35f317d2015-09-27 22:54:39 -0700435 NotifyNetworkChanged(provider::Network::State::kOffline, {});
Vitaly Bukaefad5b22015-10-08 10:02:14 -0700436 NotifyNetworkChanged(provider::Network::State::kOnline,
Vitaly Buka3884ce12015-09-21 13:48:48 -0700437 base::TimeDelta::FromSeconds(10));
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700438 task_runner_.Run();
439
440 // Long disconnect.
Vitaly Buka35f317d2015-09-27 22:54:39 -0700441 NotifyNetworkChanged(Network::State::kOffline, {});
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700442 auto offline_from = task_runner_.GetClock()->Now();
Vitaly Bukaa05eadb2015-09-29 16:38:24 -0700443 EXPECT_CALL(wifi_, StartAccessPoint(MatchesRegex("TEST_NAME.*prv")))
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700444 .WillOnce(InvokeWithoutArgs([this, offline_from]() {
445 EXPECT_GT(task_runner_.GetClock()->Now() - offline_from,
446 base::TimeDelta::FromMinutes(1));
Vitaly Bukacaf42bd2015-09-16 11:23:23 -0700447 task_runner_.Break();
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700448 }));
449 task_runner_.Run();
450}
451
452// If device has previously configured WiFi it will run AP for limited time
453// after which it will try to re-connect.
454TEST_F(WeaveWiFiSetupTest, StartOnlineWithPrevSsid) {
455 EXPECT_CALL(config_store_, LoadSettings())
456 .WillRepeatedly(Return(R"({"last_configured_ssid": "TEST_ssid"})"));
457 StartDevice();
458
459 // Long disconnect.
Vitaly Buka35f317d2015-09-27 22:54:39 -0700460 NotifyNetworkChanged(Network::State::kOffline, {});
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700461
462 for (int i = 0; i < 5; ++i) {
463 auto offline_from = task_runner_.GetClock()->Now();
464 // Temporarily offline mode.
Vitaly Bukaa05eadb2015-09-29 16:38:24 -0700465 EXPECT_CALL(wifi_, StartAccessPoint(MatchesRegex("TEST_NAME.*prv")))
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700466 .WillOnce(InvokeWithoutArgs([this, &offline_from]() {
467 EXPECT_GT(task_runner_.GetClock()->Now() - offline_from,
468 base::TimeDelta::FromMinutes(1));
469 task_runner_.Break();
470 }));
471 task_runner_.Run();
472
473 // Try to reconnect again.
474 offline_from = task_runner_.GetClock()->Now();
Vitaly Buka1fd619a2015-09-24 11:46:05 -0700475 EXPECT_CALL(wifi_, StopAccessPoint())
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700476 .WillOnce(InvokeWithoutArgs([this, offline_from]() {
477 EXPECT_GT(task_runner_.GetClock()->Now() - offline_from,
478 base::TimeDelta::FromMinutes(5));
479 task_runner_.Break();
480 }));
481 task_runner_.Run();
482 }
483
Vitaly Bukaefad5b22015-10-08 10:02:14 -0700484 NotifyNetworkChanged(Network::State::kOnline, {});
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700485 task_runner_.Run();
486}
487
Vitaly Bukacaf42bd2015-09-16 11:23:23 -0700488TEST_F(WeaveWiFiSetupTest, StartOfflineWithSsid) {
489 EXPECT_CALL(config_store_, LoadSettings())
490 .WillRepeatedly(Return(R"({"last_configured_ssid": "TEST_ssid"})"));
491 EXPECT_CALL(network_, GetConnectionState())
Vitaly Buka35f317d2015-09-27 22:54:39 -0700492 .WillRepeatedly(Return(Network::State::kOffline));
Vitaly Bukacaf42bd2015-09-16 11:23:23 -0700493
494 auto offline_from = task_runner_.GetClock()->Now();
Vitaly Bukaa05eadb2015-09-29 16:38:24 -0700495 EXPECT_CALL(wifi_, StartAccessPoint(MatchesRegex("TEST_NAME.*prv")))
Vitaly Bukacaf42bd2015-09-16 11:23:23 -0700496 .WillOnce(InvokeWithoutArgs([this, &offline_from]() {
497 EXPECT_GT(task_runner_.GetClock()->Now() - offline_from,
498 base::TimeDelta::FromMinutes(1));
499 task_runner_.Break();
500 }));
501
502 StartDevice();
503}
504
Vitaly Buka65e1f212015-11-05 15:54:05 -0800505TEST_F(WeaveWiFiSetupTest, OfflineLongTimeWithNoSsid) {
506 EXPECT_CALL(network_, GetConnectionState())
507 .WillRepeatedly(Return(Network::State::kOffline));
508 NotifyNetworkChanged(provider::Network::State::kOnline,
509 base::TimeDelta::FromHours(15));
510
511 {
512 InSequence s;
513 auto time_stamp = task_runner_.GetClock()->Now();
514
515 EXPECT_CALL(wifi_, StartAccessPoint(MatchesRegex("TEST_NAME.*prv")))
516 .WillOnce(InvokeWithoutArgs([this, &time_stamp]() {
517 EXPECT_LE(task_runner_.GetClock()->Now() - time_stamp,
518 base::TimeDelta::FromMinutes(1));
519 time_stamp = task_runner_.GetClock()->Now();
520 }));
521
522 EXPECT_CALL(wifi_, StopAccessPoint())
523 .WillOnce(InvokeWithoutArgs([this, &time_stamp]() {
524 EXPECT_GT(task_runner_.GetClock()->Now() - time_stamp,
525 base::TimeDelta::FromMinutes(5));
526 time_stamp = task_runner_.GetClock()->Now();
527 task_runner_.Break();
528 }));
529 }
530
531 StartDevice();
532}
533
534TEST_F(WeaveWiFiSetupTest, OfflineLongTimeWithSsid) {
535 EXPECT_CALL(config_store_, LoadSettings())
536 .WillRepeatedly(Return(R"({"last_configured_ssid": "TEST_ssid"})"));
537 EXPECT_CALL(network_, GetConnectionState())
538 .WillRepeatedly(Return(Network::State::kOffline));
539 NotifyNetworkChanged(provider::Network::State::kOnline,
540 base::TimeDelta::FromHours(15));
541
542 {
543 InSequence s;
544 auto time_stamp = task_runner_.GetClock()->Now();
545 for (size_t i = 0; i < 10; ++i) {
546 EXPECT_CALL(wifi_, StartAccessPoint(MatchesRegex("TEST_NAME.*prv")))
547 .WillOnce(InvokeWithoutArgs([this, &time_stamp]() {
548 EXPECT_GT(task_runner_.GetClock()->Now() - time_stamp,
549 base::TimeDelta::FromMinutes(1));
550 time_stamp = task_runner_.GetClock()->Now();
551 }));
552
553 EXPECT_CALL(wifi_, StopAccessPoint())
554 .WillOnce(InvokeWithoutArgs([this, &time_stamp]() {
555 EXPECT_GT(task_runner_.GetClock()->Now() - time_stamp,
556 base::TimeDelta::FromMinutes(5));
557 time_stamp = task_runner_.GetClock()->Now();
558 }));
559 }
560
561 EXPECT_CALL(wifi_, StartAccessPoint(MatchesRegex("TEST_NAME.*prv")))
562 .WillOnce(InvokeWithoutArgs([this]() { task_runner_.Break(); }));
563 }
564
565 StartDevice();
566}
567
Vitaly Buka11b2f232015-08-20 13:55:41 -0700568} // namespace weave