| Index: chromeos/dbus/biod/fake_biod_client_unittest.cc
|
| diff --git a/chromeos/dbus/biod/fake_biod_client_unittest.cc b/chromeos/dbus/biod/fake_biod_client_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..521c3e60c4464202255dafcc5b3a9a2cd0f1efe9
|
| --- /dev/null
|
| +++ b/chromeos/dbus/biod/fake_biod_client_unittest.cc
|
| @@ -0,0 +1,308 @@
|
| +// Copyright 2017 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "chromeos/dbus/biod/fake_biod_client.h"
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/macros.h"
|
| +#include "base/strings/string_util.h"
|
| +#include "base/test/test_simple_task_runner.h"
|
| +#include "base/threading/thread_task_runner_handle.h"
|
| +#include "chromeos/dbus/biod/test_utils.h"
|
| +#include "dbus/object_path.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +using namespace biod;
|
| +
|
| +namespace chromeos {
|
| +
|
| +namespace {
|
| +
|
| +const char kTestUserId[] = "testuser@gmail.com";
|
| +const char kTestLabel[] = "testLabel";
|
| +// Template of a scan string to be used in GenerateTestFingerprint. The # and $
|
| +// are two wildcards that will be replaced by numbers to ensure unique scans.
|
| +const char kTestScan[] = "finger#scan$";
|
| +
|
| +} // namepsace
|
| +
|
| +class FakeBiodClientTest : public testing::Test {
|
| + public:
|
| + FakeBiodClientTest()
|
| + : task_runner_(new base::TestSimpleTaskRunner),
|
| + task_runner_handle_(task_runner_) {}
|
| + ~FakeBiodClientTest() override {}
|
| +
|
| + // Returns the stored records for |user_id|. Verified to work in
|
| + // TestGetRecordsForUser.
|
| + std::vector<dbus::ObjectPath> GetRecordsForUser(const std::string& user_id) {
|
| + std::vector<dbus::ObjectPath> enrollment_paths;
|
| + fake_biod_client_.GetRecordsForUser(
|
| + user_id,
|
| + base::Bind(&test_utils::CopyObjectPathArray, &enrollment_paths));
|
| + task_runner_->RunUntilIdle();
|
| + return enrollment_paths;
|
| + }
|
| +
|
| + // Helper function which enrolls a fingerprint. Each element in
|
| + // |fingerprint_data| corresponds to a finger tap.
|
| + void EnrollFingerprint(const std::string& id,
|
| + const std::string& label,
|
| + const std::vector<std::string>& fingerprint_data) {
|
| + ASSERT_FALSE(fingerprint_data.empty());
|
| +
|
| + dbus::ObjectPath returned_path;
|
| + fake_biod_client_.StartEnrollSession(
|
| + id, label, base::Bind(&test_utils::CopyObjectPath, &returned_path));
|
| + task_runner_->RunUntilIdle();
|
| + EXPECT_NE(dbus::ObjectPath(), returned_path);
|
| +
|
| + // Send |fingerprint_data| size - 1 incomplete scans, then finish the
|
| + // enrollment by sending a complete scan signal.
|
| + for (size_t i = 0; i < fingerprint_data.size(); ++i) {
|
| + fake_biod_client_.SendEnrollScanDone(
|
| + fingerprint_data[i], SCAN_RESULT_SUCCESS,
|
| + i == fingerprint_data.size() - 1 /* is_complete */);
|
| + }
|
| + }
|
| +
|
| + // Helper function which enrolls |n| fingerprints with the same |id|, |label|
|
| + // and |fingerprint_data|.
|
| + void EnrollNTestFingerprints(const std::string& id,
|
| + const std::string& label,
|
| + const std::vector<std::string>& fingerprint_data,
|
| + int n) {
|
| + for (int i = 0; i < n; ++i)
|
| + EnrollFingerprint(id, label, fingerprint_data);
|
| + }
|
| +
|
| + // Creates a new unique fingerprint consisting of unique scans.
|
| + std::vector<std::string> GenerateTestFingerprint(int scans) {
|
| + EXPECT_GE(scans, 0);
|
| + num_test_fingerprints_++;
|
| +
|
| + std::vector<std::string> fingerprint;
|
| + for (int i = 0; i < scans; ++i) {
|
| + std::string scan = kTestScan;
|
| + base::ReplaceSubstringsAfterOffset(
|
| + &scan, 0, "#", std::to_string(num_test_fingerprints_));
|
| + base::ReplaceSubstringsAfterOffset(&scan, 0, "$", std::to_string(i));
|
| + fingerprint.push_back(scan);
|
| + }
|
| + return fingerprint;
|
| + }
|
| +
|
| + protected:
|
| + FakeBiodClient fake_biod_client_;
|
| + scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
|
| + base::ThreadTaskRunnerHandle task_runner_handle_;
|
| +
|
| + // This number is incremented each time GenerateTestFingerprint is called to
|
| + // ensure each fingerprint is unique.
|
| + int num_test_fingerprints_ = 0;
|
| +
|
| + private:
|
| + DISALLOW_COPY_AND_ASSIGN(FakeBiodClientTest);
|
| +};
|
| +
|
| +TEST_F(FakeBiodClientTest, TestEnrollSessionWorkflow) {
|
| + test_utils::TestBiodObserver observer;
|
| + fake_biod_client_.AddObserver(&observer);
|
| +
|
| + const std::vector<std::string>& kTestFingerprint = GenerateTestFingerprint(2);
|
| + // Verify that successful enrollments get stored as expected. A fingerprint
|
| + // that was created with 2 scans should have 1 incomplete scan and 1 complete
|
| + // scan.
|
| + EnrollFingerprint(kTestUserId, kTestLabel, kTestFingerprint);
|
| + EXPECT_EQ(1u, GetRecordsForUser(kTestUserId).size());
|
| + EXPECT_EQ(1, observer.num_incomplete_enroll_scans_received());
|
| + EXPECT_EQ(1, observer.num_complete_enroll_scans_received());
|
| +
|
| + // Verify that the enroll session worflow can be used repeatedly by enrolling
|
| + // 3 more fingerprints (each with 1 incomplete and 1 complete scan).
|
| + observer.ResetAllCounts();
|
| + EnrollNTestFingerprints(kTestUserId, kTestLabel, kTestFingerprint, 3);
|
| + EXPECT_EQ(4u, GetRecordsForUser(kTestUserId).size());
|
| + EXPECT_EQ(3, observer.num_incomplete_enroll_scans_received());
|
| + EXPECT_EQ(3, observer.num_complete_enroll_scans_received());
|
| +}
|
| +
|
| +// Test authentication when one user has one or more fingerprints registered.
|
| +// This should be the normal scenario.
|
| +TEST_F(FakeBiodClientTest, TestAuthSessionWorkflowSingleUser) {
|
| + test_utils::TestBiodObserver observer;
|
| + fake_biod_client_.AddObserver(&observer);
|
| + EXPECT_EQ(0u, GetRecordsForUser(kTestUserId).size());
|
| +
|
| + const std::vector<std::string>& kTestFingerprint1 =
|
| + GenerateTestFingerprint(2);
|
| + const std::vector<std::string>& kTestFingerprint2 =
|
| + GenerateTestFingerprint(2);
|
| + const std::vector<std::string>& kTestFingerprint3 =
|
| + GenerateTestFingerprint(2);
|
| + const std::vector<std::string>& kTestFingerprint4 =
|
| + GenerateTestFingerprint(2);
|
| +
|
| + // Add two fingerprints |kTestFingerprint1| and |kTestFingerprint2| and start
|
| + // an auth session.
|
| + EnrollFingerprint(kTestUserId, kTestLabel, kTestFingerprint1);
|
| + EnrollFingerprint(kTestUserId, kTestLabel, kTestFingerprint2);
|
| + dbus::ObjectPath returned_path;
|
| + fake_biod_client_.StartAuthSession(
|
| + base::Bind(&test_utils::CopyObjectPath, &returned_path));
|
| + task_runner_->RunUntilIdle();
|
| + EXPECT_NE(returned_path, dbus::ObjectPath());
|
| +
|
| + // Verify that by sending two attempt signals of fingerprints that have been
|
| + // enrolled, the observer should receive two matches and zero non-matches.
|
| + fake_biod_client_.SendAuthScanDone(kTestFingerprint1[0], SCAN_RESULT_SUCCESS);
|
| + fake_biod_client_.SendAuthScanDone(kTestFingerprint2[0], SCAN_RESULT_SUCCESS);
|
| + EXPECT_EQ(2, observer.num_matched_auth_scans_received());
|
| + EXPECT_EQ(0, observer.num_unmatched_auth_scans_received());
|
| +
|
| + // Verify that by sending two attempt signals of fingerprints that have not
|
| + // been enrolled, the observer should receive two non-matches and zero
|
| + // matches.
|
| + observer.ResetAllCounts();
|
| + fake_biod_client_.SendAuthScanDone(kTestFingerprint3[0], SCAN_RESULT_SUCCESS);
|
| + fake_biod_client_.SendAuthScanDone(kTestFingerprint4[0], SCAN_RESULT_SUCCESS);
|
| + EXPECT_EQ(0, observer.num_matched_auth_scans_received());
|
| + EXPECT_EQ(2, observer.num_unmatched_auth_scans_received());
|
| +}
|
| +
|
| +// Test authentication when multiple users have fingerprints registered. Cover
|
| +// cases such as when both users use the same labels, a user had registered the
|
| +// same fingerprint multiple times, or two users use the same fingerprint.
|
| +TEST_F(FakeBiodClientTest, TestAuthenticateWorkflowMultipleUsers) {
|
| + test_utils::TestBiodObserver observer;
|
| + fake_biod_client_.AddObserver(&observer);
|
| + EXPECT_EQ(0u, GetRecordsForUser(kTestUserId).size());
|
| +
|
| + // Add two users, who have scanned three fingers between the two of them.
|
| + const std::string kUserOne = std::string(kTestUserId) + "1";
|
| + const std::string kUserTwo = std::string(kTestUserId) + "2";
|
| +
|
| + const std::string kLabelOne = std::string(kTestLabel) + "1";
|
| + const std::string kLabelTwo = std::string(kTestLabel) + "2";
|
| + const std::string kLabelThree = std::string(kTestLabel) + "3";
|
| +
|
| + // Generate 2 test fingerprints per user.
|
| + const std::vector<std::string>& kUser1Finger1 = GenerateTestFingerprint(2);
|
| + const std::vector<std::string>& kUser1Finger2 = GenerateTestFingerprint(2);
|
| + const std::vector<std::string>& kUser2Finger1 = GenerateTestFingerprint(2);
|
| + const std::vector<std::string>& kUser2Finger2 = GenerateTestFingerprint(2);
|
| +
|
| + EnrollFingerprint(kUserOne, kLabelOne, kUser1Finger1);
|
| + EnrollFingerprint(kUserOne, kLabelTwo, kUser1Finger2);
|
| + // User one has registered finger two twice.
|
| + EnrollFingerprint(kUserOne, kLabelThree, kUser1Finger2);
|
| + EnrollFingerprint(kUserTwo, kLabelOne, kUser2Finger1);
|
| + EnrollFingerprint(kUserTwo, kLabelTwo, kUser2Finger2);
|
| + // User two has allowed user one to unlock their account with their first
|
| + // finger.
|
| + EnrollFingerprint(kUserTwo, kLabelThree, kUser1Finger1);
|
| +
|
| + dbus::ObjectPath returned_path;
|
| + fake_biod_client_.StartAuthSession(
|
| + base::Bind(&test_utils::CopyObjectPath, &returned_path));
|
| + task_runner_->RunUntilIdle();
|
| + EXPECT_NE(returned_path, dbus::ObjectPath());
|
| +
|
| + // Verify that if a user registers the same finger to two different labels,
|
| + // both labels are returned as matches.
|
| + AuthScanMatches expected_auth_scans_matches;
|
| + expected_auth_scans_matches[kUserOne] = {kLabelTwo, kLabelThree};
|
| + fake_biod_client_.SendAuthScanDone(kUser1Finger2[0], SCAN_RESULT_SUCCESS);
|
| + EXPECT_EQ(expected_auth_scans_matches, observer.last_auth_scan_matches());
|
| +
|
| + // Verify that a fingerprint associated with one user and one label returns a
|
| + // match with one user and one label.
|
| + expected_auth_scans_matches.clear();
|
| + expected_auth_scans_matches[kUserTwo] = {kLabelOne};
|
| + fake_biod_client_.SendAuthScanDone(kUser2Finger1[0], SCAN_RESULT_SUCCESS);
|
| + EXPECT_EQ(expected_auth_scans_matches, observer.last_auth_scan_matches());
|
| +
|
| + // Verify if two users register the same fingerprint, the matches contain
|
| + // both users.
|
| + expected_auth_scans_matches.clear();
|
| + expected_auth_scans_matches[kUserOne] = {kLabelOne};
|
| + expected_auth_scans_matches[kUserTwo] = {kLabelThree};
|
| + fake_biod_client_.SendAuthScanDone(kUser1Finger1[0], SCAN_RESULT_SUCCESS);
|
| + EXPECT_EQ(expected_auth_scans_matches, observer.last_auth_scan_matches());
|
| +
|
| + // Verify if a unregistered finger is scanned, the matches are empty.
|
| + expected_auth_scans_matches.clear();
|
| + fake_biod_client_.SendAuthScanDone("Unregistered", SCAN_RESULT_SUCCESS);
|
| + EXPECT_EQ(expected_auth_scans_matches, observer.last_auth_scan_matches());
|
| +}
|
| +
|
| +TEST_F(FakeBiodClientTest, TestGetRecordsForUser) {
|
| + // Verify that initially |kTestUserId| will have no fingerprints.
|
| + EXPECT_EQ(0u, GetRecordsForUser(kTestUserId).size());
|
| +
|
| + // Verify that after enrolling 2 fingerprints, a GetRecords call return 2
|
| + // items.
|
| + EnrollNTestFingerprints(kTestUserId, kTestLabel, GenerateTestFingerprint(2),
|
| + 2);
|
| + EXPECT_EQ(2u, GetRecordsForUser(kTestUserId).size());
|
| +
|
| + // Verify that GetRecords call for a user with no registered fingerprints
|
| + // should return 0 items.
|
| + EXPECT_EQ(0u, GetRecordsForUser("noRegisteredFingerprints@gmail.com").size());
|
| +}
|
| +
|
| +TEST_F(FakeBiodClientTest, TestDestroyingRecords) {
|
| + // Verify that after enrolling 2 fingerprints and destroying them, 0
|
| + // fingerprints will remain.
|
| + EnrollNTestFingerprints(kTestUserId, kTestLabel, GenerateTestFingerprint(2),
|
| + 2);
|
| + EXPECT_EQ(2u, GetRecordsForUser(kTestUserId).size());
|
| + DBusMethodCallStatus returned_status;
|
| + fake_biod_client_.DestroyAllRecords(
|
| + base::Bind(&test_utils::CopyDBusMethodCallStatus, &returned_status));
|
| + EXPECT_EQ(0u, GetRecordsForUser(kTestUserId).size());
|
| +}
|
| +
|
| +TEST_F(FakeBiodClientTest, TestGetAndSetRecordLabels) {
|
| + const std::string kLabelOne = "Finger 1";
|
| + const std::string kLabelTwo = "Finger 2";
|
| +
|
| + EnrollFingerprint(kTestUserId, kLabelOne, GenerateTestFingerprint(2));
|
| + EnrollFingerprint(kTestUserId, kLabelTwo, GenerateTestFingerprint(2));
|
| + EXPECT_EQ(2u, GetRecordsForUser(kTestUserId).size());
|
| + std::vector<dbus::ObjectPath> enrollment_paths;
|
| + fake_biod_client_.GetRecordsForUser(
|
| + kTestUserId,
|
| + base::Bind(&test_utils::CopyObjectPathArray, &enrollment_paths));
|
| + task_runner_->RunUntilIdle();
|
| + EXPECT_EQ(2u, enrollment_paths.size());
|
| +
|
| + // Verify the labels we get using GetLabel are the same as the one we
|
| + // originally set.
|
| + std::string returned_str;
|
| + fake_biod_client_.RequestRecordLabel(
|
| + enrollment_paths[0], base::Bind(&test_utils::CopyString, &returned_str));
|
| + task_runner_->RunUntilIdle();
|
| + EXPECT_EQ(kLabelOne, returned_str);
|
| +
|
| + returned_str = "";
|
| + fake_biod_client_.RequestRecordLabel(
|
| + enrollment_paths[1], base::Bind(&test_utils::CopyString, &returned_str));
|
| + task_runner_->RunUntilIdle();
|
| + EXPECT_EQ(kLabelTwo, returned_str);
|
| +
|
| + // Verify that by setting a new label, getting the label will return the value
|
| + // of the new label.
|
| + const std::string kNewLabelTwo = "Finger 2 New";
|
| + DBusMethodCallStatus returned_status;
|
| + fake_biod_client_.SetRecordLabel(
|
| + enrollment_paths[1], kNewLabelTwo,
|
| + base::Bind(&test_utils::CopyDBusMethodCallStatus, &returned_status));
|
| + fake_biod_client_.RequestRecordLabel(
|
| + enrollment_paths[1], base::Bind(&test_utils::CopyString, &returned_str));
|
| + task_runner_->RunUntilIdle();
|
| + EXPECT_EQ(kNewLabelTwo, returned_str);
|
| +}
|
| +
|
| +} // namespace chromeos
|
|
|