#include <stddef.h>
#include <stdint.h>
#include <memory>
#include <utility>
#include <vector>
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/test/bind.h"
#include "base/test/task_environment.h"
#include "dbus/object_path.h"
#include "device/bluetooth/bluetooth_adapter.h"
#include "device/bluetooth/bluetooth_adapter_factory.h"
#include "device/bluetooth/bluetooth_device.h"
#include "device/bluetooth/bluetooth_discovery_filter.h"
#include "device/bluetooth/bluetooth_gatt_characteristic.h"
#include "device/bluetooth/bluetooth_gatt_connection.h"
#include "device/bluetooth/bluetooth_gatt_notify_session.h"
#include "device/bluetooth/bluetooth_remote_gatt_characteristic.h"
#include "device/bluetooth/bluetooth_remote_gatt_descriptor.h"
#include "device/bluetooth/bluetooth_remote_gatt_service.h"
#include "device/bluetooth/bluez/bluetooth_device_bluez.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_gatt_characteristic_client.h"
#include "device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_client.h"
#include "device/bluetooth/dbus/fake_bluetooth_gatt_service_client.h"
#include "device/bluetooth/dbus/fake_bluetooth_input_client.h"
#include "device/bluetooth/floss/floss_features.h"
#include "device/bluetooth/public/cpp/bluetooth_uuid.h"
#include "device/bluetooth/test/test_bluetooth_adapter_observer.h"
#include "testing/gtest/include/gtest/gtest.h"
BluetoothAdapter;
BluetoothDevice;
BluetoothDiscoveryFilter;
BluetoothGattConnection;
BluetoothGattNotifySession;
BluetoothGattService;
BluetoothRemoteGattCharacteristic;
BluetoothRemoteGattDescriptor;
BluetoothRemoteGattService;
BluetoothUUID;
TestBluetoothAdapterObserver;
UUIDSet;
WriteType;
DeviceToUUIDs;
namespace bluez {
namespace {
const BluetoothUUID kGenericAccessServiceUUID(
bluez::FakeBluetoothGattServiceClient::kGenericAccessServiceUUID);
const BluetoothUUID kBatteryServiceUUID(
bluez::FakeBluetoothGattServiceClient::kBatteryServiceUUID);
const BluetoothUUID kHeartRateServiceUUID(
bluez::FakeBluetoothGattServiceClient::kHeartRateServiceUUID);
const BluetoothUUID kHeartRateMeasurementUUID(
bluez::FakeBluetoothGattCharacteristicClient::kHeartRateMeasurementUUID);
const BluetoothUUID kBodySensorLocationUUID(
bluez::FakeBluetoothGattCharacteristicClient::kBodySensorLocationUUID);
const BluetoothUUID kHeartRateControlPointUUID(
bluez::FakeBluetoothGattCharacteristicClient::kHeartRateControlPointUUID);
bool ValuesEqual(const std::vector<uint8_t>& value0,
const std::vector<uint8_t>& value1) { … }
void AddDeviceFilterWithUUID(BluetoothDiscoveryFilter* filter,
BluetoothUUID uuid) { … }
}
class BluetoothGattBlueZTest : public testing::Test { … };
TEST_F(BluetoothGattBlueZTest,
RetrieveGattConnectedDevicesWithDiscoveryFilter_NoFilter) { … }
TEST_F(BluetoothGattBlueZTest,
RetrieveGattConnectedDevicesWithDiscoveryFilter_NonMatchingFilter) { … }
TEST_F(
BluetoothGattBlueZTest,
RetrieveGattConnectedDevicesWithDiscoveryFilter_OneMatchingServiceOneDevice) { … }
TEST_F(
BluetoothGattBlueZTest,
RetrieveGattConnectedDevicesWithDiscoveryFilter_OneMatchingServiceTwoDevices) { … }
TEST_F(BluetoothGattBlueZTest,
RetrieveGattConnectedDevicesWithDiscoveryFilter_TwoServicesTwoDevices) { … }
TEST_F(
BluetoothGattBlueZTest,
RetrieveGattConnectedDevicesWithDiscoveryFilter_OneMatchingServiceOneNonMatchingService) { … }
TEST_F(BluetoothGattBlueZTest, GattConnection) { … }
TEST_F(BluetoothGattBlueZTest, GattServiceAddedAndRemoved) { … }
TEST_F(BluetoothGattBlueZTest, ServicesDiscoveredBeforeAdapterIsCreated) { … }
TEST_F(BluetoothGattBlueZTest, ServicesDiscoveredAfterAdapterIsCreated) { … }
TEST_F(BluetoothGattBlueZTest, DiscoverCachedServices) { … }
TEST_F(BluetoothGattBlueZTest, DiscoverNewServices) { … }
TEST_F(BluetoothGattBlueZTest, DiscoverCachedAndNewServices) { … }
TEST_F(BluetoothGattBlueZTest, GattCharacteristicAddedAndRemoved) { … }
TEST_F(BluetoothGattBlueZTest, GattDescriptorAddedAndRemoved) { … }
TEST_F(BluetoothGattBlueZTest, GattCharacteristicValue) { … }
TEST_F(BluetoothGattBlueZTest, DeprecatedGattCharacteristicValue) { … }
TEST_F(BluetoothGattBlueZTest, GattCharacteristicValue_Nested_Read_Read) { … }
TEST_F(BluetoothGattBlueZTest, GattCharacteristicValue_Nested_Write_Write) { … }
TEST_F(BluetoothGattBlueZTest,
GattCharacteristicValue_Nested_DeprecatedWrite_DeprecatedWrite) { … }
TEST_F(BluetoothGattBlueZTest, GattCharacteristicValue_Nested_Read_Write) { … }
TEST_F(BluetoothGattBlueZTest,
GattCharacteristicValue_Nested_Read_DeprecatedWrite) { … }
TEST_F(BluetoothGattBlueZTest, GattCharacteristicValue_Nested_Write_Read) { … }
TEST_F(BluetoothGattBlueZTest,
GattCharacteristicValue_Nested_DeprecatedWrite_Read) { … }
TEST_F(BluetoothGattBlueZTest, GattCharacteristicProperties) { … }
TEST_F(BluetoothGattBlueZTest, GattDescriptorValue) { … }
TEST_F(BluetoothGattBlueZTest, NotifySessions) { … }
TEST_F(BluetoothGattBlueZTest, NotifySessionsMadeInactive) { … }
#if BUILDFLAG(IS_CHROMEOS)
TEST_F(BluetoothGattBlueZTest, ReliableWrite) {
fake_bluetooth_device_client_->CreateDevice(
dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath));
BluetoothDeviceBlueZ* device = static_cast<BluetoothDeviceBlueZ*>(
adapter_->GetDevice(bluez::FakeBluetoothDeviceClient::kLowEnergyAddress));
ASSERT_TRUE(device);
TestBluetoothAdapterObserver observer(adapter_);
fake_bluetooth_gatt_service_client_->ExposeHeartRateService(
dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath));
ASSERT_EQ(1, observer.gatt_service_added_count());
BluetoothRemoteGattService* service =
device->GetGattService(observer.last_gatt_service_id());
{
base::RunLoop loop;
observer.set_quit_closure(loop.QuitWhenIdleClosure());
loop.Run();
}
base::RunLoop loop;
service
->GetCharacteristic(fake_bluetooth_gatt_characteristic_client_
->GetHeartRateMeasurementPath()
.value())
->StartNotifySession(
base::BindLambdaForTesting(
[&loop,
this](std::unique_ptr<BluetoothGattNotifySession> session) {
NotifySessionCallback(std::move(session));
loop.Quit();
}),
base::BindOnce(&BluetoothGattBlueZTest::ServiceErrorCallback,
base::Unretained(this)));
loop.Run();
BluetoothRemoteGattCharacteristic* characteristic =
service->GetCharacteristic(fake_bluetooth_gatt_characteristic_client_
->GetHeartRateControlPointPath()
.value());
std::vector<uint8_t> write_value = {0x01};
success_callback_count_ = 0;
error_callback_count_ = 0;
observer.Reset();
for (int i = 0; i < 1000; ++i) {
characteristic->PrepareWriteRemoteCharacteristic(
write_value,
base::BindOnce(&BluetoothGattBlueZTest::SuccessCallback,
base::Unretained(this)),
base::BindOnce(&BluetoothGattBlueZTest::ServiceErrorCallback,
base::Unretained(this)));
}
EXPECT_EQ(1000, success_callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count());
device->AbortWrite(
base::BindOnce(&BluetoothGattBlueZTest::SuccessCallback,
base::Unretained(this)),
base::BindOnce(&BluetoothGattBlueZTest::ServiceErrorCallback,
base::Unretained(this)));
EXPECT_EQ(1001, success_callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count());
success_callback_count_ = 0;
error_callback_count_ = 0;
observer.Reset();
for (int i = 0; i < 1000; ++i) {
characteristic->PrepareWriteRemoteCharacteristic(
write_value,
base::BindOnce(&BluetoothGattBlueZTest::SuccessCallback,
base::Unretained(this)),
base::BindOnce(&BluetoothGattBlueZTest::ServiceErrorCallback,
base::Unretained(this)));
}
EXPECT_EQ(1000, success_callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count());
device->ExecuteWrite(
base::BindOnce(&BluetoothGattBlueZTest::SuccessCallback,
base::Unretained(this)),
base::BindOnce(&BluetoothGattBlueZTest::ServiceErrorCallback,
base::Unretained(this)));
EXPECT_EQ(1001, success_callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_EQ(1000, observer.gatt_characteristic_value_changed_count());
}
TEST_F(BluetoothGattBlueZTest, NotificationType) {
fake_bluetooth_device_client_->CreateDevice(
dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath));
BluetoothDeviceBlueZ* device = static_cast<BluetoothDeviceBlueZ*>(
adapter_->GetDevice(bluez::FakeBluetoothDeviceClient::kLowEnergyAddress));
ASSERT_TRUE(device);
TestBluetoothAdapterObserver observer(adapter_);
fake_bluetooth_gatt_service_client_->ExposeHeartRateService(
dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath));
ASSERT_EQ(1, observer.gatt_service_added_count());
BluetoothRemoteGattService* service =
device->GetGattService(observer.last_gatt_service_id());
{
base::RunLoop loop;
observer.set_quit_closure(loop.QuitWhenIdleClosure());
loop.Run();
}
BluetoothRemoteGattCharacteristic* characteristic =
service->GetCharacteristic(fake_bluetooth_gatt_characteristic_client_
->GetHeartRateMeasurementPath()
.value());
{
base::RunLoop loop;
characteristic->StartNotifySession(
device::BluetoothGattCharacteristic::NotificationType::kNotification,
base::BindLambdaForTesting(
[&loop, this](std::unique_ptr<BluetoothGattNotifySession> session) {
NotifySessionCallback(std::move(session));
loop.Quit();
}),
base::BindOnce(&BluetoothGattBlueZTest::ServiceErrorCallback,
base::Unretained(this)));
loop.Run();
}
EXPECT_EQ(1, observer.gatt_characteristic_value_changed_count());
fake_bluetooth_gatt_characteristic_client_->StopNotify(
fake_bluetooth_gatt_characteristic_client_->GetHeartRateMeasurementPath(),
base::BindOnce(&BluetoothGattBlueZTest::SuccessCallback,
base::Unretained(this)),
base::BindOnce(&BluetoothGattBlueZTest::DBusErrorCallback,
base::Unretained(this)));
{
base::RunLoop loop;
characteristic->StartNotifySession(
device::BluetoothGattCharacteristic::NotificationType::kIndication,
base::BindLambdaForTesting(
[&loop, this](std::unique_ptr<BluetoothGattNotifySession> session) {
NotifySessionCallback(std::move(session));
loop.Quit();
}),
base::BindOnce(&BluetoothGattBlueZTest::ServiceErrorCallback,
base::Unretained(this)));
loop.Run();
}
EXPECT_EQ(2, observer.gatt_characteristic_value_changed_count());
}
#endif
TEST_F(BluetoothGattBlueZTest, MultipleDevices) { … }
}