blob: 7420e56dd78721fad6e040bc4f99d601c58eb732 [file] [log] [blame]
// Copyright 2018 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 "bluetooth/newblued/agent_manager_interface_handler.h"
#include <memory>
#include <string>
#include <utility>
#include <base/memory/ref_counted.h>
#include <brillo/dbus/dbus_object.h>
#include <brillo/dbus/exported_property_set.h>
#include <brillo/dbus/mock_exported_object_manager.h>
#include <chromeos/dbus/service_constants.h>
#include <dbus/exported_object.h>
#include <dbus/mock_bus.h>
#include <dbus/mock_exported_object.h>
#include <dbus/mock_object_proxy.h>
#include <dbus/object_path.h>
#include <gtest/gtest.h>
#include "bluetooth/common/exported_object_manager_wrapper.h"
using ::testing::_;
using ::testing::Return;
using ::testing::SaveArg;
using ::testing::SaveArgPointee;
namespace bluetooth {
namespace {
constexpr char kTestAgentPath[] = "/some/agent";
constexpr char kTestSender[] = ":1.1";
constexpr char kTestDeviceAddress[] = "11:22:33:44:55:66";
constexpr char kTestCapability[] = "some capability";
constexpr int kTestSerial = 123;
constexpr int kTestPasskey = 123456;
void SaveResponse(std::unique_ptr<dbus::Response>* saved_response,
std::unique_ptr<dbus::Response> response) {
*saved_response = std::move(response);
}
// Matcher to compare method call by its interface and member name, ignoring
// the message payload.
MATCHER_P(MethodCallEq, expected_method_call, "") {
return (arg->GetInterface() == (expected_method_call)->GetInterface() &&
arg->GetMember() == (expected_method_call)->GetMember());
}
} // namespace
class AgentManagerInterfaceHandlerTest : public ::testing::Test {
public:
void SetUp() override {
bus_ = new dbus::MockBus(dbus::Bus::Options());
auto exported_object_manager =
std::make_unique<brillo::dbus_utils::MockExportedObjectManager>(
bus_, dbus::ObjectPath("/"));
exported_object_manager_wrapper_ =
std::make_unique<ExportedObjectManagerWrapper>(
bus_, std::move(exported_object_manager));
exported_object_manager_wrapper_->SetPropertyHandlerSetupCallback(
base::Bind(
&AgentManagerInterfaceHandlerTest::SetupPropertyMethodHandlers,
base::Unretained(this)));
agent_manager_interface_handler_ =
std::make_unique<AgentManagerInterfaceHandler>(
bus_, exported_object_manager_wrapper_.get());
exported_agent_manager_object_ = SetupExportedAgentManagerObject();
}
protected:
void SetupPropertyMethodHandlers(
brillo::dbus_utils::DBusInterface* prop_interface,
brillo::dbus_utils::ExportedPropertySet* property_set) {
// We don't care about property method handlers.
}
void ExpectAgentManagerMethodsExported(
dbus::ExportedObject::MethodCallCallback* register_agent_method_handler,
dbus::ExportedObject::MethodCallCallback* unregister_agent_method_handler,
dbus::ExportedObject::MethodCallCallback*
request_default_agent_method_handler) {
EXPECT_CALL(*exported_agent_manager_object_,
ExportMethodAndBlock(
bluetooth_agent_manager::kBluetoothAgentManagerInterface,
bluetooth_agent_manager::kRegisterAgent, _))
.WillOnce(
DoAll(SaveArg<2>(register_agent_method_handler), Return(true)));
EXPECT_CALL(*exported_agent_manager_object_,
ExportMethodAndBlock(
bluetooth_agent_manager::kBluetoothAgentManagerInterface,
bluetooth_agent_manager::kUnregisterAgent, _))
.WillOnce(
DoAll(SaveArg<2>(unregister_agent_method_handler), Return(true)));
EXPECT_CALL(*exported_agent_manager_object_,
ExportMethodAndBlock(
bluetooth_agent_manager::kBluetoothAgentManagerInterface,
bluetooth_agent_manager::kRequestDefaultAgent, _))
.WillOnce(DoAll(SaveArg<2>(request_default_agent_method_handler),
Return(true)));
}
scoped_refptr<dbus::MockExportedObject> SetupExportedAgentManagerObject() {
dbus::ObjectPath agent_manager_path(
bluetooth_agent_manager::kBluetoothAgentManagerServicePath);
scoped_refptr<dbus::MockExportedObject> exported_agent_manager_object =
new dbus::MockExportedObject(bus_.get(), agent_manager_path);
EXPECT_CALL(*bus_, GetExportedObject(agent_manager_path))
.WillRepeatedly(Return(exported_agent_manager_object.get()));
return exported_agent_manager_object;
}
scoped_refptr<dbus::MockBus> bus_;
// A raw pointer of this is kept by exported_object_manager_wrapper_, so
// declare this first to make sure it's destructed later.
scoped_refptr<dbus::MockExportedObject> exported_agent_manager_object_;
std::unique_ptr<ExportedObjectManagerWrapper>
exported_object_manager_wrapper_;
std::unique_ptr<AgentManagerInterfaceHandler>
agent_manager_interface_handler_;
};
TEST_F(AgentManagerInterfaceHandlerTest, DisplayPasskey) {
dbus::ExportedObject::MethodCallCallback register_agent_method_handler;
dbus::ExportedObject::MethodCallCallback unregister_agent_method_handler;
dbus::ExportedObject::MethodCallCallback request_default_agent_method_handler;
ExpectAgentManagerMethodsExported(&register_agent_method_handler,
&unregister_agent_method_handler,
&request_default_agent_method_handler);
agent_manager_interface_handler_->Init();
scoped_refptr<dbus::MockObjectProxy> agent_object_proxy =
new dbus::MockObjectProxy(
bus_.get(), bluetooth_agent_manager::kBluetoothAgentManagerInterface,
dbus::ObjectPath(kTestAgentPath));
// Before any client registers as an agent, DisplayPasskey won't call any
// agent.
EXPECT_CALL(*agent_object_proxy, CallMethod(_, _, _)).Times(0);
agent_manager_interface_handler_->DisplayPasskey(kTestDeviceAddress,
kTestPasskey);
// Test org.bluez.AgentManager1.RegisterAgent.
dbus::MethodCall register_agent_method_call(
bluetooth_agent_manager::kBluetoothAgentManagerInterface,
bluetooth_agent_manager::kRegisterAgent);
register_agent_method_call.SetPath(dbus::ObjectPath(
bluetooth_agent_manager::kBluetoothAgentManagerServicePath));
register_agent_method_call.SetSender(kTestSender);
register_agent_method_call.SetSerial(kTestSerial);
dbus::MessageWriter register_agent_writer(&register_agent_method_call);
register_agent_writer.AppendObjectPath(dbus::ObjectPath(kTestAgentPath));
register_agent_writer.AppendString(kTestCapability);
std::unique_ptr<dbus::Response> register_agent_response;
register_agent_method_handler.Run(
&register_agent_method_call,
base::Bind(&SaveResponse, &register_agent_response));
EXPECT_EQ("", register_agent_response->GetErrorName());
// A client has registered as an agent but has not requested to become the
// default agent. So DisplayPasskey should still not call any agent.
EXPECT_CALL(*agent_object_proxy, CallMethod(_, _, _)).Times(0);
agent_manager_interface_handler_->DisplayPasskey(kTestDeviceAddress,
kTestPasskey);
// Test org.bluez.AgentManager1.RequestDefaultAgent.
dbus::MethodCall request_default_agent_method_call(
bluetooth_agent_manager::kBluetoothAgentManagerInterface,
bluetooth_agent_manager::kRequestDefaultAgent);
request_default_agent_method_call.SetPath(dbus::ObjectPath(
bluetooth_agent_manager::kBluetoothAgentManagerServicePath));
request_default_agent_method_call.SetSender(kTestSender);
request_default_agent_method_call.SetSerial(kTestSerial);
dbus::MessageWriter request_default_agent_writer(
&request_default_agent_method_call);
request_default_agent_writer.AppendObjectPath(
dbus::ObjectPath(kTestAgentPath));
std::unique_ptr<dbus::Response> request_default_agent_response;
request_default_agent_method_handler.Run(
&request_default_agent_method_call,
base::Bind(&SaveResponse, &request_default_agent_response));
EXPECT_EQ("", request_default_agent_response->GetErrorName());
// Now that a client has requested to become the default agent, check that
// DisplayPasskey correctly handles this based on the current default agent.
EXPECT_CALL(*bus_,
GetObjectProxy(kTestSender, dbus::ObjectPath(kTestAgentPath)))
.WillOnce(Return(agent_object_proxy.get()));
dbus::MethodCall expected_method_call(
bluetooth_agent::kBluetoothAgentInterface,
bluetooth_agent::kDisplayPasskey);
EXPECT_CALL(*agent_object_proxy,
CallMethod(MethodCallEq(&expected_method_call), _, _))
.Times(1);
agent_manager_interface_handler_->DisplayPasskey(kTestDeviceAddress,
kTestPasskey);
// Test org.bluez.AgentManager1.UnregisterAgent.
dbus::MethodCall unregister_agent_method_call(
bluetooth_agent_manager::kBluetoothAgentManagerInterface,
bluetooth_agent_manager::kUnregisterAgent);
unregister_agent_method_call.SetPath(dbus::ObjectPath(
bluetooth_agent_manager::kBluetoothAgentManagerServicePath));
unregister_agent_method_call.SetSender(kTestSender);
unregister_agent_method_call.SetSerial(kTestSerial);
dbus::MessageWriter unregister_agent_writer(&unregister_agent_method_call);
unregister_agent_writer.AppendObjectPath(dbus::ObjectPath(kTestAgentPath));
std::unique_ptr<dbus::Response> unregister_agent_response;
register_agent_method_handler.Run(
&unregister_agent_method_call,
base::Bind(&SaveResponse, &unregister_agent_response));
EXPECT_EQ("", unregister_agent_response->GetErrorName());
// After the client unregisters from an agent, DisplayPasskey won't call any
// agent.
EXPECT_CALL(*agent_object_proxy, CallMethod(_, _, _)).Times(0);
agent_manager_interface_handler_->DisplayPasskey(kTestDeviceAddress,
kTestPasskey);
}
} // namespace bluetooth