• 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/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 = [](auto kConnectionHandle, auto cid, auto& buffer) {};
104   auto fake_l2cap_custom_handler =
105       FakeL2cap(send_cb, unexpected_cb, l2cap::kLastACLDynamicChannelId);
106 
107   StaticByteBuffer sample_packet(
108       // L2CAP B-Frame header for signaling channel packet.
109       // Length 0x0001
110       0x01,
111       0x00,
112       // Channel Id: 0x0001
113       LowerBits(l2cap::kSignalingChannelId),
114       UpperBits(l2cap::kSignalingChannelId),
115       // Payload: "#"
116       0x23);
117   fake_l2cap_custom_handler.HandlePdu(kConnectionHandle, sample_packet);
118   EXPECT_EQ(1u, n_pdus);
119 }
120 
TEST_F(FakeL2capTest,DefaultUnexpectedPacketHandler)121 TEST_F(FakeL2capTest, DefaultUnexpectedPacketHandler) {
122   size_t n_pdus = 0;
123   auto cb = [&](auto kConnectionHandle, auto& buffer) { ++n_pdus; };
124   fake_l2cap().RegisterHandler(l2cap::kConnectionlessChannelId, cb);
125   StaticByteBuffer sample_packet = StaticByteBuffer(
126       // L2CAP B-Frame header for signaling channel packet.
127       // Length 0x0001
128       0x01,
129       0x00,
130       // Channel Id: 0x0001
131       LowerBits(l2cap::kSignalingChannelId),
132       UpperBits(l2cap::kSignalingChannelId),
133       // Payload: "#"
134       0x23);
135   fake_l2cap().HandlePdu(kConnectionHandle, sample_packet);
136 
137   // As the ChannelIds of the registered handler and the received packet are
138   // different, cb should not be called and n_pdus should still be 0 as the
139   // default packet handler ignores unroutable packets.
140   EXPECT_EQ(0u, n_pdus);
141 }
142 
TEST_F(FakeL2capTest,DefaultSendPacketOnCustomChannel)143 TEST_F(FakeL2capTest, DefaultSendPacketOnCustomChannel) {
144   std::unique_ptr<ByteBuffer> received_packet;
145   auto send_cb = [&received_packet](
146                      auto kConnectionHandle, auto cid, auto& buffer) {
147     received_packet = std::make_unique<DynamicByteBuffer>(buffer);
148   };
149   set_send_frame_callback(send_cb);
150 
151   // Configure the FakeService to use FakeL2cap's SendFrameCallback.
152   auto channel_cb = [](FakeDynamicChannel::WeakPtr channel) {
153     auto handle_sdu = [channel](auto& request) {
154       if (channel.is_alive()) {
155         auto& callback = channel->send_packet_callback();
156         return callback(std::move(request));
157       }
158     };
159     channel->set_packet_handler_callback(handle_sdu);
160   };
161   fake_l2cap().RegisterService(l2cap::kSDP, channel_cb);
162   l2cap::ChannelId src_id = l2cap::kFirstDynamicChannelId;
163 
164   // Open up the SDP channel.
165   fake_l2cap().RegisterDynamicChannel(
166       kConnectionHandle, l2cap::kSDP, src_id, src_id);
167   auto channel =
168       fake_l2cap().FindDynamicChannelByLocalId(kConnectionHandle, src_id);
169   channel->set_opened();
170   fake_l2cap().RegisterDynamicChannelWithPsm(kConnectionHandle, src_id);
171 
172   // Expect that the custom channel only sends back the payload
173   StaticByteBuffer sample_packet(
174       // L2CAP B-Frame header for signaling channel packet.
175       // Length 0x0001
176       0x01,
177       0x00,
178       // Channel Id: 0x0040
179       LowerBits(src_id),
180       UpperBits(src_id),
181       // Payload: "#"
182       0x23);
183   fake_l2cap().HandlePdu(kConnectionHandle, sample_packet);
184   auto response_payload = DynamicByteBuffer(StaticByteBuffer(0x23));
185   EXPECT_TRUE(ContainersEqual(response_payload, *received_packet));
186 }
187 
188 }  // namespace bt::testing
189