xref: /aosp_15_r20/external/pigweed/pw_bluetooth_sapphire/host/gap/low_energy_discovery_manager_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/gap/low_energy_discovery_manager.h"
16 
17 #include <gmock/gmock.h>
18 
19 #include <unordered_set>
20 #include <vector>
21 
22 #include "pw_bluetooth_sapphire/internal/host/common/advertising_data.h"
23 #include "pw_bluetooth_sapphire/internal/host/common/assert.h"
24 #include "pw_bluetooth_sapphire/internal/host/common/macros.h"
25 #include "pw_bluetooth_sapphire/internal/host/gap/peer.h"
26 #include "pw_bluetooth_sapphire/internal/host/gap/peer_cache.h"
27 #include "pw_bluetooth_sapphire/internal/host/hci/fake_local_address_delegate.h"
28 #include "pw_bluetooth_sapphire/internal/host/hci/legacy_low_energy_scanner.h"
29 #include "pw_bluetooth_sapphire/internal/host/testing/controller_test.h"
30 #include "pw_bluetooth_sapphire/internal/host/testing/fake_controller.h"
31 #include "pw_bluetooth_sapphire/internal/host/testing/fake_peer.h"
32 #include "pw_bluetooth_sapphire/internal/host/testing/inspect.h"
33 #include "pw_bluetooth_sapphire/internal/host/testing/test_helpers.h"
34 
35 namespace bt::gap {
36 namespace {
37 
38 using namespace inspect::testing;
39 using bt::testing::FakeController;
40 using bt::testing::FakePeer;
41 using PauseToken = LowEnergyDiscoveryManager::PauseToken;
42 
43 using TestingBase = bt::testing::FakeDispatcherControllerTest<FakeController>;
44 
45 const DeviceAddress kAddress0(DeviceAddress::Type::kLEPublic, {0});
46 const DeviceAddress kAddrAlias0(DeviceAddress::Type::kBREDR, kAddress0.value());
47 const DeviceAddress kAddress1(DeviceAddress::Type::kLERandom, {1});
48 const DeviceAddress kAddress2(DeviceAddress::Type::kLEPublic, {2});
49 const DeviceAddress kAddress3(DeviceAddress::Type::kLEPublic, {3});
50 const DeviceAddress kAddress4(DeviceAddress::Type::kLEPublic, {4});
51 const DeviceAddress kAddress5(DeviceAddress::Type::kLEPublic, {5});
52 
53 constexpr uint16_t kServiceDataUuid = 0x1234;
54 
55 constexpr pw::chrono::SystemClock::duration kTestScanPeriod =
56     std::chrono::seconds(10);
57 
58 const char* kInspectNodeName = "low_energy_discovery_manager";
59 
60 class LowEnergyDiscoveryManagerTest : public TestingBase {
61  public:
62   LowEnergyDiscoveryManagerTest() = default;
63   ~LowEnergyDiscoveryManagerTest() override = default;
64 
SetUp()65   void SetUp() override {
66     TestingBase::SetUp();
67 
68     scan_enabled_ = false;
69 
70     FakeController::Settings settings;
71     settings.ApplyLegacyLEConfig();
72     test_device()->set_settings(settings);
73 
74     // TODO(armansito): Now that the hci::LowEnergyScanner is injected into
75     // |discovery_manager_| rather than constructed by it, a fake implementation
76     // could be injected directly. Consider providing fake behavior here in this
77     // harness rather than using a FakeController.
78     scanner_ = std::make_unique<hci::LegacyLowEnergyScanner>(
79         &fake_address_delegate_, transport()->GetWeakPtr(), dispatcher());
80     discovery_manager_ = std::make_unique<LowEnergyDiscoveryManager>(
81         scanner_.get(), &peer_cache_, dispatcher());
82     discovery_manager_->AttachInspect(inspector_.GetRoot(), kInspectNodeName);
83 
84     test_device()->set_scan_state_callback(
85         std::bind(&LowEnergyDiscoveryManagerTest::OnScanStateChanged,
86                   this,
87                   std::placeholders::_1));
88   }
89 
TearDown()90   void TearDown() override {
91     if (discovery_manager_) {
92       discovery_manager_ = nullptr;
93     }
94     scanner_ = nullptr;
95     test_device()->Stop();
96     TestingBase::TearDown();
97   }
98 
99  protected:
discovery_manager() const100   LowEnergyDiscoveryManager* discovery_manager() const {
101     return discovery_manager_.get();
102   }
103 
104   // Deletes |discovery_manager_|.
DeleteDiscoveryManager()105   void DeleteDiscoveryManager() { discovery_manager_ = nullptr; }
106 
107 #ifndef NINSPECT
InspectHierarchy() const108   inspect::Hierarchy InspectHierarchy() const {
109     return inspect::ReadFromVmo(inspector_.DuplicateVmo()).take_value();
110   }
111 
InspectProperties() const112   std::vector<inspect::PropertyValue> InspectProperties() const {
113     auto hierarchy = InspectHierarchy();
114     auto children = hierarchy.take_children();
115     PW_CHECK(children.size() == 1u);
116     return children.front().node_ptr()->take_properties();
117   }
118 #endif  // NINSPECT
119 
peer_cache()120   PeerCache* peer_cache() { return &peer_cache_; }
121 
122   // Returns the last reported scan state of the FakeController.
scan_enabled() const123   bool scan_enabled() const { return scan_enabled_; }
124 
125   // The scan states that the FakeController has transitioned through.
scan_states() const126   const std::vector<bool> scan_states() const { return scan_states_; }
127 
128   // Sets a callback that will run when the scan state transitions |count|
129   // times.
set_scan_state_handler(size_t count,fit::closure callback)130   void set_scan_state_handler(size_t count, fit::closure callback) {
131     scan_state_callbacks_[count] = std::move(callback);
132   }
133 
134   // Called by FakeController when the scan state changes.
OnScanStateChanged(bool enabled)135   void OnScanStateChanged(bool enabled) {
136     auto scan_type = test_device()->le_scan_state().scan_type;
137     bt_log(DEBUG,
138            "gap-test",
139            "FakeController scan state: %s %s",
140            enabled ? "enabled" : "disabled",
141            scan_type == pw::bluetooth::emboss::LEScanType::ACTIVE ? "active"
142                                                                   : "passive");
143     scan_enabled_ = enabled;
144     scan_states_.push_back(enabled);
145 
146     auto iter = scan_state_callbacks_.find(scan_states_.size());
147     if (iter != scan_state_callbacks_.end()) {
148       iter->second();
149     }
150   }
151 
152   // Registers the following fake peers with the FakeController:
153   //
154   // Peer 0:
155   //   - Connectable, not scannable;
156   //   - General discoverable;
157   //   - UUIDs: 0x180d, 0x180f;
158   //   - Service Data UUIDs: kServiceDataUuid;
159   //   - has name: "Device 0"
160   //
161   // Peer 1:
162   //   - Connectable, not scannable;
163   //   - Limited discoverable;
164   //   - UUIDs: 0x180d;
165   //   - has name: "Device 1"
166   //
167   // Peer 2:
168   //   - Not connectable, not scannable;
169   //   - General discoverable;
170   //   - UUIDs: none;
171   //   - has name: "Device 2"
172   //
173   // Peer 3:
174   //   - Not discoverable;
AddFakePeers()175   void AddFakePeers() {
176     // Peer 0
177     const StaticByteBuffer kAdvData0(
178         // Flags
179         0x02,
180         0x01,
181         0x02,
182 
183         // Complete 16-bit service UUIDs
184         0x05,
185         0x03,
186         0x0d,
187         0x18,
188         0x0f,
189         0x18,
190 
191         // 16-bit service data UUID
192         0x03,
193         DataType::kServiceData16Bit,
194         LowerBits(kServiceDataUuid),
195         UpperBits(kServiceDataUuid),
196 
197         // Complete local name
198         0x09,
199         0x09,
200         'D',
201         'e',
202         'v',
203         'i',
204         'c',
205         'e',
206         ' ',
207         '0');
208     auto fake_peer =
209         std::make_unique<FakePeer>(kAddress0, dispatcher(), true, true);
210     fake_peer->set_advertising_data(kAdvData0);
211     test_device()->AddPeer(std::move(fake_peer));
212 
213     // Peer 1
214     const StaticByteBuffer kAdvData1(
215         // Flags
216         0x02,
217         0x01,
218         0x01,
219 
220         // Complete 16-bit service UUIDs
221         0x03,
222         0x03,
223         0x0d,
224         0x18);
225     fake_peer = std::make_unique<FakePeer>(kAddress1, dispatcher(), true, true);
226     fake_peer->set_advertising_data(kAdvData1);
227     test_device()->AddPeer(std::move(fake_peer));
228 
229     // Peer 2
230     const StaticByteBuffer kAdvData2(
231         // Flags
232         0x02,
233         0x01,
234         0x02,
235 
236         // Complete local name
237         0x09,
238         0x09,
239         'D',
240         'e',
241         'v',
242         'i',
243         'c',
244         'e',
245         ' ',
246         '2');
247     fake_peer =
248         std::make_unique<FakePeer>(kAddress2, dispatcher(), false, false);
249     fake_peer->set_advertising_data(kAdvData2);
250     test_device()->AddPeer(std::move(fake_peer));
251 
252     // Peer 3
253     const StaticByteBuffer kAdvData3(
254         // Flags
255         0x02,
256         0x01,
257         0x00,
258 
259         // Complete local name
260         0x09,
261         0x09,
262         'D',
263         'e',
264         'v',
265         'i',
266         'c',
267         'e',
268         ' ',
269         '3');
270     fake_peer =
271         std::make_unique<FakePeer>(kAddress3, dispatcher(), false, false);
272     fake_peer->set_advertising_data(kAdvData3);
273     test_device()->AddPeer(std::move(fake_peer));
274   }
275 
276   // Creates and returns a discovery session.
StartDiscoverySession(bool active=true)277   std::unique_ptr<LowEnergyDiscoverySession> StartDiscoverySession(
278       bool active = true) {
279     std::unique_ptr<LowEnergyDiscoverySession> session;
280     discovery_manager()->StartDiscovery(active, [&](auto cb_session) {
281       PW_CHECK(cb_session);
282       session = std::move(cb_session);
283     });
284 
285     RunUntilIdle();
286     PW_CHECK(session);
287     return session;
288   }
289 
290  private:
291   PeerCache peer_cache_{dispatcher()};
292   hci::FakeLocalAddressDelegate fake_address_delegate_{dispatcher()};
293   std::unique_ptr<hci::LegacyLowEnergyScanner> scanner_;
294   std::unique_ptr<LowEnergyDiscoveryManager> discovery_manager_;
295 
296   bool scan_enabled_;
297   std::vector<bool> scan_states_;
298   std::unordered_map<size_t, fit::closure> scan_state_callbacks_;
299 
300   inspect::Inspector inspector_;
301 
302   BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(LowEnergyDiscoveryManagerTest);
303 };
304 
305 using GAP_LowEnergyDiscoveryManagerTest = LowEnergyDiscoveryManagerTest;
306 
TEST_F(LowEnergyDiscoveryManagerTest,StartDiscoveryAndStop)307 TEST_F(LowEnergyDiscoveryManagerTest, StartDiscoveryAndStop) {
308   std::unique_ptr<LowEnergyDiscoverySession> session;
309   discovery_manager()->StartDiscovery(
310       /*active=*/true,
311       [&session](auto cb_session) { session = std::move(cb_session); });
312 
313   RunUntilIdle();
314 
315   // The test fixture will be notified of the change in scan state before we
316   // receive the session.
317   EXPECT_TRUE(scan_enabled());
318   RunUntilIdle();
319 
320   ASSERT_TRUE(session);
321   EXPECT_TRUE(session->alive());
322 
323   session->Stop();
324   EXPECT_FALSE(session->alive());
325 
326   RunUntilIdle();
327   EXPECT_FALSE(scan_enabled());
328 }
329 
TEST_F(LowEnergyDiscoveryManagerTest,StartDiscoveryAndStopByDeleting)330 TEST_F(LowEnergyDiscoveryManagerTest, StartDiscoveryAndStopByDeleting) {
331   // Start discovery but don't acquire ownership of the received session. This
332   // should immediately terminate the session.
333   std::unique_ptr<LowEnergyDiscoverySession> session;
334   discovery_manager()->StartDiscovery(
335       /*active=*/true,
336       [&session](auto cb_session) { session = std::move(cb_session); });
337 
338   RunUntilIdle();
339 
340   // The test fixture will be notified of the change in scan state before we
341   // receive the session.
342   EXPECT_TRUE(scan_enabled());
343   RunUntilIdle();
344 
345   ASSERT_TRUE(session);
346   EXPECT_TRUE(session->alive());
347 
348   session = nullptr;
349 
350   RunUntilIdle();
351   EXPECT_FALSE(scan_enabled());
352 }
353 
TEST_F(LowEnergyDiscoveryManagerTest,Destructor)354 TEST_F(LowEnergyDiscoveryManagerTest, Destructor) {
355   // Start discovery with a session, delete the manager and ensure that the
356   // session is inactive with the error callback called.
357   std::unique_ptr<LowEnergyDiscoverySession> session;
358   discovery_manager()->StartDiscovery(
359       /*active=*/true,
360       [&session](auto cb_session) { session = std::move(cb_session); });
361 
362   RunUntilIdle();
363 
364   EXPECT_TRUE(scan_enabled());
365 
366   ASSERT_TRUE(session);
367   EXPECT_TRUE(session->alive());
368 
369   size_t num_errors = 0u;
370   session->set_error_callback([&num_errors]() { num_errors++; });
371 
372   EXPECT_EQ(0u, num_errors);
373   DeleteDiscoveryManager();
374   EXPECT_EQ(1u, num_errors);
375   EXPECT_FALSE(session->alive());
376 }
377 
TEST_F(LowEnergyDiscoveryManagerTest,StartDiscoveryAndStopInCallback)378 TEST_F(LowEnergyDiscoveryManagerTest, StartDiscoveryAndStopInCallback) {
379   // Start discovery but don't acquire ownership of the received session. This
380   // should terminate the session when |session| goes out of scope.
381   discovery_manager()->StartDiscovery(/*active=*/true, [](auto) {});
382 
383   RunUntilIdle();
384   ASSERT_EQ(2u, scan_states().size());
385   EXPECT_TRUE(scan_states()[0]);
386   EXPECT_FALSE(scan_states()[1]);
387 }
388 
TEST_F(LowEnergyDiscoveryManagerTest,StartDiscoveryFailure)389 TEST_F(LowEnergyDiscoveryManagerTest, StartDiscoveryFailure) {
390   test_device()->SetDefaultResponseStatus(
391       hci_spec::kLESetScanEnable,
392       pw::bluetooth::emboss::StatusCode::COMMAND_DISALLOWED);
393 
394   // |session| should contain nullptr.
395   discovery_manager()->StartDiscovery(
396       /*active=*/true, [](auto session) { EXPECT_FALSE(session); });
397 
398   RunUntilIdle();
399   EXPECT_FALSE(scan_enabled());
400 }
401 
TEST_F(LowEnergyDiscoveryManagerTest,StartDiscoveryWhileScanning)402 TEST_F(LowEnergyDiscoveryManagerTest, StartDiscoveryWhileScanning) {
403   std::vector<std::unique_ptr<LowEnergyDiscoverySession>> sessions;
404 
405   constexpr size_t kExpectedSessionCount = 5;
406   size_t cb_count = 0u;
407   auto cb = [&cb_count, &sessions](auto session) {
408     sessions.push_back(std::move(session));
409     cb_count++;
410   };
411 
412   discovery_manager()->StartDiscovery(/*active=*/true, cb);
413 
414   RunUntilIdle();
415   EXPECT_TRUE(scan_enabled());
416   EXPECT_EQ(1u, sessions.size());
417 
418   // Add the rest of the sessions. These are expected to succeed immediately but
419   // the callbacks should be called asynchronously.
420   for (size_t i = 1u; i < kExpectedSessionCount; i++) {
421     discovery_manager()->StartDiscovery(/*active=*/true, cb);
422   }
423 
424   RunUntilIdle();
425   EXPECT_TRUE(scan_enabled());
426   EXPECT_EQ(kExpectedSessionCount, sessions.size());
427 
428   // Remove one session from the list. Scan should continue.
429   sessions.pop_back();
430   RunUntilIdle();
431   EXPECT_TRUE(scan_enabled());
432 
433   // Remove all but one session from the list. Scan should continue.
434   sessions.erase(sessions.begin() + 1, sessions.end());
435   RunUntilIdle();
436   EXPECT_TRUE(scan_enabled());
437   EXPECT_EQ(1u, sessions.size());
438 
439   // Remove the last session.
440   sessions.clear();
441   RunUntilIdle();
442   EXPECT_FALSE(scan_enabled());
443 }
444 
TEST_F(LowEnergyDiscoveryManagerTest,StartDiscoveryWhilePendingStart)445 TEST_F(LowEnergyDiscoveryManagerTest, StartDiscoveryWhilePendingStart) {
446   std::vector<std::unique_ptr<LowEnergyDiscoverySession>> sessions;
447 
448   constexpr size_t kExpectedSessionCount = 5;
449   size_t cb_count = 0u;
450   auto cb = [&cb_count, &sessions](auto session) {
451     sessions.push_back(std::move(session));
452     cb_count++;
453   };
454 
455   for (size_t i = 0u; i < kExpectedSessionCount; i++) {
456     discovery_manager()->StartDiscovery(/*active=*/true, cb);
457   }
458 
459   RunUntilIdle();
460   EXPECT_TRUE(scan_enabled());
461   EXPECT_EQ(kExpectedSessionCount, sessions.size());
462 
463   // Remove all sessions. This should stop the scan.
464   sessions.clear();
465   RunUntilIdle();
466   EXPECT_FALSE(scan_enabled());
467 }
468 
TEST_F(LowEnergyDiscoveryManagerTest,StartDiscoveryWhilePendingStartAndStopInCallback)469 TEST_F(LowEnergyDiscoveryManagerTest,
470        StartDiscoveryWhilePendingStartAndStopInCallback) {
471   constexpr size_t kExpectedSessionCount = 5;
472   size_t cb_count = 0u;
473   std::unique_ptr<LowEnergyDiscoverySession> session;
474   auto cb = [&cb_count, &session](auto cb_session) {
475     cb_count++;
476     if (cb_count == kExpectedSessionCount) {
477       // Hold on to only the last session object. The rest should get deleted
478       // within the callback.
479       session = std::move(cb_session);
480     }
481   };
482 
483   for (size_t i = 0u; i < kExpectedSessionCount; i++) {
484     discovery_manager()->StartDiscovery(/*active=*/true, cb);
485   }
486 
487   RunUntilIdle();
488   EXPECT_TRUE(scan_enabled());
489   EXPECT_TRUE(session);
490 
491   RunUntilIdle();
492   EXPECT_EQ(kExpectedSessionCount, cb_count);
493   EXPECT_TRUE(scan_enabled());
494 
495   // Deleting the only remaning session should stop the scan.
496   session = nullptr;
497   RunUntilIdle();
498   EXPECT_FALSE(scan_enabled());
499 }
500 
TEST_F(LowEnergyDiscoveryManagerTest,StartDiscoveryWhilePendingStop)501 TEST_F(LowEnergyDiscoveryManagerTest, StartDiscoveryWhilePendingStop) {
502   std::unique_ptr<LowEnergyDiscoverySession> session;
503 
504   discovery_manager()->StartDiscovery(
505       /*active=*/true,
506       [&session](auto cb_session) { session = std::move(cb_session); });
507 
508   RunUntilIdle();
509   EXPECT_TRUE(scan_enabled());
510   EXPECT_TRUE(session);
511 
512   // Stop the session. This should issue a request to stop the ongoing scan but
513   // the request will remain pending until we run the message loop.
514   session = nullptr;
515 
516   // Request a new session. The discovery manager should restart the scan after
517   // the ongoing one stops.
518   discovery_manager()->StartDiscovery(
519       /*active=*/true,
520       [&session](auto cb_session) { session = std::move(cb_session); });
521 
522   // Discovery should stop and start again.
523   RunUntilIdle();
524   ASSERT_EQ(3u, scan_states().size());
525   EXPECT_TRUE(scan_states()[0]);
526   EXPECT_FALSE(scan_states()[1]);
527   EXPECT_TRUE(scan_states()[2]);
528 }
529 
TEST_F(LowEnergyDiscoveryManagerTest,StartDiscoveryFailureManyPending)530 TEST_F(LowEnergyDiscoveryManagerTest, StartDiscoveryFailureManyPending) {
531   test_device()->SetDefaultResponseStatus(
532       hci_spec::kLESetScanEnable,
533       pw::bluetooth::emboss::StatusCode::COMMAND_DISALLOWED);
534 
535   constexpr size_t kExpectedSessionCount = 5;
536   size_t cb_count = 0u;
537   auto cb = [&cb_count](auto session) {
538     // |session| should contain nullptr as the request will fail.
539     EXPECT_FALSE(session);
540     cb_count++;
541   };
542 
543   for (size_t i = 0u; i < kExpectedSessionCount; i++) {
544     discovery_manager()->StartDiscovery(/*active=*/true, cb);
545   }
546 
547   RunUntilIdle();
548   EXPECT_FALSE(scan_enabled());
549 }
550 
TEST_F(LowEnergyDiscoveryManagerTest,ScanPeriodRestart)551 TEST_F(LowEnergyDiscoveryManagerTest, ScanPeriodRestart) {
552   constexpr size_t kNumScanStates = 3;
553 
554   discovery_manager()->set_scan_period(kTestScanPeriod);
555 
556   std::unique_ptr<LowEnergyDiscoverySession> session;
557   discovery_manager()->StartDiscovery(
558       /*active=*/true,
559       [&session](auto cb_session) { session = std::move(cb_session); });
560 
561   // We should observe the scan state become enabled -> disabled -> enabled.
562   RunUntilIdle();
563   EXPECT_TRUE(scan_enabled());
564 
565   // End the scan period.
566   RunFor(kTestScanPeriod);
567   ASSERT_EQ(kNumScanStates, scan_states().size());
568   EXPECT_TRUE(scan_states()[0]);
569   EXPECT_FALSE(scan_states()[1]);
570   EXPECT_TRUE(scan_states()[2]);
571 }
572 
TEST_F(LowEnergyDiscoveryManagerTest,ScanPeriodRestartFailure)573 TEST_F(LowEnergyDiscoveryManagerTest, ScanPeriodRestartFailure) {
574   constexpr size_t kNumScanStates = 2;
575 
576   discovery_manager()->set_scan_period(kTestScanPeriod);
577 
578   std::unique_ptr<LowEnergyDiscoverySession> session;
579   bool session_error = false;
580   discovery_manager()->StartDiscovery(/*active=*/true, [&](auto cb_session) {
581     session = std::move(cb_session);
582     session->set_error_callback([&session_error] { session_error = true; });
583   });
584 
585   // The controller will fail to restart scanning after scanning stops at the
586   // end of the period. The scan state will transition twice (-> enabled ->
587   // disabled).
588   set_scan_state_handler(kNumScanStates, [this] {
589     test_device()->SetDefaultResponseStatus(
590         hci_spec::kLESetScanEnable,
591         pw::bluetooth::emboss::StatusCode::COMMAND_DISALLOWED);
592   });
593 
594   RunUntilIdle();
595   EXPECT_TRUE(scan_enabled());
596 
597   // End the scan period. The scan should not restart.
598   RunFor(kTestScanPeriod);
599 
600   ASSERT_EQ(kNumScanStates, scan_states().size());
601   EXPECT_TRUE(scan_states()[0]);
602   EXPECT_FALSE(scan_states()[1]);
603   EXPECT_TRUE(session_error);
604 }
605 
TEST_F(LowEnergyDiscoveryManagerTest,ScanPeriodRestartRemoveSession)606 TEST_F(LowEnergyDiscoveryManagerTest, ScanPeriodRestartRemoveSession) {
607   constexpr size_t kNumScanStates = 4;
608 
609   discovery_manager()->set_scan_period(kTestScanPeriod);
610 
611   std::unique_ptr<LowEnergyDiscoverySession> session;
612   discovery_manager()->StartDiscovery(
613       /*active=*/true,
614       [&session](auto cb_session) { session = std::move(cb_session); });
615 
616   // We should observe 3 scan state transitions (-> enabled -> disabled ->
617   // enabled).
618   set_scan_state_handler(kNumScanStates - 1, [this, &session] {
619     ASSERT_TRUE(session);
620     EXPECT_TRUE(scan_enabled());
621 
622     // At this point the fake controller has updated its state but the discovery
623     // manager has not processed the restarted scan. We should be able to remove
624     // the current session and the state should ultimately become disabled.
625     session->Stop();
626   });
627 
628   RunUntilIdle();
629   EXPECT_TRUE(scan_enabled());
630 
631   // End the scan period.
632   RunFor(kTestScanPeriod);
633   EXPECT_THAT(scan_states(), ::testing::ElementsAre(true, false, true, false));
634 }
635 
TEST_F(LowEnergyDiscoveryManagerTest,ScanPeriodRemoveSessionDuringRestart)636 TEST_F(LowEnergyDiscoveryManagerTest, ScanPeriodRemoveSessionDuringRestart) {
637   constexpr size_t kNumScanStates = 2;
638 
639   // Set a very short scan period for the sake of the test.
640   discovery_manager()->set_scan_period(kTestScanPeriod);
641 
642   std::unique_ptr<LowEnergyDiscoverySession> session;
643   discovery_manager()->StartDiscovery(
644       /*active=*/true,
645       [&session](auto cb_session) { session = std::move(cb_session); });
646 
647   // The controller will fail to restart scanning after scanning stops at the
648   // end of the period. The scan state will transition twice (-> enabled ->
649   // disabled).
650   set_scan_state_handler(kNumScanStates, [this, &session] {
651     ASSERT_TRUE(session);
652     EXPECT_FALSE(scan_enabled());
653 
654     // Stop the session before the discovery manager processes the event. It
655     // should detect this and discontinue the scan.
656     session->Stop();
657   });
658 
659   RunUntilIdle();
660   EXPECT_TRUE(scan_enabled());
661 
662   // End the scan period.
663   RunFor(kTestScanPeriod);
664   EXPECT_THAT(scan_states(), ::testing::ElementsAre(true, false));
665 }
666 
TEST_F(LowEnergyDiscoveryManagerTest,ScanPeriodRestartRemoveAndAddSession)667 TEST_F(LowEnergyDiscoveryManagerTest, ScanPeriodRestartRemoveAndAddSession) {
668   constexpr size_t kNumScanPeriodRestartStates = 3;
669   constexpr size_t kTotalNumStates = 5;
670 
671   // Set a very short scan period for the sake of the test.
672   discovery_manager()->set_scan_period(kTestScanPeriod);
673 
674   std::unique_ptr<LowEnergyDiscoverySession> session;
675   auto cb = [&session](auto cb_session) { session = std::move(cb_session); };
676   discovery_manager()->StartDiscovery(/*active=*/true, cb);
677 
678   // We should observe 3 scan state transitions (-> enabled -> disabled ->
679   // enabled).
680   set_scan_state_handler(kNumScanPeriodRestartStates, [this, &session, cb] {
681     ASSERT_TRUE(session);
682     EXPECT_TRUE(scan_enabled());
683 
684     // At this point the fake controller has updated its state but the discovery
685     // manager has not processed the restarted scan. We should be able to remove
686     // the current session and create a new one and the state should update
687     // accordingly.
688     session->Stop();
689     discovery_manager()->StartDiscovery(/*active=*/true, cb);
690   });
691 
692   RunUntilIdle();
693   EXPECT_TRUE(scan_enabled());
694 
695   // End the scan period.
696   RunFor(kTestScanPeriod);
697 
698   // Scan should have been disabled and re-enabled.
699   ASSERT_EQ(kTotalNumStates, scan_states().size());
700   EXPECT_TRUE(scan_states()[0]);
701   EXPECT_FALSE(scan_states()[1]);
702   EXPECT_TRUE(scan_states()[2]);
703 }
704 
TEST_F(LowEnergyDiscoveryManagerTest,StartDiscoveryWithFilters)705 TEST_F(LowEnergyDiscoveryManagerTest, StartDiscoveryWithFilters) {
706   AddFakePeers();
707 
708   std::vector<std::unique_ptr<LowEnergyDiscoverySession>> sessions;
709 
710   // Set a short scan period so that we that we process events for multiple scan
711   // periods during the test.
712   discovery_manager()->set_scan_period(std::chrono::milliseconds(200));
713 
714   // Session 0 is interested in performing general discovery.
715   std::unordered_set<DeviceAddress> peers_session0;
716   LowEnergyDiscoverySession::PeerFoundCallback result_cb =
717       [&peers_session0](const auto& peer) {
718         peers_session0.insert(peer.address());
719       };
720   sessions.push_back(StartDiscoverySession());
721   sessions[0]->filter()->SetGeneralDiscoveryFlags();
722   sessions[0]->SetResultCallback(std::move(result_cb));
723 
724   // Session 1 is interested in performing limited discovery.
725   std::unordered_set<DeviceAddress> peers_session1;
726   result_cb = [&peers_session1](const auto& peer) {
727     peers_session1.insert(peer.address());
728   };
729   sessions.push_back(StartDiscoverySession());
730   sessions[1]->filter()->set_flags(
731       static_cast<uint8_t>(AdvFlag::kLELimitedDiscoverableMode));
732   sessions[1]->SetResultCallback(std::move(result_cb));
733 
734   // Session 2 is interested in peers with UUID 0x180d.
735   std::unordered_set<DeviceAddress> peers_session2;
736   result_cb = [&peers_session2](const auto& peer) {
737     peers_session2.insert(peer.address());
738   };
739   sessions.push_back(StartDiscoverySession());
740 
741   uint16_t uuid = 0x180d;
742   sessions[2]->filter()->set_service_uuids({UUID(uuid)});
743   sessions[2]->SetResultCallback(std::move(result_cb));
744 
745   // Session 3 is interested in peers whose names contain "Device".
746   std::unordered_set<DeviceAddress> peers_session3;
747   result_cb = [&peers_session3](const auto& peer) {
748     peers_session3.insert(peer.address());
749   };
750   sessions.push_back(StartDiscoverySession());
751   sessions[3]->filter()->set_name_substring("Device");
752   sessions[3]->SetResultCallback(std::move(result_cb));
753 
754   // Session 4 is interested in non-connectable peers.
755   std::unordered_set<DeviceAddress> peers_session4;
756   result_cb = [&peers_session4](const auto& peer) {
757     peers_session4.insert(peer.address());
758   };
759   sessions.push_back(StartDiscoverySession());
760   sessions[4]->filter()->set_connectable(false);
761   sessions[4]->SetResultCallback(std::move(result_cb));
762 
763   // Session 5 is interested in peers with UUID 0x180d and service data UUID
764   // 0x1234.
765   std::unordered_set<DeviceAddress> peers_session5;
766   result_cb = [&peers_session5](const auto& peer) {
767     peers_session5.insert(peer.address());
768   };
769   sessions.push_back(StartDiscoverySession());
770 
771   sessions[5]->filter()->set_service_uuids({UUID(uuid)});
772   sessions[5]->filter()->set_service_data_uuids({UUID(kServiceDataUuid)});
773   sessions[5]->SetResultCallback(std::move(result_cb));
774 
775   RunUntilIdle();
776 
777   EXPECT_EQ(6u, sessions.size());
778 
779   // At this point all sessions should have processed all peers at least once.
780 
781   // Session 0: Should have seen all peers except for peer 3, which is
782   // non-discoverable.
783   EXPECT_EQ(3u, peers_session0.size());
784   EXPECT_THAT(peers_session0, ::testing::Contains(kAddress0));
785   EXPECT_THAT(peers_session0, ::testing::Contains(kAddress1));
786   EXPECT_THAT(peers_session0, ::testing::Contains(kAddress2));
787 
788   // Session 1: Should have only seen peer 1.
789   EXPECT_EQ(1u, peers_session1.size());
790   EXPECT_THAT(peers_session1, ::testing::Contains(kAddress1));
791 
792   // Session 2: Should have only seen peers 0 and 1
793   EXPECT_EQ(2u, peers_session2.size());
794   EXPECT_THAT(peers_session2, ::testing::Contains(kAddress0));
795   EXPECT_THAT(peers_session2, ::testing::Contains(kAddress1));
796 
797   // Session 3: Should have only seen peers 0, 2, and 3
798   EXPECT_EQ(3u, peers_session3.size());
799   EXPECT_THAT(peers_session3, ::testing::Contains(kAddress0));
800   EXPECT_THAT(peers_session3, ::testing::Contains(kAddress2));
801   EXPECT_THAT(peers_session3, ::testing::Contains(kAddress3));
802 
803   // Session 4: Should have seen peers 2 and 3
804   EXPECT_EQ(2u, peers_session4.size());
805   EXPECT_THAT(peers_session4, ::testing::Contains(kAddress2));
806   EXPECT_THAT(peers_session4, ::testing::Contains(kAddress3));
807 
808   // Session 5: Should only see peer 0.
809   EXPECT_EQ(1u, peers_session5.size());
810   EXPECT_THAT(peers_session5, ::testing::Contains(kAddress0));
811 }
812 
TEST_F(LowEnergyDiscoveryManagerTest,StartDiscoveryWithFiltersCachedPeerNotifications)813 TEST_F(LowEnergyDiscoveryManagerTest,
814        StartDiscoveryWithFiltersCachedPeerNotifications) {
815   AddFakePeers();
816 
817   std::vector<std::unique_ptr<LowEnergyDiscoverySession>> sessions;
818 
819   // Set a long scan period to make sure that the FakeController sends
820   // advertising reports only once.
821   discovery_manager()->set_scan_period(std::chrono::seconds(20));
822 
823   // Session 0 is interested in performing general discovery.
824   std::unordered_set<DeviceAddress> peers_session0;
825   LowEnergyDiscoverySession::PeerFoundCallback result_cb =
826       [&peers_session0](const auto& peer) {
827         peers_session0.insert(peer.address());
828       };
829   sessions.push_back(StartDiscoverySession());
830   sessions[0]->filter()->SetGeneralDiscoveryFlags();
831   sessions[0]->SetResultCallback(std::move(result_cb));
832 
833   RunUntilIdle();
834   ASSERT_EQ(3u, peers_session0.size());
835 
836   // Session 1 is interested in performing limited discovery.
837   std::unordered_set<DeviceAddress> peers_session1;
838   result_cb = [&peers_session1](const auto& peer) {
839     peers_session1.insert(peer.address());
840   };
841   sessions.push_back(StartDiscoverySession());
842   sessions[1]->filter()->set_flags(
843       static_cast<uint8_t>(AdvFlag::kLELimitedDiscoverableMode));
844   sessions[1]->SetResultCallback(std::move(result_cb));
845 
846   // Session 2 is interested in peers with UUID 0x180d.
847   std::unordered_set<DeviceAddress> peers_session2;
848   result_cb = [&peers_session2](const auto& peer) {
849     peers_session2.insert(peer.address());
850   };
851   sessions.push_back(StartDiscoverySession());
852 
853   uint16_t uuid = 0x180d;
854   sessions[2]->filter()->set_service_uuids({UUID(uuid)});
855   sessions[2]->SetResultCallback(std::move(result_cb));
856 
857   // Session 3 is interested in peers whose names contain "Device".
858   std::unordered_set<DeviceAddress> peers_session3;
859   result_cb = [&peers_session3](const auto& peer) {
860     peers_session3.insert(peer.address());
861   };
862   sessions.push_back(StartDiscoverySession());
863   sessions[3]->filter()->set_name_substring("Device");
864   sessions[3]->SetResultCallback(std::move(result_cb));
865 
866   // Session 4 is interested in non-connectable peers.
867   std::unordered_set<DeviceAddress> peers_session4;
868   result_cb = [&peers_session4](const auto& peer) {
869     peers_session4.insert(peer.address());
870   };
871   sessions.push_back(StartDiscoverySession());
872   sessions[4]->filter()->set_connectable(false);
873   sessions[4]->SetResultCallback(std::move(result_cb));
874 
875   EXPECT_EQ(5u, sessions.size());
876 
877 #define EXPECT_CONTAINS(addr, dev_list) \
878   EXPECT_TRUE(dev_list.find(addr) != dev_list.end())
879   // At this point all sessions should have processed all peers at least once
880   // without running the message loop; results for Sessions 1, 2, 3, and 4
881   // should have come from the cache.
882 
883   // Session 0: Should have seen all peers except for peer 3, which is
884   // non-discoverable.
885   EXPECT_EQ(3u, peers_session0.size());
886   EXPECT_CONTAINS(kAddress0, peers_session0);
887   EXPECT_CONTAINS(kAddress1, peers_session0);
888   EXPECT_CONTAINS(kAddress2, peers_session0);
889 
890   // Session 1: Should have only seen peer 1.
891   EXPECT_EQ(1u, peers_session1.size());
892   EXPECT_CONTAINS(kAddress1, peers_session1);
893 
894   // Session 2: Should have only seen peers 0 and 1
895   EXPECT_EQ(2u, peers_session2.size());
896   EXPECT_CONTAINS(kAddress0, peers_session2);
897   EXPECT_CONTAINS(kAddress1, peers_session2);
898 
899   // Session 3: Should have only seen peers 0, 2, and 3
900   EXPECT_EQ(3u, peers_session3.size());
901   EXPECT_CONTAINS(kAddress0, peers_session3);
902   EXPECT_CONTAINS(kAddress2, peers_session3);
903   EXPECT_CONTAINS(kAddress3, peers_session3);
904 
905   // Session 4: Should have seen peers 2 and 3
906   EXPECT_EQ(2u, peers_session4.size());
907   EXPECT_CONTAINS(kAddress2, peers_session4);
908   EXPECT_CONTAINS(kAddress3, peers_session4);
909 
910 #undef EXPECT_CONTAINS
911 }
912 
TEST_F(LowEnergyDiscoveryManagerTest,DirectedAdvertisingEventFromUnknownPeer)913 TEST_F(LowEnergyDiscoveryManagerTest, DirectedAdvertisingEventFromUnknownPeer) {
914   auto fake_peer = std::make_unique<FakePeer>(kAddress0,
915                                               dispatcher(),
916                                               /*connectable=*/true,
917                                               /*scannable=*/false);
918   fake_peer->set_directed_advertising_enabled(true);
919   test_device()->AddPeer(std::move(fake_peer));
920 
921   int connectable_count = 0;
922   discovery_manager()->set_peer_connectable_callback(
923       [&](auto) { connectable_count++; });
924   discovery_manager()->set_scan_period(kTestScanPeriod);
925 
926   auto active_session = StartDiscoverySession();
927   int active_count = 0;
928   active_session->SetResultCallback([&](auto&) { active_count++; });
929 
930   auto passive_session = StartDiscoverySession(/*active=*/false);
931   int passive_count = 0;
932   passive_session->SetResultCallback([&](auto&) { passive_count++; });
933 
934   RunUntilIdle();
935   ASSERT_TRUE(active_session);
936   ASSERT_TRUE(passive_session);
937   EXPECT_EQ(0, connectable_count);
938   EXPECT_EQ(0, active_count);
939   EXPECT_EQ(0, passive_count);
940 }
941 
TEST_F(LowEnergyDiscoveryManagerTest,DirectedAdvertisingEventFromKnownNonConnectablePeer)942 TEST_F(LowEnergyDiscoveryManagerTest,
943        DirectedAdvertisingEventFromKnownNonConnectablePeer) {
944   auto fake_peer = std::make_unique<FakePeer>(kAddress0,
945                                               dispatcher(),
946                                               /*connectable=*/false,
947                                               /*scannable=*/false);
948   fake_peer->set_directed_advertising_enabled(true);
949   test_device()->AddPeer(std::move(fake_peer));
950   Peer* peer = peer_cache()->NewPeer(kAddress0, /*connectable=*/false);
951   ASSERT_TRUE(peer);
952 
953   int connectable_count = 0;
954   discovery_manager()->set_peer_connectable_callback(
955       [&](auto) { connectable_count++; });
956   discovery_manager()->set_scan_period(kTestScanPeriod);
957 
958   auto active_session = StartDiscoverySession();
959   int active_count = 0;
960   active_session->SetResultCallback([&](auto&) { active_count++; });
961 
962   auto passive_session = StartDiscoverySession(/*active=*/false);
963   int passive_count = 0;
964   passive_session->SetResultCallback([&](auto&) { passive_count++; });
965 
966   RunFor(kTestScanPeriod);
967   ASSERT_TRUE(active_session);
968   ASSERT_TRUE(passive_session);
969   EXPECT_EQ(0, connectable_count);
970   EXPECT_EQ(0, active_count);
971   EXPECT_EQ(1, passive_count);
972 }
973 
TEST_F(LowEnergyDiscoveryManagerTest,DirectedAdvertisingEventFromKnownConnectablePeer)974 TEST_F(LowEnergyDiscoveryManagerTest,
975        DirectedAdvertisingEventFromKnownConnectablePeer) {
976   auto fake_peer = std::make_unique<FakePeer>(kAddress0,
977                                               dispatcher(),
978                                               /*connectable=*/true,
979                                               /*scannable=*/false);
980   fake_peer->set_directed_advertising_enabled(true);
981   test_device()->AddPeer(std::move(fake_peer));
982   Peer* peer = peer_cache()->NewPeer(kAddress0, /*connectable=*/true);
983   ASSERT_TRUE(peer);
984 
985   int connectable_count = 0;
986   discovery_manager()->set_peer_connectable_callback([&](Peer* callback_peer) {
987     ASSERT_TRUE(callback_peer);
988     EXPECT_TRUE(callback_peer->le());
989     EXPECT_EQ(peer, callback_peer);
990     connectable_count++;
991   });
992   discovery_manager()->set_scan_period(kTestScanPeriod);
993 
994   auto active_session = StartDiscoverySession();
995   int active_count = 0;
996   active_session->SetResultCallback([&](auto&) { active_count++; });
997 
998   auto passive_session = StartDiscoverySession(/*active=*/false);
999   int passive_count = 0;
1000   passive_session->SetResultCallback([&](auto&) { passive_count++; });
1001 
1002   RunFor(kTestScanPeriod);
1003   ASSERT_TRUE(active_session);
1004   ASSERT_TRUE(passive_session);
1005   // Connectable callback will be notified at the start of each scan period.
1006   EXPECT_EQ(2, connectable_count);
1007   EXPECT_EQ(0, active_count);
1008   EXPECT_EQ(1, passive_count);
1009 }
1010 
TEST_F(LowEnergyDiscoveryManagerTest,ScanResultUpgradesKnownBrEdrPeerToDualMode)1011 TEST_F(LowEnergyDiscoveryManagerTest,
1012        ScanResultUpgradesKnownBrEdrPeerToDualMode) {
1013   Peer* peer = peer_cache()->NewPeer(kAddrAlias0, /*connectable=*/true);
1014   ASSERT_TRUE(peer);
1015   ASSERT_EQ(peer, peer_cache()->FindByAddress(kAddress0));
1016   ASSERT_EQ(TechnologyType::kClassic, peer->technology());
1017 
1018   AddFakePeers();
1019 
1020   discovery_manager()->set_scan_period(kTestScanPeriod);
1021 
1022   std::unordered_set<DeviceAddress> addresses_found;
1023   LowEnergyDiscoverySession::PeerFoundCallback result_cb =
1024       [&addresses_found](const auto& peer) {
1025         addresses_found.insert(peer.address());
1026       };
1027   auto session = StartDiscoverySession();
1028   session->filter()->SetGeneralDiscoveryFlags();
1029   session->SetResultCallback(std::move(result_cb));
1030 
1031   RunUntilIdle();
1032 
1033   ASSERT_EQ(3u, addresses_found.size());
1034   EXPECT_TRUE(addresses_found.find(kAddrAlias0) != addresses_found.end());
1035   EXPECT_EQ(TechnologyType::kDualMode, peer->technology());
1036 }
1037 
TEST_F(LowEnergyDiscoveryManagerTest,StartAndDisablePassiveScan)1038 TEST_F(LowEnergyDiscoveryManagerTest, StartAndDisablePassiveScan) {
1039   ASSERT_FALSE(test_device()->le_scan_state().enabled);
1040 
1041   auto session = StartDiscoverySession(/*active=*/false);
1042   RunUntilIdle();
1043   EXPECT_TRUE(test_device()->le_scan_state().enabled);
1044   EXPECT_EQ(pw::bluetooth::emboss::LEScanType::PASSIVE,
1045             test_device()->le_scan_state().scan_type);
1046   EXPECT_FALSE(discovery_manager()->discovering());
1047 
1048   session.reset();
1049   RunUntilIdle();
1050   EXPECT_FALSE(test_device()->le_scan_state().enabled);
1051 }
1052 
TEST_F(LowEnergyDiscoveryManagerTest,StartAndDisablePassiveScanQuickly)1053 TEST_F(LowEnergyDiscoveryManagerTest, StartAndDisablePassiveScanQuickly) {
1054   ASSERT_FALSE(test_device()->le_scan_state().enabled);
1055 
1056   // Session will be destroyed in callback, stopping scan.
1057   discovery_manager()->StartDiscovery(
1058       /*active=*/false, [&](auto cb_session) { PW_CHECK(cb_session); });
1059   RunUntilIdle();
1060 
1061   EXPECT_FALSE(test_device()->le_scan_state().enabled);
1062   EXPECT_EQ(2u, scan_states().size());
1063 
1064   // This should not result in a request to stop scan because both pending
1065   // requests will be processed at the same time, and second call to
1066   // StartDiscovery() retains its session.
1067   discovery_manager()->StartDiscovery(
1068       /*active=*/false, [&](auto cb_session) { PW_CHECK(cb_session); });
1069   std::unique_ptr<LowEnergyDiscoverySession> session;
1070   discovery_manager()->StartDiscovery(/*active=*/false, [&](auto cb_session) {
1071     PW_CHECK(cb_session);
1072     session = std::move(cb_session);
1073   });
1074   RunUntilIdle();
1075   EXPECT_EQ(3u, scan_states().size());
1076 
1077   EXPECT_TRUE(test_device()->le_scan_state().enabled);
1078 }
1079 
TEST_F(LowEnergyDiscoveryManagerTest,EnablePassiveScanDuringActiveScanAndDisableActiveScanCausesDowngrade)1080 TEST_F(LowEnergyDiscoveryManagerTest,
1081        EnablePassiveScanDuringActiveScanAndDisableActiveScanCausesDowngrade) {
1082   auto active_session = StartDiscoverySession();
1083   ASSERT_TRUE(active_session);
1084   ASSERT_TRUE(test_device()->le_scan_state().enabled);
1085   ASSERT_EQ(pw::bluetooth::emboss::LEScanType::ACTIVE,
1086             test_device()->le_scan_state().scan_type);
1087 
1088   // The scan state should transition to enabled.
1089   ASSERT_EQ(1u, scan_states().size());
1090   EXPECT_TRUE(scan_states()[0]);
1091 
1092   // Enabling passive scans should not disable the active scan.
1093   auto passive_session = StartDiscoverySession(false);
1094   RunUntilIdle();
1095   ASSERT_EQ(pw::bluetooth::emboss::LEScanType::ACTIVE,
1096             test_device()->le_scan_state().scan_type);
1097   EXPECT_TRUE(test_device()->le_scan_state().enabled);
1098   EXPECT_EQ(1u, scan_states().size());
1099 
1100   // Stopping the active session should fall back to passive scan.
1101   active_session = nullptr;
1102   RunUntilIdle();
1103   EXPECT_TRUE(test_device()->le_scan_state().enabled);
1104   EXPECT_EQ(pw::bluetooth::emboss::LEScanType::PASSIVE,
1105             test_device()->le_scan_state().scan_type);
1106   EXPECT_THAT(scan_states(), ::testing::ElementsAre(true, false, true));
1107 }
1108 
TEST_F(LowEnergyDiscoveryManagerTest,DisablePassiveScanDuringActiveScan)1109 TEST_F(LowEnergyDiscoveryManagerTest, DisablePassiveScanDuringActiveScan) {
1110   auto active_session = StartDiscoverySession();
1111   ASSERT_TRUE(active_session);
1112   ASSERT_TRUE(test_device()->le_scan_state().enabled);
1113   ASSERT_EQ(pw::bluetooth::emboss::LEScanType::ACTIVE,
1114             test_device()->le_scan_state().scan_type);
1115 
1116   // The scan state should transition to enabled.
1117   ASSERT_EQ(1u, scan_states().size());
1118   EXPECT_TRUE(scan_states()[0]);
1119 
1120   // Enabling passive scans should not disable the active scan.
1121   auto passive_session = StartDiscoverySession(false);
1122   RunUntilIdle();
1123   ASSERT_EQ(pw::bluetooth::emboss::LEScanType::ACTIVE,
1124             test_device()->le_scan_state().scan_type);
1125   EXPECT_TRUE(test_device()->le_scan_state().enabled);
1126   EXPECT_EQ(1u, scan_states().size());
1127 
1128   // Disabling the passive scan should not disable the active scan.
1129   passive_session.reset();
1130   RunUntilIdle();
1131   ASSERT_EQ(pw::bluetooth::emboss::LEScanType::ACTIVE,
1132             test_device()->le_scan_state().scan_type);
1133   EXPECT_TRUE(test_device()->le_scan_state().enabled);
1134   EXPECT_EQ(1u, scan_states().size());
1135 
1136   // Stopping the active session should stop scans.
1137   active_session = nullptr;
1138   RunUntilIdle();
1139   EXPECT_FALSE(test_device()->le_scan_state().enabled);
1140   EXPECT_THAT(scan_states(), ::testing::ElementsAre(true, false));
1141 }
1142 
TEST_F(LowEnergyDiscoveryManagerTest,StartActiveScanDuringPassiveScan)1143 TEST_F(LowEnergyDiscoveryManagerTest, StartActiveScanDuringPassiveScan) {
1144   auto passive_session = StartDiscoverySession(false);
1145   RunUntilIdle();
1146   ASSERT_TRUE(test_device()->le_scan_state().enabled);
1147   ASSERT_EQ(pw::bluetooth::emboss::LEScanType::PASSIVE,
1148             test_device()->le_scan_state().scan_type);
1149 
1150   // The scan state should transition to enabled.
1151   ASSERT_EQ(1u, scan_states().size());
1152   EXPECT_TRUE(scan_states()[0]);
1153 
1154   // Starting discovery should turn off the passive scan and initiate an active
1155   // scan.
1156   auto active_session = StartDiscoverySession();
1157   EXPECT_TRUE(active_session);
1158   EXPECT_TRUE(test_device()->le_scan_state().enabled);
1159   EXPECT_EQ(pw::bluetooth::emboss::LEScanType::ACTIVE,
1160             test_device()->le_scan_state().scan_type);
1161   EXPECT_THAT(scan_states(), ::testing::ElementsAre(true, false, true));
1162 }
1163 
TEST_F(LowEnergyDiscoveryManagerTest,StartActiveScanWhileStartingPassiveScan)1164 TEST_F(LowEnergyDiscoveryManagerTest, StartActiveScanWhileStartingPassiveScan) {
1165   std::unique_ptr<LowEnergyDiscoverySession> passive_session;
1166   discovery_manager()->StartDiscovery(/*active=*/false, [&](auto cb_session) {
1167     PW_CHECK(cb_session);
1168     passive_session = std::move(cb_session);
1169   });
1170   ASSERT_FALSE(passive_session);
1171 
1172   std::unique_ptr<LowEnergyDiscoverySession> active_session;
1173   discovery_manager()->StartDiscovery(/*active=*/true, [&](auto cb_session) {
1174     PW_CHECK(cb_session);
1175     active_session = std::move(cb_session);
1176   });
1177   ASSERT_FALSE(active_session);
1178 
1179   // Scan should not be enabled yet.
1180   EXPECT_FALSE(test_device()->le_scan_state().enabled);
1181   EXPECT_TRUE(scan_states().empty());
1182 
1183   // Process all the requests. We should observe multiple state transitions:
1184   // -> enabled (passive) -> disabled -> enabled (active)
1185   RunUntilIdle();
1186   ASSERT_TRUE(test_device()->le_scan_state().enabled);
1187   EXPECT_EQ(pw::bluetooth::emboss::LEScanType::ACTIVE,
1188             test_device()->le_scan_state().scan_type);
1189   EXPECT_THAT(scan_states(), ::testing::ElementsAre(true, false, true));
1190 }
1191 
1192 // Emulate a number of connectable and non-connectable advertisers in both
1193 // undirected connectable and directed connectable modes. This test is to ensure
1194 // that the only peers notified during a passive scan are from connectable peers
1195 // that are already in the cache.
TEST_F(LowEnergyDiscoveryManagerTest,PeerConnectableCallbackOnlyHandlesEventsFromKnownConnectableDevices)1196 TEST_F(LowEnergyDiscoveryManagerTest,
1197        PeerConnectableCallbackOnlyHandlesEventsFromKnownConnectableDevices) {
1198   // Address 0: undirected connectable; added to cache below
1199   {
1200     auto peer = std::make_unique<FakePeer>(kAddress0,
1201                                            dispatcher(),
1202                                            /*connectable=*/true,
1203                                            /*scannable=*/true);
1204     test_device()->AddPeer(std::move(peer));
1205   }
1206   // Address 1: undirected connectable; NOT in cache
1207   {
1208     auto peer = std::make_unique<FakePeer>(kAddress1,
1209                                            dispatcher(),
1210                                            /*connectable=*/true,
1211                                            /*scannable=*/true);
1212     test_device()->AddPeer(std::move(peer));
1213   }
1214   // Address 2: not connectable; added to cache below
1215   {
1216     auto peer = std::make_unique<FakePeer>(kAddress2,
1217                                            dispatcher(),
1218                                            /*connectable=*/false,
1219                                            /*scannable=*/false);
1220     test_device()->AddPeer(std::move(peer));
1221   }
1222   // Address 3: not connectable but directed advertising (NOTE: although a
1223   // directed advertising PDU is inherently connectable, it is theoretically
1224   // possible for the peer_cache() to be in this state, even if unlikely in
1225   // practice).
1226   //
1227   // added to cache below
1228   {
1229     auto peer = std::make_unique<FakePeer>(kAddress3,
1230                                            dispatcher(),
1231                                            /*connectable=*/false,
1232                                            /*scannable=*/false);
1233     peer->set_directed_advertising_enabled(true);
1234     test_device()->AddPeer(std::move(peer));
1235   }
1236   // Address 4: directed connectable; added to cache below
1237   {
1238     auto peer = std::make_unique<FakePeer>(kAddress4,
1239                                            dispatcher(),
1240                                            /*connectable=*/true,
1241                                            /*scannable=*/false);
1242     peer->set_directed_advertising_enabled(true);
1243     test_device()->AddPeer(std::move(peer));
1244   }
1245   // Address 5: directed connectable; NOT in cache
1246   {
1247     auto peer = std::make_unique<FakePeer>(kAddress5,
1248                                            dispatcher(),
1249                                            /*connectable=*/true,
1250                                            /*scannable=*/false);
1251     peer->set_directed_advertising_enabled(true);
1252     test_device()->AddPeer(std::move(peer));
1253   }
1254 
1255   // Add cache entries for addresses 0, 2, 3, and 4. The callback should only
1256   // run for addresses 0 and 4 as the only known connectable peers. All other
1257   // advertisements should be ignored.
1258   auto address0_id =
1259       peer_cache()->NewPeer(kAddress0, /*connectable=*/true)->identifier();
1260   peer_cache()->NewPeer(kAddress2, /*connectable=*/false);
1261   peer_cache()->NewPeer(kAddress3, /*connectable=*/false);
1262   auto address4_id =
1263       peer_cache()->NewPeer(kAddress4, /*connectable=*/true)->identifier();
1264   EXPECT_EQ(4u, peer_cache()->count());
1265 
1266   int count = 0;
1267   discovery_manager()->set_peer_connectable_callback([&](Peer* peer) {
1268     ASSERT_TRUE(peer);
1269     auto id = peer->identifier();
1270     count++;
1271     EXPECT_TRUE(id == address0_id || id == address4_id) << id.ToString();
1272   });
1273   auto session = StartDiscoverySession(/*active=*/false);
1274   RunUntilIdle();
1275   EXPECT_EQ(2, count);
1276 
1277   // No new remote peer cache entries should have been created.
1278   EXPECT_EQ(4u, peer_cache()->count());
1279 }
1280 
TEST_F(LowEnergyDiscoveryManagerTest,PassiveScanPeriodRestart)1281 TEST_F(LowEnergyDiscoveryManagerTest, PassiveScanPeriodRestart) {
1282   discovery_manager()->set_scan_period(kTestScanPeriod);
1283   auto session = StartDiscoverySession(/*active=*/false);
1284 
1285   // The scan state should transition to enabled.
1286   RunUntilIdle();
1287   EXPECT_TRUE(scan_enabled());
1288   ASSERT_EQ(1u, scan_states().size());
1289   EXPECT_TRUE(test_device()->le_scan_state().enabled);
1290 
1291   // End the scan period by advancing time.
1292   RunFor(kTestScanPeriod);
1293   EXPECT_TRUE(test_device()->le_scan_state().enabled);
1294   EXPECT_EQ(pw::bluetooth::emboss::LEScanType::PASSIVE,
1295             test_device()->le_scan_state().scan_type);
1296   EXPECT_THAT(scan_states(), ::testing::ElementsAre(true, false, true));
1297 }
1298 
TEST_F(LowEnergyDiscoveryManagerTest,PauseActiveDiscoveryTwiceKeepsScanningDisabledUntilBothPauseTokensDestroyed)1299 TEST_F(
1300     LowEnergyDiscoveryManagerTest,
1301     PauseActiveDiscoveryTwiceKeepsScanningDisabledUntilBothPauseTokensDestroyed) {
1302   auto session = StartDiscoverySession();
1303   EXPECT_TRUE(scan_enabled());
1304 
1305   std::optional<PauseToken> pause_0 = discovery_manager()->PauseDiscovery();
1306   RunUntilIdle();
1307   EXPECT_FALSE(scan_enabled());
1308   EXPECT_TRUE(discovery_manager()->discovering());
1309 
1310   std::optional<PauseToken> pause_1 = discovery_manager()->PauseDiscovery();
1311   RunUntilIdle();
1312   EXPECT_FALSE(scan_enabled());
1313   EXPECT_TRUE(discovery_manager()->discovering());
1314 
1315   pause_0.reset();
1316   RunUntilIdle();
1317   EXPECT_FALSE(scan_enabled());
1318   EXPECT_TRUE(discovery_manager()->discovering());
1319 
1320   pause_1.reset();
1321   RunUntilIdle();
1322   EXPECT_TRUE(scan_enabled());
1323   EXPECT_TRUE(discovery_manager()->discovering());
1324 }
1325 
TEST_F(LowEnergyDiscoveryManagerTest,EnablePassiveScanAfterPausing)1326 TEST_F(LowEnergyDiscoveryManagerTest, EnablePassiveScanAfterPausing) {
1327   std::optional<PauseToken> pause = discovery_manager()->PauseDiscovery();
1328   RunUntilIdle();
1329   EXPECT_FALSE(scan_enabled());
1330 
1331   std::unique_ptr<LowEnergyDiscoverySession> session;
1332   discovery_manager()->StartDiscovery(/*active=*/false, [&](auto cb_session) {
1333     session = std::move(cb_session);
1334   });
1335   RunUntilIdle();
1336   EXPECT_FALSE(scan_enabled());
1337   EXPECT_FALSE(session);
1338 
1339   pause.reset();
1340   RunUntilIdle();
1341   EXPECT_TRUE(scan_enabled());
1342 }
1343 
TEST_F(LowEnergyDiscoveryManagerTest,StartActiveScanAfterPausing)1344 TEST_F(LowEnergyDiscoveryManagerTest, StartActiveScanAfterPausing) {
1345   std::optional<PauseToken> pause = discovery_manager()->PauseDiscovery();
1346   RunUntilIdle();
1347   EXPECT_FALSE(scan_enabled());
1348 
1349   std::unique_ptr<LowEnergyDiscoverySession> session;
1350   discovery_manager()->StartDiscovery(/*active=*/true, [&](auto cb_session) {
1351     session = std::move(cb_session);
1352   });
1353   RunUntilIdle();
1354   EXPECT_FALSE(scan_enabled());
1355   EXPECT_FALSE(session);
1356 
1357   pause.reset();
1358   RunUntilIdle();
1359   EXPECT_TRUE(scan_enabled());
1360   EXPECT_TRUE(session);
1361 }
1362 
TEST_F(LowEnergyDiscoveryManagerTest,PauseDiscoveryJustBeforeScanComplete)1363 TEST_F(LowEnergyDiscoveryManagerTest, PauseDiscoveryJustBeforeScanComplete) {
1364   discovery_manager()->set_scan_period(kTestScanPeriod);
1365 
1366   auto session = StartDiscoverySession();
1367   EXPECT_TRUE(scan_enabled());
1368 
1369   // Pause discovery in FakeController scan state callback to ensure it is
1370   // called just before kComplete status is received. This will be the 2nd scan
1371   // state change because it is started above and then stopped by the scan
1372   // period ending below.
1373   std::optional<PauseToken> pause;
1374   set_scan_state_handler(
1375       2, [this, &pause]() { pause = discovery_manager()->PauseDiscovery(); });
1376 
1377   RunFor(kTestScanPeriod);
1378   EXPECT_TRUE(pause.has_value());
1379   EXPECT_EQ(scan_states().size(), 2u);
1380   EXPECT_FALSE(scan_enabled());
1381 }
1382 
TEST_F(LowEnergyDiscoveryManagerTest,PauseDiscoveryJustBeforeScanStopped)1383 TEST_F(LowEnergyDiscoveryManagerTest, PauseDiscoveryJustBeforeScanStopped) {
1384   auto session = StartDiscoverySession();
1385   EXPECT_TRUE(scan_enabled());
1386 
1387   // Pause discovery in FakeController scan state callback to ensure it is
1388   // called just before kStopped status is received. This will be the 2nd scan
1389   // state change because it is started above and then stopped by the session
1390   // being destroyed below.
1391   std::optional<PauseToken> pause;
1392   set_scan_state_handler(
1393       2, [this, &pause]() { pause = discovery_manager()->PauseDiscovery(); });
1394 
1395   session.reset();
1396   RunUntilIdle();
1397   EXPECT_TRUE(pause.has_value());
1398   EXPECT_EQ(scan_states().size(), 2u);
1399   EXPECT_FALSE(scan_enabled());
1400 }
1401 
TEST_F(LowEnergyDiscoveryManagerTest,PauseJustBeforeScanActive)1402 TEST_F(LowEnergyDiscoveryManagerTest, PauseJustBeforeScanActive) {
1403   // Pause discovery in FakeController scan state callback to ensure it is
1404   // called just before kActive status is received. This will be the first scan
1405   // state change.
1406   std::optional<PauseToken> pause;
1407   set_scan_state_handler(
1408       1, [this, &pause]() { pause = discovery_manager()->PauseDiscovery(); });
1409 
1410   std::unique_ptr<LowEnergyDiscoverySession> session;
1411   discovery_manager()->StartDiscovery(/*active=*/true, [&](auto cb_session) {
1412     session = std::move(cb_session);
1413   });
1414 
1415   // The scan should be canceled.
1416   RunUntilIdle();
1417   EXPECT_FALSE(session);
1418   EXPECT_TRUE(pause.has_value());
1419   EXPECT_EQ(scan_states().size(), 2u);
1420   EXPECT_FALSE(scan_enabled());
1421   EXPECT_FALSE(discovery_manager()->discovering());
1422 
1423   // Resume discovery.
1424   pause.reset();
1425   RunUntilIdle();
1426   EXPECT_TRUE(session);
1427   EXPECT_TRUE(scan_enabled());
1428   EXPECT_TRUE(discovery_manager()->discovering());
1429 }
1430 
TEST_F(LowEnergyDiscoveryManagerTest,PauseJustBeforeScanPassive)1431 TEST_F(LowEnergyDiscoveryManagerTest, PauseJustBeforeScanPassive) {
1432   // Pause discovery in FakeController scan state callback to ensure it is
1433   // called just before kPassive status is received. This will be the first scan
1434   // state change.
1435   std::optional<PauseToken> pause;
1436   set_scan_state_handler(
1437       1, [this, &pause]() { pause = discovery_manager()->PauseDiscovery(); });
1438 
1439   std::unique_ptr<LowEnergyDiscoverySession> session;
1440   discovery_manager()->StartDiscovery(/*active=*/false, [&](auto cb_session) {
1441     session = std::move(cb_session);
1442   });
1443 
1444   // The scan should be canceled.
1445   RunUntilIdle();
1446   EXPECT_FALSE(session);
1447   EXPECT_TRUE(pause.has_value());
1448   EXPECT_EQ(scan_states().size(), 2u);
1449   EXPECT_FALSE(scan_enabled());
1450 
1451   // Resume scan.
1452   pause.reset();
1453   RunUntilIdle();
1454   EXPECT_TRUE(scan_enabled());
1455 }
1456 
TEST_F(LowEnergyDiscoveryManagerTest,StartActiveScanWhilePassiveScanStoppingBetweenScanPeriods)1457 TEST_F(LowEnergyDiscoveryManagerTest,
1458        StartActiveScanWhilePassiveScanStoppingBetweenScanPeriods) {
1459   discovery_manager()->set_scan_period(kTestScanPeriod);
1460 
1461   auto passive_session = StartDiscoverySession(/*active=*/false);
1462 
1463   std::unique_ptr<LowEnergyDiscoverySession> active_session;
1464   set_scan_state_handler(2, [this, &active_session]() {
1465     discovery_manager()->StartDiscovery(
1466         /*active=*/true, [&active_session](auto session) {
1467           active_session = std::move(session);
1468         });
1469   });
1470   RunFor(kTestScanPeriod);
1471   EXPECT_TRUE(test_device()->le_scan_state().enabled);
1472   EXPECT_EQ(pw::bluetooth::emboss::LEScanType::ACTIVE,
1473             test_device()->le_scan_state().scan_type);
1474   EXPECT_THAT(scan_states(), ::testing::ElementsAre(true, false, true));
1475 }
1476 
TEST_F(LowEnergyDiscoveryManagerTest,StopSessionInsideOfResultCallbackDoesNotCrash)1477 TEST_F(LowEnergyDiscoveryManagerTest,
1478        StopSessionInsideOfResultCallbackDoesNotCrash) {
1479   auto session = StartDiscoverySession(/*active=*/false);
1480   auto result_cb = [&session](const auto&) { session->Stop(); };
1481   session->SetResultCallback(std::move(result_cb));
1482   RunUntilIdle();
1483 
1484   AddFakePeers();
1485   RunUntilIdle();
1486 }
1487 
TEST_F(LowEnergyDiscoveryManagerTest,PeerChangesFromNonConnectableToConnectable)1488 TEST_F(LowEnergyDiscoveryManagerTest,
1489        PeerChangesFromNonConnectableToConnectable) {
1490   test_device()->AddPeer(std::make_unique<FakePeer>(
1491       kAddress0, dispatcher(), /*connectable=*/false));
1492 
1493   std::unique_ptr<LowEnergyDiscoverySession> session;
1494   discovery_manager()->StartDiscovery(
1495       /*active=*/true,
1496       [&session](auto cb_session) { session = std::move(cb_session); });
1497 
1498   RunUntilIdle();
1499   EXPECT_TRUE(scan_enabled());
1500   auto peer = peer_cache()->FindByAddress(kAddress0);
1501   ASSERT_TRUE(peer);
1502   EXPECT_FALSE(peer->connectable());
1503 
1504   // Make peer connectable.
1505   test_device()->RemovePeer(kAddress0);
1506   test_device()->AddPeer(std::make_unique<FakePeer>(
1507       kAddress0, dispatcher(), /*connectable=*/true));
1508 
1509   RunUntilIdle();
1510   peer = peer_cache()->FindByAddress(kAddress0);
1511   ASSERT_TRUE(peer);
1512   EXPECT_TRUE(peer->connectable());
1513 
1514   // Ensure peer stays connectable after non-connectable advertisement.
1515   test_device()->RemovePeer(kAddress0);
1516   test_device()->AddPeer(std::make_unique<FakePeer>(
1517       kAddress0, dispatcher(), /*connectable=*/false));
1518 
1519   RunUntilIdle();
1520   peer = peer_cache()->FindByAddress(kAddress0);
1521   ASSERT_TRUE(peer);
1522   EXPECT_TRUE(peer->connectable());
1523 }
1524 
1525 #ifndef NINSPECT
TEST_F(LowEnergyDiscoveryManagerTest,Inspect)1526 TEST_F(LowEnergyDiscoveryManagerTest, Inspect) {
1527   // Ensure node exists before testing properties.
1528   ASSERT_THAT(InspectHierarchy(),
1529               AllOf(ChildrenMatch(ElementsAre(NodeMatches(
1530                   AllOf(NameMatches(std::string(kInspectNodeName))))))));
1531   EXPECT_THAT(InspectProperties(),
1532               UnorderedElementsAre(StringIs("state", "Idle"),
1533                                    IntIs("paused", 0),
1534                                    UintIs("failed_count", 0u),
1535                                    DoubleIs("scan_interval_ms", 0.0),
1536                                    DoubleIs("scan_window_ms", 0.0)));
1537 
1538   std::unique_ptr<LowEnergyDiscoverySession> passive_session;
1539   discovery_manager()->StartDiscovery(/*active=*/false, [&](auto cb_session) {
1540     PW_CHECK(cb_session);
1541     passive_session = std::move(cb_session);
1542   });
1543   EXPECT_THAT(InspectProperties(),
1544               ::testing::IsSupersetOf(
1545                   {StringIs("state", "Starting"),
1546                    DoubleIs("scan_interval_ms", ::testing::Gt(0.0)),
1547                    DoubleIs("scan_window_ms", ::testing::Gt(0.0))}));
1548 
1549   RunUntilIdle();
1550   EXPECT_THAT(InspectProperties(),
1551               ::testing::IsSupersetOf(
1552                   {StringIs("state", "Passive"),
1553                    DoubleIs("scan_interval_ms", ::testing::Gt(0.0)),
1554                    DoubleIs("scan_window_ms", ::testing::Gt(0.0))}));
1555 
1556   {
1557     auto pause_token = discovery_manager()->PauseDiscovery();
1558     EXPECT_THAT(InspectProperties(),
1559                 ::testing::IsSupersetOf(
1560                     {StringIs("state", "Stopping"), IntIs("paused", 1)}));
1561   }
1562 
1563   auto active_session = StartDiscoverySession();
1564   EXPECT_THAT(InspectProperties(),
1565               ::testing::IsSupersetOf(
1566                   {StringIs("state", "Active"),
1567                    DoubleIs("scan_interval_ms", ::testing::Gt(0.0)),
1568                    DoubleIs("scan_window_ms", ::testing::Gt(0.0))}));
1569 
1570   passive_session.reset();
1571   active_session.reset();
1572   EXPECT_THAT(InspectProperties(),
1573               ::testing::IsSupersetOf({StringIs("state", "Stopping")}));
1574   RunUntilIdle();
1575   EXPECT_THAT(InspectProperties(),
1576               ::testing::IsSupersetOf({StringIs("state", "Idle")}));
1577 
1578   // Cause discovery to fail.
1579   test_device()->SetDefaultResponseStatus(
1580       hci_spec::kLESetScanEnable,
1581       pw::bluetooth::emboss::StatusCode::COMMAND_DISALLOWED);
1582   discovery_manager()->StartDiscovery(
1583       /*active=*/true, [](auto session) { EXPECT_FALSE(session); });
1584   RunUntilIdle();
1585   EXPECT_THAT(InspectProperties(),
1586               ::testing::IsSupersetOf({UintIs("failed_count", 1u)}));
1587 }
1588 #endif  // NINSPECT
1589 
TEST_F(LowEnergyDiscoveryManagerTest,SetResultCallbackIgnoresRemovedPeers)1590 TEST_F(LowEnergyDiscoveryManagerTest, SetResultCallbackIgnoresRemovedPeers) {
1591   auto fake_peer_0 = std::make_unique<FakePeer>(kAddress0, dispatcher());
1592   test_device()->AddPeer(std::move(fake_peer_0));
1593   Peer* peer_0 = peer_cache()->NewPeer(kAddress0, /*connectable=*/true);
1594   PeerId peer_id_0 = peer_0->identifier();
1595 
1596   auto fake_peer_1 = std::make_unique<FakePeer>(kAddress1, dispatcher());
1597   test_device()->AddPeer(std::move(fake_peer_1));
1598   Peer* peer_1 = peer_cache()->NewPeer(kAddress1, /*connectable=*/true);
1599   PeerId peer_id_1 = peer_1->identifier();
1600 
1601   // Start active session so that results get cached.
1602   auto session = StartDiscoverySession(/*active=*/true);
1603 
1604   std::unordered_map<PeerId, int> result_counts;
1605   session->SetResultCallback(
1606       [&](const Peer& peer) { result_counts[peer.identifier()]++; });
1607   RunUntilIdle();
1608   EXPECT_EQ(result_counts[peer_id_0], 1);
1609   EXPECT_EQ(result_counts[peer_id_1], 1);
1610 
1611   // Remove peer_0 to make the cached result stale. The result callback should
1612   // not be called again for peer_0.
1613   ASSERT_TRUE(peer_cache()->RemoveDisconnectedPeer(peer_0->identifier()));
1614   session->SetResultCallback(
1615       [&](const Peer& peer) { result_counts[peer.identifier()]++; });
1616   RunUntilIdle();
1617   EXPECT_EQ(result_counts[peer_id_0], 1);
1618   EXPECT_EQ(result_counts[peer_id_1], 2);
1619 }
1620 
1621 }  // namespace
1622 }  // namespace bt::gap
1623