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