blob: 01e8d130d044375d945edec69387fc1d840760b2 [file] [log] [blame]
// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <map>
#include <utility>
#include <base/strings/stringprintf.h>
#include <base/test/task_environment.h>
#include <brillo/dbus/async_event_sequencer.h>
#include <brillo/dbus/mock_exported_object_manager.h>
#include <dbus/mock_bus.h>
#include <dbus/mock_exported_object.h>
#include <dbus/mock_object_proxy.h>
#include <dbus/object_path.h>
#include <dbus/property.h>
#include <biod/biometrics_manager_wrapper.h>
#include <biod/mock_biometrics_manager.h>
#include <biod/mock_biometrics_manager_record.h>
#include <biod/mock_session_state_manager.h>
namespace biod {
namespace {
using testing::_;
using testing::ByMove;
using testing::HasSubstr;
using testing::Return;
using testing::ReturnRef;
using testing::SaveArg;
constexpr char kUserID[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
constexpr char kUserID2[] = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
static_assert(sizeof(kUserID) == 41);
static_assert(sizeof(kUserID2) == 41);
constexpr char kRecordID[] = "record";
constexpr char kLabel[] = "Finger";
constexpr char kClientConnectionName[] = ":1.33";
class BiometricsManagerWrapperTest : public ::testing::Test {
public:
BiometricsManagerWrapperTest() {
dbus::Bus::Options options;
options.bus_type = dbus::Bus::SYSTEM;
bus_ = new dbus::MockBus(options);
ON_CALL(*bus_, GetExportedObject)
.WillByDefault(
Invoke(this, &BiometricsManagerWrapperTest::GetExportedObject));
proxy_ =
new dbus::MockObjectProxy(bus_.get(), dbus::kDBusServiceName,
dbus::ObjectPath(dbus::kDBusServicePath));
ON_CALL(*bus_, GetObjectProxy(dbus::kDBusServiceName, _))
.WillByDefault(Return(proxy_.get()));
EXPECT_CALL(*proxy_, DoConnectToSignal(dbus::kDBusInterface, _, _, _))
.WillRepeatedly(
Invoke(this, &BiometricsManagerWrapperTest::ConnectToSignal));
auto mock_biometrics_manager = std::make_unique<MockBiometricsManager>();
bio_manager_ = mock_biometrics_manager.get();
EXPECT_CALL(*bio_manager_, SetEnrollScanDoneHandler)
.WillRepeatedly(SaveArg<0>(&on_enroll_scan_done));
EXPECT_CALL(*bio_manager_, SetAuthScanDoneHandler)
.WillRepeatedly(SaveArg<0>(&on_auth_scan_done));
EXPECT_CALL(*bio_manager_, SetSessionFailedHandler)
.WillRepeatedly(SaveArg<0>(&on_session_failed));
EXPECT_CALL(*bio_manager_, GetType)
.WillRepeatedly(Return(BIOMETRIC_TYPE_UNKNOWN));
object_manager_ =
std::make_unique<brillo::dbus_utils::MockExportedObjectManager>(
bus_, dbus::ObjectPath(kBiodServicePath));
session_manager_ = std::make_unique<MockSessionStateManager>();
EXPECT_CALL(*session_manager_, AddObserver).Times(1);
mock_bio_path_ = dbus::ObjectPath(
base::StringPrintf("%s/%s", kBiodServicePath, "MockBiometricsManager"));
auto sequencer =
base::MakeRefCounted<brillo::dbus_utils::AsyncEventSequencer>();
wrapper_.emplace(
std::move(mock_biometrics_manager), object_manager_.get(),
session_manager_.get(), mock_bio_path_,
sequencer->GetHandler("Failed to register BiometricsManager", false));
}
protected:
scoped_refptr<dbus::MockBus> bus_;
scoped_refptr<dbus::MockObjectProxy> proxy_;
MockBiometricsManager* bio_manager_;
std::unique_ptr<brillo::dbus_utils::MockExportedObjectManager>
object_manager_;
dbus::ObjectPath mock_bio_path_;
std::map<std::string, scoped_refptr<dbus::MockExportedObject>>
exported_objects_;
std::unique_ptr<MockSessionStateManager> session_manager_;
std::optional<BiometricsManagerWrapper> wrapper_;
BiometricsManager::EnrollScanDoneCallback on_enroll_scan_done;
BiometricsManager::AuthScanDoneCallback on_auth_scan_done;
BiometricsManager::SessionFailedCallback on_session_failed;
MOCK_METHOD(void,
ResponseSender,
(std::unique_ptr<dbus::Response> response),
());
std::unique_ptr<dbus::Response> CallMethod(dbus::MethodCall* method_call);
std::unique_ptr<dbus::Response> StartEnrollSession(
const std::string& user_id,
const std::string& label,
dbus::ObjectPath* object_path);
std::unique_ptr<dbus::Response> StartAuthSession(
dbus::ObjectPath* object_path);
void EmitNameOwnerChangedSignal(const std::string& name,
const std::string& old_owner,
const std::string& new_owner);
std::unique_ptr<dbus::Response> GetRecordsForUser(
const std::string& user_id, std::vector<dbus::ObjectPath>* paths);
private:
std::map<std::string, dbus::ObjectProxy::SignalCallback> signal_callbacks_;
std::map<std::string, dbus::ExportedObject::MethodCallCallback>
method_callbacks_;
base::test::SingleThreadTaskEnvironment task_environment_;
void ConnectToSignal(
const std::string& interface_name,
const std::string& signal_name,
dbus::ObjectProxy::SignalCallback signal_callback,
dbus::ObjectProxy::OnConnectedCallback* on_connected_callback);
dbus::ExportedObject* GetExportedObject(const dbus::ObjectPath& object_path);
void ExportMethod(
const std::string& interface_name,
const std::string& method_name,
const dbus::ExportedObject::MethodCallCallback& method_call_callback,
dbus::ExportedObject::OnExportedCallback on_exported_callback);
bool ExportMethodAndBlock(
const std::string& interface_name,
const std::string& method_name,
const dbus::ExportedObject::MethodCallCallback& method_call_callback);
};
void BiometricsManagerWrapperTest::ConnectToSignal(
const std::string& interface_name,
const std::string& signal_name,
dbus::ObjectProxy::SignalCallback signal_callback,
dbus::ObjectProxy::OnConnectedCallback* on_connected_callback) {
EXPECT_EQ(interface_name, dbus::kDBusInterface);
signal_callbacks_[signal_name] = std::move(signal_callback);
task_environment_.GetMainThreadTaskRunner()->PostTask(
FROM_HERE,
base::BindOnce(std::move(*on_connected_callback), interface_name,
signal_name, true /* success */));
}
void BiometricsManagerWrapperTest::EmitNameOwnerChangedSignal(
const std::string& name,
const std::string& old_owner,
const std::string& new_owner) {
const auto it = signal_callbacks_.find("NameOwnerChanged");
ASSERT_TRUE(it != signal_callbacks_.end())
<< "Client didn't register for NameOwnerChanged signal";
dbus::Signal signal(dbus::kDBusInterface, "NameOwnerChanged");
dbus::MessageWriter writer(&signal);
writer.AppendString(name);
writer.AppendString(old_owner);
writer.AppendString(new_owner);
it->second.Run(&signal);
}
dbus::ExportedObject* BiometricsManagerWrapperTest::GetExportedObject(
const dbus::ObjectPath& object_path) {
auto iter = exported_objects_.find(object_path.value());
if (iter != exported_objects_.end()) {
return iter->second.get();
}
scoped_refptr<dbus::MockExportedObject> exported_object =
new dbus::MockExportedObject(bus_.get(), object_path);
exported_objects_[object_path.value()] = exported_object;
ON_CALL(*exported_object, ExportMethod)
.WillByDefault(Invoke(this, &BiometricsManagerWrapperTest::ExportMethod));
ON_CALL(*exported_object, ExportMethodAndBlock)
.WillByDefault(
Invoke(this, &BiometricsManagerWrapperTest::ExportMethodAndBlock));
return exported_object.get();
}
void BiometricsManagerWrapperTest::ExportMethod(
const std::string& interface_name,
const std::string& method_name,
const dbus::ExportedObject::MethodCallCallback& method_call_callback,
dbus::ExportedObject::OnExportedCallback on_exported_callback) {
std::string full_name = interface_name + "." + method_name;
method_callbacks_[full_name] = method_call_callback;
task_environment_.GetMainThreadTaskRunner()->PostTask(
FROM_HERE, base::BindOnce(std::move(on_exported_callback), interface_name,
method_name, true /* success */));
}
bool BiometricsManagerWrapperTest::ExportMethodAndBlock(
const std::string& interface_name,
const std::string& method_name,
const dbus::ExportedObject::MethodCallCallback& method_call_callback) {
std::string full_name = interface_name + "." + method_name;
method_callbacks_[full_name] = method_call_callback;
return true;
}
std::unique_ptr<dbus::Response> BiometricsManagerWrapperTest::CallMethod(
dbus::MethodCall* method_call) {
std::string full_name =
method_call->GetInterface() + "." + method_call->GetMember();
std::unique_ptr<dbus::Response> response;
EXPECT_CALL(*this, ResponseSender)
.WillOnce([&response](std::unique_ptr<dbus::Response> result) {
response = std::move(result);
});
auto response_sender = base::BindOnce(
&BiometricsManagerWrapperTest::ResponseSender, base::Unretained(this));
method_call->SetSerial(1);
method_call->SetSender(kClientConnectionName);
auto iter = method_callbacks_.find(full_name);
EXPECT_TRUE(iter != method_callbacks_.end());
dbus::ExportedObject::MethodCallCallback& method_callback = iter->second;
method_callback.Run(method_call, std::move(response_sender));
return response;
}
std::unique_ptr<dbus::Response>
BiometricsManagerWrapperTest::StartEnrollSession(
const std::string& user_id,
const std::string& label,
dbus::ObjectPath* object_path) {
dbus::MethodCall start_enroll_session(
kBiometricsManagerInterface, kBiometricsManagerStartEnrollSessionMethod);
dbus::MessageWriter writer(&start_enroll_session);
writer.AppendString(user_id);
writer.AppendString(label);
auto response = CallMethod(&start_enroll_session);
if (response->GetMessageType() == dbus::Message::MESSAGE_METHOD_RETURN) {
dbus::MessageReader reader(response.get());
reader.PopObjectPath(object_path);
}
return response;
}
std::unique_ptr<dbus::Response> BiometricsManagerWrapperTest::StartAuthSession(
dbus::ObjectPath* object_path) {
dbus::MethodCall start_auth_session(kBiometricsManagerInterface,
kBiometricsManagerStartAuthSessionMethod);
auto response = CallMethod(&start_auth_session);
if (response->GetMessageType() == dbus::Message::MESSAGE_METHOD_RETURN) {
dbus::MessageReader reader(response.get());
reader.PopObjectPath(object_path);
}
return response;
}
std::unique_ptr<dbus::Response> BiometricsManagerWrapperTest::GetRecordsForUser(
const std::string& user_id, std::vector<dbus::ObjectPath>* paths) {
dbus::MethodCall get_records_for_user(
kBiometricsManagerInterface, kBiometricsManagerGetRecordsForUserMethod);
dbus::MessageWriter writer(&get_records_for_user);
writer.AppendString(user_id);
auto response = CallMethod(&get_records_for_user);
if (response->GetMessageType() == dbus::Message::MESSAGE_METHOD_RETURN) {
dbus::MessageReader reader(response.get());
dbus::MessageReader array_reader(nullptr);
reader.PopArray(&array_reader);
dbus::ObjectPath object_path;
while (array_reader.HasMoreData()) {
array_reader.PopObjectPath(&object_path);
paths->emplace_back(std::move(object_path));
}
}
return response;
}
TEST_F(BiometricsManagerWrapperTest, TestStartEnrollSession) {
dbus::ObjectPath object_path;
auto enroll_session = BiometricsManager::EnrollSession(
bio_manager_->session_weak_factory_.GetWeakPtr());
EXPECT_CALL(*bio_manager_, StartEnrollSession)
.WillOnce(Return(ByMove(std::move(enroll_session))));
EXPECT_CALL(*session_manager_, GetPrimaryUser).WillOnce(Return(kUserID));
auto response = StartEnrollSession(kUserID, kLabel, &object_path);
EXPECT_TRUE(response->GetMessageType() ==
dbus::Message::MESSAGE_METHOD_RETURN);
dbus::ObjectPath expected_object_path(mock_bio_path_.value() +
"/EnrollSession");
EXPECT_EQ(object_path, expected_object_path);
// Expect that enroll session will be finished on destruction of
// the enroll_session object. EXPECT_CALL is able to catch calls from
// enroll_session destructor which is called at the end of this
// test.
auto iter = exported_objects_.find(object_path.value());
ASSERT_TRUE(iter != exported_objects_.end());
scoped_refptr<dbus::MockExportedObject> object = iter->second;
EXPECT_CALL(*object, Unregister).Times(1);
EXPECT_CALL(*bio_manager_, EndEnrollSession).Times(1);
}
TEST_F(BiometricsManagerWrapperTest, TestStartEnrollSessionThenCancel) {
dbus::ObjectPath object_path;
auto enroll_session = BiometricsManager::EnrollSession(
bio_manager_->session_weak_factory_.GetWeakPtr());
EXPECT_CALL(*bio_manager_, StartEnrollSession)
.WillOnce(Return(ByMove(std::move(enroll_session))));
EXPECT_CALL(*session_manager_, GetPrimaryUser).WillOnce(Return(kUserID));
auto response = StartEnrollSession(kUserID, kLabel, &object_path);
EXPECT_TRUE(response->GetMessageType() ==
dbus::Message::MESSAGE_METHOD_RETURN);
// Cancel enroll session.
auto iter = exported_objects_.find(object_path.value());
ASSERT_TRUE(iter != exported_objects_.end());
scoped_refptr<dbus::MockExportedObject> object = iter->second;
EXPECT_CALL(*object, Unregister).Times(1);
EXPECT_CALL(*bio_manager_, EndEnrollSession).Times(1);
dbus::MethodCall cancel_enroll_session(kEnrollSessionInterface,
kEnrollSessionCancelMethod);
auto cancel_response = CallMethod(&cancel_enroll_session);
// Make sure enroll session is not killed on destruction
// of the enroll_session object. EXPECT_CALL is able to catch calls from
// enroll_session destructor which is called at the end of this test.
EXPECT_CALL(*object, Unregister).Times(0);
EXPECT_CALL(*bio_manager_, EndEnrollSession).Times(0);
}
TEST_F(BiometricsManagerWrapperTest, TestEnrollSessionFinish) {
dbus::ObjectPath object_path;
auto enroll_session = BiometricsManager::EnrollSession(
bio_manager_->session_weak_factory_.GetWeakPtr());
EXPECT_CALL(*bio_manager_, StartEnrollSession)
.WillOnce(Return(ByMove(std::move(enroll_session))));
EXPECT_CALL(*session_manager_, GetPrimaryUser)
.WillRepeatedly(Return(kUserID));
auto response = StartEnrollSession(kUserID, kLabel, &object_path);
EXPECT_TRUE(response->GetMessageType() ==
dbus::Message::MESSAGE_METHOD_RETURN);
// Expect enroll session is active when not finished.
auto iter = exported_objects_.find(object_path.value());
ASSERT_TRUE(iter != exported_objects_.end());
scoped_refptr<dbus::MockExportedObject> object = iter->second;
EXPECT_CALL(*object, Unregister).Times(0);
EXPECT_CALL(*bio_manager_, EndEnrollSession).Times(0);
BiometricsManager::EnrollStatus enroll_status = {false, 50};
on_enroll_scan_done.Run(ScanResult::SCAN_RESULT_SUCCESS, enroll_status);
// Finish enroll session.
EXPECT_CALL(*object, Unregister).Times(1);
EXPECT_CALL(*bio_manager_, EndEnrollSession).Times(1);
BiometricsManager::EnrollStatus enroll_status_finish = {true, 100};
on_enroll_scan_done.Run(ScanResult::SCAN_RESULT_SUCCESS,
enroll_status_finish);
}
TEST_F(BiometricsManagerWrapperTest, TestEnrollSessionSignal) {
dbus::ObjectPath object_path;
auto enroll_session = BiometricsManager::EnrollSession(
bio_manager_->session_weak_factory_.GetWeakPtr());
EXPECT_CALL(*bio_manager_, StartEnrollSession)
.WillOnce(Return(ByMove(std::move(enroll_session))));
EXPECT_CALL(*session_manager_, GetPrimaryUser)
.WillRepeatedly(Return(kUserID));
auto response = StartEnrollSession(kUserID, kLabel, &object_path);
EXPECT_TRUE(response->GetMessageType() ==
dbus::Message::MESSAGE_METHOD_RETURN);
// Expect enroll scan done signal is emitted when enroll session not finished.
auto iter = exported_objects_.find(mock_bio_path_.value());
ASSERT_TRUE(iter != exported_objects_.end());
scoped_refptr<dbus::MockExportedObject> object = iter->second;
EXPECT_CALL(*object, SendSignal).WillOnce([](dbus::Signal* signal) {
EXPECT_EQ(signal->GetInterface(), kBiometricsManagerInterface);
EXPECT_EQ(signal->GetMember(), kBiometricsManagerEnrollScanDoneSignal);
dbus::MessageReader reader(signal);
EnrollScanDone proto;
reader.PopArrayOfBytesAsProto(&proto);
EXPECT_FALSE(proto.done());
EXPECT_EQ(proto.scan_result(), ScanResult::SCAN_RESULT_SUCCESS);
EXPECT_EQ(proto.percent_complete(), 50);
});
BiometricsManager::EnrollStatus enroll_status = {false, 50};
on_enroll_scan_done.Run(ScanResult::SCAN_RESULT_SUCCESS, enroll_status);
// Finish enroll session.
EXPECT_CALL(*object, SendSignal).WillOnce([](dbus::Signal* signal) {
EXPECT_EQ(signal->GetInterface(), kBiometricsManagerInterface);
EXPECT_EQ(signal->GetMember(), kBiometricsManagerEnrollScanDoneSignal);
dbus::MessageReader reader(signal);
EnrollScanDone proto;
reader.PopArrayOfBytesAsProto(&proto);
EXPECT_TRUE(proto.done());
EXPECT_EQ(proto.scan_result(), ScanResult::SCAN_RESULT_SUCCESS);
EXPECT_EQ(proto.percent_complete(), 100);
});
BiometricsManager::EnrollStatus enroll_status_finish = {true, 100};
on_enroll_scan_done.Run(ScanResult::SCAN_RESULT_SUCCESS,
enroll_status_finish);
}
TEST_F(BiometricsManagerWrapperTest, TestEnrollSessionRefreshRecords) {
dbus::ObjectPath object_path;
auto enroll_session = BiometricsManager::EnrollSession(
bio_manager_->session_weak_factory_.GetWeakPtr());
EXPECT_CALL(*bio_manager_, StartEnrollSession)
.WillOnce(Return(ByMove(std::move(enroll_session))));
EXPECT_CALL(*session_manager_, GetPrimaryUser)
.WillRepeatedly(Return(kUserID));
auto response = StartEnrollSession(kUserID, kLabel, &object_path);
EXPECT_TRUE(response->GetMessageType() ==
dbus::Message::MESSAGE_METHOD_RETURN);
// Expect we won't refresh records when enroll session is not finished.
auto iter = exported_objects_.find(mock_bio_path_.value());
ASSERT_TRUE(iter != exported_objects_.end());
EXPECT_CALL(*bio_manager_, GetLoadedRecords).Times(0);
BiometricsManager::EnrollStatus enroll_status = {false, 50};
on_enroll_scan_done.Run(ScanResult::SCAN_RESULT_SUCCESS, enroll_status);
// Finish enroll session.
EXPECT_CALL(*bio_manager_, GetLoadedRecords).Times(1);
BiometricsManager::EnrollStatus enroll_status_finish = {true, 100};
on_enroll_scan_done.Run(ScanResult::SCAN_RESULT_SUCCESS,
enroll_status_finish);
}
TEST_F(BiometricsManagerWrapperTest, TestOnEnrollScanDoneWithoutActiveSession) {
auto iter = exported_objects_.find(mock_bio_path_.value());
ASSERT_TRUE(iter != exported_objects_.end());
scoped_refptr<dbus::MockExportedObject> object = iter->second;
// Expect we won't refresh records when enroll session was not started.
EXPECT_CALL(*bio_manager_, GetLoadedRecords).Times(0);
// Expect that no signal will be sent when there is no enroll session.
EXPECT_CALL(*object, SendSignal).Times(0);
BiometricsManager::EnrollStatus enroll_status_finish = {true, 100};
on_enroll_scan_done.Run(ScanResult::SCAN_RESULT_SUCCESS,
enroll_status_finish);
}
TEST_F(BiometricsManagerWrapperTest, TestStartEnrollSessionFailed) {
dbus::ObjectPath object_path;
// Empty enroll session indicates that we were not able to start
// enroll session.
auto enroll_session = BiometricsManager::EnrollSession();
EXPECT_CALL(*bio_manager_, StartEnrollSession)
.WillOnce(Return(ByMove(std::move(enroll_session))));
EXPECT_CALL(*session_manager_, GetPrimaryUser).WillOnce(Return(kUserID));
auto response = StartEnrollSession(kUserID, kLabel, &object_path);
EXPECT_TRUE(response->GetMessageType() == dbus::Message::MESSAGE_ERROR);
}
TEST_F(BiometricsManagerWrapperTest,
TestStartEnrollSessionFailedNoPrimaryUser) {
dbus::ObjectPath object_path;
EXPECT_CALL(*bio_manager_, StartEnrollSession).Times(0);
// Empty string means that primary user is not set.
EXPECT_CALL(*session_manager_, GetPrimaryUser).WillOnce(Return(""));
auto response = StartEnrollSession(kUserID, kLabel, &object_path);
EXPECT_TRUE(response->GetMessageType() == dbus::Message::MESSAGE_ERROR);
}
TEST_F(BiometricsManagerWrapperTest, TestStartEnrollSessionFailedWithErrors) {
dbus::ObjectPath object_path;
const std::string enroll_session_error = kFpHwUnavailable;
auto enroll_session = BiometricsManager::EnrollSession();
enroll_session.set_error(enroll_session_error);
EXPECT_CALL(*session_manager_, GetPrimaryUser).WillOnce(Return(kUserID));
EXPECT_CALL(*bio_manager_, StartEnrollSession)
.WillOnce(Return(ByMove(std::move(enroll_session))));
auto response = StartEnrollSession(kUserID, kLabel, &object_path);
EXPECT_EQ(response->GetMessageType(), dbus::Message::MESSAGE_ERROR);
EXPECT_THAT(response->ToString(), testing::HasSubstr(kFpHwUnavailable));
}
TEST_F(BiometricsManagerWrapperTest, TestOnSessionFailedEndsEnrollSession) {
dbus::ObjectPath object_path;
auto enroll_session = BiometricsManager::EnrollSession(
bio_manager_->session_weak_factory_.GetWeakPtr());
EXPECT_CALL(*bio_manager_, StartEnrollSession)
.WillOnce(Return(ByMove(std::move(enroll_session))));
EXPECT_CALL(*session_manager_, GetPrimaryUser).WillOnce(Return(kUserID));
auto response = StartEnrollSession(kUserID, kLabel, &object_path);
EXPECT_TRUE(response->GetMessageType() ==
dbus::Message::MESSAGE_METHOD_RETURN);
// Fail enroll session.
auto iter = exported_objects_.find(object_path.value());
ASSERT_TRUE(iter != exported_objects_.end());
scoped_refptr<dbus::MockExportedObject> object = iter->second;
EXPECT_CALL(*object, Unregister).Times(1);
EXPECT_CALL(*bio_manager_, EndEnrollSession).Times(1);
on_session_failed.Run();
// Make sure enroll session is not killed on destruction
// of the enroll_session object. EXPECT_CALL is able to catch calls from
// enroll_session destructor which is called at the end of this test.
EXPECT_CALL(*object, Unregister).Times(0);
EXPECT_CALL(*bio_manager_, EndEnrollSession).Times(0);
}
TEST_F(BiometricsManagerWrapperTest, TestEnrollOnSessionFailedSendSignal) {
dbus::ObjectPath object_path;
auto enroll_session = BiometricsManager::EnrollSession(
bio_manager_->session_weak_factory_.GetWeakPtr());
EXPECT_CALL(*bio_manager_, StartEnrollSession)
.WillOnce(Return(ByMove(std::move(enroll_session))));
EXPECT_CALL(*session_manager_, GetPrimaryUser).WillOnce(Return(kUserID));
auto response = StartEnrollSession(kUserID, kLabel, &object_path);
EXPECT_TRUE(response->GetMessageType() ==
dbus::Message::MESSAGE_METHOD_RETURN);
auto iter = exported_objects_.find(mock_bio_path_.value());
ASSERT_TRUE(iter != exported_objects_.end());
scoped_refptr<dbus::MockExportedObject> object = iter->second;
EXPECT_CALL(*object, SendSignal).WillOnce([](dbus::Signal* signal) {
EXPECT_EQ(signal->GetInterface(), kBiometricsManagerInterface);
EXPECT_EQ(signal->GetMember(), kBiometricsManagerSessionFailedSignal);
});
// Fail enroll session.
on_session_failed.Run();
}
TEST_F(BiometricsManagerWrapperTest, TestEnrollSessionOwnerDies) {
dbus::ObjectPath object_path;
auto enroll_session = BiometricsManager::EnrollSession(
bio_manager_->session_weak_factory_.GetWeakPtr());
EXPECT_CALL(*bio_manager_, StartEnrollSession)
.WillOnce(Return(ByMove(std::move(enroll_session))));
EXPECT_CALL(*session_manager_, GetPrimaryUser).WillOnce(Return(kUserID));
auto response = StartEnrollSession(kUserID, kLabel, &object_path);
EXPECT_TRUE(response->GetMessageType() ==
dbus::Message::MESSAGE_METHOD_RETURN);
// Fail enroll session.
auto iter = exported_objects_.find(object_path.value());
ASSERT_TRUE(iter != exported_objects_.end());
scoped_refptr<dbus::MockExportedObject> object = iter->second;
EXPECT_CALL(*object, Unregister).Times(1);
EXPECT_CALL(*bio_manager_, EndEnrollSession).Times(1);
EmitNameOwnerChangedSignal(kClientConnectionName, kClientConnectionName, "");
// Make sure enroll session is not killed on destruction
// of the enroll_session object. EXPECT_CALL is able to catch calls from
// enroll_session destructor which is called at the end of this test.
EXPECT_CALL(*object, Unregister).Times(0);
EXPECT_CALL(*bio_manager_, EndEnrollSession).Times(0);
}
TEST_F(BiometricsManagerWrapperTest, TestStartAuthSession) {
dbus::ObjectPath object_path;
auto auth_session = BiometricsManager::AuthSession(
bio_manager_->session_weak_factory_.GetWeakPtr());
EXPECT_CALL(*bio_manager_, StartAuthSession)
.WillOnce(Return(ByMove(std::move(auth_session))));
EXPECT_CALL(*session_manager_, GetPrimaryUser).WillOnce(Return(kUserID));
auto response = StartAuthSession(&object_path);
EXPECT_TRUE(response->GetMessageType() ==
dbus::Message::MESSAGE_METHOD_RETURN);
dbus::ObjectPath expected_object_path(mock_bio_path_.value() +
"/AuthSession");
EXPECT_EQ(object_path, expected_object_path);
// Expect that auth session will be killed on destruction of the auth_sesson
// object. EXPECT_CALL is able to catch calls from auth_session destructor
// which is called at the end of this test.
auto iter = exported_objects_.find(object_path.value());
ASSERT_TRUE(iter != exported_objects_.end());
scoped_refptr<dbus::MockExportedObject> object = iter->second;
EXPECT_CALL(*object, Unregister).Times(1);
EXPECT_CALL(*bio_manager_, EndAuthSession).Times(1);
}
TEST_F(BiometricsManagerWrapperTest, TestStartAuthSessionThenEnd) {
dbus::ObjectPath object_path;
auto auth_session = BiometricsManager::AuthSession(
bio_manager_->session_weak_factory_.GetWeakPtr());
EXPECT_CALL(*bio_manager_, StartAuthSession)
.WillOnce(Return(ByMove(std::move(auth_session))));
EXPECT_CALL(*session_manager_, GetPrimaryUser).WillOnce(Return(kUserID));
auto response = StartAuthSession(&object_path);
EXPECT_TRUE(response->GetMessageType() ==
dbus::Message::MESSAGE_METHOD_RETURN);
// Cancel auth session.
auto iter = exported_objects_.find(object_path.value());
ASSERT_TRUE(iter != exported_objects_.end());
scoped_refptr<dbus::MockExportedObject> object = iter->second;
EXPECT_CALL(*object, Unregister).Times(1);
EXPECT_CALL(*bio_manager_, EndAuthSession).Times(1);
dbus::MethodCall end_auth_session(kAuthSessionInterface,
kAuthSessionEndMethod);
auto cancel_response = CallMethod(&end_auth_session);
// Make sure auth session is not killed on destruction of the auth_session
// object. EXPECT_CALL is able to catch calls from auth_session destructor
// which is called at the end of this test.
EXPECT_CALL(*object, Unregister).Times(0);
EXPECT_CALL(*bio_manager_, EndAuthSession).Times(0);
}
TEST_F(BiometricsManagerWrapperTest, TestStartAuthSessionSuccess) {
dbus::ObjectPath object_path;
auto auth_session = BiometricsManager::AuthSession(
bio_manager_->session_weak_factory_.GetWeakPtr());
EXPECT_CALL(*bio_manager_, StartAuthSession)
.WillOnce(Return(ByMove(std::move(auth_session))));
EXPECT_CALL(*session_manager_, GetPrimaryUser).WillOnce(Return(kUserID));
auto response = StartAuthSession(&object_path);
EXPECT_TRUE(response->GetMessageType() ==
dbus::Message::MESSAGE_METHOD_RETURN);
// Expect that calling OnAuthScanDone doesn't end auth session.
auto iter = exported_objects_.find(object_path.value());
ASSERT_TRUE(iter != exported_objects_.end());
scoped_refptr<dbus::MockExportedObject> object = iter->second;
EXPECT_CALL(*object, Unregister).Times(0);
EXPECT_CALL(*bio_manager_, EndAuthSession).Times(0);
BiometricsManager::AttemptMatches matches;
FingerprintMessage result;
matches.emplace(kUserID, std::vector<std::string>({kRecordID}));
result.set_scan_result(ScanResult::SCAN_RESULT_SUCCESS);
on_auth_scan_done.Run(std::move(result), std::move(matches));
// Expect that auth session will be killed on destruction of the auth_session
// object. EXPECT_CALL is able to catch calls from auth_session destructor
// which is called at the end of this test.
EXPECT_CALL(*object, Unregister).Times(1);
EXPECT_CALL(*bio_manager_, EndAuthSession).Times(1);
}
TEST_F(BiometricsManagerWrapperTest, TestStartAuthSessionSuccessSignal) {
dbus::ObjectPath object_path;
auto auth_session = BiometricsManager::AuthSession(
bio_manager_->session_weak_factory_.GetWeakPtr());
EXPECT_CALL(*bio_manager_, StartAuthSession)
.WillOnce(Return(ByMove(std::move(auth_session))));
EXPECT_CALL(*session_manager_, GetPrimaryUser).WillOnce(Return(kUserID));
auto response = StartAuthSession(&object_path);
EXPECT_TRUE(response->GetMessageType() ==
dbus::Message::MESSAGE_METHOD_RETURN);
BiometricsManager::AttemptMatches matches;
FingerprintMessage result;
matches.emplace(kUserID, std::vector<std::string>({kRecordID}));
result.set_scan_result(ScanResult::SCAN_RESULT_SUCCESS);
// Check signal contents.
auto iter = exported_objects_.find(mock_bio_path_.value());
ASSERT_TRUE(iter != exported_objects_.end());
scoped_refptr<dbus::MockExportedObject> object = iter->second;
EXPECT_CALL(*object, SendSignal)
.WillOnce([&result, this](dbus::Signal* signal) {
EXPECT_EQ(signal->GetInterface(), kBiometricsManagerInterface);
EXPECT_EQ(signal->GetMember(), kBiometricsManagerAuthScanDoneSignal);
dbus::MessageReader reader(signal);
dbus::MessageReader array_reader(nullptr);
dbus::MessageReader dict_reader(nullptr);
FingerprintMessage proto;
std::string user_id;
std::vector<dbus::ObjectPath> paths;
dbus::ObjectPath record_path(mock_bio_path_.value() + "/Record" +
kRecordID);
EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&proto));
EXPECT_TRUE(reader.PopArray(&array_reader));
EXPECT_TRUE(array_reader.PopDictEntry(&dict_reader));
EXPECT_TRUE(dict_reader.PopString(&user_id));
EXPECT_TRUE(dict_reader.PopArrayOfObjectPaths(&paths));
EXPECT_EQ(paths, std::vector{record_path});
EXPECT_EQ(result.scan_result(), proto.scan_result());
EXPECT_EQ(user_id, kUserID);
});
on_auth_scan_done.Run(std::move(result), std::move(matches));
}
TEST_F(BiometricsManagerWrapperTest, TestStartAuthSessionFailedWithErrors) {
dbus::ObjectPath object_path;
std::string auth_session_error = kFpHwUnavailable;
auto auth_session = BiometricsManager::AuthSession();
auth_session.set_error(auth_session_error);
EXPECT_CALL(*session_manager_, GetPrimaryUser).WillOnce(Return(kUserID));
EXPECT_CALL(*bio_manager_, StartAuthSession)
.WillOnce(Return(ByMove(std::move(auth_session))));
auto response = StartAuthSession(&object_path);
EXPECT_EQ(response->GetMessageType(), dbus::Message::MESSAGE_ERROR);
EXPECT_THAT(response->ToString(), testing::HasSubstr(auth_session_error));
}
TEST_F(BiometricsManagerWrapperTest, TestStartAuthSessionFailed) {
dbus::ObjectPath object_path;
// Empty auth session indicates that we were not able to start
// enroll session.
auto auth_session = BiometricsManager::AuthSession();
EXPECT_CALL(*bio_manager_, StartAuthSession)
.WillOnce(Return(ByMove(std::move(auth_session))));
EXPECT_CALL(*session_manager_, GetPrimaryUser).WillOnce(Return(kUserID));
auto response = StartAuthSession(&object_path);
EXPECT_TRUE(response->GetMessageType() == dbus::Message::MESSAGE_ERROR);
}
TEST_F(BiometricsManagerWrapperTest, TestStartAuthSessionFailedNoPrimaryUser) {
dbus::ObjectPath object_path;
EXPECT_CALL(*bio_manager_, StartAuthSession).Times(0);
// Empty string means that primary user is not set.
EXPECT_CALL(*session_manager_, GetPrimaryUser).WillOnce(Return(""));
auto response = StartAuthSession(&object_path);
EXPECT_TRUE(response->GetMessageType() == dbus::Message::MESSAGE_ERROR);
}
TEST_F(BiometricsManagerWrapperTest, TestOnSessionFailedEndsAuthSession) {
dbus::ObjectPath object_path;
auto auth_session = BiometricsManager::AuthSession(
bio_manager_->session_weak_factory_.GetWeakPtr());
EXPECT_CALL(*bio_manager_, StartAuthSession)
.WillOnce(Return(ByMove(std::move(auth_session))));
EXPECT_CALL(*session_manager_, GetPrimaryUser).WillOnce(Return(kUserID));
auto response = StartAuthSession(&object_path);
EXPECT_TRUE(response->GetMessageType() ==
dbus::Message::MESSAGE_METHOD_RETURN);
// Cancel auth session.
auto iter = exported_objects_.find(object_path.value());
ASSERT_TRUE(iter != exported_objects_.end());
scoped_refptr<dbus::MockExportedObject> object = iter->second;
EXPECT_CALL(*object, Unregister).Times(1);
EXPECT_CALL(*bio_manager_, EndAuthSession).Times(1);
on_session_failed.Run();
// Make sure auth session is not killed on destruction of the auth_session
// object. EXPECT_CALL is able to catch calls from auth_session destructor
// which is called at the end of this test.
EXPECT_CALL(*object, Unregister).Times(0);
EXPECT_CALL(*bio_manager_, EndAuthSession).Times(0);
}
TEST_F(BiometricsManagerWrapperTest, TestAuthOnSessionFailedSendsSignal) {
dbus::ObjectPath object_path;
auto auth_session = BiometricsManager::AuthSession(
bio_manager_->session_weak_factory_.GetWeakPtr());
EXPECT_CALL(*bio_manager_, StartAuthSession)
.WillOnce(Return(ByMove(std::move(auth_session))));
EXPECT_CALL(*session_manager_, GetPrimaryUser).WillOnce(Return(kUserID));
auto response = StartAuthSession(&object_path);
EXPECT_TRUE(response->GetMessageType() ==
dbus::Message::MESSAGE_METHOD_RETURN);
auto iter = exported_objects_.find(mock_bio_path_.value());
ASSERT_TRUE(iter != exported_objects_.end());
scoped_refptr<dbus::MockExportedObject> object = iter->second;
EXPECT_CALL(*object, SendSignal).WillOnce([](dbus::Signal* signal) {
EXPECT_EQ(signal->GetInterface(), kBiometricsManagerInterface);
EXPECT_EQ(signal->GetMember(), kBiometricsManagerSessionFailedSignal);
});
// Fail enroll session.
on_session_failed.Run();
}
TEST_F(BiometricsManagerWrapperTest, TestAuthSessionOwnerDies) {
dbus::ObjectPath object_path;
auto auth_session = BiometricsManager::AuthSession(
bio_manager_->session_weak_factory_.GetWeakPtr());
EXPECT_CALL(*bio_manager_, StartAuthSession)
.WillOnce(Return(ByMove(std::move(auth_session))));
EXPECT_CALL(*session_manager_, GetPrimaryUser).WillOnce(Return(kUserID));
auto response = StartAuthSession(&object_path);
EXPECT_TRUE(response->GetMessageType() ==
dbus::Message::MESSAGE_METHOD_RETURN);
// Cancel auth session.
auto iter = exported_objects_.find(object_path.value());
ASSERT_TRUE(iter != exported_objects_.end());
scoped_refptr<dbus::MockExportedObject> object = iter->second;
EXPECT_CALL(*object, Unregister).Times(1);
EXPECT_CALL(*bio_manager_, EndAuthSession).Times(1);
EmitNameOwnerChangedSignal(kClientConnectionName, kClientConnectionName, "");
// Make sure auth session is not killed on destruction of the auth_session
// object. EXPECT_CALL is able to catch calls from auth_session destructor
// which is called at the end of this test.
EXPECT_CALL(*object, Unregister).Times(0);
EXPECT_CALL(*bio_manager_, EndAuthSession).Times(0);
}
TEST_F(BiometricsManagerWrapperTest, TestRefreshRecordObjectsNoPrimaryUser) {
// Empty string means that primary user is not set.
EXPECT_CALL(*session_manager_, GetPrimaryUser).WillOnce(Return(""));
EXPECT_CALL(*bio_manager_, GetLoadedRecords).Times(0);
EXPECT_CALL(*object_manager_, ClaimInterface).Times(0);
wrapper_->RefreshRecordObjects();
}
TEST_F(BiometricsManagerWrapperTest, TestRefreshRecordObjectsNoRecords) {
EXPECT_CALL(*session_manager_, GetPrimaryUser).WillOnce(Return(kUserID));
EXPECT_CALL(*bio_manager_, GetLoadedRecords).Times(1);
EXPECT_CALL(*object_manager_, ClaimInterface).Times(0);
wrapper_->RefreshRecordObjects();
}
TEST_F(BiometricsManagerWrapperTest, TestRefreshRecordObjects) {
auto record = std::make_unique<MockBiometricsManagerRecord>();
std::string record_id(kRecordID);
EXPECT_CALL(*record, GetId).WillRepeatedly(ReturnRef(record_id));
EXPECT_CALL(*record, GetUserId).WillRepeatedly(Return(kUserID));
std::vector<std::unique_ptr<BiometricsManagerRecordInterface>> records;
records.emplace_back(std::move(record));
EXPECT_CALL(*session_manager_, GetPrimaryUser)
.WillRepeatedly(Return(kUserID));
EXPECT_CALL(*bio_manager_, GetLoadedRecords)
.WillOnce(Return(ByMove(std::move(records))));
// Calling ClaimInterface is enough to make sure that record was constructed.
dbus::ObjectPath record_path(mock_bio_path_.value() + "/Record" + kRecordID);
EXPECT_CALL(*object_manager_,
ClaimInterface(record_path, dbus::kPropertiesInterface, _))
.Times(1);
EXPECT_CALL(*object_manager_,
ClaimInterface(record_path, kRecordInterface, _))
.Times(1);
wrapper_->RefreshRecordObjects();
// Check if proper record object path is returned
std::vector<dbus::ObjectPath> paths;
GetRecordsForUser(kUserID, &paths);
EXPECT_EQ(paths, std::vector{record_path});
}
TEST_F(BiometricsManagerWrapperTest, TestGetRecordsForUser) {
auto record = std::make_unique<MockBiometricsManagerRecord>();
std::string record_id(kRecordID);
EXPECT_CALL(*record, GetId).WillRepeatedly(ReturnRef(record_id));
EXPECT_CALL(*record, GetUserId).WillRepeatedly(Return(kUserID));
std::vector<std::unique_ptr<BiometricsManagerRecordInterface>> records;
records.emplace_back(std::move(record));
EXPECT_CALL(*session_manager_, GetPrimaryUser)
.WillRepeatedly(Return(kUserID));
EXPECT_CALL(*bio_manager_, GetLoadedRecords)
.WillOnce(Return(ByMove(std::move(records))));
wrapper_->RefreshRecordObjects();
// Check if for correct UserID proper record object path is returned.
dbus::ObjectPath record_path(mock_bio_path_.value() + "/Record" + kRecordID);
std::vector<dbus::ObjectPath> paths;
GetRecordsForUser(kUserID, &paths);
EXPECT_EQ(paths, std::vector{record_path});
// Check if for wrong UserID, nothing is returned.
paths.clear();
GetRecordsForUser(kUserID2, &paths);
EXPECT_EQ(paths.size(), 0);
}
TEST_F(BiometricsManagerWrapperTest, TestGetRecordsForUserNoPrimaryUser) {
std::vector<dbus::ObjectPath> paths;
EXPECT_CALL(*session_manager_, GetPrimaryUser).WillOnce(Return(""));
auto response = GetRecordsForUser(kUserID, &paths);
EXPECT_EQ(response->GetMessageType(), dbus::Message::MESSAGE_ERROR);
}
TEST_F(BiometricsManagerWrapperTest, TestRefreshRecordObjectsClearsRecords) {
auto record = std::make_unique<MockBiometricsManagerRecord>();
std::string record_id(kRecordID);
EXPECT_CALL(*record, GetId).WillRepeatedly(ReturnRef(record_id));
EXPECT_CALL(*record, GetUserId).WillRepeatedly(Return(kUserID));
EXPECT_CALL(*session_manager_, GetPrimaryUser)
.WillRepeatedly(Return(kUserID));
// Load one record.
std::vector<std::unique_ptr<BiometricsManagerRecordInterface>> records;
records.emplace_back(std::move(record));
EXPECT_CALL(*bio_manager_, GetLoadedRecords)
.WillOnce(Return(ByMove(std::move(records))));
wrapper_->RefreshRecordObjects();
// Get object path to loaded record.
dbus::ObjectPath record_path(mock_bio_path_.value() + "/Record" + kRecordID);
std::vector<dbus::ObjectPath> paths;
GetRecordsForUser(kUserID, &paths);
EXPECT_EQ(paths, std::vector{record_path});
// Refresh record objects but don't load any records.
records.clear();
EXPECT_CALL(*bio_manager_, GetLoadedRecords)
.WillOnce(Return(ByMove(std::move(records))));
wrapper_->RefreshRecordObjects();
// Check if there are no loaded records.
paths.clear();
GetRecordsForUser(kUserID, &paths);
EXPECT_EQ(paths.size(), 0);
}
TEST_F(BiometricsManagerWrapperTest,
TestRefreshRecordObjectsNoPrimaryUserClearsRecords) {
auto record = std::make_unique<MockBiometricsManagerRecord>();
std::string record_id(kRecordID);
EXPECT_CALL(*record, GetId).WillRepeatedly(ReturnRef(record_id));
EXPECT_CALL(*record, GetUserId).WillRepeatedly(Return(kUserID));
EXPECT_CALL(*session_manager_, GetPrimaryUser)
.WillRepeatedly(Return(kUserID));
// Load one record.
std::vector<std::unique_ptr<BiometricsManagerRecordInterface>> records;
records.emplace_back(std::move(record));
EXPECT_CALL(*bio_manager_, GetLoadedRecords)
.WillOnce(Return(ByMove(std::move(records))));
wrapper_->RefreshRecordObjects();
// Get object path to loaded record.
dbus::ObjectPath record_path(mock_bio_path_.value() + "/Record" + kRecordID);
std::vector<dbus::ObjectPath> paths;
GetRecordsForUser(kUserID, &paths);
EXPECT_EQ(paths, std::vector{record_path});
// Refresh record objects when primary user is not available.
EXPECT_CALL(*session_manager_, GetPrimaryUser).WillRepeatedly(Return(""));
EXPECT_CALL(*bio_manager_, GetLoadedRecords).Times(0);
wrapper_->RefreshRecordObjects();
// Check if there are no loaded records.
EXPECT_CALL(*session_manager_, GetPrimaryUser)
.WillRepeatedly(Return(kUserID));
paths.clear();
GetRecordsForUser(kUserID, &paths);
EXPECT_EQ(paths.size(), 0);
}
TEST_F(BiometricsManagerWrapperTest, TestDestroyAllRecordsFailedNoPrimaryUser) {
// Empty string means that primary user is not set.
EXPECT_CALL(*session_manager_, GetPrimaryUser).WillOnce(Return(""));
EXPECT_CALL(*bio_manager_, DestroyAllRecords).Times(0);
dbus::MethodCall destroy_all_records(
kBiometricsManagerInterface, kBiometricsManagerDestroyAllRecordsMethod);
auto response = CallMethod(&destroy_all_records);
EXPECT_EQ(response->GetMessageType(), dbus::Message::MESSAGE_ERROR);
}
TEST_F(BiometricsManagerWrapperTest, TestDestroyAllRecordsFailed) {
EXPECT_CALL(*session_manager_, GetPrimaryUser).WillOnce(Return(kUserID));
EXPECT_CALL(*bio_manager_, DestroyAllRecords).WillOnce(Return(false));
dbus::MethodCall destroy_all_records(
kBiometricsManagerInterface, kBiometricsManagerDestroyAllRecordsMethod);
auto response = CallMethod(&destroy_all_records);
EXPECT_EQ(response->GetMessageType(), dbus::Message::MESSAGE_ERROR);
}
TEST_F(BiometricsManagerWrapperTest, TestDestroyAllRecords) {
EXPECT_CALL(*session_manager_, GetPrimaryUser)
.WillRepeatedly(Return(kUserID));
EXPECT_CALL(*bio_manager_, DestroyAllRecords).WillOnce(Return(true));
// Expect refreshing records.
EXPECT_CALL(*bio_manager_, GetLoadedRecords).Times(1);
dbus::MethodCall destroy_all_records(
kBiometricsManagerInterface, kBiometricsManagerDestroyAllRecordsMethod);
auto response = CallMethod(&destroy_all_records);
EXPECT_EQ(response->GetMessageType(), dbus::Message::MESSAGE_METHOD_RETURN);
}
TEST_F(BiometricsManagerWrapperTest, TestOnUserLoggedInResetSensor) {
EXPECT_CALL(*bio_manager_, ResetSensor).WillOnce(Return(true));
wrapper_->OnUserLoggedIn(kUserID, false);
}
TEST_F(BiometricsManagerWrapperTest, TestOnUserLoggedInResetSensorFailed) {
EXPECT_CALL(*bio_manager_, ResetSensor).WillOnce(Return(false));
wrapper_->OnUserLoggedIn(kUserID, false);
}
TEST_F(BiometricsManagerWrapperTest, TestOnUserLoggedInSendStatsTrue) {
EXPECT_CALL(*bio_manager_, SendStatsOnLogin).Times(1);
wrapper_->OnUserLoggedIn(kUserID, true);
}
TEST_F(BiometricsManagerWrapperTest, TestOnUserLoggedInSendStatsFalse) {
EXPECT_CALL(*bio_manager_, SendStatsOnLogin).Times(0);
wrapper_->OnUserLoggedIn(kUserID, false);
}
TEST_F(BiometricsManagerWrapperTest, TestOnUserLoggedIn) {
EXPECT_CALL(*session_manager_, GetPrimaryUser)
.WillRepeatedly(Return(kUserID));
// User is logged in, so expect to allow disk access.
EXPECT_CALL(*bio_manager_, SetDiskAccesses(true)).Times(1);
// When access to records is allowed, then we expect to read records for user.
EXPECT_CALL(*bio_manager_, ReadRecordsForSingleUser(kUserID)).Times(1);
// Expect to get list of records that are loaded.
EXPECT_CALL(*bio_manager_, GetLoadedRecords).Times(1);
// Expect 'StatusChanged' signal is emitted.
auto iter = exported_objects_.find(mock_bio_path_.value());
ASSERT_TRUE(iter != exported_objects_.end());
scoped_refptr<dbus::MockExportedObject> object = iter->second;
EXPECT_CALL(*object, SendSignal).WillOnce([](dbus::Signal* signal) {
EXPECT_EQ(signal->GetInterface(), kBiometricsManagerInterface);
EXPECT_EQ(signal->GetMember(), kBiometricsManagerStatusChangedSignal);
dbus::MessageReader reader(signal);
BiometricsManagerStatusChanged proto;
reader.PopArrayOfBytesAsProto(&proto);
EXPECT_EQ(proto.status(), BiometricsManagerStatus::INITIALIZED);
});
wrapper_->OnUserLoggedIn(kUserID, false);
}
TEST_F(BiometricsManagerWrapperTest, TestOnUserLoggedOut) {
EXPECT_CALL(*session_manager_, GetPrimaryUser)
.WillRepeatedly(Return(kUserID));
// User is logged in, so expect to forbid disk access.
EXPECT_CALL(*bio_manager_, SetDiskAccesses(false)).Times(1);
// Remove all records from biometrics daemon memory and FPMCU.
EXPECT_CALL(*bio_manager_, RemoveRecordsFromMemory).Times(1);
// Expect that records are refreshed (part RefreshRecordObject()).
EXPECT_CALL(*bio_manager_, GetLoadedRecords).Times(1);
wrapper_->OnUserLoggedOut();
}
// This test will validate that a hibernate resume ends existing enroll sessions
TEST_F(BiometricsManagerWrapperTest,
TestHibernateResumeEndsExistingEnrollSessions) {
// Start an enroll session before we "resume".
dbus::ObjectPath object_path;
auto enroll_session = BiometricsManager::EnrollSession(
bio_manager_->session_weak_factory_.GetWeakPtr());
EXPECT_CALL(*bio_manager_, StartEnrollSession)
.WillOnce(Return(ByMove(std::move(enroll_session))));
// We will expect a call to GetPrimaryUser for starting the enroll session,
// and we will get a second call for ReadRecordsForSingleUser which is called
// on OnSessionResumedFromHibernate.
EXPECT_CALL(*session_manager_, GetPrimaryUser)
.Times(2)
.WillRepeatedly(Return(kUserID));
// The enroll session will start normally.
auto response = StartEnrollSession(kUserID, kLabel, &object_path);
EXPECT_TRUE(response->GetMessageType() ==
dbus::Message::MESSAGE_METHOD_RETURN);
// Now by calling OnSessionResumedFromHibernate we will expect that the
// session will be ended.
EXPECT_CALL(*bio_manager_, EndEnrollSession).Times(1);
wrapper_->OnSessionResumedFromHibernate();
}
// This test will validate that a hibernate resume ends existing auth sessions
// and starts a new one.
TEST_F(BiometricsManagerWrapperTest,
TestHibernateResumeEndsExistingAuthSessions) {
// Start an AuthSession before our resume so we can verify it is ended.
dbus::ObjectPath object_path;
auto auth_session_pre_resume = BiometricsManager::AuthSession(
bio_manager_->session_weak_factory_.GetWeakPtr());
// The first auth session will be ended and we will return this auth session
// the second time.
auto auth_session_post_resume = BiometricsManager::AuthSession(
bio_manager_->session_weak_factory_.GetWeakPtr());
// We're creating an auth session before resume and the resume will cause that
// session to be ended and a new one to be created.
EXPECT_CALL(*bio_manager_, StartAuthSession)
.WillOnce(Return(ByMove(std::move(auth_session_pre_resume))))
.WillOnce(Return(ByMove(std::move(auth_session_post_resume))));
EXPECT_CALL(*session_manager_, GetPrimaryUser)
.Times(2)
.WillRepeatedly(Return(kUserID));
auto response = StartAuthSession(&object_path);
EXPECT_TRUE(response->GetMessageType() ==
dbus::Message::MESSAGE_METHOD_RETURN);
dbus::ObjectPath expected_object_path(mock_bio_path_.value() +
"/AuthSession");
EXPECT_EQ(object_path, expected_object_path);
// We expect the first auth session to be ended by the resume and the second
// one to be ended when the test ends.
EXPECT_CALL(*bio_manager_, EndAuthSession).Times(2);
wrapper_->OnSessionResumedFromHibernate();
}
// This test will validate that a hibernate resume reloads the fpmcu state.
TEST_F(BiometricsManagerWrapperTest,
TestHibernateResumeReloadsPrimaryUserRecords) {
EXPECT_CALL(*session_manager_, GetPrimaryUser).WillOnce(Return(kUserID));
EXPECT_CALL(*bio_manager_, ReadRecordsForSingleUser(kUserID));
wrapper_->OnSessionResumedFromHibernate();
}
// This test will validate that a hibernate resume without a primary user does
// nothing.
TEST_F(BiometricsManagerWrapperTest,
TestHibernateResumeOnlyProceedWithPrimaryUser) {
EXPECT_CALL(*session_manager_, GetPrimaryUser).WillOnce(Return(""));
EXPECT_CALL(*bio_manager_, ReadRecordsForSingleUser).Times(0);
wrapper_->OnSessionResumedFromHibernate();
}
} // namespace
} // namespace biod