xref: /aosp_15_r20/external/pigweed/pw_bluetooth_sapphire/host/testing/fake_l2cap_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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/testing/fake_l2cap.h"
16 
17 #include "pw_bluetooth_sapphire/internal/host/testing/test_helpers.h"
18 #include "pw_unit_test/framework.h"
19 
20 namespace bt::testing {
21 
22 hci_spec::ConnectionHandle kConnectionHandle = 0x01;
23 
24 class FakeL2capTest : public ::testing::Test {
25  public:
26   FakeL2capTest() = default;
27   ~FakeL2capTest() override = default;
28 
SetUp()29   void SetUp() override {
30     auto send_cb = [this](auto kConnectionHandle, auto cid, auto& buffer) {
31       if (this->send_frame_callback_) {
32         send_frame_callback_(kConnectionHandle, cid, buffer);
33       }
34     };
35     fake_l2cap_ = std::make_unique<FakeL2cap>(send_cb);
36   }
37 
38  protected:
set_send_frame_callback(FakeL2cap::SendFrameCallback cb)39   void set_send_frame_callback(FakeL2cap::SendFrameCallback cb) {
40     send_frame_callback_ = std::move(cb);
41   }
fake_l2cap()42   FakeL2cap& fake_l2cap() { return *fake_l2cap_; }
43 
44  private:
45   FakeL2cap::SendFrameCallback send_frame_callback_;
46   std::unique_ptr<FakeL2cap> fake_l2cap_;
47   BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(FakeL2capTest);
48 };
49 
TEST_F(FakeL2capTest,RegisterHandler)50 TEST_F(FakeL2capTest, RegisterHandler) {
51   size_t n_pdus = 0;
52   auto cb = [&](auto /*kConnectionHandle*/, auto& buffer) {
53     ++n_pdus;
54     EXPECT_TRUE(ContainersEqual(StaticByteBuffer(0x23), buffer));
55   };
56 
57   fake_l2cap().RegisterHandler(l2cap::kSignalingChannelId, cb);
58   StaticByteBuffer sample_packet(
59       // L2CAP B-Frame header for signaling channel packet.
60       // Length 0x0001
61       0x01,
62       0x00,
63       // Channel Id: 0x0001
64       LowerBits(l2cap::kSignalingChannelId),
65       UpperBits(l2cap::kSignalingChannelId),
66       // Payload: "#"
67       0x23);
68   fake_l2cap().HandlePdu(kConnectionHandle, sample_packet);
69   EXPECT_EQ(1u, n_pdus);
70 }
71 
TEST_F(FakeL2capTest,CallHandlerMultipleTimes)72 TEST_F(FakeL2capTest, CallHandlerMultipleTimes) {
73   size_t n_pdus = 0;
74   auto cb = [&](auto /*kConnectionHandle*/, auto& buffer) {
75     ++n_pdus;
76     EXPECT_TRUE(ContainersEqual(StaticByteBuffer(0x23), buffer));
77   };
78 
79   fake_l2cap().RegisterHandler(l2cap::kSignalingChannelId, cb);
80   StaticByteBuffer sample_packet(
81       // L2CAP B-Frame header for signaling channel packet.
82       // Length 0x0001
83       0x01,
84       0x00,
85       // Channel Id: 0x0001
86       LowerBits(l2cap::kSignalingChannelId),
87       UpperBits(l2cap::kSignalingChannelId),
88       // Payload: "#"
89       0x23);
90   fake_l2cap().HandlePdu(kConnectionHandle, sample_packet);
91   EXPECT_EQ(1u, n_pdus);
92   fake_l2cap().HandlePdu(kConnectionHandle, sample_packet);
93   EXPECT_EQ(2u, n_pdus);
94 }
95 
TEST_F(FakeL2capTest,CustomUnexpectedPacketHandler)96 TEST_F(FakeL2capTest, CustomUnexpectedPacketHandler) {
97   size_t n_pdus = 0;
98   auto unexpected_cb = [&](auto /*kConnectionHandle*/, auto& buffer) {
99     ++n_pdus;
100     EXPECT_TRUE(ContainersEqual(StaticByteBuffer(0x01, 0x00, 0x01, 0x00, 0x23),
101                                 buffer));
102   };
103   auto send_cb =
104       [](auto /*kConnectionHandle*/, auto /*cid*/, auto& /*buffer*/) {};
105   auto fake_l2cap_custom_handler =
106       FakeL2cap(send_cb, unexpected_cb, l2cap::kLastACLDynamicChannelId);
107 
108   StaticByteBuffer sample_packet(
109       // L2CAP B-Frame header for signaling channel packet.
110       // Length 0x0001
111       0x01,
112       0x00,
113       // Channel Id: 0x0001
114       LowerBits(l2cap::kSignalingChannelId),
115       UpperBits(l2cap::kSignalingChannelId),
116       // Payload: "#"
117       0x23);
118   fake_l2cap_custom_handler.HandlePdu(kConnectionHandle, sample_packet);
119   EXPECT_EQ(1u, n_pdus);
120 }
121 
TEST_F(FakeL2capTest,DefaultUnexpectedPacketHandler)122 TEST_F(FakeL2capTest, DefaultUnexpectedPacketHandler) {
123   size_t n_pdus = 0;
124   auto cb = [&](auto /*kConnectionHandle*/, auto& /*buffer*/) { ++n_pdus; };
125   fake_l2cap().RegisterHandler(l2cap::kConnectionlessChannelId, cb);
126   StaticByteBuffer sample_packet = StaticByteBuffer(
127       // L2CAP B-Frame header for signaling channel packet.
128       // Length 0x0001
129       0x01,
130       0x00,
131       // Channel Id: 0x0001
132       LowerBits(l2cap::kSignalingChannelId),
133       UpperBits(l2cap::kSignalingChannelId),
134       // Payload: "#"
135       0x23);
136   fake_l2cap().HandlePdu(kConnectionHandle, sample_packet);
137 
138   // As the ChannelIds of the registered handler and the received packet are
139   // different, cb should not be called and n_pdus should still be 0 as the
140   // default packet handler ignores unroutable packets.
141   EXPECT_EQ(0u, n_pdus);
142 }
143 
TEST_F(FakeL2capTest,DefaultSendPacketOnCustomChannel)144 TEST_F(FakeL2capTest, DefaultSendPacketOnCustomChannel) {
145   std::unique_ptr<ByteBuffer> received_packet;
146   auto send_cb = [&received_packet](
147                      auto /*kConnectionHandle*/, auto /*cid*/, auto& buffer) {
148     received_packet = std::make_unique<DynamicByteBuffer>(buffer);
149   };
150   set_send_frame_callback(send_cb);
151 
152   // Configure the FakeService to use FakeL2cap's SendFrameCallback.
153   auto channel_cb = [](FakeDynamicChannel::WeakPtr channel) {
154     auto handle_sdu = [channel](auto& request) {
155       if (channel.is_alive()) {
156         auto& callback = channel->send_packet_callback();
157         return callback(std::move(request));
158       }
159     };
160     channel->set_packet_handler_callback(handle_sdu);
161   };
162   fake_l2cap().RegisterService(l2cap::kSDP, channel_cb);
163   l2cap::ChannelId src_id = l2cap::kFirstDynamicChannelId;
164 
165   // Open up the SDP channel.
166   fake_l2cap().RegisterDynamicChannel(
167       kConnectionHandle, l2cap::kSDP, src_id, src_id);
168   auto channel =
169       fake_l2cap().FindDynamicChannelByLocalId(kConnectionHandle, src_id);
170   channel->set_opened();
171   fake_l2cap().RegisterDynamicChannelWithPsm(kConnectionHandle, src_id);
172 
173   // Expect that the custom channel only sends back the payload
174   StaticByteBuffer sample_packet(
175       // L2CAP B-Frame header for signaling channel packet.
176       // Length 0x0001
177       0x01,
178       0x00,
179       // Channel Id: 0x0040
180       LowerBits(src_id),
181       UpperBits(src_id),
182       // Payload: "#"
183       0x23);
184   fake_l2cap().HandlePdu(kConnectionHandle, sample_packet);
185   auto response_payload = DynamicByteBuffer(StaticByteBuffer(0x23));
186   EXPECT_TRUE(ContainersEqual(response_payload, *received_packet));
187 }
188 
189 }  // namespace bt::testing
190