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