blob: f6daee3df170645ed8f11cad5d6466b544f26e78 [file] [log] [blame]
// Copyright 2020 The Chromium OS 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 <functional>
#include <memory>
#include <utility>
#include <base/test/bind.h>
#include <chromeos/dbus/service_constants.h>
#include <dbus/bus.h>
#include <dbus/mock_bus.h>
#include <dbus/mock_object_proxy.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "biod/biod_proxy/biometrics_manager_proxy_base.h"
namespace biod {
using testing::_;
using testing::ByMove;
using testing::Return;
class BiometricsManagerProxyBaseTest : public testing::Test {
public:
BiometricsManagerProxyBaseTest() {
dbus::Bus::Options options;
options.bus_type = dbus::Bus::SYSTEM;
mock_bus_ = base::MakeRefCounted<dbus::MockBus>(options);
mock_object_proxy_ = base::MakeRefCounted<dbus::MockObjectProxy>(
mock_bus_.get(), kBiodServiceName, dbus::ObjectPath(kBiodServicePath));
// Set an expectation so that the MockBus will return our mock proxy.
EXPECT_CALL(*mock_bus_, GetObjectProxy(kBiodServiceName,
dbus::ObjectPath(kBiodServicePath)))
.WillOnce(Return(mock_object_proxy_.get()));
proxy_base_ = BiometricsManagerProxyBase::Create(
mock_bus_.get(), dbus::ObjectPath(kBiodServicePath));
}
void CallFinish(bool success) { proxy_base_->OnFinish(success); }
void CallOnSignalConnected(bool success) {
proxy_base_->OnSignalConnected("unused interface", "unused signal",
success);
}
void CallOnSessionFailed() { proxy_base_->OnSessionFailed(nullptr); }
dbus::ObjectProxy* GetBiodAuthSession() {
return proxy_base_->biod_auth_session_;
}
std::unique_ptr<BiometricsManagerProxyBase> proxy_base_;
scoped_refptr<dbus::MockObjectProxy> mock_object_proxy_;
scoped_refptr<dbus::MockBus> mock_bus_;
bool status_ = false;
};
namespace {
// Test that we can install and exercise a custom finish handler.
TEST_F(BiometricsManagerProxyBaseTest, RunFinishHandlerWithTrue) {
status_ = false;
proxy_base_->SetFinishHandler(
base::BindLambdaForTesting([this](bool success) { status_ = success; }));
CallFinish(true);
EXPECT_TRUE(status_);
}
// Test that we can install and exercise a custom finish handler.
TEST_F(BiometricsManagerProxyBaseTest, RunFinishHandlerWithFalse) {
status_ = true;
proxy_base_->SetFinishHandler(
base::BindLambdaForTesting([this](bool success) { status_ = success; }));
CallFinish(false);
EXPECT_FALSE(status_);
}
// Test that StartAuthSession returns nullptr if no dbus response.
TEST_F(BiometricsManagerProxyBaseTest, StartAuthSessionNoResponse) {
EXPECT_CALL(*mock_object_proxy_, CallMethodAndBlock)
.WillOnce(Return(ByMove(dbus::Response::CreateEmpty())));
EXPECT_FALSE(proxy_base_->StartAuthSession());
EXPECT_EQ(GetBiodAuthSession(), nullptr);
}
// Test that StartAuthSession succeeds and the object proxy saved by
// StartAuthSession is what the mock provides.
TEST_F(BiometricsManagerProxyBaseTest, StartAuthSessionGetSessionProxy) {
// The path must be correctly formatted for the writer to accept it.
const dbus::ObjectPath auth_session_path("/org/chromium/Foo/AuthSession");
auto fake_response = dbus::Response::CreateEmpty();
dbus::MessageWriter writer(fake_response.get());
writer.AppendObjectPath(auth_session_path);
auto auth_session_proxy = base::MakeRefCounted<dbus::MockObjectProxy>(
mock_bus_.get(), kBiodServiceName, auth_session_path);
// Set the underlying mock proxy to return our fake_response, and set the
// mock bus to return the predefined ObjectProxy once it sees that path,
// which the class under test will extract from the fake_response.
EXPECT_CALL(*mock_object_proxy_, CallMethodAndBlock)
.WillOnce(Return(ByMove(std::move(fake_response))));
EXPECT_CALL(*mock_bus_, GetObjectProxy(kBiodServiceName, auth_session_path))
.WillOnce(Return(auth_session_proxy.get()));
EXPECT_TRUE(proxy_base_->StartAuthSession());
EXPECT_EQ(GetBiodAuthSession(), auth_session_proxy.get());
}
// Test that StartAuthSessionAsync succeeds and the object proxy saved by
// StartAuthSession is what the mock provides.
TEST_F(BiometricsManagerProxyBaseTest, StartAuthSessionGetSessionProxyAsync) {
// The path must be correctly formatted for the writer to accept it.
const dbus::ObjectPath auth_session_path("/org/chromium/Foo/AuthSession");
auto auth_session_proxy = base::MakeRefCounted<dbus::MockObjectProxy>(
mock_bus_.get(), kBiodServiceName, auth_session_path);
// Set the underlying |mock_object_proxy_| to invoke the dbus callback (in
// this case OnStartAuthSessionResp) with a fake response containing
// |auth_session_path|.
auto ExecuteCallbackWithFakeResponse =
[auth_session_path](
dbus::MethodCall* unused_method, int unused_ms,
base::OnceCallback<void(dbus::Response*)>* dbus_callback) {
std::unique_ptr<dbus::Response> fake_response =
dbus::Response::CreateEmpty();
dbus::MessageWriter writer(fake_response.get());
writer.AppendObjectPath(auth_session_path);
std::move(*dbus_callback).Run(fake_response.get());
};
EXPECT_CALL(*mock_object_proxy_, DoCallMethod(_, _, _))
.WillOnce(ExecuteCallbackWithFakeResponse);
// Once OnStartAuthSessionResp is invoked with the fake response, it extracts
// |auth_session_path| from the fake response and asks |mock_bus_| for the
// corresponding ObjectProxy, which we set to be |auth_session_proxy|.
// If OnStartAuthSessionResp is unable to extract the correct ObjectPath, the
// bus will not return the correct ObjectProxy, which we catch in the end.
EXPECT_CALL(*mock_bus_, GetObjectProxy(kBiodServiceName, auth_session_path))
.WillOnce(Return(auth_session_proxy.get()));
status_ = false;
// Install a lambda as the client callback and verify it is run.
proxy_base_->StartAuthSessionAsync(
base::BindLambdaForTesting([this](bool success) { status_ = success; }));
EXPECT_TRUE(status_);
EXPECT_EQ(GetBiodAuthSession(), auth_session_proxy.get());
}
// Test that OnSessionFailed will call on_finish_ with false
TEST_F(BiometricsManagerProxyBaseTest, OnSessionFailed) {
status_ = true;
proxy_base_->SetFinishHandler(
base::BindLambdaForTesting([this](bool success) { status_ = success; }));
CallOnSessionFailed();
EXPECT_FALSE(status_);
}
// Test that OnSignalConnected if failed will call on_finish_ with false
TEST_F(BiometricsManagerProxyBaseTest, OnSignalConnectFailed) {
status_ = true;
proxy_base_->SetFinishHandler(
base::BindLambdaForTesting([this](bool success) { status_ = success; }));
CallOnSignalConnected(false);
EXPECT_FALSE(status_);
}
} // namespace
} // namespace biod