blob: 716da219bd409d8ccaa23e8574f2b5c5f370833a [file] [log] [blame]
// 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/transport/slab_allocators.h"
#include <forward_list>
#include <list>
#include "pw_bluetooth_sapphire/internal/host/transport/acl_data_packet.h"
#include "pw_bluetooth_sapphire/internal/host/transport/control_packets.h"
#include "pw_unit_test/framework.h"
namespace bt::hci::allocators {
namespace {
constexpr hci_spec::OpCode kTestOpCode = 0xFFFF;
TEST(SlabAllocatorsTest, CommandPacket) {
auto packet = CommandPacket::New(kTestOpCode, 5);
EXPECT_TRUE(packet);
EXPECT_EQ(5u + sizeof(hci_spec::CommandHeader), packet->view().size());
packet = CommandPacket::New(kTestOpCode, kSmallControlPayloadSize);
EXPECT_TRUE(packet);
EXPECT_GE(packet->view().size(), kSmallControlPacketSize);
packet = CommandPacket::New(kTestOpCode, kSmallControlPayloadSize + 1);
EXPECT_TRUE(packet);
EXPECT_EQ(kSmallControlPacketSize + 1, packet->view().size());
}
TEST(SlabAllocatorsTest, CommandPacketFallBack) {
// Maximum number of packets we can expect to obtain from all the slab
// allocators.
const size_t kMaxSlabPackets = kMaxNumSlabs * kNumSmallControlPackets +
kMaxNumSlabs * kNumLargeControlPackets;
std::list<std::unique_ptr<hci::CommandPacket>> packets;
for (size_t num_packets = 0; num_packets < kMaxSlabPackets; num_packets++) {
auto packet = CommandPacket::New(kTestOpCode, 5);
packets.push_front(std::move(packet));
}
// Command allocator can fall back on system allocator after slabs are
// exhausted.
auto packet = CommandPacket::New(kTestOpCode, 5);
ASSERT_TRUE(packet);
}
TEST(SlabAllocatorsTest, ACLDataPacket) {
auto packet = ACLDataPacket::New(5);
EXPECT_TRUE(packet);
EXPECT_EQ(packet->view().size(), 5u + sizeof(hci_spec::ACLDataHeader));
packet = ACLDataPacket::New(kSmallACLDataPayloadSize);
EXPECT_TRUE(packet);
EXPECT_EQ(kSmallACLDataPacketSize, packet->view().size());
packet = ACLDataPacket::New(kSmallACLDataPayloadSize + 1);
EXPECT_TRUE(packet);
EXPECT_EQ(kSmallACLDataPacketSize + 1, packet->view().size());
packet = ACLDataPacket::New(kMediumACLDataPayloadSize + 1);
EXPECT_EQ(kMediumACLDataPacketSize + 1, packet->view().size());
}
TEST(SlabAllocatorsTest, ACLDataPacketFallBack) {
// Maximum number of packets we can expect to obtain from all the slab
// allocators.
const size_t kMaxSlabPackets = kMaxNumSlabs * kNumSmallACLDataPackets +
kMaxNumSlabs * kNumMediumACLDataPackets +
kMaxNumSlabs * kNumLargeACLDataPackets;
const size_t kPayloadSize = 5;
std::list<hci::ACLDataPacketPtr> packets;
for (size_t num_packets = 0; num_packets < kMaxSlabPackets; num_packets++) {
auto packet = ACLDataPacket::New(kPayloadSize);
EXPECT_TRUE(packet);
packets.push_front(std::move(packet));
}
// ACL allocator can fall back on system allocator after slabs are exhausted.
auto packet = ACLDataPacket::New(kPayloadSize);
ASSERT_TRUE(packet);
// Fallback-allocated packet should still function as expected.
EXPECT_EQ(sizeof(hci_spec::ACLDataHeader) + kPayloadSize,
packet->view().size());
// Write over the whole allocation (errors to be caught by sanitizer
// instrumentation).
packet->mutable_view()->mutable_data().Fill('m');
}
TEST(SlabAllocatorsTest, LargeACLDataPacketFallback) {
// Maximum number of packets we can expect to obtain from the large slab
// allocator.
const size_t kMaxSlabPackets = kMaxNumSlabs * kNumLargeACLDataPackets;
const size_t kPayloadSize = kLargeACLDataPayloadSize;
std::list<hci::ACLDataPacketPtr> packets;
for (size_t num_packets = 0; num_packets < kMaxSlabPackets; num_packets++) {
auto packet = ACLDataPacket::New(kPayloadSize);
EXPECT_TRUE(packet);
packets.push_front(std::move(packet));
}
// ACL allocator can fall back on system allocator after slabs are exhausted.
auto packet = ACLDataPacket::New(kPayloadSize);
ASSERT_TRUE(packet);
// Fallback-allocated packet should still function as expected.
EXPECT_EQ(sizeof(hci_spec::ACLDataHeader) + kPayloadSize,
packet->view().size());
// Write over the whole allocation (errors to be caught by sanitizer
// instrumentation).
packet->mutable_view()->mutable_data().Fill('m');
}
} // namespace
} // namespace bt::hci::allocators