• 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/gap/bredr_interrogator.h"
16 
17 #include "pw_bluetooth_sapphire/internal/host/gap/peer_cache.h"
18 #include "pw_bluetooth_sapphire/internal/host/hci-spec/protocol.h"
19 #include "pw_bluetooth_sapphire/internal/host/hci-spec/util.h"
20 #include "pw_bluetooth_sapphire/internal/host/l2cap/fake_l2cap.h"
21 #include "pw_bluetooth_sapphire/internal/host/l2cap/l2cap_defs.h"
22 #include "pw_bluetooth_sapphire/internal/host/testing/controller_test.h"
23 #include "pw_bluetooth_sapphire/internal/host/testing/fake_peer.h"
24 #include "pw_bluetooth_sapphire/internal/host/testing/mock_controller.h"
25 #include "pw_bluetooth_sapphire/internal/host/testing/test_helpers.h"
26 #include "pw_bluetooth_sapphire/internal/host/testing/test_packets.h"
27 #include "pw_bluetooth_sapphire/internal/host/transport/error.h"
28 
29 namespace bt::gap {
30 
31 constexpr hci_spec::ConnectionHandle kConnectionHandle = 0x0BAA;
32 const DeviceAddress kTestDevAddr(DeviceAddress::Type::kBREDR, {1});
33 
34 const auto kRemoteNameRequestRsp = testing::CommandStatusPacket(
35     hci_spec::kRemoteNameRequest, pw::bluetooth::emboss::StatusCode::SUCCESS);
36 
37 const auto kReadRemoteVersionInfoRsp =
38     testing::CommandStatusPacket(hci_spec::kReadRemoteVersionInfo,
39                                  pw::bluetooth::emboss::StatusCode::SUCCESS);
40 
41 const auto kReadRemoteSupportedFeaturesRsp =
42     testing::CommandStatusPacket(hci_spec::kReadRemoteSupportedFeatures,
43                                  pw::bluetooth::emboss::StatusCode::SUCCESS);
44 
45 const auto kReadRemoteExtendedFeaturesRsp =
46     testing::CommandStatusPacket(hci_spec::kReadRemoteExtendedFeatures,
47                                  pw::bluetooth::emboss::StatusCode::SUCCESS);
48 
49 using bt::testing::CommandTransaction;
50 
51 using TestingBase =
52     bt::testing::FakeDispatcherControllerTest<bt::testing::MockController>;
53 
54 class BrEdrInterrogatorTest : public TestingBase {
55  public:
56   BrEdrInterrogatorTest() = default;
57   ~BrEdrInterrogatorTest() override = default;
58 
SetUp()59   void SetUp() override {
60     TestingBase::SetUp();
61 
62     peer_cache_ = std::make_unique<PeerCache>(dispatcher());
63     peer_ = peer_cache()->NewPeer(kTestDevAddr, /*connectable=*/true);
64     EXPECT_FALSE(peer_->name());
65     EXPECT_FALSE(peer_->version());
66     EXPECT_FALSE(peer_->features().HasPage(0));
67     EXPECT_FALSE(peer_->features().HasBit(
68         /*page=*/0, hci_spec::LMPFeature::kExtendedFeatures));
69     EXPECT_EQ(0u, peer_->features().last_page_number());
70 
71     interrogator_ = std::make_unique<BrEdrInterrogator>(
72         peer_->GetWeakPtr(), kConnectionHandle, cmd_channel()->AsWeakPtr());
73   }
74 
TearDown()75   void TearDown() override {
76     RunUntilIdle();
77     test_device()->Stop();
78     interrogator_ = nullptr;
79     peer_cache_ = nullptr;
80     TestingBase::TearDown();
81   }
82 
83  protected:
QueueSuccessfulInterrogation(DeviceAddress addr,hci_spec::ConnectionHandle conn,bool extended_features=true) const84   void QueueSuccessfulInterrogation(DeviceAddress addr,
85                                     hci_spec::ConnectionHandle conn,
86                                     bool extended_features = true) const {
87     const DynamicByteBuffer remote_name_request_complete_packet =
88         testing::RemoteNameRequestCompletePacket(addr);
89     const DynamicByteBuffer remote_version_complete_packet =
90         testing::ReadRemoteVersionInfoCompletePacket(conn);
91     const DynamicByteBuffer remote_supported_complete_packet =
92         testing::ReadRemoteSupportedFeaturesCompletePacket(conn,
93                                                            extended_features);
94 
95     EXPECT_CMD_PACKET_OUT(test_device(),
96                           testing::RemoteNameRequestPacket(addr),
97                           &kRemoteNameRequestRsp,
98                           &remote_name_request_complete_packet);
99     EXPECT_CMD_PACKET_OUT(test_device(),
100                           testing::ReadRemoteVersionInfoPacket(conn),
101                           &kReadRemoteVersionInfoRsp,
102                           &remote_version_complete_packet);
103     EXPECT_CMD_PACKET_OUT(test_device(),
104                           testing::ReadRemoteSupportedFeaturesPacket(conn),
105                           &kReadRemoteSupportedFeaturesRsp,
106                           &remote_supported_complete_packet);
107     if (extended_features) {
108       QueueSuccessfulReadRemoteExtendedFeatures(conn);
109     }
110   }
111 
QueueSuccessfulReadRemoteExtendedFeatures(hci_spec::ConnectionHandle conn) const112   void QueueSuccessfulReadRemoteExtendedFeatures(
113       hci_spec::ConnectionHandle conn) const {
114     const DynamicByteBuffer remote_extended1_complete_packet =
115         testing::ReadRemoteExtended1CompletePacket(conn);
116     const DynamicByteBuffer remote_extended2_complete_packet =
117         testing::ReadRemoteExtended2CompletePacket(conn);
118 
119     EXPECT_CMD_PACKET_OUT(test_device(),
120                           testing::ReadRemoteExtended1Packet(conn),
121                           &kReadRemoteExtendedFeaturesRsp,
122                           &remote_extended1_complete_packet);
123     EXPECT_CMD_PACKET_OUT(test_device(),
124                           testing::ReadRemoteExtended2Packet(conn),
125                           &kReadRemoteExtendedFeaturesRsp,
126                           &remote_extended2_complete_packet);
127   }
128 
DestroyInterrogator()129   void DestroyInterrogator() { interrogator_.reset(); }
130 
peer() const131   Peer* peer() const { return peer_; }
132 
peer_cache() const133   PeerCache* peer_cache() const { return peer_cache_.get(); }
134 
interrogator() const135   BrEdrInterrogator* interrogator() const { return interrogator_.get(); }
136 
137  private:
138   Peer* peer_ = nullptr;
139   std::unique_ptr<PeerCache> peer_cache_;
140   std::unique_ptr<BrEdrInterrogator> interrogator_;
141 
142   BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(BrEdrInterrogatorTest);
143 };
144 
145 using GAP_BrEdrInterrogatorTest = BrEdrInterrogatorTest;
146 
TEST_F(BrEdrInterrogatorTest,InterrogationFailsWithMalformedRemoteNameRequestComplete)147 TEST_F(BrEdrInterrogatorTest,
148        InterrogationFailsWithMalformedRemoteNameRequestComplete) {
149   // Remote Name Request Complete event with insufficient length.
150   const auto addr = kTestDevAddr.value().bytes();
151   StaticByteBuffer remote_name_request_complete_packet(
152       hci_spec::kRemoteNameRequestCompleteEventCode,
153       0x08,                                        // parameter_total_size (8)
154       pw::bluetooth::emboss::StatusCode::SUCCESS,  // status
155       addr[0],
156       addr[1],
157       addr[2],
158       addr[3],
159       addr[4],
160       addr[5],  // peer address
161       'F'       // remote name
162   );
163   EXPECT_CMD_PACKET_OUT(test_device(),
164                         testing::RemoteNameRequestPacket(kTestDevAddr),
165                         &kRemoteNameRequestRsp,
166                         &remote_name_request_complete_packet);
167   EXPECT_CMD_PACKET_OUT(
168       test_device(), testing::ReadRemoteVersionInfoPacket(kConnectionHandle));
169   EXPECT_CMD_PACKET_OUT(
170       test_device(),
171       testing::ReadRemoteSupportedFeaturesPacket(kConnectionHandle));
172 
173   hci::Result<> status = fit::ok();
174   interrogator()->Start(
175       [&status](hci::Result<> cb_status) { status = cb_status; });
176   RunUntilIdle();
177   EXPECT_TRUE(status.is_error());
178 }
179 
TEST_F(BrEdrInterrogatorTest,SuccessfulInterrogation)180 TEST_F(BrEdrInterrogatorTest, SuccessfulInterrogation) {
181   QueueSuccessfulInterrogation(kTestDevAddr, kConnectionHandle);
182 
183   std::optional<hci::Result<>> status;
184   interrogator()->Start(
185       [&status](hci::Result<> cb_status) { status = cb_status; });
186   RunUntilIdle();
187 
188   ASSERT_TRUE(status.has_value());
189   EXPECT_EQ(fit::ok(), *status);
190 
191   EXPECT_TRUE(peer()->name());
192   EXPECT_TRUE(peer()->version());
193   EXPECT_TRUE(peer()->features().HasPage(0));
194   EXPECT_TRUE(peer()->features().HasBit(
195       /*page=*/0, hci_spec::LMPFeature::kExtendedFeatures));
196   EXPECT_EQ(2u, peer()->features().last_page_number());
197 }
198 
TEST_F(BrEdrInterrogatorTest,SuccessfulReinterrogation)199 TEST_F(BrEdrInterrogatorTest, SuccessfulReinterrogation) {
200   QueueSuccessfulInterrogation(kTestDevAddr, kConnectionHandle);
201 
202   std::optional<hci::Result<>> status;
203   interrogator()->Start(
204       [&status](hci::Result<> cb_status) { status = cb_status; });
205   RunUntilIdle();
206 
207   ASSERT_TRUE(status.has_value());
208   EXPECT_EQ(fit::ok(), *status);
209   status = std::nullopt;
210 
211   QueueSuccessfulReadRemoteExtendedFeatures(kConnectionHandle);
212   interrogator()->Start(
213       [&status](hci::Result<> cb_status) { status = cb_status; });
214   RunUntilIdle();
215   ASSERT_TRUE(status.has_value());
216   EXPECT_EQ(fit::ok(), *status);
217 }
218 
TEST_F(BrEdrInterrogatorTest,InterrogationFailedToGetName)219 TEST_F(BrEdrInterrogatorTest, InterrogationFailedToGetName) {
220   const DynamicByteBuffer remote_name_request_failure_rsp =
221       testing::CommandStatusPacket(
222           hci_spec::kRemoteNameRequest,
223           pw::bluetooth::emboss::StatusCode::UNSPECIFIED_ERROR);
224   EXPECT_CMD_PACKET_OUT(test_device(),
225                         testing::RemoteNameRequestPacket(kTestDevAddr),
226                         &remote_name_request_failure_rsp);
227   EXPECT_CMD_PACKET_OUT(
228       test_device(), testing::ReadRemoteVersionInfoPacket(kConnectionHandle));
229   EXPECT_CMD_PACKET_OUT(
230       test_device(),
231       testing::ReadRemoteSupportedFeaturesPacket(kConnectionHandle));
232 
233   std::optional<hci::Result<>> status;
234   interrogator()->Start(
235       [&status](hci::Result<> cb_status) { status = cb_status; });
236   RunUntilIdle();
237 
238   ASSERT_TRUE(status.has_value());
239   EXPECT_FALSE(status->is_ok());
240 }
241 
TEST_F(BrEdrInterrogatorTest,Cancel)242 TEST_F(BrEdrInterrogatorTest, Cancel) {
243   QueueSuccessfulInterrogation(
244       kTestDevAddr, kConnectionHandle, /*extended_features=*/false);
245 
246   std::optional<hci::Result<>> result;
247   interrogator()->Start([&](hci::Result<> status) { result = status; });
248   EXPECT_FALSE(result.has_value());
249 
250   interrogator()->Cancel();
251 
252   // The result callback should be called synchronously.
253   ASSERT_TRUE(result.has_value());
254   EXPECT_EQ(result.value(), ToResult(HostError::kCanceled));
255   result.reset();
256 
257   // Events should be ignored.
258   RunUntilIdle();
259   EXPECT_FALSE(result.has_value());
260 }
261 
TEST_F(BrEdrInterrogatorTest,InterrogatorDestroyedInCompleteCallback)262 TEST_F(BrEdrInterrogatorTest, InterrogatorDestroyedInCompleteCallback) {
263   QueueSuccessfulInterrogation(kTestDevAddr, kConnectionHandle);
264 
265   std::optional<hci::Result<>> status;
266   interrogator()->Start([this, &status](hci::Result<> cb_status) {
267     status = cb_status;
268     DestroyInterrogator();
269   });
270   RunUntilIdle();
271 
272   ASSERT_TRUE(status.has_value());
273   EXPECT_TRUE(status->is_ok());
274 
275   EXPECT_TRUE(peer()->name());
276   EXPECT_TRUE(peer()->version());
277   EXPECT_TRUE(peer()->features().HasPage(0));
278   EXPECT_TRUE(peer()->features().HasBit(
279       /*page=*/0, hci_spec::LMPFeature::kExtendedFeatures));
280   EXPECT_EQ(2u, peer()->features().last_page_number());
281 }
282 }  // namespace bt::gap
283