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

Side by Side Diff: chromeos/dbus/biod/biod_biometrics_manager_client_unittest.cc

Issue 2567813002: cros: DBUS client to interact with fingerprint DBUS API. (Closed)
Patch Set: Addressed comments. Created 3 years, 8 months 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
« no previous file with comments | « chromeos/dbus/biod/biod_biometrics_manager_client.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2016 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 "chromeos/dbus/biod/biod_biometrics_manager_client.h"
6
7 #include <map>
8 #include <string>
9
10 #include "base/bind.h"
11 #include "base/run_loop.h"
12 #include "dbus/mock_bus.h"
13 #include "dbus/mock_object_proxy.h"
14 #include "dbus/object_path.h"
15 #include "testing/gmock/include/gmock/gmock.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 using ::testing::_;
19 using ::testing::Invoke;
20 using ::testing::Return;
21
22 namespace chromeos {
23
24 namespace {
25
26 // Shorthand for a commonly-used constant.
27 const char* kInterface = biod::kBiometricsManagerInterface;
28
29 void CheckObjectPathCallback(const dbus::ObjectPath& expected_object_path,
30 const dbus::ObjectPath& object_path) {
31 EXPECT_EQ(expected_object_path, object_path);
32 }
33
34 void CheckObjectPathArrayCallback(
35 const std::vector<dbus::ObjectPath>& expected_object_paths,
36 const std::vector<dbus::ObjectPath>& object_paths) {
37 CHECK_EQ(expected_object_paths.size(), object_paths.size());
38 for (size_t i = 0; i < expected_object_paths.size(); ++i)
39 EXPECT_EQ(expected_object_paths[i], object_paths[i]);
40 }
41
42 // Matcher that verifies that a dbus::Message has member |name|.
43 MATCHER_P(HasMember, name, "") {
44 if (arg->GetMember() != name) {
45 *result_listener << "has member " << arg->GetMember();
46 return false;
47 }
48 return true;
49 }
50
51 // Runs |callback| with |response|. Needed due to ResponseCallback expecting a
52 // bare pointer rather than an std::unique_ptr.
53 void RunResponseCallback(dbus::ObjectProxy::ResponseCallback callback,
54 std::unique_ptr<dbus::Response> response) {
55 callback.Run(response.get());
56 }
57
58 // Implementation of BiodBiometricsManagerClient::Observer.
59 class TestBiometricsObserver : public BiodBiometricsManagerClient::Observer {
60 public:
61 TestBiometricsObserver() {}
62 ~TestBiometricsObserver() override {}
63
64 int num_enroll_scan_received() const { return num_enroll_scan_received_; }
65 int num_auth_scan_received() const { return num_auth_scan_received_; }
66 int num_failure_received() const { return num_failure_received_; }
67
68 // BiodBiometricsManagerClient::Observer:
69 void BiodServiceRestarted() override {}
70
71 void BiodEnrollScanDoneReceived(biod::ScanResult scan_result,
72 bool enroll_sesion_complete) override {
73 num_enroll_scan_received_++;
74 }
75
76 void BiodAuthScanDoneReceived(biod::ScanResult scan_result,
77 const AuthScanMatches& matches) override {
78 num_auth_scan_received_++;
79 }
80
81 void BiodSessionFailedReceived() override { num_failure_received_++; }
82
83 private:
84 int num_enroll_scan_received_ = 0;
85 int num_auth_scan_received_ = 0;
86 int num_failure_received_ = 0;
87
88 DISALLOW_COPY_AND_ASSIGN(TestBiometricsObserver);
89 };
90
91 } // namespace
92
93 class BiodBiometricsManagerClientTest : public testing::Test {
94 public:
95 BiodBiometricsManagerClientTest() {}
96 ~BiodBiometricsManagerClientTest() override {}
97
98 void SetUp() override {
99 dbus::Bus::Options options;
100 options.bus_type = dbus::Bus::SYSTEM;
101 bus_ = new dbus::MockBus(options);
102
103 proxy_ =
104 new dbus::MockObjectProxy(bus_.get(), biod::kBiodServiceName,
105 dbus::ObjectPath(biod::kBiodServicePath));
106
107 // |client_|'s Init() method should request a proxy for communicating with
108 // biometrics api.
109 EXPECT_CALL(*bus_.get(),
110 GetObjectProxy(biod::kBiodServiceName,
111 dbus::ObjectPath(biod::kBiodServicePath)))
112 .WillRepeatedly(Return(proxy_.get()));
113
114 // Save |client_|'s signal callback.
115 EXPECT_CALL(*proxy_.get(), ConnectToSignal(kInterface, _, _, _))
116 .WillRepeatedly(
117 Invoke(this, &BiodBiometricsManagerClientTest::ConnectToSignal));
118
119 // |client_|'s Init() method should register methods.
120 EXPECT_CALL(
121 *proxy_.get(),
122 CallMethod(HasMember(biod::kBiometricsManagerStartEnrollSessionMethod),
123 _, _))
124 .WillRepeatedly(
125 Invoke(this, &BiodBiometricsManagerClientTest::OnCallMethod));
126 EXPECT_CALL(
127 *proxy_.get(),
128 CallMethod(HasMember(biod::kBiometricsManagerGetRecordsForUserMethod),
129 _, _))
130 .WillRepeatedly(
131 Invoke(this, &BiodBiometricsManagerClientTest::OnCallMethod));
132 EXPECT_CALL(
133 *proxy_.get(),
134 CallMethod(HasMember(biod::kBiometricsManagerDestroyAllRecordsMethod),
135 _, _))
136 .WillRepeatedly(
137 Invoke(this, &BiodBiometricsManagerClientTest::OnCallMethod));
138 EXPECT_CALL(
139 *proxy_.get(),
140 CallMethod(HasMember(biod::kBiometricsManagerStartAuthSessionMethod), _,
141 _))
142 .WillRepeatedly(
143 Invoke(this, &BiodBiometricsManagerClientTest::OnCallMethod));
144
145 client_.reset(
146 BiodBiometricsManagerClient::Create(REAL_DBUS_CLIENT_IMPLEMENTATION));
147 client_->Init(bus_.get());
148
149 // Execute callbacks posted by Init().
150 base::RunLoop().RunUntilIdle();
151 }
152
153 protected:
154 // Set the response a method is expected to have when a D-Bus method is
155 // called.
156 void SetExpectedResponse(std::unique_ptr<dbus::Response> response) {
157 expected_response_ = std::move(response);
158 }
159
160 // Synchronously passes |signal| to |client_|'s handler, simulating the signal
161 // from biometrics.
162 void EmitSignal(dbus::Signal* signal) {
163 const std::string signal_name = signal->GetMember();
164 const auto it = signal_callbacks_.find(signal_name);
165 ASSERT_TRUE(it != signal_callbacks_.end())
166 << "Client didn't register for signal " << signal_name;
167 it->second.Run(signal);
168 }
169
170 // Passes a enroll scan done signal to |client_|.
171 void EmitEnrollScanDoneSignal(biod::ScanResult scan_result,
172 bool enroll_session_complete) {
173 dbus::Signal signal(kInterface,
174 biod::kBiometricsManagerEnrollScanDoneSignal);
175 dbus::MessageWriter writer(&signal);
176 writer.AppendUint32(uint32_t{scan_result});
177 writer.AppendBool(enroll_session_complete);
178 EmitSignal(&signal);
179 }
180
181 // Passes a auth scan done signal to |client_|.
182 void EmitAuthScanDoneSignal(biod::ScanResult scan_result,
183 const AuthScanMatches& matches) {
184 dbus::Signal signal(kInterface, biod::kBiometricsManagerAuthScanDoneSignal);
185 dbus::MessageWriter writer(&signal);
186 writer.AppendUint32(uint32_t{scan_result});
187
188 dbus::MessageWriter array_writer(nullptr);
189 writer.OpenArray("{sx}", &array_writer);
190 for (auto& match : matches) {
191 dbus::MessageWriter entry_writer(nullptr);
192 array_writer.OpenDictEntry(&entry_writer);
193 entry_writer.AppendString(match.first);
194 entry_writer.AppendArrayOfStrings(match.second);
195 array_writer.CloseContainer(&entry_writer);
196 }
197 writer.CloseContainer(&array_writer);
198 EmitSignal(&signal);
199 }
200
201 // Passes a scan failed signal to |client_|.
202 void EmitScanFailedSignal() {
203 dbus::Signal signal(kInterface,
204 biod::kBiometricsManagerSessionFailedSignal);
205 EmitSignal(&signal);
206 }
207
208 std::unique_ptr<dbus::Response> expected_response_ = nullptr;
209
210 base::MessageLoop message_loop_;
211
212 // Mock bus and proxy for simulating calls.
213 scoped_refptr<dbus::MockBus> bus_;
214 scoped_refptr<dbus::MockObjectProxy> proxy_;
215
216 std::unique_ptr<BiodBiometricsManagerClient> client_;
217
218 // Maps from biod signal name to the corresponding callback provided by
219 // |client_|.
220 std::map<std::string, dbus::ObjectProxy::SignalCallback> signal_callbacks_;
221
222 private:
223 // Handles calls to |proxy_|'s ConnectToSignal() method.
224 void ConnectToSignal(
225 const std::string& interface_name,
226 const std::string& signal_name,
227 dbus::ObjectProxy::SignalCallback signal_callback,
228 dbus::ObjectProxy::OnConnectedCallback on_connected_callback) {
229 EXPECT_EQ(interface_name, kInterface);
230 signal_callbacks_[signal_name] = signal_callback;
231 message_loop_.task_runner()->PostTask(
232 FROM_HERE, base::Bind(on_connected_callback, interface_name,
233 signal_name, true /* success */));
234 }
235
236 // Handles calls to |proxy_|'s CallMethod().
237 void OnCallMethod(dbus::MethodCall* method_call,
238 int timeout_ms,
239 const dbus::ObjectProxy::ResponseCallback& callback) {
240 message_loop_.task_runner()->PostTask(
241 FROM_HERE, base::Bind(&RunResponseCallback, callback,
242 base::Passed(&expected_response_)));
243 }
244
245 DISALLOW_COPY_AND_ASSIGN(BiodBiometricsManagerClientTest);
246 };
247
248 TEST_F(BiodBiometricsManagerClientTest, TestStartEnrollSession) {
249 const std::string fake_id("fakeId");
250 const std::string fake_label("fakeLabel");
251 const dbus::ObjectPath fake_object_path(std::string("/fake/object/path"));
252
253 std::unique_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
254 dbus::MessageWriter writer(response.get());
255 writer.AppendObjectPath(fake_object_path);
256
257 // Create a fake response with a fake object path. The start enroll
258 // call should return this object path.
259 SetExpectedResponse(std::move(response));
260 client_->StartEnrollSession(
261 fake_id, fake_label,
262 base::Bind(&CheckObjectPathCallback, fake_object_path));
263 base::RunLoop().RunUntilIdle();
264
265 // Verify that by sending a empty reponse or a improperly formatted one, the
266 // response is an empty object path. Also, logs will get printed.
267 SetExpectedResponse(nullptr);
268 client_->StartEnrollSession(
269 fake_id, fake_label,
270 base::Bind(&CheckObjectPathCallback, dbus::ObjectPath()));
271 base::RunLoop().RunUntilIdle();
272
273 std::unique_ptr<dbus::Response> bad_response(dbus::Response::CreateEmpty());
274 dbus::MessageWriter bad_writer(bad_response.get());
275 bad_writer.AppendString("");
276 SetExpectedResponse(std::move(bad_response));
277 client_->StartEnrollSession(
278 fake_id, fake_label,
279 base::Bind(&CheckObjectPathCallback, dbus::ObjectPath()));
280 base::RunLoop().RunUntilIdle();
281 }
282
283 TEST_F(BiodBiometricsManagerClientTest, TestGetRecordsForUser) {
284 const std::string fake_id("fakeId");
285 const dbus::ObjectPath fake_object_path(std::string("/fake/object/path"));
286 const dbus::ObjectPath fake_object_path2(std::string("/fake/object/path2"));
287 const std::vector<dbus::ObjectPath> fake_object_paths = {fake_object_path,
288 fake_object_path2};
289
290 std::unique_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
291 dbus::MessageWriter writer(response.get());
292 writer.AppendArrayOfObjectPaths(fake_object_paths);
293
294 // Create a fake response with an array of fake object paths. The get
295 // enrollments call should return this array of object paths.
296 SetExpectedResponse(std::move(response));
297 client_->GetRecordsForUser(
298 fake_id, base::Bind(&CheckObjectPathArrayCallback, fake_object_paths));
299 base::RunLoop().RunUntilIdle();
300
301 // Verify that by sending a empty reponse the response is an empty array of
302 // object paths. Also, logs will get printed.
303 SetExpectedResponse(nullptr);
304 client_->GetRecordsForUser(fake_id,
305 base::Bind(&CheckObjectPathArrayCallback,
306 std::vector<dbus::ObjectPath>()));
307 base::RunLoop().RunUntilIdle();
308 }
309
310 TEST_F(BiodBiometricsManagerClientTest, TestDestroyAllRecords) {
311 std::unique_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
312
313 SetExpectedResponse(std::move(response));
314 client_->DestroyAllRecords();
315 base::RunLoop().RunUntilIdle();
316 }
317
318 TEST_F(BiodBiometricsManagerClientTest, TestStartAuthentication) {
319 const dbus::ObjectPath fake_object_path(std::string("/fake/object/path"));
320
321 // Create a fake response with a fake object path. The start authentication
322 // call should return this object path.
323 std::unique_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
324 dbus::MessageWriter writer(response.get());
325 writer.AppendObjectPath(fake_object_path);
326
327 SetExpectedResponse(std::move(response));
328 client_->StartAuthSession(
329 base::Bind(&CheckObjectPathCallback, fake_object_path));
330 base::RunLoop().RunUntilIdle();
331
332 // Verify that by sending a empty reponse or a improperly formatted one, the
333 // response is an empty object path. Also, logs will get printed.
334 SetExpectedResponse(nullptr);
335 client_->StartAuthSession(
336 base::Bind(&CheckObjectPathCallback, dbus::ObjectPath()));
337 base::RunLoop().RunUntilIdle();
338
339 std::unique_ptr<dbus::Response> bad_response(dbus::Response::CreateEmpty());
340 dbus::MessageWriter bad_writer(bad_response.get());
341 bad_writer.AppendString("");
342 SetExpectedResponse(std::move(bad_response));
343 client_->StartAuthSession(
344 base::Bind(&CheckObjectPathCallback, dbus::ObjectPath()));
345 base::RunLoop().RunUntilIdle();
346 }
347
348 // Verify when enroll scan done signals are mocked, observer(s) catch the
349 // signals as expected.
350 TEST_F(BiodBiometricsManagerClientTest, TestEnrollScanDoneObserver) {
351 TestBiometricsObserver observer1;
352 TestBiometricsObserver observer2;
353 client_->AddObserver(&observer1);
354
355 const biod::ScanResult scan_signal = biod::ScanResult::SCAN_RESULT_SUCCESS;
356 const bool enroll_session_complete = false;
357 EmitEnrollScanDoneSignal(scan_signal, enroll_session_complete);
358 EXPECT_EQ(1, observer1.num_enroll_scan_received());
359 EXPECT_EQ(0, observer2.num_enroll_scan_received());
360
361 client_->AddObserver(&observer2);
362 EmitEnrollScanDoneSignal(scan_signal, enroll_session_complete);
363 EXPECT_EQ(2, observer1.num_enroll_scan_received());
364 EXPECT_EQ(1, observer2.num_enroll_scan_received());
365
366 client_->RemoveObserver(&observer1);
367 EmitEnrollScanDoneSignal(scan_signal, enroll_session_complete);
368 EXPECT_EQ(2, observer1.num_enroll_scan_received());
369 EXPECT_EQ(2, observer2.num_enroll_scan_received());
370 }
371
372 // Verify when auth scan done signals are mocked, observer(s) catch the signals
373 // as expected.
374 TEST_F(BiodBiometricsManagerClientTest, TestAuthScanDoneObserver) {
375 TestBiometricsObserver observer1;
376 TestBiometricsObserver observer2;
377 client_->AddObserver(&observer1);
378
379 const biod::ScanResult scan_signal = biod::ScanResult::SCAN_RESULT_SUCCESS;
380 const AuthScanMatches test_attempt;
381 EmitAuthScanDoneSignal(scan_signal, test_attempt);
382 EXPECT_EQ(1, observer1.num_auth_scan_received());
383 EXPECT_EQ(0, observer2.num_auth_scan_received());
384
385 client_->AddObserver(&observer2);
386 EmitAuthScanDoneSignal(scan_signal, test_attempt);
387 EXPECT_EQ(2, observer1.num_auth_scan_received());
388 EXPECT_EQ(1, observer2.num_auth_scan_received());
389
390 client_->RemoveObserver(&observer1);
391 EmitAuthScanDoneSignal(scan_signal, test_attempt);
392 EXPECT_EQ(2, observer1.num_auth_scan_received());
393 EXPECT_EQ(2, observer2.num_auth_scan_received());
394 }
395 } // namespace chromeos
OLDNEW
« no previous file with comments | « chromeos/dbus/biod/biod_biometrics_manager_client.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698