// Copyright 2015 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 "base/bind.h" #include "base/message_loop/message_loop.h" #include "device/bluetooth/bluetooth_adapter.h" #include "device/bluetooth/bluetooth_adapter_bluez.h" #include "device/bluetooth/bluetooth_adapter_factory.h" #include "device/bluetooth/bluetooth_adapter_profile_bluez.h" #include "device/bluetooth/bluetooth_uuid.h" #include "device/bluetooth/dbus/bluetooth_profile_service_provider.h" #include "device/bluetooth/dbus/bluez_dbus_manager.h" #include "device/bluetooth/dbus/fake_bluetooth_adapter_client.h" #include "device/bluetooth/dbus/fake_bluetooth_agent_manager_client.h" #include "device/bluetooth/dbus/fake_bluetooth_device_client.h" #include "device/bluetooth/dbus/fake_bluetooth_profile_manager_client.h" #include "testing/gtest/include/gtest/gtest.h" using device::BluetoothAdapter; using device::BluetoothUUID; namespace bluez { class BluetoothAdapterProfileBlueZTest : public testing::Test { public: BluetoothAdapterProfileBlueZTest() : success_callback_count_(0), error_callback_count_(0), fake_delegate_paired_( bluez::FakeBluetoothDeviceClient::kPairedDevicePath), fake_delegate_autopair_( bluez::FakeBluetoothDeviceClient::kLegacyAutopairPath), fake_delegate_listen_(""), profile_user_ptr_(nullptr) {} void SetUp() override { scoped_ptr dbus_setter = bluez::BluezDBusManager::GetSetterForTesting(); dbus_setter->SetBluetoothAdapterClient( scoped_ptr( new bluez::FakeBluetoothAdapterClient)); dbus_setter->SetBluetoothAgentManagerClient( scoped_ptr( new bluez::FakeBluetoothAgentManagerClient)); dbus_setter->SetBluetoothDeviceClient( scoped_ptr( new bluez::FakeBluetoothDeviceClient)); dbus_setter->SetBluetoothProfileManagerClient( scoped_ptr( new bluez::FakeBluetoothProfileManagerClient)); // Grab a pointer to the adapter. device::BluetoothAdapterFactory::GetAdapter( base::Bind(&BluetoothAdapterProfileBlueZTest::AdapterCallback, base::Unretained(this))); base::MessageLoop::current()->Run(); ASSERT_TRUE(adapter_.get() != nullptr); ASSERT_TRUE(adapter_->IsInitialized()); ASSERT_TRUE(adapter_->IsPresent()); // Turn on the adapter. adapter_->SetPowered(true, base::Bind(&base::DoNothing), base::Bind(&base::DoNothing)); ASSERT_TRUE(adapter_->IsPowered()); } void TearDown() override { profile_.reset(); adapter_ = nullptr; bluez::BluezDBusManager::Shutdown(); } void AdapterCallback(scoped_refptr adapter) { adapter_ = adapter; if (base::MessageLoop::current() && base::MessageLoop::current()->is_running()) { base::MessageLoop::current()->QuitWhenIdle(); } } class FakeDelegate : public bluez::BluetoothProfileServiceProvider::Delegate { public: FakeDelegate(const std::string& device_path) : connections_(0) { device_path_ = dbus::ObjectPath(device_path); } // bluez::BluetoothProfileServiceProvider::Delegate: void Released() override { // noop } void NewConnection( const dbus::ObjectPath& device_path, scoped_ptr fd, const bluez::BluetoothProfileServiceProvider::Delegate::Options& options, const ConfirmationCallback& callback) override { ++connections_; fd->CheckValidity(); close(fd->TakeValue()); callback.Run(SUCCESS); if (device_path_.value() != "") ASSERT_EQ(device_path_, device_path); } void RequestDisconnection(const dbus::ObjectPath& device_path, const ConfirmationCallback& callback) override { ++disconnections_; } void Cancel() override { // noop } unsigned int connections_; unsigned int disconnections_; dbus::ObjectPath device_path_; }; void ProfileSuccessCallback( scoped_ptr profile) { profile_.swap(profile); ++success_callback_count_; } void ProfileUserSuccessCallback(BluetoothAdapterProfileBlueZ* profile) { profile_user_ptr_ = profile; ++success_callback_count_; } void MatchedProfileCallback(BluetoothAdapterProfileBlueZ* profile) { ASSERT_EQ(profile_user_ptr_, profile); ++success_callback_count_; } void DBusConnectSuccessCallback() { ++success_callback_count_; } void DBusErrorCallback(const std::string& error_name, const std::string& error_message) { ++error_callback_count_; } void BasicErrorCallback(const std::string& error_message) { ++error_callback_count_; } protected: base::MessageLoop message_loop_; scoped_refptr adapter_; unsigned int success_callback_count_; unsigned int error_callback_count_; FakeDelegate fake_delegate_paired_; FakeDelegate fake_delegate_autopair_; FakeDelegate fake_delegate_listen_; scoped_ptr profile_; // unowned pointer as expected to be used by clients of // BluetoothAdapterBlueZ::UseProfile like BluetoothSocketBlueZ BluetoothAdapterProfileBlueZ* profile_user_ptr_; }; TEST_F(BluetoothAdapterProfileBlueZTest, DelegateCount) { BluetoothUUID uuid(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid); bluez::BluetoothProfileManagerClient::Options options; options.require_authentication.reset(new bool(false)); BluetoothAdapterProfileBlueZ::Register( uuid, options, base::Bind(&BluetoothAdapterProfileBlueZTest::ProfileSuccessCallback, base::Unretained(this)), base::Bind(&BluetoothAdapterProfileBlueZTest::DBusErrorCallback, base::Unretained(this))); message_loop_.RunUntilIdle(); EXPECT_TRUE(profile_); EXPECT_EQ(1U, success_callback_count_); EXPECT_EQ(0U, error_callback_count_); EXPECT_EQ(0U, profile_->DelegateCount()); profile_->SetDelegate(fake_delegate_paired_.device_path_, &fake_delegate_paired_); EXPECT_EQ(1U, profile_->DelegateCount()); profile_->RemoveDelegate(fake_delegate_autopair_.device_path_, base::Bind(&base::DoNothing)); EXPECT_EQ(1U, profile_->DelegateCount()); profile_->RemoveDelegate(fake_delegate_paired_.device_path_, base::Bind(&base::DoNothing)); EXPECT_EQ(0U, profile_->DelegateCount()); } TEST_F(BluetoothAdapterProfileBlueZTest, BlackHole) { BluetoothUUID uuid(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid); bluez::BluetoothProfileManagerClient::Options options; options.require_authentication.reset(new bool(false)); BluetoothAdapterProfileBlueZ::Register( uuid, options, base::Bind(&BluetoothAdapterProfileBlueZTest::ProfileSuccessCallback, base::Unretained(this)), base::Bind(&BluetoothAdapterProfileBlueZTest::DBusErrorCallback, base::Unretained(this))); message_loop_.RunUntilIdle(); EXPECT_TRUE(profile_); EXPECT_EQ(1U, success_callback_count_); EXPECT_EQ(0U, error_callback_count_); bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->ConnectProfile( dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kPairedDevicePath), bluez::FakeBluetoothProfileManagerClient::kRfcommUuid, base::Bind(&BluetoothAdapterProfileBlueZTest::DBusConnectSuccessCallback, base::Unretained(this)), base::Bind(&BluetoothAdapterProfileBlueZTest::DBusErrorCallback, base::Unretained(this))); message_loop_.RunUntilIdle(); EXPECT_EQ(1U, success_callback_count_); EXPECT_EQ(1U, error_callback_count_); EXPECT_EQ(0U, fake_delegate_paired_.connections_); } TEST_F(BluetoothAdapterProfileBlueZTest, Routing) { BluetoothUUID uuid(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid); bluez::BluetoothProfileManagerClient::Options options; options.require_authentication.reset(new bool(false)); BluetoothAdapterProfileBlueZ::Register( uuid, options, base::Bind(&BluetoothAdapterProfileBlueZTest::ProfileSuccessCallback, base::Unretained(this)), base::Bind(&BluetoothAdapterProfileBlueZTest::DBusErrorCallback, base::Unretained(this))); message_loop_.RunUntilIdle(); ASSERT_TRUE(profile_); ASSERT_EQ(1U, success_callback_count_); ASSERT_EQ(0U, error_callback_count_); profile_->SetDelegate(fake_delegate_paired_.device_path_, &fake_delegate_paired_); profile_->SetDelegate(fake_delegate_autopair_.device_path_, &fake_delegate_autopair_); profile_->SetDelegate(fake_delegate_listen_.device_path_, &fake_delegate_listen_); bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->ConnectProfile( dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kPairedDevicePath), bluez::FakeBluetoothProfileManagerClient::kRfcommUuid, base::Bind(&BluetoothAdapterProfileBlueZTest::DBusConnectSuccessCallback, base::Unretained(this)), base::Bind(&BluetoothAdapterProfileBlueZTest::DBusErrorCallback, base::Unretained(this))); message_loop_.RunUntilIdle(); EXPECT_EQ(2U, success_callback_count_); EXPECT_EQ(0U, error_callback_count_); EXPECT_EQ(1U, fake_delegate_paired_.connections_); bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->ConnectProfile( dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLegacyAutopairPath), bluez::FakeBluetoothProfileManagerClient::kRfcommUuid, base::Bind(&BluetoothAdapterProfileBlueZTest::DBusConnectSuccessCallback, base::Unretained(this)), base::Bind(&BluetoothAdapterProfileBlueZTest::DBusErrorCallback, base::Unretained(this))); message_loop_.RunUntilIdle(); EXPECT_EQ(3U, success_callback_count_); EXPECT_EQ(0U, error_callback_count_); EXPECT_EQ(1U, fake_delegate_autopair_.connections_); // Incoming connections look the same from BlueZ. bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->ConnectProfile( dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kDisplayPinCodePath), bluez::FakeBluetoothProfileManagerClient::kRfcommUuid, base::Bind(&BluetoothAdapterProfileBlueZTest::DBusConnectSuccessCallback, base::Unretained(this)), base::Bind(&BluetoothAdapterProfileBlueZTest::DBusErrorCallback, base::Unretained(this))); message_loop_.RunUntilIdle(); EXPECT_EQ(4U, success_callback_count_); EXPECT_EQ(0U, error_callback_count_); EXPECT_EQ(1U, fake_delegate_listen_.connections_); } TEST_F(BluetoothAdapterProfileBlueZTest, SimultaneousRegister) { BluetoothUUID uuid(bluez::FakeBluetoothProfileManagerClient::kRfcommUuid); bluez::BluetoothProfileManagerClient::Options options; BluetoothAdapterBlueZ* adapter = static_cast(adapter_.get()); options.require_authentication.reset(new bool(false)); success_callback_count_ = 0; error_callback_count_ = 0; adapter->UseProfile( uuid, fake_delegate_paired_.device_path_, options, &fake_delegate_paired_, base::Bind(&BluetoothAdapterProfileBlueZTest::ProfileUserSuccessCallback, base::Unretained(this)), base::Bind(&BluetoothAdapterProfileBlueZTest::BasicErrorCallback, base::Unretained(this))); adapter->UseProfile( uuid, fake_delegate_autopair_.device_path_, options, &fake_delegate_autopair_, base::Bind(&BluetoothAdapterProfileBlueZTest::MatchedProfileCallback, base::Unretained(this)), base::Bind(&BluetoothAdapterProfileBlueZTest::BasicErrorCallback, base::Unretained(this))); message_loop_.RunUntilIdle(); EXPECT_TRUE(profile_user_ptr_); EXPECT_EQ(2U, success_callback_count_); EXPECT_EQ(0U, error_callback_count_); adapter->ReleaseProfile(fake_delegate_paired_.device_path_, profile_user_ptr_); adapter->ReleaseProfile(fake_delegate_autopair_.device_path_, profile_user_ptr_); message_loop_.RunUntilIdle(); } TEST_F(BluetoothAdapterProfileBlueZTest, SimultaneousRegisterFail) { BluetoothUUID uuid( bluez::FakeBluetoothProfileManagerClient::kUnregisterableUuid); bluez::BluetoothProfileManagerClient::Options options; BluetoothAdapterBlueZ* adapter = static_cast(adapter_.get()); options.require_authentication.reset(new bool(false)); success_callback_count_ = 0; error_callback_count_ = 0; adapter->UseProfile( uuid, fake_delegate_paired_.device_path_, options, &fake_delegate_paired_, base::Bind(&BluetoothAdapterProfileBlueZTest::ProfileUserSuccessCallback, base::Unretained(this)), base::Bind(&BluetoothAdapterProfileBlueZTest::BasicErrorCallback, base::Unretained(this))); adapter->UseProfile( uuid, fake_delegate_autopair_.device_path_, options, &fake_delegate_autopair_, base::Bind(&BluetoothAdapterProfileBlueZTest::MatchedProfileCallback, base::Unretained(this)), base::Bind(&BluetoothAdapterProfileBlueZTest::BasicErrorCallback, base::Unretained(this))); message_loop_.RunUntilIdle(); EXPECT_FALSE(profile_user_ptr_); EXPECT_EQ(0U, success_callback_count_); EXPECT_EQ(2U, error_callback_count_); } } // namespace bluez