xref: /aosp_15_r20/external/pigweed/pw_bluetooth_sapphire/host/hci/low_energy_scanner_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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/hci/extended_low_energy_scanner.h"
16 #include "pw_bluetooth_sapphire/internal/host/hci/fake_local_address_delegate.h"
17 #include "pw_bluetooth_sapphire/internal/host/hci/legacy_low_energy_scanner.h"
18 #include "pw_bluetooth_sapphire/internal/host/testing/controller_test.h"
19 #include "pw_bluetooth_sapphire/internal/host/testing/fake_controller.h"
20 #include "pw_bluetooth_sapphire/internal/host/testing/fake_peer.h"
21 
22 // LowEnergyScanner has many potential subclasses (e.g. LegacyLowEnergyScanner,
23 // ExtendedLowEnergyScanner, etc). The unique features of these subclasses are
24 // tested individually in their own unittest files. However, there are some
25 // common features that all LowEnergyScanners should follow. This test file
26 // implements a type parameterized test to exercise those common features.
27 //
28 // If you add a new subclass of LowEnergyScanner in the future, make sure to add
29 // its type to the list of types below (in the TYPED_TEST_SUITE) so that its
30 // common features are exercised as well.
31 
32 namespace bt::hci {
33 
34 using bt::testing::FakeController;
35 using bt::testing::FakePeer;
36 using TestingBase = bt::testing::FakeDispatcherControllerTest<FakeController>;
37 
38 constexpr pw::chrono::SystemClock::duration kScanPeriod =
39     std::chrono::seconds(10);
40 constexpr pw::chrono::SystemClock::duration kPwScanPeriod =
41     std::chrono::seconds(10);
42 constexpr pw::chrono::SystemClock::duration kScanResponseTimeout =
43     std::chrono::seconds(2);
44 constexpr pw::chrono::SystemClock::duration kPwScanResponseTimeout =
45     std::chrono::seconds(2);
46 
47 // The unit tests below assume that the scan period is longer than the scan
48 // response timeout when exercising timeout expiration.
49 static_assert(kScanResponseTimeout < kScanPeriod,
50               "expected a smaller scan response timeout for testing");
51 
52 const StaticByteBuffer kPlainAdvDataBytes('T', 'e', 's', 't');
53 const StaticByteBuffer kPlainScanRspBytes('D', 'a', 't', 'a');
54 
55 constexpr char kPlainAdvData[] = "Test";
56 constexpr char kPlainScanRsp[] = "Data";
57 constexpr char kAdvDataAndScanRsp[] = "TestData";
58 
59 const DeviceAddress kPublicAddress1(DeviceAddress::Type::kLEPublic, {1});
60 const DeviceAddress kPublicAddress2(DeviceAddress::Type::kLEPublic, {2});
61 
62 const DeviceAddress kRandomAddress1(DeviceAddress::Type::kLERandom, {3});
63 const DeviceAddress kRandomAddress2(DeviceAddress::Type::kLERandom, {4});
64 const DeviceAddress kRandomAddress3(DeviceAddress::Type::kLERandom, {5});
65 const DeviceAddress kRandomAddress4(DeviceAddress::Type::kLERandom, {6});
66 
67 template <typename T>
68 class LowEnergyScannerTest : public TestingBase,
69                              public LowEnergyScanner::Delegate {
70  public:
71   LowEnergyScannerTest() = default;
72   ~LowEnergyScannerTest() override = default;
73 
74  protected:
SetUp()75   void SetUp() override {
76     TestingBase::SetUp();
77 
78     FakeController::Settings settings;
79     settings.ApplyLegacyLEConfig();
80     this->test_device()->set_settings(settings);
81 
82     scanner_ = std::unique_ptr<T>(CreateScannerInternal());
83     scanner_->set_delegate(this);
84   }
85 
TearDown()86   void TearDown() override {
87     scanner_ = nullptr;
88     this->test_device()->Stop();
89     TestingBase::TearDown();
90   }
91 
92   template <bool same = std::is_same_v<T, ExtendedLowEnergyScanner>>
CreateScannerInternal()93   std::enable_if_t<same, ExtendedLowEnergyScanner>* CreateScannerInternal() {
94     return new ExtendedLowEnergyScanner(
95         fake_address_delegate(), transport()->GetWeakPtr(), dispatcher());
96   }
97 
98   template <bool same = std::is_same_v<T, LegacyLowEnergyScanner>>
CreateScannerInternal()99   std::enable_if_t<same, LegacyLowEnergyScanner>* CreateScannerInternal() {
100     return new LegacyLowEnergyScanner(
101         fake_address_delegate(), transport()->GetWeakPtr(), dispatcher());
102   }
103 
104   using PeerFoundCallback = fit::function<void(const LowEnergyScanResult&)>;
set_peer_found_callback(PeerFoundCallback cb)105   void set_peer_found_callback(PeerFoundCallback cb) {
106     peer_found_cb_ = std::move(cb);
107   }
108 
109   using DirectedAdvCallback = fit::function<void(const LowEnergyScanResult&)>;
set_directed_adv_callback(DirectedAdvCallback cb)110   void set_directed_adv_callback(DirectedAdvCallback cb) {
111     directed_adv_cb_ = std::move(cb);
112   }
113 
StartScan(bool active,pw::chrono::SystemClock::duration period=LowEnergyScanner::kPeriodInfinite)114   bool StartScan(bool active,
115                  pw::chrono::SystemClock::duration period =
116                      LowEnergyScanner::kPeriodInfinite) {
117     LowEnergyScanner::ScanOptions options{
118         .active = active,
119         .filter_duplicates = true,
120         .period = period,
121         .scan_response_timeout = kPwScanResponseTimeout};
122     return scanner()->StartScan(
123         options, [this](auto status) { last_scan_status_ = status; });
124   }
125 
126   // LowEnergyScanner::Delegate override:
OnPeerFound(const LowEnergyScanResult & result)127   void OnPeerFound(const LowEnergyScanResult& result) override {
128     if (peer_found_cb_) {
129       peer_found_cb_(result);
130     }
131   }
132 
133   // LowEnergyScanner::Observer override:
OnDirectedAdvertisement(const LowEnergyScanResult & result)134   void OnDirectedAdvertisement(const LowEnergyScanResult& result) override {
135     if (directed_adv_cb_) {
136       directed_adv_cb_(result);
137     }
138   }
139 
140   // Adds 6 fake peers using kAddress[0-5] above.
AddFakePeers()141   void AddFakePeers() {
142     // Generates ADV_IND
143     auto fake_peer =
144         std::make_unique<FakePeer>(kPublicAddress1, dispatcher(), true, true);
145     fake_peer->set_advertising_data(kPlainAdvDataBytes);
146     fake_peer->set_scan_response(kPlainScanRspBytes);
147     test_device()->AddPeer(std::move(fake_peer));
148 
149     // Generates ADV_SCAN_IND
150     fake_peer =
151         std::make_unique<FakePeer>(kRandomAddress1, dispatcher(), false, true);
152     fake_peer->set_advertising_data(kPlainAdvDataBytes);
153     fake_peer->set_scan_response(kPlainScanRspBytes);
154     test_device()->AddPeer(std::move(fake_peer));
155 
156     // Generates ADV_IND
157     fake_peer =
158         std::make_unique<FakePeer>(kPublicAddress2, dispatcher(), true, true);
159     fake_peer->set_advertising_data(kPlainAdvDataBytes);
160     fake_peer->set_scan_response(DynamicByteBuffer());
161     test_device()->AddPeer(std::move(fake_peer));
162 
163     // Generates ADV_IND
164     fake_peer =
165         std::make_unique<FakePeer>(kRandomAddress2, dispatcher(), true, true);
166     fake_peer->set_scan_response(kPlainScanRspBytes);
167     test_device()->AddPeer(std::move(fake_peer));
168 
169     // Generates ADV_IND, a scan response is never sent even though ADV_IND is
170     // scannable.
171     fake_peer =
172         std::make_unique<FakePeer>(kRandomAddress3, dispatcher(), true, false);
173     fake_peer->set_advertising_data(kPlainAdvDataBytes);
174     test_device()->AddPeer(std::move(fake_peer));
175 
176     // Generates ADV_NONCONN_IND
177     fake_peer =
178         std::make_unique<FakePeer>(kRandomAddress4, dispatcher(), false, false);
179     fake_peer->set_advertising_data(kPlainAdvDataBytes);
180     test_device()->AddPeer(std::move(fake_peer));
181   }
182 
scanner() const183   LowEnergyScanner* scanner() const { return scanner_.get(); }
fake_address_delegate()184   FakeLocalAddressDelegate* fake_address_delegate() {
185     return &fake_address_delegate_;
186   }
187 
last_scan_status() const188   LowEnergyScanner::ScanStatus last_scan_status() const {
189     return last_scan_status_;
190   }
191 
192  private:
193   PeerFoundCallback peer_found_cb_;
194   DirectedAdvCallback directed_adv_cb_;
195   FakeLocalAddressDelegate fake_address_delegate_{dispatcher()};
196   std::unique_ptr<LowEnergyScanner> scanner_;
197 
198   LowEnergyScanner::ScanStatus last_scan_status_;
199 
200   BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(LowEnergyScannerTest);
201 };
202 
203 using Implementations =
204     ::testing::Types<LegacyLowEnergyScanner, ExtendedLowEnergyScanner>;
205 TYPED_TEST_SUITE(LowEnergyScannerTest, Implementations);
206 
TYPED_TEST(LowEnergyScannerTest,StartScanHCIErrors)207 TYPED_TEST(LowEnergyScannerTest, StartScanHCIErrors) {
208   EXPECT_TRUE(this->scanner()->IsIdle());
209   EXPECT_FALSE(this->scanner()->IsScanning());
210   EXPECT_FALSE(this->test_device()->le_scan_state().enabled);
211 
212   // Set Scan Parameters will fail.
213   this->test_device()->SetDefaultResponseStatus(
214       hci_spec::kLESetScanParameters,
215       pw::bluetooth::emboss::StatusCode::HARDWARE_FAILURE);
216   this->test_device()->SetDefaultResponseStatus(
217       hci_spec::kLESetExtendedScanParameters,
218       pw::bluetooth::emboss::StatusCode::HARDWARE_FAILURE);
219   EXPECT_EQ(0, this->test_device()->le_scan_state().scan_interval);
220 
221   EXPECT_TRUE(this->StartScan(false));
222   EXPECT_EQ(LowEnergyScanner::State::kInitiating, this->scanner()->state());
223 
224   // Calling StartScan() should fail as the state is not kIdle.
225   EXPECT_FALSE(this->StartScan(false));
226   this->RunUntilIdle();
227 
228   // Status should be failure and the scan parameters shouldn't have applied.
229   EXPECT_EQ(LowEnergyScanner::ScanStatus::kFailed, this->last_scan_status());
230   EXPECT_EQ(0, this->test_device()->le_scan_state().scan_interval);
231   EXPECT_FALSE(this->test_device()->le_scan_state().enabled);
232   EXPECT_TRUE(this->scanner()->IsIdle());
233   EXPECT_FALSE(this->scanner()->IsScanning());
234 
235   // Set Scan Parameters will succeed but Set Scan Enable will fail.
236   this->test_device()->ClearDefaultResponseStatus(
237       hci_spec::kLESetScanParameters);
238   this->test_device()->ClearDefaultResponseStatus(
239       hci_spec::kLESetExtendedScanParameters);
240   this->test_device()->SetDefaultResponseStatus(
241       hci_spec::kLESetScanEnable,
242       pw::bluetooth::emboss::StatusCode::HARDWARE_FAILURE);
243   this->test_device()->SetDefaultResponseStatus(
244       hci_spec::kLESetExtendedScanEnable,
245       pw::bluetooth::emboss::StatusCode::HARDWARE_FAILURE);
246 
247   EXPECT_TRUE(this->StartScan(false));
248   EXPECT_EQ(LowEnergyScanner::State::kInitiating, this->scanner()->state());
249   this->RunUntilIdle();
250 
251   // Status should be failure but the scan parameters should have applied.
252   EXPECT_EQ(LowEnergyScanner::ScanStatus::kFailed, this->last_scan_status());
253   EXPECT_EQ(hci_spec::defaults::kLEScanInterval,
254             this->test_device()->le_scan_state().scan_interval);
255   EXPECT_EQ(hci_spec::defaults::kLEScanWindow,
256             this->test_device()->le_scan_state().scan_window);
257   EXPECT_EQ(pw::bluetooth::emboss::LEScanFilterPolicy::BASIC_UNFILTERED,
258             this->test_device()->le_scan_state().filter_policy);
259   EXPECT_FALSE(this->test_device()->le_scan_state().enabled);
260   EXPECT_TRUE(this->scanner()->IsIdle());
261   EXPECT_FALSE(this->scanner()->IsScanning());
262 }
263 
TYPED_TEST(LowEnergyScannerTest,StartScan)264 TYPED_TEST(LowEnergyScannerTest, StartScan) {
265   EXPECT_TRUE(this->scanner()->IsIdle());
266   EXPECT_FALSE(this->scanner()->IsScanning());
267   EXPECT_FALSE(this->test_device()->le_scan_state().enabled);
268 
269   EXPECT_TRUE(this->StartScan(true, kPwScanPeriod));
270   EXPECT_EQ(LowEnergyScanner::State::kInitiating, this->scanner()->state());
271   this->RunUntilIdle();
272 
273   // Scan should have started.
274   EXPECT_EQ(LowEnergyScanner::ScanStatus::kActive, this->last_scan_status());
275   EXPECT_EQ(hci_spec::defaults::kLEScanInterval,
276             this->test_device()->le_scan_state().scan_interval);
277   EXPECT_EQ(hci_spec::defaults::kLEScanWindow,
278             this->test_device()->le_scan_state().scan_window);
279   EXPECT_EQ(pw::bluetooth::emboss::LEScanFilterPolicy::BASIC_UNFILTERED,
280             this->test_device()->le_scan_state().filter_policy);
281   EXPECT_EQ(pw::bluetooth::emboss::LEScanType::ACTIVE,
282             this->test_device()->le_scan_state().scan_type);
283   EXPECT_TRUE(this->test_device()->le_scan_state().filter_duplicates);
284   EXPECT_TRUE(this->test_device()->le_scan_state().enabled);
285   EXPECT_EQ(LowEnergyScanner::State::kActiveScanning, this->scanner()->state());
286   EXPECT_TRUE(this->scanner()->IsScanning());
287 
288   // Calling StartScan should fail as a scan is already in progress.
289   EXPECT_FALSE(this->StartScan(true));
290 
291   // After 10 s (kScanPeriod) the scan should stop by itself.
292   this->RunFor(kScanPeriod);
293 
294   EXPECT_EQ(LowEnergyScanner::ScanStatus::kComplete, this->last_scan_status());
295   EXPECT_FALSE(this->test_device()->le_scan_state().enabled);
296   EXPECT_TRUE(this->scanner()->IsIdle());
297   EXPECT_FALSE(this->scanner()->IsScanning());
298 }
299 
TYPED_TEST(LowEnergyScannerTest,StopScan)300 TYPED_TEST(LowEnergyScannerTest, StopScan) {
301   EXPECT_TRUE(this->scanner()->IsIdle());
302   EXPECT_FALSE(this->scanner()->IsScanning());
303   EXPECT_FALSE(this->test_device()->le_scan_state().enabled);
304 
305   // Calling StopScan should fail while a scan is not in progress.
306   EXPECT_FALSE(this->scanner()->StopScan());
307 
308   // Pass a long scan period value. This should not matter as we will terminate
309   // the scan directly.
310   EXPECT_TRUE(this->StartScan(true, kPwScanPeriod * 10u));
311   EXPECT_EQ(LowEnergyScanner::State::kInitiating, this->scanner()->state());
312   this->RunUntilIdle();
313 
314   // Scan should have started.
315   EXPECT_EQ(LowEnergyScanner::ScanStatus::kActive, this->last_scan_status());
316   EXPECT_TRUE(this->test_device()->le_scan_state().enabled);
317   EXPECT_EQ(LowEnergyScanner::State::kActiveScanning, this->scanner()->state());
318   EXPECT_TRUE(this->scanner()->IsScanning());
319 
320   // StopScan() should terminate the scan session and the status should be
321   // kStopped.
322   EXPECT_TRUE(this->scanner()->StopScan());
323   this->RunUntilIdle();
324 
325   EXPECT_EQ(LowEnergyScanner::ScanStatus::kStopped, this->last_scan_status());
326   EXPECT_FALSE(this->test_device()->le_scan_state().enabled);
327   EXPECT_TRUE(this->scanner()->IsIdle());
328   EXPECT_FALSE(this->scanner()->IsScanning());
329 }
330 
TYPED_TEST(LowEnergyScannerTest,StopScanWhileInitiating)331 TYPED_TEST(LowEnergyScannerTest, StopScanWhileInitiating) {
332   EXPECT_TRUE(this->scanner()->IsIdle());
333   EXPECT_FALSE(this->scanner()->IsScanning());
334   EXPECT_FALSE(this->test_device()->le_scan_state().enabled);
335 
336   EXPECT_TRUE(this->StartScan(true));
337   EXPECT_EQ(LowEnergyScanner::State::kInitiating, this->scanner()->state());
338 
339   // Call StopScan(). This should cancel the HCI command sequence set up by
340   // StartScan() so that the it never completes. The HCI_LE_Set_Scan_Parameters
341   // command *may* get sent but the scan should never get enabled.
342   EXPECT_TRUE(this->scanner()->StopScan());
343   this->RunUntilIdle();
344 
345   EXPECT_EQ(LowEnergyScanner::ScanStatus::kStopped, this->last_scan_status());
346   EXPECT_FALSE(this->test_device()->le_scan_state().enabled);
347   EXPECT_TRUE(this->scanner()->IsIdle());
348   EXPECT_FALSE(this->scanner()->IsScanning());
349 }
350 
TYPED_TEST(LowEnergyScannerTest,ScanResponseTimeout)351 TYPED_TEST(LowEnergyScannerTest, ScanResponseTimeout) {
352   constexpr pw::chrono::SystemClock::duration kHalfTimeout =
353       kScanResponseTimeout / 2;
354 
355   std::unordered_set<DeviceAddress> results;
356   this->set_peer_found_callback([&](const LowEnergyScanResult& result) {
357     results.insert(result.address());
358   });
359 
360   // Add a peer that sends a scan response and one that doesn't.
361   auto fake_peer = std::make_unique<FakePeer>(
362       kRandomAddress1, this->dispatcher(), false, true);
363   fake_peer->set_advertising_data(kPlainAdvDataBytes);
364   fake_peer->set_scan_response(kPlainScanRspBytes);
365   this->test_device()->AddPeer(std::move(fake_peer));
366 
367   fake_peer = std::make_unique<FakePeer>(
368       kRandomAddress2, this->dispatcher(), true, false);
369   fake_peer->set_advertising_data(kPlainAdvDataBytes);
370   this->test_device()->AddPeer(std::move(fake_peer));
371 
372   EXPECT_TRUE(this->StartScan(true));
373   this->RunUntilIdle();
374   ASSERT_EQ(1u, results.size());
375   EXPECT_EQ(1u, results.count(kRandomAddress1));
376 
377   // Advance the time but do not expire the timeout.
378   this->RunFor(kHalfTimeout);
379   ASSERT_EQ(1u, results.size());
380 
381   // Add another peer that doesn't send a scan response after the kHalfTimeout
382   // delay. This is to test that a separate timeout is kept for every peer.
383   fake_peer = std::make_unique<FakePeer>(
384       kRandomAddress3, this->dispatcher(), true, false);
385   fake_peer->set_advertising_data(kPlainAdvDataBytes);
386   this->test_device()->AddPeer(std::move(fake_peer));
387 
388   // Expire the first timeout.
389   this->RunFor(kHalfTimeout);
390   ASSERT_EQ(2u, results.size());
391   EXPECT_EQ(1u, results.count(kRandomAddress1));
392   EXPECT_EQ(1u, results.count(kRandomAddress2));
393 
394   // Expire the second timeout.
395   this->RunFor(kHalfTimeout);
396   ASSERT_EQ(3u, results.size());
397   EXPECT_EQ(1u, results.count(kRandomAddress1));
398   EXPECT_EQ(1u, results.count(kRandomAddress2));
399   EXPECT_EQ(1u, results.count(kRandomAddress3));
400 }
401 
TYPED_TEST(LowEnergyScannerTest,ScanResponseAfterTimeout)402 TYPED_TEST(LowEnergyScannerTest, ScanResponseAfterTimeout) {
403   {
404     auto peer = std::make_unique<FakePeer>(
405         kPublicAddress1, this->dispatcher(), true, true, false);
406     peer->set_advertising_data(kPlainAdvDataBytes);
407     peer->set_scan_response(kPlainScanRspBytes);
408     this->test_device()->AddPeer(std::move(peer));
409   }
410   auto peer = this->test_device()->FindPeer(kPublicAddress1);
411 
412   // The callback should get called on timeout waiting for a scan response
413   bool peer_found_callback_called = false;
414   std::unordered_map<DeviceAddress, std::unique_ptr<DynamicByteBuffer>> map;
415 
416   this->set_peer_found_callback([&](const LowEnergyScanResult& result) {
417     peer_found_callback_called = true;
418     map[result.address()] = std::make_unique<DynamicByteBuffer>(result.data());
419   });
420 
421   EXPECT_TRUE(this->StartScan(true));
422   this->RunUntilIdle();
423 
424   this->test_device()->SendAdvertisingReport(*peer);
425   this->RunFor(kPwScanResponseTimeout);
426   ASSERT_TRUE(peer_found_callback_called);
427   ASSERT_EQ(1u, map.count(peer->address()));
428   EXPECT_EQ(kPlainAdvDataBytes.ToString(), map[peer->address()]->ToString());
429 
430   peer_found_callback_called = false;
431   this->test_device()->SendScanResponseReport(*peer);
432   this->RunUntilIdle();
433   ASSERT_FALSE(peer_found_callback_called);
434 }
435 
TYPED_TEST(LowEnergyScannerTest,ActiveScanResults)436 TYPED_TEST(LowEnergyScannerTest, ActiveScanResults) {
437   // One of the 6 fake peers is scannable but never sends scan response
438   // packets. That peer doesn't get reported until the end of the scan period.
439   constexpr size_t kExpectedResultCount = 5u;
440 
441   this->AddFakePeers();
442 
443   std::map<DeviceAddress, LowEnergyScanResult> results;
444   this->set_peer_found_callback([&](const LowEnergyScanResult& result) {
445     results[result.address()] = result;
446   });
447 
448   // Perform an active scan.
449   EXPECT_TRUE(this->StartScan(true, kPwScanPeriod));
450   EXPECT_EQ(LowEnergyScanner::State::kInitiating, this->scanner()->state());
451 
452   this->RunUntilIdle();
453 
454   ASSERT_EQ(kExpectedResultCount, results.size());
455 
456   // Ending the scan period should notify Fake Peer #4.
457   this->RunFor(kScanPeriod);
458   EXPECT_EQ(LowEnergyScanner::ScanStatus::kComplete, this->last_scan_status());
459   ASSERT_EQ(kExpectedResultCount + 1, results.size());
460 
461   // Verify the 6 results against the fake peers that were set up by
462   // this->AddFakePeers(). Since the scan period ended naturally,
463   // LowEnergyScanner should generate a peer found event for all pending reports
464   // even if a scan response was not received for a scannable peer (see Fake
465   // Peer 4, i.e. kRandomAddress3).
466 
467   // Result 0 (ADV_IND)
468   {
469     const auto& iter = results.find(kPublicAddress1);
470     ASSERT_NE(iter, results.end());
471     EXPECT_EQ(kAdvDataAndScanRsp, iter->second.data().ToString());
472     EXPECT_EQ(kPublicAddress1, iter->second.address());
473     EXPECT_TRUE(iter->second.connectable());
474     results.erase(iter);
475   }
476 
477   // Result 1 (ADV_SCAN_IND)
478   {
479     const auto& iter = results.find(kRandomAddress1);
480     ASSERT_NE(iter, results.end());
481     EXPECT_EQ(kAdvDataAndScanRsp, iter->second.data().ToString());
482     EXPECT_EQ(kRandomAddress1, iter->second.address());
483     EXPECT_FALSE(iter->second.connectable());
484     results.erase(iter);
485   }
486 
487   // Result 2 (ADV_IND), empty scan response
488   {
489     const auto& iter = results.find(kPublicAddress2);
490     ASSERT_NE(iter, results.end());
491     EXPECT_EQ(kPlainAdvData, iter->second.data().ToString());
492     EXPECT_EQ(kPublicAddress2, iter->second.address());
493     EXPECT_TRUE(iter->second.connectable());
494     results.erase(iter);
495   }
496 
497   // Result 3 (ADV_IND), empty advertising data w/ scan response
498   {
499     const auto& iter = results.find(kRandomAddress2);
500     ASSERT_NE(iter, results.end());
501     EXPECT_EQ(kPlainScanRsp, iter->second.data().ToString());
502     EXPECT_EQ(kRandomAddress2, iter->second.address());
503     EXPECT_TRUE(iter->second.connectable());
504     results.erase(iter);
505   }
506 
507   // Result 4 (ADV_IND), no scan response
508   {
509     const auto& iter = results.find(kRandomAddress3);
510     ASSERT_NE(iter, results.end());
511     EXPECT_EQ(kPlainAdvData, iter->second.data().ToString());
512     EXPECT_EQ(kRandomAddress3, iter->second.address());
513     EXPECT_TRUE(iter->second.connectable());
514     results.erase(iter);
515   }
516 
517   // Result 5 (ADV_NONCONN_IND)
518   {
519     const auto& iter = results.find(kRandomAddress4);
520     ASSERT_NE(iter, results.end());
521     EXPECT_EQ(kPlainAdvData, iter->second.data().ToString());
522     EXPECT_EQ(kRandomAddress4, iter->second.address());
523     EXPECT_FALSE(iter->second.connectable());
524     results.erase(iter);
525   }
526 
527   // No other reports are expected
528   EXPECT_TRUE(results.empty());
529 }
530 
TYPED_TEST(LowEnergyScannerTest,StopDuringActiveScan)531 TYPED_TEST(LowEnergyScannerTest, StopDuringActiveScan) {
532   this->AddFakePeers();
533 
534   std::map<DeviceAddress, LowEnergyScanResult> results;
535   this->set_peer_found_callback([&results](const LowEnergyScanResult& result) {
536     results[result.address()] = result;
537   });
538 
539   // Perform an active scan indefinitely. This means that the scan period will
540   // never complete by itself.
541   EXPECT_TRUE(this->StartScan(true));
542   EXPECT_EQ(LowEnergyScanner::State::kInitiating, this->scanner()->state());
543   this->RunUntilIdle();
544   EXPECT_EQ(LowEnergyScanner::State::kActiveScanning, this->scanner()->state());
545 
546   // Run the loop until we've seen an event for the last peer that we
547   // added. Fake Peer kRandomAddress3 is scannable but it never sends a scan
548   // response so we expect that to remain in the scanner's pending reports list.
549   this->RunUntilIdle();
550   EXPECT_EQ(5u, results.size());
551   EXPECT_EQ(results.find(kRandomAddress3), results.end());
552 
553   // Stop the scan. Since we are terminating the scan period early,
554   // LowEnergyScanner should not send a report for the pending peer.
555   EXPECT_TRUE(this->scanner()->StopScan());
556   this->RunUntilIdle();
557   EXPECT_TRUE(this->scanner()->IsIdle());
558 
559   EXPECT_EQ(5u, results.size());
560   EXPECT_EQ(results.find(kRandomAddress3), results.end());
561 }
562 
TYPED_TEST(LowEnergyScannerTest,PassiveScanResults)563 TYPED_TEST(LowEnergyScannerTest, PassiveScanResults) {
564   constexpr size_t kExpectedResultCount = 6u;
565   this->AddFakePeers();
566 
567   std::map<DeviceAddress, LowEnergyScanResult> results;
568   this->set_peer_found_callback([&](const LowEnergyScanResult& result) {
569     results[result.address()] = result;
570   });
571 
572   // Perform a passive scan.
573   EXPECT_TRUE(this->StartScan(false));
574 
575   EXPECT_EQ(LowEnergyScanner::State::kInitiating, this->scanner()->state());
576 
577   this->RunUntilIdle();
578   EXPECT_EQ(LowEnergyScanner::State::kPassiveScanning,
579             this->scanner()->state());
580   EXPECT_EQ(LowEnergyScanner::ScanStatus::kPassive, this->last_scan_status());
581   ASSERT_EQ(kExpectedResultCount, results.size());
582 
583   // Verify the 6 results against the fake peers that were set up by
584   // this->AddFakePeers(). All Scan Response PDUs should have been ignored.
585 
586   // Result 0
587   {
588     const auto& iter = results.find(kPublicAddress1);
589     ASSERT_NE(iter, results.end());
590     EXPECT_EQ(kPlainAdvData, iter->second.data().ToString());
591     EXPECT_EQ(kPublicAddress1, iter->second.address());
592     EXPECT_TRUE(iter->second.connectable());
593     results.erase(iter);
594   }
595 
596   // Result 1
597   {
598     const auto& iter = results.find(kRandomAddress1);
599     ASSERT_NE(iter, results.end());
600     EXPECT_EQ(kPlainAdvData, iter->second.data().ToString());
601     EXPECT_EQ(kRandomAddress1, iter->second.address());
602     EXPECT_FALSE(iter->second.connectable());
603     results.erase(iter);
604   }
605 
606   // Result 2
607   {
608     const auto& iter = results.find(kPublicAddress2);
609     ASSERT_NE(iter, results.end());
610     EXPECT_EQ(kPlainAdvData, iter->second.data().ToString());
611     EXPECT_EQ(kPublicAddress2, iter->second.address());
612     EXPECT_TRUE(iter->second.connectable());
613     results.erase(iter);
614   }
615 
616   // Result 3
617   {
618     const auto& iter = results.find(kRandomAddress2);
619     ASSERT_NE(iter, results.end());
620     EXPECT_EQ("", iter->second.data().ToString());
621     EXPECT_EQ(kRandomAddress2, iter->second.address());
622     EXPECT_TRUE(iter->second.connectable());
623     results.erase(iter);
624   }
625 
626   // Result 4
627   {
628     const auto& iter = results.find(kRandomAddress3);
629     ASSERT_NE(iter, results.end());
630     EXPECT_EQ(kPlainAdvData, iter->second.data().ToString());
631     EXPECT_EQ(kRandomAddress3, iter->second.address());
632     EXPECT_TRUE(iter->second.connectable());
633     results.erase(iter);
634   }
635 
636   // Result 5
637   {
638     const auto& iter = results.find(kRandomAddress4);
639     ASSERT_NE(iter, results.end());
640     EXPECT_EQ(kPlainAdvData, iter->second.data().ToString());
641     EXPECT_EQ(kRandomAddress4, iter->second.address());
642     EXPECT_FALSE(iter->second.connectable());
643     results.erase(iter);
644   }
645 
646   EXPECT_TRUE(results.empty());
647 }
648 
TYPED_TEST(LowEnergyScannerTest,DirectedReport)649 TYPED_TEST(LowEnergyScannerTest, DirectedReport) {
650   const auto& kPublicUnresolved = kPublicAddress1;
651   const auto& kPublicResolved = kPublicAddress2;
652   const auto& kRandomUnresolved = kRandomAddress1;
653   const auto& kRandomResolved = kRandomAddress2;
654   constexpr size_t kExpectedResultCount = 4u;
655 
656   // Unresolved public.
657   auto fake_peer = std::make_unique<FakePeer>(
658       kPublicUnresolved, this->dispatcher(), true, false);
659   fake_peer->set_directed_advertising_enabled(true);
660   this->test_device()->AddPeer(std::move(fake_peer));
661 
662   // Unresolved random.
663   fake_peer = std::make_unique<FakePeer>(
664       kRandomUnresolved, this->dispatcher(), true, false);
665   fake_peer->set_directed_advertising_enabled(true);
666   this->test_device()->AddPeer(std::move(fake_peer));
667 
668   // Resolved public.
669   fake_peer = std::make_unique<FakePeer>(
670       kPublicResolved, this->dispatcher(), true, false);
671   fake_peer->set_address_resolved(true);
672   fake_peer->set_directed_advertising_enabled(true);
673   this->test_device()->AddPeer(std::move(fake_peer));
674 
675   // Resolved random.
676   fake_peer = std::make_unique<FakePeer>(
677       kRandomResolved, this->dispatcher(), true, false);
678   fake_peer->set_address_resolved(true);
679   fake_peer->set_directed_advertising_enabled(true);
680   this->test_device()->AddPeer(std::move(fake_peer));
681 
682   std::unordered_map<DeviceAddress, LowEnergyScanResult> results;
683   this->set_directed_adv_callback([&](const LowEnergyScanResult& result) {
684     results[result.address()] = result;
685   });
686 
687   EXPECT_TRUE(this->StartScan(true));
688   EXPECT_EQ(LowEnergyScanner::State::kInitiating, this->scanner()->state());
689 
690   this->RunUntilIdle();
691 
692   ASSERT_EQ(LowEnergyScanner::ScanStatus::kActive, this->last_scan_status());
693   ASSERT_EQ(kExpectedResultCount, results.size());
694 
695   ASSERT_TRUE(results.count(kPublicUnresolved));
696   EXPECT_FALSE(results[kPublicUnresolved].resolved());
697 
698   ASSERT_TRUE(results.count(kRandomUnresolved));
699   EXPECT_FALSE(results[kRandomUnresolved].resolved());
700 
701   ASSERT_TRUE(results.count(kPublicResolved));
702   EXPECT_TRUE(results[kPublicResolved].resolved());
703 
704   ASSERT_TRUE(results.count(kRandomResolved));
705   EXPECT_TRUE(results[kRandomResolved].resolved());
706 }
707 
TYPED_TEST(LowEnergyScannerTest,AllowsRandomAddressChange)708 TYPED_TEST(LowEnergyScannerTest, AllowsRandomAddressChange) {
709   EXPECT_TRUE(this->scanner()->AllowsRandomAddressChange());
710   EXPECT_TRUE(this->StartScan(false));
711 
712   // Address change should not be allowed while the procedure is pending.
713   EXPECT_TRUE(this->scanner()->IsInitiating());
714   EXPECT_FALSE(this->scanner()->AllowsRandomAddressChange());
715 
716   this->RunUntilIdle();
717   EXPECT_TRUE(this->scanner()->IsPassiveScanning());
718   EXPECT_FALSE(this->scanner()->AllowsRandomAddressChange());
719 }
720 
TYPED_TEST(LowEnergyScannerTest,AllowsRandomAddressChangeWhileRequestingLocalAddress)721 TYPED_TEST(LowEnergyScannerTest,
722            AllowsRandomAddressChangeWhileRequestingLocalAddress) {
723   // Make the local address delegate report its result asynchronously.
724   this->fake_address_delegate()->set_async(true);
725   EXPECT_TRUE(this->StartScan(false));
726 
727   // The scanner should be in the initiating state without initiating controller
728   // procedures that would prevent a local address change.
729   EXPECT_TRUE(this->scanner()->IsInitiating());
730   EXPECT_TRUE(this->scanner()->AllowsRandomAddressChange());
731 
732   this->RunUntilIdle();
733   EXPECT_TRUE(this->scanner()->IsPassiveScanning());
734   EXPECT_FALSE(this->scanner()->AllowsRandomAddressChange());
735 }
736 
TYPED_TEST(LowEnergyScannerTest,ScanUsingPublicAddress)737 TYPED_TEST(LowEnergyScannerTest, ScanUsingPublicAddress) {
738   this->fake_address_delegate()->set_local_address(kPublicAddress1);
739   EXPECT_TRUE(this->StartScan(false));
740   this->RunUntilIdle();
741   EXPECT_TRUE(this->scanner()->IsPassiveScanning());
742   EXPECT_EQ(pw::bluetooth::emboss::LEOwnAddressType::PUBLIC,
743             this->test_device()->le_scan_state().own_address_type);
744 }
745 
TYPED_TEST(LowEnergyScannerTest,ScanUsingRandomAddress)746 TYPED_TEST(LowEnergyScannerTest, ScanUsingRandomAddress) {
747   this->fake_address_delegate()->set_local_address(kRandomAddress1);
748   // Public address would be used if privacy was disabled
749   this->fake_address_delegate()->EnablePrivacy(true);
750   EXPECT_TRUE(this->StartScan(false));
751   this->RunUntilIdle();
752   EXPECT_TRUE(this->scanner()->IsPassiveScanning());
753   EXPECT_EQ(pw::bluetooth::emboss::LEOwnAddressType::RANDOM,
754             this->test_device()->le_scan_state().own_address_type);
755 }
756 
TYPED_TEST(LowEnergyScannerTest,StopScanWhileWaitingForLocalAddress)757 TYPED_TEST(LowEnergyScannerTest, StopScanWhileWaitingForLocalAddress) {
758   this->fake_address_delegate()->set_async(true);
759   EXPECT_TRUE(this->StartScan(false));
760 
761   // Should be waiting for the random address.
762   EXPECT_TRUE(this->scanner()->IsInitiating());
763   EXPECT_TRUE(this->scanner()->AllowsRandomAddressChange());
764 
765   EXPECT_TRUE(this->scanner()->StopScan());
766   this->RunUntilIdle();
767 
768   // Should end up not scanning.
769   EXPECT_TRUE(this->scanner()->IsIdle());
770   EXPECT_FALSE(this->test_device()->le_scan_state().enabled);
771 }
772 
TYPED_TEST(LowEnergyScannerTest,CallbackStopsScanning)773 TYPED_TEST(LowEnergyScannerTest, CallbackStopsScanning) {
774   auto fake_peer = std::make_unique<FakePeer>(
775       kRandomAddress1, this->dispatcher(), true, false);
776   fake_peer->set_advertising_data(kPlainAdvDataBytes);
777   this->test_device()->AddPeer(std::move(fake_peer));
778 
779   fake_peer = std::make_unique<FakePeer>(
780       kRandomAddress2, this->dispatcher(), true, false);
781   fake_peer->set_advertising_data(kPlainAdvDataBytes);
782   this->test_device()->AddPeer(std::move(fake_peer));
783 
784   // We should be able to stop scanning in the callback and not crash. Note: if
785   // crashing, it will likely be due to a use-after-free type bug. Such a bug
786   // may or may not manifest itself in a non-asan build.
787   this->set_peer_found_callback(
788       [&](const LowEnergyScanResult&) { this->scanner()->StopScan(); });
789 
790   EXPECT_TRUE(this->StartScan(true, kPwScanPeriod));
791   this->RunFor(kScanPeriod);
792 }
793 
794 }  // namespace bt::hci
795