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

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 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/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"
17
18 using testing::_;
19 using testing::DoAll;
20 using testing::Return;
21 using testing::SaveArg;
22 using testing::NiceMock;
23
24 namespace proximity_auth {
25
26 namespace {
27
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";
34
35 // CryptAuthAccessTokenFetcher implementation simply returning a predetermined
36 // access token.
37 class FakeCryptAuthAccessTokenFetcher : public CryptAuthAccessTokenFetcher {
38 public:
39 FakeCryptAuthAccessTokenFetcher() : access_token_(kAccessToken) {}
40
41 void FetchAccessToken(const AccessTokenCallback& callback) override {
42 callback.Run(access_token_);
43 }
44
45 void set_access_token(const std::string& access_token) {
46 access_token_ = access_token;
47 };
48
49 private:
50 std::string access_token_;
51 };
52
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() {}
58
59 MOCK_METHOD5(Start,
60 void(net::URLRequestContextGetter* context,
61 const std::string& access_token,
62 const std::string& serialized_request,
63 ResultCallback result_callback,
64 ErrorCallback error_callback));
Ilya Sherman 2014/12/03 03:16:37 Hmm, how come the callbacks aren't passed by const
Tim Song 2014/12/05 00:00:36 Done.
65
66 private:
67 DISALLOW_COPY_AND_ASSIGN(MockCryptAuthApiCallFlow);
68 };
69
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.
Ilya Sherman 2014/12/03 03:16:37 Hmm, could you clarify how gmock is involved here?
Tim Song 2014/12/05 00:00:36 It's for the same reason I think. The definition o
Ilya Sherman 2014/12/05 00:14:20 Oh, I see, because we wrap this class in a NiceMoc
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() {}
82
83 MOCK_METHOD1(CreateFlow, CryptAuthApiCallFlow*(const GURL& request_url));
Ilya Sherman 2014/12/03 03:16:37 I'm wondering if the reason you made CreateFlow re
Tim Song 2014/12/05 00:00:36 Done.
84
85 private:
86 DISALLOW_COPY_AND_ASSIGN(MockCryptAuthClient);
87 };
88
89 // Callback that should never be invoked.
90 template <class T>
91 void NotCalled(const T& type) {
92 EXPECT_TRUE(false);
93 }
94
95 // Callback that saves the result returned by CryptAuthClient.
96 template <class T>
97 void SaveResult(T* out, const T& result) {
98 // static assert
Ilya Sherman 2014/12/03 03:16:37 I don't follow what this comment means -- could yo
Tim Song 2014/12/05 00:00:36 Sorry, that comment was accidentally left in.
99 *out = result;
100 }
101
102 } // namespace
103
104 class ProximityAuthCryptAuthClientTest : public testing::Test {
105 protected:
106 ProximityAuthCryptAuthClientTest()
107 : access_token_fetcher_(new FakeCryptAuthAccessTokenFetcher()),
108 url_request_context_(
109 new net::TestURLRequestContextGetter(new base::NullTaskRunner())),
110 serialized_request_("") {}
Ilya Sherman 2014/12/03 03:16:37 nit: Please prefer std::string() to "".
Tim Song 2014/12/05 00:00:36 Done.
111 virtual ~ProximityAuthCryptAuthClientTest() {}
112
113 void SetUp() override {
114 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
115 switches::kCryptAuthHTTPHost, kTestGoogleApisUrl);
116
117 client_.reset(new NiceMock<MockCryptAuthClient>(access_token_fetcher_,
Ilya Sherman 2014/12/03 03:16:37 nit: Any reason not to use a StrictMock? Are ther
Tim Song 2014/12/05 00:00:36 Done.
118 url_request_context_));
119 }
120
121 // Sets up an expectation and captures a CryptAuth API request to
122 // |request_url|.
123 void ExpectRequest(const std::string& request_url) {
124 NiceMock<MockCryptAuthApiCallFlow>* api_call_flow =
125 new NiceMock<MockCryptAuthApiCallFlow>();
126
127 EXPECT_CALL(*client_, CreateFlow(GURL(request_url)))
128 .WillOnce(Return(api_call_flow));
129
130 EXPECT_CALL(*api_call_flow,
131 Start(url_request_context_.get(), kAccessToken, _, _, _))
132 .WillOnce(DoAll(SaveArg<2>(&serialized_request_),
133 SaveArg<3>(&flow_result_callback_),
134 SaveArg<4>(&flow_error_callback_)));
135 }
136
137 // Returns |response_proto| as the result to the current API request.
138 // ExpectResult() must have been called first.
139 void FinishApiCallFlow(const google::protobuf::MessageLite* response_proto) {
140 std::string serialized_proto;
141 response_proto->SerializeToString(&serialized_proto);
Ilya Sherman 2014/12/03 03:16:37 nit: I think you can use "SerializeAsString" to sa
Tim Song 2014/12/05 00:00:36 Done.
142 flow_result_callback_.Run(serialized_proto);
143 }
144
145 // Ends the current API request with |error_message|. ExpectResult() must have
146 // been called first.
147 void FailApiCallFlow(const std::string& error_message) {
148 flow_error_callback_.Run(error_message);
149 }
150
151 protected:
152 // Owned by |client_|.
153 FakeCryptAuthAccessTokenFetcher* access_token_fetcher_;
154
155 scoped_refptr<net::URLRequestContextGetter> url_request_context_;
156 scoped_ptr<NiceMock<MockCryptAuthClient>> client_;
157
158 std::string serialized_request_;
159 CryptAuthApiCallFlow::ResultCallback flow_result_callback_;
160 CryptAuthApiCallFlow::ErrorCallback flow_error_callback_;
161 };
162
163 TEST_F(ProximityAuthCryptAuthClientTest, GetMyDevicesSuccess) {
164 ExpectRequest(
165 "https://www.testgoogleapis.com/cryptauth/v1/deviceSync/"
166 "getmydevices?alt=proto");
167
168 cryptauth::GetMyDevicesResponse result_proto;
169 cryptauth::GetMyDevicesRequest request_proto;
170 request_proto.set_allow_stale_read(true);
171 client_->GetMyDevices(
172 request_proto,
173 base::Bind(&SaveResult<cryptauth::GetMyDevicesResponse>, &result_proto),
174 base::Bind(&NotCalled<std::string>));
175
176 cryptauth::GetMyDevicesRequest expected_request;
177 EXPECT_TRUE(expected_request.ParseFromString(serialized_request_));
178 EXPECT_TRUE(expected_request.allow_stale_read());
179
180 // Return two devices, one unlock key and one unlockable device.
181 {
182 cryptauth::GetMyDevicesResponse response_proto;
183 response_proto.add_devices();
184 response_proto.mutable_devices(0)->set_public_key(kPublicKey1);
185 response_proto.mutable_devices(0)->set_unlock_key(true);
186 response_proto.mutable_devices(0)
187 ->set_bluetooth_address(kBluetoothAddress1);
188 response_proto.add_devices();
189 response_proto.mutable_devices(1)->set_public_key(kPublicKey2);
190 response_proto.mutable_devices(1)->set_unlockable(true);
191 FinishApiCallFlow(&response_proto);
192 }
193
194 // Check that the result received in callback is the same as the response.
195 ASSERT_EQ(2, result_proto.devices_size());
196 EXPECT_EQ(kPublicKey1, result_proto.devices(0).public_key());
197 EXPECT_TRUE(result_proto.devices(0).unlock_key());
198 EXPECT_EQ(kBluetoothAddress1, result_proto.devices(0).bluetooth_address());
199 EXPECT_EQ(kPublicKey2, result_proto.devices(1).public_key());
200 EXPECT_TRUE(result_proto.devices(1).unlockable());
201 }
202
203 TEST_F(ProximityAuthCryptAuthClientTest, GetMyDevicesFailure) {
204 ExpectRequest(
205 "https://www.testgoogleapis.com/cryptauth/v1/deviceSync/"
206 "getmydevices?alt=proto");
207
208 std::string error_message;
209 client_->GetMyDevices(cryptauth::GetMyDevicesRequest(),
210 base::Bind(&NotCalled<cryptauth::GetMyDevicesResponse>),
211 base::Bind(&SaveResult<std::string>, &error_message));
212
213 std::string kStatus500Error("HTTP status: 500");
214 FailApiCallFlow(kStatus500Error);
215 EXPECT_EQ(kStatus500Error, error_message);
216 }
217
218 TEST_F(ProximityAuthCryptAuthClientTest, FindEligibleUnlockDevicesSuccess) {
219 ExpectRequest(
220 "https://www.testgoogleapis.com/cryptauth/v1/deviceSync/"
221 "findeligibleunlockdevices?alt=proto");
222
223 cryptauth::FindEligibleUnlockDevicesResponse result_proto;
224 cryptauth::FindEligibleUnlockDevicesRequest request_proto;
225 request_proto.set_callback_bluetooth_address(kBluetoothAddress2);
226 client_->FindEligibleUnlockDevices(
227 request_proto,
228 base::Bind(&SaveResult<cryptauth::FindEligibleUnlockDevicesResponse>,
229 &result_proto),
230 base::Bind(&NotCalled<std::string>));
231
232 cryptauth::FindEligibleUnlockDevicesRequest expected_request;
233 EXPECT_TRUE(expected_request.ParseFromString(serialized_request_));
234 EXPECT_EQ(kBluetoothAddress2, expected_request.callback_bluetooth_address());
235
236 // Return a response proto with one eligible and one ineligible device.
237 cryptauth::FindEligibleUnlockDevicesResponse response_proto;
238 response_proto.add_eligible_devices();
239 response_proto.mutable_eligible_devices(0)->set_public_key(kPublicKey1);
240
241 const std::string kIneligibilityReason = "You require more vespine gas.";
Ilya Sherman 2014/12/03 03:16:37 :)
242 response_proto.add_ineligible_devices();
243 response_proto.mutable_ineligible_devices(0)
244 ->mutable_device()
245 ->set_public_key(kPublicKey2);
246 response_proto.mutable_ineligible_devices(0)
247 ->add_reasons(kIneligibilityReason);
248 FinishApiCallFlow(&response_proto);
249
250 // Check that the result received in callback is the same as the response.
251 ASSERT_EQ(1, result_proto.eligible_devices_size());
252 EXPECT_EQ(kPublicKey1, result_proto.eligible_devices(0).public_key());
253 ASSERT_EQ(1, result_proto.ineligible_devices_size());
254 EXPECT_EQ(kPublicKey2,
255 result_proto.ineligible_devices(0).device().public_key());
256 ASSERT_EQ(1, result_proto.ineligible_devices(0).reasons_size());
257 EXPECT_EQ(kIneligibilityReason,
258 result_proto.ineligible_devices(0).reasons(0));
259 }
260
261 TEST_F(ProximityAuthCryptAuthClientTest, FindEligibleUnlockDevicesFailure) {
262 ExpectRequest(
263 "https://www.testgoogleapis.com/cryptauth/v1/deviceSync/"
264 "findeligibleunlockdevices?alt=proto");
265
266 std::string error_message;
267 cryptauth::FindEligibleUnlockDevicesRequest request_proto;
268 request_proto.set_callback_bluetooth_address(kBluetoothAddress1);
269 client_->FindEligibleUnlockDevices(
270 request_proto,
271 base::Bind(&NotCalled<cryptauth::FindEligibleUnlockDevicesResponse>),
272 base::Bind(&SaveResult<std::string>, &error_message));
273
274 std::string kStatus403Error("HTTP status: 403");
275 FailApiCallFlow(kStatus403Error);
276 EXPECT_EQ(kStatus403Error, error_message);
277 }
278
279 TEST_F(ProximityAuthCryptAuthClientTest, SendDeviceSyncTickleSuccess) {
280 ExpectRequest(
281 "https://www.testgoogleapis.com/cryptauth/v1/deviceSync/"
282 "senddevicesynctickle?alt=proto");
283
284 cryptauth::SendDeviceSyncTickleResponse result_proto;
285 client_->SendDeviceSyncTickle(
286 cryptauth::SendDeviceSyncTickleRequest(),
287 base::Bind(&SaveResult<cryptauth::SendDeviceSyncTickleResponse>,
288 &result_proto),
289 base::Bind(&NotCalled<std::string>));
290
291 cryptauth::SendDeviceSyncTickleRequest expected_request;
292 EXPECT_TRUE(expected_request.ParseFromString(serialized_request_));
293
294 cryptauth::SendDeviceSyncTickleResponse response_proto;
295 FinishApiCallFlow(&response_proto);
296 }
297
298 TEST_F(ProximityAuthCryptAuthClientTest, ToggleEasyUnlockSuccess) {
299 ExpectRequest(
300 "https://www.testgoogleapis.com/cryptauth/v1/deviceSync/"
301 "toggleeasyunlock?alt=proto");
302
303 cryptauth::ToggleEasyUnlockResponse result_proto;
304 cryptauth::ToggleEasyUnlockRequest request_proto;
305 request_proto.set_enable(true);
306 request_proto.set_apply_to_all(false);
307 request_proto.set_public_key(kPublicKey1);
308 client_->ToggleEasyUnlock(
309 request_proto,
310 base::Bind(&SaveResult<cryptauth::ToggleEasyUnlockResponse>,
311 &result_proto),
312 base::Bind(&NotCalled<std::string>));
313
314 cryptauth::ToggleEasyUnlockRequest expected_request;
315 EXPECT_TRUE(expected_request.ParseFromString(serialized_request_));
316 EXPECT_TRUE(expected_request.enable());
317 EXPECT_EQ(kPublicKey1, expected_request.public_key());
318 EXPECT_FALSE(expected_request.apply_to_all());
319
320 cryptauth::ToggleEasyUnlockResponse response_proto;
321 FinishApiCallFlow(&response_proto);
322 }
323
324 TEST_F(ProximityAuthCryptAuthClientTest, SetupEnrollmentSuccess) {
325 ExpectRequest(
326 "https://www.testgoogleapis.com/cryptauth/v1/enrollment/"
327 "setupenrollment?alt=proto");
328
329 std::string kApplicationId = "mkaes";
330 std::vector<std::string> supported_protocols;
331 supported_protocols.push_back("gcmV1");
332 supported_protocols.push_back("testProtocol");
333
334 cryptauth::SetupEnrollmentResponse result_proto;
335 cryptauth::SetupEnrollmentRequest request_proto;
336 request_proto.set_application_id(kApplicationId);
337 request_proto.add_types("gcmV1");
338 request_proto.add_types("testProtocol");
339 client_->SetupEnrollment(
340 request_proto, base::Bind(&SaveResult<cryptauth::SetupEnrollmentResponse>,
341 &result_proto),
342 base::Bind(&NotCalled<std::string>));
343
344 cryptauth::SetupEnrollmentRequest expected_request;
345 EXPECT_TRUE(expected_request.ParseFromString(serialized_request_));
346 EXPECT_EQ(kApplicationId, expected_request.application_id());
347 ASSERT_EQ(2, expected_request.types_size());
348 EXPECT_EQ("gcmV1", expected_request.types(0));
349 EXPECT_EQ("testProtocol", expected_request.types(1));
350
351 // Return a fake enrollment session.
352 {
353 cryptauth::SetupEnrollmentResponse response_proto;
354 response_proto.set_status("OK");
355 response_proto.add_infos();
356 response_proto.mutable_infos(0)->set_type("gcmV1");
357 response_proto.mutable_infos(0)->set_enrollment_session_id("session_id");
358 response_proto.mutable_infos(0)->set_server_ephemeral_key("ephemeral_key");
359 FinishApiCallFlow(&response_proto);
360 }
361
362 // Check that the returned proto is the same as the one just created.
363 EXPECT_EQ("OK", result_proto.status());
364 ASSERT_EQ(1, result_proto.infos_size());
365 EXPECT_EQ("gcmV1", result_proto.infos(0).type());
366 EXPECT_EQ("session_id", result_proto.infos(0).enrollment_session_id());
367 EXPECT_EQ("ephemeral_key", result_proto.infos(0).server_ephemeral_key());
368 }
369
370 TEST_F(ProximityAuthCryptAuthClientTest, FinishEnrollmentSuccess) {
371 ExpectRequest(
372 "https://www.testgoogleapis.com/cryptauth/v1/enrollment/"
373 "finishenrollment?alt=proto");
374
375 const char kEnrollmentSessionId[] = "enrollment_session_id";
376 const char kEnrollmentMessage[] = "enrollment_message";
377 const char kDeviceEphemeralKey[] = "device_ephermal_key";
378 cryptauth::FinishEnrollmentResponse result_proto;
379 cryptauth::FinishEnrollmentRequest request_proto;
380 request_proto.set_enrollment_session_id(kEnrollmentSessionId);
381 request_proto.set_enrollment_message(kEnrollmentMessage);
382 request_proto.set_device_ephemeral_key(kDeviceEphemeralKey);
383 client_->FinishEnrollment(
384 request_proto,
385 base::Bind(&SaveResult<cryptauth::FinishEnrollmentResponse>,
386 &result_proto),
387 base::Bind(&NotCalled<const std::string&>));
388
389 cryptauth::FinishEnrollmentRequest expected_request;
390 EXPECT_TRUE(expected_request.ParseFromString(serialized_request_));
391 EXPECT_EQ(kEnrollmentSessionId, expected_request.enrollment_session_id());
392 EXPECT_EQ(kEnrollmentMessage, expected_request.enrollment_message());
393 EXPECT_EQ(kDeviceEphemeralKey, expected_request.device_ephemeral_key());
394
395 {
396 cryptauth::FinishEnrollmentResponse response_proto;
397 response_proto.set_status("OK");
398 FinishApiCallFlow(&response_proto);
399 }
400 EXPECT_EQ("OK", result_proto.status());
401 }
402
403 TEST_F(ProximityAuthCryptAuthClientTest, FetchAccessTokenFailure) {
404 access_token_fetcher_->set_access_token("");
405
406 std::string error_message;
407 client_->GetMyDevices(cryptauth::GetMyDevicesRequest(),
408 base::Bind(&NotCalled<cryptauth::GetMyDevicesResponse>),
409 base::Bind(&SaveResult<std::string>, &error_message));
410
411 EXPECT_EQ("Failed to get a valid access token", error_message);
412 }
413
414 TEST_F(ProximityAuthCryptAuthClientTest,
415 MakeSecondRequestBeforeFirstRequestSucceeds) {
416 ExpectRequest(
417 "https://www.testgoogleapis.com/cryptauth/v1/deviceSync/"
418 "getmydevices?alt=proto");
419
420 // Make first request.
421 cryptauth::GetMyDevicesResponse result_proto;
422 client_->GetMyDevices(
423 cryptauth::GetMyDevicesRequest(),
424 base::Bind(&SaveResult<cryptauth::GetMyDevicesResponse>, &result_proto),
425 base::Bind(&NotCalled<std::string>));
426
427 // With request pending, make second request.
428 {
429 std::string error_message;
430 client_->FindEligibleUnlockDevices(
431 cryptauth::FindEligibleUnlockDevicesRequest(),
432 base::Bind(&NotCalled<cryptauth::FindEligibleUnlockDevicesResponse>),
433 base::Bind(&SaveResult<std::string>, &error_message));
434 EXPECT_EQ("Client has been used for another request. Do not reuse.",
435 error_message);
436 }
437
438 // Complete first request.
439 {
440 cryptauth::GetMyDevicesResponse response_proto;
441 response_proto.add_devices();
442 response_proto.mutable_devices(0)->set_public_key(kPublicKey1);
443 FinishApiCallFlow(&response_proto);
444 }
445
446 ASSERT_EQ(1, result_proto.devices_size());
447 EXPECT_EQ(kPublicKey1, result_proto.devices(0).public_key());
448 }
449
450 TEST_F(ProximityAuthCryptAuthClientTest,
451 MakeSecondRequestBeforeFirstRequestFails) {
452 ExpectRequest(
453 "https://www.testgoogleapis.com/cryptauth/v1/deviceSync/"
454 "getmydevices?alt=proto");
455
456 // Make first request.
457 std::string error_message;
458 client_->GetMyDevices(cryptauth::GetMyDevicesRequest(),
459 base::Bind(&NotCalled<cryptauth::GetMyDevicesResponse>),
460 base::Bind(&SaveResult<std::string>, &error_message));
461
462 // With request pending, make second request.
463 {
464 std::string error_message;
465 client_->FindEligibleUnlockDevices(
466 cryptauth::FindEligibleUnlockDevicesRequest(),
467 base::Bind(&NotCalled<cryptauth::FindEligibleUnlockDevicesResponse>),
468 base::Bind(&SaveResult<std::string>, &error_message));
469 EXPECT_EQ("Client has been used for another request. Do not reuse.",
470 error_message);
471 }
472
473 // Fail first request.
474 std::string kStatus429Error = "HTTP status: 429";
475 FailApiCallFlow(kStatus429Error);
476 EXPECT_EQ(kStatus429Error, error_message);
477 }
478
479 TEST_F(ProximityAuthCryptAuthClientTest,
480 MakeSecondRequestAfterFirstRequestSucceeds) {
481 // Make first request successfully.
482 {
483 ExpectRequest(
484 "https://www.testgoogleapis.com/cryptauth/v1/deviceSync/"
485 "getmydevices?alt=proto");
486 cryptauth::GetMyDevicesResponse result_proto;
487 client_->GetMyDevices(
488 cryptauth::GetMyDevicesRequest(),
489 base::Bind(&SaveResult<cryptauth::GetMyDevicesResponse>, &result_proto),
490 base::Bind(&NotCalled<std::string>));
491
492 cryptauth::GetMyDevicesResponse response_proto;
493 response_proto.add_devices();
494 response_proto.mutable_devices(0)->set_public_key(kPublicKey1);
495 FinishApiCallFlow(&response_proto);
496 ASSERT_EQ(1, result_proto.devices_size());
497 EXPECT_EQ(kPublicKey1, result_proto.devices(0).public_key());
498 }
499
500 // Second request fails.
501 {
502 std::string error_message;
503 client_->FindEligibleUnlockDevices(
504 cryptauth::FindEligibleUnlockDevicesRequest(),
505 base::Bind(&NotCalled<cryptauth::FindEligibleUnlockDevicesResponse>),
506 base::Bind(&SaveResult<std::string>, &error_message));
507 EXPECT_EQ("Client has been used for another request. Do not reuse.",
508 error_message);
509 }
510 }
511
512 } // namespace proximity_auth
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698