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" |
| 6 |
| 7 #include "base/bind.h" |
| 8 #include "base/macros.h" |
| 9 #include "base/strings/string_util.h" |
| 10 #include "base/test/test_simple_task_runner.h" |
| 11 #include "base/threading/thread_task_runner_handle.h" |
| 12 #include "chromeos/dbus/biod/test_utils.h" |
| 13 #include "dbus/object_path.h" |
| 14 #include "testing/gtest/include/gtest/gtest.h" |
| 15 |
| 16 namespace chromeos { |
| 17 |
| 18 namespace { |
| 19 |
| 20 const char kTestUserId[] = "testuser@gmail.com"; |
| 21 const char kTestLabel[] = "testLabel"; |
| 22 // Template of a scan string to be used in GenerateTestFingerprint. The # and $ |
| 23 // are two wildcards that will be replaced by numbers to ensure unique scans. |
| 24 const char kTestScan[] = "finger#scan$"; |
| 25 |
| 26 } // namepsace |
| 27 |
| 28 class FakeBiodClientTest : public testing::Test { |
| 29 public: |
| 30 FakeBiodClientTest() |
| 31 : task_runner_(new base::TestSimpleTaskRunner), |
| 32 task_runner_handle_(task_runner_) {} |
| 33 ~FakeBiodClientTest() override {} |
| 34 |
| 35 // Returns the stored records for |user_id|. |
| 36 std::vector<dbus::ObjectPath> GetRecordsForUser(const std::string& user_id) { |
| 37 std::vector<dbus::ObjectPath> enrollment_paths; |
| 38 fake_biod_client_.GetRecordsForUser( |
| 39 user_id, |
| 40 base::Bind(&test_utils::CopyObjectPathArray, &enrollment_paths)); |
| 41 task_runner_->RunUntilIdle(); |
| 42 return enrollment_paths; |
| 43 } |
| 44 |
| 45 void SendAuthScanDone(const std::string& scan_data) { |
| 46 fake_biod_client_.SendAuthScanDone(scan_data, |
| 47 biod::ScanResult::SCAN_RESULT_SUCCESS); |
| 48 } |
| 49 |
| 50 // Helper function which enrolls a fingerprint. Each element in |
| 51 // |fingerprint_data| corresponds to a finger tap. |
| 52 void EnrollFingerprint(const std::string& id, |
| 53 const std::string& label, |
| 54 const std::vector<std::string>& fingerprint_data) { |
| 55 CHECK(!fingerprint_data.empty()); |
| 56 |
| 57 dbus::ObjectPath returned_path; |
| 58 fake_biod_client_.StartEnrollSession( |
| 59 id, label, base::Bind(&test_utils::CopyObjectPath, &returned_path)); |
| 60 task_runner_->RunUntilIdle(); |
| 61 EXPECT_NE(dbus::ObjectPath(), returned_path); |
| 62 |
| 63 // Send |fingerprint_data| size - 1 incomplete scans, then finish the |
| 64 // enrollment by sending a complete scan signal. |
| 65 for (size_t i = 0; i < fingerprint_data.size(); ++i) { |
| 66 fake_biod_client_.SendEnrollScanDone( |
| 67 fingerprint_data[i], biod::ScanResult::SCAN_RESULT_SUCCESS, |
| 68 i == fingerprint_data.size() - 1 /* is_complete*/); |
| 69 } |
| 70 } |
| 71 |
| 72 // Helper function which enrolls |n| fingerprints with the same |id|, |label| |
| 73 // and |fingerprint_data|. |
| 74 void EnrollNTestFingerprints(const std::string& id, |
| 75 const std::string& label, |
| 76 const std::vector<std::string>& fingerprint_data, |
| 77 int n) { |
| 78 for (int i = 0; i < n; ++i) |
| 79 EnrollFingerprint(id, label, fingerprint_data); |
| 80 } |
| 81 |
| 82 // Creates a new unique fingerprint consisting of unique scans. |
| 83 std::vector<std::string> GenerateTestFingerprint(int scans) { |
| 84 DCHECK_GE(scans, 0); |
| 85 num_test_fingerprints_++; |
| 86 |
| 87 std::vector<std::string> fingerprint; |
| 88 for (int i = 0; i < scans; ++i) { |
| 89 std::string scan = kTestScan; |
| 90 base::ReplaceSubstringsAfterOffset( |
| 91 &scan, 0, "#", std::to_string(num_test_fingerprints_)); |
| 92 base::ReplaceSubstringsAfterOffset(&scan, 0, "$", std::to_string(i)); |
| 93 fingerprint.push_back(scan); |
| 94 } |
| 95 return fingerprint; |
| 96 } |
| 97 |
| 98 protected: |
| 99 FakeBiodClient fake_biod_client_; |
| 100 scoped_refptr<base::TestSimpleTaskRunner> task_runner_; |
| 101 base::ThreadTaskRunnerHandle task_runner_handle_; |
| 102 |
| 103 // This number is incremented each time GenerateTestFingerprint is called to |
| 104 // ensure each fingerprint is unique. |
| 105 int num_test_fingerprints_ = 0; |
| 106 |
| 107 private: |
| 108 DISALLOW_COPY_AND_ASSIGN(FakeBiodClientTest); |
| 109 }; |
| 110 |
| 111 TEST_F(FakeBiodClientTest, TestEnrollSessionWorkflow) { |
| 112 test_utils::TestBiodObserver observer; |
| 113 fake_biod_client_.AddObserver(&observer); |
| 114 |
| 115 const std::vector<std::string>& kTestFingerprint = GenerateTestFingerprint(2); |
| 116 // Verify that successful enrollments get stored as expected. A fingerprint |
| 117 // that was created with 2 scans should have 1 incomplete scans and 1 complete |
| 118 // scans. |
| 119 EnrollFingerprint(kTestUserId, kTestLabel, kTestFingerprint); |
| 120 EXPECT_EQ(1u, GetRecordsForUser(kTestUserId).size()); |
| 121 EXPECT_EQ(1, observer.num_incomplete_enroll_scans_received()); |
| 122 EXPECT_EQ(1, observer.num_complete_enroll_scans_received()); |
| 123 |
| 124 // Verify that the enroll session worflow can be used repeatedly by enrolling |
| 125 // 3 more fingerprints (each with 1 incomplete and 1 complete scans). |
| 126 EnrollNTestFingerprints(kTestUserId, kTestLabel, kTestFingerprint, 3); |
| 127 EXPECT_EQ(4u, GetRecordsForUser(kTestUserId).size()); |
| 128 EXPECT_EQ(4, observer.num_incomplete_enroll_scans_received()); |
| 129 EXPECT_EQ(4, observer.num_complete_enroll_scans_received()); |
| 130 } |
| 131 |
| 132 // Test authentication when one user has one or more fingerprints registered. |
| 133 // This should be the normal scenario. |
| 134 TEST_F(FakeBiodClientTest, TestAuthSessionWorkflowSingleUser) { |
| 135 test_utils::TestBiodObserver observer; |
| 136 fake_biod_client_.AddObserver(&observer); |
| 137 EXPECT_EQ(0u, GetRecordsForUser(kTestUserId).size()); |
| 138 |
| 139 const std::vector<std::string>& kTestFingerprint1 = |
| 140 GenerateTestFingerprint(2); |
| 141 const std::vector<std::string>& kTestFingerprint2 = |
| 142 GenerateTestFingerprint(2); |
| 143 const std::vector<std::string>& kTestFingerprint3 = |
| 144 GenerateTestFingerprint(2); |
| 145 const std::vector<std::string>& kTestFingerprint4 = |
| 146 GenerateTestFingerprint(2); |
| 147 |
| 148 // Add two fingerprints |kTestFingerprint1| and |kTestFingerprint2| and start |
| 149 // an auth session. |
| 150 EnrollFingerprint(kTestUserId, kTestLabel, kTestFingerprint1); |
| 151 EnrollFingerprint(kTestUserId, kTestLabel, kTestFingerprint2); |
| 152 dbus::ObjectPath returned_path; |
| 153 fake_biod_client_.StartAuthSession( |
| 154 base::Bind(&test_utils::CopyObjectPath, &returned_path)); |
| 155 task_runner_->RunUntilIdle(); |
| 156 EXPECT_NE(returned_path, dbus::ObjectPath()); |
| 157 |
| 158 // Verify that by sending two attempts signals of fingerprints that have been |
| 159 // enrolled, the observer should receive two matches and zero non-matches. |
| 160 fake_biod_client_.SendAuthScanDone(kTestFingerprint1[0], |
| 161 biod::ScanResult::SCAN_RESULT_SUCCESS); |
| 162 fake_biod_client_.SendAuthScanDone(kTestFingerprint2[0], |
| 163 biod::ScanResult::SCAN_RESULT_SUCCESS); |
| 164 EXPECT_EQ(2, observer.num_matched_auth_scans_received()); |
| 165 EXPECT_EQ(0, observer.num_unmatched_auth_scans_received()); |
| 166 |
| 167 // Verify that by sending two attempt signals of fingerprints that have not |
| 168 // been enrolled, the observer should receive two non-matches and zero |
| 169 // matches. |
| 170 fake_biod_client_.SendAuthScanDone(kTestFingerprint3[0], |
| 171 biod::ScanResult::SCAN_RESULT_SUCCESS); |
| 172 fake_biod_client_.SendAuthScanDone(kTestFingerprint4[0], |
| 173 biod::ScanResult::SCAN_RESULT_SUCCESS); |
| 174 EXPECT_EQ(2, observer.num_matched_auth_scans_received()); |
| 175 EXPECT_EQ(2, observer.num_unmatched_auth_scans_received()); |
| 176 } |
| 177 |
| 178 // Test authentication when multiple users have fingerprints registered. Cover |
| 179 // cases such as when both users use the same labels, a user had registered the |
| 180 // same fingerprint multiple times, or two users use the same fingerprint. |
| 181 TEST_F(FakeBiodClientTest, TestAuthenticateWorkflowMultipleUsers) { |
| 182 test_utils::TestBiodObserver observer; |
| 183 fake_biod_client_.AddObserver(&observer); |
| 184 EXPECT_EQ(0u, GetRecordsForUser(kTestUserId).size()); |
| 185 |
| 186 // Add two users, who have scanned three fingers between the two of them. |
| 187 const std::string kUserOne = std::string(kTestUserId) + "1"; |
| 188 const std::string kUserTwo = std::string(kTestUserId) + "2"; |
| 189 |
| 190 const std::string kLabelOne = std::string(kTestLabel) + "1"; |
| 191 const std::string kLabelTwo = std::string(kTestLabel) + "2"; |
| 192 const std::string kLabelThree = std::string(kTestLabel) + "3"; |
| 193 |
| 194 // Generate 2 test fingerprints per user. |
| 195 const std::vector<std::string>& kUser1Finger1 = GenerateTestFingerprint(2); |
| 196 const std::vector<std::string>& kUser1Finger2 = GenerateTestFingerprint(2); |
| 197 const std::vector<std::string>& kUser2Finger1 = GenerateTestFingerprint(2); |
| 198 const std::vector<std::string>& kUser2Finger2 = GenerateTestFingerprint(2); |
| 199 |
| 200 EnrollFingerprint(kUserOne, kLabelOne, kUser1Finger1); |
| 201 EnrollFingerprint(kUserOne, kLabelTwo, kUser1Finger2); |
| 202 // User one has registered finger two twice. |
| 203 EnrollFingerprint(kUserOne, kLabelThree, kUser1Finger2); |
| 204 EnrollFingerprint(kUserTwo, kLabelOne, kUser2Finger1); |
| 205 EnrollFingerprint(kUserTwo, kLabelTwo, kUser2Finger2); |
| 206 // User two has allowed user one to unlock his/her account with his/her |
| 207 // first finger. |
| 208 EnrollFingerprint(kUserTwo, kLabelThree, kUser1Finger1); |
| 209 |
| 210 dbus::ObjectPath returned_path; |
| 211 fake_biod_client_.StartAuthSession( |
| 212 base::Bind(&test_utils::CopyObjectPath, &returned_path)); |
| 213 task_runner_->RunUntilIdle(); |
| 214 EXPECT_NE(returned_path, dbus::ObjectPath()); |
| 215 |
| 216 // Verify that if a user registers the same finger to two different labels, |
| 217 // both labels are returned as matches. |
| 218 AuthScanMatches expected_auth_scans_matches; |
| 219 expected_auth_scans_matches[kUserOne] = {kLabelTwo, kLabelThree}; |
| 220 fake_biod_client_.SendAuthScanDone(kUser1Finger2[0], |
| 221 biod::ScanResult::SCAN_RESULT_SUCCESS); |
| 222 EXPECT_TRUE( |
| 223 observer.CheckExpectedLastAttemptMatches(expected_auth_scans_matches)); |
| 224 |
| 225 // Verify that a fingerprint associated with one user and one label returns a |
| 226 // match with one user and one label. |
| 227 expected_auth_scans_matches.clear(); |
| 228 expected_auth_scans_matches[kUserTwo] = {kLabelOne}; |
| 229 fake_biod_client_.SendAuthScanDone(kUser2Finger1[0], |
| 230 biod::ScanResult::SCAN_RESULT_SUCCESS); |
| 231 EXPECT_TRUE( |
| 232 observer.CheckExpectedLastAttemptMatches(expected_auth_scans_matches)); |
| 233 |
| 234 // Verify if two users register the same fingerprint, the matches contain |
| 235 // both users. |
| 236 expected_auth_scans_matches.clear(); |
| 237 expected_auth_scans_matches[kUserOne] = {kLabelOne}; |
| 238 expected_auth_scans_matches[kUserTwo] = {kLabelThree}; |
| 239 fake_biod_client_.SendAuthScanDone(kUser1Finger1[0], |
| 240 biod::ScanResult::SCAN_RESULT_SUCCESS); |
| 241 EXPECT_TRUE( |
| 242 observer.CheckExpectedLastAttemptMatches(expected_auth_scans_matches)); |
| 243 |
| 244 // Verify if a unregistered finger is scanned, the matches are empty. |
| 245 expected_auth_scans_matches.clear(); |
| 246 fake_biod_client_.SendAuthScanDone("Unregistered", |
| 247 biod::ScanResult::SCAN_RESULT_SUCCESS); |
| 248 EXPECT_TRUE( |
| 249 observer.CheckExpectedLastAttemptMatches(expected_auth_scans_matches)); |
| 250 } |
| 251 |
| 252 TEST_F(FakeBiodClientTest, TestGetRecordsForUser) { |
| 253 // Verify that initially |kTestUserId| will have no fingerprints. |
| 254 EXPECT_EQ(0u, GetRecordsForUser(kTestUserId).size()); |
| 255 |
| 256 // Verify that after enrolling 2 fingerprints, a GetRecords call return 2 |
| 257 // items. |
| 258 EnrollNTestFingerprints(kTestUserId, kTestLabel, GenerateTestFingerprint(2), |
| 259 2); |
| 260 EXPECT_EQ(2u, GetRecordsForUser(kTestUserId).size()); |
| 261 |
| 262 // Verify that GetRecords call for a user with no registered fingerprints |
| 263 // should return 0 items. |
| 264 EXPECT_EQ(0u, GetRecordsForUser("noRegisteredFingerprints@gmail.com").size()); |
| 265 } |
| 266 |
| 267 TEST_F(FakeBiodClientTest, TestDestroyingRecords) { |
| 268 // Verify that after enrolling 2 fingerprints and destroying them, 0 |
| 269 // fingerprints will remain. |
| 270 EnrollNTestFingerprints(kTestUserId, kTestLabel, GenerateTestFingerprint(2), |
| 271 2); |
| 272 EXPECT_EQ(2u, GetRecordsForUser(kTestUserId).size()); |
| 273 fake_biod_client_.DestroyAllRecords(); |
| 274 EXPECT_EQ(0u, GetRecordsForUser(kTestUserId).size()); |
| 275 } |
| 276 |
| 277 TEST_F(FakeBiodClientTest, TestGetAndSetRecordLabels) { |
| 278 const std::string kLabelOne = "Finger 1"; |
| 279 const std::string kLabelTwo = "Finger 2"; |
| 280 |
| 281 EnrollFingerprint(kTestUserId, kLabelOne, GenerateTestFingerprint(2)); |
| 282 EnrollFingerprint(kTestUserId, kLabelTwo, GenerateTestFingerprint(2)); |
| 283 EXPECT_EQ(2u, GetRecordsForUser(kTestUserId).size()); |
| 284 std::vector<dbus::ObjectPath> enrollment_paths; |
| 285 fake_biod_client_.GetRecordsForUser( |
| 286 kTestUserId, |
| 287 base::Bind(&test_utils::CopyObjectPathArray, &enrollment_paths)); |
| 288 task_runner_->RunUntilIdle(); |
| 289 EXPECT_EQ(2u, enrollment_paths.size()); |
| 290 |
| 291 // Verify the labels we get using GetLabel are the same as the one we |
| 292 // originally set. |
| 293 std::string returned_str; |
| 294 fake_biod_client_.RequestRecordLabel( |
| 295 enrollment_paths[0], base::Bind(&test_utils::CopyString, &returned_str)); |
| 296 task_runner_->RunUntilIdle(); |
| 297 EXPECT_EQ(kLabelOne, returned_str); |
| 298 |
| 299 returned_str = ""; |
| 300 fake_biod_client_.RequestRecordLabel( |
| 301 enrollment_paths[1], base::Bind(&test_utils::CopyString, &returned_str)); |
| 302 task_runner_->RunUntilIdle(); |
| 303 EXPECT_EQ(kLabelTwo, returned_str); |
| 304 |
| 305 // Verify that by setting a new label, getting the label will return the value |
| 306 // of the new label. |
| 307 const std::string kNewLabelTwo = "Finger 2 New"; |
| 308 fake_biod_client_.SetRecordLabel(enrollment_paths[1], kNewLabelTwo); |
| 309 fake_biod_client_.RequestRecordLabel( |
| 310 enrollment_paths[1], base::Bind(&test_utils::CopyString, &returned_str)); |
| 311 task_runner_->RunUntilIdle(); |
| 312 EXPECT_EQ(kNewLabelTwo, returned_str); |
| 313 } |
| 314 |
| 315 } // namespace chromeos |
OLD | NEW |