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/peer.h"
16
17 #include <gmock/gmock.h>
18 #include <gtest/gtest.h>
19 #include <pw_async/fake_dispatcher_fixture.h>
20
21 #include "pw_bluetooth_sapphire/internal/host/common/advertising_data.h"
22 #include "pw_bluetooth_sapphire/internal/host/common/byte_buffer.h"
23 #include "pw_bluetooth_sapphire/internal/host/common/manufacturer_names.h"
24 #include "pw_bluetooth_sapphire/internal/host/hci-spec/util.h"
25 #include "pw_bluetooth_sapphire/internal/host/testing/inspect_util.h"
26
27 namespace bt::gap {
28 namespace {
29
30 #ifndef NINSPECT
31 using namespace inspect::testing;
32 using bt::testing::GetInspectValue;
33 using bt::testing::ReadInspect;
34
35 constexpr uint16_t kManufacturer = 0x0001;
36 constexpr uint16_t kSubversion = 0x0002;
37 #endif // NINSPECT
38
39 const StaticByteBuffer kAdvData(0x05, // Length
40 0x09, // AD type: Complete Local Name
41 'T',
42 'e',
43 's',
44 't');
45
46 const StaticByteBuffer kInvalidAdvData{
47 // 32 bit service UUIDs are supposed to be 4 bytes, but the value in this
48 // TLV field is only 3
49 // bytes long, hence the AdvertisingData is not valid.
50 0x04,
51 static_cast<uint8_t>(DataType::kComplete32BitServiceUuids),
52 0x01,
53 0x02,
54 0x03,
55 };
56
57 const bt::sm::LTK kLTK;
58
59 const DeviceAddress kAddrLePublic(DeviceAddress::Type::kLEPublic,
60 {1, 2, 3, 4, 5, 6});
61 const DeviceAddress kAddrLeRandom(DeviceAddress::Type::kLERandom,
62 {1, 2, 3, 4, 5, 6});
63 const DeviceAddress kAddrBrEdr(DeviceAddress::Type::kBREDR,
64 {0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA});
65 // LE Public Device Address that has the same value as a BR/EDR BD_ADDR, e.g. on
66 // a dual-mode device.
67 const DeviceAddress kAddrLeAlias(DeviceAddress::Type::kLEPublic,
68 {0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA});
69
70 const bt::sm::LTK kSecureBrEdrKey(
71 sm::SecurityProperties(/*encrypted=*/true,
72 /*authenticated=*/true,
73 /*secure_connections=*/true,
74 sm::kMaxEncryptionKeySize),
75 hci_spec::LinkKey(UInt128{4}, 5, 6));
76
77 class PeerTest : public pw::async::test::FakeDispatcherFixture {
78 public:
79 PeerTest() = default;
80
SetUp()81 void SetUp() override {
82 // Set up a default peer.
83 SetUpPeer(/*address=*/kAddrLePublic, /*connectable=*/true);
84 }
85
TearDown()86 void TearDown() override { peer_.reset(); }
87
88 protected:
89 // Can be used to override or reset the default peer. Resets metrics to
90 // prevent interference between peers (e.g. by metrics updated in
91 // construction).
SetUpPeer(const DeviceAddress & address,bool connectable)92 void SetUpPeer(const DeviceAddress& address, bool connectable) {
93 address_ = address;
94 peer_ = std::make_unique<Peer>(
95 fit::bind_member<&PeerTest::NotifyListenersCallback>(this),
96 fit::bind_member<&PeerTest::UpdateExpiryCallback>(this),
97 fit::bind_member<&PeerTest::DualModeCallback>(this),
98 fit::bind_member<&PeerTest::StoreLowEnergyBondCallback>(this),
99 PeerId(1),
100 address_,
101 connectable,
102 &metrics_,
103 dispatcher());
104 peer_->AttachInspect(peer_inspector_.GetRoot());
105 // Reset metrics as they should only apply to the new peer under test.
106 metrics_.AttachInspect(metrics_inspector_.GetRoot());
107 }
peer()108 Peer& peer() { return *peer_; }
109
110 #ifndef NINSPECT
ReadPeerInspect()111 inspect::Hierarchy ReadPeerInspect() { return ReadInspect(peer_inspector_); }
112
InspectLowEnergyConnectionState()113 std::string InspectLowEnergyConnectionState() {
114 std::optional<std::string> val =
115 GetInspectValue<inspect::StringPropertyValue>(
116 peer_inspector_,
117 {"peer",
118 "le_data",
119 Peer::LowEnergyData::kInspectConnectionStateName});
120 BT_ASSERT(val);
121 return *val;
122 }
123
InspectAdvertisingDataParseFailureCount()124 int64_t InspectAdvertisingDataParseFailureCount() {
125 std::optional<int64_t> val = GetInspectValue<inspect::IntPropertyValue>(
126 peer_inspector_,
127 {"peer",
128 "le_data",
129 Peer::LowEnergyData::kInspectAdvertisingDataParseFailureCountName});
130 BT_ASSERT(val);
131 return *val;
132 }
133
InspectLastAdvertisingDataParseFailure()134 std::string InspectLastAdvertisingDataParseFailure() {
135 std::optional<std::string> val =
136 GetInspectValue<inspect::StringPropertyValue>(
137 peer_inspector_,
138 {"peer",
139 "le_data",
140 Peer::LowEnergyData::kInspectLastAdvertisingDataParseFailureName});
141 BT_ASSERT(val);
142 return *val;
143 }
144
MetricsLowEnergyConnections()145 uint64_t MetricsLowEnergyConnections() {
146 std::optional<uint64_t> val = GetInspectValue<inspect::UintPropertyValue>(
147 metrics_inspector_, {"metrics", "le", "connection_events"});
148 BT_ASSERT(val);
149 return *val;
150 }
151
MetricsLowEnergyDisconnections()152 uint64_t MetricsLowEnergyDisconnections() {
153 std::optional<uint64_t> val = GetInspectValue<inspect::UintPropertyValue>(
154 metrics_inspector_, {"metrics", "le", "disconnection_events"});
155 BT_ASSERT(val);
156 return *val;
157 }
158
InspectBrEdrConnectionState()159 std::string InspectBrEdrConnectionState() {
160 std::optional<std::string> val =
161 GetInspectValue<inspect::StringPropertyValue>(
162 peer_inspector_,
163 {"peer",
164 "bredr_data",
165 Peer::BrEdrData::kInspectConnectionStateName});
166 BT_ASSERT(val);
167 return *val;
168 }
169
MetricsBrEdrConnections()170 uint64_t MetricsBrEdrConnections() {
171 std::optional<uint64_t> val = GetInspectValue<inspect::UintPropertyValue>(
172 metrics_inspector_, {"metrics", "bredr", "connection_events"});
173 BT_ASSERT(val);
174 return *val;
175 }
176
MetricsBrEdrDisconnections()177 uint64_t MetricsBrEdrDisconnections() {
178 std::optional<uint64_t> val = GetInspectValue<inspect::UintPropertyValue>(
179 metrics_inspector_, {"metrics", "bredr", "disconnection_events"});
180 BT_ASSERT(val);
181 return *val;
182 }
183 #endif // NINSPECT
184
set_notify_listeners_cb(Peer::NotifyListenersCallback cb)185 void set_notify_listeners_cb(Peer::NotifyListenersCallback cb) {
186 notify_listeners_cb_ = std::move(cb);
187 }
set_update_expiry_cb(Peer::PeerCallback cb)188 void set_update_expiry_cb(Peer::PeerCallback cb) {
189 update_expiry_cb_ = std::move(cb);
190 }
set_dual_mode_cb(Peer::PeerCallback cb)191 void set_dual_mode_cb(Peer::PeerCallback cb) {
192 dual_mode_cb_ = std::move(cb);
193 }
set_store_le_bond_cb(Peer::StoreLowEnergyBondCallback cb)194 void set_store_le_bond_cb(Peer::StoreLowEnergyBondCallback cb) {
195 store_le_bond_cb_ = std::move(cb);
196 }
197
198 private:
NotifyListenersCallback(const Peer & peer,Peer::NotifyListenersChange change)199 void NotifyListenersCallback(const Peer& peer,
200 Peer::NotifyListenersChange change) {
201 if (notify_listeners_cb_) {
202 notify_listeners_cb_(peer, change);
203 }
204 }
205
UpdateExpiryCallback(const Peer & peer)206 void UpdateExpiryCallback(const Peer& peer) {
207 if (update_expiry_cb_) {
208 update_expiry_cb_(peer);
209 }
210 }
211
DualModeCallback(const Peer & peer)212 void DualModeCallback(const Peer& peer) {
213 if (dual_mode_cb_) {
214 dual_mode_cb_(peer);
215 }
216 }
217
StoreLowEnergyBondCallback(const sm::PairingData & data)218 bool StoreLowEnergyBondCallback(const sm::PairingData& data) {
219 if (store_le_bond_cb_) {
220 return store_le_bond_cb_(data);
221 }
222 return false;
223 }
224
225 std::unique_ptr<Peer> peer_;
226 DeviceAddress address_;
227 Peer::NotifyListenersCallback notify_listeners_cb_;
228 Peer::PeerCallback update_expiry_cb_;
229 Peer::PeerCallback dual_mode_cb_;
230 Peer::StoreLowEnergyBondCallback store_le_bond_cb_;
231 inspect::Inspector metrics_inspector_;
232 PeerMetrics metrics_;
233 inspect::Inspector peer_inspector_;
234 };
235
236 class PeerDeathTest : public PeerTest {};
237
238 #ifndef NINSPECT
TEST_F(PeerTest,InspectHierarchy)239 TEST_F(PeerTest, InspectHierarchy) {
240 peer().set_version(pw::bluetooth::emboss::CoreSpecificationVersion::V5_0,
241 kManufacturer,
242 kSubversion);
243
244 peer().RegisterName("Sapphire", Peer::NameSource::kGenericAccessService);
245
246 peer().MutLe();
247 ASSERT_TRUE(peer().le().has_value());
248
249 peer().MutLe().SetFeatures(hci_spec::LESupportedFeatures{0x0000000000000001});
250
251 peer().MutBrEdr().AddService(UUID(uint16_t{0x110b}));
252
253 auto bredr_data_matcher = AllOf(NodeMatches(
254 AllOf(NameMatches(Peer::BrEdrData::kInspectNodeName),
255 PropertyList(UnorderedElementsAre(
256 StringIs(Peer::BrEdrData::kInspectConnectionStateName,
257 Peer::ConnectionStateToString(
258 peer().bredr()->connection_state())),
259 StringIs(Peer::BrEdrData::kInspectServicesName,
260 "{ 0000110b-0000-1000-8000-00805f9b34fb }"))))));
261
262 auto le_data_matcher = AllOf(NodeMatches(AllOf(
263 NameMatches(Peer::LowEnergyData::kInspectNodeName),
264 PropertyList(UnorderedElementsAre(
265 StringIs(
266 Peer::LowEnergyData::kInspectConnectionStateName,
267 Peer::ConnectionStateToString(peer().le()->connection_state())),
268 IntIs(
269 Peer::LowEnergyData::kInspectAdvertisingDataParseFailureCountName,
270 0),
271 StringIs(
272 Peer::LowEnergyData::kInspectLastAdvertisingDataParseFailureName,
273 ""),
274 BoolIs(Peer::LowEnergyData::kInspectBondDataName,
275 peer().le()->bonded()),
276 StringIs(Peer::LowEnergyData::kInspectFeaturesName,
277 "0x0000000000000001"))))));
278
279 auto peer_matcher = AllOf(
280 NodeMatches(PropertyList(UnorderedElementsAre(
281 StringIs(Peer::kInspectPeerIdName, peer().identifier().ToString()),
282 StringIs(Peer::kInspectPeerNameName,
283 peer().name().value() + " [source: " +
284 Peer::NameSourceToString(
285 Peer::NameSource::kGenericAccessService) +
286 "]"),
287 StringIs(Peer::kInspectTechnologyName,
288 TechnologyTypeToString(peer().technology())),
289 StringIs(Peer::kInspectAddressName, peer().address().ToString()),
290 BoolIs(Peer::kInspectConnectableName, peer().connectable()),
291 BoolIs(Peer::kInspectTemporaryName, peer().temporary()),
292 StringIs(Peer::kInspectFeaturesName, peer().features().ToString()),
293 StringIs(Peer::kInspectVersionName,
294 hci_spec::HCIVersionToString(peer().version().value())),
295 StringIs(Peer::kInspectManufacturerName,
296 GetManufacturerName(kManufacturer))))),
297 ChildrenMatch(UnorderedElementsAre(bredr_data_matcher, le_data_matcher)));
298 // clang-format on
299 inspect::Hierarchy hierarchy = ReadPeerInspect();
300 EXPECT_THAT(hierarchy,
301 AllOf(ChildrenMatch(UnorderedElementsAre(peer_matcher))));
302 }
303 #endif // NINSPECT
304
305 #ifndef NINSPECT
TEST_F(PeerTest,SetBrEdrBondDataUpdatesInspectProperties)306 TEST_F(PeerTest, SetBrEdrBondDataUpdatesInspectProperties) {
307 const char* const kInspectLevelPropertyName = "level";
308 const char* const kInspectEncryptedPropertyName = "encrypted";
309 const char* const kInspectSecureConnectionsPropertyName =
310 "secure_connections";
311 const char* const kInspectAuthenticatedPropertyName = "authenticated";
312 const char* const kInspectKeyTypePropertyName = "key_type";
313
314 peer().set_version(pw::bluetooth::emboss::CoreSpecificationVersion::V5_0,
315 kManufacturer,
316 kSubversion);
317
318 peer().RegisterName("Sapphire", Peer::NameSource::kGenericAccessService);
319
320 peer().MutLe();
321 ASSERT_TRUE(peer().le().has_value());
322
323 peer().MutLe().SetFeatures(hci_spec::LESupportedFeatures{0x0000000000000001});
324
325 peer().MutBrEdr().AddService(UUID(uint16_t{0x110b}));
326 peer().MutBrEdr().SetBondData(kLTK);
327
328 // clang-format off
329 auto bredr_data_matcher = AllOf(
330 NodeMatches(AllOf(
331 NameMatches(Peer::BrEdrData::kInspectNodeName),
332 PropertyList(UnorderedElementsAre(
333 StringIs(Peer::BrEdrData::kInspectConnectionStateName,
334 Peer::ConnectionStateToString(peer().bredr()->connection_state())),
335 StringIs(Peer::BrEdrData::kInspectServicesName, "{ 0000110b-0000-1000-8000-00805f9b34fb }")
336 )))));
337
338 auto le_data_matcher = AllOf(
339 NodeMatches(AllOf(
340 NameMatches(Peer::LowEnergyData::kInspectNodeName),
341 PropertyList(UnorderedElementsAre(
342 StringIs(Peer::LowEnergyData::kInspectConnectionStateName,
343 Peer::ConnectionStateToString(peer().le()->connection_state())),
344 IntIs(Peer::LowEnergyData::kInspectAdvertisingDataParseFailureCountName, 0),
345 StringIs(Peer::LowEnergyData::kInspectLastAdvertisingDataParseFailureName, ""),
346 BoolIs(Peer::LowEnergyData::kInspectBondDataName, peer().le()->bonded()),
347 StringIs(Peer::LowEnergyData::kInspectFeaturesName, "0x0000000000000001")
348 )))));
349
350 auto peer_matcher = AllOf(
351 NodeMatches(
352 PropertyList(UnorderedElementsAre(
353 StringIs(Peer::kInspectPeerIdName, peer().identifier().ToString()),
354 StringIs(Peer::kInspectPeerNameName, peer().name().value() + " [source: " + Peer::NameSourceToString(Peer::NameSource::kGenericAccessService) + "]"),
355 StringIs(Peer::kInspectTechnologyName, TechnologyTypeToString(peer().technology())),
356 StringIs(Peer::kInspectAddressName, peer().address().ToString()),
357 BoolIs(Peer::kInspectConnectableName, peer().connectable()),
358 BoolIs(Peer::kInspectTemporaryName, peer().temporary()),
359 StringIs(Peer::kInspectFeaturesName, peer().features().ToString()),
360 StringIs(Peer::kInspectVersionName, hci_spec::HCIVersionToString(peer().version().value())),
361 StringIs(Peer::kInspectManufacturerName, GetManufacturerName(kManufacturer))
362 ))),
363 ChildrenMatch(UnorderedElementsAre(bredr_data_matcher, le_data_matcher)));
364 // clang-format on
365 inspect::Hierarchy hierarchy = ReadPeerInspect();
366 EXPECT_THAT(hierarchy,
367 AllOf(ChildrenMatch(UnorderedElementsAre(peer_matcher))));
368
369 peer().MutBrEdr().SetBondData(kSecureBrEdrKey);
370
371 const sm::SecurityProperties security_properties =
372 peer().bredr()->link_key().value().security();
373 auto link_key_matcher = AllOf(NodeMatches(AllOf(
374 NameMatches("link_key"),
375 PropertyList(UnorderedElementsAre(
376 StringIs(kInspectLevelPropertyName,
377 LevelToString(security_properties.level())),
378 BoolIs(kInspectEncryptedPropertyName,
379 security_properties.encrypted()),
380 BoolIs(kInspectSecureConnectionsPropertyName,
381 security_properties.secure_connections()),
382 BoolIs(kInspectAuthenticatedPropertyName,
383 security_properties.authenticated()),
384 StringIs(kInspectKeyTypePropertyName,
385 hci_spec::LinkKeyTypeToString(
386 security_properties.GetLinkKeyType().value())))))));
387
388 auto bredr_data_matcher2 =
389 AllOf(NodeMatches(AllOf(
390 NameMatches(Peer::BrEdrData::kInspectNodeName),
391 PropertyList(UnorderedElementsAre(
392 StringIs(Peer::BrEdrData::kInspectConnectionStateName,
393 Peer::ConnectionStateToString(
394 peer().bredr()->connection_state())),
395 StringIs(Peer::BrEdrData::kInspectServicesName,
396 "{ 0000110b-0000-1000-8000-00805f9b34fb }"))))),
397 ChildrenMatch(UnorderedElementsAre(link_key_matcher)));
398
399 auto le_data_matcher2 = AllOf(NodeMatches(AllOf(
400 NameMatches(Peer::LowEnergyData::kInspectNodeName),
401 PropertyList(UnorderedElementsAre(
402 StringIs(
403 Peer::LowEnergyData::kInspectConnectionStateName,
404 Peer::ConnectionStateToString(peer().le()->connection_state())),
405 IntIs(
406 Peer::LowEnergyData::kInspectAdvertisingDataParseFailureCountName,
407 0),
408 StringIs(
409 Peer::LowEnergyData::kInspectLastAdvertisingDataParseFailureName,
410 ""),
411 BoolIs(Peer::LowEnergyData::kInspectBondDataName,
412 peer().le()->bonded()),
413 StringIs(Peer::LowEnergyData::kInspectFeaturesName,
414 "0x0000000000000001"))))));
415
416 auto peer_matcher2 = AllOf(
417 NodeMatches(PropertyList(UnorderedElementsAre(
418 StringIs(Peer::kInspectPeerIdName, peer().identifier().ToString()),
419 StringIs(Peer::kInspectPeerNameName,
420 peer().name().value() + " [source: " +
421 Peer::NameSourceToString(
422 Peer::NameSource::kGenericAccessService) +
423 "]"),
424 StringIs(Peer::kInspectTechnologyName,
425 TechnologyTypeToString(peer().technology())),
426 StringIs(Peer::kInspectAddressName, peer().address().ToString()),
427 BoolIs(Peer::kInspectConnectableName, peer().connectable()),
428 BoolIs(Peer::kInspectTemporaryName, peer().temporary()),
429 StringIs(Peer::kInspectFeaturesName, peer().features().ToString()),
430 StringIs(Peer::kInspectVersionName,
431 hci_spec::HCIVersionToString(peer().version().value())),
432 StringIs(Peer::kInspectManufacturerName,
433 GetManufacturerName(kManufacturer))))),
434 ChildrenMatch(
435 UnorderedElementsAre(bredr_data_matcher2, le_data_matcher2)));
436 // clang-format on
437 hierarchy = ReadPeerInspect();
438 EXPECT_THAT(hierarchy,
439 AllOf(ChildrenMatch(UnorderedElementsAre(peer_matcher2))));
440 }
441 #endif // NINSPECT
442
TEST_F(PeerTest,BrEdrDataAddServiceNotifiesListeners)443 TEST_F(PeerTest, BrEdrDataAddServiceNotifiesListeners) {
444 // Initialize BrEdrData.
445 peer().MutBrEdr();
446 ASSERT_TRUE(peer().bredr()->services().empty());
447
448 bool listener_notified = false;
449 set_notify_listeners_cb([&](auto&, Peer::NotifyListenersChange change) {
450 listener_notified = true;
451 // Non-bonded peer should not update bond
452 EXPECT_EQ(Peer::NotifyListenersChange::kBondNotUpdated, change);
453 });
454
455 constexpr UUID kServiceUuid;
456 peer().MutBrEdr().AddService(kServiceUuid);
457 EXPECT_TRUE(listener_notified);
458 EXPECT_EQ(1u, peer().bredr()->services().count(kServiceUuid));
459
460 // De-duplicate subsequent additions of the same service.
461 listener_notified = false;
462 peer().MutBrEdr().AddService(kServiceUuid);
463 EXPECT_FALSE(listener_notified);
464 }
465
TEST_F(PeerTest,BrEdrDataAddServiceOnBondedPeerNotifiesListenersToUpdateBond)466 TEST_F(PeerTest, BrEdrDataAddServiceOnBondedPeerNotifiesListenersToUpdateBond) {
467 // Initialize BrEdrData.
468 peer().MutBrEdr().SetBondData({});
469 ASSERT_TRUE(peer().bredr()->services().empty());
470
471 bool listener_notified = false;
472 set_notify_listeners_cb([&](auto&, Peer::NotifyListenersChange change) {
473 listener_notified = true;
474 // Bonded peer should update bond
475 EXPECT_EQ(Peer::NotifyListenersChange::kBondUpdated, change);
476 });
477
478 peer().MutBrEdr().AddService(UUID());
479 EXPECT_TRUE(listener_notified);
480 }
481
TEST_F(PeerTest,LowEnergyDataSetAdvDataWithInvalidUtf8NameDoesNotUpdatePeerName)482 TEST_F(PeerTest,
483 LowEnergyDataSetAdvDataWithInvalidUtf8NameDoesNotUpdatePeerName) {
484 peer().MutLe(); // Initialize LowEnergyData.
485 ASSERT_FALSE(peer().name().has_value());
486
487 bool listener_notified = false;
488 set_notify_listeners_cb(
489 [&](auto&, Peer::NotifyListenersChange) { listener_notified = true; });
490
491 const StaticByteBuffer kAdvData(
492 0x05, // Length
493 0x09, // AD type: Complete Local Name
494 'T',
495 'e',
496 's',
497 0xFF // 0xFF should not appear in a valid UTF-8 string
498 );
499
500 peer().MutLe().SetAdvertisingData(
501 /*rssi=*/0, kAdvData, pw::chrono::SystemClock::time_point());
502 EXPECT_TRUE(listener_notified); // Fresh AD still results in an update
503 EXPECT_FALSE(peer().name().has_value());
504 }
505
TEST_F(PeerTest,BrEdrDataSetEirDataWithInvalidUtf8NameDoesNotUpdatePeerName)506 TEST_F(PeerTest, BrEdrDataSetEirDataWithInvalidUtf8NameDoesNotUpdatePeerName) {
507 peer().MutBrEdr(); // Initialize BrEdrData.
508 ASSERT_FALSE(peer().name().has_value());
509
510 bool listener_notified = false;
511 set_notify_listeners_cb(
512 [&](auto&, Peer::NotifyListenersChange) { listener_notified = true; });
513
514 const StaticByteBuffer kEirData(
515 0x05, // Length
516 0x09, // AD type: Complete Local Name
517 'T',
518 'e',
519 's',
520 0xFF // 0xFF should not appear in a valid UTF-8 string
521 );
522
523 StaticPacket<pw::bluetooth::emboss::ExtendedInquiryResultEventWriter> eirep;
524 eirep.view().num_responses().Write(1);
525 eirep.view().bd_addr().CopyFrom(peer().address().value().view());
526 eirep.view().extended_inquiry_response().BackingStorage().CopyFrom(
527 ::emboss::support::ReadOnlyContiguousBuffer(&kEirData), kEirData.size());
528
529 peer().MutBrEdr().SetInquiryData(eirep.view());
530 EXPECT_TRUE(listener_notified); // Fresh EIR data still results in an update
531 EXPECT_FALSE(peer().name().has_value());
532 }
533
TEST_F(PeerTest,RegisterNameWithInvalidUtf8NameDoesNotUpdatePeerName)534 TEST_F(PeerTest, RegisterNameWithInvalidUtf8NameDoesNotUpdatePeerName) {
535 ASSERT_FALSE(peer().name().has_value());
536
537 bool listener_notified = false;
538 set_notify_listeners_cb(
539 [&](auto&, Peer::NotifyListenersChange) { listener_notified = true; });
540
541 const std::string kName =
542 "Tes\xFF\x01"; // 0xFF should not appear in a valid UTF-8 string
543 peer().RegisterName(kName);
544 EXPECT_FALSE(listener_notified);
545 EXPECT_FALSE(peer().name().has_value());
546 }
547
TEST_F(PeerTest,LowEnergyAdvertisingDataTimestamp)548 TEST_F(PeerTest, LowEnergyAdvertisingDataTimestamp) {
549 EXPECT_FALSE(peer().MutLe().parsed_advertising_data_timestamp());
550 peer().MutLe().SetAdvertisingData(
551 /*rssi=*/0,
552 kAdvData,
553 pw::chrono::SystemClock::time_point(std::chrono::nanoseconds(1)));
554 ASSERT_TRUE(peer().MutLe().parsed_advertising_data_timestamp());
555 EXPECT_EQ(peer().MutLe().parsed_advertising_data_timestamp().value(),
556 pw::chrono::SystemClock::time_point(std::chrono::nanoseconds(1)));
557
558 peer().MutLe().SetAdvertisingData(
559 /*rssi=*/0,
560 kAdvData,
561 pw::chrono::SystemClock::time_point(std::chrono::nanoseconds(2)));
562 ASSERT_TRUE(peer().MutLe().parsed_advertising_data_timestamp());
563 EXPECT_EQ(peer().MutLe().parsed_advertising_data_timestamp().value(),
564 pw::chrono::SystemClock::time_point(std::chrono::nanoseconds(2)));
565
566 // SetAdvertisingData with data that fails to parse should not update the
567 // advertising data timestamp.
568 peer().MutLe().SetAdvertisingData(
569 /*rssi=*/0,
570 kInvalidAdvData,
571 pw::chrono::SystemClock::time_point(std::chrono::nanoseconds(3)));
572 ASSERT_TRUE(peer().MutLe().parsed_advertising_data_timestamp());
573 EXPECT_EQ(peer().MutLe().parsed_advertising_data_timestamp().value(),
574 pw::chrono::SystemClock::time_point(std::chrono::nanoseconds(2)));
575 }
576
TEST_F(PeerTest,SettingLowEnergyAdvertisingDataUpdatesLastUpdated)577 TEST_F(PeerTest, SettingLowEnergyAdvertisingDataUpdatesLastUpdated) {
578 EXPECT_EQ(peer().last_updated(),
579 pw::chrono::SystemClock::time_point(std::chrono::nanoseconds(0)));
580
581 int notify_count = 0;
582 set_notify_listeners_cb([&](const Peer&, Peer::NotifyListenersChange) {
583 EXPECT_EQ(peer().last_updated(),
584 pw::chrono::SystemClock::time_point(std::chrono::nanoseconds(2)));
585 notify_count++;
586 });
587
588 RunFor(pw::chrono::SystemClock::duration(2));
589 peer().MutLe().SetAdvertisingData(
590 /*rssi=*/0,
591 kAdvData,
592 pw::chrono::SystemClock::time_point(std::chrono::nanoseconds(1)));
593 EXPECT_EQ(peer().last_updated(),
594 pw::chrono::SystemClock::time_point(std::chrono::nanoseconds(2)));
595 EXPECT_GE(notify_count, 1);
596 }
597
TEST_F(PeerTest,RegisteringLowEnergyInitializingConnectionUpdatesLastUpdated)598 TEST_F(PeerTest, RegisteringLowEnergyInitializingConnectionUpdatesLastUpdated) {
599 EXPECT_EQ(peer().last_updated(),
600 pw::chrono::SystemClock::time_point(std::chrono::nanoseconds(0)));
601
602 int notify_count = 0;
603 set_notify_listeners_cb([&](const Peer&, Peer::NotifyListenersChange) {
604 EXPECT_EQ(peer().last_updated(),
605 pw::chrono::SystemClock::time_point(std::chrono::nanoseconds(2)));
606 notify_count++;
607 });
608
609 RunFor(pw::chrono::SystemClock::duration(2));
610 Peer::InitializingConnectionToken token =
611 peer().MutLe().RegisterInitializingConnection();
612 EXPECT_EQ(peer().last_updated(),
613 pw::chrono::SystemClock::time_point(std::chrono::nanoseconds(2)));
614 EXPECT_GE(notify_count, 1);
615 }
616
TEST_F(PeerTest,SettingLowEnergyBondDataUpdatesLastUpdated)617 TEST_F(PeerTest, SettingLowEnergyBondDataUpdatesLastUpdated) {
618 EXPECT_EQ(peer().last_updated(),
619 pw::chrono::SystemClock::time_point(std::chrono::nanoseconds(0)));
620
621 int notify_count = 0;
622 set_notify_listeners_cb([&](const Peer&, Peer::NotifyListenersChange) {
623 EXPECT_EQ(peer().last_updated(),
624 pw::chrono::SystemClock::time_point(std::chrono::nanoseconds(2)));
625 notify_count++;
626 });
627
628 RunFor(pw::chrono::SystemClock::duration(2));
629 sm::PairingData data;
630 data.peer_ltk = kLTK;
631 data.local_ltk = kLTK;
632 peer().MutLe().SetBondData(data);
633 EXPECT_EQ(peer().last_updated(),
634 pw::chrono::SystemClock::time_point(std::chrono::nanoseconds(2)));
635 EXPECT_GE(notify_count, 1);
636 }
637
TEST_F(PeerTest,RegisteringBrEdrInitializingConnectionUpdatesLastUpdated)638 TEST_F(PeerTest, RegisteringBrEdrInitializingConnectionUpdatesLastUpdated) {
639 EXPECT_EQ(peer().last_updated(),
640 pw::chrono::SystemClock::time_point(std::chrono::nanoseconds(0)));
641
642 int notify_count = 0;
643 set_notify_listeners_cb([&](const Peer&, Peer::NotifyListenersChange) {
644 EXPECT_EQ(peer().last_updated(),
645 pw::chrono::SystemClock::time_point(std::chrono::nanoseconds(2)));
646 notify_count++;
647 });
648
649 RunFor(pw::chrono::SystemClock::duration(2));
650 Peer::InitializingConnectionToken token =
651 peer().MutBrEdr().RegisterInitializingConnection();
652 EXPECT_EQ(peer().last_updated(),
653 pw::chrono::SystemClock::time_point(std::chrono::nanoseconds(2)));
654 EXPECT_GE(notify_count, 1);
655 }
656
TEST_F(PeerTest,SettingInquiryDataUpdatesLastUpdated)657 TEST_F(PeerTest, SettingInquiryDataUpdatesLastUpdated) {
658 SetUpPeer(/*address=*/kAddrLeAlias, /*connectable=*/true);
659 EXPECT_EQ(peer().last_updated(),
660 pw::chrono::SystemClock::time_point(std::chrono::nanoseconds(0)));
661
662 int notify_count = 0;
663 set_notify_listeners_cb([&](const Peer&, Peer::NotifyListenersChange) {
664 EXPECT_EQ(peer().last_updated(),
665 pw::chrono::SystemClock::time_point(std::chrono::nanoseconds(2)));
666 notify_count++;
667 });
668
669 RunFor(pw::chrono::SystemClock::duration(2));
670 StaticPacket<pw::bluetooth::emboss::InquiryResultWriter> ir;
671 ir.view().bd_addr().CopyFrom(kAddrLeAlias.value().view());
672 peer().MutBrEdr().SetInquiryData(ir.view());
673 EXPECT_EQ(peer().last_updated(),
674 pw::chrono::SystemClock::time_point(std::chrono::nanoseconds(2)));
675 EXPECT_GE(notify_count, 1);
676 }
677
TEST_F(PeerTest,SettingBrEdrBondDataUpdatesLastUpdated)678 TEST_F(PeerTest, SettingBrEdrBondDataUpdatesLastUpdated) {
679 EXPECT_EQ(peer().last_updated(),
680 pw::chrono::SystemClock::time_point(std::chrono::nanoseconds(0)));
681
682 int notify_count = 0;
683 set_notify_listeners_cb([&](const Peer&, Peer::NotifyListenersChange) {
684 EXPECT_EQ(peer().last_updated(),
685 pw::chrono::SystemClock::time_point(std::chrono::nanoseconds(2)));
686 notify_count++;
687 });
688
689 RunFor(pw::chrono::SystemClock::duration(2));
690 peer().MutBrEdr().SetBondData(kSecureBrEdrKey);
691 EXPECT_EQ(peer().last_updated(),
692 pw::chrono::SystemClock::time_point(std::chrono::nanoseconds(2)));
693 EXPECT_GE(notify_count, 1);
694 }
695
TEST_F(PeerTest,SettingAddingBrEdrServiceUpdatesLastUpdated)696 TEST_F(PeerTest, SettingAddingBrEdrServiceUpdatesLastUpdated) {
697 EXPECT_EQ(peer().last_updated(),
698 pw::chrono::SystemClock::time_point(std::chrono::nanoseconds(0)));
699
700 int notify_count = 0;
701 set_notify_listeners_cb([&](const Peer&, Peer::NotifyListenersChange) {
702 EXPECT_EQ(peer().last_updated(),
703 pw::chrono::SystemClock::time_point(std::chrono::nanoseconds(2)));
704 notify_count++;
705 });
706
707 RunFor(pw::chrono::SystemClock::duration(2));
708 peer().MutBrEdr().AddService(UUID(uint16_t{0x110b}));
709 EXPECT_EQ(peer().last_updated(),
710 pw::chrono::SystemClock::time_point(std::chrono::nanoseconds(2)));
711 EXPECT_GE(notify_count, 1);
712 }
713
TEST_F(PeerTest,RegisteringNameUpdatesLastUpdated)714 TEST_F(PeerTest, RegisteringNameUpdatesLastUpdated) {
715 EXPECT_EQ(peer().last_updated(),
716 pw::chrono::SystemClock::time_point(std::chrono::nanoseconds(0)));
717
718 int notify_count = 0;
719 set_notify_listeners_cb([&](const Peer&, Peer::NotifyListenersChange) {
720 EXPECT_EQ(peer().last_updated(),
721 pw::chrono::SystemClock::time_point(std::chrono::nanoseconds(2)));
722 notify_count++;
723 });
724
725 RunFor(pw::chrono::SystemClock::duration(2));
726 peer().RegisterName("name");
727 EXPECT_EQ(peer().last_updated(),
728 pw::chrono::SystemClock::time_point(std::chrono::nanoseconds(2)));
729 EXPECT_GE(notify_count, 1);
730 }
731
TEST_F(PeerTest,RegisterAndUnregisterTwoLowEnergyConnections)732 TEST_F(PeerTest, RegisterAndUnregisterTwoLowEnergyConnections) {
733 SetUpPeer(/*address=*/kAddrLeRandom, /*connectable=*/true);
734
735 int update_expiry_count = 0;
736 set_update_expiry_cb([&](const Peer&) { update_expiry_count++; });
737 int notify_count = 0;
738 set_notify_listeners_cb(
739 [&](const Peer&, Peer::NotifyListenersChange) { notify_count++; });
740
741 std::optional<Peer::ConnectionToken> token_0 =
742 peer().MutLe().RegisterConnection();
743 // A notification and expiry update are sent when the peer becomes
744 // non-temporary, and a second notification and update expiry are sent because
745 // the connection is registered.
746 EXPECT_EQ(update_expiry_count, 2);
747 EXPECT_EQ(notify_count, 2);
748 EXPECT_FALSE(peer().temporary());
749 EXPECT_EQ(peer().le()->connection_state(), Peer::ConnectionState::kConnected);
750 #ifndef NINSPECT
751 EXPECT_EQ(InspectLowEnergyConnectionState(),
752 Peer::ConnectionStateToString(Peer::ConnectionState::kConnected));
753 EXPECT_EQ(MetricsLowEnergyConnections(), 1u);
754 #endif // NINSPECT
755
756 std::optional<Peer::ConnectionToken> token_1 =
757 peer().MutLe().RegisterConnection();
758 // The second connection should not update expiry or notify.
759 EXPECT_EQ(update_expiry_count, 2);
760 EXPECT_EQ(notify_count, 2);
761 EXPECT_FALSE(peer().temporary());
762 EXPECT_EQ(peer().le()->connection_state(), Peer::ConnectionState::kConnected);
763 #ifndef NINSPECT
764 EXPECT_EQ(InspectLowEnergyConnectionState(),
765 Peer::ConnectionStateToString(Peer::ConnectionState::kConnected));
766 // Although the second connection does not change the high-level connection
767 // state, we track it in metrics to support multiple connections to the same
768 // peer.
769 EXPECT_EQ(MetricsLowEnergyConnections(), 2u);
770 EXPECT_EQ(MetricsLowEnergyDisconnections(), 0u);
771 #endif // NINSPECT
772
773 token_0.reset();
774 EXPECT_EQ(update_expiry_count, 2);
775 EXPECT_EQ(notify_count, 2);
776 EXPECT_FALSE(peer().temporary());
777 EXPECT_EQ(peer().le()->connection_state(), Peer::ConnectionState::kConnected);
778 #ifndef NINSPECT
779 EXPECT_EQ(InspectLowEnergyConnectionState(),
780 Peer::ConnectionStateToString(Peer::ConnectionState::kConnected));
781 EXPECT_EQ(MetricsLowEnergyDisconnections(), 1u);
782 #endif // NINSPECT
783
784 token_1.reset();
785 EXPECT_EQ(update_expiry_count, 3);
786 EXPECT_EQ(notify_count, 3);
787 EXPECT_TRUE(peer().temporary());
788 EXPECT_EQ(peer().le()->connection_state(),
789 Peer::ConnectionState::kNotConnected);
790 #ifndef NINSPECT
791 EXPECT_EQ(
792 InspectLowEnergyConnectionState(),
793 Peer::ConnectionStateToString(Peer::ConnectionState::kNotConnected));
794 EXPECT_EQ(MetricsLowEnergyDisconnections(), 2u);
795 #endif // NINSPECT
796 }
797
TEST_F(PeerTest,RegisterAndUnregisterLowEnergyConnectionsWhenIdentityKnown)798 TEST_F(PeerTest, RegisterAndUnregisterLowEnergyConnectionsWhenIdentityKnown) {
799 EXPECT_TRUE(peer().identity_known());
800 std::optional<Peer::ConnectionToken> token =
801 peer().MutLe().RegisterConnection();
802 EXPECT_FALSE(peer().temporary());
803 token.reset();
804 // The peer's identity is known, so it should stay non-temporary upon
805 // disconnection.
806 EXPECT_FALSE(peer().temporary());
807 EXPECT_EQ(peer().le()->connection_state(),
808 Peer::ConnectionState::kNotConnected);
809 #ifndef NINSPECT
810 EXPECT_EQ(
811 InspectLowEnergyConnectionState(),
812 Peer::ConnectionStateToString(Peer::ConnectionState::kNotConnected));
813 #endif // NINSPECT
814 }
815
TEST_F(PeerTest,RegisterAndUnregisterInitializingLowEnergyConnectionsWhenIdentityKnown)816 TEST_F(PeerTest,
817 RegisterAndUnregisterInitializingLowEnergyConnectionsWhenIdentityKnown) {
818 EXPECT_TRUE(peer().identity_known());
819 std::optional<Peer::InitializingConnectionToken> token =
820 peer().MutLe().RegisterInitializingConnection();
821 EXPECT_FALSE(peer().temporary());
822 token.reset();
823 // The peer's identity is known, so it should stay non-temporary upon
824 // disconnection.
825 EXPECT_FALSE(peer().temporary());
826 EXPECT_EQ(peer().le()->connection_state(),
827 Peer::ConnectionState::kNotConnected);
828 #ifndef NINSPECT
829 EXPECT_EQ(
830 InspectLowEnergyConnectionState(),
831 Peer::ConnectionStateToString(Peer::ConnectionState::kNotConnected));
832 #endif // NINSPECT
833 }
834
TEST_F(PeerTest,RegisterAndUnregisterLowEnergyConnectionDuringInitializingConnection)835 TEST_F(PeerTest,
836 RegisterAndUnregisterLowEnergyConnectionDuringInitializingConnection) {
837 SetUpPeer(/*address=*/kAddrLeRandom, /*connectable=*/true);
838
839 int update_expiry_count = 0;
840 set_update_expiry_cb([&](const Peer&) { update_expiry_count++; });
841 int notify_count = 0;
842 set_notify_listeners_cb(
843 [&](const Peer&, Peer::NotifyListenersChange) { notify_count++; });
844
845 std::optional<Peer::InitializingConnectionToken> init_token =
846 peer().MutLe().RegisterInitializingConnection();
847 // A notification and expiry update are sent when the peer becomes
848 // non-temporary, and a second notification and update expiry are sent because
849 // the initializing connection is registered.
850 EXPECT_EQ(update_expiry_count, 2);
851 EXPECT_EQ(notify_count, 2);
852 EXPECT_FALSE(peer().temporary());
853 EXPECT_EQ(peer().le()->connection_state(),
854 Peer::ConnectionState::kInitializing);
855 #ifndef NINSPECT
856 EXPECT_EQ(
857 InspectLowEnergyConnectionState(),
858 Peer::ConnectionStateToString(Peer::ConnectionState::kInitializing));
859 #endif // NINSPECT
860
861 std::optional<Peer::ConnectionToken> conn_token =
862 peer().MutLe().RegisterConnection();
863 EXPECT_EQ(update_expiry_count, 3);
864 EXPECT_EQ(notify_count, 3);
865 EXPECT_FALSE(peer().temporary());
866 EXPECT_EQ(peer().le()->connection_state(), Peer::ConnectionState::kConnected);
867 #ifndef NINSPECT
868 EXPECT_EQ(InspectLowEnergyConnectionState(),
869 Peer::ConnectionStateToString(Peer::ConnectionState::kConnected));
870 #endif // NINSPECT
871
872 conn_token.reset();
873 EXPECT_EQ(update_expiry_count, 4);
874 EXPECT_EQ(notify_count, 4);
875 EXPECT_FALSE(peer().temporary());
876 EXPECT_EQ(peer().le()->connection_state(),
877 Peer::ConnectionState::kInitializing);
878 #ifndef NINSPECT
879 EXPECT_EQ(
880 InspectLowEnergyConnectionState(),
881 Peer::ConnectionStateToString(Peer::ConnectionState::kInitializing));
882 #endif // NINSPECT
883
884 init_token.reset();
885 EXPECT_EQ(update_expiry_count, 5);
886 EXPECT_EQ(notify_count, 5);
887 EXPECT_TRUE(peer().temporary());
888 EXPECT_EQ(peer().le()->connection_state(),
889 Peer::ConnectionState::kNotConnected);
890 #ifndef NINSPECT
891 EXPECT_EQ(
892 InspectLowEnergyConnectionState(),
893 Peer::ConnectionStateToString(Peer::ConnectionState::kNotConnected));
894 #endif // NINSPECT
895 }
896
TEST_F(PeerTest,RegisterAndUnregisterInitializingLowEnergyConnectionDuringConnection)897 TEST_F(PeerTest,
898 RegisterAndUnregisterInitializingLowEnergyConnectionDuringConnection) {
899 SetUpPeer(/*address=*/kAddrLeRandom, /*connectable=*/true);
900
901 int update_expiry_count = 0;
902 set_update_expiry_cb([&](const Peer&) { update_expiry_count++; });
903 int notify_count = 0;
904 set_notify_listeners_cb(
905 [&](const Peer&, Peer::NotifyListenersChange) { notify_count++; });
906
907 std::optional<Peer::ConnectionToken> conn_token =
908 peer().MutLe().RegisterConnection();
909 // A notification and expiry update are sent when the peer becomes
910 // non-temporary, and a second notification and update expiry are sent because
911 // the initializing connection is registered.
912 EXPECT_EQ(update_expiry_count, 2);
913 EXPECT_EQ(notify_count, 2);
914 EXPECT_FALSE(peer().temporary());
915 EXPECT_EQ(peer().le()->connection_state(), Peer::ConnectionState::kConnected);
916 #ifndef NINSPECT
917 EXPECT_EQ(InspectLowEnergyConnectionState(),
918 Peer::ConnectionStateToString(Peer::ConnectionState::kConnected));
919 #endif // NINSPECT
920
921 std::optional<Peer::InitializingConnectionToken> init_token =
922 peer().MutLe().RegisterInitializingConnection();
923 // Initializing connections should not affect the expiry or notify listeners
924 // for peers that are already connected.
925 EXPECT_EQ(update_expiry_count, 2);
926 EXPECT_EQ(notify_count, 2);
927 EXPECT_FALSE(peer().temporary());
928 EXPECT_EQ(peer().le()->connection_state(), Peer::ConnectionState::kConnected);
929 #ifndef NINSPECT
930 EXPECT_EQ(InspectLowEnergyConnectionState(),
931 Peer::ConnectionStateToString(Peer::ConnectionState::kConnected));
932 #endif // NINSPECT
933
934 init_token.reset();
935 EXPECT_EQ(update_expiry_count, 2);
936 EXPECT_EQ(notify_count, 2);
937 EXPECT_FALSE(peer().temporary());
938 EXPECT_EQ(peer().le()->connection_state(), Peer::ConnectionState::kConnected);
939 #ifndef NINSPECT
940 EXPECT_EQ(InspectLowEnergyConnectionState(),
941 Peer::ConnectionStateToString(Peer::ConnectionState::kConnected));
942 #endif // NINSPECT
943
944 conn_token.reset();
945 EXPECT_EQ(update_expiry_count, 3);
946 EXPECT_EQ(notify_count, 3);
947 EXPECT_TRUE(peer().temporary());
948 EXPECT_EQ(peer().le()->connection_state(),
949 Peer::ConnectionState::kNotConnected);
950 #ifndef NINSPECT
951 EXPECT_EQ(
952 InspectLowEnergyConnectionState(),
953 Peer::ConnectionStateToString(Peer::ConnectionState::kNotConnected));
954 #endif // NINSPECT
955 }
956
TEST_F(PeerTest,RegisterAndUnregisterTwoLowEnergyInitializingConnections)957 TEST_F(PeerTest, RegisterAndUnregisterTwoLowEnergyInitializingConnections) {
958 SetUpPeer(/*address=*/kAddrLeRandom, /*connectable=*/true);
959
960 int update_expiry_count = 0;
961 set_update_expiry_cb([&](const Peer&) { update_expiry_count++; });
962 int notify_count = 0;
963 set_notify_listeners_cb(
964 [&](const Peer&, Peer::NotifyListenersChange) { notify_count++; });
965
966 std::optional<Peer::InitializingConnectionToken> token_0 =
967 peer().MutLe().RegisterInitializingConnection();
968 // A notification and expiry update are sent when the peer becomes
969 // non-temporary, and a second notification and update expiry are sent because
970 // the initializing connection is registered.
971 EXPECT_EQ(update_expiry_count, 2);
972 EXPECT_EQ(notify_count, 2);
973 EXPECT_FALSE(peer().temporary());
974 EXPECT_EQ(peer().le()->connection_state(),
975 Peer::ConnectionState::kInitializing);
976 #ifndef NINSPECT
977 EXPECT_EQ(
978 InspectLowEnergyConnectionState(),
979 Peer::ConnectionStateToString(Peer::ConnectionState::kInitializing));
980 #endif // NINSPECT
981
982 std::optional<Peer::InitializingConnectionToken> token_1 =
983 peer().MutLe().RegisterInitializingConnection();
984 // The second initializing connection should not update expiry or notify.
985 EXPECT_EQ(update_expiry_count, 2);
986 EXPECT_EQ(notify_count, 2);
987 EXPECT_FALSE(peer().temporary());
988 EXPECT_EQ(peer().le()->connection_state(),
989 Peer::ConnectionState::kInitializing);
990 #ifndef NINSPECT
991 EXPECT_EQ(
992 InspectLowEnergyConnectionState(),
993 Peer::ConnectionStateToString(Peer::ConnectionState::kInitializing));
994 #endif // NINSPECT
995
996 token_0.reset();
997 EXPECT_EQ(update_expiry_count, 2);
998 EXPECT_EQ(notify_count, 2);
999 EXPECT_FALSE(peer().temporary());
1000 EXPECT_EQ(peer().le()->connection_state(),
1001 Peer::ConnectionState::kInitializing);
1002 #ifndef NINSPECT
1003 EXPECT_EQ(
1004 InspectLowEnergyConnectionState(),
1005 Peer::ConnectionStateToString(Peer::ConnectionState::kInitializing));
1006 #endif // NINSPECT
1007 token_1.reset();
1008 EXPECT_EQ(update_expiry_count, 3);
1009 EXPECT_EQ(notify_count, 3);
1010 // The peer's identity is not known, so it should become temporary upon
1011 // disconnection.
1012 EXPECT_TRUE(peer().temporary());
1013 EXPECT_EQ(peer().le()->connection_state(),
1014 Peer::ConnectionState::kNotConnected);
1015 #ifndef NINSPECT
1016 EXPECT_EQ(
1017 InspectLowEnergyConnectionState(),
1018 Peer::ConnectionStateToString(Peer::ConnectionState::kNotConnected));
1019 #endif // NINSPECT
1020 }
1021
TEST_F(PeerTest,MovingLowEnergyConnectionTokenWorksAsExpected)1022 TEST_F(PeerTest, MovingLowEnergyConnectionTokenWorksAsExpected) {
1023 std::optional<Peer::ConnectionToken> token_0 =
1024 peer().MutLe().RegisterConnection();
1025 EXPECT_EQ(peer().le()->connection_state(), Peer::ConnectionState::kConnected);
1026
1027 std::optional<Peer::ConnectionToken> token_1 = std::move(token_0);
1028 EXPECT_EQ(peer().le()->connection_state(), Peer::ConnectionState::kConnected);
1029
1030 token_0.reset();
1031 EXPECT_EQ(peer().le()->connection_state(), Peer::ConnectionState::kConnected);
1032
1033 token_1.reset();
1034 EXPECT_EQ(peer().le()->connection_state(),
1035 Peer::ConnectionState::kNotConnected);
1036 }
1037
TEST_F(PeerTest,RegisterNamesWithVariousSources)1038 TEST_F(PeerTest, RegisterNamesWithVariousSources) {
1039 ASSERT_FALSE(peer().name().has_value());
1040 ASSERT_TRUE(peer().RegisterName("test", Peer::kAdvertisingDataComplete));
1041
1042 // Test that name with lower source priority does not replace stored name with
1043 // higher priority.
1044 ASSERT_FALSE(peer().RegisterName("test", Peer::kUnknown));
1045
1046 // Test that name with higher source priority replaces stored name with lower
1047 // priority.
1048 ASSERT_TRUE(peer().RegisterName("test", Peer::kGenericAccessService));
1049
1050 // Test that stored name is not replaced with an identical name from an
1051 // identical source.
1052 ASSERT_FALSE(peer().RegisterName("test", Peer::kGenericAccessService));
1053
1054 // Test that stored name is replaced by a different name from the same source.
1055 ASSERT_TRUE(
1056 peer().RegisterName("different_name", Peer::kGenericAccessService));
1057 }
1058
TEST_F(PeerTest,SetValidAdvertisingData)1059 TEST_F(PeerTest, SetValidAdvertisingData) {
1060 constexpr const char* kLocalName = "Test";
1061 StaticByteBuffer raw_data{
1062 // Length - Type - Value formatted Local name
1063 0x05,
1064 static_cast<uint8_t>(DataType::kCompleteLocalName),
1065 kLocalName[0],
1066 kLocalName[1],
1067 kLocalName[2],
1068 kLocalName[3],
1069 };
1070 peer().MutLe().SetAdvertisingData(
1071 /*rssi=*/32, raw_data, pw::chrono::SystemClock::time_point());
1072 // Setting an AdvertisingData with a local name field should update the peer's
1073 // local name.
1074 ASSERT_TRUE(peer().name().has_value());
1075 EXPECT_EQ(kLocalName, peer().name().value());
1076 EXPECT_EQ(Peer::NameSource::kAdvertisingDataComplete, peer().name_source());
1077 #ifndef NINSPECT
1078 EXPECT_EQ(0, InspectAdvertisingDataParseFailureCount());
1079 EXPECT_EQ("", InspectLastAdvertisingDataParseFailure());
1080 #endif // NINSPECT
1081 }
1082
TEST_F(PeerTest,SetShortenedLocalName)1083 TEST_F(PeerTest, SetShortenedLocalName) {
1084 constexpr const char* kLocalName = "Test";
1085 StaticByteBuffer raw_data{
1086 // Length - Type - Value formatted Local name
1087 0x05,
1088 static_cast<uint8_t>(DataType::kShortenedLocalName),
1089 kLocalName[0],
1090 kLocalName[1],
1091 kLocalName[2],
1092 kLocalName[3],
1093 };
1094 peer().MutLe().SetAdvertisingData(
1095 /*rssi=*/32, raw_data, pw::chrono::SystemClock::time_point());
1096 ASSERT_TRUE(peer().name().has_value());
1097 EXPECT_EQ(kLocalName, peer().name().value());
1098 EXPECT_EQ(Peer::NameSource::kAdvertisingDataShortened, peer().name_source());
1099 }
1100
TEST_F(PeerTest,SetInvalidAdvertisingData)1101 TEST_F(PeerTest, SetInvalidAdvertisingData) {
1102 peer().MutLe().SetAdvertisingData(
1103 /*rssi=*/32, kInvalidAdvData, pw::chrono::SystemClock::time_point());
1104
1105 #ifndef NINSPECT
1106 EXPECT_EQ(1, InspectAdvertisingDataParseFailureCount());
1107 EXPECT_EQ(AdvertisingData::ParseErrorToString(
1108 AdvertisingData::ParseError::kUuidsMalformed),
1109 InspectLastAdvertisingDataParseFailure());
1110 #endif // NINSPECT
1111 }
1112
TEST_F(PeerDeathTest,RegisterTwoBrEdrConnectionsAsserts)1113 TEST_F(PeerDeathTest, RegisterTwoBrEdrConnectionsAsserts) {
1114 SetUpPeer(/*address=*/kAddrBrEdr, /*connectable=*/true);
1115 std::optional<Peer::ConnectionToken> token_0 =
1116 peer().MutBrEdr().RegisterConnection();
1117 ASSERT_DEATH_IF_SUPPORTED(
1118 {
1119 std::optional<Peer::ConnectionToken> token_1 =
1120 peer().MutBrEdr().RegisterConnection();
1121 },
1122 ".*already registered.*");
1123 }
1124
TEST_F(PeerTest,RegisterAndUnregisterInitializingBrEdrConnectionLeavesPeerTemporary)1125 TEST_F(PeerTest,
1126 RegisterAndUnregisterInitializingBrEdrConnectionLeavesPeerTemporary) {
1127 SetUpPeer(/*address=*/kAddrBrEdr, /*connectable=*/true);
1128 EXPECT_TRUE(peer().identity_known());
1129 std::optional<Peer::InitializingConnectionToken> token =
1130 peer().MutBrEdr().RegisterInitializingConnection();
1131 EXPECT_FALSE(peer().temporary());
1132 token.reset();
1133 EXPECT_TRUE(peer().temporary());
1134 EXPECT_EQ(peer().bredr()->connection_state(),
1135 Peer::ConnectionState::kNotConnected);
1136 #ifndef NINSPECT
1137 EXPECT_EQ(
1138 InspectBrEdrConnectionState(),
1139 Peer::ConnectionStateToString(Peer::ConnectionState::kNotConnected));
1140 #endif // NINSPECT
1141 }
1142
TEST_F(PeerTest,RegisterAndUnregisterBrEdrConnectionWithoutBonding)1143 TEST_F(PeerTest, RegisterAndUnregisterBrEdrConnectionWithoutBonding) {
1144 SetUpPeer(/*address=*/kAddrBrEdr, /*connectable=*/true);
1145
1146 int update_expiry_count = 0;
1147 set_update_expiry_cb([&](const Peer&) { update_expiry_count++; });
1148 int notify_count = 0;
1149 set_notify_listeners_cb(
1150 [&](const Peer&, Peer::NotifyListenersChange) { notify_count++; });
1151
1152 std::optional<Peer::ConnectionToken> conn_token =
1153 peer().MutBrEdr().RegisterConnection();
1154 // A notification and expiry update are sent when the peer becomes
1155 // non-temporary, and a second notification and update expiry are sent because
1156 // the initializing connection is registered.
1157 EXPECT_EQ(update_expiry_count, 2);
1158 EXPECT_EQ(notify_count, 2);
1159 EXPECT_FALSE(peer().temporary());
1160 EXPECT_EQ(peer().bredr()->connection_state(),
1161 Peer::ConnectionState::kConnected);
1162 #ifndef NINSPECT
1163 EXPECT_EQ(InspectBrEdrConnectionState(),
1164 Peer::ConnectionStateToString(Peer::ConnectionState::kConnected));
1165 #endif // NINSPECT
1166
1167 conn_token.reset();
1168 EXPECT_EQ(update_expiry_count, 3);
1169 EXPECT_EQ(notify_count, 3);
1170 // BR/EDR peers should become non-temporary after disconnecting if not bonded.
1171 EXPECT_TRUE(peer().temporary());
1172 EXPECT_EQ(peer().bredr()->connection_state(),
1173 Peer::ConnectionState::kNotConnected);
1174 #ifndef NINSPECT
1175 EXPECT_EQ(
1176 InspectBrEdrConnectionState(),
1177 Peer::ConnectionStateToString(Peer::ConnectionState::kNotConnected));
1178 #endif // NINSPECT
1179 }
1180
TEST_F(PeerTest,RegisterAndUnregisterBrEdrConnectionWithBonding)1181 TEST_F(PeerTest, RegisterAndUnregisterBrEdrConnectionWithBonding) {
1182 SetUpPeer(/*address=*/kAddrBrEdr, /*connectable=*/true);
1183
1184 int update_expiry_count = 0;
1185 set_update_expiry_cb([&](const Peer&) { update_expiry_count++; });
1186 int notify_count = 0;
1187 set_notify_listeners_cb(
1188 [&](const Peer&, Peer::NotifyListenersChange) { notify_count++; });
1189
1190 std::optional<Peer::ConnectionToken> conn_token =
1191 peer().MutBrEdr().RegisterConnection();
1192 // A notification and expiry update are sent when the peer becomes
1193 // non-temporary, and a second notification and update expiry are sent because
1194 // the initializing connection is registered.
1195 EXPECT_EQ(update_expiry_count, 2);
1196 EXPECT_EQ(notify_count, 2);
1197 EXPECT_FALSE(peer().temporary());
1198 EXPECT_EQ(peer().bredr()->connection_state(),
1199 Peer::ConnectionState::kConnected);
1200 #ifndef NINSPECT
1201 EXPECT_EQ(InspectBrEdrConnectionState(),
1202 Peer::ConnectionStateToString(Peer::ConnectionState::kConnected));
1203 #endif // NINSPECT
1204
1205 peer().MutBrEdr().SetBondData(kSecureBrEdrKey);
1206 EXPECT_EQ(update_expiry_count, 2);
1207 EXPECT_EQ(notify_count, 3);
1208
1209 conn_token.reset();
1210 EXPECT_EQ(update_expiry_count, 3);
1211 EXPECT_EQ(notify_count, 4);
1212 // Bonded BR/EDR peers should remain non-temporary after disconnecting.
1213 EXPECT_FALSE(peer().temporary());
1214 EXPECT_EQ(peer().bredr()->connection_state(),
1215 Peer::ConnectionState::kNotConnected);
1216 #ifndef NINSPECT
1217 EXPECT_EQ(
1218 InspectBrEdrConnectionState(),
1219 Peer::ConnectionStateToString(Peer::ConnectionState::kNotConnected));
1220 #endif // NINSPECT
1221 }
1222
TEST_F(PeerTest,RegisterAndUnregisterBrEdrConnectionDuringInitializingConnection)1223 TEST_F(PeerTest,
1224 RegisterAndUnregisterBrEdrConnectionDuringInitializingConnection) {
1225 SetUpPeer(/*address=*/kAddrBrEdr, /*connectable=*/true);
1226
1227 int update_expiry_count = 0;
1228 set_update_expiry_cb([&](const Peer&) { update_expiry_count++; });
1229 int notify_count = 0;
1230 set_notify_listeners_cb(
1231 [&](const Peer&, Peer::NotifyListenersChange) { notify_count++; });
1232
1233 std::optional<Peer::InitializingConnectionToken> init_token =
1234 peer().MutBrEdr().RegisterInitializingConnection();
1235 // Expiry is updated for state change + becoming non-temporary.
1236 EXPECT_EQ(update_expiry_count, 2);
1237 // 1 notification for becoming non-temporary.
1238 EXPECT_EQ(notify_count, 1);
1239 EXPECT_FALSE(peer().temporary());
1240 EXPECT_EQ(peer().bredr()->connection_state(),
1241 Peer::ConnectionState::kInitializing);
1242 #ifndef NINSPECT
1243 EXPECT_EQ(
1244 InspectBrEdrConnectionState(),
1245 Peer::ConnectionStateToString(Peer::ConnectionState::kInitializing));
1246 #endif // NINSPECT
1247
1248 // The connection state should not change when registering a connection
1249 // because the peer is still initializing.
1250 std::optional<Peer::ConnectionToken> conn_token =
1251 peer().MutBrEdr().RegisterConnection();
1252 EXPECT_EQ(update_expiry_count, 2);
1253 EXPECT_EQ(notify_count, 1);
1254 EXPECT_FALSE(peer().temporary());
1255 EXPECT_EQ(peer().bredr()->connection_state(),
1256 Peer::ConnectionState::kInitializing);
1257 #ifndef NINSPECT
1258 EXPECT_EQ(
1259 InspectBrEdrConnectionState(),
1260 Peer::ConnectionStateToString(Peer::ConnectionState::kInitializing));
1261 #endif // NINSPECT
1262
1263 conn_token.reset();
1264 EXPECT_EQ(update_expiry_count, 2);
1265 EXPECT_EQ(notify_count, 1);
1266 EXPECT_FALSE(peer().temporary());
1267 EXPECT_EQ(peer().bredr()->connection_state(),
1268 Peer::ConnectionState::kInitializing);
1269 #ifndef NINSPECT
1270 EXPECT_EQ(
1271 InspectBrEdrConnectionState(),
1272 Peer::ConnectionStateToString(Peer::ConnectionState::kInitializing));
1273 #endif // NINSPECT
1274
1275 init_token.reset();
1276 EXPECT_EQ(update_expiry_count, 3);
1277 EXPECT_EQ(notify_count, 1);
1278 EXPECT_TRUE(peer().temporary());
1279 EXPECT_EQ(peer().bredr()->connection_state(),
1280 Peer::ConnectionState::kNotConnected);
1281 #ifndef NINSPECT
1282 EXPECT_EQ(
1283 InspectBrEdrConnectionState(),
1284 Peer::ConnectionStateToString(Peer::ConnectionState::kNotConnected));
1285 #endif // NINSPECT
1286 }
1287
TEST_F(PeerTest,RegisterBrEdrConnectionDuringInitializingConnectionAndThenCompleteInitialization)1288 TEST_F(
1289 PeerTest,
1290 RegisterBrEdrConnectionDuringInitializingConnectionAndThenCompleteInitialization) {
1291 SetUpPeer(/*address=*/kAddrBrEdr, /*connectable=*/true);
1292
1293 int update_expiry_count = 0;
1294 set_update_expiry_cb([&](const Peer&) { update_expiry_count++; });
1295 int notify_count = 0;
1296 set_notify_listeners_cb(
1297 [&](const Peer&, Peer::NotifyListenersChange) { notify_count++; });
1298
1299 std::optional<Peer::InitializingConnectionToken> init_token =
1300 peer().MutBrEdr().RegisterInitializingConnection();
1301 // Expiry is updated for state change + becoming non-temporary.
1302 EXPECT_EQ(update_expiry_count, 2);
1303 // 1 notification for becoming non-temporary.
1304 EXPECT_EQ(notify_count, 1);
1305 EXPECT_FALSE(peer().temporary());
1306 EXPECT_EQ(peer().bredr()->connection_state(),
1307 Peer::ConnectionState::kInitializing);
1308 #ifndef NINSPECT
1309 EXPECT_EQ(
1310 InspectBrEdrConnectionState(),
1311 Peer::ConnectionStateToString(Peer::ConnectionState::kInitializing));
1312 #endif // NINSPECT
1313
1314 // The connection state should not change when registering a connection
1315 // because the peer is still initializing.
1316 std::optional<Peer::ConnectionToken> conn_token =
1317 peer().MutBrEdr().RegisterConnection();
1318 EXPECT_EQ(update_expiry_count, 2);
1319 EXPECT_EQ(notify_count, 1);
1320 EXPECT_FALSE(peer().temporary());
1321 EXPECT_EQ(peer().bredr()->connection_state(),
1322 Peer::ConnectionState::kInitializing);
1323 #ifndef NINSPECT
1324 EXPECT_EQ(
1325 InspectBrEdrConnectionState(),
1326 Peer::ConnectionStateToString(Peer::ConnectionState::kInitializing));
1327 #endif // NINSPECT
1328
1329 // When initialization completes, the connection state should become
1330 // kConnected.
1331 init_token.reset();
1332 EXPECT_EQ(update_expiry_count, 3);
1333 EXPECT_EQ(notify_count, 2);
1334 EXPECT_FALSE(peer().temporary());
1335 EXPECT_EQ(peer().bredr()->connection_state(),
1336 Peer::ConnectionState::kConnected);
1337 #ifndef NINSPECT
1338 EXPECT_EQ(InspectBrEdrConnectionState(),
1339 Peer::ConnectionStateToString(Peer::ConnectionState::kConnected));
1340 #endif // NINSPECT
1341
1342 conn_token.reset();
1343 EXPECT_EQ(update_expiry_count, 4);
1344 EXPECT_EQ(notify_count, 3);
1345 EXPECT_TRUE(peer().temporary());
1346 EXPECT_EQ(peer().bredr()->connection_state(),
1347 Peer::ConnectionState::kNotConnected);
1348 #ifndef NINSPECT
1349 EXPECT_EQ(
1350 InspectBrEdrConnectionState(),
1351 Peer::ConnectionStateToString(Peer::ConnectionState::kNotConnected));
1352 #endif // NINSPECT
1353 }
1354
TEST_F(PeerDeathTest,RegisterInitializingBrEdrConnectionDuringConnectionAsserts)1355 TEST_F(PeerDeathTest,
1356 RegisterInitializingBrEdrConnectionDuringConnectionAsserts) {
1357 SetUpPeer(/*address=*/kAddrBrEdr, /*connectable=*/true);
1358
1359 int update_expiry_count = 0;
1360 set_update_expiry_cb([&](const Peer&) { update_expiry_count++; });
1361 int notify_count = 0;
1362 set_notify_listeners_cb(
1363 [&](const Peer&, Peer::NotifyListenersChange) { notify_count++; });
1364
1365 std::optional<Peer::ConnectionToken> conn_token =
1366 peer().MutBrEdr().RegisterConnection();
1367 // A notification and expiry update are sent when the peer becomes
1368 // non-temporary, and a second notification and update expiry are sent because
1369 // the initializing connection is registered.
1370 EXPECT_EQ(update_expiry_count, 2);
1371 EXPECT_EQ(notify_count, 2);
1372 EXPECT_FALSE(peer().temporary());
1373 EXPECT_EQ(peer().bredr()->connection_state(),
1374 Peer::ConnectionState::kConnected);
1375 #ifndef NINSPECT
1376 EXPECT_EQ(InspectBrEdrConnectionState(),
1377 Peer::ConnectionStateToString(Peer::ConnectionState::kConnected));
1378 #endif // NINSPECT
1379
1380 // Registering an initializing connection when the peer is already connected
1381 // should assert.
1382 ASSERT_DEATH_IF_SUPPORTED(
1383 {
1384 Peer::InitializingConnectionToken init_token =
1385 peer().MutBrEdr().RegisterInitializingConnection();
1386 },
1387 ".*connected.*");
1388 }
1389
TEST_F(PeerTest,RegisterAndUnregisterTwoBrEdrInitializingConnections)1390 TEST_F(PeerTest, RegisterAndUnregisterTwoBrEdrInitializingConnections) {
1391 SetUpPeer(/*address=*/kAddrBrEdr, /*connectable=*/true);
1392
1393 int update_expiry_count = 0;
1394 set_update_expiry_cb([&](const Peer&) { update_expiry_count++; });
1395 int notify_count = 0;
1396 set_notify_listeners_cb(
1397 [&](const Peer&, Peer::NotifyListenersChange) { notify_count++; });
1398
1399 std::optional<Peer::InitializingConnectionToken> token_0 =
1400 peer().MutBrEdr().RegisterInitializingConnection();
1401 EXPECT_EQ(update_expiry_count, 2);
1402 EXPECT_EQ(notify_count, 1);
1403 EXPECT_FALSE(peer().temporary());
1404 EXPECT_EQ(peer().bredr()->connection_state(),
1405 Peer::ConnectionState::kInitializing);
1406 #ifndef NINSPECT
1407 std::optional<std::string> inspect_conn_state = InspectBrEdrConnectionState();
1408 ASSERT_TRUE(inspect_conn_state);
1409 EXPECT_EQ(
1410 inspect_conn_state.value(),
1411 Peer::ConnectionStateToString(Peer::ConnectionState::kInitializing));
1412 #endif // NINSPECT
1413
1414 std::optional<Peer::InitializingConnectionToken> token_1 =
1415 peer().MutBrEdr().RegisterInitializingConnection();
1416 // The second initializing connection should not update expiry or notify.
1417 EXPECT_EQ(update_expiry_count, 2);
1418 EXPECT_EQ(notify_count, 1);
1419 EXPECT_FALSE(peer().temporary());
1420 EXPECT_EQ(peer().bredr()->connection_state(),
1421 Peer::ConnectionState::kInitializing);
1422 #ifndef NINSPECT
1423 inspect_conn_state = InspectBrEdrConnectionState();
1424 ASSERT_TRUE(inspect_conn_state);
1425 EXPECT_EQ(
1426 inspect_conn_state.value(),
1427 Peer::ConnectionStateToString(Peer::ConnectionState::kInitializing));
1428 #endif // NINSPECT
1429
1430 token_0.reset();
1431 EXPECT_EQ(update_expiry_count, 2);
1432 EXPECT_EQ(notify_count, 1);
1433 EXPECT_FALSE(peer().temporary());
1434 EXPECT_EQ(peer().bredr()->connection_state(),
1435 Peer::ConnectionState::kInitializing);
1436 #ifndef NINSPECT
1437 inspect_conn_state = InspectBrEdrConnectionState();
1438 ASSERT_TRUE(inspect_conn_state);
1439 EXPECT_EQ(
1440 inspect_conn_state.value(),
1441 Peer::ConnectionStateToString(Peer::ConnectionState::kInitializing));
1442 #endif // NINSPECT
1443
1444 token_1.reset();
1445 EXPECT_EQ(update_expiry_count, 3);
1446 EXPECT_EQ(notify_count, 1);
1447 EXPECT_TRUE(peer().temporary());
1448 EXPECT_EQ(peer().bredr()->connection_state(),
1449 Peer::ConnectionState::kNotConnected);
1450 #ifndef NINSPECT
1451 inspect_conn_state = InspectBrEdrConnectionState();
1452 ASSERT_TRUE(inspect_conn_state);
1453 EXPECT_EQ(
1454 inspect_conn_state.value(),
1455 Peer::ConnectionStateToString(Peer::ConnectionState::kNotConnected));
1456 #endif // NINSPECT
1457 }
1458
TEST_F(PeerTest,SettingLeAdvertisingDataOfBondedPeerDoesNotUpdateName)1459 TEST_F(PeerTest, SettingLeAdvertisingDataOfBondedPeerDoesNotUpdateName) {
1460 peer().RegisterName("alice");
1461 sm::PairingData data;
1462 data.peer_ltk = kLTK;
1463 data.local_ltk = kLTK;
1464 peer().MutLe().SetBondData(data);
1465
1466 const StaticByteBuffer kAdvData(0x08, // Length
1467 0x09, // AD type: Complete Local Name
1468 'M',
1469 'a',
1470 'l',
1471 'l',
1472 'o',
1473 'r',
1474 'y');
1475 peer().MutLe().SetAdvertisingData(
1476 /*rssi=*/0,
1477 kAdvData,
1478 pw::chrono::SystemClock::time_point(std::chrono::nanoseconds(0)));
1479
1480 ASSERT_TRUE(peer().name().has_value());
1481 EXPECT_EQ(peer().name().value(), "alice");
1482 }
1483
TEST_F(PeerTest,SettingInquiryDataOfBondedPeerDoesNotUpdateName)1484 TEST_F(PeerTest, SettingInquiryDataOfBondedPeerDoesNotUpdateName) {
1485 peer().RegisterName("alice");
1486 peer().MutBrEdr().SetBondData(kLTK);
1487
1488 const StaticByteBuffer kEirData(0x08, // Length
1489 0x09, // AD type: Complete Local Name
1490 'M',
1491 'a',
1492 'l',
1493 'l',
1494 'o',
1495 'r',
1496 'y');
1497 StaticPacket<pw::bluetooth::emboss::ExtendedInquiryResultEventWriter> eirep;
1498 eirep.view().num_responses().Write(1);
1499 eirep.view().bd_addr().CopyFrom(peer().address().value().view());
1500 eirep.view().extended_inquiry_response().BackingStorage().CopyFrom(
1501 ::emboss::support::ReadOnlyContiguousBuffer(&kEirData), kEirData.size());
1502
1503 peer().MutBrEdr().SetInquiryData(eirep.view());
1504
1505 ASSERT_TRUE(peer().name().has_value());
1506 EXPECT_EQ(peer().name().value(), "alice");
1507 }
1508
TEST_F(PeerTest,BrEdrDataSetEirDataDoesUpdatePeerName)1509 TEST_F(PeerTest, BrEdrDataSetEirDataDoesUpdatePeerName) {
1510 peer().MutBrEdr(); // Initialize BrEdrData.
1511 ASSERT_FALSE(peer().name().has_value());
1512
1513 bool listener_notified = false;
1514 set_notify_listeners_cb(
1515 [&](auto&, Peer::NotifyListenersChange) { listener_notified = true; });
1516
1517 const StaticByteBuffer kEirData(0x0D, // Length (13)
1518 0x09, // AD type: Complete Local Name
1519 'S',
1520 'a',
1521 'p',
1522 'p',
1523 'h',
1524 'i',
1525 'r',
1526 'e',
1527 0xf0,
1528 0x9f,
1529 0x92,
1530 0x96);
1531
1532 StaticPacket<pw::bluetooth::emboss::ExtendedInquiryResultEventWriter> eirep;
1533 eirep.view().num_responses().Write(1);
1534 eirep.view().bd_addr().CopyFrom(peer().address().value().view());
1535 eirep.view().extended_inquiry_response().BackingStorage().CopyFrom(
1536 ::emboss::support::ReadOnlyContiguousBuffer(&kEirData), kEirData.size());
1537
1538 peer().MutBrEdr().SetInquiryData(eirep.view());
1539
1540 EXPECT_TRUE(listener_notified); // Fresh EIR data results in an update
1541 ASSERT_TRUE(peer().name().has_value());
1542 EXPECT_EQ(peer().name().value(), "Sapphire");
1543 }
1544
TEST_F(PeerTest,SetEirDataUpdatesServiceUUIDs)1545 TEST_F(PeerTest, SetEirDataUpdatesServiceUUIDs) {
1546 peer().MutBrEdr(); // Initialize BrEdrData.
1547 // clang-format off
1548 const StaticByteBuffer kEirJustServiceUuids{
1549 // One 16-bit UUID: AudioSink
1550 0x03, static_cast<uint8_t>(DataType::kIncomplete16BitServiceUuids), 0x0A, 0x11,
1551 };
1552
1553 StaticPacket<pw::bluetooth::emboss::ExtendedInquiryResultEventWriter> eirep;
1554 eirep.view().num_responses().Write(1);
1555 eirep.view().bd_addr().CopyFrom(peer().address().value().view());
1556 eirep.view().extended_inquiry_response().BackingStorage().CopyFrom(
1557 ::emboss::support::ReadOnlyContiguousBuffer(&kEirJustServiceUuids),
1558 kEirJustServiceUuids.size());
1559 peer().MutBrEdr().SetInquiryData(eirep.view());
1560
1561 EXPECT_EQ(peer().bredr()->services().size(), 1u);
1562 EXPECT_EQ(peer().bredr()->services().count(UUID((uint16_t)0x110A)), 1u);
1563 }
1564
TEST_F(PeerTest,LowEnergyStoreBondCallsCallback)1565 TEST_F(PeerTest, LowEnergyStoreBondCallsCallback) {
1566 int cb_count = 0;
1567 set_store_le_bond_cb([&cb_count](const sm::PairingData& data) {
1568 cb_count++;
1569 return true;
1570 });
1571
1572 sm::PairingData data;
1573 data.peer_ltk = kLTK;
1574 data.local_ltk = kLTK;
1575 EXPECT_TRUE(peer().MutLe().StoreBond(data));
1576 EXPECT_EQ(cb_count, 1);
1577 }
1578
1579 } // namespace
1580 } // namespace bt::gap
1581