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/l2cap/bredr_signaling_channel.h"
16
17 #include "pw_bluetooth_sapphire/internal/host/l2cap/mock_channel_test.h"
18 #include "pw_bluetooth_sapphire/internal/host/testing/test_helpers.h"
19
20 namespace bt::l2cap::internal {
21 namespace {
22
23 constexpr hci_spec::ConnectionHandle kTestHandle = 0x0001;
24 constexpr uint8_t kTestCmdId = 97;
25 constexpr pw::bluetooth::emboss::ConnectionRole kDeviceRole =
26 pw::bluetooth::emboss::ConnectionRole::CENTRAL;
27
28 class BrEdrSignalingChannelTest : public testing::MockChannelTest {
29 public:
30 BrEdrSignalingChannelTest() = default;
31 ~BrEdrSignalingChannelTest() override = default;
32
33 BrEdrSignalingChannelTest(const BrEdrSignalingChannelTest&) = delete;
34 BrEdrSignalingChannelTest& operator=(const BrEdrSignalingChannelTest&) =
35 delete;
36
37 protected:
SetUp()38 void SetUp() override {
39 ChannelOptions options(kSignalingChannelId);
40 options.conn_handle = kTestHandle;
41
42 fake_chan_ = CreateFakeChannel(options);
43 sig_ = std::make_unique<BrEdrSignalingChannel>(
44 fake_chan_->GetWeakPtr(), kDeviceRole, dispatcher());
45 }
46
TearDown()47 void TearDown() override {
48 RunUntilIdle();
49 sig_ = nullptr;
50 }
51
sig() const52 BrEdrSignalingChannel* sig() const { return sig_.get(); }
53
54 private:
55 testing::FakeChannel::WeakPtr fake_chan_;
56 std::unique_ptr<BrEdrSignalingChannel> sig_;
57 };
58
TEST_F(BrEdrSignalingChannelTest,RespondsToEchoRequest)59 TEST_F(BrEdrSignalingChannelTest, RespondsToEchoRequest) {
60 const StaticByteBuffer cmd(
61 // Command header (Echo Request, length 1)
62 0x08,
63 kTestCmdId,
64 0x01,
65 0x00,
66
67 // Payload
68 0x23);
69
70 const StaticByteBuffer response(
71 // Command header (Echo Response, length 1)
72 0x09,
73 kTestCmdId,
74 0x01,
75 0x00,
76 // Payload
77 0x23);
78
79 EXPECT_PACKET_OUT(response);
80 fake_chan()->Receive(cmd);
81 }
82
TEST_F(BrEdrSignalingChannelTest,IgnoreEmptyFrame)83 TEST_F(BrEdrSignalingChannelTest, IgnoreEmptyFrame) {
84 fake_chan()->Receive(BufferView());
85 }
86
TEST_F(BrEdrSignalingChannelTest,RejectMalformedAdditionalCommand)87 TEST_F(BrEdrSignalingChannelTest, RejectMalformedAdditionalCommand) {
88 constexpr uint8_t kTestId0 = 14;
89 constexpr uint8_t kTestId1 = 15;
90
91 // Echo Request (see other test for command support), followed by an
92 // incomplete command packet
93 StaticByteBuffer cmd(
94 // Command header (length 3)
95 0x08,
96 kTestId0,
97 0x03,
98 0x00,
99
100 // Payload data
101 'L',
102 'O',
103 'L',
104
105 // Second command header
106 0x08,
107 kTestId1,
108 0x01,
109 0x00);
110
111 // Echo Response packet
112 StaticByteBuffer rsp0(
113 // Command header (length 3)
114 0x09,
115 kTestId0,
116 0x03,
117 0x00,
118
119 // Payload data
120 'L',
121 'O',
122 'L');
123
124 // Command Reject packet
125 StaticByteBuffer rsp1(
126 // Command header
127 0x01,
128 kTestId1,
129 0x02,
130 0x00,
131
132 // Reason (Command not understood)
133 0x00,
134 0x00);
135
136 EXPECT_PACKET_OUT(rsp0);
137 EXPECT_PACKET_OUT(rsp1);
138 fake_chan()->Receive(cmd);
139 }
140
TEST_F(BrEdrSignalingChannelTest,HandleMultipleCommands)141 TEST_F(BrEdrSignalingChannelTest, HandleMultipleCommands) {
142 constexpr uint8_t kTestId0 = 14;
143 constexpr uint8_t kTestId1 = 15;
144 constexpr uint8_t kTestId2 = 16;
145
146 StaticByteBuffer cmd(
147 // Command header (Echo Request)
148 0x08,
149 kTestId0,
150 0x04,
151 0x00,
152
153 // Payload data
154 'L',
155 'O',
156 'L',
157 'Z',
158
159 // Header with command to be rejected
160 0xFF,
161 kTestId1,
162 0x03,
163 0x00,
164
165 // Payload data
166 'L',
167 'O',
168 'L',
169
170 // Command header (Echo Request, no payload data)
171 0x08,
172 kTestId2,
173 0x00,
174 0x00,
175
176 // Additional command fragment to be dropped
177 0xFF,
178 0x00);
179
180 StaticByteBuffer echo_rsp0(
181 // Command header (Echo Response)
182 0x09,
183 kTestId0,
184 0x04,
185 0x00,
186
187 // Payload data
188 'L',
189 'O',
190 'L',
191 'Z');
192
193 StaticByteBuffer reject_rsp1(
194 // Command header (Command Rejected)
195 0x01,
196 kTestId1,
197 0x02,
198 0x00,
199
200 // Reason (Command not understood)
201 0x00,
202 0x00);
203
204 StaticByteBuffer echo_rsp2(
205 // Command header (Echo Response)
206 0x09,
207 kTestId2,
208 0x00,
209 0x00);
210
211 EXPECT_PACKET_OUT(echo_rsp0);
212 EXPECT_PACKET_OUT(reject_rsp1);
213 EXPECT_PACKET_OUT(echo_rsp2);
214 fake_chan()->Receive(cmd);
215 }
216
TEST_F(BrEdrSignalingChannelTest,SendAndReceiveEcho)217 TEST_F(BrEdrSignalingChannelTest, SendAndReceiveEcho) {
218 const StaticByteBuffer expected_req(
219 // Echo request with 3-byte payload.
220 0x08,
221 0x01,
222 0x03,
223 0x00,
224
225 // Payload
226 'P',
227 'W',
228 'N');
229 const BufferView req_data = expected_req.view(4, 3);
230
231 const StaticByteBuffer expected_rsp(
232 // Echo response with 4-byte payload.
233 0x09,
234 0x01,
235 0x04,
236 0x00,
237
238 // Payload
239 'L',
240 '3',
241 '3',
242 'T');
243 const BufferView rsp_data = expected_rsp.view(4, 4);
244
245 EXPECT_PACKET_OUT(expected_req);
246 bool rx_success = false;
247 EXPECT_TRUE(
248 sig()->TestLink(req_data, [&rx_success, &rsp_data](const auto& data) {
249 rx_success = ContainersEqual(rsp_data, data);
250 }));
251
252 RunUntilIdle();
253 EXPECT_TRUE(AllExpectedPacketsSent());
254
255 // Remote sends back an echo response with a different payload than in local
256 // request (this is allowed).
257 fake_chan()->Receive(expected_rsp);
258 EXPECT_TRUE(rx_success);
259 }
260
261 } // namespace
262 } // namespace bt::l2cap::internal
263