Index: components/arc/bluetooth/arc_bluetooth_bridge_unittest.cc |
diff --git a/components/arc/bluetooth/arc_bluetooth_bridge_unittest.cc b/components/arc/bluetooth/arc_bluetooth_bridge_unittest.cc |
index 62f984996eadfb88a931bd74b978d8a4f2a6de92..23041dfd22170f16fc4a1f6775af9b1d3b2a4ff3 100644 |
--- a/components/arc/bluetooth/arc_bluetooth_bridge_unittest.cc |
+++ b/components/arc/bluetooth/arc_bluetooth_bridge_unittest.cc |
@@ -21,11 +21,14 @@ |
#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_le_advertising_manager_client.h" |
#include "mojo/public/cpp/bindings/array.h" |
#include "testing/gtest/include/gtest/gtest.h" |
namespace arc { |
+constexpr int kFailureAdvHandle = -1; |
+ |
class ArcBluetoothBridgeTest : public testing::Test { |
protected: |
void AddTestDevice() { |
@@ -82,6 +85,70 @@ class ArcBluetoothBridgeTest : public testing::Test { |
get_adapter_run_loop_.Run(); |
} |
+ // Helper methods for multi advertisement tests. |
+ int32_t ReserveAdvertisementHandle() { |
+ constexpr int kSentinelHandle = -2; |
+ last_adv_handle_ = kSentinelHandle; |
+ arc_bluetooth_bridge_->ReserveAdvertisementHandle( |
+ base::Bind(&ArcBluetoothBridgeTest::ReserveAdvertisementHandleCallback, |
+ base::Unretained(this))); |
+ |
+ base::RunLoop().RunUntilIdle(); |
+ // Make sure the callback was called. |
+ EXPECT_NE(kSentinelHandle, last_adv_handle_); |
+ return last_adv_handle_; |
+ } |
+ |
+ mojom::BluetoothGattStatus BroadcastAdvertisement( |
+ int adv_handle, |
+ std::unique_ptr<device::BluetoothAdvertisement::Data> data) { |
+ last_status_ = mojom::BluetoothGattStatus::GATT_REQUEST_NOT_SUPPORTED; |
+ arc_bluetooth_bridge_->BroadcastAdvertisement( |
+ adv_handle, std::move(data), |
+ base::Bind(&ArcBluetoothBridgeTest::StatusSetterCallback, |
+ base::Unretained(this))); |
+ |
+ base::RunLoop().RunUntilIdle(); |
+ EXPECT_NE(mojom::BluetoothGattStatus::GATT_REQUEST_NOT_SUPPORTED, |
+ last_status_); |
+ return last_status_; |
+ } |
+ |
+ mojom::BluetoothGattStatus ReleaseAdvertisementHandle(int adv_handle) { |
+ last_status_ = mojom::BluetoothGattStatus::GATT_REQUEST_NOT_SUPPORTED; |
+ arc_bluetooth_bridge_->ReleaseAdvertisementHandle( |
+ adv_handle, base::Bind(&ArcBluetoothBridgeTest::StatusSetterCallback, |
+ base::Unretained(this))); |
+ |
+ base::RunLoop().RunUntilIdle(); |
+ EXPECT_NE(mojom::BluetoothGattStatus::GATT_REQUEST_NOT_SUPPORTED, |
+ last_status_); |
+ return last_status_; |
+ } |
+ |
+ void ReserveAdvertisementHandleCallback(mojom::BluetoothGattStatus status, |
+ int32_t adv_handle) { |
+ if (status == mojom::BluetoothGattStatus::GATT_FAILURE) |
+ last_adv_handle_ = kFailureAdvHandle; |
+ else |
+ last_adv_handle_ = adv_handle; |
+ } |
+ |
+ void StatusSetterCallback(mojom::BluetoothGattStatus status) { |
+ last_status_ = status; |
+ } |
+ |
+ int NumActiveAdvertisements() { |
+ bluez::FakeBluetoothLEAdvertisingManagerClient* adv_client = |
+ static_cast<bluez::FakeBluetoothLEAdvertisingManagerClient*>( |
+ bluez::BluezDBusManager::Get() |
+ ->GetBluetoothLEAdvertisingManagerClient()); |
+ return adv_client->currently_registered(); |
+ } |
+ |
+ int last_adv_handle_; |
+ mojom::BluetoothGattStatus last_status_; |
+ |
std::unique_ptr<FakeArcBridgeService> fake_arc_bridge_service_; |
std::unique_ptr<FakeBluetoothInstance> fake_bluetooth_instance_; |
std::unique_ptr<ArcBluetoothBridge> arc_bluetooth_bridge_; |
@@ -211,4 +278,78 @@ TEST_F(ArcBluetoothBridgeTest, GetGattDB) { |
db[4]->properties); |
} |
+// Invoke multi advertisement methods and make sure they are going down to the |
+// D-Bus clients. |
+TEST_F(ArcBluetoothBridgeTest, SingleAdvertisement) { |
+ int32_t handle = ReserveAdvertisementHandle(); |
+ EXPECT_NE(kFailureAdvHandle, handle); |
+ EXPECT_EQ(0, NumActiveAdvertisements()); |
+ |
+ auto adv_data = base::MakeUnique<device::BluetoothAdvertisement::Data>( |
+ device::BluetoothAdvertisement::ADVERTISEMENT_TYPE_BROADCAST); |
+ mojom::BluetoothGattStatus status = |
+ BroadcastAdvertisement(handle, std::move(adv_data)); |
+ EXPECT_EQ(mojom::BluetoothGattStatus::GATT_SUCCESS, status); |
+ EXPECT_EQ(1, NumActiveAdvertisements()); |
+ |
+ status = ReleaseAdvertisementHandle(handle); |
+ EXPECT_EQ(mojom::BluetoothGattStatus::GATT_SUCCESS, status); |
+ EXPECT_EQ(0, NumActiveAdvertisements()); |
+} |
+ |
+// Invoke multi advertisement methods and make sure they are going down to the |
+// D-Bus clients. |
+TEST_F(ArcBluetoothBridgeTest, MultiAdvertisement) { |
+ int32_t handle = ReserveAdvertisementHandle(); |
+ EXPECT_NE(kFailureAdvHandle, handle); |
+ EXPECT_EQ(0, NumActiveAdvertisements()); |
+ |
+ auto adv_data = base::MakeUnique<device::BluetoothAdvertisement::Data>( |
+ device::BluetoothAdvertisement::ADVERTISEMENT_TYPE_BROADCAST); |
+ mojom::BluetoothGattStatus status = |
+ BroadcastAdvertisement(handle, std::move(adv_data)); |
+ EXPECT_EQ(mojom::BluetoothGattStatus::GATT_SUCCESS, status); |
+ EXPECT_EQ(1, NumActiveAdvertisements()); |
+ |
+ int32_t handle2 = ReserveAdvertisementHandle(); |
+ EXPECT_NE(kFailureAdvHandle, handle2); |
+ auto adv_data2 = base::MakeUnique<device::BluetoothAdvertisement::Data>( |
+ device::BluetoothAdvertisement::ADVERTISEMENT_TYPE_PERIPHERAL); |
+ status = BroadcastAdvertisement(handle2, std::move(adv_data2)); |
+ EXPECT_EQ(mojom::BluetoothGattStatus::GATT_SUCCESS, status); |
+ EXPECT_EQ(2, NumActiveAdvertisements()); |
+ |
+ status = ReleaseAdvertisementHandle(handle); |
+ EXPECT_EQ(mojom::BluetoothGattStatus::GATT_SUCCESS, status); |
+ EXPECT_EQ(1, NumActiveAdvertisements()); |
+ |
+ status = ReleaseAdvertisementHandle(handle2); |
+ EXPECT_EQ(mojom::BluetoothGattStatus::GATT_SUCCESS, status); |
+ EXPECT_EQ(0, NumActiveAdvertisements()); |
+} |
+ |
+// This tests that we support releasing reserved but unused handles. |
+// TODO(ejcaruso): When Chrome supports more handles, make sure we |
+// will stop reserving handles before we use all of Chrome's. |
+TEST_F(ArcBluetoothBridgeTest, ReleaseUnusedHandles) { |
+ constexpr size_t kMaxBluezAdvertisements = |
+ bluez::FakeBluetoothLEAdvertisingManagerClient::kMaxBluezAdvertisements; |
+ std::vector<int32_t> reserved_handles; |
+ |
+ for (size_t i = 0; i < kMaxBluezAdvertisements; i++) { |
+ int32_t handle = ReserveAdvertisementHandle(); |
+ if (handle == kFailureAdvHandle) |
+ break; |
+ reserved_handles.push_back(handle); |
+ } |
+ EXPECT_GT(reserved_handles.size(), 1Ul); |
+ EXPECT_LE(reserved_handles.size(), kMaxBluezAdvertisements); |
+ EXPECT_EQ(0, NumActiveAdvertisements()); |
+ |
+ for (int32_t handle : reserved_handles) { |
+ EXPECT_EQ(ReleaseAdvertisementHandle(handle), |
+ mojom::BluetoothGattStatus::GATT_SUCCESS); |
+ } |
+} |
+ |
} // namespace arc |