• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #include "pw_bluetooth_sapphire/internal/host/transport/slab_allocators.h"
16 
17 #include <forward_list>
18 #include <list>
19 
20 #include "pw_bluetooth_sapphire/internal/host/transport/acl_data_packet.h"
21 #include "pw_bluetooth_sapphire/internal/host/transport/control_packets.h"
22 #include "pw_unit_test/framework.h"
23 
24 namespace bt::hci::allocators {
25 namespace {
26 
27 constexpr hci_spec::OpCode kTestOpCode = 0xFFFF;
28 
TEST(SlabAllocatorsTest,CommandPacket)29 TEST(SlabAllocatorsTest, CommandPacket) {
30   auto packet = CommandPacket::New(kTestOpCode, 5);
31   EXPECT_TRUE(packet);
32   EXPECT_EQ(5u + sizeof(hci_spec::CommandHeader), packet->view().size());
33 
34   packet = CommandPacket::New(kTestOpCode, kSmallControlPayloadSize);
35   EXPECT_TRUE(packet);
36   EXPECT_GE(packet->view().size(), kSmallControlPacketSize);
37 
38   packet = CommandPacket::New(kTestOpCode, kSmallControlPayloadSize + 1);
39   EXPECT_TRUE(packet);
40   EXPECT_EQ(kSmallControlPacketSize + 1, packet->view().size());
41 }
42 
TEST(SlabAllocatorsTest,CommandPacketFallBack)43 TEST(SlabAllocatorsTest, CommandPacketFallBack) {
44   // Maximum number of packets we can expect to obtain from all the slab
45   // allocators.
46   const size_t kMaxSlabPackets = kMaxNumSlabs * kNumSmallControlPackets +
47                                  kMaxNumSlabs * kNumLargeControlPackets;
48 
49   std::list<std::unique_ptr<hci::CommandPacket>> packets;
50   for (size_t num_packets = 0; num_packets < kMaxSlabPackets; num_packets++) {
51     auto packet = CommandPacket::New(kTestOpCode, 5);
52     packets.push_front(std::move(packet));
53   }
54 
55   // Command allocator can fall back on system allocator after slabs are
56   // exhausted.
57   auto packet = CommandPacket::New(kTestOpCode, 5);
58   ASSERT_TRUE(packet);
59 }
60 
TEST(SlabAllocatorsTest,ACLDataPacket)61 TEST(SlabAllocatorsTest, ACLDataPacket) {
62   auto packet = ACLDataPacket::New(5);
63   EXPECT_TRUE(packet);
64   EXPECT_EQ(packet->view().size(), 5u + sizeof(hci_spec::ACLDataHeader));
65 
66   packet = ACLDataPacket::New(kSmallACLDataPayloadSize);
67   EXPECT_TRUE(packet);
68   EXPECT_EQ(kSmallACLDataPacketSize, packet->view().size());
69 
70   packet = ACLDataPacket::New(kSmallACLDataPayloadSize + 1);
71   EXPECT_TRUE(packet);
72   EXPECT_EQ(kSmallACLDataPacketSize + 1, packet->view().size());
73 
74   packet = ACLDataPacket::New(kMediumACLDataPayloadSize + 1);
75   EXPECT_EQ(kMediumACLDataPacketSize + 1, packet->view().size());
76 }
77 
TEST(SlabAllocatorsTest,ACLDataPacketFallBack)78 TEST(SlabAllocatorsTest, ACLDataPacketFallBack) {
79   // Maximum number of packets we can expect to obtain from all the slab
80   // allocators.
81   const size_t kMaxSlabPackets = kMaxNumSlabs * kNumSmallACLDataPackets +
82                                  kMaxNumSlabs * kNumMediumACLDataPackets +
83                                  kMaxNumSlabs * kNumLargeACLDataPackets;
84   const size_t kPayloadSize = 5;
85   std::list<hci::ACLDataPacketPtr> packets;
86 
87   for (size_t num_packets = 0; num_packets < kMaxSlabPackets; num_packets++) {
88     auto packet = ACLDataPacket::New(kPayloadSize);
89     EXPECT_TRUE(packet);
90     packets.push_front(std::move(packet));
91   }
92 
93   // ACL allocator can fall back on system allocator after slabs are exhausted.
94   auto packet = ACLDataPacket::New(kPayloadSize);
95   ASSERT_TRUE(packet);
96 
97   // Fallback-allocated packet should still function as expected.
98   EXPECT_EQ(sizeof(hci_spec::ACLDataHeader) + kPayloadSize,
99             packet->view().size());
100 
101   // Write over the whole allocation (errors to be caught by sanitizer
102   // instrumentation).
103   packet->mutable_view()->mutable_data().Fill('m');
104 }
105 
TEST(SlabAllocatorsTest,LargeACLDataPacketFallback)106 TEST(SlabAllocatorsTest, LargeACLDataPacketFallback) {
107   // Maximum number of packets we can expect to obtain from the large slab
108   // allocator.
109   const size_t kMaxSlabPackets = kMaxNumSlabs * kNumLargeACLDataPackets;
110   const size_t kPayloadSize = kLargeACLDataPayloadSize;
111   std::list<hci::ACLDataPacketPtr> packets;
112 
113   for (size_t num_packets = 0; num_packets < kMaxSlabPackets; num_packets++) {
114     auto packet = ACLDataPacket::New(kPayloadSize);
115     EXPECT_TRUE(packet);
116     packets.push_front(std::move(packet));
117   }
118 
119   // ACL allocator can fall back on system allocator after slabs are exhausted.
120   auto packet = ACLDataPacket::New(kPayloadSize);
121   ASSERT_TRUE(packet);
122 
123   // Fallback-allocated packet should still function as expected.
124   EXPECT_EQ(sizeof(hci_spec::ACLDataHeader) + kPayloadSize,
125             packet->view().size());
126 
127   // Write over the whole allocation (errors to be caught by sanitizer
128   // instrumentation).
129   packet->mutable_view()->mutable_data().Fill('m');
130 }
131 
132 }  // namespace
133 }  // namespace bt::hci::allocators
134