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