blob: 9574c4dd0cc9c7346ec0e39d95d16a76ac7e4c5b [file] [log] [blame]
// 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/run_loop.h"
#include "build/build_config.h"
#include "device/bluetooth/bluetooth_gatt_service.h"
#include "device/bluetooth/bluetooth_remote_gatt_characteristic.h"
#include "device/bluetooth/test/test_bluetooth_adapter_observer.h"
#include "testing/gtest/include/gtest/gtest.h"
#if defined(OS_ANDROID)
#include "device/bluetooth/test/bluetooth_test_android.h"
#elif defined(OS_MACOSX)
#include "device/bluetooth/test/bluetooth_test_mac.h"
#elif defined(OS_WIN)
#include "device/bluetooth/test/bluetooth_test_win.h"
#elif defined(USE_CAST_BLUETOOTH_ADAPTER)
#include "device/bluetooth/test/bluetooth_test_cast.h"
#elif defined(OS_CHROMEOS) || defined(OS_LINUX)
#include "device/bluetooth/test/bluetooth_test_bluez.h"
#endif
namespace device {
class BluetoothRemoteGattServiceTest : public BluetoothTest {};
#if defined(OS_WIN)
class BluetoothRemoteGattServiceTestWinrt : public BluetoothTestWinrt {};
#endif
// Android is excluded because it fires a single discovery event per device.
#if defined(OS_MACOSX)
#define MAYBE_IsDiscoveryComplete IsDiscoveryComplete
#else
#define MAYBE_IsDiscoveryComplete DISABLED_IsDiscoveryComplete
#endif
#if defined(OS_WIN)
TEST_P(BluetoothRemoteGattServiceTestWinrt, IsDiscoveryComplete) {
#else
TEST_F(BluetoothRemoteGattServiceTest, MAYBE_IsDiscoveryComplete) {
#endif
if (!PlatformSupportsLowEnergy()) {
LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
return;
}
InitWithFakeAdapter();
StartLowEnergyDiscoverySession();
BluetoothDevice* device = SimulateLowEnergyDevice(1);
device->CreateGattConnection(GetGattConnectionCallback(Call::EXPECTED),
GetConnectErrorCallback(Call::NOT_EXPECTED));
SimulateGattConnection(device);
base::RunLoop().RunUntilIdle();
SimulateGattServicesDiscovered(
device, std::vector<std::string>(
{kTestUUIDGenericAccess, kTestUUIDGenericAccess}));
base::RunLoop().RunUntilIdle();
BluetoothRemoteGattService* service = device->GetGattServices()[0];
EXPECT_TRUE(service->IsDiscoveryComplete());
}
#if defined(OS_ANDROID) || defined(OS_MACOSX)
#define MAYBE_GetIdentifier GetIdentifier
#else
#define MAYBE_GetIdentifier DISABLED_GetIdentifier
#endif
#if defined(OS_WIN)
TEST_P(BluetoothRemoteGattServiceTestWinrt, GetIdentifier) {
#else
TEST_F(BluetoothRemoteGattServiceTest, MAYBE_GetIdentifier) {
#endif
if (!PlatformSupportsLowEnergy()) {
LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
return;
}
InitWithFakeAdapter();
StartLowEnergyDiscoverySession();
// 2 devices to verify unique IDs across them.
BluetoothDevice* device1 = SimulateLowEnergyDevice(3);
BluetoothDevice* device2 = SimulateLowEnergyDevice(4);
device1->CreateGattConnection(GetGattConnectionCallback(Call::EXPECTED),
GetConnectErrorCallback(Call::NOT_EXPECTED));
device2->CreateGattConnection(GetGattConnectionCallback(Call::EXPECTED),
GetConnectErrorCallback(Call::NOT_EXPECTED));
SimulateGattConnection(device1);
SimulateGattConnection(device2);
base::RunLoop().RunUntilIdle();
// 2 duplicate UUIDs creating 2 service instances on each device.
SimulateGattServicesDiscovered(
device1, std::vector<std::string>(
{kTestUUIDGenericAccess, kTestUUIDGenericAccess}));
SimulateGattServicesDiscovered(
device2, std::vector<std::string>(
{kTestUUIDGenericAccess, kTestUUIDGenericAccess}));
base::RunLoop().RunUntilIdle();
BluetoothRemoteGattService* service1 = device1->GetGattServices()[0];
BluetoothRemoteGattService* service2 = device1->GetGattServices()[1];
BluetoothRemoteGattService* service3 = device2->GetGattServices()[0];
BluetoothRemoteGattService* service4 = device2->GetGattServices()[1];
// All IDs are unique, even though they have the same UUID.
EXPECT_NE(service1->GetIdentifier(), service2->GetIdentifier());
EXPECT_NE(service1->GetIdentifier(), service3->GetIdentifier());
EXPECT_NE(service1->GetIdentifier(), service4->GetIdentifier());
EXPECT_NE(service2->GetIdentifier(), service3->GetIdentifier());
EXPECT_NE(service2->GetIdentifier(), service4->GetIdentifier());
EXPECT_NE(service3->GetIdentifier(), service4->GetIdentifier());
}
#if defined(OS_ANDROID) || defined(OS_MACOSX)
#define MAYBE_GetUUID GetUUID
#else
#define MAYBE_GetUUID DISABLED_GetUUID
#endif
#if defined(OS_WIN)
TEST_P(BluetoothRemoteGattServiceTestWinrt, GetUUID) {
#else
TEST_F(BluetoothRemoteGattServiceTest, MAYBE_GetUUID) {
#endif
if (!PlatformSupportsLowEnergy()) {
LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
return;
}
InitWithFakeAdapter();
StartLowEnergyDiscoverySession();
BluetoothDevice* device = SimulateLowEnergyDevice(3);
device->CreateGattConnection(GetGattConnectionCallback(Call::EXPECTED),
GetConnectErrorCallback(Call::NOT_EXPECTED));
SimulateGattConnection(device);
base::RunLoop().RunUntilIdle();
// Create multiple instances with the same UUID.
BluetoothUUID uuid(kTestUUIDGenericAccess);
std::vector<std::string> services;
services.push_back(uuid.canonical_value());
services.push_back(uuid.canonical_value());
SimulateGattServicesDiscovered(device, services);
base::RunLoop().RunUntilIdle();
// Each has the same UUID.
EXPECT_EQ(uuid, device->GetGattServices()[0]->GetUUID());
EXPECT_EQ(uuid, device->GetGattServices()[1]->GetUUID());
}
#if defined(OS_ANDROID) || defined(OS_MACOSX)
#define MAYBE_GetCharacteristics_FindNone GetCharacteristics_FindNone
#else
#define MAYBE_GetCharacteristics_FindNone DISABLED_GetCharacteristics_FindNone
#endif
#if defined(OS_WIN)
TEST_P(BluetoothRemoteGattServiceTestWinrt, GetCharacteristics_FindNone) {
#else
TEST_F(BluetoothRemoteGattServiceTest, MAYBE_GetCharacteristics_FindNone) {
#endif
if (!PlatformSupportsLowEnergy()) {
LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
return;
}
InitWithFakeAdapter();
StartLowEnergyDiscoverySession();
BluetoothDevice* device = SimulateLowEnergyDevice(3);
device->CreateGattConnection(GetGattConnectionCallback(Call::EXPECTED),
GetConnectErrorCallback(Call::NOT_EXPECTED));
SimulateGattConnection(device);
base::RunLoop().RunUntilIdle();
// Simulate a service, with no Characteristics:
SimulateGattServicesDiscovered(
device, std::vector<std::string>({kTestUUIDGenericAccess}));
base::RunLoop().RunUntilIdle();
BluetoothRemoteGattService* service = device->GetGattServices()[0];
EXPECT_EQ(0u, service->GetCharacteristics().size());
}
#if defined(OS_ANDROID) || defined(OS_MACOSX)
#define MAYBE_GetCharacteristics_and_GetCharacteristic \
GetCharacteristics_and_GetCharacteristic
#else
#define MAYBE_GetCharacteristics_and_GetCharacteristic \
DISABLED_GetCharacteristics_and_GetCharacteristic
#endif
#if defined(OS_WIN)
TEST_P(BluetoothRemoteGattServiceTestWinrt,
GetCharacteristics_and_GetCharacteristic) {
#else
TEST_F(BluetoothRemoteGattServiceTest,
MAYBE_GetCharacteristics_and_GetCharacteristic) {
#endif
if (!PlatformSupportsLowEnergy()) {
LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
return;
}
InitWithFakeAdapter();
StartLowEnergyDiscoverySession();
BluetoothDevice* device = SimulateLowEnergyDevice(3);
device->CreateGattConnection(GetGattConnectionCallback(Call::EXPECTED),
GetConnectErrorCallback(Call::NOT_EXPECTED));
SimulateGattConnection(device);
base::RunLoop().RunUntilIdle();
// Simulate a service, with several Characteristics:
SimulateGattServicesDiscovered(
device, std::vector<std::string>({kTestUUIDGenericAccess}));
base::RunLoop().RunUntilIdle();
BluetoothRemoteGattService* service = device->GetGattServices()[0];
SimulateGattCharacteristic(service, kTestUUIDDeviceName, /* properties */ 0);
SimulateGattCharacteristic(service, kTestUUIDAppearance,
/* properties */ 0);
// Duplicate UUID.
SimulateGattCharacteristic(service, kTestUUIDAppearance,
/* properties */ 0);
SimulateGattCharacteristic(service, kTestUUIDReconnectionAddress,
/* properties */ 0);
base::RunLoop().RunUntilIdle();
// Verify that GetCharacteristic can retrieve characteristics again by ID,
// and that the same Characteristics come back.
EXPECT_EQ(4u, service->GetCharacteristics().size());
std::string char_id1 = service->GetCharacteristics()[0]->GetIdentifier();
std::string char_id2 = service->GetCharacteristics()[1]->GetIdentifier();
std::string char_id3 = service->GetCharacteristics()[2]->GetIdentifier();
std::string char_id4 = service->GetCharacteristics()[3]->GetIdentifier();
BluetoothUUID char_uuid1 = service->GetCharacteristics()[0]->GetUUID();
BluetoothUUID char_uuid2 = service->GetCharacteristics()[1]->GetUUID();
BluetoothUUID char_uuid3 = service->GetCharacteristics()[2]->GetUUID();
BluetoothUUID char_uuid4 = service->GetCharacteristics()[3]->GetUUID();
EXPECT_EQ(char_uuid1, service->GetCharacteristic(char_id1)->GetUUID());
EXPECT_EQ(char_uuid2, service->GetCharacteristic(char_id2)->GetUUID());
EXPECT_EQ(char_uuid3, service->GetCharacteristic(char_id3)->GetUUID());
EXPECT_EQ(char_uuid4, service->GetCharacteristic(char_id4)->GetUUID());
// GetCharacteristics & GetCharacteristic return the same object for the same
// ID:
EXPECT_EQ(service->GetCharacteristics()[0],
service->GetCharacteristic(char_id1));
EXPECT_EQ(service->GetCharacteristic(char_id1),
service->GetCharacteristic(char_id1));
}
#if defined(OS_ANDROID) || defined(OS_MACOSX)
#define MAYBE_GetCharacteristicsByUUID GetCharacteristicsByUUID
#else
#define MAYBE_GetCharacteristicsByUUID DISABLED_GetCharacteristicsByUUID
#endif
#if defined(OS_WIN)
TEST_P(BluetoothRemoteGattServiceTestWinrt, GetCharacteristicsByUUID) {
#else
TEST_F(BluetoothRemoteGattServiceTest, MAYBE_GetCharacteristicsByUUID) {
#endif
if (!PlatformSupportsLowEnergy()) {
LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
return;
}
InitWithFakeAdapter();
StartLowEnergyDiscoverySession();
BluetoothDevice* device = SimulateLowEnergyDevice(3);
device->CreateGattConnection(GetGattConnectionCallback(Call::EXPECTED),
GetConnectErrorCallback(Call::NOT_EXPECTED));
SimulateGattConnection(device);
base::RunLoop().RunUntilIdle();
// Simulate two primary GATT services.
SimulateGattServicesDiscovered(
device,
std::vector<std::string>({kTestUUIDGenericAccess, kTestUUIDHeartRate}));
base::RunLoop().RunUntilIdle();
BluetoothRemoteGattService* service1 = device->GetGattServices()[0];
BluetoothRemoteGattService* service2 = device->GetGattServices()[1];
SimulateGattCharacteristic(service1, kTestUUIDDeviceName,
/* properties */ 0);
// 2 duplicate UUIDs creating 2 instances.
SimulateGattCharacteristic(service2, kTestUUIDHeartRateMeasurement,
/* properties */ 0);
SimulateGattCharacteristic(service2, kTestUUIDHeartRateMeasurement,
/* properties */ 0);
base::RunLoop().RunUntilIdle();
{
std::vector<BluetoothRemoteGattCharacteristic*> characteristics =
service1->GetCharacteristicsByUUID(BluetoothUUID(kTestUUIDDeviceName));
EXPECT_EQ(1u, characteristics.size());
EXPECT_EQ(kTestUUIDDeviceName,
characteristics[0]->GetUUID().canonical_value());
}
{
std::vector<BluetoothRemoteGattCharacteristic*> characteristics =
service2->GetCharacteristicsByUUID(
BluetoothUUID(kTestUUIDHeartRateMeasurement));
EXPECT_EQ(2u, characteristics.size());
EXPECT_EQ(kTestUUIDHeartRateMeasurement,
characteristics[0]->GetUUID().canonical_value());
EXPECT_EQ(kTestUUIDHeartRateMeasurement,
characteristics[1]->GetUUID().canonical_value());
EXPECT_NE(characteristics[0]->GetIdentifier(),
characteristics[1]->GetIdentifier());
}
BluetoothUUID characteristic_uuid_not_exist_in_setup(
"33333333-0000-1000-8000-00805f9b34fb");
EXPECT_TRUE(
service1->GetCharacteristicsByUUID(characteristic_uuid_not_exist_in_setup)
.empty());
EXPECT_TRUE(
service2->GetCharacteristicsByUUID(characteristic_uuid_not_exist_in_setup)
.empty());
}
#if defined(OS_MACOSX) || defined(OS_WIN)
#define MAYBE_GattCharacteristics_ObserversCalls \
GattCharacteristics_ObserversCalls
#else
#define MAYBE_GattCharacteristics_ObserversCalls \
DISABLED_GattCharacteristics_ObserversCalls
#endif
// The GattServicesRemoved event is not implemented for WinRT.
TEST_F(BluetoothRemoteGattServiceTest,
MAYBE_GattCharacteristics_ObserversCalls) {
if (!PlatformSupportsLowEnergy()) {
LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
return;
}
InitWithFakeAdapter();
StartLowEnergyDiscoverySession();
BluetoothDevice* device = SimulateLowEnergyDevice(3);
device->CreateGattConnection(GetGattConnectionCallback(Call::EXPECTED),
GetConnectErrorCallback(Call::NOT_EXPECTED));
SimulateGattConnection(device);
base::RunLoop().RunUntilIdle();
TestBluetoothAdapterObserver observer(adapter_);
// Simulate a service, with several Characteristics:
SimulateGattServicesDiscovered(
device, std::vector<std::string>({kTestUUIDGenericAccess}));
base::RunLoop().RunUntilIdle();
BluetoothRemoteGattService* service = device->GetGattServices()[0];
SimulateGattCharacteristic(service, kTestUUIDDeviceName, /* properties */ 0);
SimulateGattCharacteristic(service, kTestUUIDAppearance,
/* properties */ 0);
// Duplicate UUID.
SimulateGattCharacteristic(service, kTestUUIDAppearance,
/* properties */ 0);
SimulateGattCharacteristic(service, kTestUUIDReconnectionAddress,
/* properties */ 0);
// Simulate remove of characteristics one by one.
EXPECT_EQ(4u, service->GetCharacteristics().size());
std::string removed_char = service->GetCharacteristics()[0]->GetIdentifier();
SimulateGattCharacteristicRemoved(service,
service->GetCharacteristic(removed_char));
EXPECT_EQ(1, observer.gatt_characteristic_removed_count());
EXPECT_FALSE(service->GetCharacteristic(removed_char));
EXPECT_EQ(3u, service->GetCharacteristics().size());
removed_char = service->GetCharacteristics()[0]->GetIdentifier();
SimulateGattCharacteristicRemoved(service,
service->GetCharacteristic(removed_char));
EXPECT_EQ(2, observer.gatt_characteristic_removed_count());
EXPECT_FALSE(service->GetCharacteristic(removed_char));
EXPECT_EQ(2u, service->GetCharacteristics().size());
removed_char = service->GetCharacteristics()[0]->GetIdentifier();
SimulateGattCharacteristicRemoved(service,
service->GetCharacteristic(removed_char));
EXPECT_EQ(3, observer.gatt_characteristic_removed_count());
EXPECT_FALSE(service->GetCharacteristic(removed_char));
EXPECT_EQ(1u, service->GetCharacteristics().size());
removed_char = service->GetCharacteristics()[0]->GetIdentifier();
SimulateGattCharacteristicRemoved(service,
service->GetCharacteristic(removed_char));
EXPECT_EQ(4, observer.gatt_characteristic_removed_count());
EXPECT_FALSE(service->GetCharacteristic(removed_char));
EXPECT_EQ(0u, service->GetCharacteristics().size());
}
#if defined(OS_MACOSX)
#define MAYBE_SimulateGattServiceRemove SimulateGattServiceRemove
#else
#define MAYBE_SimulateGattServiceRemove DISABLED_SimulateGattServiceRemove
#endif
#if defined(OS_WIN)
TEST_P(BluetoothRemoteGattServiceTestWinrt, SimulateGattServiceRemove) {
#else
TEST_F(BluetoothRemoteGattServiceTest, MAYBE_SimulateGattServiceRemove) {
#endif
if (!PlatformSupportsLowEnergy()) {
LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
return;
}
InitWithFakeAdapter();
StartLowEnergyDiscoverySession();
BluetoothDevice* device = SimulateLowEnergyDevice(3);
device->CreateGattConnection(GetGattConnectionCallback(Call::EXPECTED),
GetConnectErrorCallback(Call::NOT_EXPECTED));
SimulateGattConnection(device);
base::RunLoop().RunUntilIdle();
TestBluetoothAdapterObserver observer(adapter_);
// Simulate two primary GATT services.
SimulateGattServicesDiscovered(
device,
std::vector<std::string>({kTestUUIDGenericAccess, kTestUUIDHeartRate}));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(2u, device->GetGattServices().size());
// Simulate remove of a primary service.
BluetoothRemoteGattService* service1 = device->GetGattServices()[0];
BluetoothRemoteGattService* service2 = device->GetGattServices()[1];
std::string removed_service = service1->GetIdentifier();
SimulateGattServiceRemoved(device->GetGattService(removed_service));
base::RunLoop().RunUntilIdle();
#if defined(OS_WIN)
if (!GetParam()) {
// The GattServicesRemoved event is not implemented for WinRT.
EXPECT_EQ(1, observer.gatt_service_removed_count());
}
#endif // defined(OS_WIN)
EXPECT_EQ(1u, device->GetGattServices().size());
EXPECT_FALSE(device->GetGattService(removed_service));
EXPECT_EQ(device->GetGattServices()[0], service2);
}
#if defined(OS_MACOSX)
// Tests to receive a services changed notification from macOS, while
// discovering characteristics. The gatt device should scan again for services
// and characteristics, before scanning for descriptors. Only after the gatt
// service changed notification should be sent.
// Android: This test doesn't apply to Android because there is no services
// changed event that could arrive during a discovery procedure.
TEST_F(BluetoothRemoteGattServiceTest,
SimulateDeviceModificationWhileDiscoveringCharacteristics) {
if (!PlatformSupportsLowEnergy()) {
LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
return;
}
InitWithFakeAdapter();
StartLowEnergyDiscoverySession();
BluetoothDevice* device = SimulateLowEnergyDevice(3);
device->CreateGattConnection(GetGattConnectionCallback(Call::EXPECTED),
GetConnectErrorCallback(Call::NOT_EXPECTED));
TestBluetoothAdapterObserver observer(adapter_);
// Starts first discovery process.
SimulateGattConnection(device);
AddServicesToDeviceMac(device, {kTestUUIDHeartRate});
SimulateDidDiscoverServicesMac(device);
EXPECT_EQ(1u, device->GetGattServices().size());
BluetoothRemoteGattService* service = device->GetGattServices()[0];
std::string characteristic_uuid1 = "11111111-0000-1000-8000-00805f9b34fb";
AddCharacteristicToServiceMac(service, characteristic_uuid1,
/* properties */ 0);
// Now waiting for characteristic discovery.
// Starts second discovery process.
SimulateGattServicesChanged(device);
SimulateDidDiscoverServicesMac(device);
// Now waiting for the second characteristic discovery.
// First system call to -[id<CBPeripheralDelegate>
// peripheral:didDiscoverCharacteristicsForService:error:]
SimulateDidDiscoverCharacteristicsMac(service);
EXPECT_EQ(0, observer.gatt_service_changed_count());
EXPECT_EQ(1u, service->GetCharacteristics().size());
// Finish discovery process.
std::string characteristic_uuid2 = "22222222-0000-1000-8000-00805f9b34fb";
AddCharacteristicToServiceMac(service, characteristic_uuid2,
/* properties */ 0);
// Second system call to -[id<CBPeripheralDelegate>
// peripheral:didDiscoverCharacteristicsForService:error:]
SimulateDidDiscoverCharacteristicsMac(service);
EXPECT_EQ(2u, service->GetCharacteristics().size());
EXPECT_EQ(0, observer.gatt_service_changed_count());
BluetoothRemoteGattCharacteristic* characteristic1 =
service->GetCharacteristics()[0];
BluetoothRemoteGattCharacteristic* characteristic2 =
service->GetCharacteristics()[1];
if (characteristic1->GetUUID().canonical_value() == characteristic_uuid2) {
BluetoothRemoteGattCharacteristic* tmp = characteristic1;
characteristic1 = characteristic2;
characteristic2 = tmp;
}
EXPECT_EQ(characteristic_uuid1, characteristic1->GetUUID().canonical_value());
EXPECT_EQ(characteristic_uuid2, characteristic2->GetUUID().canonical_value());
SimulateDidDiscoverDescriptorsMac(characteristic1);
SimulateDidDiscoverDescriptorsMac(characteristic2);
EXPECT_EQ(1, observer.gatt_service_changed_count());
}
#endif // defined(OS_MACOSX)
#if defined(OS_MACOSX)
// Simulates to receive an extra discovery characteristic notifications from
// macOS. Those notifications should be ignored.
// Android: This test doesn't apply to Android because there is no services
// changed event that could arrive during a discovery procedure.
TEST_F(BluetoothRemoteGattServiceTest, ExtraDidDiscoverServicesCall) {
if (!PlatformSupportsLowEnergy()) {
LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
return;
}
InitWithFakeAdapter();
StartLowEnergyDiscoverySession();
BluetoothDevice* device = SimulateLowEnergyDevice(3);
device->CreateGattConnection(GetGattConnectionCallback(Call::EXPECTED),
GetConnectErrorCallback(Call::NOT_EXPECTED));
TestBluetoothAdapterObserver observer(adapter_);
// Starts first discovery process.
SimulateGattConnection(device);
AddServicesToDeviceMac(device, {kTestUUIDHeartRate});
SimulateDidDiscoverServicesMac(device);
EXPECT_EQ(1u, device->GetGattServices().size());
BluetoothRemoteGattService* service = device->GetGattServices()[0];
std::string characteristic_uuid = "11111111-0000-1000-8000-00805f9b34fb";
AddCharacteristicToServiceMac(service, characteristic_uuid,
/* properties */ 0);
SimulateDidDiscoverCharacteristicsMac(service);
EXPECT_EQ(1u, service->GetCharacteristics().size());
BluetoothRemoteGattCharacteristic* characteristic =
service->GetCharacteristics()[0];
std::string descriptor_uuid = "22222222-0000-1000-8000-00805f9b34fb";
AddDescriptorToCharacteristicMac(characteristic, descriptor_uuid);
SimulateDidDiscoverDescriptorsMac(characteristic);
EXPECT_EQ(1, observer.gatt_service_changed_count());
EXPECT_EQ(1u, service->GetCharacteristics().size());
EXPECT_EQ(1u, characteristic->GetDescriptors().size());
observer.Reset();
SimulateDidDiscoverServicesMac(device); // Extra system call.
SimulateGattServicesChanged(device);
SimulateDidDiscoverServicesMac(device);
SimulateDidDiscoverServicesMac(device); // Extra system call.
SimulateDidDiscoverCharacteristicsMac(service);
SimulateDidDiscoverServicesMac(device); // Extra system call.
SimulateDidDiscoverDescriptorsMac(characteristic);
SimulateDidDiscoverServicesMac(device); // Extra system call.
EXPECT_EQ(2, observer.device_changed_count());
}
#endif // defined(OS_MACOSX)
#if defined(OS_MACOSX)
// Simulates to receive an extra discovery characteristic notifications from
// macOS. Those notifications should be ignored.
// Android: This test doesn't apply to Android because there is no services
// changed event that could arrive during a discovery procedure.
TEST_F(BluetoothRemoteGattServiceTest, ExtraDidDiscoverCharacteristicsCall) {
if (!PlatformSupportsLowEnergy()) {
LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
return;
}
InitWithFakeAdapter();
StartLowEnergyDiscoverySession();
BluetoothDevice* device = SimulateLowEnergyDevice(3);
device->CreateGattConnection(GetGattConnectionCallback(Call::EXPECTED),
GetConnectErrorCallback(Call::NOT_EXPECTED));
TestBluetoothAdapterObserver observer(adapter_);
// Starts first discovery process.
SimulateGattConnection(device);
AddServicesToDeviceMac(device, {kTestUUIDHeartRate});
SimulateDidDiscoverServicesMac(device);
EXPECT_EQ(1u, device->GetGattServices().size());
BluetoothRemoteGattService* service = device->GetGattServices()[0];
std::string characteristic_uuid = "11111111-0000-1000-8000-00805f9b34fb";
AddCharacteristicToServiceMac(service, characteristic_uuid,
/* properties */ 0);
SimulateDidDiscoverCharacteristicsMac(service);
EXPECT_EQ(1u, service->GetCharacteristics().size());
BluetoothRemoteGattCharacteristic* characteristic =
service->GetCharacteristics()[0];
std::string descriptor_uuid = "22222222-0000-1000-8000-00805f9b34fb";
AddDescriptorToCharacteristicMac(characteristic, descriptor_uuid);
SimulateDidDiscoverDescriptorsMac(characteristic);
EXPECT_EQ(1, observer.gatt_service_changed_count());
EXPECT_EQ(1u, service->GetCharacteristics().size());
EXPECT_EQ(1u, characteristic->GetDescriptors().size());
observer.Reset();
SimulateDidDiscoverCharacteristicsMac(service); // Extra system call.
SimulateGattServicesChanged(device);
SimulateDidDiscoverCharacteristicsMac(service); // Extra system call.
SimulateDidDiscoverServicesMac(device);
SimulateDidDiscoverCharacteristicsMac(service);
SimulateDidDiscoverCharacteristicsMac(service); // Extra system call.
SimulateDidDiscoverDescriptorsMac(characteristic);
SimulateDidDiscoverCharacteristicsMac(service); // Extra system call.
EXPECT_EQ(2, observer.device_changed_count());
}
#endif // defined(OS_MACOSX)
#if defined(OS_WIN)
INSTANTIATE_TEST_CASE_P(
/* no prefix */,
BluetoothRemoteGattServiceTestWinrt,
::testing::Bool());
#endif // defined(OS_WIN)
} // namespace device