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 #pragma once 16 #include "pw_bluetooth_sapphire/internal/host/l2cap/channel_manager.h" 17 #include "pw_bluetooth_sapphire/internal/host/l2cap/test_packets.h" 18 #include "pw_bluetooth_sapphire/internal/host/l2cap/types.h" 19 #include "pw_bluetooth_sapphire/internal/host/testing/controller_test.h" 20 #include "pw_bluetooth_sapphire/internal/host/testing/mock_controller.h" 21 22 namespace bt::l2cap { 23 24 using TestingBase = bt::testing::ControllerTest<bt::testing::MockController>; 25 26 // ChannelManager test fixture that uses a real AclDataChannel and uses 27 // MockController for HCI packet expectations. 28 class ChannelManagerMockControllerTest : public TestingBase { 29 public: 30 static constexpr size_t kMaxDataPacketLength = 64; 31 // High enough so that most tests don't need to worry about HCI flow control. 32 static constexpr size_t kBufferMaxNumPackets = 10; 33 34 static constexpr l2cap::ChannelParameters kChannelParameters{ 35 l2cap::RetransmissionAndFlowControlMode::kBasic, 36 l2cap::kMaxMTU, 37 std::nullopt}; 38 39 static constexpr l2cap::ExtendedFeatures kExtendedFeatures = 40 l2cap::kExtendedFeaturesBitEnhancedRetransmission; 41 DoNothing()42 static void DoNothing() {} NopRxCallback(ByteBufferPtr)43 static void NopRxCallback(ByteBufferPtr) {} 44 ChannelManagerMockControllerTest(pw::async::Dispatcher & dispatcher)45 ChannelManagerMockControllerTest(pw::async::Dispatcher& dispatcher) 46 : TestingBase(dispatcher), dispatcher_(dispatcher) {} 47 ~ChannelManagerMockControllerTest() = default; 48 49 protected: Initialize()50 void Initialize() { 51 TestingBase::Initialize(pw::bluetooth::Controller::FeaturesBits::kHciSco); 52 const auto bredr_buffer_info = 53 hci::DataBufferInfo(kMaxDataPacketLength, kBufferMaxNumPackets); 54 InitializeACLDataChannel(bredr_buffer_info); 55 56 // TODO(fxbug.dev/42141538): Remove assumptions about channel ordering so we 57 // can turn random ids on. 58 channel_manager_ = ChannelManager::Create(transport()->acl_data_channel(), 59 transport()->command_channel(), 60 /*random_channel_ids=*/false, 61 dispatcher_); 62 63 next_command_id_ = 1; 64 } 65 Initialize(size_t max_acl_payload_size,size_t max_le_payload_size,size_t max_acl_packets,size_t max_le_packets)66 void Initialize(size_t max_acl_payload_size, 67 size_t max_le_payload_size, 68 size_t max_acl_packets, 69 size_t max_le_packets) { 70 TestingBase::Initialize(pw::bluetooth::Controller::FeaturesBits::kHciSco); 71 72 InitializeACLDataChannel( 73 hci::DataBufferInfo(max_acl_payload_size, max_acl_packets), 74 hci::DataBufferInfo(max_le_payload_size, max_le_packets)); 75 76 channel_manager_ = ChannelManager::Create(transport()->acl_data_channel(), 77 transport()->command_channel(), 78 /*random_channel_ids=*/false, 79 dispatcher_); 80 81 next_command_id_ = 1; 82 } 83 DeleteChannelManager()84 void DeleteChannelManager() { channel_manager_ = nullptr; } 85 NextCommandId()86 l2cap::CommandId NextCommandId() { return next_command_id_++; } 87 QueueConfigNegotiation(hci_spec::ConnectionHandle handle,l2cap::ChannelParameters local_params,l2cap::ChannelParameters peer_params,l2cap::ChannelId local_cid,l2cap::ChannelId remote_cid,l2cap::CommandId local_config_req_id,l2cap::CommandId peer_config_req_id)88 void QueueConfigNegotiation(hci_spec::ConnectionHandle handle, 89 l2cap::ChannelParameters local_params, 90 l2cap::ChannelParameters peer_params, 91 l2cap::ChannelId local_cid, 92 l2cap::ChannelId remote_cid, 93 l2cap::CommandId local_config_req_id, 94 l2cap::CommandId peer_config_req_id) { 95 const auto kPeerConfigRsp = l2cap::testing::AclConfigRsp( 96 local_config_req_id, handle, local_cid, local_params); 97 const auto kPeerConfigReq = l2cap::testing::AclConfigReq( 98 peer_config_req_id, handle, local_cid, peer_params); 99 EXPECT_ACL_PACKET_OUT( 100 test_device(), 101 l2cap::testing::AclConfigReq( 102 local_config_req_id, handle, remote_cid, local_params), 103 &kPeerConfigRsp, 104 &kPeerConfigReq); 105 EXPECT_ACL_PACKET_OUT( 106 test_device(), 107 l2cap::testing::AclConfigRsp( 108 peer_config_req_id, handle, remote_cid, peer_params)); 109 } 110 111 void QueueInboundL2capConnection( 112 hci_spec::ConnectionHandle handle, 113 l2cap::Psm psm, 114 l2cap::ChannelId local_cid, 115 l2cap::ChannelId remote_cid, 116 l2cap::ChannelParameters local_params = kChannelParameters, 117 l2cap::ChannelParameters peer_params = kChannelParameters) { 118 const l2cap::CommandId kPeerConnReqId = 1; 119 const l2cap::CommandId kPeerConfigReqId = kPeerConnReqId + 1; 120 const auto kConfigReqId = NextCommandId(); 121 EXPECT_ACL_PACKET_OUT(test_device(), 122 l2cap::testing::AclConnectionRsp( 123 kPeerConnReqId, handle, remote_cid, local_cid)); 124 QueueConfigNegotiation(handle, 125 local_params, 126 peer_params, 127 local_cid, 128 remote_cid, 129 kConfigReqId, 130 kPeerConfigReqId); 131 132 test_device()->SendACLDataChannelPacket(l2cap::testing::AclConnectionReq( 133 kPeerConnReqId, handle, remote_cid, psm)); 134 } 135 136 void QueueOutboundL2capConnection( 137 hci_spec::ConnectionHandle handle, 138 l2cap::Psm psm, 139 l2cap::ChannelId local_cid, 140 l2cap::ChannelId remote_cid, 141 ChannelCallback open_cb, 142 l2cap::ChannelParameters local_params = kChannelParameters, 143 l2cap::ChannelParameters peer_params = kChannelParameters) { 144 const l2cap::CommandId kPeerConfigReqId = 1; 145 const auto kConnReqId = NextCommandId(); 146 const auto kConfigReqId = NextCommandId(); 147 const auto kConnRsp = l2cap::testing::AclConnectionRsp( 148 kConnReqId, handle, local_cid, remote_cid); 149 EXPECT_ACL_PACKET_OUT( 150 test_device(), 151 l2cap::testing::AclConnectionReq(kConnReqId, handle, local_cid, psm), 152 &kConnRsp); 153 QueueConfigNegotiation(handle, 154 local_params, 155 peer_params, 156 local_cid, 157 remote_cid, 158 kConfigReqId, 159 kPeerConfigReqId); 160 161 chanmgr()->OpenL2capChannel(handle, psm, local_params, std::move(open_cb)); 162 } 163 164 struct QueueAclConnectionRetVal { 165 l2cap::CommandId extended_features_id; 166 l2cap::CommandId fixed_channels_supported_id; 167 ChannelManager::BrEdrFixedChannels fixed_channels; 168 }; 169 170 QueueAclConnectionRetVal QueueAclConnection( 171 hci_spec::ConnectionHandle handle, 172 pw::bluetooth::emboss::ConnectionRole role = 173 pw::bluetooth::emboss::ConnectionRole::CENTRAL) { 174 QueueAclConnectionRetVal return_val; 175 return_val.extended_features_id = NextCommandId(); 176 return_val.fixed_channels_supported_id = NextCommandId(); 177 178 const auto kExtFeaturesRsp = l2cap::testing::AclExtFeaturesInfoRsp( 179 return_val.extended_features_id, handle, kExtendedFeatures); 180 EXPECT_ACL_PACKET_OUT(test_device(), 181 l2cap::testing::AclExtFeaturesInfoReq( 182 return_val.extended_features_id, handle), 183 &kExtFeaturesRsp); 184 EXPECT_ACL_PACKET_OUT(test_device(), 185 l2cap::testing::AclFixedChannelsSupportedInfoReq( 186 return_val.fixed_channels_supported_id, handle)); 187 188 return_val.fixed_channels = chanmgr()->AddACLConnection( 189 handle, 190 role, 191 /*link_error_callback=*/[]() {}, 192 /*security_callback=*/[](auto, auto, auto) {}); 193 194 return return_val; 195 } 196 QueueLEConnection(hci_spec::ConnectionHandle handle,pw::bluetooth::emboss::ConnectionRole role)197 ChannelManager::LEFixedChannels QueueLEConnection( 198 hci_spec::ConnectionHandle handle, 199 pw::bluetooth::emboss::ConnectionRole role) { 200 return chanmgr()->AddLEConnection( 201 handle, 202 role, 203 /*link_error_callback=*/[] {}, 204 /*conn_param_callback=*/[](auto&) {}, 205 /*security_callback=*/[](auto, auto, auto) {}); 206 } 207 208 Channel::WeakPtr ActivateNewFixedChannel( 209 ChannelId id, 210 hci_spec::ConnectionHandle conn_handle = 0x0001, 211 Channel::ClosedCallback closed_cb = DoNothing, 212 Channel::RxCallback rx_cb = NopRxCallback) { 213 auto chan = chanmgr()->OpenFixedChannel(conn_handle, id); 214 if (!chan.is_alive() || 215 !chan->Activate(std::move(rx_cb), std::move(closed_cb))) { 216 return Channel::WeakPtr(); 217 } 218 219 return chan; 220 } 221 chanmgr()222 ChannelManager* chanmgr() const { return channel_manager_.get(); } 223 224 private: 225 std::unique_ptr<ChannelManager> channel_manager_; 226 l2cap::CommandId next_command_id_; 227 pw::async::Dispatcher& dispatcher_; 228 229 BT_DISALLOW_COPY_ASSIGN_AND_MOVE(ChannelManagerMockControllerTest); 230 }; 231 232 class FakeDispatcherChannelManagerMockControllerTest 233 : public pw::async::test::FakeDispatcherFixture, 234 public ChannelManagerMockControllerTest { 235 protected: FakeDispatcherChannelManagerMockControllerTest()236 FakeDispatcherChannelManagerMockControllerTest() 237 : ChannelManagerMockControllerTest(dispatcher()) {} 238 SetUp()239 void SetUp() override { Initialize(); } 240 241 void SetUp(size_t max_acl_payload_size, 242 size_t max_le_payload_size, 243 size_t max_acl_packets = kBufferMaxNumPackets, 244 size_t max_le_packets = kBufferMaxNumPackets) { 245 Initialize(max_acl_payload_size, 246 max_le_payload_size, 247 max_acl_packets, 248 max_le_packets); 249 } 250 TearDown()251 void TearDown() override { 252 DeleteChannelManager(); 253 RunUntilIdle(); 254 DeleteTransport(); 255 } 256 }; 257 258 } // namespace bt::l2cap 259