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