Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2017 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/fake_biod_client.h" | |
|
Daniel Erat
2017/04/07 18:27:56
add a blank line after this one
sammiequon
2017/04/07 20:45:51
Done.
| |
| 6 #include "base/bind.h" | |
| 7 #include "base/macros.h" | |
| 8 #include "base/test/test_simple_task_runner.h" | |
| 9 #include "base/threading/thread_task_runner_handle.h" | |
| 10 #include "dbus/object_path.h" | |
| 11 #include "testing/gtest/include/gtest/gtest.h" | |
| 12 | |
| 13 namespace chromeos { | |
| 14 | |
| 15 namespace { | |
| 16 | |
| 17 const char kTestUserId[] = "testuser@gmail.com"; | |
| 18 const char kTestLabel[] = "testLabel"; | |
| 19 | |
| 20 void CopyObjectPath(dbus::ObjectPath* dest_path, | |
|
Daniel Erat
2017/04/07 18:27:56
instead of copy-and-pasting code from biod_client_
sammiequon
2017/04/07 20:45:51
Yeah, sorry that should've been obvious. Done.
| |
| 21 const dbus::ObjectPath& src_path) { | |
| 22 CHECK(dest_path); | |
| 23 *dest_path = src_path; | |
| 24 } | |
| 25 | |
| 26 void CopyObjectPathArray( | |
| 27 std::vector<dbus::ObjectPath>* dest_object_paths, | |
| 28 const std::vector<dbus::ObjectPath>& src_object_paths) { | |
| 29 CHECK(dest_object_paths); | |
| 30 *dest_object_paths = src_object_paths; | |
| 31 } | |
| 32 | |
| 33 void CopyNumRecords(int* out_num, | |
| 34 const std::vector<dbus::ObjectPath>& object_path_array) { | |
| 35 CHECK(out_num); | |
| 36 *out_num = int{object_path_array.size()}; | |
|
Daniel Erat
2017/04/07 18:27:56
static_cast
sammiequon
2017/04/07 20:45:51
https://google.github.io/styleguide/cppguide.html#
Daniel Erat
2017/04/07 20:57:25
i think that this is one place where chromium styl
sammiequon
2017/04/07 22:43:55
Understood, I would say those half are mine :S (sm
| |
| 37 } | |
| 38 | |
| 39 void CopyLabel(std::string* expected_label, const std::string& src_label) { | |
| 40 CHECK(expected_label); | |
| 41 *expected_label = src_label; | |
| 42 } | |
| 43 | |
| 44 // Implementation of BiodClient::Observer for testing. | |
| 45 class TestBiometricsObserver : public BiodClient::Observer { | |
|
Daniel Erat
2017/04/07 18:27:56
put this into the utils class as well; it looks li
sammiequon
2017/04/07 20:45:50
Done.
| |
| 46 public: | |
| 47 TestBiometricsObserver() {} | |
| 48 ~TestBiometricsObserver() override {} | |
| 49 | |
| 50 bool CheckExpectedLastAttemptMatches( | |
| 51 const AuthScanMatches& expected_matches) { | |
| 52 return expected_matches == last_auth_scan_matches_; | |
| 53 } | |
| 54 | |
| 55 int num_complete_enroll_scan_received() const { | |
| 56 return num_complete_enroll_scan_received_; | |
| 57 } | |
| 58 | |
| 59 int num_incomplete_enroll_scan_received() const { | |
| 60 return num_incomplete_enroll_scan_received_; | |
| 61 } | |
| 62 | |
| 63 int num_matched_auth_scan_received() const { | |
| 64 return num_matched_auth_scan_received_; | |
| 65 } | |
| 66 | |
| 67 int num_unmatched_auth_scan_received() const { | |
| 68 return num_unmatched_auth_scan_received_; | |
| 69 } | |
| 70 | |
| 71 // BiodClient::Observer: | |
| 72 void BiodServiceRestarted() override {} | |
| 73 | |
| 74 void BiodEnrollScanDoneReceived(biod::ScanResult scan_result, | |
| 75 bool is_complete) override { | |
| 76 is_complete ? num_complete_enroll_scan_received_++ | |
| 77 : num_incomplete_enroll_scan_received_++; | |
| 78 } | |
| 79 | |
| 80 void BiodAuthScanDoneReceived(biod::ScanResult scan_result, | |
| 81 const AuthScanMatches& matches) override { | |
| 82 matches.empty() ? num_unmatched_auth_scan_received_++ | |
| 83 : num_matched_auth_scan_received_++; | |
| 84 last_auth_scan_matches_ = matches; | |
| 85 } | |
| 86 | |
| 87 void BiodSessionFailedReceived() override { num_failure_received_++; } | |
| 88 | |
| 89 private: | |
| 90 int num_complete_enroll_scan_received_ = 0; | |
| 91 int num_incomplete_enroll_scan_received_ = 0; | |
| 92 int num_matched_auth_scan_received_ = 0; | |
| 93 int num_unmatched_auth_scan_received_ = 0; | |
| 94 int num_failure_received_ = 0; | |
| 95 | |
| 96 // When auth scan is received, store the result. | |
| 97 AuthScanMatches last_auth_scan_matches_; | |
| 98 | |
| 99 DISALLOW_COPY_AND_ASSIGN(TestBiometricsObserver); | |
| 100 }; | |
| 101 | |
| 102 } // namepsace | |
| 103 | |
| 104 class FakeBiodClientTest : public testing::Test { | |
| 105 public: | |
| 106 FakeBiodClientTest() | |
| 107 : task_runner_(new base::TestSimpleTaskRunner), | |
| 108 task_runner_handle_(task_runner_) {} | |
| 109 ~FakeBiodClientTest() override {} | |
| 110 | |
| 111 int NumRecords() { return int{fake_biod_client_.records_.size()}; } | |
|
Daniel Erat
2017/04/07 18:27:56
again, static_cast
sammiequon
2017/04/07 20:45:51
Done.
| |
| 112 | |
| 113 int NumRecords(const std::string& user_id) { | |
| 114 std::vector<dbus::ObjectPath> enrollment_paths; | |
| 115 fake_biod_client_.GetRecordsForUser( | |
| 116 kTestUserId, base::Bind(&CopyObjectPathArray, &enrollment_paths)); | |
| 117 task_runner_->RunUntilIdle(); | |
| 118 return int{enrollment_paths.size()}; | |
|
Daniel Erat
2017/04/07 18:27:56
static_cast
sammiequon
2017/04/07 20:45:51
Done.
| |
| 119 } | |
| 120 | |
| 121 void SendAuthScanDone(char c) { | |
| 122 fake_biod_client_.SendAuthScanDone(c, | |
| 123 biod::ScanResult::SCAN_RESULT_SUCCESS); | |
| 124 } | |
| 125 | |
| 126 // Helper function which enrolls a fingerprint. Each element in | |
| 127 // |fingerprint_data| corresponds to a finger tap. | |
| 128 void EnrollFingerprint(const std::string& id, | |
| 129 const std::string& label, | |
| 130 const std::string& fingerprint_data) { | |
| 131 if (fingerprint_data.size() < 1) | |
| 132 return; | |
| 133 | |
| 134 dbus::ObjectPath returned_path; | |
| 135 fake_biod_client_.StartEnrollSession( | |
| 136 id, label, base::Bind(CopyObjectPath, &returned_path)); | |
| 137 task_runner_->RunUntilIdle(); | |
| 138 EXPECT_NE(returned_path, dbus::ObjectPath()); | |
| 139 | |
| 140 // Send |fingerprint_data| size - 1 incomplete scans. | |
| 141 for (int i = 0; i < int{fingerprint_data.size()} - 1; ++i) { | |
|
Daniel Erat
2017/04/07 18:27:56
static_cast
sammiequon
2017/04/07 20:45:51
Done.
| |
| 142 fake_biod_client_.SendEnrollScanDone( | |
| 143 fingerprint_data[i], biod::ScanResult::SCAN_RESULT_SUCCESS, | |
| 144 false /* is_complete*/); | |
| 145 } | |
| 146 | |
| 147 // Finish the enrollment by sending a complete scan signal. | |
| 148 fake_biod_client_.SendEnrollScanDone(fingerprint_data.back(), | |
| 149 biod::ScanResult::SCAN_RESULT_SUCCESS, | |
| 150 true /*is_complete*/); | |
| 151 } | |
| 152 | |
| 153 // Helper function which enrolls |n| fingerprints with the same |id|, |label| | |
| 154 // and |fingerprint_data|. | |
| 155 void EnrollNTestFingerprints(const std::string& id, | |
| 156 const std::string& label, | |
| 157 const std::string& fingerprint_data, | |
| 158 int n) { | |
| 159 for (int i = 0; i < n; ++i) | |
| 160 EnrollFingerprint(id, label, fingerprint_data); | |
| 161 } | |
| 162 | |
| 163 protected: | |
| 164 FakeBiodClient fake_biod_client_; | |
| 165 scoped_refptr<base::TestSimpleTaskRunner> task_runner_; | |
| 166 base::ThreadTaskRunnerHandle task_runner_handle_; | |
| 167 | |
| 168 private: | |
| 169 DISALLOW_COPY_AND_ASSIGN(FakeBiodClientTest); | |
| 170 }; | |
| 171 | |
| 172 TEST_F(FakeBiodClientTest, TestEnrollSessionWorkflow) { | |
| 173 TestBiometricsObserver observer; | |
| 174 fake_biod_client_.AddObserver(&observer); | |
| 175 | |
| 176 // Verify that successful enrollments gets stored as expected. A fingerprint | |
| 177 // that was created with 3 chars should have 2 incomplete scans and 1 complete | |
| 178 // scans. | |
| 179 EnrollFingerprint(kTestUserId, kTestLabel, "aaa"); | |
| 180 EXPECT_EQ(1, NumRecords()); | |
| 181 EXPECT_EQ(2, observer.num_incomplete_enroll_scan_received()); | |
| 182 EXPECT_EQ(1, observer.num_complete_enroll_scan_received()); | |
| 183 | |
| 184 // Verify that the enroll session worflow can be used repeatedly. A | |
| 185 // fingerprint that was created with 4 chars should have 3 incomplete scans | |
| 186 // and 1 complete scan. | |
| 187 EnrollNTestFingerprints(kTestUserId, kTestLabel, "aaaa", 2); | |
| 188 EXPECT_EQ(3, NumRecords()); | |
| 189 EXPECT_EQ(8, observer.num_incomplete_enroll_scan_received()); | |
| 190 EXPECT_EQ(3, observer.num_complete_enroll_scan_received()); | |
| 191 } | |
| 192 | |
| 193 // Test authentication when one user has one or more fingerprints registered. | |
| 194 // This should be the normal scenario. | |
| 195 TEST_F(FakeBiodClientTest, TestAuthSessionWorkflowSingleUser) { | |
| 196 TestBiometricsObserver observer; | |
| 197 fake_biod_client_.AddObserver(&observer); | |
| 198 EXPECT_EQ(0, NumRecords(kTestUserId)); | |
| 199 | |
| 200 // Add two fingerprints a and b and start an auth session. | |
| 201 EnrollFingerprint(kTestUserId, kTestLabel, "a"); | |
| 202 EnrollFingerprint(kTestUserId, kTestLabel, "b"); | |
| 203 dbus::ObjectPath returned_path; | |
| 204 fake_biod_client_.StartAuthSession( | |
| 205 base::Bind(CopyObjectPath, &returned_path)); | |
| 206 task_runner_->RunUntilIdle(); | |
| 207 EXPECT_NE(returned_path, dbus::ObjectPath()); | |
| 208 | |
| 209 // Verify that by sending two attempts signals of fingerprints that have been | |
| 210 // enrolled, the observer should received two matches and zero unmatches. | |
| 211 SendAuthScanDone('a'); | |
| 212 SendAuthScanDone('b'); | |
| 213 EXPECT_EQ(2, observer.num_matched_auth_scan_received()); | |
| 214 EXPECT_EQ(0, observer.num_unmatched_auth_scan_received()); | |
| 215 | |
| 216 // Verify that by sending two attempts signals of fingerprints that have not | |
| 217 // been enrolled, the observer should received two unmatches and zero | |
| 218 // matches. | |
| 219 SendAuthScanDone('c'); | |
| 220 SendAuthScanDone('d'); | |
| 221 EXPECT_EQ(2, observer.num_matched_auth_scan_received()); | |
| 222 EXPECT_EQ(2, observer.num_unmatched_auth_scan_received()); | |
| 223 } | |
| 224 | |
| 225 // Test authentication when multiple users have fingerprints registered. Cover | |
| 226 // cases such as when both users use the same labels, a user had registered the | |
| 227 // same fingerprint multiple times, or two users use the same fingerprint. | |
| 228 TEST_F(FakeBiodClientTest, TestAuthenticateWorkflowMultipleUsers) { | |
| 229 TestBiometricsObserver observer; | |
| 230 fake_biod_client_.AddObserver(&observer); | |
| 231 EXPECT_EQ(0, NumRecords(kTestUserId)); | |
| 232 | |
| 233 // Add two users, who have scanned three fingers between the two of them. | |
| 234 const std::string& kUserOne = std::string(kTestUserId) + "1"; | |
| 235 const std::string& kUserTwo = std::string(kTestUserId) + "2"; | |
| 236 | |
| 237 const std::string& kLabelOne = std::string(kTestLabel) + "1"; | |
| 238 const std::string& kLabelTwo = std::string(kTestLabel) + "2"; | |
| 239 const std::string& kLabelThree = std::string(kTestLabel) + "3"; | |
| 240 | |
| 241 EnrollFingerprint(kUserOne, kLabelOne, "a"); | |
| 242 EnrollFingerprint(kUserOne, kLabelTwo, "b"); | |
| 243 // User one has registered finger two twice. | |
| 244 EnrollFingerprint(kUserOne, kLabelThree, "b"); | |
| 245 EnrollFingerprint(kUserTwo, kLabelOne, "d"); | |
| 246 EnrollFingerprint(kUserTwo, kLabelTwo, "e"); | |
| 247 // User two has allowed user one to unlock his/her account with his/her first | |
| 248 // finger. | |
| 249 EnrollFingerprint(kUserTwo, kLabelThree, "a"); | |
| 250 | |
| 251 dbus::ObjectPath returned_path; | |
| 252 fake_biod_client_.StartAuthSession( | |
| 253 base::Bind(CopyObjectPath, &returned_path)); | |
| 254 task_runner_->RunUntilIdle(); | |
| 255 EXPECT_NE(returned_path, dbus::ObjectPath()); | |
| 256 | |
| 257 // Verify that if a user registers the same finger to two different labels, | |
| 258 // both labels are returned as matches. | |
| 259 AuthScanMatches expected_auth_scan_matches; | |
| 260 expected_auth_scan_matches[kUserOne] = {kLabelTwo, kLabelThree}; | |
| 261 SendAuthScanDone('b'); | |
| 262 EXPECT_TRUE( | |
| 263 observer.CheckExpectedLastAttemptMatches(expected_auth_scan_matches)); | |
| 264 | |
| 265 // Verify that a fingerprint associated with one user and one label returns a | |
| 266 // match with one user and one label. | |
| 267 expected_auth_scan_matches.clear(); | |
| 268 expected_auth_scan_matches[kUserTwo] = {kLabelOne}; | |
| 269 SendAuthScanDone('d'); | |
| 270 EXPECT_TRUE( | |
| 271 observer.CheckExpectedLastAttemptMatches(expected_auth_scan_matches)); | |
| 272 | |
| 273 // Verify if two users register the same fingerprint, the matches contain both | |
| 274 // users. | |
| 275 expected_auth_scan_matches.clear(); | |
| 276 expected_auth_scan_matches[kUserOne] = {kLabelOne}; | |
| 277 expected_auth_scan_matches[kUserTwo] = {kLabelThree}; | |
| 278 SendAuthScanDone('a'); | |
| 279 EXPECT_TRUE( | |
| 280 observer.CheckExpectedLastAttemptMatches(expected_auth_scan_matches)); | |
| 281 | |
| 282 // Verify if a unregistered finger is scanned, the matches are empty. | |
| 283 expected_auth_scan_matches.clear(); | |
| 284 SendAuthScanDone('f'); | |
| 285 EXPECT_TRUE( | |
| 286 observer.CheckExpectedLastAttemptMatches(expected_auth_scan_matches)); | |
| 287 } | |
| 288 | |
| 289 TEST_F(FakeBiodClientTest, TestGetAllRecords) { | |
| 290 // Verify that initially |kTestUserId| will have no fingerprints. | |
| 291 int num_fingerprints = -1; | |
| 292 fake_biod_client_.GetRecordsForUser( | |
| 293 kTestUserId, base::Bind(&CopyNumRecords, &num_fingerprints)); | |
| 294 task_runner_->RunUntilIdle(); | |
| 295 EXPECT_EQ(0, num_fingerprints); | |
| 296 | |
| 297 // Verify that after enrolling 2 fingerprints, a GetRecords call return 2 | |
| 298 // items. | |
| 299 EnrollNTestFingerprints(kTestUserId, kTestLabel, "aa", 2); | |
| 300 num_fingerprints = -1; | |
| 301 fake_biod_client_.GetRecordsForUser( | |
| 302 kTestUserId, base::Bind(&CopyNumRecords, &num_fingerprints)); | |
| 303 task_runner_->RunUntilIdle(); | |
| 304 EXPECT_EQ(2, num_fingerprints); | |
| 305 | |
| 306 // Verify that GetRecords call for a user with no registered fingerprints | |
| 307 // should return 0 items. | |
| 308 num_fingerprints = -1; | |
| 309 fake_biod_client_.GetRecordsForUser( | |
| 310 "noregisteredginerprints@gmail.com", | |
| 311 base::Bind(&CopyNumRecords, &num_fingerprints)); | |
| 312 task_runner_->RunUntilIdle(); | |
| 313 EXPECT_EQ(0, num_fingerprints); | |
| 314 } | |
| 315 | |
| 316 TEST_F(FakeBiodClientTest, TestDestroyingRecords) { | |
| 317 // Verify that after enrolling 2 fingerprints and destroying them, 0 | |
| 318 // fingerprints will remain. | |
| 319 EnrollNTestFingerprints(kTestUserId, kTestLabel, "aaaa", 2); | |
| 320 EXPECT_EQ(2, NumRecords(kTestUserId)); | |
| 321 fake_biod_client_.DestroyAllRecords(); | |
| 322 EXPECT_EQ(0, NumRecords(kTestUserId)); | |
| 323 } | |
| 324 | |
| 325 TEST_F(FakeBiodClientTest, TestGetAndSetRecordLabels) { | |
| 326 const std::string& kLabelOne = "Finger 1"; | |
| 327 const std::string& kLabelTwo = "Finger 2"; | |
| 328 | |
| 329 EnrollFingerprint(kTestUserId, kLabelOne, "abc"); | |
| 330 EnrollFingerprint(kTestUserId, kLabelTwo, "abc"); | |
| 331 EXPECT_EQ(2, NumRecords(kTestUserId)); | |
| 332 std::vector<dbus::ObjectPath> enrollment_paths; | |
| 333 fake_biod_client_.GetRecordsForUser( | |
| 334 kTestUserId, base::Bind(&CopyObjectPathArray, &enrollment_paths)); | |
| 335 task_runner_->RunUntilIdle(); | |
| 336 EXPECT_EQ(2u, enrollment_paths.size()); | |
| 337 | |
| 338 // Verify the labels we get using GetLabel are the same as the one we | |
| 339 // originally set. | |
| 340 std::string returned_label; | |
| 341 fake_biod_client_.RequestRecordLabel(enrollment_paths[0], | |
| 342 base::Bind(&CopyLabel, &returned_label)); | |
| 343 task_runner_->RunUntilIdle(); | |
| 344 EXPECT_EQ(kLabelOne, returned_label); | |
| 345 | |
| 346 returned_label = ""; | |
| 347 fake_biod_client_.RequestRecordLabel(enrollment_paths[1], | |
| 348 base::Bind(&CopyLabel, &returned_label)); | |
| 349 task_runner_->RunUntilIdle(); | |
| 350 EXPECT_EQ(kLabelTwo, returned_label); | |
| 351 | |
| 352 // Verify that by setting a new label, getting the label will return the value | |
| 353 // of the new label. | |
| 354 const std::string& kNewLabelTwo = "Finger 2 New"; | |
| 355 fake_biod_client_.SetRecordLabel(enrollment_paths[1], kNewLabelTwo); | |
| 356 fake_biod_client_.RequestRecordLabel(enrollment_paths[1], | |
| 357 base::Bind(&CopyLabel, &returned_label)); | |
| 358 task_runner_->RunUntilIdle(); | |
| 359 EXPECT_EQ(kNewLabelTwo, returned_label); | |
| 360 } | |
| 361 | |
| 362 } // namespace chromeos | |
| OLD | NEW |