xref: /aosp_15_r20/external/pigweed/pw_bluetooth_sapphire/host/l2cap/bredr_signaling_channel_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/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