Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1012)

Side by Side Diff: components/proximity_auth/cryptauth/cryptauth_client_unittest.cc

Issue 738593002: Introduce CryptAuthClient, a class capable of performing all CryptAuth APIs. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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.
4
5 #include "components/proximity_auth/cryptauth/cryptauth_client.h"
6
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/switches.h"
12 #include "net/url_request/test_url_fetcher_factory.h"
13 #include "net/url_request/url_request_test_util.h"
14 #include "testing/gmock/include/gmock/gmock.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16
17 using testing::_;
18 using testing::DoAll;
19 using testing::Return;
20 using testing::SaveArg;
21 using testing::NiceMock;
22
23 namespace proximity_auth {
24
25 namespace {
26
27 const char kTestGoogleApisUrl[] = "https://www.testgoogleapis.com";
28 const char kAccessToken[] = "access_token";
29 const char kPublicKey1[] = "public_key1";
30 const char kPublicKey2[] = "public_key2";
31 const char kBluetoothAddress1[] = "AA:AA:AA:AA:AA:AA";
32 const char kBluetoothAddress2[] = "BB:BB:BB:BB:BB:BB";
33
34 // CryptAuthAccessTokenFetcher implementation simply returning a predetermined
35 // access token.
36 class FakeCryptAuthAccessTokenFetcher : public CryptAuthAccessTokenFetcher {
37 public:
38 FakeCryptAuthAccessTokenFetcher() : access_token_(kAccessToken) {}
39
40 void FetchAccessToken(const AccessTokenCallback& callback) override {
41 callback.Run(access_token_);
42 }
43
44 void set_access_token(const std::string& access_token) {
45 access_token_ = access_token;
46 };
47
48 private:
49 std::string access_token_;
50 };
51
52 // Mock CryptAuthApiCallFlow, which handles the HTTP requests to CryptAuth.
53 class MockCryptAuthApiCallFlow : public CryptAuthApiCallFlow {
54 public:
55 MockCryptAuthApiCallFlow() : CryptAuthApiCallFlow(GURL(std::string())) {}
56 virtual ~MockCryptAuthApiCallFlow() {}
57
58 MOCK_METHOD5(Start,
59 void(net::URLRequestContextGetter* context,
60 const std::string& access_token,
61 const std::string& serialized_request,
62 ResultCallback result_callback,
63 ErrorCallback error_callback));
64
65 private:
66 DISALLOW_COPY_AND_ASSIGN(MockCryptAuthApiCallFlow);
67 };
68
69 // Subclass of CryptAuthClient to use as test harness.
70 class MockCryptAuthClient : public CryptAuthClient {
71 public:
72 MockCryptAuthClient(net::URLRequestContextGetter* url_request_context,
73 CryptAuthAccessTokenFetcher* access_token_fetcher)
74 : CryptAuthClient(url_request_context, access_token_fetcher) {}
75 virtual ~MockCryptAuthClient() {}
76
77 MOCK_METHOD1(CreateFlow, CryptAuthApiCallFlow*(GURL request_url));
78
79 private:
80 DISALLOW_COPY_AND_ASSIGN(MockCryptAuthClient);
81 };
82
83 // Callback that should never be invoked.
84 template <class T>
85 void NotCalled(const T& type) {
86 EXPECT_TRUE(false);
87 }
88
89 // Callback that saves the result returned by CryptAuthClient.
90 template <class T>
91 void SaveResult(T* out, const T& result) {
92 // static assert
93 *out = result;
94 }
95
96 } // namespace
97
98 class ProximityAuthCryptAuthClientTest : public testing::Test {
99 protected:
100 ProximityAuthCryptAuthClientTest()
101 : url_request_context_(
102 new net::TestURLRequestContextGetter(new base::NullTaskRunner())),
103 serialized_request_("") {}
104 virtual ~ProximityAuthCryptAuthClientTest() {}
105
106 void SetUp() override {
107 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
108 switches::kCryptAuthGoogleApisUrl, kTestGoogleApisUrl);
109
110 client_.reset(new NiceMock<MockCryptAuthClient>(url_request_context_.get(),
111 &access_token_fetcher_));
112 }
113
114 // Sets up an expectation and captures a CryptAuth API request to
115 // |request_url|.
116 void ExpectRequest(const std::string& request_url) {
117 NiceMock<MockCryptAuthApiCallFlow>* api_call_flow =
118 new NiceMock<MockCryptAuthApiCallFlow>();
119
120 EXPECT_CALL(*client_, CreateFlow(GURL(request_url)))
121 .WillOnce(Return(api_call_flow));
122
123 EXPECT_CALL(*api_call_flow,
124 Start(url_request_context_.get(), kAccessToken, _, _, _))
125 .WillOnce(DoAll(SaveArg<2>(&serialized_request_),
126 SaveArg<3>(&flow_result_callback_),
127 SaveArg<4>(&flow_error_callback_)));
128 }
129
130 // Returns |response_proto| as the result to the current API request.
131 // ExpectResult() must have been called first.
132 void FinishApiCallFlow(const google::protobuf::MessageLite* response_proto) {
133 std::string serialized_proto;
134 response_proto->SerializeToString(&serialized_proto);
135 flow_result_callback_.Run(serialized_proto);
136 }
137
138 // Ends the current API request with |error_message|. ExpectResult() must have
139 // been called first.
140 void FailApiCallFlow(const std::string& error_message) {
141 flow_error_callback_.Run(error_message);
142 }
143
144 protected:
145 scoped_refptr<net::URLRequestContextGetter> url_request_context_;
146 FakeCryptAuthAccessTokenFetcher access_token_fetcher_;
147 scoped_ptr<NiceMock<MockCryptAuthClient>> client_;
148
149 std::string serialized_request_;
150 CryptAuthApiCallFlow::ResultCallback flow_result_callback_;
151 CryptAuthApiCallFlow::ErrorCallback flow_error_callback_;
152 };
153
154 TEST_F(ProximityAuthCryptAuthClientTest, GetMyDevicesSuccess) {
155 ExpectRequest(
156 "https://www.testgoogleapis.com/cryptauth/v1/deviceSync/"
157 "getmydevices?alt=proto");
158
159 cryptauth::GetMyDevicesResponse result_proto;
160 client_->GetMyDevices(
161 true,
162 base::Bind(&SaveResult<cryptauth::GetMyDevicesResponse>, &result_proto),
163 base::Bind(&NotCalled<const std::string&>));
164
165 cryptauth::GetMyDevicesRequest request;
166 EXPECT_TRUE(request.ParseFromString(serialized_request_));
167 EXPECT_TRUE(request.allow_stale_read());
168
169 // Return two devices, one unlock key and one unlockable device.
170 {
171 cryptauth::GetMyDevicesResponse response_proto;
172 response_proto.add_devices();
173 response_proto.mutable_devices(0)->set_public_key(kPublicKey1);
174 response_proto.mutable_devices(0)->set_unlock_key(true);
175 response_proto.mutable_devices(0)
176 ->set_bluetooth_address(kBluetoothAddress1);
177 response_proto.add_devices();
178 response_proto.mutable_devices(1)->set_public_key(kPublicKey2);
179 response_proto.mutable_devices(1)->set_unlockable(true);
180 FinishApiCallFlow(&response_proto);
181 }
182
183 // Check that the result received in callback is the same as the response.
184 ASSERT_EQ(2, result_proto.devices_size());
185 EXPECT_EQ(kPublicKey1, result_proto.devices(0).public_key());
186 EXPECT_TRUE(result_proto.devices(0).unlock_key());
187 EXPECT_EQ(kBluetoothAddress1, result_proto.devices(0).bluetooth_address());
188 EXPECT_EQ(kPublicKey2, result_proto.devices(1).public_key());
189 EXPECT_TRUE(result_proto.devices(1).unlockable());
190 }
191
192 TEST_F(ProximityAuthCryptAuthClientTest, GetMyDevicesFailure) {
193 ExpectRequest(
194 "https://www.testgoogleapis.com/cryptauth/v1/deviceSync/"
195 "getmydevices?alt=proto");
196
197 std::string error_message;
198 client_->GetMyDevices(true,
199 base::Bind(&NotCalled<cryptauth::GetMyDevicesResponse>),
200 base::Bind(&SaveResult<std::string>, &error_message));
201
202 std::string kStatus500Error("HTTP status: 500");
203 FailApiCallFlow(kStatus500Error);
204 EXPECT_EQ(kStatus500Error, error_message);
205 }
206
207 TEST_F(ProximityAuthCryptAuthClientTest, FindEligibleUnlockDevicesSuccess) {
208 ExpectRequest(
209 "https://www.testgoogleapis.com/cryptauth/v1/deviceSync/"
210 "findeligibleunlockdevices?alt=proto");
211
212 cryptauth::FindEligibleUnlockDevicesResponse result_proto;
213 client_->FindEligibleUnlockDevices(
214 kBluetoothAddress2,
215 base::Bind(&SaveResult<cryptauth::FindEligibleUnlockDevicesResponse>,
216 &result_proto),
217 base::Bind(&NotCalled<const std::string&>));
218
219 cryptauth::FindEligibleUnlockDevicesRequest request;
220 EXPECT_TRUE(request.ParseFromString(serialized_request_));
221 EXPECT_EQ(kBluetoothAddress2, request.callback_bluetooth_address());
222
223 // Return a response proto with one eligible and one ineligible device.
224 cryptauth::FindEligibleUnlockDevicesResponse response_proto;
225 response_proto.add_eligible_devices();
226 response_proto.mutable_eligible_devices(0)->set_public_key(kPublicKey1);
227
228 const std::string kIneligibilityReason = "You require more vespine gas.";
229 response_proto.add_ineligible_devices();
230 response_proto.mutable_ineligible_devices(0)
231 ->mutable_device()
232 ->set_public_key(kPublicKey2);
233 response_proto.mutable_ineligible_devices(0)
234 ->add_reasons(kIneligibilityReason);
235 FinishApiCallFlow(&response_proto);
236
237 // Check that the result received in callback is the same as the response.
238 ASSERT_EQ(1, result_proto.eligible_devices_size());
239 EXPECT_EQ(kPublicKey1, result_proto.eligible_devices(0).public_key());
240 ASSERT_EQ(1, result_proto.ineligible_devices_size());
241 EXPECT_EQ(kPublicKey2,
242 result_proto.ineligible_devices(0).device().public_key());
243 ASSERT_EQ(1, result_proto.ineligible_devices(0).reasons_size());
244 EXPECT_EQ(kIneligibilityReason,
245 result_proto.ineligible_devices(0).reasons(0));
246 }
247
248 TEST_F(ProximityAuthCryptAuthClientTest, FindEligibleUnlockDevicesFailure) {
249 ExpectRequest(
250 "https://www.testgoogleapis.com/cryptauth/v1/deviceSync/"
251 "findeligibleunlockdevices?alt=proto");
252
253 std::string error_message;
254 client_->FindEligibleUnlockDevices(
255 kBluetoothAddress1,
256 base::Bind(&NotCalled<cryptauth::FindEligibleUnlockDevicesResponse>),
257 base::Bind(&SaveResult<std::string>, &error_message));
258
259 std::string kStatus403Error("HTTP status: 403");
260 FailApiCallFlow(kStatus403Error);
261 EXPECT_EQ(kStatus403Error, error_message);
262 }
263
264 TEST_F(ProximityAuthCryptAuthClientTest, SendDeviceSyncTickleSuccess) {
265 ExpectRequest(
266 "https://www.testgoogleapis.com/cryptauth/v1/deviceSync/"
267 "senddevicesynctickle?alt=proto");
268
269 cryptauth::SendDeviceSyncTickleResponse result_proto;
270 client_->SendDeviceSyncTickle(
271 base::Bind(&SaveResult<cryptauth::SendDeviceSyncTickleResponse>,
272 &result_proto),
273 base::Bind(&NotCalled<const std::string&>));
274
275 cryptauth::SendDeviceSyncTickleRequest request;
276 EXPECT_TRUE(request.ParseFromString(serialized_request_));
277
278 cryptauth::SendDeviceSyncTickleResponse response_proto;
279 FinishApiCallFlow(&response_proto);
280 }
281
282 TEST_F(ProximityAuthCryptAuthClientTest, ToggleEasyUnlockSuccess) {
283 ExpectRequest(
284 "https://www.testgoogleapis.com/cryptauth/v1/deviceSync/"
285 "toggleeasyunlock?alt=proto");
286
287 cryptauth::ToggleEasyUnlockResponse result_proto;
288 client_->ToggleEasyUnlock(
289 true, false, kPublicKey1,
290 base::Bind(&SaveResult<cryptauth::ToggleEasyUnlockResponse>,
291 &result_proto),
292 base::Bind(&NotCalled<const std::string&>));
293
294 cryptauth::ToggleEasyUnlockRequest request;
295 EXPECT_TRUE(request.ParseFromString(serialized_request_));
296 EXPECT_TRUE(request.enable());
297 EXPECT_EQ(kPublicKey1, request.public_key());
298 EXPECT_FALSE(request.apply_to_all());
299
300 cryptauth::ToggleEasyUnlockResponse response_proto;
301 FinishApiCallFlow(&response_proto);
302 }
303
304 TEST_F(ProximityAuthCryptAuthClientTest, SetupEnrollmentSuccess) {
305 ExpectRequest(
306 "https://www.testgoogleapis.com/cryptauth/v1/enrollment/"
307 "setupenrollment?alt=proto");
308
309 std::string kApplicationId = "mkaes";
310 std::vector<std::string> supported_protocols;
311 supported_protocols.push_back("gcmV1");
312 supported_protocols.push_back("testProtocol");
313
314 cryptauth::SetupEnrollmentResponse result_proto;
315 client_->SetupEnrollment(
316 kApplicationId, supported_protocols,
317 base::Bind(&SaveResult<cryptauth::SetupEnrollmentResponse>,
318 &result_proto),
319 base::Bind(&NotCalled<const std::string&>));
320
321 cryptauth::SetupEnrollmentRequest request;
322 EXPECT_TRUE(request.ParseFromString(serialized_request_));
323 EXPECT_EQ(kApplicationId, request.application_id());
324 ASSERT_EQ(2, request.types_size());
325 EXPECT_EQ("gcmV1", request.types(0));
326 EXPECT_EQ("testProtocol", request.types(1));
327
328 // Return a fake enrollment session.
329 {
330 cryptauth::SetupEnrollmentResponse response_proto;
331 response_proto.set_status("OK");
332 response_proto.add_infos();
333 response_proto.mutable_infos(0)->set_type("gcmV1");
334 response_proto.mutable_infos(0)->set_enrollment_session_id("session_id");
335 response_proto.mutable_infos(0)->set_server_ephemeral_key("ephemeral_key");
336 FinishApiCallFlow(&response_proto);
337 }
338
339 // Check that the returned proto is the same as the one just created.
340 EXPECT_EQ("OK", result_proto.status());
341 ASSERT_EQ(1, result_proto.infos_size());
342 EXPECT_EQ("gcmV1", result_proto.infos(0).type());
343 EXPECT_EQ("session_id", result_proto.infos(0).enrollment_session_id());
344 EXPECT_EQ("ephemeral_key", result_proto.infos(0).server_ephemeral_key());
345 }
346
347 TEST_F(ProximityAuthCryptAuthClientTest, FinishEnrollmentSuccess) {
348 ExpectRequest(
349 "https://www.testgoogleapis.com/cryptauth/v1/enrollment/"
350 "finishenrollment?alt=proto");
351
352 const char kEnrollmentSessionId[] = "enrollment_session_id";
353 const char kEnrollmentMessage[] = "enrollment_message";
354 const char kDeviceEphemeralKey[] = "device_ephermal_key";
355 cryptauth::FinishEnrollmentResponse result_proto;
356 client_->FinishEnrollment(
357 kEnrollmentSessionId, kEnrollmentMessage, kDeviceEphemeralKey,
358 base::Bind(&SaveResult<cryptauth::FinishEnrollmentResponse>,
359 &result_proto),
360 base::Bind(&NotCalled<const std::string&>));
361
362 cryptauth::FinishEnrollmentRequest request;
363 EXPECT_TRUE(request.ParseFromString(serialized_request_));
364 EXPECT_EQ(kEnrollmentSessionId, request.enrollment_session_id());
365 EXPECT_EQ(kEnrollmentMessage, request.enrollment_message());
366 EXPECT_EQ(kDeviceEphemeralKey, request.device_ephemeral_key());
367
368 {
369 cryptauth::FinishEnrollmentResponse response_proto;
370 response_proto.set_status("OK");
371 FinishApiCallFlow(&response_proto);
372 }
373 EXPECT_EQ("OK", result_proto.status());
374 }
375
376 TEST_F(ProximityAuthCryptAuthClientTest, FetchAccessTokenFailure) {
377 access_token_fetcher_.set_access_token("");
378
379 std::string error_message;
380 client_->GetMyDevices(true,
381 base::Bind(&NotCalled<cryptauth::GetMyDevicesResponse>),
382 base::Bind(&SaveResult<std::string>, &error_message));
383
384 EXPECT_EQ("Failed to get a valid access token", error_message);
385 }
386
387 TEST_F(ProximityAuthCryptAuthClientTest, MakeRequestWhenOldRequestPending) {
388 ExpectRequest(
389 "https://www.testgoogleapis.com/cryptauth/v1/deviceSync/"
390 "getmydevices?alt=proto");
391
392 // Make first request.
393 cryptauth::GetMyDevicesResponse result_proto;
394 client_->GetMyDevices(
395 false,
396 base::Bind(&SaveResult<cryptauth::GetMyDevicesResponse>, &result_proto),
397 base::Bind(&NotCalled<const std::string&>));
398
399 // With request pending, make second request.
400 std::string error_message;
401 client_->FindEligibleUnlockDevices(
402 kBluetoothAddress2,
403 base::Bind(&NotCalled<cryptauth::FindEligibleUnlockDevicesResponse>),
404 base::Bind(&SaveResult<std::string>, &error_message));
405 EXPECT_EQ("Another request in progress", error_message);
406
407 // Complete first request.
408 {
409 cryptauth::GetMyDevicesResponse response_proto;
410 response_proto.add_devices();
411 response_proto.mutable_devices(0)->set_public_key(kPublicKey1);
412 FinishApiCallFlow(&response_proto);
413 }
414
415 ASSERT_EQ(1, result_proto.devices_size());
416 EXPECT_EQ(kPublicKey1, result_proto.devices(0).public_key());
417 }
418
419 TEST_F(ProximityAuthCryptAuthClientTest, MakeRequestAfterOldRequestFinishes) {
420 {
421 // Make first request successfully.
422 ExpectRequest(
423 "https://www.testgoogleapis.com/cryptauth/v1/deviceSync/"
424 "getmydevices?alt=proto");
425 cryptauth::GetMyDevicesResponse result_proto;
426 client_->GetMyDevices(
427 false,
428 base::Bind(&SaveResult<cryptauth::GetMyDevicesResponse>, &result_proto),
429 base::Bind(&NotCalled<const std::string&>));
430
431 cryptauth::GetMyDevicesResponse response_proto;
432 response_proto.add_devices();
433 response_proto.mutable_devices(0)->set_public_key(kPublicKey1);
434 FinishApiCallFlow(&response_proto);
435 ASSERT_EQ(1, result_proto.devices_size());
436 EXPECT_EQ(kPublicKey1, result_proto.devices(0).public_key());
437 }
438 {
439 // Make second request successfully.
440 cryptauth::FindEligibleUnlockDevicesResponse result_proto;
441 ExpectRequest(
442 "https://www.testgoogleapis.com/cryptauth/v1/deviceSync/"
443 "findeligibleunlockdevices?alt=proto");
444 client_->FindEligibleUnlockDevices(
445 kBluetoothAddress2,
446 base::Bind(&SaveResult<cryptauth::FindEligibleUnlockDevicesResponse>,
447 &result_proto),
448 base::Bind(&NotCalled<const std::string&>));
449
450 cryptauth::FindEligibleUnlockDevicesResponse response_proto;
451 response_proto.add_eligible_devices();
452 response_proto.mutable_eligible_devices(0)->set_public_key(kPublicKey2);
453 FinishApiCallFlow(&response_proto);
454 ASSERT_EQ(1, result_proto.eligible_devices_size());
455 EXPECT_EQ(kPublicKey2, result_proto.eligible_devices(0).public_key());
456 }
457 }
458
459 } // namespace proximity_auth
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698