ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / components / proximity_auth / cryptauth / cryptauth_client_unittest.cc
blob6ee8343b0cafca72790a6f5bd2216ac9c90b1efb
1 // Copyright 2014 The Chromium 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.
5 #include "components/proximity_auth/cryptauth/cryptauth_client.h"
7 #include "base/command_line.h"
8 #include "base/test/null_task_runner.h"
9 #include "components/proximity_auth/cryptauth/cryptauth_access_token_fetcher.h"
10 #include "components/proximity_auth/cryptauth/cryptauth_api_call_flow.h"
11 #include "components/proximity_auth/cryptauth/proto/cryptauth_api.pb.h"
12 #include "components/proximity_auth/switches.h"
13 #include "net/url_request/test_url_fetcher_factory.h"
14 #include "net/url_request/url_request_test_util.h"
15 #include "testing/gmock/include/gmock/gmock.h"
16 #include "testing/gtest/include/gtest/gtest.h"
18 using testing::_;
19 using testing::DoAll;
20 using testing::Return;
21 using testing::SaveArg;
22 using testing::StrictMock;
24 namespace proximity_auth {
26 namespace {
28 const char kTestGoogleApisUrl[] = "https://www.testgoogleapis.com";
29 const char kAccessToken[] = "access_token";
30 const char kPublicKey1[] = "public_key1";
31 const char kPublicKey2[] = "public_key2";
32 const char kBluetoothAddress1[] = "AA:AA:AA:AA:AA:AA";
33 const char kBluetoothAddress2[] = "BB:BB:BB:BB:BB:BB";
35 // CryptAuthAccessTokenFetcher implementation simply returning a predetermined
36 // access token.
37 class FakeCryptAuthAccessTokenFetcher : public CryptAuthAccessTokenFetcher {
38 public:
39 FakeCryptAuthAccessTokenFetcher() : access_token_(kAccessToken) {}
41 void FetchAccessToken(const AccessTokenCallback& callback) override {
42 callback.Run(access_token_);
45 void set_access_token(const std::string& access_token) {
46 access_token_ = access_token;
49 private:
50 std::string access_token_;
53 // Mock CryptAuthApiCallFlow, which handles the HTTP requests to CryptAuth.
54 class MockCryptAuthApiCallFlow : public CryptAuthApiCallFlow {
55 public:
56 MockCryptAuthApiCallFlow() : CryptAuthApiCallFlow(GURL(std::string())) {}
57 virtual ~MockCryptAuthApiCallFlow() {}
59 MOCK_METHOD5(Start,
60 void(net::URLRequestContextGetter* context,
61 const std::string& access_token,
62 const std::string& serialized_request,
63 const ResultCallback& result_callback,
64 const ErrorCallback& error_callback));
66 private:
67 DISALLOW_COPY_AND_ASSIGN(MockCryptAuthApiCallFlow);
70 // Subclass of CryptAuthClient to use as test harness.
71 class MockCryptAuthClient : public CryptAuthClient {
72 public:
73 // Ownership of |access_token_fetcher| is passed to the superclass. Due to the
74 // limitations of gmock, we need to use a raw pointer argument rather than a
75 // scoped_ptr.
76 MockCryptAuthClient(
77 CryptAuthAccessTokenFetcher* access_token_fetcher,
78 scoped_refptr<net::URLRequestContextGetter> url_request_context)
79 : CryptAuthClient(make_scoped_ptr(access_token_fetcher),
80 url_request_context) {}
81 virtual ~MockCryptAuthClient() {}
83 MOCK_METHOD1(CreateFlowProxy, CryptAuthApiCallFlow*(const GURL& request_url));
85 scoped_ptr<CryptAuthApiCallFlow> CreateFlow(
86 const GURL& request_url) override {
87 return make_scoped_ptr(CreateFlowProxy(request_url));
90 private:
91 DISALLOW_COPY_AND_ASSIGN(MockCryptAuthClient);
94 // Callback that should never be invoked.
95 template <class T>
96 void NotCalled(const T& type) {
97 EXPECT_TRUE(false);
100 // Callback that saves the result returned by CryptAuthClient.
101 template <class T>
102 void SaveResult(T* out, const T& result) {
103 *out = result;
106 } // namespace
108 class ProximityAuthCryptAuthClientTest : public testing::Test {
109 protected:
110 ProximityAuthCryptAuthClientTest()
111 : access_token_fetcher_(new FakeCryptAuthAccessTokenFetcher()),
112 url_request_context_(
113 new net::TestURLRequestContextGetter(new base::NullTaskRunner())),
114 serialized_request_(std::string()) {}
116 void SetUp() override {
117 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
118 switches::kCryptAuthHTTPHost, kTestGoogleApisUrl);
120 client_.reset(new StrictMock<MockCryptAuthClient>(access_token_fetcher_,
121 url_request_context_));
124 // Sets up an expectation and captures a CryptAuth API request to
125 // |request_url|.
126 void ExpectRequest(const std::string& request_url) {
127 StrictMock<MockCryptAuthApiCallFlow>* api_call_flow =
128 new StrictMock<MockCryptAuthApiCallFlow>();
130 EXPECT_CALL(*client_, CreateFlowProxy(GURL(request_url)))
131 .WillOnce(Return(api_call_flow));
133 EXPECT_CALL(*api_call_flow,
134 Start(url_request_context_.get(), kAccessToken, _, _, _))
135 .WillOnce(DoAll(SaveArg<2>(&serialized_request_),
136 SaveArg<3>(&flow_result_callback_),
137 SaveArg<4>(&flow_error_callback_)));
140 // Returns |response_proto| as the result to the current API request.
141 // ExpectResult() must have been called first.
142 void FinishApiCallFlow(const google::protobuf::MessageLite* response_proto) {
143 flow_result_callback_.Run(response_proto->SerializeAsString());
146 // Ends the current API request with |error_message|. ExpectResult() must have
147 // been called first.
148 void FailApiCallFlow(const std::string& error_message) {
149 flow_error_callback_.Run(error_message);
152 protected:
153 // Owned by |client_|.
154 FakeCryptAuthAccessTokenFetcher* access_token_fetcher_;
156 scoped_refptr<net::URLRequestContextGetter> url_request_context_;
157 scoped_ptr<StrictMock<MockCryptAuthClient>> client_;
159 std::string serialized_request_;
160 CryptAuthApiCallFlow::ResultCallback flow_result_callback_;
161 CryptAuthApiCallFlow::ErrorCallback flow_error_callback_;
164 TEST_F(ProximityAuthCryptAuthClientTest, GetMyDevicesSuccess) {
165 ExpectRequest(
166 "https://www.testgoogleapis.com/cryptauth/v1/deviceSync/"
167 "getmydevices?alt=proto");
169 cryptauth::GetMyDevicesResponse result_proto;
170 cryptauth::GetMyDevicesRequest request_proto;
171 request_proto.set_allow_stale_read(true);
172 client_->GetMyDevices(
173 request_proto,
174 base::Bind(&SaveResult<cryptauth::GetMyDevicesResponse>, &result_proto),
175 base::Bind(&NotCalled<std::string>));
177 cryptauth::GetMyDevicesRequest expected_request;
178 EXPECT_TRUE(expected_request.ParseFromString(serialized_request_));
179 EXPECT_TRUE(expected_request.allow_stale_read());
181 // Return two devices, one unlock key and one unlockable device.
183 cryptauth::GetMyDevicesResponse response_proto;
184 response_proto.add_devices();
185 response_proto.mutable_devices(0)->set_public_key(kPublicKey1);
186 response_proto.mutable_devices(0)->set_unlock_key(true);
187 response_proto.mutable_devices(0)
188 ->set_bluetooth_address(kBluetoothAddress1);
189 response_proto.add_devices();
190 response_proto.mutable_devices(1)->set_public_key(kPublicKey2);
191 response_proto.mutable_devices(1)->set_unlockable(true);
192 FinishApiCallFlow(&response_proto);
195 // Check that the result received in callback is the same as the response.
196 ASSERT_EQ(2, result_proto.devices_size());
197 EXPECT_EQ(kPublicKey1, result_proto.devices(0).public_key());
198 EXPECT_TRUE(result_proto.devices(0).unlock_key());
199 EXPECT_EQ(kBluetoothAddress1, result_proto.devices(0).bluetooth_address());
200 EXPECT_EQ(kPublicKey2, result_proto.devices(1).public_key());
201 EXPECT_TRUE(result_proto.devices(1).unlockable());
204 TEST_F(ProximityAuthCryptAuthClientTest, GetMyDevicesFailure) {
205 ExpectRequest(
206 "https://www.testgoogleapis.com/cryptauth/v1/deviceSync/"
207 "getmydevices?alt=proto");
209 std::string error_message;
210 client_->GetMyDevices(cryptauth::GetMyDevicesRequest(),
211 base::Bind(&NotCalled<cryptauth::GetMyDevicesResponse>),
212 base::Bind(&SaveResult<std::string>, &error_message));
214 std::string kStatus500Error("HTTP status: 500");
215 FailApiCallFlow(kStatus500Error);
216 EXPECT_EQ(kStatus500Error, error_message);
219 TEST_F(ProximityAuthCryptAuthClientTest, FindEligibleUnlockDevicesSuccess) {
220 ExpectRequest(
221 "https://www.testgoogleapis.com/cryptauth/v1/deviceSync/"
222 "findeligibleunlockdevices?alt=proto");
224 cryptauth::FindEligibleUnlockDevicesResponse result_proto;
225 cryptauth::FindEligibleUnlockDevicesRequest request_proto;
226 request_proto.set_callback_bluetooth_address(kBluetoothAddress2);
227 client_->FindEligibleUnlockDevices(
228 request_proto,
229 base::Bind(&SaveResult<cryptauth::FindEligibleUnlockDevicesResponse>,
230 &result_proto),
231 base::Bind(&NotCalled<std::string>));
233 cryptauth::FindEligibleUnlockDevicesRequest expected_request;
234 EXPECT_TRUE(expected_request.ParseFromString(serialized_request_));
235 EXPECT_EQ(kBluetoothAddress2, expected_request.callback_bluetooth_address());
237 // Return a response proto with one eligible and one ineligible device.
238 cryptauth::FindEligibleUnlockDevicesResponse response_proto;
239 response_proto.add_eligible_devices();
240 response_proto.mutable_eligible_devices(0)->set_public_key(kPublicKey1);
242 const std::string kIneligibilityReason = "You require more vespine gas.";
243 response_proto.add_ineligible_devices();
244 response_proto.mutable_ineligible_devices(0)
245 ->mutable_device()
246 ->set_public_key(kPublicKey2);
247 response_proto.mutable_ineligible_devices(0)
248 ->add_reasons(kIneligibilityReason);
249 FinishApiCallFlow(&response_proto);
251 // Check that the result received in callback is the same as the response.
252 ASSERT_EQ(1, result_proto.eligible_devices_size());
253 EXPECT_EQ(kPublicKey1, result_proto.eligible_devices(0).public_key());
254 ASSERT_EQ(1, result_proto.ineligible_devices_size());
255 EXPECT_EQ(kPublicKey2,
256 result_proto.ineligible_devices(0).device().public_key());
257 ASSERT_EQ(1, result_proto.ineligible_devices(0).reasons_size());
258 EXPECT_EQ(kIneligibilityReason,
259 result_proto.ineligible_devices(0).reasons(0));
262 TEST_F(ProximityAuthCryptAuthClientTest, FindEligibleUnlockDevicesFailure) {
263 ExpectRequest(
264 "https://www.testgoogleapis.com/cryptauth/v1/deviceSync/"
265 "findeligibleunlockdevices?alt=proto");
267 std::string error_message;
268 cryptauth::FindEligibleUnlockDevicesRequest request_proto;
269 request_proto.set_callback_bluetooth_address(kBluetoothAddress1);
270 client_->FindEligibleUnlockDevices(
271 request_proto,
272 base::Bind(&NotCalled<cryptauth::FindEligibleUnlockDevicesResponse>),
273 base::Bind(&SaveResult<std::string>, &error_message));
275 std::string kStatus403Error("HTTP status: 403");
276 FailApiCallFlow(kStatus403Error);
277 EXPECT_EQ(kStatus403Error, error_message);
280 TEST_F(ProximityAuthCryptAuthClientTest, SendDeviceSyncTickleSuccess) {
281 ExpectRequest(
282 "https://www.testgoogleapis.com/cryptauth/v1/deviceSync/"
283 "senddevicesynctickle?alt=proto");
285 cryptauth::SendDeviceSyncTickleResponse result_proto;
286 client_->SendDeviceSyncTickle(
287 cryptauth::SendDeviceSyncTickleRequest(),
288 base::Bind(&SaveResult<cryptauth::SendDeviceSyncTickleResponse>,
289 &result_proto),
290 base::Bind(&NotCalled<std::string>));
292 cryptauth::SendDeviceSyncTickleRequest expected_request;
293 EXPECT_TRUE(expected_request.ParseFromString(serialized_request_));
295 cryptauth::SendDeviceSyncTickleResponse response_proto;
296 FinishApiCallFlow(&response_proto);
299 TEST_F(ProximityAuthCryptAuthClientTest, ToggleEasyUnlockSuccess) {
300 ExpectRequest(
301 "https://www.testgoogleapis.com/cryptauth/v1/deviceSync/"
302 "toggleeasyunlock?alt=proto");
304 cryptauth::ToggleEasyUnlockResponse result_proto;
305 cryptauth::ToggleEasyUnlockRequest request_proto;
306 request_proto.set_enable(true);
307 request_proto.set_apply_to_all(false);
308 request_proto.set_public_key(kPublicKey1);
309 client_->ToggleEasyUnlock(
310 request_proto,
311 base::Bind(&SaveResult<cryptauth::ToggleEasyUnlockResponse>,
312 &result_proto),
313 base::Bind(&NotCalled<std::string>));
315 cryptauth::ToggleEasyUnlockRequest expected_request;
316 EXPECT_TRUE(expected_request.ParseFromString(serialized_request_));
317 EXPECT_TRUE(expected_request.enable());
318 EXPECT_EQ(kPublicKey1, expected_request.public_key());
319 EXPECT_FALSE(expected_request.apply_to_all());
321 cryptauth::ToggleEasyUnlockResponse response_proto;
322 FinishApiCallFlow(&response_proto);
325 TEST_F(ProximityAuthCryptAuthClientTest, SetupEnrollmentSuccess) {
326 ExpectRequest(
327 "https://www.testgoogleapis.com/cryptauth/v1/enrollment/"
328 "setupenrollment?alt=proto");
330 std::string kApplicationId = "mkaes";
331 std::vector<std::string> supported_protocols;
332 supported_protocols.push_back("gcmV1");
333 supported_protocols.push_back("testProtocol");
335 cryptauth::SetupEnrollmentResponse result_proto;
336 cryptauth::SetupEnrollmentRequest request_proto;
337 request_proto.set_application_id(kApplicationId);
338 request_proto.add_types("gcmV1");
339 request_proto.add_types("testProtocol");
340 client_->SetupEnrollment(
341 request_proto, base::Bind(&SaveResult<cryptauth::SetupEnrollmentResponse>,
342 &result_proto),
343 base::Bind(&NotCalled<std::string>));
345 cryptauth::SetupEnrollmentRequest expected_request;
346 EXPECT_TRUE(expected_request.ParseFromString(serialized_request_));
347 EXPECT_EQ(kApplicationId, expected_request.application_id());
348 ASSERT_EQ(2, expected_request.types_size());
349 EXPECT_EQ("gcmV1", expected_request.types(0));
350 EXPECT_EQ("testProtocol", expected_request.types(1));
352 // Return a fake enrollment session.
354 cryptauth::SetupEnrollmentResponse response_proto;
355 response_proto.set_status("OK");
356 response_proto.add_infos();
357 response_proto.mutable_infos(0)->set_type("gcmV1");
358 response_proto.mutable_infos(0)->set_enrollment_session_id("session_id");
359 response_proto.mutable_infos(0)->set_server_ephemeral_key("ephemeral_key");
360 FinishApiCallFlow(&response_proto);
363 // Check that the returned proto is the same as the one just created.
364 EXPECT_EQ("OK", result_proto.status());
365 ASSERT_EQ(1, result_proto.infos_size());
366 EXPECT_EQ("gcmV1", result_proto.infos(0).type());
367 EXPECT_EQ("session_id", result_proto.infos(0).enrollment_session_id());
368 EXPECT_EQ("ephemeral_key", result_proto.infos(0).server_ephemeral_key());
371 TEST_F(ProximityAuthCryptAuthClientTest, FinishEnrollmentSuccess) {
372 ExpectRequest(
373 "https://www.testgoogleapis.com/cryptauth/v1/enrollment/"
374 "finishenrollment?alt=proto");
376 const char kEnrollmentSessionId[] = "enrollment_session_id";
377 const char kEnrollmentMessage[] = "enrollment_message";
378 const char kDeviceEphemeralKey[] = "device_ephermal_key";
379 cryptauth::FinishEnrollmentResponse result_proto;
380 cryptauth::FinishEnrollmentRequest request_proto;
381 request_proto.set_enrollment_session_id(kEnrollmentSessionId);
382 request_proto.set_enrollment_message(kEnrollmentMessage);
383 request_proto.set_device_ephemeral_key(kDeviceEphemeralKey);
384 client_->FinishEnrollment(
385 request_proto,
386 base::Bind(&SaveResult<cryptauth::FinishEnrollmentResponse>,
387 &result_proto),
388 base::Bind(&NotCalled<const std::string&>));
390 cryptauth::FinishEnrollmentRequest expected_request;
391 EXPECT_TRUE(expected_request.ParseFromString(serialized_request_));
392 EXPECT_EQ(kEnrollmentSessionId, expected_request.enrollment_session_id());
393 EXPECT_EQ(kEnrollmentMessage, expected_request.enrollment_message());
394 EXPECT_EQ(kDeviceEphemeralKey, expected_request.device_ephemeral_key());
397 cryptauth::FinishEnrollmentResponse response_proto;
398 response_proto.set_status("OK");
399 FinishApiCallFlow(&response_proto);
401 EXPECT_EQ("OK", result_proto.status());
404 TEST_F(ProximityAuthCryptAuthClientTest, FetchAccessTokenFailure) {
405 access_token_fetcher_->set_access_token("");
407 std::string error_message;
408 client_->GetMyDevices(cryptauth::GetMyDevicesRequest(),
409 base::Bind(&NotCalled<cryptauth::GetMyDevicesResponse>),
410 base::Bind(&SaveResult<std::string>, &error_message));
412 EXPECT_EQ("Failed to get a valid access token.", error_message);
415 TEST_F(ProximityAuthCryptAuthClientTest, ParseResponseProtoFailure) {
416 ExpectRequest(
417 "https://www.testgoogleapis.com/cryptauth/v1/deviceSync/"
418 "getmydevices?alt=proto");
420 std::string error_message;
421 client_->GetMyDevices(cryptauth::GetMyDevicesRequest(),
422 base::Bind(&NotCalled<cryptauth::GetMyDevicesResponse>),
423 base::Bind(&SaveResult<std::string>, &error_message));
425 flow_result_callback_.Run("Not a valid serialized response message.");
426 EXPECT_EQ("Failed to parse response proto.", error_message);
429 TEST_F(ProximityAuthCryptAuthClientTest,
430 MakeSecondRequestBeforeFirstRequestSucceeds) {
431 ExpectRequest(
432 "https://www.testgoogleapis.com/cryptauth/v1/deviceSync/"
433 "getmydevices?alt=proto");
435 // Make first request.
436 cryptauth::GetMyDevicesResponse result_proto;
437 client_->GetMyDevices(
438 cryptauth::GetMyDevicesRequest(),
439 base::Bind(&SaveResult<cryptauth::GetMyDevicesResponse>, &result_proto),
440 base::Bind(&NotCalled<std::string>));
442 // With request pending, make second request.
444 std::string error_message;
445 client_->FindEligibleUnlockDevices(
446 cryptauth::FindEligibleUnlockDevicesRequest(),
447 base::Bind(&NotCalled<cryptauth::FindEligibleUnlockDevicesResponse>),
448 base::Bind(&SaveResult<std::string>, &error_message));
449 EXPECT_EQ("Client has been used for another request. Do not reuse.",
450 error_message);
453 // Complete first request.
455 cryptauth::GetMyDevicesResponse response_proto;
456 response_proto.add_devices();
457 response_proto.mutable_devices(0)->set_public_key(kPublicKey1);
458 FinishApiCallFlow(&response_proto);
461 ASSERT_EQ(1, result_proto.devices_size());
462 EXPECT_EQ(kPublicKey1, result_proto.devices(0).public_key());
465 TEST_F(ProximityAuthCryptAuthClientTest,
466 MakeSecondRequestBeforeFirstRequestFails) {
467 ExpectRequest(
468 "https://www.testgoogleapis.com/cryptauth/v1/deviceSync/"
469 "getmydevices?alt=proto");
471 // Make first request.
472 std::string error_message;
473 client_->GetMyDevices(cryptauth::GetMyDevicesRequest(),
474 base::Bind(&NotCalled<cryptauth::GetMyDevicesResponse>),
475 base::Bind(&SaveResult<std::string>, &error_message));
477 // With request pending, make second request.
479 std::string error_message;
480 client_->FindEligibleUnlockDevices(
481 cryptauth::FindEligibleUnlockDevicesRequest(),
482 base::Bind(&NotCalled<cryptauth::FindEligibleUnlockDevicesResponse>),
483 base::Bind(&SaveResult<std::string>, &error_message));
484 EXPECT_EQ("Client has been used for another request. Do not reuse.",
485 error_message);
488 // Fail first request.
489 std::string kStatus429Error = "HTTP status: 429";
490 FailApiCallFlow(kStatus429Error);
491 EXPECT_EQ(kStatus429Error, error_message);
494 TEST_F(ProximityAuthCryptAuthClientTest,
495 MakeSecondRequestAfterFirstRequestSucceeds) {
496 // Make first request successfully.
498 ExpectRequest(
499 "https://www.testgoogleapis.com/cryptauth/v1/deviceSync/"
500 "getmydevices?alt=proto");
501 cryptauth::GetMyDevicesResponse result_proto;
502 client_->GetMyDevices(
503 cryptauth::GetMyDevicesRequest(),
504 base::Bind(&SaveResult<cryptauth::GetMyDevicesResponse>, &result_proto),
505 base::Bind(&NotCalled<std::string>));
507 cryptauth::GetMyDevicesResponse response_proto;
508 response_proto.add_devices();
509 response_proto.mutable_devices(0)->set_public_key(kPublicKey1);
510 FinishApiCallFlow(&response_proto);
511 ASSERT_EQ(1, result_proto.devices_size());
512 EXPECT_EQ(kPublicKey1, result_proto.devices(0).public_key());
515 // Second request fails.
517 std::string error_message;
518 client_->FindEligibleUnlockDevices(
519 cryptauth::FindEligibleUnlockDevicesRequest(),
520 base::Bind(&NotCalled<cryptauth::FindEligibleUnlockDevicesResponse>),
521 base::Bind(&SaveResult<std::string>, &error_message));
522 EXPECT_EQ("Client has been used for another request. Do not reuse.",
523 error_message);
527 } // namespace proximity_auth