| // Copyright 2023 The Pigweed Authors |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| // use this file except in compliance with the License. You may obtain a copy of |
| // the License at |
| // |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| // License for the specific language governing permissions and limitations under |
| // the License. |
| |
| #include "pw_bluetooth_sapphire/internal/host/hci/advertising_handle_map.h" |
| |
| #include "pw_bluetooth_sapphire/internal/host/hci-spec/constants.h" |
| #include "pw_bluetooth_sapphire/internal/host/hci-spec/protocol.h" |
| #include "pw_unit_test/framework.h" |
| |
| namespace bt::hci { |
| namespace { |
| |
| TEST(AdvertisingHandleMapTest, Bidirectional) { |
| AdvertisingHandleMap handle_map; |
| |
| DeviceAddress address_a = DeviceAddress(DeviceAddress::Type::kLEPublic, {0}); |
| std::optional<hci_spec::AdvertisingHandle> handle_a = |
| handle_map.MapHandle(address_a); |
| EXPECT_LE(handle_a.value(), hci_spec::kMaxAdvertisingHandle); |
| EXPECT_TRUE(handle_a); |
| |
| DeviceAddress address_b = DeviceAddress(DeviceAddress::Type::kLEPublic, {1}); |
| std::optional<hci_spec::AdvertisingHandle> handle_b = |
| handle_map.MapHandle(address_b); |
| EXPECT_TRUE(handle_b); |
| EXPECT_LE(handle_b.value(), hci_spec::kMaxAdvertisingHandle); |
| |
| EXPECT_EQ(address_a, handle_map.GetAddress(handle_a.value())); |
| EXPECT_EQ(address_b, handle_map.GetAddress(handle_b.value())); |
| } |
| |
| TEST(AdvertisingHandleMapTest, GetHandleDoesntCreateMapping) { |
| AdvertisingHandleMap handle_map; |
| EXPECT_EQ(0u, handle_map.Size()); |
| EXPECT_TRUE(handle_map.Empty()); |
| |
| DeviceAddress address = DeviceAddress(DeviceAddress::Type::kLEPublic, {0}); |
| std::optional<hci_spec::AdvertisingHandle> handle = |
| handle_map.GetHandle(address); |
| EXPECT_EQ(0u, handle_map.Size()); |
| EXPECT_TRUE(handle_map.Empty()); |
| EXPECT_FALSE(handle); |
| |
| handle = handle_map.MapHandle(address); |
| EXPECT_EQ(1u, handle_map.Size()); |
| EXPECT_FALSE(handle_map.Empty()); |
| EXPECT_TRUE(handle); |
| EXPECT_EQ(0u, handle.value()); |
| |
| handle = handle_map.GetHandle(address); |
| EXPECT_EQ(1u, handle_map.Size()); |
| EXPECT_FALSE(handle_map.Empty()); |
| EXPECT_TRUE(handle); |
| } |
| |
| TEST(AdvertisingHandleMapTest, MapHandleAlreadyExists) { |
| AdvertisingHandleMap handle_map; |
| |
| DeviceAddress address = DeviceAddress(DeviceAddress::Type::kLEPublic, {0}); |
| std::optional<hci_spec::AdvertisingHandle> expected = |
| handle_map.MapHandle(address); |
| EXPECT_LE(expected.value(), hci_spec::kMaxAdvertisingHandle); |
| ASSERT_TRUE(expected); |
| |
| std::optional<hci_spec::AdvertisingHandle> actual = |
| handle_map.MapHandle(address); |
| EXPECT_LE(actual.value(), hci_spec::kMaxAdvertisingHandle); |
| ASSERT_TRUE(actual); |
| EXPECT_EQ(expected, actual); |
| } |
| |
| TEST(AdvertisingHandleMapTest, MapHandleMoreThanSupported) { |
| AdvertisingHandleMap handle_map; |
| |
| for (uint8_t i = 0; i < handle_map.capacity(); i++) { |
| DeviceAddress address = DeviceAddress(DeviceAddress::Type::kLEPublic, {i}); |
| std::optional<hci_spec::AdvertisingHandle> handle = |
| handle_map.MapHandle(address); |
| EXPECT_LE(handle.value(), hci_spec::kMaxAdvertisingHandle); |
| EXPECT_TRUE(handle) << "Couldn't add device address " << i; |
| EXPECT_EQ(i + 1u, handle_map.Size()); |
| } |
| |
| DeviceAddress address = |
| DeviceAddress(DeviceAddress::Type::kLEPublic, {handle_map.capacity()}); |
| |
| std::optional<hci_spec::AdvertisingHandle> handle = |
| handle_map.MapHandle(address); |
| EXPECT_FALSE(handle); |
| EXPECT_EQ(handle_map.capacity(), handle_map.Size()); |
| } |
| |
| TEST(AdvertisingHandleMapTest, MapHandleSupportHandleReallocation) { |
| AdvertisingHandleMap handle_map; |
| |
| for (uint8_t i = 0; i < handle_map.capacity(); i++) { |
| DeviceAddress address = DeviceAddress(DeviceAddress::Type::kLEPublic, {i}); |
| std::optional<hci_spec::AdvertisingHandle> handle = |
| handle_map.MapHandle(address); |
| EXPECT_LE(handle.value(), hci_spec::kMaxAdvertisingHandle); |
| EXPECT_TRUE(handle) << "Couldn't add device address " << i; |
| EXPECT_EQ(i + 1u, handle_map.Size()); |
| } |
| |
| hci_spec::AdvertisingHandle old_handle = 0; |
| std::optional<DeviceAddress> old_address = handle_map.GetAddress(old_handle); |
| ASSERT_TRUE(old_address); |
| |
| handle_map.RemoveHandle(old_handle); |
| |
| DeviceAddress address = |
| DeviceAddress(DeviceAddress::Type::kLEPublic, {handle_map.capacity()}); |
| std::optional<hci_spec::AdvertisingHandle> new_handle = |
| handle_map.MapHandle(address); |
| EXPECT_LE(new_handle.value(), hci_spec::kMaxAdvertisingHandle); |
| |
| ASSERT_TRUE(new_handle); |
| ASSERT_EQ(old_handle, new_handle.value()); |
| |
| std::optional<DeviceAddress> new_address = |
| handle_map.GetAddress(new_handle.value()); |
| ASSERT_TRUE(new_address); |
| ASSERT_NE(old_address, new_address); |
| } |
| |
| TEST(AdvertisingHandleMapTest, GetAddressNonExistent) { |
| AdvertisingHandleMap handle_map; |
| std::optional<DeviceAddress> address = handle_map.GetAddress(0); |
| EXPECT_FALSE(address); |
| } |
| |
| TEST(AdvertisingHandleMapTest, RemoveHandle) { |
| AdvertisingHandleMap handle_map; |
| EXPECT_TRUE(handle_map.Empty()); |
| |
| DeviceAddress address = DeviceAddress(DeviceAddress::Type::kLEPublic, {0}); |
| std::optional<hci_spec::AdvertisingHandle> handle = |
| handle_map.MapHandle(address); |
| EXPECT_LE(handle.value(), hci_spec::kMaxAdvertisingHandle); |
| EXPECT_EQ(1u, handle_map.Size()); |
| EXPECT_FALSE(handle_map.Empty()); |
| |
| handle_map.RemoveHandle(handle.value()); |
| EXPECT_EQ(0u, handle_map.Size()); |
| EXPECT_TRUE(handle_map.Empty()); |
| } |
| |
| TEST(AdvertisingHandleMapTest, RemoveAddress) { |
| AdvertisingHandleMap handle_map; |
| EXPECT_TRUE(handle_map.Empty()); |
| |
| DeviceAddress address = DeviceAddress(DeviceAddress::Type::kLEPublic, {0}); |
| handle_map.MapHandle(address); |
| EXPECT_EQ(1u, handle_map.Size()); |
| EXPECT_FALSE(handle_map.Empty()); |
| |
| handle_map.RemoveAddress(address); |
| EXPECT_EQ(0u, handle_map.Size()); |
| EXPECT_TRUE(handle_map.Empty()); |
| } |
| |
| TEST(AdvertisingHandleMapTest, RemoveHandleNonExistent) { |
| AdvertisingHandleMap handle_map; |
| DeviceAddress address = DeviceAddress(DeviceAddress::Type::kLEPublic, {0}); |
| std::optional<hci_spec::AdvertisingHandle> handle = |
| handle_map.MapHandle(address); |
| ASSERT_TRUE(handle); |
| |
| size_t size = handle_map.Size(); |
| |
| handle_map.RemoveHandle(handle.value() + 1); |
| |
| EXPECT_EQ(size, handle_map.Size()); |
| handle = handle_map.MapHandle(address); |
| EXPECT_TRUE(handle); |
| } |
| |
| TEST(AdvertisingHandleMapTest, RemoveAddressNonExistent) { |
| AdvertisingHandleMap handle_map; |
| DeviceAddress address = DeviceAddress(DeviceAddress::Type::kLEPublic, {0}); |
| std::optional<hci_spec::AdvertisingHandle> handle = |
| handle_map.MapHandle(address); |
| ASSERT_TRUE(handle); |
| |
| size_t size = handle_map.Size(); |
| |
| DeviceAddress nonexistent_address = |
| DeviceAddress(DeviceAddress::Type::kLEPublic, {1}); |
| handle_map.RemoveAddress(nonexistent_address); |
| |
| EXPECT_EQ(size, handle_map.Size()); |
| handle = handle_map.MapHandle(address); |
| EXPECT_TRUE(handle); |
| } |
| |
| TEST(AdvertisingHandleMapTest, Clear) { |
| AdvertisingHandleMap handle_map; |
| std::optional<hci_spec::AdvertisingHandle> handle = |
| handle_map.MapHandle(DeviceAddress(DeviceAddress::Type::kLEPublic, {0})); |
| EXPECT_LE(handle.value(), hci_spec::kMaxAdvertisingHandle); |
| EXPECT_TRUE(handle); |
| EXPECT_EQ(1u, handle_map.Size()); |
| |
| handle_map.Clear(); |
| EXPECT_EQ(0u, handle_map.Size()); |
| |
| std::optional<DeviceAddress> address = handle_map.GetAddress(handle.value()); |
| EXPECT_FALSE(address); |
| } |
| |
| } // namespace |
| } // namespace bt::hci |