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 PW_CHECK(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 PW_CHECK(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 PW_CHECK(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 PW_CHECK(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 PW_CHECK(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 PW_CHECK(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 PW_CHECK(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 PW_CHECK(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(
374 AllOf(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())))))));
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 kBadAdvData(
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, kBadAdvData, 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(
1041 peer().RegisterName("test", Peer::NameSource::kAdvertisingDataComplete));
1042
1043 // Test that name with lower source priority does not replace stored name with
1044 // higher priority.
1045 ASSERT_FALSE(peer().RegisterName("test", Peer::NameSource::kUnknown));
1046
1047 // Test that name with higher source priority replaces stored name with lower
1048 // priority.
1049 ASSERT_TRUE(
1050 peer().RegisterName("test", Peer::NameSource::kGenericAccessService));
1051
1052 // Test that stored name is not replaced with an identical name from an
1053 // identical source.
1054 ASSERT_FALSE(
1055 peer().RegisterName("test", Peer::NameSource::kGenericAccessService));
1056
1057 // Test that stored name is replaced by a different name from the same source.
1058 ASSERT_TRUE(peer().RegisterName("different_name",
1059 Peer::NameSource::kGenericAccessService));
1060 }
1061
TEST_F(PeerTest,SetValidAdvertisingData)1062 TEST_F(PeerTest, SetValidAdvertisingData) {
1063 constexpr const char* kLocalName = "Test";
1064 StaticByteBuffer raw_data{
1065 // Length - Type - Value formatted Local name
1066 0x05,
1067 static_cast<uint8_t>(DataType::kCompleteLocalName),
1068 kLocalName[0],
1069 kLocalName[1],
1070 kLocalName[2],
1071 kLocalName[3],
1072 };
1073 peer().MutLe().SetAdvertisingData(
1074 /*rssi=*/32, raw_data, pw::chrono::SystemClock::time_point());
1075 // Setting an AdvertisingData with a local name field should update the peer's
1076 // local name.
1077 ASSERT_TRUE(peer().name().has_value());
1078 EXPECT_EQ(kLocalName, peer().name().value());
1079 EXPECT_EQ(Peer::NameSource::kAdvertisingDataComplete, peer().name_source());
1080 #ifndef NINSPECT
1081 EXPECT_EQ(0, InspectAdvertisingDataParseFailureCount());
1082 EXPECT_EQ("", InspectLastAdvertisingDataParseFailure());
1083 #endif // NINSPECT
1084 }
1085
TEST_F(PeerTest,SetShortenedLocalName)1086 TEST_F(PeerTest, SetShortenedLocalName) {
1087 constexpr const char* kLocalName = "Test";
1088 StaticByteBuffer raw_data{
1089 // Length - Type - Value formatted Local name
1090 0x05,
1091 static_cast<uint8_t>(DataType::kShortenedLocalName),
1092 kLocalName[0],
1093 kLocalName[1],
1094 kLocalName[2],
1095 kLocalName[3],
1096 };
1097 peer().MutLe().SetAdvertisingData(
1098 /*rssi=*/32, raw_data, pw::chrono::SystemClock::time_point());
1099 ASSERT_TRUE(peer().name().has_value());
1100 EXPECT_EQ(kLocalName, peer().name().value());
1101 EXPECT_EQ(Peer::NameSource::kAdvertisingDataShortened, peer().name_source());
1102 }
1103
TEST_F(PeerTest,SetInvalidAdvertisingData)1104 TEST_F(PeerTest, SetInvalidAdvertisingData) {
1105 peer().MutLe().SetAdvertisingData(
1106 /*rssi=*/32, kInvalidAdvData, pw::chrono::SystemClock::time_point());
1107
1108 #ifndef NINSPECT
1109 EXPECT_EQ(1, InspectAdvertisingDataParseFailureCount());
1110 EXPECT_EQ(AdvertisingData::ParseErrorToString(
1111 AdvertisingData::ParseError::kUuidsMalformed),
1112 InspectLastAdvertisingDataParseFailure());
1113 #endif // NINSPECT
1114 }
1115
TEST_F(PeerDeathTest,RegisterTwoBrEdrConnectionsAsserts)1116 TEST_F(PeerDeathTest, RegisterTwoBrEdrConnectionsAsserts) {
1117 SetUpPeer(/*address=*/kAddrBrEdr, /*connectable=*/true);
1118 std::optional<Peer::ConnectionToken> token_0 =
1119 peer().MutBrEdr().RegisterConnection();
1120 ASSERT_DEATH_IF_SUPPORTED(
1121 {
1122 std::optional<Peer::ConnectionToken> token_1 =
1123 peer().MutBrEdr().RegisterConnection();
1124 },
1125 ".*already registered.*");
1126 }
1127
TEST_F(PeerTest,RegisterAndUnregisterInitializingBrEdrConnectionLeavesPeerTemporary)1128 TEST_F(PeerTest,
1129 RegisterAndUnregisterInitializingBrEdrConnectionLeavesPeerTemporary) {
1130 SetUpPeer(/*address=*/kAddrBrEdr, /*connectable=*/true);
1131 EXPECT_TRUE(peer().identity_known());
1132 std::optional<Peer::InitializingConnectionToken> token =
1133 peer().MutBrEdr().RegisterInitializingConnection();
1134 EXPECT_FALSE(peer().temporary());
1135 token.reset();
1136 EXPECT_TRUE(peer().temporary());
1137 EXPECT_EQ(peer().bredr()->connection_state(),
1138 Peer::ConnectionState::kNotConnected);
1139 #ifndef NINSPECT
1140 EXPECT_EQ(
1141 InspectBrEdrConnectionState(),
1142 Peer::ConnectionStateToString(Peer::ConnectionState::kNotConnected));
1143 #endif // NINSPECT
1144 }
1145
TEST_F(PeerTest,RegisterAndUnregisterBrEdrConnectionWithoutBonding)1146 TEST_F(PeerTest, RegisterAndUnregisterBrEdrConnectionWithoutBonding) {
1147 SetUpPeer(/*address=*/kAddrBrEdr, /*connectable=*/true);
1148
1149 int update_expiry_count = 0;
1150 set_update_expiry_cb([&](const Peer&) { update_expiry_count++; });
1151 int notify_count = 0;
1152 set_notify_listeners_cb(
1153 [&](const Peer&, Peer::NotifyListenersChange) { notify_count++; });
1154
1155 std::optional<Peer::ConnectionToken> conn_token =
1156 peer().MutBrEdr().RegisterConnection();
1157 // A notification and expiry update are sent when the peer becomes
1158 // non-temporary, and a second notification and update expiry are sent because
1159 // the initializing connection is registered.
1160 EXPECT_EQ(update_expiry_count, 2);
1161 EXPECT_EQ(notify_count, 2);
1162 EXPECT_FALSE(peer().temporary());
1163 EXPECT_EQ(peer().bredr()->connection_state(),
1164 Peer::ConnectionState::kConnected);
1165 #ifndef NINSPECT
1166 EXPECT_EQ(InspectBrEdrConnectionState(),
1167 Peer::ConnectionStateToString(Peer::ConnectionState::kConnected));
1168 #endif // NINSPECT
1169
1170 conn_token.reset();
1171 EXPECT_EQ(update_expiry_count, 3);
1172 EXPECT_EQ(notify_count, 3);
1173 // BR/EDR peers should become non-temporary after disconnecting if not bonded.
1174 EXPECT_TRUE(peer().temporary());
1175 EXPECT_EQ(peer().bredr()->connection_state(),
1176 Peer::ConnectionState::kNotConnected);
1177 #ifndef NINSPECT
1178 EXPECT_EQ(
1179 InspectBrEdrConnectionState(),
1180 Peer::ConnectionStateToString(Peer::ConnectionState::kNotConnected));
1181 #endif // NINSPECT
1182 }
1183
TEST_F(PeerTest,RegisterAndUnregisterBrEdrConnectionWithBonding)1184 TEST_F(PeerTest, RegisterAndUnregisterBrEdrConnectionWithBonding) {
1185 SetUpPeer(/*address=*/kAddrBrEdr, /*connectable=*/true);
1186
1187 int update_expiry_count = 0;
1188 set_update_expiry_cb([&](const Peer&) { update_expiry_count++; });
1189 int notify_count = 0;
1190 set_notify_listeners_cb(
1191 [&](const Peer&, Peer::NotifyListenersChange) { notify_count++; });
1192
1193 std::optional<Peer::ConnectionToken> conn_token =
1194 peer().MutBrEdr().RegisterConnection();
1195 // A notification and expiry update are sent when the peer becomes
1196 // non-temporary, and a second notification and update expiry are sent because
1197 // the initializing connection is registered.
1198 EXPECT_EQ(update_expiry_count, 2);
1199 EXPECT_EQ(notify_count, 2);
1200 EXPECT_FALSE(peer().temporary());
1201 EXPECT_EQ(peer().bredr()->connection_state(),
1202 Peer::ConnectionState::kConnected);
1203 #ifndef NINSPECT
1204 EXPECT_EQ(InspectBrEdrConnectionState(),
1205 Peer::ConnectionStateToString(Peer::ConnectionState::kConnected));
1206 #endif // NINSPECT
1207
1208 peer().MutBrEdr().SetBondData(kSecureBrEdrKey);
1209 EXPECT_EQ(update_expiry_count, 2);
1210 EXPECT_EQ(notify_count, 3);
1211
1212 conn_token.reset();
1213 EXPECT_EQ(update_expiry_count, 3);
1214 EXPECT_EQ(notify_count, 4);
1215 // Bonded BR/EDR peers should remain non-temporary after disconnecting.
1216 EXPECT_FALSE(peer().temporary());
1217 EXPECT_EQ(peer().bredr()->connection_state(),
1218 Peer::ConnectionState::kNotConnected);
1219 #ifndef NINSPECT
1220 EXPECT_EQ(
1221 InspectBrEdrConnectionState(),
1222 Peer::ConnectionStateToString(Peer::ConnectionState::kNotConnected));
1223 #endif // NINSPECT
1224 }
1225
TEST_F(PeerTest,RegisterAndUnregisterBrEdrConnectionDuringInitializingConnection)1226 TEST_F(PeerTest,
1227 RegisterAndUnregisterBrEdrConnectionDuringInitializingConnection) {
1228 SetUpPeer(/*address=*/kAddrBrEdr, /*connectable=*/true);
1229
1230 int update_expiry_count = 0;
1231 set_update_expiry_cb([&](const Peer&) { update_expiry_count++; });
1232 int notify_count = 0;
1233 set_notify_listeners_cb(
1234 [&](const Peer&, Peer::NotifyListenersChange) { notify_count++; });
1235
1236 std::optional<Peer::InitializingConnectionToken> init_token =
1237 peer().MutBrEdr().RegisterInitializingConnection();
1238 // Expiry is updated for state change + becoming non-temporary.
1239 EXPECT_EQ(update_expiry_count, 2);
1240 // 1 notification for becoming non-temporary.
1241 EXPECT_EQ(notify_count, 1);
1242 EXPECT_FALSE(peer().temporary());
1243 EXPECT_EQ(peer().bredr()->connection_state(),
1244 Peer::ConnectionState::kInitializing);
1245 #ifndef NINSPECT
1246 EXPECT_EQ(
1247 InspectBrEdrConnectionState(),
1248 Peer::ConnectionStateToString(Peer::ConnectionState::kInitializing));
1249 #endif // NINSPECT
1250
1251 // The connection state should not change when registering a connection
1252 // because the peer is still initializing.
1253 std::optional<Peer::ConnectionToken> conn_token =
1254 peer().MutBrEdr().RegisterConnection();
1255 EXPECT_EQ(update_expiry_count, 2);
1256 EXPECT_EQ(notify_count, 1);
1257 EXPECT_FALSE(peer().temporary());
1258 EXPECT_EQ(peer().bredr()->connection_state(),
1259 Peer::ConnectionState::kInitializing);
1260 #ifndef NINSPECT
1261 EXPECT_EQ(
1262 InspectBrEdrConnectionState(),
1263 Peer::ConnectionStateToString(Peer::ConnectionState::kInitializing));
1264 #endif // NINSPECT
1265
1266 conn_token.reset();
1267 EXPECT_EQ(update_expiry_count, 2);
1268 EXPECT_EQ(notify_count, 1);
1269 EXPECT_FALSE(peer().temporary());
1270 EXPECT_EQ(peer().bredr()->connection_state(),
1271 Peer::ConnectionState::kInitializing);
1272 #ifndef NINSPECT
1273 EXPECT_EQ(
1274 InspectBrEdrConnectionState(),
1275 Peer::ConnectionStateToString(Peer::ConnectionState::kInitializing));
1276 #endif // NINSPECT
1277
1278 init_token.reset();
1279 EXPECT_EQ(update_expiry_count, 3);
1280 EXPECT_EQ(notify_count, 1);
1281 EXPECT_TRUE(peer().temporary());
1282 EXPECT_EQ(peer().bredr()->connection_state(),
1283 Peer::ConnectionState::kNotConnected);
1284 #ifndef NINSPECT
1285 EXPECT_EQ(
1286 InspectBrEdrConnectionState(),
1287 Peer::ConnectionStateToString(Peer::ConnectionState::kNotConnected));
1288 #endif // NINSPECT
1289 }
1290
TEST_F(PeerTest,RegisterBrEdrConnectionDuringInitializingConnectionAndThenCompleteInitialization)1291 TEST_F(
1292 PeerTest,
1293 RegisterBrEdrConnectionDuringInitializingConnectionAndThenCompleteInitialization) {
1294 SetUpPeer(/*address=*/kAddrBrEdr, /*connectable=*/true);
1295
1296 int update_expiry_count = 0;
1297 set_update_expiry_cb([&](const Peer&) { update_expiry_count++; });
1298 int notify_count = 0;
1299 set_notify_listeners_cb(
1300 [&](const Peer&, Peer::NotifyListenersChange) { notify_count++; });
1301
1302 std::optional<Peer::InitializingConnectionToken> init_token =
1303 peer().MutBrEdr().RegisterInitializingConnection();
1304 // Expiry is updated for state change + becoming non-temporary.
1305 EXPECT_EQ(update_expiry_count, 2);
1306 // 1 notification for becoming non-temporary.
1307 EXPECT_EQ(notify_count, 1);
1308 EXPECT_FALSE(peer().temporary());
1309 EXPECT_EQ(peer().bredr()->connection_state(),
1310 Peer::ConnectionState::kInitializing);
1311 #ifndef NINSPECT
1312 EXPECT_EQ(
1313 InspectBrEdrConnectionState(),
1314 Peer::ConnectionStateToString(Peer::ConnectionState::kInitializing));
1315 #endif // NINSPECT
1316
1317 // The connection state should not change when registering a connection
1318 // because the peer is still initializing.
1319 std::optional<Peer::ConnectionToken> conn_token =
1320 peer().MutBrEdr().RegisterConnection();
1321 EXPECT_EQ(update_expiry_count, 2);
1322 EXPECT_EQ(notify_count, 1);
1323 EXPECT_FALSE(peer().temporary());
1324 EXPECT_EQ(peer().bredr()->connection_state(),
1325 Peer::ConnectionState::kInitializing);
1326 #ifndef NINSPECT
1327 EXPECT_EQ(
1328 InspectBrEdrConnectionState(),
1329 Peer::ConnectionStateToString(Peer::ConnectionState::kInitializing));
1330 #endif // NINSPECT
1331
1332 // When initialization completes, the connection state should become
1333 // kConnected.
1334 init_token.reset();
1335 EXPECT_EQ(update_expiry_count, 3);
1336 EXPECT_EQ(notify_count, 2);
1337 EXPECT_FALSE(peer().temporary());
1338 EXPECT_EQ(peer().bredr()->connection_state(),
1339 Peer::ConnectionState::kConnected);
1340 #ifndef NINSPECT
1341 EXPECT_EQ(InspectBrEdrConnectionState(),
1342 Peer::ConnectionStateToString(Peer::ConnectionState::kConnected));
1343 #endif // NINSPECT
1344
1345 conn_token.reset();
1346 EXPECT_EQ(update_expiry_count, 4);
1347 EXPECT_EQ(notify_count, 3);
1348 EXPECT_TRUE(peer().temporary());
1349 EXPECT_EQ(peer().bredr()->connection_state(),
1350 Peer::ConnectionState::kNotConnected);
1351 #ifndef NINSPECT
1352 EXPECT_EQ(
1353 InspectBrEdrConnectionState(),
1354 Peer::ConnectionStateToString(Peer::ConnectionState::kNotConnected));
1355 #endif // NINSPECT
1356 }
1357
TEST_F(PeerDeathTest,RegisterInitializingBrEdrConnectionDuringConnectionAsserts)1358 TEST_F(PeerDeathTest,
1359 RegisterInitializingBrEdrConnectionDuringConnectionAsserts) {
1360 SetUpPeer(/*address=*/kAddrBrEdr, /*connectable=*/true);
1361
1362 int update_expiry_count = 0;
1363 set_update_expiry_cb([&](const Peer&) { update_expiry_count++; });
1364 int notify_count = 0;
1365 set_notify_listeners_cb(
1366 [&](const Peer&, Peer::NotifyListenersChange) { notify_count++; });
1367
1368 std::optional<Peer::ConnectionToken> conn_token =
1369 peer().MutBrEdr().RegisterConnection();
1370 // A notification and expiry update are sent when the peer becomes
1371 // non-temporary, and a second notification and update expiry are sent because
1372 // the initializing connection is registered.
1373 EXPECT_EQ(update_expiry_count, 2);
1374 EXPECT_EQ(notify_count, 2);
1375 EXPECT_FALSE(peer().temporary());
1376 EXPECT_EQ(peer().bredr()->connection_state(),
1377 Peer::ConnectionState::kConnected);
1378 #ifndef NINSPECT
1379 EXPECT_EQ(InspectBrEdrConnectionState(),
1380 Peer::ConnectionStateToString(Peer::ConnectionState::kConnected));
1381 #endif // NINSPECT
1382
1383 // Registering an initializing connection when the peer is already connected
1384 // should assert.
1385 ASSERT_DEATH_IF_SUPPORTED(
1386 {
1387 Peer::InitializingConnectionToken init_token =
1388 peer().MutBrEdr().RegisterInitializingConnection();
1389 },
1390 ".*connected.*");
1391 }
1392
TEST_F(PeerTest,RegisterAndUnregisterTwoBrEdrInitializingConnections)1393 TEST_F(PeerTest, RegisterAndUnregisterTwoBrEdrInitializingConnections) {
1394 SetUpPeer(/*address=*/kAddrBrEdr, /*connectable=*/true);
1395
1396 int update_expiry_count = 0;
1397 set_update_expiry_cb([&](const Peer&) { update_expiry_count++; });
1398 int notify_count = 0;
1399 set_notify_listeners_cb(
1400 [&](const Peer&, Peer::NotifyListenersChange) { notify_count++; });
1401
1402 std::optional<Peer::InitializingConnectionToken> token_0 =
1403 peer().MutBrEdr().RegisterInitializingConnection();
1404 EXPECT_EQ(update_expiry_count, 2);
1405 EXPECT_EQ(notify_count, 1);
1406 EXPECT_FALSE(peer().temporary());
1407 EXPECT_EQ(peer().bredr()->connection_state(),
1408 Peer::ConnectionState::kInitializing);
1409 #ifndef NINSPECT
1410 std::optional<std::string> inspect_conn_state = InspectBrEdrConnectionState();
1411 ASSERT_TRUE(inspect_conn_state);
1412 EXPECT_EQ(
1413 inspect_conn_state.value(),
1414 Peer::ConnectionStateToString(Peer::ConnectionState::kInitializing));
1415 #endif // NINSPECT
1416
1417 std::optional<Peer::InitializingConnectionToken> token_1 =
1418 peer().MutBrEdr().RegisterInitializingConnection();
1419 // The second initializing connection should not update expiry or notify.
1420 EXPECT_EQ(update_expiry_count, 2);
1421 EXPECT_EQ(notify_count, 1);
1422 EXPECT_FALSE(peer().temporary());
1423 EXPECT_EQ(peer().bredr()->connection_state(),
1424 Peer::ConnectionState::kInitializing);
1425 #ifndef NINSPECT
1426 inspect_conn_state = InspectBrEdrConnectionState();
1427 ASSERT_TRUE(inspect_conn_state);
1428 EXPECT_EQ(
1429 inspect_conn_state.value(),
1430 Peer::ConnectionStateToString(Peer::ConnectionState::kInitializing));
1431 #endif // NINSPECT
1432
1433 token_0.reset();
1434 EXPECT_EQ(update_expiry_count, 2);
1435 EXPECT_EQ(notify_count, 1);
1436 EXPECT_FALSE(peer().temporary());
1437 EXPECT_EQ(peer().bredr()->connection_state(),
1438 Peer::ConnectionState::kInitializing);
1439 #ifndef NINSPECT
1440 inspect_conn_state = InspectBrEdrConnectionState();
1441 ASSERT_TRUE(inspect_conn_state);
1442 EXPECT_EQ(
1443 inspect_conn_state.value(),
1444 Peer::ConnectionStateToString(Peer::ConnectionState::kInitializing));
1445 #endif // NINSPECT
1446
1447 token_1.reset();
1448 EXPECT_EQ(update_expiry_count, 3);
1449 EXPECT_EQ(notify_count, 1);
1450 EXPECT_TRUE(peer().temporary());
1451 EXPECT_EQ(peer().bredr()->connection_state(),
1452 Peer::ConnectionState::kNotConnected);
1453 #ifndef NINSPECT
1454 inspect_conn_state = InspectBrEdrConnectionState();
1455 ASSERT_TRUE(inspect_conn_state);
1456 EXPECT_EQ(
1457 inspect_conn_state.value(),
1458 Peer::ConnectionStateToString(Peer::ConnectionState::kNotConnected));
1459 #endif // NINSPECT
1460 }
1461
TEST_F(PeerTest,SettingLeAdvertisingDataOfBondedPeerDoesNotUpdateName)1462 TEST_F(PeerTest, SettingLeAdvertisingDataOfBondedPeerDoesNotUpdateName) {
1463 peer().RegisterName("alice");
1464 sm::PairingData data;
1465 data.peer_ltk = kLTK;
1466 data.local_ltk = kLTK;
1467 peer().MutLe().SetBondData(data);
1468
1469 const StaticByteBuffer kBondedAdvData(0x08, // Length
1470 0x09, // AD type: Complete Local Name
1471 'M',
1472 'a',
1473 'l',
1474 'l',
1475 'o',
1476 'r',
1477 'y');
1478 peer().MutLe().SetAdvertisingData(
1479 /*rssi=*/0,
1480 kBondedAdvData,
1481 pw::chrono::SystemClock::time_point(std::chrono::nanoseconds(0)));
1482
1483 ASSERT_TRUE(peer().name().has_value());
1484 EXPECT_EQ(peer().name().value(), "alice");
1485 }
1486
TEST_F(PeerTest,SettingInquiryDataOfBondedPeerDoesNotUpdateName)1487 TEST_F(PeerTest, SettingInquiryDataOfBondedPeerDoesNotUpdateName) {
1488 peer().RegisterName("alice");
1489 peer().MutBrEdr().SetBondData(kLTK);
1490
1491 const StaticByteBuffer kEirData(0x08, // Length
1492 0x09, // AD type: Complete Local Name
1493 'M',
1494 'a',
1495 'l',
1496 'l',
1497 'o',
1498 'r',
1499 'y');
1500 StaticPacket<pw::bluetooth::emboss::ExtendedInquiryResultEventWriter> eirep;
1501 eirep.view().num_responses().Write(1);
1502 eirep.view().bd_addr().CopyFrom(peer().address().value().view());
1503 eirep.view().extended_inquiry_response().BackingStorage().CopyFrom(
1504 ::emboss::support::ReadOnlyContiguousBuffer(&kEirData), kEirData.size());
1505
1506 peer().MutBrEdr().SetInquiryData(eirep.view());
1507
1508 ASSERT_TRUE(peer().name().has_value());
1509 EXPECT_EQ(peer().name().value(), "alice");
1510 }
1511
TEST_F(PeerTest,BrEdrDataSetEirDataDoesUpdatePeerName)1512 TEST_F(PeerTest, BrEdrDataSetEirDataDoesUpdatePeerName) {
1513 peer().MutBrEdr(); // Initialize BrEdrData.
1514 ASSERT_FALSE(peer().name().has_value());
1515
1516 bool listener_notified = false;
1517 set_notify_listeners_cb(
1518 [&](auto&, Peer::NotifyListenersChange) { listener_notified = true; });
1519
1520 const StaticByteBuffer kEirData(0x0D, // Length (13)
1521 0x09, // AD type: Complete Local Name
1522 'S',
1523 'a',
1524 'p',
1525 'p',
1526 'h',
1527 'i',
1528 'r',
1529 'e',
1530 0xf0,
1531 0x9f,
1532 0x92,
1533 0x96);
1534
1535 StaticPacket<pw::bluetooth::emboss::ExtendedInquiryResultEventWriter> eirep;
1536 eirep.view().num_responses().Write(1);
1537 eirep.view().bd_addr().CopyFrom(peer().address().value().view());
1538 eirep.view().extended_inquiry_response().BackingStorage().CopyFrom(
1539 ::emboss::support::ReadOnlyContiguousBuffer(&kEirData), kEirData.size());
1540
1541 peer().MutBrEdr().SetInquiryData(eirep.view());
1542
1543 EXPECT_TRUE(listener_notified); // Fresh EIR data results in an update
1544 ASSERT_TRUE(peer().name().has_value());
1545 EXPECT_EQ(peer().name().value(), "Sapphire");
1546 }
1547
TEST_F(PeerTest,SetEirDataUpdatesServiceUUIDs)1548 TEST_F(PeerTest, SetEirDataUpdatesServiceUUIDs) {
1549 peer().MutBrEdr(); // Initialize BrEdrData.
1550 // clang-format off
1551 const StaticByteBuffer kEirJustServiceUuids{
1552 // One 16-bit UUID: AudioSink
1553 0x03, static_cast<uint8_t>(DataType::kIncomplete16BitServiceUuids), 0x0A, 0x11,
1554 };
1555
1556 StaticPacket<pw::bluetooth::emboss::ExtendedInquiryResultEventWriter> eirep;
1557 eirep.view().num_responses().Write(1);
1558 eirep.view().bd_addr().CopyFrom(peer().address().value().view());
1559 eirep.view().extended_inquiry_response().BackingStorage().CopyFrom(
1560 ::emboss::support::ReadOnlyContiguousBuffer(&kEirJustServiceUuids),
1561 kEirJustServiceUuids.size());
1562 peer().MutBrEdr().SetInquiryData(eirep.view());
1563
1564 EXPECT_EQ(peer().bredr()->services().size(), 1u);
1565 EXPECT_EQ(peer().bredr()->services().count(UUID((uint16_t)0x110A)), 1u);
1566 }
1567
TEST_F(PeerTest,LowEnergyStoreBondCallsCallback)1568 TEST_F(PeerTest, LowEnergyStoreBondCallsCallback) {
1569 int cb_count = 0;
1570 set_store_le_bond_cb([&cb_count](const sm::PairingData&) {
1571 cb_count++;
1572 return true;
1573 });
1574
1575 sm::PairingData data;
1576 data.peer_ltk = kLTK;
1577 data.local_ltk = kLTK;
1578 EXPECT_TRUE(peer().MutLe().StoreBond(data));
1579 EXPECT_EQ(cb_count, 1);
1580 }
1581
1582 } // namespace
1583 } // namespace bt::gap
1584