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_dynamic_channel.h"
16
17 #include "pw_bluetooth_sapphire/internal/host/common/byte_buffer.h"
18 #include "pw_bluetooth_sapphire/internal/host/hci-spec/protocol.h"
19 #include "pw_bluetooth_sapphire/internal/host/l2cap/l2cap_defs.h"
20 #include "pw_bluetooth_sapphire/internal/host/l2cap/test_packets.h"
21 #include "pw_bluetooth_sapphire/internal/host/testing/fake_l2cap.h"
22 #include "pw_bluetooth_sapphire/internal/host/testing/fake_signaling_server.h"
23 #include "pw_bluetooth_sapphire/internal/host/testing/test_helpers.h"
24
25 namespace bt::testing {
26 namespace {
27
28 hci_spec::ConnectionHandle kConnectionHandle = 0x01;
29 l2cap::CommandId kCommandId = 0x02;
30 l2cap::Psm kPsm = l2cap::kSDP;
31
TEST(FakeDynamicChannelTest,ConnectOpenDisconnectChannel)32 TEST(FakeDynamicChannelTest, ConnectOpenDisconnectChannel) {
33 std::unique_ptr<ByteBuffer> received_packet;
34 auto send_cb = [&received_packet](
35 auto kConnectionHandle, auto cid, auto& buffer) {
36 received_packet = std::make_unique<DynamicByteBuffer>(buffer);
37 };
38 auto fake_l2cap = FakeL2cap(send_cb);
39 auto server = std::make_unique<FakeSignalingServer>();
40 server->RegisterWithL2cap(&fake_l2cap);
41 auto channel_cb = [](auto fake_dynamic_channel) {};
42 fake_l2cap.RegisterService(kPsm, channel_cb);
43 l2cap::ChannelId src_id = l2cap::kFirstDynamicChannelId;
44 l2cap::ChannelParameters params;
45
46 // Assemble and send the ConnectionRequest to connect, but not open, the
47 // channel.
48 auto connection_acl_packet = l2cap::testing::AclConnectionReq(
49 kCommandId, kConnectionHandle, src_id, kPsm);
50 const auto& connection_header =
51 connection_acl_packet.To<hci_spec::ACLDataHeader>();
52 auto connection_header_len = sizeof(connection_header);
53 auto connection_payload_len = le16toh(connection_header.data_total_length);
54 auto connection_packet = DynamicByteBuffer(connection_payload_len);
55 connection_acl_packet.Copy(
56 &connection_packet, connection_header_len, connection_payload_len);
57 fake_l2cap.HandlePdu(kConnectionHandle, connection_packet);
58
59 // Anticipate that we then receive a ConfigurationRequest. HandlePdu will
60 // first send a ConnectionResponse, but the most recent packet should be a
61 // ConfigurationRequest. The channel should also be connected, but not open,
62 // at this time.
63 // Manually create the expected ConfigurationRequest with no payload.
64 StaticByteBuffer expected_request(
65 // Configuration request command code, CommandId associated with the test
66 l2cap::kConfigurationRequest,
67 kCommandId,
68 // Payload length (4 total bytes)
69 0x04,
70 0x00,
71 // Source ID (2 bytes)
72 LowerBits(src_id),
73 UpperBits(src_id),
74 // No continuation flags (2 bytes)
75 0x00,
76 0x00);
77 EXPECT_TRUE(ContainersEqual(expected_request, *received_packet));
78 EXPECT_FALSE(
79 fake_l2cap.FindDynamicChannelByLocalId(kConnectionHandle, src_id)
80 ->configuration_request_received());
81 EXPECT_FALSE(
82 fake_l2cap.FindDynamicChannelByLocalId(kConnectionHandle, src_id)
83 ->configuration_response_received());
84 EXPECT_FALSE(
85 fake_l2cap.FindDynamicChannelByRemoteId(kConnectionHandle, src_id)
86 ->opened());
87
88 // Send a ConfigurationResponse to the received ConfigurationRequest.
89 auto configuration_response_acl_packet = l2cap::testing::AclConfigRsp(
90 kCommandId, kConnectionHandle, src_id, params);
91 const auto& configuration_response_header =
92 configuration_response_acl_packet.To<hci_spec::ACLDataHeader>();
93 auto configuration_response_header_len =
94 sizeof(configuration_response_header);
95 auto configuration_response_payload_len =
96 le16toh(configuration_response_header.data_total_length);
97 auto configuration_response_packet =
98 DynamicByteBuffer(configuration_response_payload_len);
99 configuration_response_acl_packet.Copy(&configuration_response_packet,
100 configuration_response_header_len,
101 configuration_response_payload_len);
102 fake_l2cap.HandlePdu(kConnectionHandle, configuration_response_packet);
103 EXPECT_FALSE(
104 fake_l2cap.FindDynamicChannelByLocalId(kConnectionHandle, src_id)
105 ->configuration_request_received());
106 EXPECT_TRUE(fake_l2cap.FindDynamicChannelByLocalId(kConnectionHandle, src_id)
107 ->configuration_response_received());
108 EXPECT_FALSE(
109 fake_l2cap.FindDynamicChannelByRemoteId(kConnectionHandle, src_id)
110 ->opened());
111
112 // Assemble and send the ConfigurationRequest to open up the channel.
113 // In this isolated test, we can assume that the src_id and dest_id are
114 // identical.
115 auto configuration_request_acl_packet = l2cap::testing::AclConfigReq(
116 kCommandId, kConnectionHandle, src_id, params);
117 const auto& configuration_request_header =
118 configuration_request_acl_packet.To<hci_spec::ACLDataHeader>();
119 auto configuration_request_header_len = sizeof(configuration_request_header);
120 auto configuration_request_payload_len =
121 le16toh(configuration_request_header.data_total_length);
122 auto configuration_request_packet =
123 DynamicByteBuffer(configuration_request_payload_len);
124 configuration_request_acl_packet.Copy(&configuration_request_packet,
125 configuration_request_header_len,
126 configuration_request_payload_len);
127 fake_l2cap.HandlePdu(kConnectionHandle, configuration_request_packet);
128
129 // Anticipate that we then receive a ConfigurationResponse after we send a
130 // Manually create the expected ConfigurationRequest with no payload.
131 StaticByteBuffer expected_response(
132 // Configuration request command code, CommandId associated with the test
133 l2cap::kConfigurationResponse,
134 kCommandId,
135 // Payload length (6 total bytes)
136 0x06,
137 0x00,
138 // Source ID (2 bytes)
139 LowerBits(src_id),
140 UpperBits(src_id),
141 // No continuation flags (2 bytes)
142 0x00,
143 0x00,
144 // Result (Success)
145 LowerBits(0x0000),
146 UpperBits(0x0000));
147 EXPECT_TRUE(ContainersEqual(expected_response, *received_packet));
148 EXPECT_TRUE(fake_l2cap.FindDynamicChannelByLocalId(kConnectionHandle, src_id)
149 ->configuration_request_received());
150 EXPECT_TRUE(fake_l2cap.FindDynamicChannelByLocalId(kConnectionHandle, src_id)
151 ->configuration_response_received());
152 EXPECT_TRUE(
153 fake_l2cap.FindDynamicChannelByRemoteId(kConnectionHandle, src_id)
154 ->opened());
155
156 // Assemble and send the DisconnectionRequest to open up the channel.
157 // In this isolated test, we can assume that the src_id and dest_id are
158 // identical.
159 auto disconnection_acl_packet = l2cap::testing::AclDisconnectionReq(
160 kCommandId, kConnectionHandle, src_id, src_id);
161 const auto& disconnection_header =
162 disconnection_acl_packet.To<hci_spec::ACLDataHeader>();
163 auto disconnection_header_len = sizeof(disconnection_header);
164 auto disconnection_payload_len =
165 le16toh(disconnection_header.data_total_length);
166 auto disconnection_packet = DynamicByteBuffer(disconnection_payload_len);
167 disconnection_acl_packet.Copy(&disconnection_packet,
168 disconnection_header_len,
169 disconnection_payload_len);
170 fake_l2cap.HandlePdu(kConnectionHandle, disconnection_packet);
171
172 // Anticipate that we receive a DisconnectionResponse after we send the
173 // request and that the channel has been deleted.
174 StaticByteBuffer disconnection_response(
175 // Configuration request command code, CommandId associated with the test
176 l2cap::kDisconnectionResponse,
177 kCommandId,
178 // Payload length (4 total bytes)
179 0x04,
180 0x00,
181 // Source ID (2 bytes)
182 LowerBits(src_id),
183 UpperBits(src_id),
184 // Dest ID (2 bytes)
185 LowerBits(src_id),
186 UpperBits(src_id));
187 EXPECT_TRUE(ContainersEqual(disconnection_response, *received_packet));
188 EXPECT_FALSE(fake_l2cap.FindDynamicChannelByLocalId(kConnectionHandle, src_id)
189 .is_alive());
190 }
191
TEST(FakeDynamicChannelTest,FailToRegisterChannelWithoutRegisteredService)192 TEST(FakeDynamicChannelTest, FailToRegisterChannelWithoutRegisteredService) {
193 // Create a custom FakeL2cap with no registered services.
194 std::unique_ptr<ByteBuffer> received_packet;
195 auto send_cb = [&received_packet](
196 auto kConnectionHandle, auto cid, auto& buffer) {
197 received_packet = std::make_unique<DynamicByteBuffer>(buffer);
198 };
199 auto fake_l2cap_without_service = FakeL2cap(send_cb);
200 auto server = std::make_unique<FakeSignalingServer>();
201 server->RegisterWithL2cap(&fake_l2cap_without_service);
202 l2cap::ChannelId src_id = l2cap::kFirstDynamicChannelId;
203
204 // Assemble and send the ConnectionRequest to connect, but not open, the
205 // channel.
206 auto connection_acl_packet = l2cap::testing::AclConnectionReq(
207 kCommandId, kConnectionHandle, src_id, kPsm);
208 const auto& connection_header =
209 connection_acl_packet.To<hci_spec::ACLDataHeader>();
210 auto connection_header_len = sizeof(connection_header);
211 auto connection_payload_len = le16toh(connection_header.data_total_length);
212 auto connection_packet = DynamicByteBuffer(connection_payload_len);
213 connection_acl_packet.Copy(
214 &connection_packet, connection_header_len, connection_payload_len);
215 fake_l2cap_without_service.HandlePdu(kConnectionHandle, connection_packet);
216
217 // Anticipate that we will receive a rejection as the packet is not supported.
218 // As this is an isolated test case, assume that src_id and dst_id are the
219 // same.
220 auto expected_acl_response = l2cap::testing::AclConnectionRsp(
221 kCommandId,
222 kConnectionHandle,
223 src_id,
224 l2cap::kInvalidChannelId,
225 l2cap::ConnectionResult::kPsmNotSupported);
226 auto expected_response = expected_acl_response.view(
227 sizeof(hci_spec::ACLDataHeader) + sizeof(l2cap::CommandHeader));
228 EXPECT_TRUE(ContainersEqual(expected_response, *received_packet));
229 EXPECT_FALSE(fake_l2cap_without_service
230 .FindDynamicChannelByLocalId(kConnectionHandle, src_id)
231 .is_alive());
232 }
233
TEST(FakeDynamicChannelTest,FailToRegisterChannelWithInvalidCid)234 TEST(FakeDynamicChannelTest, FailToRegisterChannelWithInvalidCid) {
235 // Configure FakeSignalingServer to copy any received signaling packets.
236 std::unique_ptr<ByteBuffer> received_packet;
237 auto send_cb = [&received_packet](
238 auto kConnectionHandle, auto cid, auto& buffer) {
239 received_packet = std::make_unique<DynamicByteBuffer>(buffer);
240 };
241 auto fake_l2cap = FakeL2cap(send_cb);
242 auto server = std::make_unique<FakeSignalingServer>();
243 server->RegisterWithL2cap(&fake_l2cap);
244 auto channel_cb = [](auto fake_dynamic_channel) {};
245 fake_l2cap.RegisterService(kPsm, channel_cb);
246 l2cap::ChannelId src_id = l2cap::kInvalidChannelId;
247
248 // Assemble and send the ConnectionRequest to connect, but not open, the
249 // channel.
250 auto connection_acl_packet = l2cap::testing::AclConnectionReq(
251 kCommandId, kConnectionHandle, src_id, kPsm);
252 const auto& connection_header =
253 connection_acl_packet.To<hci_spec::ACLDataHeader>();
254 auto connection_header_len = sizeof(connection_header);
255 auto connection_payload_len = le16toh(connection_header.data_total_length);
256 auto connection_packet = DynamicByteBuffer(connection_payload_len);
257 connection_acl_packet.Copy(
258 &connection_packet, connection_header_len, connection_payload_len);
259 fake_l2cap.HandlePdu(kConnectionHandle, connection_packet);
260
261 // Anticipate that we will receive a rejection as the ID is not supported.
262 auto expected_acl_response = l2cap::testing::AclConnectionRsp(
263 kCommandId,
264 kConnectionHandle,
265 src_id,
266 l2cap::kInvalidChannelId,
267 l2cap::ConnectionResult::kInvalidSourceCID);
268 auto expected_response = expected_acl_response.view(
269 sizeof(hci_spec::ACLDataHeader) + sizeof(l2cap::CommandHeader));
270 EXPECT_TRUE(ContainersEqual(expected_response, *received_packet));
271 EXPECT_FALSE(fake_l2cap.FindDynamicChannelByLocalId(kConnectionHandle, src_id)
272 .is_alive());
273 }
274
TEST(FakeDynamicChannelTest,FailToRegisterDuplicateRemoteId)275 TEST(FakeDynamicChannelTest, FailToRegisterDuplicateRemoteId) {
276 std::unique_ptr<ByteBuffer> received_packet;
277 auto send_cb = [&received_packet](
278 auto kConnectionHandle, auto cid, auto& buffer) {
279 received_packet = std::make_unique<DynamicByteBuffer>(buffer);
280 };
281 auto fake_l2cap = FakeL2cap(send_cb);
282 auto server = std::make_unique<FakeSignalingServer>();
283 server->RegisterWithL2cap(&fake_l2cap);
284 auto channel_cb = [](auto fake_dynamic_channel) {};
285 fake_l2cap.RegisterService(kPsm, channel_cb);
286 l2cap::ChannelId src_id = l2cap::kFirstDynamicChannelId;
287 l2cap::ChannelParameters params;
288
289 // Assemble and send the ConnectionRequest to connect, but not open, the
290 // channel.
291 auto connection_acl_packet = l2cap::testing::AclConnectionReq(
292 kCommandId, kConnectionHandle, src_id, kPsm);
293 const auto& connection_header =
294 connection_acl_packet.To<hci_spec::ACLDataHeader>();
295 auto connection_header_len = sizeof(connection_header);
296 auto connection_payload_len = le16toh(connection_header.data_total_length);
297 auto connection_packet = DynamicByteBuffer(connection_payload_len);
298 connection_acl_packet.Copy(
299 &connection_packet, connection_header_len, connection_payload_len);
300 fake_l2cap.HandlePdu(kConnectionHandle, connection_packet);
301
302 // Anticipate that we then receive a ConfigurationRequest. HandlePdu will
303 // first send a ConnectionResponse, but the most recent packet should be a
304 // ConfigurationRequest. The channel should also be connected, but not open,
305 // at this time.
306 // Manually create the expected ConfigurationRequest with no payload.
307 StaticByteBuffer expected_request(
308 // Configuration request command code, CommandId associated with the test
309 l2cap::kConfigurationRequest,
310 kCommandId,
311 // Payload length (4 total bytes)
312 0x04,
313 0x00,
314 // Source ID (2 bytes)
315 LowerBits(src_id),
316 UpperBits(src_id),
317 // No continuation flags (2 bytes)
318 0x00,
319 0x00);
320 EXPECT_TRUE(ContainersEqual(expected_request, *received_packet));
321 EXPECT_FALSE(
322 fake_l2cap.FindDynamicChannelByLocalId(kConnectionHandle, src_id)
323 ->configuration_request_received());
324 EXPECT_FALSE(
325 fake_l2cap.FindDynamicChannelByLocalId(kConnectionHandle, src_id)
326 ->configuration_response_received());
327 EXPECT_FALSE(
328 fake_l2cap.FindDynamicChannelByLocalId(kConnectionHandle, src_id)
329 ->opened());
330
331 // Send a ConfigurationResponse to the received ConfigurationRequest.
332 auto configuration_response_acl_packet = l2cap::testing::AclConfigRsp(
333 kCommandId, kConnectionHandle, src_id, params);
334 const auto& configuration_response_header =
335 configuration_response_acl_packet.To<hci_spec::ACLDataHeader>();
336 auto configuration_response_header_len =
337 sizeof(configuration_response_header);
338 auto configuration_response_payload_len =
339 le16toh(configuration_response_header.data_total_length);
340 auto configuration_response_packet =
341 DynamicByteBuffer(configuration_response_payload_len);
342 configuration_response_acl_packet.Copy(&configuration_response_packet,
343 configuration_response_header_len,
344 configuration_response_payload_len);
345 fake_l2cap.HandlePdu(kConnectionHandle, configuration_response_packet);
346 EXPECT_FALSE(
347 fake_l2cap.FindDynamicChannelByLocalId(kConnectionHandle, src_id)
348 ->configuration_request_received());
349 EXPECT_TRUE(fake_l2cap.FindDynamicChannelByLocalId(kConnectionHandle, src_id)
350 ->configuration_response_received());
351 EXPECT_FALSE(
352 fake_l2cap.FindDynamicChannelByLocalId(kConnectionHandle, src_id)
353 ->opened());
354
355 // Assemble and send the ConfigurationRequest to open up the channel.
356 // In this isolated test, we can assume that the src_id and dest_id are
357 // identical.
358 auto configuration_request_acl_packet = l2cap::testing::AclConfigReq(
359 kCommandId, kConnectionHandle, src_id, params);
360 const auto& configuration_request_header =
361 configuration_request_acl_packet.To<hci_spec::ACLDataHeader>();
362 auto configuration_request_header_len = sizeof(configuration_request_header);
363 auto configuration_request_payload_len =
364 le16toh(configuration_request_header.data_total_length);
365 auto configuration_request_packet =
366 DynamicByteBuffer(configuration_request_payload_len);
367 configuration_request_acl_packet.Copy(&configuration_request_packet,
368 configuration_request_header_len,
369 configuration_request_payload_len);
370 fake_l2cap.HandlePdu(kConnectionHandle, configuration_request_packet);
371
372 // Anticipate that we then receive a ConfigurationResponse after we send a
373 // Manually create the expected ConfigurationRequest with no payload.
374 StaticByteBuffer expected_response(
375 // Configuration request command code, CommandId associated with the test
376 l2cap::kConfigurationResponse,
377 kCommandId,
378 // Payload length (6 total bytes)
379 0x06,
380 0x00,
381 // Source ID (2 bytes)
382 LowerBits(src_id),
383 UpperBits(src_id),
384 // No continuation flags (2 bytes)
385 0x00,
386 0x00,
387 // Result (Success)
388 LowerBits(0x0000),
389 UpperBits(0x0000));
390 EXPECT_TRUE(ContainersEqual(expected_response, *received_packet));
391 EXPECT_TRUE(fake_l2cap.FindDynamicChannelByLocalId(kConnectionHandle, src_id)
392 ->configuration_request_received());
393 EXPECT_TRUE(fake_l2cap.FindDynamicChannelByLocalId(kConnectionHandle, src_id)
394 ->configuration_response_received());
395 EXPECT_TRUE(fake_l2cap.FindDynamicChannelByLocalId(kConnectionHandle, src_id)
396 ->opened());
397
398 // Try to open up the same channel again.
399 auto second_connection_acl_packet = l2cap::testing::AclConnectionReq(
400 kCommandId, kConnectionHandle, src_id, kPsm);
401 const auto& second_connection_header =
402 second_connection_acl_packet.To<hci_spec::ACLDataHeader>();
403 auto second_connection_header_len = sizeof(second_connection_header);
404 auto second_connection_payload_len =
405 le16toh(second_connection_header.data_total_length);
406 auto second_connection_packet =
407 DynamicByteBuffer(second_connection_payload_len);
408 second_connection_acl_packet.Copy(&second_connection_packet,
409 second_connection_header_len,
410 second_connection_payload_len);
411 fake_l2cap.HandlePdu(kConnectionHandle, second_connection_packet);
412
413 // Anticipate that we will receive a rejection as the remote ID has already
414 // been registered.
415 auto second_expected_acl_response = l2cap::testing::AclConnectionRsp(
416 kCommandId,
417 kConnectionHandle,
418 src_id,
419 l2cap::kInvalidChannelId,
420 l2cap::ConnectionResult::kSourceCIDAlreadyAllocated);
421 auto second_expected_response = second_expected_acl_response.view(
422 sizeof(hci_spec::ACLDataHeader) + sizeof(l2cap::CommandHeader));
423 EXPECT_TRUE(ContainersEqual(second_expected_response, *received_packet));
424 }
425
TEST(FakeDynamicChannelTest,FailWhenOutOfIds)426 TEST(FakeDynamicChannelTest, FailWhenOutOfIds) {
427 auto unexpected_cb = [](auto handle, auto& pdu) {};
428 std::unique_ptr<ByteBuffer> received_packet;
429 auto send_cb = [&received_packet](
430 auto kConnectionHandle, auto cid, auto& buffer) {
431 received_packet = std::make_unique<DynamicByteBuffer>(buffer);
432 };
433 auto fewer_ids_fake_l2cap_ =
434 FakeL2cap(send_cb, unexpected_cb, l2cap::kFirstDynamicChannelId);
435 auto server = std::make_unique<FakeSignalingServer>();
436 server->RegisterWithL2cap(&fewer_ids_fake_l2cap_);
437 auto channel_cb = [](auto fake_dynamic_channel) {};
438 fewer_ids_fake_l2cap_.RegisterService(kPsm, channel_cb);
439 l2cap::ChannelId src_id = l2cap::kFirstDynamicChannelId;
440
441 // Assemble and send the ConnectionRequest to connect, but not open, the
442 // channel.
443 auto connection_acl_packet = l2cap::testing::AclConnectionReq(
444 kCommandId, kConnectionHandle, src_id, kPsm);
445 const auto& connection_header =
446 connection_acl_packet.To<hci_spec::ACLDataHeader>();
447 auto connection_header_len = sizeof(connection_header);
448 auto connection_payload_len = le16toh(connection_header.data_total_length);
449 auto connection_packet = DynamicByteBuffer(connection_payload_len);
450 connection_acl_packet.Copy(
451 &connection_packet, connection_header_len, connection_payload_len);
452 fewer_ids_fake_l2cap_.HandlePdu(kConnectionHandle, connection_packet);
453 EXPECT_FALSE(fewer_ids_fake_l2cap_
454 .FindDynamicChannelByLocalId(kConnectionHandle, src_id)
455 ->opened());
456
457 // The FakeL2cap instance should now be out of ChannelIds to assign.
458 l2cap::ChannelId second_src_id = l2cap::kFirstDynamicChannelId + 1;
459 auto second_connection_acl_packet = l2cap::testing::AclConnectionReq(
460 kCommandId, kConnectionHandle, second_src_id, kPsm);
461 const auto& second_connection_header =
462 second_connection_acl_packet.To<hci_spec::ACLDataHeader>();
463 auto second_connection_header_len = sizeof(second_connection_header);
464 auto second_connection_payload_len =
465 le16toh(second_connection_header.data_total_length);
466 auto second_connection_packet =
467 DynamicByteBuffer(second_connection_payload_len);
468 second_connection_acl_packet.Copy(&second_connection_packet,
469 second_connection_header_len,
470 second_connection_payload_len);
471 fewer_ids_fake_l2cap_.HandlePdu(kConnectionHandle, second_connection_packet);
472
473 // Anticipate that we will receive a rejection as there are no Ids left.
474 auto expected_acl_response =
475 l2cap::testing::AclConnectionRsp(kCommandId,
476 kConnectionHandle,
477 second_src_id,
478 l2cap::kInvalidChannelId,
479 l2cap::ConnectionResult::kNoResources);
480 auto expected_response = expected_acl_response.view(
481 sizeof(hci_spec::ACLDataHeader) + sizeof(l2cap::CommandHeader));
482 EXPECT_TRUE(ContainersEqual(expected_response, *received_packet));
483 EXPECT_FALSE(
484 fewer_ids_fake_l2cap_
485 .FindDynamicChannelByLocalId(kConnectionHandle, second_src_id)
486 .is_alive());
487 }
488
489 } // namespace
490 } // namespace bt::testing
491