blob: 20f5aa08cd098823d9c16fccc28fb9511c5960f9 [file] [log] [blame]
Vitaly Buka4615e0d2015-10-14 15:35:12 -07001// Copyright 2015 The Weave Authors. All rights reserved.
Vitaly Buka7ce499f2015-06-09 08:04:11 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Stefan Sauer2d16dfa2015-09-25 17:08:35 +02005#include "src/privet/privet_handler.h"
Vitaly Buka7ce499f2015-06-09 08:04:11 -07006
7#include <set>
8#include <string>
9#include <utility>
10
11#include <base/bind.h>
12#include <base/json/json_reader.h>
13#include <base/json/json_writer.h>
Vitaly Buka7ce499f2015-06-09 08:04:11 -070014#include <base/strings/string_util.h>
15#include <base/values.h>
Vitaly Buka7ce499f2015-06-09 08:04:11 -070016#include <gmock/gmock.h>
17#include <gtest/gtest.h>
Alex Vakulenko29a11ca2015-12-07 14:43:04 -080018#include <weave/test/unittest_utils.h>
Vitaly Buka7ce499f2015-06-09 08:04:11 -070019
Stefan Sauer2d16dfa2015-09-25 17:08:35 +020020#include "src/privet/constants.h"
21#include "src/privet/mock_delegates.h"
Alex Vakulenko532140d2015-12-11 17:18:21 -080022#include "src/test/mock_clock.h"
Vitaly Buka7ce499f2015-06-09 08:04:11 -070023
24using testing::_;
25using testing::DoAll;
26using testing::Invoke;
27using testing::Return;
28using testing::SetArgPointee;
Alex Vakulenkoefee3a22015-11-17 15:08:38 -080029using testing::SaveArg;
Vitaly Bukaf7f52d42015-10-10 22:43:55 -070030using testing::WithArgs;
Vitaly Buka7ce499f2015-06-09 08:04:11 -070031
Vitaly Bukab6f015a2015-07-09 14:59:23 -070032namespace weave {
33namespace privet {
Vitaly Buka7ce499f2015-06-09 08:04:11 -070034
35namespace {
36
37void LoadTestJson(const std::string& test_json,
38 base::DictionaryValue* dictionary) {
39 std::string json = test_json;
40 base::ReplaceChars(json, "'", "\"", &json);
41 int error = 0;
42 std::string message;
Alex Vakulenkoae1ffbc2015-06-15 12:53:22 -070043 std::unique_ptr<base::Value> value(
44 base::JSONReader::ReadAndReturnError(json, base::JSON_PARSE_RFC, &error,
45 &message)
46 .release());
Vitaly Buka7ce499f2015-06-09 08:04:11 -070047 EXPECT_TRUE(value.get()) << "\nError: " << message << "\n" << json;
48 base::DictionaryValue* dictionary_ptr = nullptr;
49 if (value->GetAsDictionary(&dictionary_ptr))
50 dictionary->MergeDictionary(dictionary_ptr);
51}
52
Vitaly Buka7ce499f2015-06-09 08:04:11 -070053struct CodeWithReason {
54 CodeWithReason(int code_in, const std::string& reason_in)
55 : code(code_in), reason(reason_in) {}
56 int code;
57 std::string reason;
58};
59
60std::ostream& operator<<(std::ostream& stream, const CodeWithReason& error) {
61 return stream << "{" << error.code << ", " << error.reason << "}";
62}
63
64bool IsEqualError(const CodeWithReason& expected,
65 const base::DictionaryValue& dictionary) {
66 std::string reason;
67 int code = 0;
68 return dictionary.GetInteger("error.http_status", &code) &&
69 code == expected.code && dictionary.GetString("error.code", &reason) &&
70 reason == expected.reason;
71}
72
Alex Vakulenko29a11ca2015-12-07 14:43:04 -080073// Some error sections in response JSON objects contained debugging information
Vitaly Buka34668e72015-12-15 14:46:47 -080074// which is of no interest for this test. So, remove the debug info from the
75// JSON before running validation logic on it.
Alex Vakulenko29a11ca2015-12-07 14:43:04 -080076std::unique_ptr<base::DictionaryValue> StripDebugErrorDetails(
77 const std::string& path_to_error_object,
78 const base::DictionaryValue& value) {
79 std::unique_ptr<base::DictionaryValue> result{value.DeepCopy()};
80 base::DictionaryValue* error_dict = nullptr;
81 EXPECT_TRUE(result->GetDictionary(path_to_error_object, &error_dict));
82 scoped_ptr<base::Value> dummy;
83 error_dict->RemovePath("error.debugInfo", &dummy);
84 error_dict->RemovePath("error.message", &dummy);
85 return result;
Vitaly Buka7ce499f2015-06-09 08:04:11 -070086}
87
88} // namespace
89
90class PrivetHandlerTest : public testing::Test {
91 public:
92 PrivetHandlerTest() {}
93
94 protected:
95 void SetUp() override {
Alex Vakulenko532140d2015-12-11 17:18:21 -080096 EXPECT_CALL(clock_, Now())
Vitaly Buka1884cf62015-12-12 15:47:42 -080097 .WillRepeatedly(Return(base::Time::FromTimeT(1410000001)));
Alex Vakulenko532140d2015-12-11 17:18:21 -080098
Vitaly Buka7ce499f2015-06-09 08:04:11 -070099 auth_header_ = "Privet anonymous";
Vitaly Buka34668e72015-12-15 14:46:47 -0800100 handler_.reset(
101 new PrivetHandler(&cloud_, &device_, &security_, &wifi_, &clock_));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700102 }
103
104 const base::DictionaryValue& HandleRequest(
105 const std::string& api,
106 const base::DictionaryValue* input) {
107 output_.Clear();
108 handler_->HandleRequest(api, auth_header_, input,
109 base::Bind(&PrivetHandlerTest::HandlerCallback,
110 base::Unretained(this)));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700111 return output_;
112 }
113
114 const base::DictionaryValue& HandleRequest(const std::string& api,
115 const std::string& json_input) {
116 base::DictionaryValue dictionary;
117 LoadTestJson(json_input, &dictionary);
118 return HandleRequest(api, &dictionary);
119 }
120
121 void HandleUnknownRequest(const std::string& api) {
122 output_.Clear();
123 base::DictionaryValue dictionary;
124 handler_->HandleRequest(api, auth_header_, &dictionary,
125 base::Bind(&PrivetHandlerTest::HandlerNoFound));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700126 }
127
Alex Vakulenkoefee3a22015-11-17 15:08:38 -0800128 const base::DictionaryValue& GetResponse() const { return output_; }
129 int GetResponseCount() const { return response_count_; }
130
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700131 void SetNoWifiAndGcd() {
Vitaly Buka34668e72015-12-15 14:46:47 -0800132 handler_.reset(
133 new PrivetHandler(&cloud_, &device_, &security_, nullptr, &clock_));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700134 EXPECT_CALL(cloud_, GetCloudId()).WillRepeatedly(Return(""));
135 EXPECT_CALL(cloud_, GetConnectionState())
136 .WillRepeatedly(ReturnRef(gcd_disabled_state_));
Vitaly Bukaa647c852015-07-06 14:51:01 -0700137 auto set_error = [](const std::string&, const std::string&,
Vitaly Buka0801a1f2015-08-14 10:03:46 -0700138 ErrorPtr* error) {
Vitaly Buka48a86692016-01-21 17:15:58 -0800139 Error::AddTo(error, FROM_HERE, "setupUnavailable", "");
Vitaly Buka075b3d42015-06-09 08:34:25 -0700140 };
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700141 EXPECT_CALL(cloud_, Setup(_, _, _))
142 .WillRepeatedly(DoAll(Invoke(set_error), Return(false)));
143 }
144
Alex Vakulenko532140d2015-12-11 17:18:21 -0800145 test::MockClock clock_;
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700146 testing::StrictMock<MockCloudDelegate> cloud_;
147 testing::StrictMock<MockDeviceDelegate> device_;
148 testing::StrictMock<MockSecurityDelegate> security_;
149 testing::StrictMock<MockWifiDelegate> wifi_;
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700150 std::string auth_header_;
151
152 private:
153 void HandlerCallback(int status, const base::DictionaryValue& output) {
Alex Vakulenkoefee3a22015-11-17 15:08:38 -0800154 output_.Clear();
155 ++response_count_;
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700156 output_.MergeDictionary(&output);
157 if (!output_.HasKey("error")) {
Vitaly Buka1da65992015-08-06 01:38:57 -0700158 EXPECT_EQ(200, status);
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700159 return;
160 }
Vitaly Buka1da65992015-08-06 01:38:57 -0700161 EXPECT_NE(200, status);
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700162 output_.SetInteger("error.http_status", status);
163 }
164
165 static void HandlerNoFound(int status, const base::DictionaryValue&) {
Vitaly Buka1da65992015-08-06 01:38:57 -0700166 EXPECT_EQ(404, status);
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700167 }
168
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700169 std::unique_ptr<PrivetHandler> handler_;
170 base::DictionaryValue output_;
Alex Vakulenkoefee3a22015-11-17 15:08:38 -0800171 int response_count_{0};
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700172 ConnectionState gcd_disabled_state_{ConnectionState::kDisabled};
173};
174
175TEST_F(PrivetHandlerTest, UnknownApi) {
176 HandleUnknownRequest("/privet/foo");
177}
178
179TEST_F(PrivetHandlerTest, InvalidFormat) {
180 auth_header_ = "";
181 EXPECT_PRED2(IsEqualError, CodeWithReason(400, "invalidFormat"),
182 HandleRequest("/privet/info", nullptr));
183}
184
185TEST_F(PrivetHandlerTest, MissingAuth) {
186 auth_header_ = "";
187 EXPECT_PRED2(IsEqualError, CodeWithReason(401, "missingAuthorization"),
188 HandleRequest("/privet/info", "{}"));
189}
190
191TEST_F(PrivetHandlerTest, InvalidAuth) {
192 auth_header_ = "foo";
193 EXPECT_PRED2(IsEqualError, CodeWithReason(401, "invalidAuthorization"),
194 HandleRequest("/privet/info", "{}"));
195}
196
197TEST_F(PrivetHandlerTest, ExpiredAuth) {
198 auth_header_ = "Privet 123";
Vitaly Bukaa0a81342015-12-17 13:42:13 -0800199 EXPECT_CALL(security_, ParseAccessToken(_, _, _))
Vitaly Buka0dbbf602016-01-22 11:38:37 -0800200 .WillRepeatedly(WithArgs<2>(Invoke([](ErrorPtr* error) {
201 return Error::AddTo(error, FROM_HERE, "authorizationExpired", "");
202 })));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700203 EXPECT_PRED2(IsEqualError, CodeWithReason(403, "authorizationExpired"),
204 HandleRequest("/privet/info", "{}"));
205}
206
207TEST_F(PrivetHandlerTest, InvalidAuthScope) {
208 EXPECT_PRED2(IsEqualError, CodeWithReason(403, "invalidAuthorizationScope"),
209 HandleRequest("/privet/v3/setup/start", "{}"));
210}
211
212TEST_F(PrivetHandlerTest, InfoMinimal) {
213 SetNoWifiAndGcd();
214 EXPECT_CALL(security_, GetPairingTypes())
215 .WillRepeatedly(Return(std::set<PairingType>{}));
216 EXPECT_CALL(security_, GetCryptoTypes())
217 .WillRepeatedly(Return(std::set<CryptoType>{}));
Vitaly Bukaee7322f2015-12-18 16:54:05 -0800218 EXPECT_CALL(security_, GetAuthTypes())
219 .WillRepeatedly(Return(std::set<AuthType>{}));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700220
221 const char kExpected[] = R"({
222 'version': '3.0',
223 'id': 'TestId',
224 'name': 'TestDevice',
Vitaly Buka87eb7882015-10-27 22:23:49 -0700225 'services': [ "developmentBoard" ],
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700226 'modelManifestId': "ABMID",
227 'basicModelManifest': {
228 'uiDeviceKind': 'developmentBoard',
229 'oemName': 'Chromium',
230 'modelName': 'Brillo'
231 },
232 'endpoints': {
233 'httpPort': 0,
234 'httpUpdatesPort': 0,
235 'httpsPort': 0,
236 'httpsUpdatesPort': 0
237 },
238 'authentication': {
239 'anonymousMaxScope': 'user',
240 'mode': [
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700241 ],
242 'pairing': [
243 ],
244 'crypto': [
245 ]
246 },
247 'gcd': {
248 'id': '',
249 'status': 'disabled'
250 },
Vitaly Buka483d5972015-12-16 13:45:35 -0800251 'time': 1410000001000.0,
252 'sessionId': 'SessionId'
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700253 })";
Alex Vakulenko29a11ca2015-12-07 14:43:04 -0800254 EXPECT_JSON_EQ(kExpected, HandleRequest("/privet/info", "{}"));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700255}
256
257TEST_F(PrivetHandlerTest, Info) {
258 EXPECT_CALL(cloud_, GetDescription())
259 .WillRepeatedly(Return("TestDescription"));
260 EXPECT_CALL(cloud_, GetLocation()).WillRepeatedly(Return("TestLocation"));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700261 EXPECT_CALL(device_, GetHttpEnpoint())
262 .WillRepeatedly(Return(std::make_pair(80, 10080)));
263 EXPECT_CALL(device_, GetHttpsEnpoint())
264 .WillRepeatedly(Return(std::make_pair(443, 10443)));
265 EXPECT_CALL(wifi_, GetHostedSsid())
266 .WillRepeatedly(Return("Test_device.BBABCLAprv"));
267
268 const char kExpected[] = R"({
269 'version': '3.0',
270 'id': 'TestId',
271 'name': 'TestDevice',
272 'description': 'TestDescription',
273 'location': 'TestLocation',
Vitaly Buka87eb7882015-10-27 22:23:49 -0700274 'services': [ "developmentBoard" ],
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700275 'modelManifestId': "ABMID",
276 'basicModelManifest': {
277 'uiDeviceKind': 'developmentBoard',
278 'oemName': 'Chromium',
279 'modelName': 'Brillo'
280 },
281 'endpoints': {
282 'httpPort': 80,
283 'httpUpdatesPort': 10080,
284 'httpsPort': 443,
285 'httpsUpdatesPort': 10443
286 },
287 'authentication': {
288 'anonymousMaxScope': 'none',
289 'mode': [
290 'anonymous',
Vitaly Bukaee7322f2015-12-18 16:54:05 -0800291 'pairing',
292 'local'
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700293 ],
294 'pairing': [
295 'pinCode',
Vitaly Bukac8ba2282015-10-01 17:42:40 -0700296 'embeddedCode'
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700297 ],
298 'crypto': [
Vitaly Bukac8ba2282015-10-01 17:42:40 -0700299 'p224_spake2'
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700300 ]
301 },
302 'wifi': {
303 'capabilities': [
304 '2.4GHz'
305 ],
306 'ssid': 'TestSsid',
307 'hostedSsid': 'Test_device.BBABCLAprv',
308 'status': 'offline'
309 },
310 'gcd': {
311 'id': 'TestCloudId',
312 'status': 'online'
313 },
Vitaly Buka483d5972015-12-16 13:45:35 -0800314 'time': 1410000001000.0,
315 'sessionId': 'SessionId'
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700316 })";
Alex Vakulenko29a11ca2015-12-07 14:43:04 -0800317 EXPECT_JSON_EQ(kExpected, HandleRequest("/privet/info", "{}"));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700318}
319
320TEST_F(PrivetHandlerTest, PairingStartInvalidParams) {
321 EXPECT_PRED2(IsEqualError, CodeWithReason(400, "invalidParams"),
322 HandleRequest("/privet/v3/pairing/start",
323 "{'pairing':'embeddedCode','crypto':'crypto'}"));
324
325 EXPECT_PRED2(IsEqualError, CodeWithReason(400, "invalidParams"),
326 HandleRequest("/privet/v3/pairing/start",
Vitaly Bukac8ba2282015-10-01 17:42:40 -0700327 "{'pairing':'code','crypto':'p224_spake2'}"));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700328}
329
330TEST_F(PrivetHandlerTest, PairingStart) {
Alex Vakulenko29a11ca2015-12-07 14:43:04 -0800331 EXPECT_JSON_EQ(
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700332 "{'deviceCommitment': 'testCommitment', 'sessionId': 'testSession'}",
333 HandleRequest("/privet/v3/pairing/start",
Vitaly Bukac8ba2282015-10-01 17:42:40 -0700334 "{'pairing': 'embeddedCode', 'crypto': 'p224_spake2'}"));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700335}
336
337TEST_F(PrivetHandlerTest, PairingConfirm) {
Alex Vakulenko29a11ca2015-12-07 14:43:04 -0800338 EXPECT_JSON_EQ(
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700339 "{'certFingerprint':'testFingerprint','certSignature':'testSignature'}",
340 HandleRequest(
341 "/privet/v3/pairing/confirm",
342 "{'sessionId':'testSession','clientCommitment':'testCommitment'}"));
343}
344
345TEST_F(PrivetHandlerTest, PairingCancel) {
Vitaly Buka34668e72015-12-15 14:46:47 -0800346 EXPECT_JSON_EQ("{}", HandleRequest("/privet/v3/pairing/cancel",
347 "{'sessionId': 'testSession'}"));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700348}
349
350TEST_F(PrivetHandlerTest, AuthErrorNoType) {
351 EXPECT_PRED2(IsEqualError, CodeWithReason(400, "invalidAuthMode"),
352 HandleRequest("/privet/v3/auth", "{}"));
353}
354
355TEST_F(PrivetHandlerTest, AuthErrorInvalidType) {
356 EXPECT_PRED2(IsEqualError, CodeWithReason(400, "invalidAuthMode"),
357 HandleRequest("/privet/v3/auth", "{'mode':'unknown'}"));
358}
359
360TEST_F(PrivetHandlerTest, AuthErrorNoScope) {
361 EXPECT_PRED2(IsEqualError, CodeWithReason(400, "invalidRequestedScope"),
362 HandleRequest("/privet/v3/auth", "{'mode':'anonymous'}"));
363}
364
365TEST_F(PrivetHandlerTest, AuthErrorInvalidScope) {
366 EXPECT_PRED2(
367 IsEqualError, CodeWithReason(400, "invalidRequestedScope"),
368 HandleRequest("/privet/v3/auth",
369 "{'mode':'anonymous','requestedScope':'unknown'}"));
370}
371
372TEST_F(PrivetHandlerTest, AuthErrorAccessDenied) {
373 EXPECT_PRED2(IsEqualError, CodeWithReason(403, "accessDenied"),
374 HandleRequest("/privet/v3/auth",
375 "{'mode':'anonymous','requestedScope':'owner'}"));
376}
377
378TEST_F(PrivetHandlerTest, AuthErrorInvalidAuthCode) {
Vitaly Bukafd2ef682015-12-17 20:57:01 -0800379 auto set_error = [](ErrorPtr* error) {
Vitaly Buka0dbbf602016-01-22 11:38:37 -0800380 return Error::AddTo(error, FROM_HERE, "invalidAuthCode", "");
Vitaly Bukafd2ef682015-12-17 20:57:01 -0800381 };
382 EXPECT_CALL(security_, CreateAccessToken(_, "testToken", _, _, _, _, _))
Vitaly Buka0dbbf602016-01-22 11:38:37 -0800383 .WillRepeatedly(WithArgs<6>(Invoke(set_error)));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700384 const char kInput[] = R"({
385 'mode': 'pairing',
386 'requestedScope': 'user',
387 'authCode': 'testToken'
388 })";
389 EXPECT_PRED2(IsEqualError, CodeWithReason(403, "invalidAuthCode"),
390 HandleRequest("/privet/v3/auth", kInput));
391}
392
393TEST_F(PrivetHandlerTest, AuthAnonymous) {
394 const char kExpected[] = R"({
395 'accessToken': 'GuestAccessToken',
Vitaly Bukafd2ef682015-12-17 20:57:01 -0800396 'expiresIn': 15,
397 'scope': 'viewer',
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700398 'tokenType': 'Privet'
399 })";
Alex Vakulenko29a11ca2015-12-07 14:43:04 -0800400 EXPECT_JSON_EQ(kExpected,
401 HandleRequest("/privet/v3/auth",
402 "{'mode':'anonymous','requestedScope':'auto'}"));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700403}
404
405TEST_F(PrivetHandlerTest, AuthPairing) {
Vitaly Bukafd2ef682015-12-17 20:57:01 -0800406 EXPECT_CALL(security_, CreateAccessToken(_, _, _, _, _, _, _))
407 .WillRepeatedly(DoAll(SetArgPointee<3>("OwnerAccessToken"),
408 SetArgPointee<4>(AuthScope::kOwner),
409 SetArgPointee<5>(base::TimeDelta::FromSeconds(15)),
410 Return(true)));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700411 const char kInput[] = R"({
412 'mode': 'pairing',
413 'requestedScope': 'owner',
414 'authCode': 'testToken'
415 })";
416 const char kExpected[] = R"({
417 'accessToken': 'OwnerAccessToken',
Vitaly Bukafd2ef682015-12-17 20:57:01 -0800418 'expiresIn': 15,
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700419 'scope': 'owner',
420 'tokenType': 'Privet'
421 })";
Alex Vakulenko29a11ca2015-12-07 14:43:04 -0800422 EXPECT_JSON_EQ(kExpected, HandleRequest("/privet/v3/auth", kInput));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700423}
424
Vitaly Buka4957afb2015-12-17 22:50:24 -0800425TEST_F(PrivetHandlerTest, AuthLocalAuto) {
Vitaly Buka4957afb2015-12-17 22:50:24 -0800426 EXPECT_CALL(security_, CreateAccessToken(_, _, _, _, _, _, _))
427 .WillRepeatedly(DoAll(SetArgPointee<3>("UserAccessToken"),
428 SetArgPointee<4>(AuthScope::kUser),
429 SetArgPointee<5>(base::TimeDelta::FromSeconds(15)),
430 Return(true)));
431 const char kInput[] = R"({
432 'mode': 'local',
433 'requestedScope': 'auto',
434 'authCode': 'localAuthToken'
435 })";
436 const char kExpected[] = R"({
437 'accessToken': 'UserAccessToken',
438 'expiresIn': 15,
439 'scope': 'user',
440 'tokenType': 'Privet'
441 })";
442 EXPECT_JSON_EQ(kExpected, HandleRequest("/privet/v3/auth", kInput));
443}
444
445TEST_F(PrivetHandlerTest, AuthLocal) {
Vitaly Buka4957afb2015-12-17 22:50:24 -0800446 EXPECT_CALL(security_, CreateAccessToken(_, _, _, _, _, _, _))
447 .WillRepeatedly(DoAll(SetArgPointee<3>("ManagerAccessToken"),
448 SetArgPointee<4>(AuthScope::kManager),
449 SetArgPointee<5>(base::TimeDelta::FromSeconds(15)),
450 Return(true)));
451 const char kInput[] = R"({
452 'mode': 'local',
453 'requestedScope': 'manager',
454 'authCode': 'localAuthToken'
455 })";
456 const char kExpected[] = R"({
457 'accessToken': 'ManagerAccessToken',
458 'expiresIn': 15,
459 'scope': 'manager',
460 'tokenType': 'Privet'
461 })";
462 EXPECT_JSON_EQ(kExpected, HandleRequest("/privet/v3/auth", kInput));
463}
464
465TEST_F(PrivetHandlerTest, AuthLocalHighScope) {
Vitaly Buka4957afb2015-12-17 22:50:24 -0800466 EXPECT_CALL(security_, CreateAccessToken(_, _, _, _, _, _, _))
467 .WillRepeatedly(DoAll(SetArgPointee<3>("UserAccessToken"),
468 SetArgPointee<4>(AuthScope::kUser),
469 SetArgPointee<5>(base::TimeDelta::FromSeconds(1)),
470 Return(true)));
471 const char kInput[] = R"({
472 'mode': 'local',
473 'requestedScope': 'manager',
474 'authCode': 'localAuthToken'
475 })";
476 EXPECT_PRED2(IsEqualError, CodeWithReason(403, "accessDenied"),
477 HandleRequest("/privet/v3/auth", kInput));
478}
479
Alex Vakulenkoe3cc2302015-12-07 15:26:26 -0800480class PrivetHandlerTestWithAuth : public PrivetHandlerTest {
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700481 public:
482 void SetUp() override {
483 PrivetHandlerTest::SetUp();
484 auth_header_ = "Privet 123";
Vitaly Bukaa0a81342015-12-17 13:42:13 -0800485 EXPECT_CALL(security_, ParseAccessToken(_, _, _))
Vitaly Buka66f46b82015-12-18 15:36:01 -0800486 .WillRepeatedly(DoAll(
Vitaly Buka4fe71e32016-01-29 11:50:53 -0800487 SetArgPointee<1>(UserInfo{AuthScope::kOwner, TestUserId{"1"}}),
488 Return(true)));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700489 }
490};
491
Alex Vakulenkoe3cc2302015-12-07 15:26:26 -0800492class PrivetHandlerSetupTest : public PrivetHandlerTestWithAuth {};
493
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700494TEST_F(PrivetHandlerSetupTest, StatusEmpty) {
495 SetNoWifiAndGcd();
Alex Vakulenko29a11ca2015-12-07 14:43:04 -0800496 EXPECT_JSON_EQ("{}", HandleRequest("/privet/v3/setup/status", "{}"));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700497}
498
499TEST_F(PrivetHandlerSetupTest, StatusWifi) {
500 wifi_.setup_state_ = SetupState{SetupState::kSuccess};
501
502 const char kExpected[] = R"({
503 'wifi': {
504 'ssid': 'TestSsid',
505 'status': 'success'
506 }
507 })";
Alex Vakulenko29a11ca2015-12-07 14:43:04 -0800508 EXPECT_JSON_EQ(kExpected, HandleRequest("/privet/v3/setup/status", "{}"));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700509}
510
511TEST_F(PrivetHandlerSetupTest, StatusWifiError) {
Vitaly Buka0801a1f2015-08-14 10:03:46 -0700512 ErrorPtr error;
Vitaly Buka48a86692016-01-21 17:15:58 -0800513 Error::AddTo(&error, FROM_HERE, "invalidPassphrase", "");
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700514 wifi_.setup_state_ = SetupState{std::move(error)};
515
516 const char kExpected[] = R"({
517 'wifi': {
518 'status': 'error',
519 'error': {
520 'code': 'invalidPassphrase'
521 }
522 }
523 })";
Alex Vakulenko29a11ca2015-12-07 14:43:04 -0800524 EXPECT_JSON_EQ(kExpected,
Vitaly Buka34668e72015-12-15 14:46:47 -0800525 *StripDebugErrorDetails(
526 "wifi", HandleRequest("/privet/v3/setup/status", "{}")));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700527}
528
529TEST_F(PrivetHandlerSetupTest, StatusGcd) {
530 cloud_.setup_state_ = SetupState{SetupState::kSuccess};
531
532 const char kExpected[] = R"({
533 'gcd': {
534 'id': 'TestCloudId',
535 'status': 'success'
536 }
537 })";
Alex Vakulenko29a11ca2015-12-07 14:43:04 -0800538 EXPECT_JSON_EQ(kExpected, HandleRequest("/privet/v3/setup/status", "{}"));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700539}
540
541TEST_F(PrivetHandlerSetupTest, StatusGcdError) {
Vitaly Buka0801a1f2015-08-14 10:03:46 -0700542 ErrorPtr error;
Vitaly Buka48a86692016-01-21 17:15:58 -0800543 Error::AddTo(&error, FROM_HERE, "invalidTicket", "");
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700544 cloud_.setup_state_ = SetupState{std::move(error)};
545
546 const char kExpected[] = R"({
547 'gcd': {
548 'status': 'error',
549 'error': {
550 'code': 'invalidTicket'
551 }
552 }
553 })";
Alex Vakulenko29a11ca2015-12-07 14:43:04 -0800554 EXPECT_JSON_EQ(kExpected,
Vitaly Buka34668e72015-12-15 14:46:47 -0800555 *StripDebugErrorDetails(
556 "gcd", HandleRequest("/privet/v3/setup/status", "{}")));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700557}
558
559TEST_F(PrivetHandlerSetupTest, SetupNameDescriptionLocation) {
Vitaly Bukab624bc42015-09-29 19:13:55 -0700560 EXPECT_CALL(cloud_,
561 UpdateDeviceInfo("testName", "testDescription", "testLocation"))
Vitaly Bukaa647c852015-07-06 14:51:01 -0700562 .Times(1);
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700563 const char kInput[] = R"({
564 'name': 'testName',
565 'description': 'testDescription',
566 'location': 'testLocation'
567 })";
Alex Vakulenko29a11ca2015-12-07 14:43:04 -0800568 EXPECT_JSON_EQ("{}", HandleRequest("/privet/v3/setup/start", kInput));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700569}
570
571TEST_F(PrivetHandlerSetupTest, InvalidParams) {
572 const char kInputWifi[] = R"({
573 'wifi': {
574 'ssid': ''
575 }
576 })";
577 EXPECT_PRED2(IsEqualError, CodeWithReason(400, "invalidParams"),
578 HandleRequest("/privet/v3/setup/start", kInputWifi));
579
580 const char kInputRegistration[] = R"({
581 'gcd': {
582 'ticketId': ''
583 }
584 })";
585 EXPECT_PRED2(IsEqualError, CodeWithReason(400, "invalidParams"),
586 HandleRequest("/privet/v3/setup/start", kInputRegistration));
587}
588
589TEST_F(PrivetHandlerSetupTest, WifiSetupUnavailable) {
590 SetNoWifiAndGcd();
591 EXPECT_PRED2(IsEqualError, CodeWithReason(400, "setupUnavailable"),
592 HandleRequest("/privet/v3/setup/start", "{'wifi': {}}"));
593}
594
595TEST_F(PrivetHandlerSetupTest, WifiSetup) {
596 const char kInput[] = R"({
597 'wifi': {
598 'ssid': 'testSsid',
599 'passphrase': 'testPass'
600 }
601 })";
Vitaly Buka0801a1f2015-08-14 10:03:46 -0700602 auto set_error = [](const std::string&, const std::string&, ErrorPtr* error) {
Vitaly Buka0dbbf602016-01-22 11:38:37 -0800603 return Error::AddTo(error, FROM_HERE, "deviceBusy", "");
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700604 };
Vitaly Buka0dbbf602016-01-22 11:38:37 -0800605 EXPECT_CALL(wifi_, ConfigureCredentials(_, _, _)).WillOnce(Invoke(set_error));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700606 EXPECT_PRED2(IsEqualError, CodeWithReason(503, "deviceBusy"),
607 HandleRequest("/privet/v3/setup/start", kInput));
608
609 const char kExpected[] = R"({
610 'wifi': {
611 'status': 'inProgress'
612 }
613 })";
614 wifi_.setup_state_ = SetupState{SetupState::kInProgress};
615 EXPECT_CALL(wifi_, ConfigureCredentials("testSsid", "testPass", _))
616 .WillOnce(Return(true));
Alex Vakulenko29a11ca2015-12-07 14:43:04 -0800617 EXPECT_JSON_EQ(kExpected, HandleRequest("/privet/v3/setup/start", kInput));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700618}
619
620TEST_F(PrivetHandlerSetupTest, GcdSetupUnavailable) {
621 SetNoWifiAndGcd();
622 const char kInput[] = R"({
623 'gcd': {
624 'ticketId': 'testTicket',
625 'user': 'testUser'
626 }
627 })";
628
629 EXPECT_PRED2(IsEqualError, CodeWithReason(400, "setupUnavailable"),
630 HandleRequest("/privet/v3/setup/start", kInput));
631}
632
633TEST_F(PrivetHandlerSetupTest, GcdSetup) {
634 const char kInput[] = R"({
635 'gcd': {
636 'ticketId': 'testTicket',
637 'user': 'testUser'
638 }
639 })";
640
Vitaly Buka0801a1f2015-08-14 10:03:46 -0700641 auto set_error = [](const std::string&, const std::string&, ErrorPtr* error) {
Vitaly Buka0dbbf602016-01-22 11:38:37 -0800642 return Error::AddTo(error, FROM_HERE, "deviceBusy", "");
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700643 };
Vitaly Buka0dbbf602016-01-22 11:38:37 -0800644 EXPECT_CALL(cloud_, Setup(_, _, _)).WillOnce(Invoke(set_error));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700645 EXPECT_PRED2(IsEqualError, CodeWithReason(503, "deviceBusy"),
646 HandleRequest("/privet/v3/setup/start", kInput));
647
648 const char kExpected[] = R"({
649 'gcd': {
650 'status': 'inProgress'
651 }
652 })";
653 cloud_.setup_state_ = SetupState{SetupState::kInProgress};
654 EXPECT_CALL(cloud_, Setup("testTicket", "testUser", _))
655 .WillOnce(Return(true));
Alex Vakulenko29a11ca2015-12-07 14:43:04 -0800656 EXPECT_JSON_EQ(kExpected, HandleRequest("/privet/v3/setup/start", kInput));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700657}
658
Vitaly Buka287346b2015-12-15 14:35:28 -0800659TEST_F(PrivetHandlerSetupTest, GcdSetupAsMaster) {
Vitaly Bukaa0a81342015-12-17 13:42:13 -0800660 EXPECT_CALL(security_, ParseAccessToken(_, _, _))
Vitaly Buka66f46b82015-12-18 15:36:01 -0800661 .WillRepeatedly(DoAll(
Vitaly Buka4fe71e32016-01-29 11:50:53 -0800662 SetArgPointee<1>(UserInfo{AuthScope::kManager, TestUserId{"1"}}),
663 Return(true)));
Vitaly Buka287346b2015-12-15 14:35:28 -0800664 const char kInput[] = R"({
665 'gcd': {
666 'ticketId': 'testTicket',
667 'user': 'testUser'
668 }
669 })";
670
671 EXPECT_PRED2(IsEqualError, CodeWithReason(403, "invalidAuthorizationScope"),
672 HandleRequest("/privet/v3/setup/start", kInput));
673}
674
Vitaly Buka2d24e0e2015-12-10 14:56:37 -0800675TEST_F(PrivetHandlerTestWithAuth, ClaimAccessControl) {
676 EXPECT_JSON_EQ("{'clientToken': 'RootClientAuthToken'}",
677 HandleRequest("/privet/v3/accessControl/claim", "{}"));
678}
679
680TEST_F(PrivetHandlerTestWithAuth, ConfirmAccessControl) {
681 EXPECT_JSON_EQ("{}",
682 HandleRequest("/privet/v3/accessControl/confirm",
683 "{'clientToken': 'DerivedClientAuthToken'}"));
684}
685
686TEST_F(PrivetHandlerTestWithAuth, State) {
Alex Vakulenkof9691322015-12-07 14:34:48 -0800687 EXPECT_JSON_EQ("{'state': {'test': {}}, 'fingerprint': '1'}",
Alex Vakulenko29a11ca2015-12-07 14:43:04 -0800688 HandleRequest("/privet/v3/state", "{}"));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700689
Alex Vakulenko551a82b2015-12-07 14:46:12 -0800690 cloud_.NotifyOnStateChanged();
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700691
Alex Vakulenkof9691322015-12-07 14:34:48 -0800692 EXPECT_JSON_EQ("{'state': {'test': {}}, 'fingerprint': '2'}",
Alex Vakulenko29a11ca2015-12-07 14:43:04 -0800693 HandleRequest("/privet/v3/state", "{}"));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700694}
695
Vitaly Buka2d24e0e2015-12-10 14:56:37 -0800696TEST_F(PrivetHandlerTestWithAuth, CommandsDefs) {
Alex Vakulenkof9691322015-12-07 14:34:48 -0800697 EXPECT_JSON_EQ("{'commands': {'test':{}}, 'fingerprint': '1'}",
Alex Vakulenko29a11ca2015-12-07 14:43:04 -0800698 HandleRequest("/privet/v3/commandDefs", "{}"));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700699
Alex Vakulenkod91d6252015-12-05 17:14:39 -0800700 cloud_.NotifyOnTraitDefsChanged();
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700701
Alex Vakulenkof9691322015-12-07 14:34:48 -0800702 EXPECT_JSON_EQ("{'commands': {'test':{}}, 'fingerprint': '2'}",
Alex Vakulenko29a11ca2015-12-07 14:43:04 -0800703 HandleRequest("/privet/v3/commandDefs", "{}"));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700704}
705
Vitaly Buka2d24e0e2015-12-10 14:56:37 -0800706TEST_F(PrivetHandlerTestWithAuth, Traits) {
Alex Vakulenkof9691322015-12-07 14:34:48 -0800707 EXPECT_JSON_EQ("{'traits': {'test': {}}, 'fingerprint': '1'}",
Alex Vakulenko551a82b2015-12-07 14:46:12 -0800708 HandleRequest("/privet/v3/traits", "{}"));
709
710 cloud_.NotifyOnTraitDefsChanged();
711
Alex Vakulenkof9691322015-12-07 14:34:48 -0800712 EXPECT_JSON_EQ("{'traits': {'test': {}}, 'fingerprint': '2'}",
Alex Vakulenko551a82b2015-12-07 14:46:12 -0800713 HandleRequest("/privet/v3/traits", "{}"));
714}
715
Vitaly Buka2d24e0e2015-12-10 14:56:37 -0800716TEST_F(PrivetHandlerTestWithAuth, Components) {
Alex Vakulenkof9691322015-12-07 14:34:48 -0800717 EXPECT_JSON_EQ("{'components': {'test': {}}, 'fingerprint': '1'}",
Alex Vakulenko551a82b2015-12-07 14:46:12 -0800718 HandleRequest("/privet/v3/components", "{}"));
719
720 cloud_.NotifyOnComponentTreeChanged();
721
Alex Vakulenkof9691322015-12-07 14:34:48 -0800722 EXPECT_JSON_EQ("{'components': {'test': {}}, 'fingerprint': '2'}",
Alex Vakulenko551a82b2015-12-07 14:46:12 -0800723 HandleRequest("/privet/v3/components", "{}"));
724
725 // State change will also change the components fingerprint.
726 cloud_.NotifyOnStateChanged();
727
Alex Vakulenkof9691322015-12-07 14:34:48 -0800728 EXPECT_JSON_EQ("{'components': {'test': {}}, 'fingerprint': '3'}",
Alex Vakulenko551a82b2015-12-07 14:46:12 -0800729 HandleRequest("/privet/v3/components", "{}"));
730}
731
Vitaly Buka2d24e0e2015-12-10 14:56:37 -0800732TEST_F(PrivetHandlerTestWithAuth, ComponentsWithFiltersAndPaths) {
Alex Vakulenko3eb52e72015-12-14 15:34:08 -0800733 const char kComponents[] = R"({
734 "comp1": {
735 "traits": ["a", "b"],
736 "state": {
737 "a" : {
738 "prop": 1
739 }
740 },
741 "components": {
742 "comp2": {
743 "traits": ["c"],
744 "components": {
745 "comp4": {
746 "traits": ["d"]
747 }
748 }
749 },
750 "comp3": {
751 "traits": ["e"]
752 }
753 }
754 }
755 })";
756 base::DictionaryValue components;
757 LoadTestJson(kComponents, &components);
758 EXPECT_CALL(cloud_, FindComponent(_, _)).WillRepeatedly(Return(nullptr));
759 EXPECT_CALL(cloud_, GetComponents()).WillRepeatedly(ReturnRef(components));
760 const char kExpected1[] = R"({
761 "components": {
762 "comp1": {
763 "state": {
764 "a" : {
765 "prop": 1
766 }
767 }
768 }
769 },
770 "fingerprint": "1"
771 })";
772 EXPECT_JSON_EQ(kExpected1, HandleRequest("/privet/v3/components",
773 "{'filter':['state']}"));
774
775 const char kExpected2[] = R"({
776 "components": {
777 "comp1": {
778 "traits": ["a", "b"]
779 }
780 },
781 "fingerprint": "1"
782 })";
783 EXPECT_JSON_EQ(kExpected2, HandleRequest("/privet/v3/components",
784 "{'filter':['traits']}"));
785
786 const char kExpected3[] = R"({
787 "components": {
788 "comp1": {
789 "components": {
790 "comp2": {
791 "components": {
792 "comp4": {}
793 }
794 },
795 "comp3": {}
796 }
797 }
798 },
799 "fingerprint": "1"
800 })";
801 EXPECT_JSON_EQ(kExpected3, HandleRequest("/privet/v3/components",
802 "{'filter':['components']}"));
803
804 const char kExpected4[] = R"({
805 "components": {
806 "comp1": {
807 "traits": ["a", "b"],
808 "state": {
809 "a" : {
810 "prop": 1
811 }
812 },
813 "components": {
814 "comp2": {
815 "traits": ["c"],
816 "components": {
817 "comp4": {
818 "traits": ["d"]
819 }
820 }
821 },
822 "comp3": {
823 "traits": ["e"]
824 }
825 }
826 }
827 },
828 "fingerprint": "1"
829 })";
830 EXPECT_JSON_EQ(kExpected4,
831 HandleRequest("/privet/v3/components",
832 "{'filter':['traits', 'components', 'state']}"));
833
834 const base::DictionaryValue* comp2 = nullptr;
835 ASSERT_TRUE(components.GetDictionary("comp1.components.comp2", &comp2));
Vitaly Buka34668e72015-12-15 14:46:47 -0800836 EXPECT_CALL(cloud_, FindComponent("comp1.comp2", _)).WillOnce(Return(comp2));
Alex Vakulenko3eb52e72015-12-14 15:34:08 -0800837
838 const char kExpected5[] = R"({
839 "components": {
840 "comp2": {
841 "traits": ["c"],
842 "components": {
843 "comp4": {
844 "traits": ["d"]
845 }
846 }
847 }
848 },
849 "fingerprint": "1"
850 })";
Vitaly Buka34668e72015-12-15 14:46:47 -0800851 EXPECT_JSON_EQ(
852 kExpected5,
853 HandleRequest(
854 "/privet/v3/components",
855 "{'path':'comp1.comp2', 'filter':['traits', 'components']}"));
Alex Vakulenko3eb52e72015-12-14 15:34:08 -0800856
857 auto error_handler = [](ErrorPtr* error) -> const base::DictionaryValue* {
Vitaly Buka0dbbf602016-01-22 11:38:37 -0800858 return Error::AddTo(error, FROM_HERE, "componentNotFound", "");
Alex Vakulenko3eb52e72015-12-14 15:34:08 -0800859 };
860 EXPECT_CALL(cloud_, FindComponent("comp7", _))
861 .WillOnce(WithArgs<1>(Invoke(error_handler)));
862
863 EXPECT_PRED2(
Vitaly Buka34668e72015-12-15 14:46:47 -0800864 IsEqualError, CodeWithReason(500, "componentNotFound"),
865 HandleRequest("/privet/v3/components",
866 "{'path':'comp7', 'filter':['traits', 'components']}"));
Alex Vakulenko3eb52e72015-12-14 15:34:08 -0800867}
868
Vitaly Buka2d24e0e2015-12-10 14:56:37 -0800869TEST_F(PrivetHandlerTestWithAuth, CommandsExecute) {
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700870 const char kInput[] = "{'name': 'test'}";
871 base::DictionaryValue command;
872 LoadTestJson(kInput, &command);
873 LoadTestJson("{'id':'5'}", &command);
Vitaly Buka74763422015-10-11 00:39:52 -0700874 EXPECT_CALL(cloud_, AddCommand(_, _, _))
875 .WillOnce(WithArgs<2>(Invoke(
876 [&command](const CloudDelegate::CommandDoneCallback& callback) {
877 callback.Run(command, nullptr);
878 })));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700879
Alex Vakulenko29a11ca2015-12-07 14:43:04 -0800880 EXPECT_JSON_EQ("{'name':'test', 'id':'5'}",
881 HandleRequest("/privet/v3/commands/execute", kInput));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700882}
883
Vitaly Buka2d24e0e2015-12-10 14:56:37 -0800884TEST_F(PrivetHandlerTestWithAuth, CommandsStatus) {
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700885 const char kInput[] = "{'id': '5'}";
886 base::DictionaryValue command;
887 LoadTestJson(kInput, &command);
888 LoadTestJson("{'name':'test'}", &command);
Vitaly Buka74763422015-10-11 00:39:52 -0700889 EXPECT_CALL(cloud_, GetCommand(_, _, _))
890 .WillOnce(WithArgs<2>(Invoke(
891 [&command](const CloudDelegate::CommandDoneCallback& callback) {
892 callback.Run(command, nullptr);
893 })));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700894
Alex Vakulenko29a11ca2015-12-07 14:43:04 -0800895 EXPECT_JSON_EQ("{'name':'test', 'id':'5'}",
896 HandleRequest("/privet/v3/commands/status", kInput));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700897
Vitaly Buka0801a1f2015-08-14 10:03:46 -0700898 ErrorPtr error;
Vitaly Buka48a86692016-01-21 17:15:58 -0800899 Error::AddTo(&error, FROM_HERE, "notFound", "");
Vitaly Buka74763422015-10-11 00:39:52 -0700900 EXPECT_CALL(cloud_, GetCommand(_, _, _))
901 .WillOnce(WithArgs<2>(
902 Invoke([&error](const CloudDelegate::CommandDoneCallback& callback) {
903 callback.Run({}, std::move(error));
904 })));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700905
906 EXPECT_PRED2(IsEqualError, CodeWithReason(404, "notFound"),
907 HandleRequest("/privet/v3/commands/status", "{'id': '15'}"));
908}
909
Vitaly Buka2d24e0e2015-12-10 14:56:37 -0800910TEST_F(PrivetHandlerTestWithAuth, CommandsCancel) {
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700911 const char kExpected[] = "{'id': '5', 'name':'test', 'state':'cancelled'}";
912 base::DictionaryValue command;
913 LoadTestJson(kExpected, &command);
Vitaly Buka74763422015-10-11 00:39:52 -0700914 EXPECT_CALL(cloud_, CancelCommand(_, _, _))
915 .WillOnce(WithArgs<2>(Invoke(
916 [&command](const CloudDelegate::CommandDoneCallback& callback) {
917 callback.Run(command, nullptr);
918 })));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700919
Alex Vakulenko29a11ca2015-12-07 14:43:04 -0800920 EXPECT_JSON_EQ(kExpected,
921 HandleRequest("/privet/v3/commands/cancel", "{'id': '8'}"));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700922
Vitaly Buka0801a1f2015-08-14 10:03:46 -0700923 ErrorPtr error;
Vitaly Buka48a86692016-01-21 17:15:58 -0800924 Error::AddTo(&error, FROM_HERE, "notFound", "");
Vitaly Buka74763422015-10-11 00:39:52 -0700925 EXPECT_CALL(cloud_, CancelCommand(_, _, _))
926 .WillOnce(WithArgs<2>(
927 Invoke([&error](const CloudDelegate::CommandDoneCallback& callback) {
928 callback.Run({}, std::move(error));
929 })));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700930
931 EXPECT_PRED2(IsEqualError, CodeWithReason(404, "notFound"),
932 HandleRequest("/privet/v3/commands/cancel", "{'id': '11'}"));
933}
934
Vitaly Buka2d24e0e2015-12-10 14:56:37 -0800935TEST_F(PrivetHandlerTestWithAuth, CommandsList) {
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700936 const char kExpected[] = R"({
937 'commands' : [
938 {'id':'5', 'state':'cancelled'},
939 {'id':'15', 'state':'inProgress'}
940 ]})";
941
942 base::DictionaryValue commands;
943 LoadTestJson(kExpected, &commands);
944
Vitaly Buka74763422015-10-11 00:39:52 -0700945 EXPECT_CALL(cloud_, ListCommands(_, _))
946 .WillOnce(WithArgs<1>(Invoke(
947 [&commands](const CloudDelegate::CommandDoneCallback& callback) {
948 callback.Run(commands, nullptr);
949 })));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700950
Alex Vakulenko29a11ca2015-12-07 14:43:04 -0800951 EXPECT_JSON_EQ(kExpected, HandleRequest("/privet/v3/commands/list", "{}"));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700952}
953
Alex Vakulenkoe3cc2302015-12-07 15:26:26 -0800954class PrivetHandlerCheckForUpdatesTest : public PrivetHandlerTestWithAuth {};
955
956TEST_F(PrivetHandlerCheckForUpdatesTest, NoInput) {
Alex Vakulenkoefee3a22015-11-17 15:08:38 -0800957 EXPECT_CALL(device_, GetHttpRequestTimeout())
958 .WillOnce(Return(base::TimeDelta::Max()));
Alex Vakulenkod91d6252015-12-05 17:14:39 -0800959 cloud_.NotifyOnTraitDefsChanged();
960 cloud_.NotifyOnComponentTreeChanged();
Alex Vakulenko551a82b2015-12-07 14:46:12 -0800961 cloud_.NotifyOnStateChanged();
Alex Vakulenkoefee3a22015-11-17 15:08:38 -0800962 const char kInput[] = "{}";
963 const char kExpected[] = R"({
Alex Vakulenkof9691322015-12-07 14:34:48 -0800964 'commandsFingerprint': '2',
965 'stateFingerprint': '2',
966 'traitsFingerprint': '2',
967 'componentsFingerprint': '3'
Alex Vakulenkoefee3a22015-11-17 15:08:38 -0800968 })";
Alex Vakulenko29a11ca2015-12-07 14:43:04 -0800969 EXPECT_JSON_EQ(kExpected,
970 HandleRequest("/privet/v3/checkForUpdates", kInput));
Alex Vakulenkoefee3a22015-11-17 15:08:38 -0800971 EXPECT_EQ(1, GetResponseCount());
972}
973
Alex Vakulenkoe3cc2302015-12-07 15:26:26 -0800974TEST_F(PrivetHandlerCheckForUpdatesTest, AlreadyChanged) {
Alex Vakulenkoefee3a22015-11-17 15:08:38 -0800975 EXPECT_CALL(device_, GetHttpRequestTimeout())
976 .WillOnce(Return(base::TimeDelta::Max()));
Alex Vakulenkod91d6252015-12-05 17:14:39 -0800977 cloud_.NotifyOnTraitDefsChanged();
978 cloud_.NotifyOnComponentTreeChanged();
Alex Vakulenko551a82b2015-12-07 14:46:12 -0800979 cloud_.NotifyOnStateChanged();
Alex Vakulenkoefee3a22015-11-17 15:08:38 -0800980 const char kInput[] = R"({
Alex Vakulenkoefee3a22015-11-17 15:08:38 -0800981 'commandsFingerprint': '1',
Alex Vakulenko551a82b2015-12-07 14:46:12 -0800982 'stateFingerprint': '1',
983 'traitsFingerprint': '1',
Alex Vakulenkof9691322015-12-07 14:34:48 -0800984 'componentsFingerprint': '1'
985 })";
986 const char kExpected[] = R"({
987 'commandsFingerprint': '2',
988 'stateFingerprint': '2',
989 'traitsFingerprint': '2',
990 'componentsFingerprint': '3'
Alex Vakulenkoefee3a22015-11-17 15:08:38 -0800991 })";
Alex Vakulenko29a11ca2015-12-07 14:43:04 -0800992 EXPECT_JSON_EQ(kExpected,
993 HandleRequest("/privet/v3/checkForUpdates", kInput));
Alex Vakulenkoefee3a22015-11-17 15:08:38 -0800994 EXPECT_EQ(1, GetResponseCount());
995}
996
Alex Vakulenkoe3cc2302015-12-07 15:26:26 -0800997TEST_F(PrivetHandlerCheckForUpdatesTest, LongPollCommands) {
Alex Vakulenkoefee3a22015-11-17 15:08:38 -0800998 EXPECT_CALL(device_, GetHttpRequestTimeout())
999 .WillOnce(Return(base::TimeDelta::Max()));
1000 const char kInput[] = R"({
Alex Vakulenkof9691322015-12-07 14:34:48 -08001001 'commandsFingerprint': '1',
1002 'stateFingerprint': '1',
1003 'traitsFingerprint': '1',
1004 'componentsFingerprint': '1'
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001005 })";
Alex Vakulenko29a11ca2015-12-07 14:43:04 -08001006 EXPECT_JSON_EQ("{}", HandleRequest("/privet/v3/checkForUpdates", kInput));
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001007 EXPECT_EQ(0, GetResponseCount());
Alex Vakulenkod91d6252015-12-05 17:14:39 -08001008 cloud_.NotifyOnTraitDefsChanged();
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001009 EXPECT_EQ(1, GetResponseCount());
1010 const char kExpected[] = R"({
Alex Vakulenkof9691322015-12-07 14:34:48 -08001011 'commandsFingerprint': '2',
1012 'stateFingerprint': '1',
1013 'traitsFingerprint': '2',
1014 'componentsFingerprint': '1'
Alex Vakulenko551a82b2015-12-07 14:46:12 -08001015 })";
1016 EXPECT_JSON_EQ(kExpected, GetResponse());
1017}
1018
Alex Vakulenkoe3cc2302015-12-07 15:26:26 -08001019TEST_F(PrivetHandlerCheckForUpdatesTest, LongPollTraits) {
Alex Vakulenko551a82b2015-12-07 14:46:12 -08001020 EXPECT_CALL(device_, GetHttpRequestTimeout())
1021 .WillOnce(Return(base::TimeDelta::Max()));
1022 const char kInput[] = R"({
Alex Vakulenkof9691322015-12-07 14:34:48 -08001023 'commandsFingerprint': '1',
1024 'stateFingerprint': '1',
1025 'traitsFingerprint': '1',
1026 'componentsFingerprint': '1'
Alex Vakulenko551a82b2015-12-07 14:46:12 -08001027 })";
1028 EXPECT_JSON_EQ("{}", HandleRequest("/privet/v3/checkForUpdates", kInput));
1029 EXPECT_EQ(0, GetResponseCount());
1030 cloud_.NotifyOnTraitDefsChanged();
1031 EXPECT_EQ(1, GetResponseCount());
1032 const char kExpected[] = R"({
Alex Vakulenkof9691322015-12-07 14:34:48 -08001033 'commandsFingerprint': '2',
1034 'stateFingerprint': '1',
1035 'traitsFingerprint': '2',
1036 'componentsFingerprint': '1'
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001037 })";
Alex Vakulenko29a11ca2015-12-07 14:43:04 -08001038 EXPECT_JSON_EQ(kExpected, GetResponse());
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001039}
1040
Alex Vakulenkoe3cc2302015-12-07 15:26:26 -08001041TEST_F(PrivetHandlerCheckForUpdatesTest, LongPollState) {
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001042 EXPECT_CALL(device_, GetHttpRequestTimeout())
1043 .WillOnce(Return(base::TimeDelta::Max()));
1044 const char kInput[] = R"({
Alex Vakulenkof9691322015-12-07 14:34:48 -08001045 'commandsFingerprint': '1',
1046 'stateFingerprint': '1',
1047 'traitsFingerprint': '1',
1048 'componentsFingerprint': '1'
Alex Vakulenko551a82b2015-12-07 14:46:12 -08001049 })";
1050 EXPECT_JSON_EQ("{}", HandleRequest("/privet/v3/checkForUpdates", kInput));
1051 EXPECT_EQ(0, GetResponseCount());
1052 cloud_.NotifyOnStateChanged();
1053 EXPECT_EQ(1, GetResponseCount());
1054 const char kExpected[] = R"({
Alex Vakulenkof9691322015-12-07 14:34:48 -08001055 'commandsFingerprint': '1',
1056 'stateFingerprint': '2',
1057 'traitsFingerprint': '1',
1058 'componentsFingerprint': '2'
Alex Vakulenko551a82b2015-12-07 14:46:12 -08001059 })";
1060 EXPECT_JSON_EQ(kExpected, GetResponse());
1061}
1062
Alex Vakulenkoe3cc2302015-12-07 15:26:26 -08001063TEST_F(PrivetHandlerCheckForUpdatesTest, LongPollComponents) {
Alex Vakulenko551a82b2015-12-07 14:46:12 -08001064 EXPECT_CALL(device_, GetHttpRequestTimeout())
1065 .WillOnce(Return(base::TimeDelta::Max()));
1066 const char kInput[] = R"({
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001067 'commandsFingerprint': '1',
Alex Vakulenkof9691322015-12-07 14:34:48 -08001068 'stateFingerprint': '1',
Alex Vakulenko551a82b2015-12-07 14:46:12 -08001069 'traitsFingerprint': '1',
1070 'componentsFingerprint': '1'
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001071 })";
Alex Vakulenko29a11ca2015-12-07 14:43:04 -08001072 EXPECT_JSON_EQ("{}", HandleRequest("/privet/v3/checkForUpdates", kInput));
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001073 EXPECT_EQ(0, GetResponseCount());
Alex Vakulenkod91d6252015-12-05 17:14:39 -08001074 cloud_.NotifyOnComponentTreeChanged();
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001075 EXPECT_EQ(1, GetResponseCount());
1076 const char kExpected[] = R"({
1077 'commandsFingerprint': '1',
Alex Vakulenko551a82b2015-12-07 14:46:12 -08001078 'stateFingerprint': '1',
1079 'traitsFingerprint': '1',
1080 'componentsFingerprint': '2'
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001081 })";
Alex Vakulenko29a11ca2015-12-07 14:43:04 -08001082 EXPECT_JSON_EQ(kExpected, GetResponse());
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001083}
1084
Alex Vakulenkoe3cc2302015-12-07 15:26:26 -08001085TEST_F(PrivetHandlerCheckForUpdatesTest, LongPollIgnoreTraits) {
Alex Vakulenkof9691322015-12-07 14:34:48 -08001086 EXPECT_CALL(device_, GetHttpRequestTimeout())
1087 .WillOnce(Return(base::TimeDelta::Max()));
1088 const char kInput[] = R"({
1089 'stateFingerprint': '1',
1090 'componentsFingerprint': '1'
1091 })";
1092 EXPECT_JSON_EQ("{}", HandleRequest("/privet/v3/checkForUpdates", kInput));
1093 EXPECT_EQ(0, GetResponseCount());
1094 cloud_.NotifyOnTraitDefsChanged();
1095 EXPECT_EQ(0, GetResponseCount());
1096 cloud_.NotifyOnComponentTreeChanged();
1097 EXPECT_EQ(1, GetResponseCount());
1098 const char kExpected[] = R"({
1099 'commandsFingerprint': '2',
1100 'stateFingerprint': '1',
1101 'traitsFingerprint': '2',
1102 'componentsFingerprint': '2'
1103 })";
1104 EXPECT_JSON_EQ(kExpected, GetResponse());
1105}
1106
Alex Vakulenkoe3cc2302015-12-07 15:26:26 -08001107TEST_F(PrivetHandlerCheckForUpdatesTest, LongPollIgnoreState) {
Alex Vakulenkof9691322015-12-07 14:34:48 -08001108 EXPECT_CALL(device_, GetHttpRequestTimeout())
1109 .WillOnce(Return(base::TimeDelta::Max()));
1110 const char kInput[] = R"({
1111 'commandsFingerprint': '1',
1112 'traitsFingerprint': '1'
1113 })";
1114 EXPECT_JSON_EQ("{}", HandleRequest("/privet/v3/checkForUpdates", kInput));
1115 EXPECT_EQ(0, GetResponseCount());
1116 cloud_.NotifyOnStateChanged();
1117 EXPECT_EQ(0, GetResponseCount());
1118 cloud_.NotifyOnComponentTreeChanged();
1119 EXPECT_EQ(0, GetResponseCount());
1120 cloud_.NotifyOnTraitDefsChanged();
1121 EXPECT_EQ(1, GetResponseCount());
1122 const char kExpected[] = R"({
1123 'commandsFingerprint': '2',
1124 'stateFingerprint': '2',
1125 'traitsFingerprint': '2',
1126 'componentsFingerprint': '3'
1127 })";
1128 EXPECT_JSON_EQ(kExpected, GetResponse());
1129}
1130
Alex Vakulenkoe3cc2302015-12-07 15:26:26 -08001131TEST_F(PrivetHandlerCheckForUpdatesTest, InstantTimeout) {
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001132 EXPECT_CALL(device_, GetHttpRequestTimeout())
1133 .WillOnce(Return(base::TimeDelta::Max()));
1134 const char kInput[] = R"({
Alex Vakulenkof9691322015-12-07 14:34:48 -08001135 'commandsFingerprint': '1',
1136 'stateFingerprint': '1',
1137 'traitsFingerprint': '1',
1138 'componentsFingerprint': '1',
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001139 'waitTimeout': 0
1140 })";
1141 const char kExpected[] = R"({
Alex Vakulenkof9691322015-12-07 14:34:48 -08001142 'commandsFingerprint': '1',
1143 'stateFingerprint': '1',
1144 'traitsFingerprint': '1',
1145 'componentsFingerprint': '1'
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001146 })";
Alex Vakulenko29a11ca2015-12-07 14:43:04 -08001147 EXPECT_JSON_EQ(kExpected,
1148 HandleRequest("/privet/v3/checkForUpdates", kInput));
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001149}
1150
Alex Vakulenkoe3cc2302015-12-07 15:26:26 -08001151TEST_F(PrivetHandlerCheckForUpdatesTest, UserTimeout) {
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001152 EXPECT_CALL(device_, GetHttpRequestTimeout())
1153 .WillOnce(Return(base::TimeDelta::Max()));
1154 const char kInput[] = R"({
Alex Vakulenkof9691322015-12-07 14:34:48 -08001155 'commandsFingerprint': '1',
1156 'stateFingerprint': '1',
1157 'traitsFingerprint': '1',
1158 'componentsFingerprint': '1',
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001159 'waitTimeout': 3
1160 })";
1161 base::Closure callback;
1162 EXPECT_CALL(device_, PostDelayedTask(_, _, base::TimeDelta::FromSeconds(3)))
1163 .WillOnce(SaveArg<1>(&callback));
Alex Vakulenko29a11ca2015-12-07 14:43:04 -08001164 EXPECT_JSON_EQ("{}", HandleRequest("/privet/v3/checkForUpdates", kInput));
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001165 EXPECT_EQ(0, GetResponseCount());
1166 callback.Run();
1167 EXPECT_EQ(1, GetResponseCount());
1168 const char kExpected[] = R"({
Alex Vakulenkof9691322015-12-07 14:34:48 -08001169 'commandsFingerprint': '1',
1170 'stateFingerprint': '1',
1171 'traitsFingerprint': '1',
1172 'componentsFingerprint': '1'
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001173 })";
Alex Vakulenko29a11ca2015-12-07 14:43:04 -08001174 EXPECT_JSON_EQ(kExpected, GetResponse());
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001175}
1176
Alex Vakulenkoe3cc2302015-12-07 15:26:26 -08001177TEST_F(PrivetHandlerCheckForUpdatesTest, ServerTimeout) {
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001178 EXPECT_CALL(device_, GetHttpRequestTimeout())
1179 .WillOnce(Return(base::TimeDelta::FromMinutes(1)));
1180 const char kInput[] = R"({
Alex Vakulenkof9691322015-12-07 14:34:48 -08001181 'commandsFingerprint': '1',
1182 'stateFingerprint': '1',
1183 'traitsFingerprint': '1',
1184 'componentsFingerprint': '1'
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001185 })";
1186 base::Closure callback;
1187 EXPECT_CALL(device_, PostDelayedTask(_, _, base::TimeDelta::FromSeconds(50)))
1188 .WillOnce(SaveArg<1>(&callback));
Alex Vakulenko29a11ca2015-12-07 14:43:04 -08001189 EXPECT_JSON_EQ("{}", HandleRequest("/privet/v3/checkForUpdates", kInput));
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001190 EXPECT_EQ(0, GetResponseCount());
1191 callback.Run();
1192 EXPECT_EQ(1, GetResponseCount());
1193 const char kExpected[] = R"({
Alex Vakulenkof9691322015-12-07 14:34:48 -08001194 'commandsFingerprint': '1',
1195 'stateFingerprint': '1',
1196 'traitsFingerprint': '1',
1197 'componentsFingerprint': '1'
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001198 })";
Alex Vakulenko29a11ca2015-12-07 14:43:04 -08001199 EXPECT_JSON_EQ(kExpected, GetResponse());
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001200}
1201
Alex Vakulenkoe3cc2302015-12-07 15:26:26 -08001202TEST_F(PrivetHandlerCheckForUpdatesTest, VeryShortServerTimeout) {
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001203 EXPECT_CALL(device_, GetHttpRequestTimeout())
1204 .WillOnce(Return(base::TimeDelta::FromSeconds(5)));
1205 const char kInput[] = R"({
Alex Vakulenkof9691322015-12-07 14:34:48 -08001206 'commandsFingerprint': '1',
1207 'stateFingerprint': '1',
1208 'traitsFingerprint': '1',
1209 'componentsFingerprint': '1'
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001210 })";
Alex Vakulenko29a11ca2015-12-07 14:43:04 -08001211 EXPECT_JSON_EQ(kInput, HandleRequest("/privet/v3/checkForUpdates", kInput));
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001212 EXPECT_EQ(1, GetResponseCount());
1213}
1214
Alex Vakulenkoe3cc2302015-12-07 15:26:26 -08001215TEST_F(PrivetHandlerCheckForUpdatesTest, ServerAndUserTimeout) {
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001216 EXPECT_CALL(device_, GetHttpRequestTimeout())
1217 .WillOnce(Return(base::TimeDelta::FromMinutes(1)));
1218 const char kInput[] = R"({
Alex Vakulenkof9691322015-12-07 14:34:48 -08001219 'commandsFingerprint': '1',
1220 'stateFingerprint': '1',
1221 'traitsFingerprint': '1',
1222 'componentsFingerprint': '1',
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001223 'waitTimeout': 10
1224 })";
1225 base::Closure callback;
1226 EXPECT_CALL(device_, PostDelayedTask(_, _, base::TimeDelta::FromSeconds(10)))
1227 .WillOnce(SaveArg<1>(&callback));
Alex Vakulenko29a11ca2015-12-07 14:43:04 -08001228 EXPECT_JSON_EQ("{}", HandleRequest("/privet/v3/checkForUpdates", kInput));
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001229 EXPECT_EQ(0, GetResponseCount());
1230 callback.Run();
1231 EXPECT_EQ(1, GetResponseCount());
1232 const char kExpected[] = R"({
Alex Vakulenkof9691322015-12-07 14:34:48 -08001233 'commandsFingerprint': '1',
1234 'stateFingerprint': '1',
1235 'traitsFingerprint': '1',
1236 'componentsFingerprint': '1'
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001237 })";
Alex Vakulenko29a11ca2015-12-07 14:43:04 -08001238 EXPECT_JSON_EQ(kExpected, GetResponse());
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001239}
1240
Alex Vakulenkoe3cc2302015-12-07 15:26:26 -08001241TEST_F(PrivetHandlerCheckForUpdatesTest, ChangeBeforeTimeout) {
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001242 EXPECT_CALL(device_, GetHttpRequestTimeout())
1243 .WillOnce(Return(base::TimeDelta::Max()));
1244 const char kInput[] = R"({
Alex Vakulenkof9691322015-12-07 14:34:48 -08001245 'commandsFingerprint': '1',
1246 'stateFingerprint': '1',
1247 'traitsFingerprint': '1',
1248 'componentsFingerprint': '1',
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001249 'waitTimeout': 10
1250 })";
1251 base::Closure callback;
1252 EXPECT_CALL(device_, PostDelayedTask(_, _, base::TimeDelta::FromSeconds(10)))
1253 .WillOnce(SaveArg<1>(&callback));
Alex Vakulenko29a11ca2015-12-07 14:43:04 -08001254 EXPECT_JSON_EQ("{}", HandleRequest("/privet/v3/checkForUpdates", kInput));
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001255 EXPECT_EQ(0, GetResponseCount());
Alex Vakulenkod91d6252015-12-05 17:14:39 -08001256 cloud_.NotifyOnTraitDefsChanged();
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001257 EXPECT_EQ(1, GetResponseCount());
1258 const char kExpected[] = R"({
Alex Vakulenkof9691322015-12-07 14:34:48 -08001259 'commandsFingerprint': '2',
1260 'stateFingerprint': '1',
1261 'traitsFingerprint': '2',
1262 'componentsFingerprint': '1'
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001263 })";
Alex Vakulenko29a11ca2015-12-07 14:43:04 -08001264 EXPECT_JSON_EQ(kExpected, GetResponse());
Alex Vakulenkoefee3a22015-11-17 15:08:38 -08001265 callback.Run();
1266 EXPECT_EQ(1, GetResponseCount());
1267}
1268
Vitaly Bukab6f015a2015-07-09 14:59:23 -07001269} // namespace privet
1270} // namespace weave