blob: dd10cbe621b0f3b9438f6b62c797a9e52859f391 [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
Vitaly Buka11b2f232015-08-20 13:55:41 -070048const char kCommandDefs[] = R"({
49 "base": {
Alex Vakulenko2c7740a2015-11-30 08:51:29 -080050 "reboot": {
51 "minimalRole": "user"
52 },
Vitaly Bukae5b20412015-09-30 15:41:28 -070053 "_shutdown": {
Alex Vakulenko2c7740a2015-11-30 08:51:29 -080054 "minimalRole": "user",
Vitaly Bukae5b20412015-09-30 15:41:28 -070055 "parameters": {},
56 "results": {}
Vitaly Buka11b2f232015-08-20 13:55:41 -070057 }
58 }
59})";
60
Vitaly Buka11b2f232015-08-20 13:55:41 -070061const char kDeviceResource[] = R"({
Vitaly Buka88272d52015-11-17 17:04:01 -080062 "kind": "weave#device",
Johan Euphrosine0b7bb9f2015-09-29 01:11:21 -070063 "id": "CLOUD_ID",
Vitaly Buka11b2f232015-08-20 13:55:41 -070064 "channel": {
65 "supportedType": "pull"
66 },
67 "deviceKind": "vendor",
68 "modelManifestId": "ABCDE",
69 "systemName": "",
Vitaly Bukaa05eadb2015-09-29 16:38:24 -070070 "name": "TEST_NAME",
Vitaly Buka11b2f232015-08-20 13:55:41 -070071 "displayName": "",
72 "description": "Developer device",
73 "stateValidationEnabled": true,
74 "commandDefs":{
75 "base": {
76 "reboot": {
77 "minimalRole": "user",
Alex Vakulenko7e894da2015-11-23 11:47:49 -080078 "parameters": {"delay": {"type": "integer"}},
Vitaly Buka11b2f232015-08-20 13:55:41 -070079 "results": {}
80 },
81 "shutdown": {
82 "minimalRole": "user",
83 "parameters": {},
84 "results": {}
85 }
86 }
87 },
88 "state":{
89 "base":{
90 "firmwareVersion":"FIRMWARE_VERSION",
91 "localAnonymousAccessMaxRole":"viewer",
92 "localDiscoveryEnabled":true,
93 "localPairingEnabled":true,
94 "network":{
95 }
96 },
97 "power": {"battery_level":44}
98 }
99})";
100
101const char kRegistrationResponse[] = R"({
Vitaly Buka88272d52015-11-17 17:04:01 -0800102 "kind": "weave#registrationTicket",
Johan Euphrosine0b7bb9f2015-09-29 01:11:21 -0700103 "id": "TICKET_ID",
104 "deviceId": "CLOUD_ID",
Vitaly Buka11b2f232015-08-20 13:55:41 -0700105 "oauthClientId": "CLIENT_ID",
106 "userEmail": "USER@gmail.com",
107 "creationTimeMs": "1440087183738",
108 "expirationTimeMs": "1440087423738"
109})";
110
111const char kRegistrationFinalResponse[] = R"({
Vitaly Buka88272d52015-11-17 17:04:01 -0800112 "kind": "weave#registrationTicket",
Johan Euphrosine0b7bb9f2015-09-29 01:11:21 -0700113 "id": "TICKET_ID",
114 "deviceId": "CLOUD_ID",
Vitaly Buka11b2f232015-08-20 13:55:41 -0700115 "oauthClientId": "CLIENT_ID",
116 "userEmail": "USER@gmail.com",
117 "robotAccountEmail": "ROBO@gmail.com",
118 "robotAccountAuthorizationCode": "AUTH_CODE",
119 "creationTimeMs": "1440087183738",
120 "expirationTimeMs": "1440087423738"
121})";
122
123const char kAuthTokenResponse[] = R"({
124 "access_token" : "ACCESS_TOKEN",
125 "token_type" : "Bearer",
126 "expires_in" : 3599,
127 "refresh_token" : "REFRESH_TOKEN"
128})";
129
130const char kStateDefs[] = R"({"power": {"battery_level":"integer"}})";
131
132const char kStateDefaults[] = R"({"power": {"battery_level":44}})";
133
Vitaly Buka3dc2f532015-09-08 18:01:32 -0700134MATCHER_P(MatchTxt, txt, "") {
135 std::vector<std::string> txt_copy = txt;
136 std::sort(txt_copy.begin(), txt_copy.end());
137 std::vector<std::string> arg_copy = arg;
138 std::sort(arg_copy.begin(), arg_copy.end());
139 return (arg_copy == txt_copy);
140}
141
Vitaly Bukae69e4ee2015-10-26 18:30:14 -0700142template <class Map>
143std::set<typename Map::key_type> GetKeys(const Map& map) {
144 std::set<typename Map::key_type> result;
145 for (const auto& pair : map)
146 result.insert(pair.first);
147 return result;
148}
149
150} // namespace
151
Vitaly Buka11b2f232015-08-20 13:55:41 -0700152class WeaveTest : public ::testing::Test {
153 protected:
Vitaly Bukac5bdd172015-10-01 19:48:51 -0700154 void SetUp() override {}
Vitaly Buka11b2f232015-08-20 13:55:41 -0700155
Vitaly Buka1a42e142015-10-10 18:15:15 -0700156 void ExpectRequest(HttpClient::Method method,
Vitaly Buka11b2f232015-08-20 13:55:41 -0700157 const std::string& url,
158 const std::string& json_response) {
Vitaly Buka74763422015-10-11 00:39:52 -0700159 EXPECT_CALL(http_client_, SendRequest(method, url, _, _, _))
Vitaly Buka17280372015-10-10 17:11:47 -0700160 .WillOnce(WithArgs<4>(Invoke([json_response](
Vitaly Buka74763422015-10-11 00:39:52 -0700161 const HttpClient::SendRequestCallback& callback) {
Vitaly Buka17280372015-10-10 17:11:47 -0700162 std::unique_ptr<provider::test::MockHttpClientResponse> response{
163 new StrictMock<provider::test::MockHttpClientResponse>};
Vitaly Buka11b2f232015-08-20 13:55:41 -0700164 EXPECT_CALL(*response, GetStatusCode())
165 .Times(AtLeast(1))
166 .WillRepeatedly(Return(200));
167 EXPECT_CALL(*response, GetContentType())
168 .Times(AtLeast(1))
169 .WillRepeatedly(Return("application/json; charset=utf-8"));
170 EXPECT_CALL(*response, GetData())
171 .Times(AtLeast(1))
Vitaly Buka4774df22015-10-09 12:36:22 -0700172 .WillRepeatedly(Return(json_response));
Vitaly Buka74763422015-10-11 00:39:52 -0700173 callback.Run(std::move(response), nullptr);
Vitaly Buka17280372015-10-10 17:11:47 -0700174 })));
Vitaly Buka11b2f232015-08-20 13:55:41 -0700175 }
176
177 void InitConfigStore() {
Vitaly Buka11b2f232015-08-20 13:55:41 -0700178 EXPECT_CALL(config_store_, SaveSettings("")).WillRepeatedly(Return());
Vitaly Buka11b2f232015-08-20 13:55:41 -0700179 }
180
181 void InitNetwork() {
Vitaly Buka3ab6f6e2015-09-24 13:16:16 -0700182 EXPECT_CALL(network_, AddConnectionChangedCallback(_))
183 .WillRepeatedly(Invoke(
Vitaly Buka1e363672015-09-25 14:01:16 -0700184 [this](const provider::Network::ConnectionChangedCallback& cb) {
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700185 network_callbacks_.push_back(cb);
186 }));
Vitaly Buka11b2f232015-08-20 13:55:41 -0700187 EXPECT_CALL(network_, GetConnectionState())
Vitaly Buka35f317d2015-09-27 22:54:39 -0700188 .WillRepeatedly(Return(Network::State::kOffline));
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700189 }
190
Vitaly Bukabeddc602015-09-24 15:28:03 -0700191 void InitDnsSd() {
Vitaly Bukabeddc602015-09-24 15:28:03 -0700192 EXPECT_CALL(dns_sd_, PublishService(_, _, _)).WillRepeatedly(Return());
193 EXPECT_CALL(dns_sd_, StopPublishing("_privet._tcp")).WillOnce(Return());
Vitaly Buka11b2f232015-08-20 13:55:41 -0700194 }
195
Vitaly Bukabeddc602015-09-24 15:28:03 -0700196 void InitDnsSdPublishing(bool registered, const std::string& flags) {
Vitaly Buka87eb7882015-10-27 22:23:49 -0700197 std::vector<std::string> txt{
198 {"id=TEST_DEVICE_ID"}, {"flags=" + flags}, {"mmid=ABCDE"},
199 {"services=developmentBoard"}, {"txtvers=3"}, {"ty=TEST_NAME"}};
Vitaly Buka11b2f232015-08-20 13:55:41 -0700200 if (registered) {
Johan Euphrosine0b7bb9f2015-09-29 01:11:21 -0700201 txt.push_back("gcd_id=CLOUD_ID");
Vitaly Buka11b2f232015-08-20 13:55:41 -0700202
203 // During registration device may announce itself twice:
204 // 1. with GCD ID but not connected (DB)
205 // 2. with GCD ID and connected (BB)
Vitaly Bukabeddc602015-09-24 15:28:03 -0700206 EXPECT_CALL(dns_sd_, PublishService("_privet._tcp", 11, MatchTxt(txt)))
Vitaly Buka11b2f232015-08-20 13:55:41 -0700207 .Times(AtMost(1))
208 .WillOnce(Return());
209
Vitaly Buka3dc2f532015-09-08 18:01:32 -0700210 txt[1] = "flags=BB";
Vitaly Buka11b2f232015-08-20 13:55:41 -0700211 }
212
Vitaly Bukabeddc602015-09-24 15:28:03 -0700213 EXPECT_CALL(dns_sd_, PublishService("_privet._tcp", 11, MatchTxt(txt)))
Vitaly Bukabced5af2015-10-12 17:42:30 -0700214 .Times(AtMost(1))
Vitaly Buka3dc2f532015-09-08 18:01:32 -0700215 .WillOnce(Return());
Vitaly Buka11b2f232015-08-20 13:55:41 -0700216 }
217
218 void InitHttpServer() {
219 EXPECT_CALL(http_server_, GetHttpPort()).WillRepeatedly(Return(11));
220 EXPECT_CALL(http_server_, GetHttpsPort()).WillRepeatedly(Return(12));
Alex Vakulenkoefee3a22015-11-17 15:08:38 -0800221 EXPECT_CALL(http_server_, GetRequestTimeout())
222 .WillRepeatedly(Return(base::TimeDelta::Max()));
Vitaly Buka11b2f232015-08-20 13:55:41 -0700223 EXPECT_CALL(http_server_, GetHttpsCertificateFingerprint())
Vitaly Buka138aec42015-10-08 10:17:48 -0700224 .WillRepeatedly(Return(std::vector<uint8_t>{1, 2, 3}));
Vitaly Buka1a39c812015-10-08 21:20:58 -0700225 EXPECT_CALL(http_server_, AddHttpRequestHandler(_, _))
226 .WillRepeatedly(Invoke(
227 [this](const std::string& path_prefix,
228 const provider::HttpServer::RequestHandlerCallback& cb) {
Vitaly Bukae69e4ee2015-10-26 18:30:14 -0700229 http_handlers_[path_prefix] = cb;
Vitaly Buka1a39c812015-10-08 21:20:58 -0700230 }));
231 EXPECT_CALL(http_server_, AddHttpsRequestHandler(_, _))
Vitaly Buka01893cc2015-10-08 19:58:00 -0700232 .WillRepeatedly(Invoke(
233 [this](const std::string& path_prefix,
234 const provider::HttpServer::RequestHandlerCallback& cb) {
Vitaly Bukae69e4ee2015-10-26 18:30:14 -0700235 https_handlers_[path_prefix] = cb;
Vitaly Buka1e363672015-09-25 14:01:16 -0700236 }));
Vitaly Buka11b2f232015-08-20 13:55:41 -0700237 }
238
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700239 void InitDefaultExpectations() {
Vitaly Buka11b2f232015-08-20 13:55:41 -0700240 InitConfigStore();
241 InitNetwork();
Vitaly Bukaa05eadb2015-09-29 16:38:24 -0700242 EXPECT_CALL(wifi_, StartAccessPoint(MatchesRegex("TEST_NAME.*prv")))
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700243 .WillOnce(Return());
Vitaly Buka11b2f232015-08-20 13:55:41 -0700244 InitHttpServer();
Vitaly Bukabeddc602015-09-24 15:28:03 -0700245 InitDnsSd();
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700246 }
Vitaly Buka11b2f232015-08-20 13:55:41 -0700247
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700248 void StartDevice() {
Vitaly Bukac5bdd172015-10-01 19:48:51 -0700249 device_ = weave::Device::Create(&config_store_, &task_runner_,
250 &http_client_, &network_, &dns_sd_,
251 &http_server_, &wifi_, &bluetooth_);
Vitaly Buka11b2f232015-08-20 13:55:41 -0700252
Vitaly Bukae69e4ee2015-10-26 18:30:14 -0700253 EXPECT_EQ((std::set<std::string>{
254 "/privet/info", "/privet/v3/pairing/cancel",
255 "/privet/v3/pairing/confirm", "/privet/v3/pairing/start"}),
256 GetKeys(http_handlers_));
257 EXPECT_EQ((std::set<std::string>{
Alex Vakulenkoefee3a22015-11-17 15:08:38 -0800258 "/privet/info", "/privet/v3/auth",
259 "/privet/v3/checkForUpdates", "/privet/v3/commandDefs",
Vitaly Bukae69e4ee2015-10-26 18:30:14 -0700260 "/privet/v3/commands/cancel", "/privet/v3/commands/execute",
261 "/privet/v3/commands/list", "/privet/v3/commands/status",
262 "/privet/v3/pairing/cancel", "/privet/v3/pairing/confirm",
263 "/privet/v3/pairing/start", "/privet/v3/setup/start",
264 "/privet/v3/setup/status", "/privet/v3/state"}),
265 GetKeys(https_handlers_));
266
Vitaly Buka3110deb2015-10-06 19:54:09 -0700267 device_->AddCommandDefinitionsFromJson(kCommandDefs);
268 device_->AddStateDefinitionsFromJson(kStateDefs);
Vitaly Buka216e86d2015-10-06 20:23:02 -0700269 device_->SetStatePropertiesFromJson(kStateDefaults, nullptr);
Vitaly Buka0ac6ca62015-10-06 19:16:29 -0700270
Vitaly Buka11b2f232015-08-20 13:55:41 -0700271 task_runner_.Run();
272 }
273
Vitaly Buka35f317d2015-09-27 22:54:39 -0700274 void NotifyNetworkChanged(provider::Network::State state,
Vitaly Buka1e363672015-09-25 14:01:16 -0700275 base::TimeDelta delay) {
Vitaly Buka65e1f212015-11-05 15:54:05 -0800276 auto task = [this, state] {
277 EXPECT_CALL(network_, GetConnectionState()).WillRepeatedly(Return(state));
278 for (const auto& cb : network_callbacks_)
279 cb.Run();
280 };
281
282 task_runner_.PostDelayedTask(FROM_HERE, base::Bind(task), delay);
Vitaly Buka3884ce12015-09-21 13:48:48 -0700283 }
284
Vitaly Bukae69e4ee2015-10-26 18:30:14 -0700285 std::map<std::string, provider::HttpServer::RequestHandlerCallback>
286 http_handlers_;
287 std::map<std::string, provider::HttpServer::RequestHandlerCallback>
288 https_handlers_;
Vitaly Buka11b2f232015-08-20 13:55:41 -0700289
Vitaly Buka1e363672015-09-25 14:01:16 -0700290 StrictMock<provider::test::MockConfigStore> config_store_;
Vitaly Buka727f3e62015-09-25 17:33:43 -0700291 StrictMock<provider::test::FakeTaskRunner> task_runner_;
Vitaly Buka1e363672015-09-25 14:01:16 -0700292 StrictMock<provider::test::MockHttpClient> http_client_;
293 StrictMock<provider::test::MockNetwork> network_;
294 StrictMock<provider::test::MockDnsServiceDiscovery> dns_sd_;
295 StrictMock<provider::test::MockHttpServer> http_server_;
296 StrictMock<provider::test::MockWifi> wifi_;
297 StrictMock<provider::test::MockBluetooth> bluetooth_;
Vitaly Buka11b2f232015-08-20 13:55:41 -0700298
Vitaly Buka1e363672015-09-25 14:01:16 -0700299 std::vector<provider::Network::ConnectionChangedCallback> network_callbacks_;
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700300
Vitaly Buka11b2f232015-08-20 13:55:41 -0700301 std::unique_ptr<weave::Device> device_;
302};
303
Vitaly Bukaef213d72015-10-07 15:54:58 -0700304TEST_F(WeaveTest, Mocks) {
Vitaly Bukaa8ece8f2015-10-05 13:30:23 -0700305 // Test checks if mock implements entire interface and mock can be
306 // instantiated.
307 test::MockDevice device;
Vitaly Bukaef213d72015-10-07 15:54:58 -0700308 test::MockCommand command;
Vitaly Bukaa8ece8f2015-10-05 13:30:23 -0700309}
310
Vitaly Buka11b2f232015-08-20 13:55:41 -0700311TEST_F(WeaveTest, StartMinimal) {
Vitaly Buka11b2f232015-08-20 13:55:41 -0700312 InitConfigStore();
Vitaly Bukac5bdd172015-10-01 19:48:51 -0700313 device_ = weave::Device::Create(&config_store_, &task_runner_, &http_client_,
314 &network_, nullptr, nullptr, &wifi_, nullptr);
Vitaly Bukab1041e72015-09-21 15:26:51 -0700315}
316
317TEST_F(WeaveTest, StartNoWifi) {
318 InitConfigStore();
319 InitNetwork();
320 InitHttpServer();
Vitaly Bukabeddc602015-09-24 15:28:03 -0700321 InitDnsSd();
322 InitDnsSdPublishing(false, "CB");
Vitaly Bukab1041e72015-09-21 15:26:51 -0700323
Vitaly Bukac5bdd172015-10-01 19:48:51 -0700324 device_ = weave::Device::Create(&config_store_, &task_runner_, &http_client_,
325 &network_, &dns_sd_, &http_server_, nullptr,
326 &bluetooth_);
Vitaly Buka3110deb2015-10-06 19:54:09 -0700327 device_->AddCommandDefinitionsFromJson(kCommandDefs);
Vitaly Bukab1041e72015-09-21 15:26:51 -0700328
Vitaly Bukab1041e72015-09-21 15:26:51 -0700329 task_runner_.Run();
Vitaly Buka11b2f232015-08-20 13:55:41 -0700330}
331
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700332class WeaveBasicTest : public WeaveTest {
333 public:
334 void SetUp() override {
335 WeaveTest::SetUp();
Vitaly Buka3884ce12015-09-21 13:48:48 -0700336
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700337 InitDefaultExpectations();
Vitaly Bukabeddc602015-09-24 15:28:03 -0700338 InitDnsSdPublishing(false, "DB");
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700339 }
340};
341
342TEST_F(WeaveBasicTest, Start) {
Vitaly Buka11b2f232015-08-20 13:55:41 -0700343 StartDevice();
344}
345
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700346TEST_F(WeaveBasicTest, Register) {
Vitaly Buka74763422015-10-11 00:39:52 -0700347 EXPECT_CALL(network_, OpenSslSocket(_, _, _)).WillRepeatedly(Return());
Vitaly Buka11b2f232015-08-20 13:55:41 -0700348 StartDevice();
349
350 auto draft = CreateDictionaryValue(kDeviceResource);
351 auto response = CreateDictionaryValue(kRegistrationResponse);
352 response->Set("deviceDraft", draft->DeepCopy());
Vitaly Buka0d7aac82015-11-16 23:02:24 -0800353 ExpectRequest(HttpClient::Method::kPatch,
354 "https://www.googleapis.com/weave/v1/registrationTickets/"
355 "TICKET_ID?key=TEST_API_KEY",
356 ValueToString(*response));
Vitaly Buka11b2f232015-08-20 13:55:41 -0700357
358 response = CreateDictionaryValue(kRegistrationFinalResponse);
359 response->Set("deviceDraft", draft->DeepCopy());
Vitaly Buka0d7aac82015-11-16 23:02:24 -0800360 ExpectRequest(HttpClient::Method::kPost,
361 "https://www.googleapis.com/weave/v1/registrationTickets/"
362 "TICKET_ID/finalize?key=TEST_API_KEY",
363 ValueToString(*response));
Vitaly Buka11b2f232015-08-20 13:55:41 -0700364
Vitaly Buka1a42e142015-10-10 18:15:15 -0700365 ExpectRequest(HttpClient::Method::kPost,
366 "https://accounts.google.com/o/oauth2/token",
Vitaly Buka11b2f232015-08-20 13:55:41 -0700367 kAuthTokenResponse);
368
Vitaly Bukabeddc602015-09-24 15:28:03 -0700369 InitDnsSdPublishing(true, "DB");
Vitaly Buka11b2f232015-08-20 13:55:41 -0700370
Vitaly Buka12870bd2015-10-08 23:49:39 -0700371 bool done = false;
Vitaly Buka74763422015-10-11 00:39:52 -0700372 device_->Register("TICKET_ID", base::Bind([this, &done](ErrorPtr error) {
373 EXPECT_FALSE(error);
Vitaly Buka12870bd2015-10-08 23:49:39 -0700374 done = true;
375 task_runner_.Break();
376 EXPECT_EQ("CLOUD_ID", device_->GetSettings().cloud_id);
Vitaly Buka74763422015-10-11 00:39:52 -0700377 }));
Vitaly Buka12870bd2015-10-08 23:49:39 -0700378 task_runner_.Run();
379 EXPECT_TRUE(done);
Vitaly Buka11b2f232015-08-20 13:55:41 -0700380}
381
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700382class WeaveWiFiSetupTest : public WeaveTest {
383 public:
384 void SetUp() override {
385 WeaveTest::SetUp();
386
387 InitConfigStore();
388 InitHttpServer();
389 InitNetwork();
Vitaly Bukabeddc602015-09-24 15:28:03 -0700390 InitDnsSd();
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700391
392 EXPECT_CALL(network_, GetConnectionState())
Vitaly Bukaefad5b22015-10-08 10:02:14 -0700393 .WillRepeatedly(Return(provider::Network::State::kOnline));
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700394 }
395};
396
397TEST_F(WeaveWiFiSetupTest, StartOnlineNoPrevSsid) {
398 StartDevice();
399
400 // Short disconnect.
Vitaly Buka35f317d2015-09-27 22:54:39 -0700401 NotifyNetworkChanged(provider::Network::State::kOffline, {});
Vitaly Bukaefad5b22015-10-08 10:02:14 -0700402 NotifyNetworkChanged(provider::Network::State::kOnline,
Vitaly Buka3884ce12015-09-21 13:48:48 -0700403 base::TimeDelta::FromSeconds(10));
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700404 task_runner_.Run();
405
406 // Long disconnect.
Vitaly Buka35f317d2015-09-27 22:54:39 -0700407 NotifyNetworkChanged(Network::State::kOffline, {});
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700408 auto offline_from = task_runner_.GetClock()->Now();
Vitaly Bukaa05eadb2015-09-29 16:38:24 -0700409 EXPECT_CALL(wifi_, StartAccessPoint(MatchesRegex("TEST_NAME.*prv")))
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700410 .WillOnce(InvokeWithoutArgs([this, offline_from]() {
411 EXPECT_GT(task_runner_.GetClock()->Now() - offline_from,
412 base::TimeDelta::FromMinutes(1));
Vitaly Bukacaf42bd2015-09-16 11:23:23 -0700413 task_runner_.Break();
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700414 }));
415 task_runner_.Run();
416}
417
418// If device has previously configured WiFi it will run AP for limited time
419// after which it will try to re-connect.
420TEST_F(WeaveWiFiSetupTest, StartOnlineWithPrevSsid) {
421 EXPECT_CALL(config_store_, LoadSettings())
422 .WillRepeatedly(Return(R"({"last_configured_ssid": "TEST_ssid"})"));
423 StartDevice();
424
425 // Long disconnect.
Vitaly Buka35f317d2015-09-27 22:54:39 -0700426 NotifyNetworkChanged(Network::State::kOffline, {});
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700427
428 for (int i = 0; i < 5; ++i) {
429 auto offline_from = task_runner_.GetClock()->Now();
430 // Temporarily offline mode.
Vitaly Bukaa05eadb2015-09-29 16:38:24 -0700431 EXPECT_CALL(wifi_, StartAccessPoint(MatchesRegex("TEST_NAME.*prv")))
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700432 .WillOnce(InvokeWithoutArgs([this, &offline_from]() {
433 EXPECT_GT(task_runner_.GetClock()->Now() - offline_from,
434 base::TimeDelta::FromMinutes(1));
435 task_runner_.Break();
436 }));
437 task_runner_.Run();
438
439 // Try to reconnect again.
440 offline_from = task_runner_.GetClock()->Now();
Vitaly Buka1fd619a2015-09-24 11:46:05 -0700441 EXPECT_CALL(wifi_, StopAccessPoint())
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700442 .WillOnce(InvokeWithoutArgs([this, offline_from]() {
443 EXPECT_GT(task_runner_.GetClock()->Now() - offline_from,
444 base::TimeDelta::FromMinutes(5));
445 task_runner_.Break();
446 }));
447 task_runner_.Run();
448 }
449
Vitaly Bukaefad5b22015-10-08 10:02:14 -0700450 NotifyNetworkChanged(Network::State::kOnline, {});
Vitaly Bukaca365fb2015-09-15 17:38:41 -0700451 task_runner_.Run();
452}
453
Vitaly Bukacaf42bd2015-09-16 11:23:23 -0700454TEST_F(WeaveWiFiSetupTest, StartOfflineWithSsid) {
455 EXPECT_CALL(config_store_, LoadSettings())
456 .WillRepeatedly(Return(R"({"last_configured_ssid": "TEST_ssid"})"));
457 EXPECT_CALL(network_, GetConnectionState())
Vitaly Buka35f317d2015-09-27 22:54:39 -0700458 .WillRepeatedly(Return(Network::State::kOffline));
Vitaly Bukacaf42bd2015-09-16 11:23:23 -0700459
460 auto offline_from = task_runner_.GetClock()->Now();
Vitaly Bukaa05eadb2015-09-29 16:38:24 -0700461 EXPECT_CALL(wifi_, StartAccessPoint(MatchesRegex("TEST_NAME.*prv")))
Vitaly Bukacaf42bd2015-09-16 11:23:23 -0700462 .WillOnce(InvokeWithoutArgs([this, &offline_from]() {
463 EXPECT_GT(task_runner_.GetClock()->Now() - offline_from,
464 base::TimeDelta::FromMinutes(1));
465 task_runner_.Break();
466 }));
467
468 StartDevice();
469}
470
Vitaly Buka65e1f212015-11-05 15:54:05 -0800471TEST_F(WeaveWiFiSetupTest, OfflineLongTimeWithNoSsid) {
472 EXPECT_CALL(network_, GetConnectionState())
473 .WillRepeatedly(Return(Network::State::kOffline));
474 NotifyNetworkChanged(provider::Network::State::kOnline,
475 base::TimeDelta::FromHours(15));
476
477 {
478 InSequence s;
479 auto time_stamp = task_runner_.GetClock()->Now();
480
481 EXPECT_CALL(wifi_, StartAccessPoint(MatchesRegex("TEST_NAME.*prv")))
482 .WillOnce(InvokeWithoutArgs([this, &time_stamp]() {
483 EXPECT_LE(task_runner_.GetClock()->Now() - time_stamp,
484 base::TimeDelta::FromMinutes(1));
485 time_stamp = task_runner_.GetClock()->Now();
486 }));
487
488 EXPECT_CALL(wifi_, StopAccessPoint())
489 .WillOnce(InvokeWithoutArgs([this, &time_stamp]() {
490 EXPECT_GT(task_runner_.GetClock()->Now() - time_stamp,
491 base::TimeDelta::FromMinutes(5));
492 time_stamp = task_runner_.GetClock()->Now();
493 task_runner_.Break();
494 }));
495 }
496
497 StartDevice();
498}
499
500TEST_F(WeaveWiFiSetupTest, OfflineLongTimeWithSsid) {
501 EXPECT_CALL(config_store_, LoadSettings())
502 .WillRepeatedly(Return(R"({"last_configured_ssid": "TEST_ssid"})"));
503 EXPECT_CALL(network_, GetConnectionState())
504 .WillRepeatedly(Return(Network::State::kOffline));
505 NotifyNetworkChanged(provider::Network::State::kOnline,
506 base::TimeDelta::FromHours(15));
507
508 {
509 InSequence s;
510 auto time_stamp = task_runner_.GetClock()->Now();
511 for (size_t i = 0; i < 10; ++i) {
512 EXPECT_CALL(wifi_, StartAccessPoint(MatchesRegex("TEST_NAME.*prv")))
513 .WillOnce(InvokeWithoutArgs([this, &time_stamp]() {
514 EXPECT_GT(task_runner_.GetClock()->Now() - time_stamp,
515 base::TimeDelta::FromMinutes(1));
516 time_stamp = task_runner_.GetClock()->Now();
517 }));
518
519 EXPECT_CALL(wifi_, StopAccessPoint())
520 .WillOnce(InvokeWithoutArgs([this, &time_stamp]() {
521 EXPECT_GT(task_runner_.GetClock()->Now() - time_stamp,
522 base::TimeDelta::FromMinutes(5));
523 time_stamp = task_runner_.GetClock()->Now();
524 }));
525 }
526
527 EXPECT_CALL(wifi_, StartAccessPoint(MatchesRegex("TEST_NAME.*prv")))
528 .WillOnce(InvokeWithoutArgs([this]() { task_runner_.Break(); }));
529 }
530
531 StartDevice();
532}
533
Vitaly Buka11b2f232015-08-20 13:55:41 -0700534} // namespace weave