blob: bcd39e24000a9b7a47fc1451d32cfb839d7248ae [file] [log] [blame]
Vitaly Buka11b2f232015-08-20 13:55:41 -07001// Copyright 2015 The Chromium OS Authors. All rights reserved.
2// 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 Buka0f6b2ec2015-08-20 15:35:19 -070017#include <weave/test/unittest_utils.h>
Vitaly Buka11b2f232015-08-20 13:55:41 -070018
Stefan Sauer2d16dfa2015-09-25 17:08:35 +020019#include "src/bind_lambda.h"
Vitaly Buka11b2f232015-08-20 13:55:41 -070020
21using testing::_;
22using testing::AtMost;
23using testing::HasSubstr;
24using testing::Invoke;
25using testing::InvokeWithoutArgs;
26using testing::MatchesRegex;
27using testing::Mock;
28using testing::AtLeast;
29using testing::Return;
30using testing::ReturnRefOfCopy;
31using testing::StartsWith;
32using testing::StrictMock;
33using testing::WithArgs;
34
35namespace weave {
36
Vitaly Buka0f6b2ec2015-08-20 15:35:19 -070037using test::CreateDictionaryValue;
38using test::ValueToString;
Vitaly Buka1e363672015-09-25 14:01:16 -070039using provider::test::MockHttpClientResponse;
Vitaly Buka35f317d2015-09-27 22:54:39 -070040using provider::Network;
Vitaly Buka11b2f232015-08-20 13:55:41 -070041
42const char kCategory[] = "powerd";
43
Vitaly Buka11b2f232015-08-20 13:55:41 -070044const char kCommandDefs[] = R"({
45 "base": {
46 "reboot": {},
Vitaly Bukae5b20412015-09-30 15:41:28 -070047 "_shutdown": {
48 "parameters": {},
49 "results": {}
Vitaly Buka11b2f232015-08-20 13:55:41 -070050 }
51 }
52})";
53
Vitaly Buka11b2f232015-08-20 13:55:41 -070054const char kDeviceResource[] = R"({
55 "kind": "clouddevices#device",
Johan Euphrosine0b7bb9f2015-09-29 01:11:21 -070056 "id": "CLOUD_ID",
Vitaly Buka11b2f232015-08-20 13:55:41 -070057 "channel": {
58 "supportedType": "pull"
59 },
60 "deviceKind": "vendor",
61 "modelManifestId": "ABCDE",
62 "systemName": "",
Vitaly Bukaa05eadb2015-09-29 16:38:24 -070063 "name": "TEST_NAME",
Vitaly Buka11b2f232015-08-20 13:55:41 -070064 "displayName": "",
65 "description": "Developer device",
66 "stateValidationEnabled": true,
67 "commandDefs":{
68 "base": {
69 "reboot": {
70 "minimalRole": "user",
71 "parameters": {"delay": "integer"},
72 "results": {}
73 },
74 "shutdown": {
75 "minimalRole": "user",
76 "parameters": {},
77 "results": {}
78 }
79 }
80 },
81 "state":{
82 "base":{
83 "firmwareVersion":"FIRMWARE_VERSION",
84 "localAnonymousAccessMaxRole":"viewer",
85 "localDiscoveryEnabled":true,
86 "localPairingEnabled":true,
87 "network":{
88 }
89 },
90 "power": {"battery_level":44}
91 }
92})";
93
94const char kRegistrationResponse[] = R"({
95 "kind": "clouddevices#registrationTicket",
Johan Euphrosine0b7bb9f2015-09-29 01:11:21 -070096 "id": "TICKET_ID",
97 "deviceId": "CLOUD_ID",
Vitaly Buka11b2f232015-08-20 13:55:41 -070098 "oauthClientId": "CLIENT_ID",
99 "userEmail": "USER@gmail.com",
100 "creationTimeMs": "1440087183738",
101 "expirationTimeMs": "1440087423738"
102})";
103
104const char kRegistrationFinalResponse[] = R"({
105 "kind": "clouddevices#registrationTicket",
Johan Euphrosine0b7bb9f2015-09-29 01:11:21 -0700106 "id": "TICKET_ID",
107 "deviceId": "CLOUD_ID",
Vitaly Buka11b2f232015-08-20 13:55:41 -0700108 "oauthClientId": "CLIENT_ID",
109 "userEmail": "USER@gmail.com",
110 "robotAccountEmail": "ROBO@gmail.com",
111 "robotAccountAuthorizationCode": "AUTH_CODE",
112 "creationTimeMs": "1440087183738",
113 "expirationTimeMs": "1440087423738"
114})";
115
116const char kAuthTokenResponse[] = R"({
117 "access_token" : "ACCESS_TOKEN",
118 "token_type" : "Bearer",
119 "expires_in" : 3599,
120 "refresh_token" : "REFRESH_TOKEN"
121})";
122
123const char kStateDefs[] = R"({"power": {"battery_level":"integer"}})";
124
125const char kStateDefaults[] = R"({"power": {"battery_level":44}})";
126
Vitaly Buka3dc2f532015-09-08 18:01:32 -0700127MATCHER_P(MatchTxt, txt, "") {
128 std::vector<std::string> txt_copy = txt;
129 std::sort(txt_copy.begin(), txt_copy.end());
130 std::vector<std::string> arg_copy = arg;
131 std::sort(arg_copy.begin(), arg_copy.end());
132 return (arg_copy == txt_copy);
133}
134
Vitaly Buka11b2f232015-08-20 13:55:41 -0700135class WeaveTest : public ::testing::Test {
136 protected:
137 void SetUp() override { device_ = weave::Device::Create(); }
138
139 void ExpectRequest(const std::string& method,
140 const std::string& url,
141 const std::string& json_response) {
142 EXPECT_CALL(http_client_, MockSendRequest(method, url, _, _, _))
143 .WillOnce(InvokeWithoutArgs([json_response]() {
Vitaly Buka1e363672015-09-25 14:01:16 -0700144 provider::test::MockHttpClientResponse* response =
145 new StrictMock<provider::test::MockHttpClientResponse>;
Vitaly Buka11b2f232015-08-20 13:55:41 -0700146 EXPECT_CALL(*response, GetStatusCode())
147 .Times(AtLeast(1))
148 .WillRepeatedly(Return(200));
149 EXPECT_CALL(*response, GetContentType())
150 .Times(AtLeast(1))
151 .WillRepeatedly(Return("application/json; charset=utf-8"));
152 EXPECT_CALL(*response, GetData())
153 .Times(AtLeast(1))
154 .WillRepeatedly(ReturnRefOfCopy(json_response));
155 return response;
156 }));
157 }
158
159 void InitConfigStore() {
Vitaly Buka11b2f232015-08-20 13:55:41 -0700160 EXPECT_CALL(config_store_, SaveSettings("")).WillRepeatedly(Return());
161
Vitaly Buka11b2f232015-08-20 13:55:41 -0700162 EXPECT_CALL(config_store_, LoadCommandDefs())
163 .WillOnce(Return(
164 std::map<std::string, std::string>{{kCategory, kCommandDefs}}));
165
Vitaly Buka11b2f232015-08-20 13:55:41 -0700166 EXPECT_CALL(config_store_, LoadStateDefs())
167 .WillOnce(Return(
168 std::map<std::string, std::string>{{kCategory, kStateDefs}}));
169
Vitaly Buka11b2f232015-08-20 13:55:41 -0700170 EXPECT_CALL(config_store_, LoadStateDefaults())
171 .WillOnce(Return(std::vector<std::string>{kStateDefaults}));
172 }
173
174 void InitNetwork() {
Vitaly Buka3ab6f6e2015-09-24 13:16:16 -0700175 EXPECT_CALL(network_, AddConnectionChangedCallback(_))
176 .WillRepeatedly(Invoke(
Vitaly Buka1e363672015-09-25 14:01:16 -0700177 [this](const provider::Network::ConnectionChangedCallback& cb) {
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700178 network_callbacks_.push_back(cb);
179 }));
Vitaly Buka11b2f232015-08-20 13:55:41 -0700180 EXPECT_CALL(network_, GetConnectionState())
Vitaly Buka35f317d2015-09-27 22:54:39 -0700181 .WillRepeatedly(Return(Network::State::kOffline));
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700182 }
183
Vitaly Bukabeddc602015-09-24 15:28:03 -0700184 void InitDnsSd() {
Vitaly Bukabeddc602015-09-24 15:28:03 -0700185 EXPECT_CALL(dns_sd_, PublishService(_, _, _)).WillRepeatedly(Return());
186 EXPECT_CALL(dns_sd_, StopPublishing("_privet._tcp")).WillOnce(Return());
Vitaly Buka11b2f232015-08-20 13:55:41 -0700187 }
188
Vitaly Bukabeddc602015-09-24 15:28:03 -0700189 void InitDnsSdPublishing(bool registered, const std::string& flags) {
Johan Euphrosine0b7bb9f2015-09-29 01:11:21 -0700190 std::vector<std::string> txt{{"id=TEST_DEVICE_ID"}, {"flags=" + flags},
191 {"mmid=ABCDE"}, {"services=_base"},
192 {"txtvers=3"}, {"ty=TEST_NAME"}};
Vitaly Buka11b2f232015-08-20 13:55:41 -0700193 if (registered) {
Johan Euphrosine0b7bb9f2015-09-29 01:11:21 -0700194 txt.push_back("gcd_id=CLOUD_ID");
Vitaly Buka11b2f232015-08-20 13:55:41 -0700195
196 // During registration device may announce itself twice:
197 // 1. with GCD ID but not connected (DB)
198 // 2. with GCD ID and connected (BB)
Vitaly Bukabeddc602015-09-24 15:28:03 -0700199 EXPECT_CALL(dns_sd_, PublishService("_privet._tcp", 11, MatchTxt(txt)))
Vitaly Buka11b2f232015-08-20 13:55:41 -0700200 .Times(AtMost(1))
201 .WillOnce(Return());
202
Vitaly Buka3dc2f532015-09-08 18:01:32 -0700203 txt[1] = "flags=BB";
Vitaly Buka11b2f232015-08-20 13:55:41 -0700204 }
205
Vitaly Bukabeddc602015-09-24 15:28:03 -0700206 EXPECT_CALL(dns_sd_, PublishService("_privet._tcp", 11, MatchTxt(txt)))
Vitaly Buka3dc2f532015-09-08 18:01:32 -0700207 .WillOnce(Return());
Vitaly Buka11b2f232015-08-20 13:55:41 -0700208 }
209
210 void InitHttpServer() {
211 EXPECT_CALL(http_server_, GetHttpPort()).WillRepeatedly(Return(11));
212 EXPECT_CALL(http_server_, GetHttpsPort()).WillRepeatedly(Return(12));
213 EXPECT_CALL(http_server_, GetHttpsCertificateFingerprint())
214 .WillRepeatedly(ReturnRefOfCopy(std::vector<uint8_t>{1, 2, 3}));
215 EXPECT_CALL(http_server_, AddRequestHandler(_, _))
Vitaly Buka11b2f232015-08-20 13:55:41 -0700216 .WillRepeatedly(
Vitaly Buka1e363672015-09-25 14:01:16 -0700217 Invoke([this](const std::string& path_prefix,
218 const provider::HttpServer::OnRequestCallback& cb) {
219 http_server_request_cb_.push_back(cb);
220 }));
221 EXPECT_CALL(http_server_, AddOnStateChangedCallback(_))
222 .WillRepeatedly(Invoke(
223 [this](const provider::HttpServer::OnStateChangedCallback& cb) {
Vitaly Buka11b2f232015-08-20 13:55:41 -0700224 http_server_changed_cb_.push_back(cb);
225 }));
226 }
227
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700228 void InitDefaultExpectations() {
Vitaly Buka11b2f232015-08-20 13:55:41 -0700229 InitConfigStore();
230 InitNetwork();
Vitaly Bukaa05eadb2015-09-29 16:38:24 -0700231 EXPECT_CALL(wifi_, StartAccessPoint(MatchesRegex("TEST_NAME.*prv")))
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700232 .WillOnce(Return());
Vitaly Buka11b2f232015-08-20 13:55:41 -0700233 InitHttpServer();
Vitaly Bukabeddc602015-09-24 15:28:03 -0700234 InitDnsSd();
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700235 }
Vitaly Buka11b2f232015-08-20 13:55:41 -0700236
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700237 void StartDevice() {
Vitaly Buka41a90d62015-09-29 16:58:39 -0700238 device_->Start(&config_store_, &task_runner_, &http_client_, &network_,
239 &dns_sd_, &http_server_, &wifi_, &bluetooth_);
Vitaly Buka11b2f232015-08-20 13:55:41 -0700240
241 cloud_ = device_->GetCloud();
242 ASSERT_TRUE(cloud_);
243
244 cloud_->GetDeviceInfo(
245 base::Bind(
246 [](const base::DictionaryValue& response) { ADD_FAILURE(); }),
247 base::Bind([](const Error* error) {
248 EXPECT_TRUE(error->HasError("gcd", "device_not_registered"));
249 }));
250
Vitaly Buka3884ce12015-09-21 13:48:48 -0700251 for (const auto& cb : http_server_changed_cb_)
Vitaly Buka11b2f232015-08-20 13:55:41 -0700252 cb.Run(http_server_);
Vitaly Buka11b2f232015-08-20 13:55:41 -0700253
254 task_runner_.Run();
255 }
256
Vitaly Buka35f317d2015-09-27 22:54:39 -0700257 void NotifyNetworkChanged(provider::Network::State state,
Vitaly Buka1e363672015-09-25 14:01:16 -0700258 base::TimeDelta delay) {
Vitaly Buka3884ce12015-09-21 13:48:48 -0700259 EXPECT_CALL(network_, GetConnectionState()).WillRepeatedly(Return(state));
260 for (const auto& cb : network_callbacks_) {
261 task_runner_.PostDelayedTask(FROM_HERE, cb, delay);
262 }
263 }
264
Vitaly Buka1e363672015-09-25 14:01:16 -0700265 std::vector<provider::HttpServer::OnStateChangedCallback>
266 http_server_changed_cb_;
267 std::vector<provider::HttpServer::OnRequestCallback> http_server_request_cb_;
Vitaly Buka11b2f232015-08-20 13:55:41 -0700268
Vitaly Buka1e363672015-09-25 14:01:16 -0700269 StrictMock<provider::test::MockConfigStore> config_store_;
Vitaly Buka727f3e62015-09-25 17:33:43 -0700270 StrictMock<provider::test::FakeTaskRunner> task_runner_;
Vitaly Buka1e363672015-09-25 14:01:16 -0700271 StrictMock<provider::test::MockHttpClient> http_client_;
272 StrictMock<provider::test::MockNetwork> network_;
273 StrictMock<provider::test::MockDnsServiceDiscovery> dns_sd_;
274 StrictMock<provider::test::MockHttpServer> http_server_;
275 StrictMock<provider::test::MockWifi> wifi_;
276 StrictMock<provider::test::MockBluetooth> bluetooth_;
Vitaly Buka11b2f232015-08-20 13:55:41 -0700277
Vitaly Buka1e363672015-09-25 14:01:16 -0700278 std::vector<provider::Network::ConnectionChangedCallback> network_callbacks_;
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700279
Vitaly Buka11b2f232015-08-20 13:55:41 -0700280 weave::Cloud* cloud_{nullptr};
281
282 std::unique_ptr<weave::Device> device_;
283};
284
285TEST_F(WeaveTest, Create) {
286 ASSERT_TRUE(device_.get());
287}
288
289TEST_F(WeaveTest, StartMinimal) {
Vitaly Buka11b2f232015-08-20 13:55:41 -0700290 InitConfigStore();
Vitaly Buka41a90d62015-09-29 16:58:39 -0700291 device_->Start(&config_store_, &task_runner_, &http_client_, &network_,
292 nullptr, nullptr, &wifi_, nullptr);
Vitaly Bukab1041e72015-09-21 15:26:51 -0700293}
294
295TEST_F(WeaveTest, StartNoWifi) {
296 InitConfigStore();
297 InitNetwork();
298 InitHttpServer();
Vitaly Bukabeddc602015-09-24 15:28:03 -0700299 InitDnsSd();
300 InitDnsSdPublishing(false, "CB");
Vitaly Bukab1041e72015-09-21 15:26:51 -0700301
Vitaly Buka41a90d62015-09-29 16:58:39 -0700302 device_->Start(&config_store_, &task_runner_, &http_client_, &network_,
303 &dns_sd_, &http_server_, nullptr, &bluetooth_);
Vitaly Bukab1041e72015-09-21 15:26:51 -0700304
305 for (const auto& cb : http_server_changed_cb_)
306 cb.Run(http_server_);
307
308 task_runner_.Run();
Vitaly Buka11b2f232015-08-20 13:55:41 -0700309}
310
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700311class WeaveBasicTest : public WeaveTest {
312 public:
313 void SetUp() override {
314 WeaveTest::SetUp();
Vitaly Buka3884ce12015-09-21 13:48:48 -0700315
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700316 InitDefaultExpectations();
Vitaly Bukabeddc602015-09-24 15:28:03 -0700317 InitDnsSdPublishing(false, "DB");
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700318 }
319};
320
321TEST_F(WeaveBasicTest, Start) {
Vitaly Buka11b2f232015-08-20 13:55:41 -0700322 StartDevice();
323}
324
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700325TEST_F(WeaveBasicTest, Register) {
Vitaly Buka41a90d62015-09-29 16:58:39 -0700326 EXPECT_CALL(network_, OpenSslSocket(_, _, _, _)).WillRepeatedly(Return());
Vitaly Buka11b2f232015-08-20 13:55:41 -0700327 StartDevice();
328
329 auto draft = CreateDictionaryValue(kDeviceResource);
330 auto response = CreateDictionaryValue(kRegistrationResponse);
331 response->Set("deviceDraft", draft->DeepCopy());
332 ExpectRequest(
333 "PATCH",
334 "https://www.googleapis.com/clouddevices/v1/registrationTickets/"
Johan Euphrosine0b7bb9f2015-09-29 01:11:21 -0700335 "TICKET_ID?key=TEST_API_KEY",
Vitaly Buka11b2f232015-08-20 13:55:41 -0700336 ValueToString(*response));
337
338 response = CreateDictionaryValue(kRegistrationFinalResponse);
339 response->Set("deviceDraft", draft->DeepCopy());
340 ExpectRequest(
341 "POST",
342 "https://www.googleapis.com/clouddevices/v1/registrationTickets/"
Johan Euphrosine0b7bb9f2015-09-29 01:11:21 -0700343 "TICKET_ID/finalize?key=TEST_API_KEY",
Vitaly Buka11b2f232015-08-20 13:55:41 -0700344 ValueToString(*response));
345
346 ExpectRequest("POST", "https://accounts.google.com/o/oauth2/token",
347 kAuthTokenResponse);
348
Vitaly Bukabeddc602015-09-24 15:28:03 -0700349 InitDnsSdPublishing(true, "DB");
Vitaly Buka11b2f232015-08-20 13:55:41 -0700350
Johan Euphrosine0b7bb9f2015-09-29 01:11:21 -0700351 EXPECT_EQ("CLOUD_ID", cloud_->RegisterDevice("TICKET_ID", nullptr));
Vitaly Buka11b2f232015-08-20 13:55:41 -0700352}
353
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700354class WeaveWiFiSetupTest : public WeaveTest {
355 public:
356 void SetUp() override {
357 WeaveTest::SetUp();
358
359 InitConfigStore();
360 InitHttpServer();
361 InitNetwork();
Vitaly Bukabeddc602015-09-24 15:28:03 -0700362 InitDnsSd();
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700363
364 EXPECT_CALL(network_, GetConnectionState())
Vitaly Buka35f317d2015-09-27 22:54:39 -0700365 .WillRepeatedly(Return(provider::Network::State::kConnected));
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700366 }
367};
368
369TEST_F(WeaveWiFiSetupTest, StartOnlineNoPrevSsid) {
370 StartDevice();
371
372 // Short disconnect.
Vitaly Buka35f317d2015-09-27 22:54:39 -0700373 NotifyNetworkChanged(provider::Network::State::kOffline, {});
374 NotifyNetworkChanged(provider::Network::State::kConnected,
Vitaly Buka3884ce12015-09-21 13:48:48 -0700375 base::TimeDelta::FromSeconds(10));
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700376 task_runner_.Run();
377
378 // Long disconnect.
Vitaly Buka35f317d2015-09-27 22:54:39 -0700379 NotifyNetworkChanged(Network::State::kOffline, {});
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700380 auto offline_from = task_runner_.GetClock()->Now();
Vitaly Bukaa05eadb2015-09-29 16:38:24 -0700381 EXPECT_CALL(wifi_, StartAccessPoint(MatchesRegex("TEST_NAME.*prv")))
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700382 .WillOnce(InvokeWithoutArgs([this, offline_from]() {
383 EXPECT_GT(task_runner_.GetClock()->Now() - offline_from,
384 base::TimeDelta::FromMinutes(1));
Vitaly Bukacaf42bd2015-09-16 11:23:23 -0700385 task_runner_.Break();
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700386 }));
387 task_runner_.Run();
388}
389
390// If device has previously configured WiFi it will run AP for limited time
391// after which it will try to re-connect.
392TEST_F(WeaveWiFiSetupTest, StartOnlineWithPrevSsid) {
393 EXPECT_CALL(config_store_, LoadSettings())
394 .WillRepeatedly(Return(R"({"last_configured_ssid": "TEST_ssid"})"));
395 StartDevice();
396
397 // Long disconnect.
Vitaly Buka35f317d2015-09-27 22:54:39 -0700398 NotifyNetworkChanged(Network::State::kOffline, {});
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700399
400 for (int i = 0; i < 5; ++i) {
401 auto offline_from = task_runner_.GetClock()->Now();
402 // Temporarily offline mode.
Vitaly Bukaa05eadb2015-09-29 16:38:24 -0700403 EXPECT_CALL(wifi_, StartAccessPoint(MatchesRegex("TEST_NAME.*prv")))
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700404 .WillOnce(InvokeWithoutArgs([this, &offline_from]() {
405 EXPECT_GT(task_runner_.GetClock()->Now() - offline_from,
406 base::TimeDelta::FromMinutes(1));
407 task_runner_.Break();
408 }));
409 task_runner_.Run();
410
411 // Try to reconnect again.
412 offline_from = task_runner_.GetClock()->Now();
Vitaly Buka1fd619a2015-09-24 11:46:05 -0700413 EXPECT_CALL(wifi_, StopAccessPoint())
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700414 .WillOnce(InvokeWithoutArgs([this, offline_from]() {
415 EXPECT_GT(task_runner_.GetClock()->Now() - offline_from,
416 base::TimeDelta::FromMinutes(5));
417 task_runner_.Break();
418 }));
419 task_runner_.Run();
420 }
421
Vitaly Buka35f317d2015-09-27 22:54:39 -0700422 NotifyNetworkChanged(Network::State::kConnected, {});
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700423 task_runner_.Run();
424}
425
Vitaly Bukacaf42bd2015-09-16 11:23:23 -0700426TEST_F(WeaveWiFiSetupTest, StartOfflineWithSsid) {
427 EXPECT_CALL(config_store_, LoadSettings())
428 .WillRepeatedly(Return(R"({"last_configured_ssid": "TEST_ssid"})"));
429 EXPECT_CALL(network_, GetConnectionState())
Vitaly Buka35f317d2015-09-27 22:54:39 -0700430 .WillRepeatedly(Return(Network::State::kOffline));
Vitaly Bukacaf42bd2015-09-16 11:23:23 -0700431
432 auto offline_from = task_runner_.GetClock()->Now();
Vitaly Bukaa05eadb2015-09-29 16:38:24 -0700433 EXPECT_CALL(wifi_, StartAccessPoint(MatchesRegex("TEST_NAME.*prv")))
Vitaly Bukacaf42bd2015-09-16 11:23:23 -0700434 .WillOnce(InvokeWithoutArgs([this, &offline_from]() {
435 EXPECT_GT(task_runner_.GetClock()->Now() - offline_from,
436 base::TimeDelta::FromMinutes(1));
437 task_runner_.Break();
438 }));
439
440 StartDevice();
441}
442
Vitaly Buka11b2f232015-08-20 13:55:41 -0700443} // namespace weave