• 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_discovery_manager.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/testing/controller_test.h"
20 #include "pw_bluetooth_sapphire/internal/host/testing/inspect.h"
21 #include "pw_bluetooth_sapphire/internal/host/testing/mock_controller.h"
22 #include "pw_bluetooth_sapphire/internal/host/testing/test_helpers.h"
23 #include "pw_bluetooth_sapphire/internal/host/testing/test_packets.h"
24 
25 namespace bt::gap {
26 namespace {
27 
28 using namespace inspect::testing;
29 
30 using bt::testing::CommandTransaction;
31 
32 using TestingBase =
33     bt::testing::FakeDispatcherControllerTest<bt::testing::MockController>;
34 
35 // clang-format off
36 #define COMMAND_COMPLETE_RSP(opcode)                                         \
37   StaticByteBuffer(hci_spec::kCommandCompleteEventCode, 0x04, 0xF0, \
38                                  LowerBits((opcode)), UpperBits((opcode)),   \
39                                  pw::bluetooth::emboss::StatusCode::SUCCESS)
40 
41 #define COMMAND_STATUS_RSP(opcode, statuscode)                       \
42   StaticByteBuffer( hci_spec::kCommandStatusEventCode, 0x04, \
43                                  (statuscode), 0xF0,                 \
44                                  LowerBits((opcode)), UpperBits((opcode)))
45 
46 
47 const StaticByteBuffer kWriteInquiryActivity(
48     LowerBits(hci_spec::kWriteInquiryScanActivity), UpperBits(hci_spec::kWriteInquiryScanActivity),
49     0x04, // Param total size
50     LowerBits(kInquiryScanInterval), UpperBits(kInquiryScanInterval),
51     LowerBits(kInquiryScanWindow), UpperBits(kInquiryScanWindow)
52 );
53 
54 const auto kWriteInquiryActivityRsp = COMMAND_COMPLETE_RSP(hci_spec::kWriteInquiryScanActivity);
55 
56 const StaticByteBuffer kWriteInquiryType(
57     LowerBits(hci_spec::kWriteInquiryScanType), UpperBits(hci_spec::kWriteInquiryScanType),
58     0x01, // Param total size
59     0x01 // Interlaced Inquiry Scan
60 );
61 
62 const auto kWriteInquiryTypeRsp = COMMAND_COMPLETE_RSP(hci_spec::kWriteInquiryScanType);
63 // clang-format on
64 
65 class BrEdrDiscoveryManagerTest : public TestingBase {
66  public:
67   BrEdrDiscoveryManagerTest() = default;
68   ~BrEdrDiscoveryManagerTest() override = default;
69 
SetUp()70   void SetUp() override {
71     TestingBase::SetUp();
72 
73     NewDiscoveryManager(pw::bluetooth::emboss::InquiryMode::STANDARD);
74   }
75 
TearDown()76   void TearDown() override {
77     discovery_manager_ = nullptr;
78     TestingBase::TearDown();
79   }
80 
NewDiscoveryManager(pw::bluetooth::emboss::InquiryMode mode)81   void NewDiscoveryManager(pw::bluetooth::emboss::InquiryMode mode) {
82     // We expect to set the Inquiry Scan and the Type when we start.
83     EXPECT_CMD_PACKET_OUT(
84         test_device(), kWriteInquiryActivity, &kWriteInquiryActivityRsp);
85     EXPECT_CMD_PACKET_OUT(
86         test_device(), kWriteInquiryType, &kWriteInquiryTypeRsp);
87 
88     discovery_manager_ = std::make_unique<BrEdrDiscoveryManager>(
89         dispatcher(),
90         transport()->command_channel()->AsWeakPtr(),
91         mode,
92         &peer_cache_);
93 
94     RunUntilIdle();
95   }
96 
DestroyDiscoveryManager()97   void DestroyDiscoveryManager() { discovery_manager_.reset(); }
98 
peer_cache()99   PeerCache* peer_cache() { return &peer_cache_; }
100 
101  protected:
discovery_manager() const102   BrEdrDiscoveryManager* discovery_manager() const {
103     return discovery_manager_.get();
104   }
105 
106  private:
107   PeerCache peer_cache_{dispatcher()};
108   std::unique_ptr<BrEdrDiscoveryManager> discovery_manager_;
109 
110   BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(BrEdrDiscoveryManagerTest);
111 };
112 
113 using GAP_BrEdrDiscoveryManagerTest = BrEdrDiscoveryManagerTest;
114 
115 // Suffix DeathTest has GoogleTest-specific behavior
116 using BrEdrDiscoveryManagerDeathTest = BrEdrDiscoveryManagerTest;
117 
118 // clang-format off
119 const StaticByteBuffer kInquiry(
120   LowerBits(hci_spec::kInquiry), UpperBits(hci_spec::kInquiry),
121   0x05, // Paramreter total size
122   0x33, 0x8B, 0x9E, // GIAC
123   0x08, // hci_spec::kInquiryLengthDefault
124   0x00 // Unlimited responses
125 );
126 
127 const auto kWriteLocalNameRsp =
128     COMMAND_STATUS_RSP(hci_spec::kWriteLocalName, pw::bluetooth::emboss::StatusCode::SUCCESS);
129 
130 const auto kWriteLocalNameRspError =
131     COMMAND_STATUS_RSP(hci_spec::kWriteLocalName, pw::bluetooth::emboss::StatusCode::HARDWARE_FAILURE);
132 
133 const auto kWriteExtendedInquiryResponseRsp =
134     COMMAND_STATUS_RSP(hci_spec::kWriteExtendedInquiryResponse, pw::bluetooth::emboss::StatusCode::SUCCESS);
135 
136 const auto kWriteExtendedInquiryResponseRspError =
137     COMMAND_STATUS_RSP(hci_spec::kWriteExtendedInquiryResponse, pw::bluetooth::emboss::StatusCode::HARDWARE_FAILURE);
138 
139 const auto kInquiryRsp = COMMAND_STATUS_RSP(hci_spec::kInquiry, pw::bluetooth::emboss::StatusCode::SUCCESS);
140 
141 const auto kInquiryRspError = COMMAND_STATUS_RSP(hci_spec::kInquiry, pw::bluetooth::emboss::StatusCode::HARDWARE_FAILURE);
142 
143 const StaticByteBuffer kInquiryComplete(
144   hci_spec::kInquiryCompleteEventCode,
145   0x01, // parameter_total_size (1 bytes)
146   pw::bluetooth::emboss::StatusCode::SUCCESS
147 );
148 
149 const StaticByteBuffer kInquiryCompleteError(
150   hci_spec::kInquiryCompleteEventCode,
151   0x01, // parameter_total_size (1 bytes)
152   pw::bluetooth::emboss::StatusCode::HARDWARE_FAILURE
153 );
154 
155 #define BD_ADDR(addr1) addr1, 0x00, 0x00, 0x00, 0x00, 0x00
156 
157 const DeviceAddress kDeviceAddress1(DeviceAddress::Type::kBREDR,
158                                     {BD_ADDR(0x01)});
159 const DeviceAddress kLeAliasAddress1(DeviceAddress::Type::kLEPublic,
160                                      kDeviceAddress1.value());
161 const DeviceAddress kDeviceAddress2(DeviceAddress::Type::kBREDR,
162                                     {BD_ADDR(0x02)});
163 const DeviceAddress kLeAliasAddress2(DeviceAddress::Type::kLEPublic,
164                                      kDeviceAddress2.value());
165 const DeviceAddress kDeviceAddress3(DeviceAddress::Type::kBREDR,
166                                     {BD_ADDR(0x03)});
167 const DeviceAddress kLeAliasAddress3(DeviceAddress::Type::kLEPublic,
168                                      kDeviceAddress3.value());
169 
170 const StaticByteBuffer kInquiryResult(
171   hci_spec::kInquiryResultEventCode,
172   0x0F, // parameter_total_size (15 bytes)
173   0x01, // num_responses
174   BD_ADDR(0x01), // bd_addr[0]
175   0x00, // page_scan_repetition_mode[0] (R0)
176   0x00, // unused / reserved
177   0x00, // unused / reserved
178   0x00, 0x1F, 0x00, // class_of_device[0] (unspecified)
179   0x00, 0x00 // clock_offset[0]
180 );
181 
182 const StaticByteBuffer kInquiryResultIncompleteHeader(
183   hci_spec::kInquiryResultEventCode,
184   0x00 // parameter_total_size (0 bytes)
185   // truncated
186 );
187 
188 const StaticByteBuffer kInquiryResultMissingResponses(
189   hci_spec::kInquiryResultEventCode,
190   0x1D, // parameter_total_size (29 bytes)
191   0x03, // num_responses (only two responses are packed)
192 
193   // first response
194   BD_ADDR(0x01), // bd_addr[0]
195   0x00, // page_scan_repetition_mode[0] (R0)
196   0x00, // unused / reserved
197   0x00, // unused / reserved
198   0x00, 0x1F, 0x00, // class_of_device[0] (unspecified)
199   0x00, 0x00, // clock_offset[0]
200 
201   // second response
202   BD_ADDR(0x02), // bd_addr[0]
203   0x00, // page_scan_repetition_mode[0] (R0)
204   0x00, // unused / reserved
205   0x00, // unused / reserved
206   0x00, 0x1F, 0x00, // class_of_device[0] (unspecified)
207   0x00, 0x00 // clock_offset[0]
208 );
209 
210 const StaticByteBuffer kInquiryResultIncompleteResponse(
211   hci_spec::kInquiryResultEventCode,
212   0x15, // parameter_total_size (21 bytes)
213   0x02, // num_responses
214 
215   // first response
216   BD_ADDR(0x01), // bd_addr[0]
217   0x00, // page_scan_repetition_mode[0] (R0)
218   0x00, // unused / reserved
219   0x00, // unused / reserved
220   0x00, 0x1F, 0x00, // class_of_device[0] (unspecified)
221   0x00, 0x00, // clock_offset[0]
222 
223   // second response
224   BD_ADDR(0x02) // bd_addr[0]
225   // truncated
226 );
227 
228 const StaticByteBuffer kRSSIInquiryResult(
229   hci_spec::kInquiryResultWithRSSIEventCode,
230   0x0F, // parameter_total_size (15 bytes)
231   0x01, // num_responses
232   BD_ADDR(0x02), // bd_addr[0]
233   0x00, // page_scan_repetition_mode[0] (R0)
234   0x00, // unused / reserved
235   0x00, 0x1F, 0x00, // class_of_device[0] (unspecified)
236   0x00, 0x00, // clock_offset[0]
237   0xEC // RSSI (-20dBm)
238 );
239 
240 #define REMOTE_NAME_REQUEST(addr1) StaticByteBuffer( \
241     LowerBits(hci_spec::kRemoteNameRequest), UpperBits(hci_spec::kRemoteNameRequest), \
242     0x0a, /* parameter_total_size (10 bytes) */ \
243     BD_ADDR(addr1),  /* BD_ADDR */ \
244     0x00, 0x00, 0x00, 0x80 /* page_scan_repetition_mode, 0, clock_offset */ \
245 );
246 
247 const auto kRemoteNameRequest1 = REMOTE_NAME_REQUEST(0x01)
248 const auto kRemoteNameRequest2 = REMOTE_NAME_REQUEST(0x02)
249 
250 #undef REMOTE_NAME_REQUEST
251 
252 const auto kRemoteNameRequestRsp =
253     COMMAND_STATUS_RSP(hci_spec::kRemoteNameRequest, pw::bluetooth::emboss::StatusCode::SUCCESS);
254 
255 #undef COMMAND_STATUS_RSP
256 
257 const auto kRemoteNameRequestComplete1 = testing::RemoteNameRequestCompletePacket(
258     kDeviceAddress1, {'F',    'u',    'c',    'h',    's',    'i',    'a',    '\xF0', '\x9F',
259                       '\x92', '\x96', '\x00', '\x14', '\x15', '\x16', '\x17', '\x18', '\x19',
260                       '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f', '\x20'}
261     // remote name (Fuchsia��)
262     // Everything after the 0x00 should be ignored.
263 );
264 const auto kRemoteNameRequestComplete2 =
265     testing::RemoteNameRequestCompletePacket(kDeviceAddress2, "Sapphire");
266 
267 const StaticByteBuffer kExtendedInquiryResult(
268   hci_spec::kExtendedInquiryResultEventCode,
269   0xFF, // parameter_total_size (255 bytes)
270   0x01, // num_responses
271   BD_ADDR(0x03),  // bd_addr
272   0x00, // page_scan_repetition_mode (R0)
273   0x00, // unused / reserved
274   0x00, 0x1F, 0x00, // class_of_device (unspecified)
275   0x00, 0x00, // clock_offset
276   0xEC, // RSSI (-20dBm)
277   // Extended Inquiry Response (240 bytes total)
278   // Complete Local Name (12 bytes): Fuchsia ��
279   0x0C, 0x09, 'F', 'u', 'c', 'h', 's', 'i', 'a', 0xF0, 0x9F, 0x92, 0x96,
280   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
281   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
282   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
283   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
284   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
285   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
286   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
287   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
288   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
289   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
290   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
291   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
292   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
293   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
294   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
295   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
296   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
297   0x00, 0x00, 0x00, 0x00, 0x00, 0x00
298 );
299 
300 #undef BD_ADDR
301 
302 const StaticByteBuffer kSetExtendedMode(
303     LowerBits(hci_spec::kWriteInquiryMode), UpperBits(hci_spec::kWriteInquiryMode),
304     0x01, // parameter_total_size
305     0x02 // Extended Inquiry Result or Inquiry Result with RSSI
306 );
307 
308 const auto kSetExtendedModeRsp = COMMAND_COMPLETE_RSP(hci_spec::kWriteInquiryMode);
309 
310 const StaticByteBuffer kReadScanEnable(
311     LowerBits(hci_spec::kReadScanEnable), UpperBits(hci_spec::kReadScanEnable),
312     0x00  // No parameters
313 );
314 
315 const StaticByteBuffer kWriteLocalName(
316   LowerBits(hci_spec::kWriteLocalName), UpperBits(hci_spec::kWriteLocalName),
317   0xF8, // parameter_total_size (248 bytes)
318   // Complete Local Name ()
319   'A', 'B', 'C', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
320   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
321   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
322   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
323   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
324   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
325   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
326   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
327   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
328   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
329   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
330   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
331   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
332   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
333   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
334   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
335   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
336   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
337   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
338   0x00
339 );
340 
341 const StaticByteBuffer kWriteExtendedInquiryResponse(
342   LowerBits(hci_spec::kWriteExtendedInquiryResponse),
343   UpperBits(hci_spec::kWriteExtendedInquiryResponse),
344   0xF1, // parameter_total_size (241 bytes)
345   0x00, // fec_required
346   0x04, // name_length + 1
347   0x09, // DataType::kCompleteLocalName,
348   // Complete Local Name (3 bytes + 1 byte null terminator + 234 bytes of zero padding)
349   'A', 'B', 'C', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
350   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
351   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
352   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
353   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
354   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
355   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
356   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
357   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
358   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
359   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
360   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
361   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
362   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
363   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
364   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
365   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
366   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
367   0x00, 0x00, 0x00, 0x00, 0x00, 0x00
368 );
369 
370 #define READ_SCAN_ENABLE_RSP(scan_enable)                                    \
371   StaticByteBuffer(hci_spec::kCommandCompleteEventCode, 0x05, 0xF0, \
372                                  LowerBits(hci_spec::kReadScanEnable),            \
373                                  UpperBits(hci_spec::kReadScanEnable),            \
374                                  pw::bluetooth::emboss::StatusCode::SUCCESS, (scan_enable))
375 
376 const auto kReadScanEnableRspNone = READ_SCAN_ENABLE_RSP(0x00);
377 const auto kReadScanEnableRspInquiry = READ_SCAN_ENABLE_RSP(0x01);
378 const auto kReadScanEnableRspPage = READ_SCAN_ENABLE_RSP(0x02);
379 const auto kReadScanEnableRspBoth = READ_SCAN_ENABLE_RSP(0x03);
380 
381 #undef READ_SCAN_ENABLE_RSP
382 
383 #define WRITE_SCAN_ENABLE_CMD(scan_enable)                               \
384   StaticByteBuffer(LowerBits(hci_spec::kWriteScanEnable),       \
385                                  UpperBits(hci_spec::kWriteScanEnable), 0x01, \
386                                  (scan_enable))
387 
388 const auto kWriteScanEnableNone = WRITE_SCAN_ENABLE_CMD(0x00);
389 const auto kWriteScanEnableInq = WRITE_SCAN_ENABLE_CMD(0x01);
390 const auto kWriteScanEnablePage = WRITE_SCAN_ENABLE_CMD(0x02);
391 const auto kWriteScanEnableBoth = WRITE_SCAN_ENABLE_CMD(0x03);
392 
393 #undef WRITE_SCAN_ENABLE_CMD
394 
395 const auto kWriteScanEnableRsp = COMMAND_COMPLETE_RSP(hci_spec::kWriteScanEnable);
396 
397 #undef COMMAND_COMPLETE_RSP
398 // clang-format on
399 
400 // Test: malformed inquiry result is fatal
TEST_F(BrEdrDiscoveryManagerDeathTest,MalformedInquiryResultFromControllerIsFatal)401 TEST_F(BrEdrDiscoveryManagerDeathTest,
402        MalformedInquiryResultFromControllerIsFatal) {
403   EXPECT_CMD_PACKET_OUT(test_device(), hci_spec::kInquiry, &kInquiryRsp);
404 
405   std::unique_ptr<BrEdrDiscoverySession> session;
406 
407   discovery_manager()->RequestDiscovery(
408       [&session](auto status, auto cb_session) {
409         EXPECT_EQ(fit::ok(), status);
410         session = std::move(cb_session);
411       });
412 
413   RunUntilIdle();
414 
415   for (auto event : {kInquiryResultIncompleteHeader.view(),
416                      kInquiryResultMissingResponses.view(),
417                      kInquiryResultIncompleteResponse.view()}) {
418     EXPECT_DEATH_IF_SUPPORTED(
419         [=] {
420           test_device()->SendCommandChannelPacket(event);
421           RunUntilIdle();
422         }(),
423         ".*");
424   }
425 }
426 
427 // Test: discovering() answers correctly
428 
429 // Test: requesting discovery should start inquiry
430 // Test: Inquiry Results that come in when there is discovery get reported up
431 // correctly to the sessions
432 // Test: Peers discovered are reported to the cache
433 // Test: RemoteNameRequest is processed correctly
434 // Test: Inquiry Results that come in when there's no discovery happening get
435 // discarded.
TEST_F(BrEdrDiscoveryManagerTest,RequestDiscoveryAndDrop)436 TEST_F(BrEdrDiscoveryManagerTest, RequestDiscoveryAndDrop) {
437   EXPECT_CMD_PACKET_OUT(
438       test_device(), hci_spec::kInquiry, &kInquiryRsp, &kInquiryResult);
439   EXPECT_CMD_PACKET_OUT(test_device(),
440                         kRemoteNameRequest1,
441                         &kRemoteNameRequestRsp,
442                         &kRemoteNameRequestComplete1);
443 
444   std::unique_ptr<BrEdrDiscoverySession> session;
445   size_t peers_found = 0u;
446 
447   discovery_manager()->RequestDiscovery(
448       [&session, &peers_found](auto status, auto cb_session) {
449         EXPECT_EQ(fit::ok(), status);
450         cb_session->set_result_callback(
451             [&peers_found](const auto&) { peers_found++; });
452         session = std::move(cb_session);
453       });
454 
455   EXPECT_FALSE(discovery_manager()->discovering());
456 
457   RunUntilIdle();
458 
459   EXPECT_EQ(1u, peers_found);
460   EXPECT_TRUE(discovery_manager()->discovering());
461 
462   EXPECT_CMD_PACKET_OUT(
463       test_device(), hci_spec::kInquiry, &kInquiryRsp, &kInquiryResult);
464 
465   test_device()->SendCommandChannelPacket(kInquiryComplete);
466 
467   RunUntilIdle();
468 
469   // Confirm that post-inquiry peer name request is processed correctly.
470   Peer* peer = peer_cache()->FindByAddress(kDeviceAddress1);
471   ASSERT_TRUE(peer);
472   EXPECT_EQ("Fuchsia��", *peer->name());
473   EXPECT_EQ(Peer::NameSource::kNameDiscoveryProcedure, *peer->name_source());
474 
475   EXPECT_EQ(2u, peers_found);
476 
477   // TODO(fxbug.dev/42145646): test InquiryCancel when it is implemented
478 
479   session = nullptr;
480   test_device()->SendCommandChannelPacket(kInquiryResult);
481 
482   RunUntilIdle();
483 
484   EXPECT_EQ(2u, peers_found);
485   EXPECT_FALSE(discovery_manager()->discovering());
486 
487   test_device()->SendCommandChannelPacket(kInquiryComplete);
488   RunUntilIdle();
489 }
490 
491 // Test: requesting a second discovery should start a session without sending
492 // any more HCI commands.
493 // Test: dropping the first discovery shouldn't stop inquiry
494 // Test: starting two sessions at once should only start inquiry once
TEST_F(BrEdrDiscoveryManagerTest,MultipleRequests)495 TEST_F(BrEdrDiscoveryManagerTest, MultipleRequests) {
496   EXPECT_CMD_PACKET_OUT(
497       test_device(), hci_spec::kInquiry, &kInquiryRsp, &kInquiryResult);
498   EXPECT_CMD_PACKET_OUT(test_device(),
499                         kRemoteNameRequest1,
500                         &kRemoteNameRequestRsp,
501                         &kRemoteNameRequestComplete1);
502 
503   std::unique_ptr<BrEdrDiscoverySession> session1;
504   size_t peers_found1 = 0u;
505 
506   discovery_manager()->RequestDiscovery(
507       [&session1, &peers_found1](auto status, auto cb_session) {
508         EXPECT_EQ(fit::ok(), status);
509         cb_session->set_result_callback(
510             [&peers_found1](const auto&) { peers_found1++; });
511         session1 = std::move(cb_session);
512       });
513 
514   EXPECT_FALSE(discovery_manager()->discovering());
515 
516   RunUntilIdle();
517 
518   EXPECT_TRUE(session1);
519   EXPECT_EQ(1u, peers_found1);
520   EXPECT_TRUE(discovery_manager()->discovering());
521 
522   std::unique_ptr<BrEdrDiscoverySession> session2;
523   size_t peers_found2 = 0u;
524 
525   discovery_manager()->RequestDiscovery(
526       [&session2, &peers_found2](auto status, auto cb_session) {
527         EXPECT_EQ(fit::ok(), status);
528         cb_session->set_result_callback(
529             [&peers_found2](const auto&) { peers_found2++; });
530         session2 = std::move(cb_session);
531       });
532 
533   RunUntilIdle();
534 
535   EXPECT_TRUE(session2);
536   EXPECT_EQ(1u, peers_found1);
537   EXPECT_EQ(0u, peers_found2);
538   EXPECT_TRUE(discovery_manager()->discovering());
539 
540   test_device()->SendCommandChannelPacket(kInquiryResult);
541 
542   RunUntilIdle();
543 
544   EXPECT_EQ(2u, peers_found1);
545   EXPECT_EQ(1u, peers_found2);
546 
547   session1 = nullptr;
548 
549   RunUntilIdle();
550 
551   test_device()->SendCommandChannelPacket(kInquiryResult);
552 
553   RunUntilIdle();
554 
555   EXPECT_EQ(2u, peers_found1);
556   EXPECT_EQ(2u, peers_found2);
557 
558   // TODO(fxbug.dev/42145646): test InquiryCancel when it is implemented
559 
560   session2 = nullptr;
561 
562   test_device()->SendCommandChannelPacket(kInquiryResult);
563 
564   RunUntilIdle();
565 
566   EXPECT_EQ(2u, peers_found1);
567   EXPECT_EQ(2u, peers_found2);
568 
569   EXPECT_FALSE(discovery_manager()->discovering());
570 
571   test_device()->SendCommandChannelPacket(kInquiryComplete);
572 
573   RunUntilIdle();
574 }
575 
576 // Test: starting a session "while" the other one is stopping a session should
577 // still restart the Inquiry.
578 // Test: starting a session "while" the other one is stopping should return
579 // without needing an InquiryComplete first.
580 // Test: we should only request a peer's name if it's the first time we
581 // encounter it.
TEST_F(BrEdrDiscoveryManagerTest,RequestDiscoveryWhileStop)582 TEST_F(BrEdrDiscoveryManagerTest, RequestDiscoveryWhileStop) {
583   EXPECT_CMD_PACKET_OUT(test_device(), kInquiry, &kInquiryRsp, &kInquiryResult);
584   EXPECT_CMD_PACKET_OUT(test_device(),
585                         kRemoteNameRequest1,
586                         &kRemoteNameRequestRsp,
587                         &kRemoteNameRequestComplete1);
588 
589   std::unique_ptr<BrEdrDiscoverySession> session1;
590   size_t peers_found1 = 0u;
591 
592   discovery_manager()->RequestDiscovery(
593       [&session1, &peers_found1](auto status, auto cb_session) {
594         EXPECT_EQ(fit::ok(), status);
595         cb_session->set_result_callback(
596             [&peers_found1](const auto&) { peers_found1++; });
597         session1 = std::move(cb_session);
598       });
599 
600   EXPECT_FALSE(discovery_manager()->discovering());
601 
602   RunUntilIdle();
603 
604   EXPECT_TRUE(session1);
605   EXPECT_EQ(1u, peers_found1);
606   EXPECT_TRUE(discovery_manager()->discovering());
607 
608   // Drop the active session.
609   session1 = nullptr;
610   RunUntilIdle();
611 
612   std::unique_ptr<BrEdrDiscoverySession> session2;
613   size_t peers_found2 = 0u;
614   discovery_manager()->RequestDiscovery(
615       [&session2, &peers_found2](auto status, auto cb_session) {
616         EXPECT_EQ(fit::ok(), status);
617         cb_session->set_result_callback(
618             [&peers_found2](const auto&) { peers_found2++; });
619         session2 = std::move(cb_session);
620       });
621 
622   // The new session should be started at this point, and inquiry results
623   // returned.
624   EXPECT_TRUE(session2);
625   test_device()->SendCommandChannelPacket(kInquiryResult);
626 
627   RunUntilIdle();
628 
629   EXPECT_EQ(1u, peers_found2);
630 
631   // Inquiry should be restarted when the Complete comes in because an active
632   // session2 still exists.
633   // TODO(fxbug.dev/42145646): test InquiryCancel when it is implemented
634   EXPECT_CMD_PACKET_OUT(test_device(), kInquiry, &kInquiryRsp, &kInquiryResult);
635   test_device()->SendCommandChannelPacket(kInquiryComplete);
636 
637   RunUntilIdle();
638 
639   EXPECT_EQ(1u, peers_found1);
640   EXPECT_EQ(2u, peers_found2);
641   EXPECT_TRUE(discovery_manager()->discovering());
642 
643   test_device()->SendCommandChannelPacket(kInquiryResult);
644 
645   RunUntilIdle();
646 
647   EXPECT_EQ(1u, peers_found1);
648   EXPECT_EQ(3u, peers_found2);
649 
650   // TODO(fxbug.dev/42145646): test InquiryCancel when it is implemented
651   session2 = nullptr;
652 
653   // After the session is dropped, even if another result comes in, no results
654   // are sent to the callback.
655   test_device()->SendCommandChannelPacket(kInquiryResult);
656 
657   RunUntilIdle();
658 
659   EXPECT_EQ(1u, peers_found1);
660   EXPECT_EQ(3u, peers_found2);
661 }
662 
663 // Test: When Inquiry Fails to start, we report this back to the requester.
TEST_F(BrEdrDiscoveryManagerTest,RequestDiscoveryError)664 TEST_F(BrEdrDiscoveryManagerTest, RequestDiscoveryError) {
665   EXPECT_CMD_PACKET_OUT(
666       test_device(), kInquiry, &kInquiryRspError, &kInquiryResult);
667   EXPECT_CMD_PACKET_OUT(test_device(),
668                         kRemoteNameRequest1,
669                         &kRemoteNameRequestRsp,
670                         &kRemoteNameRequestComplete1);
671 
672   std::unique_ptr<BrEdrDiscoverySession> session;
673 
674   discovery_manager()->RequestDiscovery([](auto status, auto cb_session) {
675     EXPECT_TRUE(status.is_error());
676     EXPECT_FALSE(cb_session);
677     EXPECT_EQ(ToResult(pw::bluetooth::emboss::StatusCode::HARDWARE_FAILURE),
678               status);
679   });
680 
681   EXPECT_FALSE(discovery_manager()->discovering());
682 
683   RunUntilIdle();
684 
685   EXPECT_FALSE(discovery_manager()->discovering());
686 }
687 
688 // Test: When inquiry complete indicates failure, we signal to the current
689 // sessions.
TEST_F(BrEdrDiscoveryManagerTest,ContinuingDiscoveryError)690 TEST_F(BrEdrDiscoveryManagerTest, ContinuingDiscoveryError) {
691   EXPECT_CMD_PACKET_OUT(test_device(), kInquiry, &kInquiryRsp, &kInquiryResult);
692   EXPECT_CMD_PACKET_OUT(test_device(),
693                         kRemoteNameRequest1,
694                         &kRemoteNameRequestRsp,
695                         &kRemoteNameRequestComplete1);
696 
697   std::unique_ptr<BrEdrDiscoverySession> session;
698   size_t peers_found = 0u;
699   bool error_callback = false;
700 
701   discovery_manager()->RequestDiscovery(
702       [&session, &peers_found, &error_callback](auto status, auto cb_session) {
703         EXPECT_EQ(fit::ok(), status);
704         cb_session->set_result_callback(
705             [&peers_found](const auto&) { peers_found++; });
706         cb_session->set_error_callback(
707             [&error_callback]() { error_callback = true; });
708         session = std::move(cb_session);
709       });
710 
711   EXPECT_FALSE(discovery_manager()->discovering());
712 
713   RunUntilIdle();
714 
715   EXPECT_EQ(1u, peers_found);
716   EXPECT_TRUE(discovery_manager()->discovering());
717 
718   test_device()->SendCommandChannelPacket(kInquiryCompleteError);
719 
720   RunUntilIdle();
721 
722   EXPECT_TRUE(error_callback);
723   EXPECT_FALSE(discovery_manager()->discovering());
724 
725   session = nullptr;
726 
727   RunUntilIdle();
728 }
729 
730 // clang-format off
731 const StaticByteBuffer kWriteLocalNameMaxLen(
732   LowerBits(hci_spec::kWriteLocalName), UpperBits(hci_spec::kWriteLocalName),
733   0xF8, // parameter_total_size (248 bytes)
734   // Complete Local Name (exactly 248 bytes)
735   'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
736   'T', 'U', 'V', 'W', 'X', 'Y',
737   'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
738   'T', 'U', 'V', 'W', 'X', 'Y',
739   'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
740   'T', 'U', 'V', 'W', 'X', 'Y',
741   'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
742   'T', 'U', 'V', 'W', 'X', 'Y',
743   'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
744   'T', 'U', 'V', 'W', 'X', 'Y',
745   'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
746   'T', 'U', 'V', 'W', 'X', 'Y',
747   'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
748   'T', 'U', 'V', 'W', 'X', 'Y',
749   'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
750   'T', 'U', 'V', 'W', 'X', 'Y',
751   'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
752   'T', 'U', 'V', 'W', 'X', 'Y',
753   'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
754   'T', 'U', 'V', 'W'
755 );
756 
757 const StaticByteBuffer kWriteExtInquiryResponseMaxLen(
758   LowerBits(hci_spec::kWriteExtendedInquiryResponse),
759   UpperBits(hci_spec::kWriteExtendedInquiryResponse),
760   0xF1, // parameter_total_size (241 bytes)
761   0x00, // fec_required
762   0xEF, // 239 bytes (1 + 238 bytes)
763   0x08, // DataType::kShortenedLocalName,
764   // Shortened Local Name (238 bytes, truncated from above)
765   'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
766   'T', 'U', 'V', 'W', 'X', 'Y',
767   'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
768   'T', 'U', 'V', 'W', 'X', 'Y',
769   'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
770   'T', 'U', 'V', 'W', 'X', 'Y',
771   'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
772   'T', 'U', 'V', 'W', 'X', 'Y',
773   'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
774   'T', 'U', 'V', 'W', 'X', 'Y',
775   'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
776   'T', 'U', 'V', 'W', 'X', 'Y',
777   'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
778   'T', 'U', 'V', 'W', 'X', 'Y',
779   'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
780   'T', 'U', 'V', 'W', 'X', 'Y',
781   'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
782   'T', 'U', 'V', 'W', 'X', 'Y',
783   'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M'
784 );
785 // clang-format on
786 
787 // Test: UpdateLocalName successfully sends hci command, and further calls
788 // UpdateEIRResponseData (private). Ensures the name is updated at the very end.
TEST_F(BrEdrDiscoveryManagerTest,UpdateLocalNameShortenedSuccess)789 TEST_F(BrEdrDiscoveryManagerTest, UpdateLocalNameShortenedSuccess) {
790   EXPECT_CMD_PACKET_OUT(test_device(), kWriteLocalNameMaxLen, );
791 
792   // Set the status to be an arbitrary invalid status.
793   hci::Result<> result =
794       ToResult(pw::bluetooth::emboss::StatusCode::PAIRING_NOT_ALLOWED);
795   size_t callback_count = 0u;
796   auto name_cb = [&result, &callback_count](const auto& status) {
797     EXPECT_EQ(fit::ok(), status);
798     callback_count++;
799     result = status;
800   };
801   std::string kNewName = "";
802   while (kNewName.length() < 225) {
803     kNewName.append("ABCDEFGHIJKLMNOPQRSTUVWXY");
804   }
805   kNewName.append("ABCDEFGHIJKLMNOPQRSTUVW");
806   discovery_manager()->UpdateLocalName(kNewName, name_cb);
807 
808   RunUntilIdle();
809 
810   // Local name should not be set, callback shouldn't be called yet.
811   EXPECT_NE(kNewName, discovery_manager()->local_name());
812   EXPECT_EQ(0u, callback_count);
813 
814   test_device()->SendCommandChannelPacket(kWriteLocalNameRsp);
815   EXPECT_CMD_PACKET_OUT(test_device(), kWriteExtInquiryResponseMaxLen, );
816 
817   RunUntilIdle();
818 
819   // Still waiting on EIR response.
820   // Local name should not be set, callback shouldn't be called yet.
821   EXPECT_NE(kNewName, discovery_manager()->local_name());
822   EXPECT_EQ(0u, callback_count);
823 
824   test_device()->SendCommandChannelPacket(kWriteExtendedInquiryResponseRsp);
825 
826   RunUntilIdle();
827 
828   EXPECT_EQ(kNewName, discovery_manager()->local_name());
829   EXPECT_EQ(ToResult(pw::bluetooth::emboss::StatusCode::SUCCESS), result);
830   EXPECT_EQ(1u, callback_count);
831 }
832 
833 // Test: UpdateLocalName successfully sends hci command, and further calls
834 // UpdateEIRResponseData (private). Ensures the name is updated at the very end.
TEST_F(BrEdrDiscoveryManagerTest,UpdateLocalNameSuccess)835 TEST_F(BrEdrDiscoveryManagerTest, UpdateLocalNameSuccess) {
836   EXPECT_CMD_PACKET_OUT(test_device(), kWriteLocalName, );
837 
838   // Set the status to be an arbitrary invalid status.
839   hci::Result<> result =
840       ToResult(pw::bluetooth::emboss::StatusCode::PAIRING_NOT_ALLOWED);
841   size_t callback_count = 0u;
842   auto name_cb = [&result, &callback_count](const auto& status) {
843     EXPECT_EQ(fit::ok(), status);
844     callback_count++;
845     result = status;
846   };
847   const std::string kNewName = "ABC";
848   discovery_manager()->UpdateLocalName(kNewName, name_cb);
849 
850   RunUntilIdle();
851 
852   // Local name should not be set, callback shouldn't be called yet.
853   EXPECT_NE(kNewName, discovery_manager()->local_name());
854   EXPECT_EQ(0u, callback_count);
855 
856   test_device()->SendCommandChannelPacket(kWriteLocalNameRsp);
857   EXPECT_CMD_PACKET_OUT(test_device(), kWriteExtendedInquiryResponse, );
858 
859   RunUntilIdle();
860 
861   // Still waiting on EIR response.
862   // Local name should not be set, callback shouldn't be called yet.
863   EXPECT_NE(kNewName, discovery_manager()->local_name());
864   EXPECT_EQ(0u, callback_count);
865 
866   test_device()->SendCommandChannelPacket(kWriteExtendedInquiryResponseRsp);
867 
868   RunUntilIdle();
869 
870   EXPECT_EQ(kNewName, discovery_manager()->local_name());
871   EXPECT_EQ(ToResult(pw::bluetooth::emboss::StatusCode::SUCCESS), result);
872   EXPECT_EQ(1u, callback_count);
873 }
874 
875 // Test: UpdateLocalName passes back error code through the callback and
876 // |local_name_| does not get updated.
TEST_F(BrEdrDiscoveryManagerTest,UpdateLocalNameError)877 TEST_F(BrEdrDiscoveryManagerTest, UpdateLocalNameError) {
878   EXPECT_CMD_PACKET_OUT(test_device(), kWriteLocalName, );
879 
880   // Set the status to be an arbitrary invalid status.
881   hci::Result<> result =
882       ToResult(pw::bluetooth::emboss::StatusCode::UNSUPPORTED_REMOTE_FEATURE);
883   size_t callback_count = 0u;
884   auto name_cb = [&result, &callback_count](const auto& status) {
885     EXPECT_TRUE(status.is_error());
886     callback_count++;
887     result = status;
888   };
889   const std::string kNewName = "ABC";
890   discovery_manager()->UpdateLocalName(kNewName, name_cb);
891 
892   RunUntilIdle();
893 
894   // Local name should not be set, callback shouldn't be called yet.
895   EXPECT_NE(kNewName, discovery_manager()->local_name());
896   EXPECT_EQ(0u, callback_count);
897 
898   // Send a response error.
899   test_device()->SendCommandChannelPacket(kWriteLocalNameRspError);
900 
901   RunUntilIdle();
902 
903   // |local_name_| should not be updated, return status should be error.
904   EXPECT_NE(kNewName, discovery_manager()->local_name());
905   EXPECT_EQ(ToResult(pw::bluetooth::emboss::StatusCode::HARDWARE_FAILURE),
906             result);
907   EXPECT_EQ(1u, callback_count);
908 }
909 
910 // Test: UpdateLocalName should succeed, but UpdateEIRResponseData should fail.
911 // Consequently, the |local_name_| should not be updated, and the callback
912 // should return the error.
TEST_F(BrEdrDiscoveryManagerTest,UpdateEIRResponseDataError)913 TEST_F(BrEdrDiscoveryManagerTest, UpdateEIRResponseDataError) {
914   EXPECT_CMD_PACKET_OUT(test_device(), kWriteLocalName, );
915 
916   // Set the status to be an arbitrary invalid status.
917   hci::Result<> result =
918       ToResult(pw::bluetooth::emboss::StatusCode::UNSUPPORTED_REMOTE_FEATURE);
919   size_t callback_count = 0u;
920   auto name_cb = [&result, &callback_count](const auto& status) {
921     EXPECT_TRUE(status.is_error());
922     callback_count++;
923     result = status;
924   };
925   const std::string kNewName = "ABC";
926   discovery_manager()->UpdateLocalName(kNewName, name_cb);
927 
928   RunUntilIdle();
929 
930   // Local name should not be set, callback shouldn't be called yet.
931   EXPECT_NE(kNewName, discovery_manager()->local_name());
932   EXPECT_EQ(0u, callback_count);
933 
934   // kWriteLocalName should succeed.
935   test_device()->SendCommandChannelPacket(kWriteLocalNameRsp);
936   EXPECT_CMD_PACKET_OUT(test_device(), kWriteExtendedInquiryResponse, );
937 
938   RunUntilIdle();
939 
940   // Still waiting on EIR response.
941   // Local name should not be set, callback shouldn't be called yet.
942   EXPECT_NE(kNewName, discovery_manager()->local_name());
943   EXPECT_EQ(0u, callback_count);
944 
945   // kWriteExtendedInquiryResponse should fail.
946   test_device()->SendCommandChannelPacket(
947       kWriteExtendedInquiryResponseRspError);
948 
949   RunUntilIdle();
950 
951   // |local_name_| should not be updated, return status should be error.
952   EXPECT_NE(kNewName, discovery_manager()->local_name());
953   EXPECT_EQ(ToResult(pw::bluetooth::emboss::StatusCode::HARDWARE_FAILURE),
954             result);
955   EXPECT_EQ(1u, callback_count);
956 }
957 
958 // Test: requesting discoverable works
959 // Test: requesting discoverable while discoverable is pending doesn't send
960 // any more HCI commands
TEST_F(BrEdrDiscoveryManagerTest,DiscoverableSet)961 TEST_F(BrEdrDiscoveryManagerTest, DiscoverableSet) {
962   EXPECT_CMD_PACKET_OUT(test_device(), kReadScanEnable, );
963 
964   std::vector<std::unique_ptr<BrEdrDiscoverableSession>> sessions;
965   auto session_cb = [&sessions](auto status, auto cb_session) {
966     EXPECT_EQ(fit::ok(), status);
967     sessions.emplace_back(std::move(cb_session));
968   };
969 
970   discovery_manager()->RequestDiscoverable(session_cb);
971 
972   RunUntilIdle();
973 
974   EXPECT_EQ(0u, sessions.size());
975   EXPECT_FALSE(discovery_manager()->discoverable());
976 
977   EXPECT_CMD_PACKET_OUT(test_device(), kWriteScanEnableInq, );
978 
979   test_device()->SendCommandChannelPacket(kReadScanEnableRspNone);
980 
981   RunUntilIdle();
982 
983   // Request another session while the first is pending.
984   discovery_manager()->RequestDiscoverable(session_cb);
985 
986   test_device()->SendCommandChannelPacket(kWriteScanEnableRsp);
987 
988   RunUntilIdle();
989 
990   EXPECT_EQ(2u, sessions.size());
991   EXPECT_TRUE(discovery_manager()->discoverable());
992 
993   discovery_manager()->RequestDiscoverable(session_cb);
994 
995   EXPECT_EQ(3u, sessions.size());
996   EXPECT_TRUE(discovery_manager()->discoverable());
997 
998   EXPECT_CMD_PACKET_OUT(
999       test_device(), kReadScanEnable, &kReadScanEnableRspInquiry);
1000   EXPECT_CMD_PACKET_OUT(
1001       test_device(), kWriteScanEnableNone, &kWriteScanEnableRsp);
1002 
1003   sessions.clear();
1004 
1005   RunUntilIdle();
1006 
1007   EXPECT_FALSE(discovery_manager()->discoverable());
1008 }
1009 
1010 // Test: requesting discoverable while discovery is disabling leaves
1011 // the discoverable enabled and reports success
1012 // Test: enable/disable while page scan is enabled works.
TEST_F(BrEdrDiscoveryManagerTest,DiscoverableRequestWhileStopping)1013 TEST_F(BrEdrDiscoveryManagerTest, DiscoverableRequestWhileStopping) {
1014   EXPECT_CMD_PACKET_OUT(
1015       test_device(), kReadScanEnable, &kReadScanEnableRspPage);
1016   EXPECT_CMD_PACKET_OUT(
1017       test_device(), kWriteScanEnableBoth, &kWriteScanEnableRsp);
1018 
1019   std::vector<std::unique_ptr<BrEdrDiscoverableSession>> sessions;
1020   auto session_cb = [&sessions](auto status, auto cb_session) {
1021     EXPECT_EQ(fit::ok(), status);
1022     sessions.emplace_back(std::move(cb_session));
1023   };
1024 
1025   discovery_manager()->RequestDiscoverable(session_cb);
1026 
1027   RunUntilIdle();
1028 
1029   EXPECT_EQ(1u, sessions.size());
1030   EXPECT_TRUE(discovery_manager()->discoverable());
1031 
1032   EXPECT_CMD_PACKET_OUT(test_device(), kReadScanEnable, );
1033 
1034   sessions.clear();
1035 
1036   RunUntilIdle();
1037 
1038   // Request a new discovery before the procedure finishes.
1039   // This will queue another ReadScanEnable just in case the disable write is
1040   // in progress.
1041   EXPECT_CMD_PACKET_OUT(test_device(), kReadScanEnable, );
1042   discovery_manager()->RequestDiscoverable(session_cb);
1043 
1044   test_device()->SendCommandChannelPacket(kReadScanEnableRspBoth);
1045 
1046   // This shouldn't send any WriteScanEnable because we're already in the right
1047   // mode (MockController will assert if we do as it's not expecting)
1048   RunUntilIdle();
1049 
1050   EXPECT_EQ(1u, sessions.size());
1051   EXPECT_TRUE(discovery_manager()->discoverable());
1052 
1053   // If somehow the scan got turned off, we will still turn it back on.
1054   EXPECT_CMD_PACKET_OUT(
1055       test_device(), kWriteScanEnableBoth, &kWriteScanEnableRsp);
1056   test_device()->SendCommandChannelPacket(kReadScanEnableRspPage);
1057 
1058   RunUntilIdle();
1059 
1060   EXPECT_EQ(1u, sessions.size());
1061   EXPECT_TRUE(discovery_manager()->discoverable());
1062 
1063   EXPECT_CMD_PACKET_OUT(
1064       test_device(), kReadScanEnable, &kReadScanEnableRspBoth);
1065   EXPECT_CMD_PACKET_OUT(
1066       test_device(), kWriteScanEnablePage, &kWriteScanEnableRsp);
1067 
1068   sessions.clear();
1069 
1070   RunUntilIdle();
1071 
1072   EXPECT_FALSE(discovery_manager()->discoverable());
1073 }
1074 
1075 // Test: non-standard inquiry modes mean before the first discovery, the
1076 // inquiry mode is set.
1077 // Test: extended inquiry is stored in the remote peer
TEST_F(BrEdrDiscoveryManagerTest,ExtendedInquiry)1078 TEST_F(BrEdrDiscoveryManagerTest, ExtendedInquiry) {
1079   NewDiscoveryManager(pw::bluetooth::emboss::InquiryMode::EXTENDED);
1080 
1081   EXPECT_CMD_PACKET_OUT(test_device(), kSetExtendedMode, &kSetExtendedModeRsp);
1082   EXPECT_CMD_PACKET_OUT(test_device(),
1083                         kInquiry,
1084                         &kInquiryRsp,
1085                         &kExtendedInquiryResult,
1086                         &kRSSIInquiryResult);
1087   EXPECT_CMD_PACKET_OUT(test_device(),
1088                         kRemoteNameRequest2,
1089                         &kRemoteNameRequestRsp,
1090                         &kRemoteNameRequestComplete2);
1091 
1092   std::unique_ptr<BrEdrDiscoverySession> session1;
1093   size_t peers_found1 = 0u;
1094 
1095   discovery_manager()->RequestDiscovery(
1096       [&session1, &peers_found1](auto status, auto cb_session) {
1097         EXPECT_EQ(fit::ok(), status);
1098         cb_session->set_result_callback(
1099             [&peers_found1](const auto&) { peers_found1++; });
1100         session1 = std::move(cb_session);
1101       });
1102 
1103   EXPECT_FALSE(discovery_manager()->discovering());
1104 
1105   RunUntilIdle();
1106 
1107   EXPECT_TRUE(session1);
1108   EXPECT_EQ(2u, peers_found1);
1109   EXPECT_TRUE(discovery_manager()->discovering());
1110   session1 = nullptr;
1111 
1112   Peer* peer1 = peer_cache()->FindByAddress(kDeviceAddress2);
1113   ASSERT_TRUE(peer1);
1114   EXPECT_EQ(-20, peer1->rssi());
1115 
1116   Peer* peer2 = peer_cache()->FindByAddress(kDeviceAddress3);
1117   ASSERT_TRUE(peer2);
1118   ASSERT_TRUE(peer2->name());
1119   EXPECT_EQ("Fuchsia��", *peer2->name());
1120   EXPECT_EQ(Peer::NameSource::kInquiryResultComplete, *peer2->name_source());
1121 
1122   test_device()->SendCommandChannelPacket(kInquiryComplete);
1123 
1124   RunUntilIdle();
1125 
1126   EXPECT_FALSE(discovery_manager()->discovering());
1127 }
1128 
1129 // Verify that receiving a inquiry response for a known LE non-connectable peer
1130 // results in the peer being changed to DualMode and connectable.
TEST_F(BrEdrDiscoveryManagerTest,InquiryResultUpgradesKnownLowEnergyPeer)1131 TEST_F(BrEdrDiscoveryManagerTest, InquiryResultUpgradesKnownLowEnergyPeer) {
1132   Peer* peer = peer_cache()->NewPeer(kLeAliasAddress1, /*connectable=*/false);
1133   ASSERT_TRUE(peer);
1134   ASSERT_FALSE(peer->connectable());
1135   ASSERT_EQ(TechnologyType::kLowEnergy, peer->technology());
1136 
1137   EXPECT_CMD_PACKET_OUT(test_device(), kInquiry, &kInquiryRsp, &kInquiryResult);
1138   EXPECT_CMD_PACKET_OUT(test_device(),
1139                         kRemoteNameRequest1,
1140                         &kRemoteNameRequestRsp,
1141                         &kRemoteNameRequestComplete1);
1142 
1143   std::unique_ptr<BrEdrDiscoverySession> session;
1144   size_t peers_found = 0u;
1145 
1146   discovery_manager()->RequestDiscovery([&session, &peers_found](
1147                                             auto status, auto cb_session) {
1148     EXPECT_EQ(fit::ok(), status);
1149     cb_session->set_result_callback([&peers_found](auto&) { peers_found++; });
1150     session = std::move(cb_session);
1151   });
1152   RunUntilIdle();
1153   session = nullptr;
1154 
1155   EXPECT_EQ(1u, peers_found);
1156   ASSERT_EQ(peer, peer_cache()->FindByAddress(kDeviceAddress1));
1157   EXPECT_EQ(TechnologyType::kDualMode, peer->technology());
1158   EXPECT_TRUE(peer->connectable());
1159 
1160   test_device()->SendCommandChannelPacket(kInquiryComplete);
1161 
1162   RunUntilIdle();
1163 }
1164 
1165 // Verify that receiving an extended inquiry response for a known LE
1166 // non-connectable peer results in the peer being changed to DualMode and
1167 // connectable.
TEST_F(BrEdrDiscoveryManagerTest,ExtendedInquiryResultUpgradesKnownLowEnergyPeer)1168 TEST_F(BrEdrDiscoveryManagerTest,
1169        ExtendedInquiryResultUpgradesKnownLowEnergyPeer) {
1170   Peer* peer = peer_cache()->NewPeer(kLeAliasAddress3, /*connectable=*/false);
1171   ASSERT_TRUE(peer);
1172   ASSERT_FALSE(peer->connectable());
1173   ASSERT_EQ(TechnologyType::kLowEnergy, peer->technology());
1174 
1175   NewDiscoveryManager(pw::bluetooth::emboss::InquiryMode::EXTENDED);
1176 
1177   EXPECT_CMD_PACKET_OUT(test_device(), kSetExtendedMode, &kSetExtendedModeRsp);
1178   EXPECT_CMD_PACKET_OUT(
1179       test_device(), kInquiry, &kInquiryRsp, &kExtendedInquiryResult);
1180 
1181   std::unique_ptr<BrEdrDiscoverySession> session;
1182   size_t peers_found = 0u;
1183 
1184   discovery_manager()->RequestDiscovery([&session, &peers_found](
1185                                             auto status, auto cb_session) {
1186     EXPECT_EQ(fit::ok(), status);
1187     cb_session->set_result_callback([&peers_found](auto&) { peers_found++; });
1188     session = std::move(cb_session);
1189   });
1190   RunUntilIdle();
1191   session = nullptr;
1192 
1193   EXPECT_EQ(1u, peers_found);
1194   ASSERT_EQ(peer, peer_cache()->FindByAddress(kDeviceAddress3));
1195   EXPECT_EQ(TechnologyType::kDualMode, peer->technology());
1196   EXPECT_TRUE(peer->connectable());
1197 
1198   test_device()->SendCommandChannelPacket(kInquiryComplete);
1199 
1200   RunUntilIdle();
1201 }
1202 
1203 // Verify that receiving an extended inquiry response with RSSI for a known LE
1204 // non-connectable peer results in the peer being changed to DualMode and
1205 // connectable.
TEST_F(BrEdrDiscoveryManagerTest,RSSIInquiryResultUpgradesKnownLowEnergyPeer)1206 TEST_F(BrEdrDiscoveryManagerTest, RSSIInquiryResultUpgradesKnownLowEnergyPeer) {
1207   Peer* peer = peer_cache()->NewPeer(kLeAliasAddress2, /*connectable=*/false);
1208   ASSERT_TRUE(peer);
1209   ASSERT_FALSE(peer->connectable());
1210   ASSERT_EQ(TechnologyType::kLowEnergy, peer->technology());
1211 
1212   NewDiscoveryManager(pw::bluetooth::emboss::InquiryMode::EXTENDED);
1213 
1214   EXPECT_CMD_PACKET_OUT(test_device(), kSetExtendedMode, &kSetExtendedModeRsp);
1215   EXPECT_CMD_PACKET_OUT(
1216       test_device(), kInquiry, &kInquiryRsp, &kRSSIInquiryResult);
1217   EXPECT_CMD_PACKET_OUT(test_device(),
1218                         kRemoteNameRequest2,
1219                         &kRemoteNameRequestRsp,
1220                         &kRemoteNameRequestComplete2);
1221 
1222   std::unique_ptr<BrEdrDiscoverySession> session;
1223   size_t peers_found = 0u;
1224 
1225   discovery_manager()->RequestDiscovery([&session, &peers_found](
1226                                             auto status, auto cb_session) {
1227     EXPECT_EQ(fit::ok(), status);
1228     cb_session->set_result_callback([&peers_found](auto&) { peers_found++; });
1229     session = std::move(cb_session);
1230   });
1231   RunUntilIdle();
1232   session = nullptr;
1233 
1234   EXPECT_EQ(1u, peers_found);
1235   ASSERT_EQ(peer, peer_cache()->FindByAddress(kDeviceAddress2));
1236   EXPECT_EQ(TechnologyType::kDualMode, peer->technology());
1237   EXPECT_TRUE(peer->connectable());
1238 
1239   test_device()->SendCommandChannelPacket(kInquiryComplete);
1240 
1241   RunUntilIdle();
1242 }
1243 
1244 #ifndef NINSPECT
TEST_F(BrEdrDiscoveryManagerTest,Inspect)1245 TEST_F(BrEdrDiscoveryManagerTest, Inspect) {
1246   inspect::Inspector inspector;
1247   discovery_manager()->AttachInspect(inspector.GetRoot(),
1248                                      "bredr_discovery_manager");
1249 
1250   auto discoverable_session_active_matcher =
1251       Contains(UintIs("discoverable_sessions", 1));
1252 
1253   std::unique_ptr<BrEdrDiscoverableSession> discoverable_session;
1254   auto session_cb = [&discoverable_session](auto status, auto cb_session) {
1255     EXPECT_EQ(fit::ok(), status);
1256     discoverable_session = std::move(cb_session);
1257   };
1258 
1259   EXPECT_CMD_PACKET_OUT(
1260       test_device(), kReadScanEnable, &kReadScanEnableRspPage);
1261   EXPECT_CMD_PACKET_OUT(
1262       test_device(), kWriteScanEnableBoth, &kWriteScanEnableRsp);
1263   discovery_manager()->RequestDiscoverable(session_cb);
1264   RunUntilIdle();
1265   EXPECT_TRUE(discoverable_session);
1266 
1267   auto properties = inspect::ReadFromVmo(inspector.DuplicateVmo())
1268                         .take_value()
1269                         .take_children()
1270                         .front()
1271                         .node_ptr()
1272                         ->take_properties();
1273   EXPECT_THAT(properties, discoverable_session_active_matcher);
1274 
1275   auto discoverable_session_counted_matcher =
1276       ::testing::IsSupersetOf({UintIs("discoverable_sessions", 0),
1277                                UintIs("discoverable_sessions_count", 1),
1278                                UintIs("last_discoverable_length_sec", 4)});
1279 
1280   RunFor(std::chrono::seconds(4));
1281   discoverable_session = nullptr;
1282   EXPECT_CMD_PACKET_OUT(
1283       test_device(), kReadScanEnable, &kReadScanEnableRspBoth);
1284   EXPECT_CMD_PACKET_OUT(
1285       test_device(), kWriteScanEnablePage, &kWriteScanEnableRsp);
1286   RunUntilIdle();
1287 
1288   properties = inspect::ReadFromVmo(inspector.DuplicateVmo())
1289                    .take_value()
1290                    .take_children()
1291                    .front()
1292                    .node_ptr()
1293                    ->take_properties();
1294   EXPECT_THAT(properties, discoverable_session_counted_matcher);
1295 
1296   auto discovery_session_active_matcher =
1297       Contains(UintIs("discovery_sessions", 1));
1298 
1299   std::unique_ptr<BrEdrDiscoverySession> discovery_session;
1300 
1301   discovery_manager()->RequestDiscovery(
1302       [&discovery_session](auto status, auto cb_session) {
1303         EXPECT_EQ(fit::ok(), status);
1304         discovery_session = std::move(cb_session);
1305       });
1306 
1307   EXPECT_CMD_PACKET_OUT(test_device(), kInquiry, &kInquiryRsp);
1308   RunUntilIdle();
1309   EXPECT_TRUE(discovery_session);
1310 
1311   properties = inspect::ReadFromVmo(inspector.DuplicateVmo())
1312                    .take_value()
1313                    .take_children()
1314                    .front()
1315                    .node_ptr()
1316                    ->take_properties();
1317   EXPECT_THAT(properties, discovery_session_active_matcher);
1318 
1319   auto discovery_session_counted_matcher =
1320       ::testing::IsSupersetOf({UintIs("discovery_sessions", 0),
1321                                UintIs("inquiry_sessions_count", 1),
1322                                UintIs("last_inquiry_length_sec", 7)});
1323 
1324   RunFor(std::chrono::seconds(7));
1325   discovery_session = nullptr;
1326   RunUntilIdle();
1327   test_device()->SendCommandChannelPacket(kInquiryComplete);
1328   RunUntilIdle();
1329 
1330   properties = inspect::ReadFromVmo(inspector.DuplicateVmo())
1331                    .take_value()
1332                    .take_children()
1333                    .front()
1334                    .node_ptr()
1335                    ->take_properties();
1336   EXPECT_THAT(properties, discovery_session_counted_matcher);
1337 }
1338 #endif  // NINSPECT
1339 
1340 }  // namespace
1341 }  // namespace bt::gap
1342