blob: bf883bf7f7f994f8b4165fafdb593e9636f5de6b [file] [log] [blame]
Vitaly Buka7ce499f2015-06-09 08:04:11 -07001// Copyright 2014 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 "buffet/privet/privet_handler.h"
6
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>
14#include <base/run_loop.h>
15#include <base/strings/string_util.h>
16#include <base/values.h>
17#include <chromeos/http/http_request.h>
18#include <gmock/gmock.h>
19#include <gtest/gtest.h>
20
21#include "buffet/privet/constants.h"
22#include "buffet/privet/mock_delegates.h"
23
24using testing::_;
25using testing::DoAll;
26using testing::Invoke;
27using testing::Return;
28using testing::SetArgPointee;
29
30namespace privetd {
31
32namespace {
33
34void LoadTestJson(const std::string& test_json,
35 base::DictionaryValue* dictionary) {
36 std::string json = test_json;
37 base::ReplaceChars(json, "'", "\"", &json);
38 int error = 0;
39 std::string message;
40 std::unique_ptr<base::Value> value(base::JSONReader::ReadAndReturnError(
41 json, base::JSON_PARSE_RFC, &error, &message));
42 EXPECT_TRUE(value.get()) << "\nError: " << message << "\n" << json;
43 base::DictionaryValue* dictionary_ptr = nullptr;
44 if (value->GetAsDictionary(&dictionary_ptr))
45 dictionary->MergeDictionary(dictionary_ptr);
46}
47
48bool IsEqualValue(const base::Value& val1, const base::Value& val2) {
49 return val1.Equals(&val2);
50}
51
52struct CodeWithReason {
53 CodeWithReason(int code_in, const std::string& reason_in)
54 : code(code_in), reason(reason_in) {}
55 int code;
56 std::string reason;
57};
58
59std::ostream& operator<<(std::ostream& stream, const CodeWithReason& error) {
60 return stream << "{" << error.code << ", " << error.reason << "}";
61}
62
63bool IsEqualError(const CodeWithReason& expected,
64 const base::DictionaryValue& dictionary) {
65 std::string reason;
66 int code = 0;
67 return dictionary.GetInteger("error.http_status", &code) &&
68 code == expected.code && dictionary.GetString("error.code", &reason) &&
69 reason == expected.reason;
70}
71
72bool IsEqualDictionary(const base::DictionaryValue& dictionary1,
73 const base::DictionaryValue& dictionary2) {
74 base::DictionaryValue::Iterator it1(dictionary1);
75 base::DictionaryValue::Iterator it2(dictionary2);
76 for (; !it1.IsAtEnd() && !it2.IsAtEnd(); it1.Advance(), it2.Advance()) {
77 // Output mismatched keys.
78 EXPECT_EQ(it1.key(), it2.key());
79 if (it1.key() != it2.key())
80 return false;
81
82 if (it1.key() == "error") {
83 std::string code1;
84 std::string code2;
85 const char kCodeKey[] = "error.code";
86 if (!dictionary1.GetString(kCodeKey, &code1) ||
87 !dictionary2.GetString(kCodeKey, &code2) || code1 != code2) {
88 return false;
89 }
90 continue;
91 }
92
93 const base::DictionaryValue* d1{nullptr};
94 const base::DictionaryValue* d2{nullptr};
95 if (it1.value().GetAsDictionary(&d1) && it2.value().GetAsDictionary(&d2)) {
96 if (!IsEqualDictionary(*d1, *d2))
97 return false;
98 continue;
99 }
100
101 // Output mismatched values.
102 EXPECT_PRED2(IsEqualValue, it1.value(), it2.value());
103 if (!IsEqualValue(it1.value(), it2.value()))
104 return false;
105 }
106
107 return it1.IsAtEnd() && it2.IsAtEnd();
108}
109
110bool IsEqualJson(const std::string& test_json,
111 const base::DictionaryValue& dictionary) {
112 base::DictionaryValue dictionary2;
113 LoadTestJson(test_json, &dictionary2);
114 return IsEqualDictionary(dictionary2, dictionary);
115}
116
117} // namespace
118
119class PrivetHandlerTest : public testing::Test {
120 public:
121 PrivetHandlerTest() {}
122
123 protected:
124 void SetUp() override {
125 auth_header_ = "Privet anonymous";
126 handler_.reset(
127 new PrivetHandler(&cloud_, &device_, &security_, &wifi_, &identity_));
128 }
129
130 const base::DictionaryValue& HandleRequest(
131 const std::string& api,
132 const base::DictionaryValue* input) {
133 output_.Clear();
134 handler_->HandleRequest(api, auth_header_, input,
135 base::Bind(&PrivetHandlerTest::HandlerCallback,
136 base::Unretained(this)));
137 base::RunLoop().RunUntilIdle();
138 return output_;
139 }
140
141 const base::DictionaryValue& HandleRequest(const std::string& api,
142 const std::string& json_input) {
143 base::DictionaryValue dictionary;
144 LoadTestJson(json_input, &dictionary);
145 return HandleRequest(api, &dictionary);
146 }
147
148 void HandleUnknownRequest(const std::string& api) {
149 output_.Clear();
150 base::DictionaryValue dictionary;
151 handler_->HandleRequest(api, auth_header_, &dictionary,
152 base::Bind(&PrivetHandlerTest::HandlerNoFound));
153 base::RunLoop().RunUntilIdle();
154 }
155
156 void SetNoWifiAndGcd() {
157 handler_.reset(
158 new PrivetHandler(&cloud_, &device_, &security_, nullptr, &identity_));
159 EXPECT_CALL(cloud_, GetCloudId()).WillRepeatedly(Return(""));
160 EXPECT_CALL(cloud_, GetConnectionState())
161 .WillRepeatedly(ReturnRef(gcd_disabled_state_));
162 auto set_error =
163 [](const std::string&, const std::string&, chromeos::ErrorPtr* error) {
Vitaly Buka075b3d42015-06-09 08:34:25 -0700164 chromeos::Error::AddTo(error, FROM_HERE, errors::kDomain,
165 "setupUnavailable", "");
166 };
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700167 EXPECT_CALL(cloud_, Setup(_, _, _))
168 .WillRepeatedly(DoAll(Invoke(set_error), Return(false)));
169 }
170
171 testing::StrictMock<MockCloudDelegate> cloud_;
172 testing::StrictMock<MockDeviceDelegate> device_;
173 testing::StrictMock<MockSecurityDelegate> security_;
174 testing::StrictMock<MockWifiDelegate> wifi_;
175 testing::StrictMock<MockIdentityDelegate> identity_;
176 std::string auth_header_;
177
178 private:
179 void HandlerCallback(int status, const base::DictionaryValue& output) {
180 output_.MergeDictionary(&output);
181 if (!output_.HasKey("error")) {
182 EXPECT_EQ(chromeos::http::status_code::Ok, status);
183 return;
184 }
185 EXPECT_NE(chromeos::http::status_code::Ok, status);
186 output_.SetInteger("error.http_status", status);
187 }
188
189 static void HandlerNoFound(int status, const base::DictionaryValue&) {
190 EXPECT_EQ(status, 404);
191 }
192
193 base::MessageLoop message_loop_;
194 std::unique_ptr<PrivetHandler> handler_;
195 base::DictionaryValue output_;
196 ConnectionState gcd_disabled_state_{ConnectionState::kDisabled};
197};
198
199TEST_F(PrivetHandlerTest, UnknownApi) {
200 HandleUnknownRequest("/privet/foo");
201}
202
203TEST_F(PrivetHandlerTest, InvalidFormat) {
204 auth_header_ = "";
205 EXPECT_PRED2(IsEqualError, CodeWithReason(400, "invalidFormat"),
206 HandleRequest("/privet/info", nullptr));
207}
208
209TEST_F(PrivetHandlerTest, MissingAuth) {
210 auth_header_ = "";
211 EXPECT_PRED2(IsEqualError, CodeWithReason(401, "missingAuthorization"),
212 HandleRequest("/privet/info", "{}"));
213}
214
215TEST_F(PrivetHandlerTest, InvalidAuth) {
216 auth_header_ = "foo";
217 EXPECT_PRED2(IsEqualError, CodeWithReason(401, "invalidAuthorization"),
218 HandleRequest("/privet/info", "{}"));
219}
220
221TEST_F(PrivetHandlerTest, ExpiredAuth) {
222 auth_header_ = "Privet 123";
223 EXPECT_CALL(security_, ParseAccessToken(_, _))
224 .WillRepeatedly(DoAll(SetArgPointee<1>(base::Time()),
225 Return(UserInfo{AuthScope::kOwner, 1})));
226 EXPECT_PRED2(IsEqualError, CodeWithReason(403, "authorizationExpired"),
227 HandleRequest("/privet/info", "{}"));
228}
229
230TEST_F(PrivetHandlerTest, InvalidAuthScope) {
231 EXPECT_PRED2(IsEqualError, CodeWithReason(403, "invalidAuthorizationScope"),
232 HandleRequest("/privet/v3/setup/start", "{}"));
233}
234
235TEST_F(PrivetHandlerTest, InfoMinimal) {
236 SetNoWifiAndGcd();
237 EXPECT_CALL(security_, GetPairingTypes())
238 .WillRepeatedly(Return(std::set<PairingType>{}));
239 EXPECT_CALL(security_, GetCryptoTypes())
240 .WillRepeatedly(Return(std::set<CryptoType>{}));
241
242 const char kExpected[] = R"({
243 'version': '3.0',
244 'id': 'TestId',
245 'name': 'TestDevice',
246 'services': [],
247 'modelManifestId': "ABMID",
248 'basicModelManifest': {
249 'uiDeviceKind': 'developmentBoard',
250 'oemName': 'Chromium',
251 'modelName': 'Brillo'
252 },
253 'endpoints': {
254 'httpPort': 0,
255 'httpUpdatesPort': 0,
256 'httpsPort': 0,
257 'httpsUpdatesPort': 0
258 },
259 'authentication': {
260 'anonymousMaxScope': 'user',
261 'mode': [
262 'anonymous',
263 'pairing'
264 ],
265 'pairing': [
266 ],
267 'crypto': [
268 ]
269 },
270 'gcd': {
271 'id': '',
272 'status': 'disabled'
273 },
274 'uptime': 3600
275 })";
276 EXPECT_PRED2(IsEqualJson, kExpected, HandleRequest("/privet/info", "{}"));
277}
278
279TEST_F(PrivetHandlerTest, Info) {
280 EXPECT_CALL(cloud_, GetDescription())
281 .WillRepeatedly(Return("TestDescription"));
282 EXPECT_CALL(cloud_, GetLocation()).WillRepeatedly(Return("TestLocation"));
283 EXPECT_CALL(cloud_, GetServices())
284 .WillRepeatedly(Return(std::set<std::string>{"service1", "service2"}));
285 EXPECT_CALL(device_, GetHttpEnpoint())
286 .WillRepeatedly(Return(std::make_pair(80, 10080)));
287 EXPECT_CALL(device_, GetHttpsEnpoint())
288 .WillRepeatedly(Return(std::make_pair(443, 10443)));
289 EXPECT_CALL(wifi_, GetHostedSsid())
290 .WillRepeatedly(Return("Test_device.BBABCLAprv"));
291
292 const char kExpected[] = R"({
293 'version': '3.0',
294 'id': 'TestId',
295 'name': 'TestDevice',
296 'description': 'TestDescription',
297 'location': 'TestLocation',
298 'services': [
299 "service1",
300 "service2"
301 ],
302 'modelManifestId': "ABMID",
303 'basicModelManifest': {
304 'uiDeviceKind': 'developmentBoard',
305 'oemName': 'Chromium',
306 'modelName': 'Brillo'
307 },
308 'endpoints': {
309 'httpPort': 80,
310 'httpUpdatesPort': 10080,
311 'httpsPort': 443,
312 'httpsUpdatesPort': 10443
313 },
314 'authentication': {
315 'anonymousMaxScope': 'none',
316 'mode': [
317 'anonymous',
318 'pairing'
319 ],
320 'pairing': [
321 'pinCode',
322 'embeddedCode',
323 'ultrasound32',
324 'audible32'
325 ],
326 'crypto': [
327 'p224_spake2',
328 'p256_spake2'
329 ]
330 },
331 'wifi': {
332 'capabilities': [
333 '2.4GHz'
334 ],
335 'ssid': 'TestSsid',
336 'hostedSsid': 'Test_device.BBABCLAprv',
337 'status': 'offline'
338 },
339 'gcd': {
340 'id': 'TestCloudId',
341 'status': 'online'
342 },
343 'uptime': 3600
344 })";
345 EXPECT_PRED2(IsEqualJson, kExpected, HandleRequest("/privet/info", "{}"));
346}
347
348TEST_F(PrivetHandlerTest, PairingStartInvalidParams) {
349 EXPECT_PRED2(IsEqualError, CodeWithReason(400, "invalidParams"),
350 HandleRequest("/privet/v3/pairing/start",
351 "{'pairing':'embeddedCode','crypto':'crypto'}"));
352
353 EXPECT_PRED2(IsEqualError, CodeWithReason(400, "invalidParams"),
354 HandleRequest("/privet/v3/pairing/start",
355 "{'pairing':'code','crypto':'p256_spake2'}"));
356}
357
358TEST_F(PrivetHandlerTest, PairingStart) {
359 EXPECT_PRED2(
360 IsEqualJson,
361 "{'deviceCommitment': 'testCommitment', 'sessionId': 'testSession'}",
362 HandleRequest("/privet/v3/pairing/start",
363 "{'pairing': 'embeddedCode', 'crypto': 'p256_spake2'}"));
364}
365
366TEST_F(PrivetHandlerTest, PairingConfirm) {
367 EXPECT_PRED2(
368 IsEqualJson,
369 "{'certFingerprint':'testFingerprint','certSignature':'testSignature'}",
370 HandleRequest(
371 "/privet/v3/pairing/confirm",
372 "{'sessionId':'testSession','clientCommitment':'testCommitment'}"));
373}
374
375TEST_F(PrivetHandlerTest, PairingCancel) {
376 EXPECT_PRED2(IsEqualJson, "{}",
377 HandleRequest("/privet/v3/pairing/cancel",
378 "{'sessionId': 'testSession'}"));
379}
380
381TEST_F(PrivetHandlerTest, AuthErrorNoType) {
382 EXPECT_PRED2(IsEqualError, CodeWithReason(400, "invalidAuthMode"),
383 HandleRequest("/privet/v3/auth", "{}"));
384}
385
386TEST_F(PrivetHandlerTest, AuthErrorInvalidType) {
387 EXPECT_PRED2(IsEqualError, CodeWithReason(400, "invalidAuthMode"),
388 HandleRequest("/privet/v3/auth", "{'mode':'unknown'}"));
389}
390
391TEST_F(PrivetHandlerTest, AuthErrorNoScope) {
392 EXPECT_PRED2(IsEqualError, CodeWithReason(400, "invalidRequestedScope"),
393 HandleRequest("/privet/v3/auth", "{'mode':'anonymous'}"));
394}
395
396TEST_F(PrivetHandlerTest, AuthErrorInvalidScope) {
397 EXPECT_PRED2(
398 IsEqualError, CodeWithReason(400, "invalidRequestedScope"),
399 HandleRequest("/privet/v3/auth",
400 "{'mode':'anonymous','requestedScope':'unknown'}"));
401}
402
403TEST_F(PrivetHandlerTest, AuthErrorAccessDenied) {
404 EXPECT_PRED2(IsEqualError, CodeWithReason(403, "accessDenied"),
405 HandleRequest("/privet/v3/auth",
406 "{'mode':'anonymous','requestedScope':'owner'}"));
407}
408
409TEST_F(PrivetHandlerTest, AuthErrorInvalidAuthCode) {
410 EXPECT_CALL(security_, IsValidPairingCode("testToken"))
411 .WillRepeatedly(Return(false));
412 const char kInput[] = R"({
413 'mode': 'pairing',
414 'requestedScope': 'user',
415 'authCode': 'testToken'
416 })";
417 EXPECT_PRED2(IsEqualError, CodeWithReason(403, "invalidAuthCode"),
418 HandleRequest("/privet/v3/auth", kInput));
419}
420
421TEST_F(PrivetHandlerTest, AuthAnonymous) {
422 const char kExpected[] = R"({
423 'accessToken': 'GuestAccessToken',
424 'expiresIn': 3600,
425 'scope': 'user',
426 'tokenType': 'Privet'
427 })";
428 EXPECT_PRED2(IsEqualJson, kExpected,
429 HandleRequest("/privet/v3/auth",
430 "{'mode':'anonymous','requestedScope':'auto'}"));
431}
432
433TEST_F(PrivetHandlerTest, AuthPairing) {
434 EXPECT_CALL(security_, IsValidPairingCode("testToken"))
435 .WillRepeatedly(Return(true));
436 EXPECT_CALL(security_, CreateAccessToken(_, _))
437 .WillRepeatedly(Return("OwnerAccessToken"));
438 const char kInput[] = R"({
439 'mode': 'pairing',
440 'requestedScope': 'owner',
441 'authCode': 'testToken'
442 })";
443 const char kExpected[] = R"({
444 'accessToken': 'OwnerAccessToken',
445 'expiresIn': 3600,
446 'scope': 'owner',
447 'tokenType': 'Privet'
448 })";
Vitaly Buka075b3d42015-06-09 08:34:25 -0700449 EXPECT_PRED2(IsEqualJson, kExpected,
450 HandleRequest("/privet/v3/auth", kInput));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700451}
452
453class PrivetHandlerSetupTest : public PrivetHandlerTest {
454 public:
455 void SetUp() override {
456 PrivetHandlerTest::SetUp();
457 auth_header_ = "Privet 123";
458 EXPECT_CALL(security_, ParseAccessToken(_, _))
459 .WillRepeatedly(DoAll(SetArgPointee<1>(base::Time::Now()),
460 Return(UserInfo{AuthScope::kOwner, 1})));
461 }
462};
463
464TEST_F(PrivetHandlerSetupTest, StatusEmpty) {
465 SetNoWifiAndGcd();
Vitaly Buka075b3d42015-06-09 08:34:25 -0700466 EXPECT_PRED2(IsEqualJson, "{}",
467 HandleRequest("/privet/v3/setup/status", "{}"));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700468}
469
470TEST_F(PrivetHandlerSetupTest, StatusWifi) {
471 wifi_.setup_state_ = SetupState{SetupState::kSuccess};
472
473 const char kExpected[] = R"({
474 'wifi': {
475 'ssid': 'TestSsid',
476 'status': 'success'
477 }
478 })";
Vitaly Buka075b3d42015-06-09 08:34:25 -0700479 EXPECT_PRED2(IsEqualJson, kExpected,
480 HandleRequest("/privet/v3/setup/status", "{}"));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700481}
482
483TEST_F(PrivetHandlerSetupTest, StatusWifiError) {
484 chromeos::ErrorPtr error;
485 chromeos::Error::AddTo(&error, FROM_HERE, "test", "invalidPassphrase", "");
486 wifi_.setup_state_ = SetupState{std::move(error)};
487
488 const char kExpected[] = R"({
489 'wifi': {
490 'status': 'error',
491 'error': {
492 'code': 'invalidPassphrase'
493 }
494 }
495 })";
Vitaly Buka075b3d42015-06-09 08:34:25 -0700496 EXPECT_PRED2(IsEqualJson, kExpected,
497 HandleRequest("/privet/v3/setup/status", "{}"));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700498}
499
500TEST_F(PrivetHandlerSetupTest, StatusGcd) {
501 cloud_.setup_state_ = SetupState{SetupState::kSuccess};
502
503 const char kExpected[] = R"({
504 'gcd': {
505 'id': 'TestCloudId',
506 'status': 'success'
507 }
508 })";
Vitaly Buka075b3d42015-06-09 08:34:25 -0700509 EXPECT_PRED2(IsEqualJson, kExpected,
510 HandleRequest("/privet/v3/setup/status", "{}"));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700511}
512
513TEST_F(PrivetHandlerSetupTest, StatusGcdError) {
514 chromeos::ErrorPtr error;
515 chromeos::Error::AddTo(&error, FROM_HERE, "test", "invalidTicket", "");
516 cloud_.setup_state_ = SetupState{std::move(error)};
517
518 const char kExpected[] = R"({
519 'gcd': {
520 'status': 'error',
521 'error': {
522 'code': 'invalidTicket'
523 }
524 }
525 })";
Vitaly Buka075b3d42015-06-09 08:34:25 -0700526 EXPECT_PRED2(IsEqualJson, kExpected,
527 HandleRequest("/privet/v3/setup/status", "{}"));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700528}
529
530TEST_F(PrivetHandlerSetupTest, SetupNameDescriptionLocation) {
531 EXPECT_CALL(cloud_, UpdateDeviceInfo("testName", "testDescription",
532 "testLocation", _, _)).Times(1);
533 const char kInput[] = R"({
534 'name': 'testName',
535 'description': 'testDescription',
536 'location': 'testLocation'
537 })";
538 EXPECT_PRED2(IsEqualJson, "{}",
539 HandleRequest("/privet/v3/setup/start", kInput));
540}
541
542TEST_F(PrivetHandlerSetupTest, InvalidParams) {
543 const char kInputWifi[] = R"({
544 'wifi': {
545 'ssid': ''
546 }
547 })";
548 EXPECT_PRED2(IsEqualError, CodeWithReason(400, "invalidParams"),
549 HandleRequest("/privet/v3/setup/start", kInputWifi));
550
551 const char kInputRegistration[] = R"({
552 'gcd': {
553 'ticketId': ''
554 }
555 })";
556 EXPECT_PRED2(IsEqualError, CodeWithReason(400, "invalidParams"),
557 HandleRequest("/privet/v3/setup/start", kInputRegistration));
558}
559
560TEST_F(PrivetHandlerSetupTest, WifiSetupUnavailable) {
561 SetNoWifiAndGcd();
562 EXPECT_PRED2(IsEqualError, CodeWithReason(400, "setupUnavailable"),
563 HandleRequest("/privet/v3/setup/start", "{'wifi': {}}"));
564}
565
566TEST_F(PrivetHandlerSetupTest, WifiSetup) {
567 const char kInput[] = R"({
568 'wifi': {
569 'ssid': 'testSsid',
570 'passphrase': 'testPass'
571 }
572 })";
Vitaly Buka075b3d42015-06-09 08:34:25 -0700573 auto set_error =
574 [](const std::string&, const std::string&, chromeos::ErrorPtr* error) {
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700575 chromeos::Error::AddTo(error, FROM_HERE, errors::kDomain, "deviceBusy", "");
576 };
577 EXPECT_CALL(wifi_, ConfigureCredentials(_, _, _))
578 .WillOnce(DoAll(Invoke(set_error), Return(false)));
579 EXPECT_PRED2(IsEqualError, CodeWithReason(503, "deviceBusy"),
580 HandleRequest("/privet/v3/setup/start", kInput));
581
582 const char kExpected[] = R"({
583 'wifi': {
584 'status': 'inProgress'
585 }
586 })";
587 wifi_.setup_state_ = SetupState{SetupState::kInProgress};
588 EXPECT_CALL(wifi_, ConfigureCredentials("testSsid", "testPass", _))
589 .WillOnce(Return(true));
590 EXPECT_PRED2(IsEqualJson, kExpected,
591 HandleRequest("/privet/v3/setup/start", kInput));
592}
593
594TEST_F(PrivetHandlerSetupTest, GcdSetupUnavailable) {
595 SetNoWifiAndGcd();
596 const char kInput[] = R"({
597 'gcd': {
598 'ticketId': 'testTicket',
599 'user': 'testUser'
600 }
601 })";
602
603 EXPECT_PRED2(IsEqualError, CodeWithReason(400, "setupUnavailable"),
604 HandleRequest("/privet/v3/setup/start", kInput));
605}
606
607TEST_F(PrivetHandlerSetupTest, GcdSetup) {
608 const char kInput[] = R"({
609 'gcd': {
610 'ticketId': 'testTicket',
611 'user': 'testUser'
612 }
613 })";
614
Vitaly Buka075b3d42015-06-09 08:34:25 -0700615 auto set_error =
616 [](const std::string&, const std::string&, chromeos::ErrorPtr* error) {
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700617 chromeos::Error::AddTo(error, FROM_HERE, errors::kDomain, "deviceBusy", "");
618 };
619 EXPECT_CALL(cloud_, Setup(_, _, _))
620 .WillOnce(DoAll(Invoke(set_error), Return(false)));
621 EXPECT_PRED2(IsEqualError, CodeWithReason(503, "deviceBusy"),
622 HandleRequest("/privet/v3/setup/start", kInput));
623
624 const char kExpected[] = R"({
625 'gcd': {
626 'status': 'inProgress'
627 }
628 })";
629 cloud_.setup_state_ = SetupState{SetupState::kInProgress};
630 EXPECT_CALL(cloud_, Setup("testTicket", "testUser", _))
631 .WillOnce(Return(true));
632 EXPECT_PRED2(IsEqualJson, kExpected,
633 HandleRequest("/privet/v3/setup/start", kInput));
634}
635
636TEST_F(PrivetHandlerSetupTest, State) {
637 EXPECT_PRED2(IsEqualJson, "{'state': {'test': {}}, 'fingerprint': '0'}",
638 HandleRequest("/privet/v3/state", "{}"));
639
640 cloud_.NotifyOnStateChanged();
641
642 EXPECT_PRED2(IsEqualJson, "{'state': {'test': {}}, 'fingerprint': '1'}",
643 HandleRequest("/privet/v3/state", "{}"));
644}
645
646TEST_F(PrivetHandlerSetupTest, CommandsDefs) {
647 EXPECT_PRED2(IsEqualJson, "{'commands': {'test':{}}, 'fingerprint': '0'}",
648 HandleRequest("/privet/v3/commandDefs", "{}"));
649
650 cloud_.NotifyOnCommandDefsChanged();
651
652 EXPECT_PRED2(IsEqualJson, "{'commands': {'test':{}}, 'fingerprint': '1'}",
653 HandleRequest("/privet/v3/commandDefs", "{}"));
654}
655
656TEST_F(PrivetHandlerSetupTest, CommandsExecute) {
657 const char kInput[] = "{'name': 'test'}";
658 base::DictionaryValue command;
659 LoadTestJson(kInput, &command);
660 LoadTestJson("{'id':'5'}", &command);
661 EXPECT_CALL(cloud_, AddCommand(_, _, _, _))
662 .WillOnce(RunCallback<2, const base::DictionaryValue&>(command));
663
664 EXPECT_PRED2(IsEqualJson, "{'name':'test', 'id':'5'}",
665 HandleRequest("/privet/v3/commands/execute", kInput));
666}
667
668TEST_F(PrivetHandlerSetupTest, CommandsStatus) {
669 const char kInput[] = "{'id': '5'}";
670 base::DictionaryValue command;
671 LoadTestJson(kInput, &command);
672 LoadTestJson("{'name':'test'}", &command);
673 EXPECT_CALL(cloud_, GetCommand(_, _, _, _))
674 .WillOnce(RunCallback<2, const base::DictionaryValue&>(command));
675
676 EXPECT_PRED2(IsEqualJson, "{'name':'test', 'id':'5'}",
677 HandleRequest("/privet/v3/commands/status", kInput));
678
679 chromeos::ErrorPtr error;
680 chromeos::Error::AddTo(&error, FROM_HERE, errors::kDomain, "notFound", "");
681 EXPECT_CALL(cloud_, GetCommand(_, _, _, _))
682 .WillOnce(RunCallback<3>(error.get()));
683
684 EXPECT_PRED2(IsEqualError, CodeWithReason(404, "notFound"),
685 HandleRequest("/privet/v3/commands/status", "{'id': '15'}"));
686}
687
688TEST_F(PrivetHandlerSetupTest, CommandsCancel) {
689 const char kExpected[] = "{'id': '5', 'name':'test', 'state':'cancelled'}";
690 base::DictionaryValue command;
691 LoadTestJson(kExpected, &command);
692 EXPECT_CALL(cloud_, CancelCommand(_, _, _, _))
693 .WillOnce(RunCallback<2, const base::DictionaryValue&>(command));
694
695 EXPECT_PRED2(IsEqualJson, kExpected,
696 HandleRequest("/privet/v3/commands/cancel", "{'id': '8'}"));
697
698 chromeos::ErrorPtr error;
699 chromeos::Error::AddTo(&error, FROM_HERE, errors::kDomain, "notFound", "");
700 EXPECT_CALL(cloud_, CancelCommand(_, _, _, _))
701 .WillOnce(RunCallback<3>(error.get()));
702
703 EXPECT_PRED2(IsEqualError, CodeWithReason(404, "notFound"),
704 HandleRequest("/privet/v3/commands/cancel", "{'id': '11'}"));
705}
706
707TEST_F(PrivetHandlerSetupTest, CommandsList) {
708 const char kExpected[] = R"({
709 'commands' : [
710 {'id':'5', 'state':'cancelled'},
711 {'id':'15', 'state':'inProgress'}
712 ]})";
713
714 base::DictionaryValue commands;
715 LoadTestJson(kExpected, &commands);
716
717 EXPECT_CALL(cloud_, ListCommands(_, _, _))
718 .WillOnce(RunCallback<1, const base::DictionaryValue&>(commands));
719
720 EXPECT_PRED2(IsEqualJson, kExpected,
721 HandleRequest("/privet/v3/commands/list", "{}"));
722}
723
724} // namespace privetd