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

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

Issue 2567813002: cros: DBUS client to interact with fingerprint DBUS API. (Closed)
Patch Set: s/BiodBiometricsManagerClient/BiodClient 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
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
Daniel Erat 2017/03/31 04:30:10 2017
sammiequon 2017/03/31 22:52:13 Done.
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_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());
Daniel Erat 2017/03/31 04:30:10 ASSERT_EQ?
sammiequon 2017/03/31 22:52:13 Done.
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 BiodClient::Observer.
59 class TestBiodObserver : public BiodClient::Observer {
60 public:
61 TestBiodObserver() {}
62 ~TestBiodObserver() override {}
63
64 int num_enroll_scan_received() const { return num_enroll_scan_received_; }
Daniel Erat 2017/03/31 04:30:10 s/scan/scans/
sammiequon 2017/03/31 22:52:13 Done.
65 int num_auth_scan_received() const { return num_auth_scan_received_; }
Daniel Erat 2017/03/31 04:30:10 s/scan/scans/
sammiequon 2017/03/31 22:52:13 Done.
66 int num_failure_received() const { return num_failure_received_; }
Daniel Erat 2017/03/31 04:30:11 s/failure/failures/
sammiequon 2017/03/31 22:52:13 Done.
67
68 // BiodClient::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(TestBiodObserver);
89 };
90
91 } // namespace
92
93 class BiodClientTest : public testing::Test {
94 public:
95 BiodClientTest() {}
96 ~BiodClientTest() 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(Invoke(this, &BiodClientTest::ConnectToSignal));
117
118 // |client_|'s Init() method should register methods.
119 EXPECT_CALL(
120 *proxy_.get(),
121 CallMethod(HasMember(biod::kBiometricsManagerStartEnrollSessionMethod),
122 _, _))
123 .WillRepeatedly(Invoke(this, &BiodClientTest::OnCallMethod));
124 EXPECT_CALL(
125 *proxy_.get(),
126 CallMethod(HasMember(biod::kBiometricsManagerGetRecordsForUserMethod),
127 _, _))
128 .WillRepeatedly(Invoke(this, &BiodClientTest::OnCallMethod));
129 EXPECT_CALL(
130 *proxy_.get(),
131 CallMethod(HasMember(biod::kBiometricsManagerDestroyAllRecordsMethod),
132 _, _))
133 .WillRepeatedly(Invoke(this, &BiodClientTest::OnCallMethod));
134 EXPECT_CALL(
135 *proxy_.get(),
136 CallMethod(HasMember(biod::kBiometricsManagerStartAuthSessionMethod), _,
137 _))
138 .WillRepeatedly(Invoke(this, &BiodClientTest::OnCallMethod));
Daniel Erat 2017/03/31 04:30:10 adding a bunch of expectations like this doesn't i
sammiequon 2017/03/31 22:52:13 Done.
139
140 client_.reset(BiodClient::Create(REAL_DBUS_CLIENT_IMPLEMENTATION));
141 client_->Init(bus_.get());
142
143 // Execute callbacks posted by Init().
144 base::RunLoop().RunUntilIdle();
145 }
146
147 protected:
148 // Set the response a method is expected to have when a D-Bus method is
149 // called.
150 void SetExpectedResponse(std::unique_ptr<dbus::Response> response) {
151 expected_response_ = std::move(response);
152 }
153
154 // Synchronously passes |signal| to |client_|'s handler, simulating the signal
155 // from biometrics.
156 void EmitSignal(dbus::Signal* signal) {
157 const std::string signal_name = signal->GetMember();
158 const auto it = signal_callbacks_.find(signal_name);
159 ASSERT_TRUE(it != signal_callbacks_.end())
160 << "Client didn't register for signal " << signal_name;
161 it->second.Run(signal);
162 }
163
164 // Passes a enroll scan done signal to |client_|.
165 void EmitEnrollScanDoneSignal(biod::ScanResult scan_result,
166 bool enroll_session_complete) {
167 dbus::Signal signal(kInterface,
168 biod::kBiometricsManagerEnrollScanDoneSignal);
169 dbus::MessageWriter writer(&signal);
170 writer.AppendUint32(uint32_t{scan_result});
171 writer.AppendBool(enroll_session_complete);
172 EmitSignal(&signal);
173 }
174
175 // Passes a auth scan done signal to |client_|.
176 void EmitAuthScanDoneSignal(biod::ScanResult scan_result,
177 const AuthScanMatches& matches) {
178 dbus::Signal signal(kInterface, biod::kBiometricsManagerAuthScanDoneSignal);
179 dbus::MessageWriter writer(&signal);
180 writer.AppendUint32(uint32_t{scan_result});
181
182 dbus::MessageWriter array_writer(nullptr);
183 writer.OpenArray("{sx}", &array_writer);
184 for (auto& match : matches) {
185 dbus::MessageWriter entry_writer(nullptr);
186 array_writer.OpenDictEntry(&entry_writer);
187 entry_writer.AppendString(match.first);
188 entry_writer.AppendArrayOfStrings(match.second);
189 array_writer.CloseContainer(&entry_writer);
190 }
191 writer.CloseContainer(&array_writer);
192 EmitSignal(&signal);
193 }
194
195 // Passes a scan failed signal to |client_|.
196 void EmitScanFailedSignal() {
Daniel Erat 2017/03/31 04:30:11 i don't see this getting called
sammiequon 2017/03/31 22:52:13 Done.
197 dbus::Signal signal(kInterface,
198 biod::kBiometricsManagerSessionFailedSignal);
199 EmitSignal(&signal);
200 }
201
202 std::unique_ptr<dbus::Response> expected_response_ = nullptr;
203
204 base::MessageLoop message_loop_;
205
206 // Mock bus and proxy for simulating calls.
207 scoped_refptr<dbus::MockBus> bus_;
208 scoped_refptr<dbus::MockObjectProxy> proxy_;
209
210 std::unique_ptr<BiodClient> client_;
211
212 // Maps from biod signal name to the corresponding callback provided by
213 // |client_|.
214 std::map<std::string, dbus::ObjectProxy::SignalCallback> signal_callbacks_;
215
216 private:
217 // Handles calls to |proxy_|'s ConnectToSignal() method.
218 void ConnectToSignal(
219 const std::string& interface_name,
220 const std::string& signal_name,
221 dbus::ObjectProxy::SignalCallback signal_callback,
222 dbus::ObjectProxy::OnConnectedCallback on_connected_callback) {
223 EXPECT_EQ(interface_name, kInterface);
224 signal_callbacks_[signal_name] = signal_callback;
225 message_loop_.task_runner()->PostTask(
226 FROM_HERE, base::Bind(on_connected_callback, interface_name,
227 signal_name, true /* success */));
228 }
229
230 // Handles calls to |proxy_|'s CallMethod().
231 void OnCallMethod(dbus::MethodCall* method_call,
232 int timeout_ms,
233 const dbus::ObjectProxy::ResponseCallback& callback) {
234 message_loop_.task_runner()->PostTask(
235 FROM_HERE, base::Bind(&RunResponseCallback, callback,
236 base::Passed(&expected_response_)));
237 }
238
239 DISALLOW_COPY_AND_ASSIGN(BiodClientTest);
240 };
241
242 TEST_F(BiodClientTest, TestStartEnrollSession) {
243 const std::string fake_id("fakeId");
Daniel Erat 2017/03/31 04:30:11 kFakeId, kFakeLabel, etc. https://google.github.i
sammiequon 2017/03/31 22:52:13 Done.
244 const std::string fake_label("fakeLabel");
245 const dbus::ObjectPath fake_object_path(std::string("/fake/object/path"));
246
247 std::unique_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
248 dbus::MessageWriter writer(response.get());
249 writer.AppendObjectPath(fake_object_path);
250
251 // Create a fake response with a fake object path. The start enroll
252 // call should return this object path.
253 SetExpectedResponse(std::move(response));
254 client_->StartEnrollSession(
255 fake_id, fake_label,
256 base::Bind(&CheckObjectPathCallback, fake_object_path));
Daniel Erat 2017/03/31 04:30:11 how about making the callback instead save the pat
sammiequon 2017/03/31 22:52:13 I tried using a unique ptr but I couldn't bind as
257 base::RunLoop().RunUntilIdle();
258
259 // Verify that by sending a empty reponse or a improperly formatted one, the
260 // response is an empty object path. Also, logs will get printed.
261 SetExpectedResponse(nullptr);
262 client_->StartEnrollSession(
263 fake_id, fake_label,
264 base::Bind(&CheckObjectPathCallback, dbus::ObjectPath()));
265 base::RunLoop().RunUntilIdle();
266
267 std::unique_ptr<dbus::Response> bad_response(dbus::Response::CreateEmpty());
268 dbus::MessageWriter bad_writer(bad_response.get());
269 bad_writer.AppendString("");
270 SetExpectedResponse(std::move(bad_response));
271 client_->StartEnrollSession(
272 fake_id, fake_label,
273 base::Bind(&CheckObjectPathCallback, dbus::ObjectPath()));
274 base::RunLoop().RunUntilIdle();
275 }
276
277 TEST_F(BiodClientTest, TestGetRecordsForUser) {
278 const std::string fake_id("fakeId");
279 const dbus::ObjectPath fake_object_path(std::string("/fake/object/path"));
280 const dbus::ObjectPath fake_object_path2(std::string("/fake/object/path2"));
281 const std::vector<dbus::ObjectPath> fake_object_paths = {fake_object_path,
282 fake_object_path2};
283
284 std::unique_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
285 dbus::MessageWriter writer(response.get());
286 writer.AppendArrayOfObjectPaths(fake_object_paths);
287
288 // Create a fake response with an array of fake object paths. The get
289 // enrollments call should return this array of object paths.
290 SetExpectedResponse(std::move(response));
291 client_->GetRecordsForUser(
292 fake_id, base::Bind(&CheckObjectPathArrayCallback, fake_object_paths));
293 base::RunLoop().RunUntilIdle();
294
295 // Verify that by sending a empty reponse the response is an empty array of
296 // object paths. Also, logs will get printed.
297 SetExpectedResponse(nullptr);
298 client_->GetRecordsForUser(fake_id,
299 base::Bind(&CheckObjectPathArrayCallback,
300 std::vector<dbus::ObjectPath>()));
301 base::RunLoop().RunUntilIdle();
302 }
303
304 TEST_F(BiodClientTest, TestDestroyAllRecords) {
305 std::unique_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
306
307 SetExpectedResponse(std::move(response));
308 client_->DestroyAllRecords();
309 base::RunLoop().RunUntilIdle();
Daniel Erat 2017/03/31 04:30:10 this isn't verifying anything right now, i don't t
sammiequon 2017/03/31 22:52:13 Done.
310 }
311
312 TEST_F(BiodClientTest, TestStartAuthentication) {
313 const dbus::ObjectPath fake_object_path(std::string("/fake/object/path"));
314
315 // Create a fake response with a fake object path. The start authentication
316 // call should return this object path.
317 std::unique_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
318 dbus::MessageWriter writer(response.get());
319 writer.AppendObjectPath(fake_object_path);
320
321 SetExpectedResponse(std::move(response));
322 client_->StartAuthSession(
323 base::Bind(&CheckObjectPathCallback, fake_object_path));
324 base::RunLoop().RunUntilIdle();
325
326 // Verify that by sending a empty reponse or a improperly formatted one, the
327 // response is an empty object path. Also, logs will get printed.
328 SetExpectedResponse(nullptr);
329 client_->StartAuthSession(
330 base::Bind(&CheckObjectPathCallback, dbus::ObjectPath()));
331 base::RunLoop().RunUntilIdle();
332
333 std::unique_ptr<dbus::Response> bad_response(dbus::Response::CreateEmpty());
334 dbus::MessageWriter bad_writer(bad_response.get());
335 bad_writer.AppendString("");
336 SetExpectedResponse(std::move(bad_response));
337 client_->StartAuthSession(
338 base::Bind(&CheckObjectPathCallback, dbus::ObjectPath()));
339 base::RunLoop().RunUntilIdle();
340 }
341
342 // Verify when enroll scan done signals are mocked, observer(s) catch the
343 // signals as expected.
344 TEST_F(BiodClientTest, TestEnrollScanDoneObserver) {
345 TestBiodObserver observer1;
346 TestBiodObserver observer2;
347 client_->AddObserver(&observer1);
348
349 const biod::ScanResult scan_signal = biod::ScanResult::SCAN_RESULT_SUCCESS;
350 const bool enroll_session_complete = false;
351 EmitEnrollScanDoneSignal(scan_signal, enroll_session_complete);
352 EXPECT_EQ(1, observer1.num_enroll_scan_received());
353 EXPECT_EQ(0, observer2.num_enroll_scan_received());
354
355 client_->AddObserver(&observer2);
356 EmitEnrollScanDoneSignal(scan_signal, enroll_session_complete);
357 EXPECT_EQ(2, observer1.num_enroll_scan_received());
358 EXPECT_EQ(1, observer2.num_enroll_scan_received());
359
360 client_->RemoveObserver(&observer1);
361 EmitEnrollScanDoneSignal(scan_signal, enroll_session_complete);
362 EXPECT_EQ(2, observer1.num_enroll_scan_received());
363 EXPECT_EQ(2, observer2.num_enroll_scan_received());
364 }
365
366 // Verify when auth scan done signals are mocked, observer(s) catch the signals
367 // as expected.
368 TEST_F(BiodClientTest, TestAuthScanDoneObserver) {
369 TestBiodObserver observer1;
370 TestBiodObserver observer2;
371 client_->AddObserver(&observer1);
372
373 const biod::ScanResult scan_signal = biod::ScanResult::SCAN_RESULT_SUCCESS;
374 const AuthScanMatches test_attempt;
375 EmitAuthScanDoneSignal(scan_signal, test_attempt);
376 EXPECT_EQ(1, observer1.num_auth_scan_received());
377 EXPECT_EQ(0, observer2.num_auth_scan_received());
378
379 client_->AddObserver(&observer2);
Daniel Erat 2017/03/31 04:30:11 this second observer doesn't seem useful. how woul
sammiequon 2017/03/31 22:52:13 Done.
380 EmitAuthScanDoneSignal(scan_signal, test_attempt);
381 EXPECT_EQ(2, observer1.num_auth_scan_received());
382 EXPECT_EQ(1, observer2.num_auth_scan_received());
383
384 client_->RemoveObserver(&observer1);
385 EmitAuthScanDoneSignal(scan_signal, test_attempt);
386 EXPECT_EQ(2, observer1.num_auth_scan_received());
387 EXPECT_EQ(2, observer2.num_auth_scan_received());
388 }
389 } // namespace chromeos
OLDNEW
« chromeos/dbus/biod/biod_client.cc ('K') | « chromeos/dbus/biod/biod_client.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698