• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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