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/gatt/remote_service_manager.h"
16
17 #include <gmock/gmock.h>
18
19 #include <vector>
20
21 #include "pw_async/fake_dispatcher_fixture.h"
22 #include "pw_bluetooth_sapphire/internal/host/att/att.h"
23 #include "pw_bluetooth_sapphire/internal/host/att/error.h"
24 #include "pw_bluetooth_sapphire/internal/host/common/macros.h"
25 #include "pw_bluetooth_sapphire/internal/host/gatt/fake_client.h"
26 #include "pw_bluetooth_sapphire/internal/host/gatt/gatt_defs.h"
27 #include "pw_bluetooth_sapphire/internal/host/testing/test_helpers.h"
28
29 #pragma clang diagnostic ignored "-Wshadow"
30
31 namespace bt::gatt::internal {
32 namespace {
33
34 using namespace ::testing;
35
36 constexpr UUID kTestServiceUuid1(uint16_t{0xbeef});
37 constexpr UUID kTestServiceUuid2(uint16_t{0xcafe});
38 constexpr UUID kTestServiceUuid3(uint16_t{0xface});
39 constexpr UUID kTestUuid3(uint16_t{0xfefe});
40 constexpr UUID kTestUuid4(uint16_t{0xefef});
41
42 // Buffers for descriptor responses.
43 // ExtendedProperty::kReliableWrite enabled.
44 const StaticByteBuffer kExtendedPropValue(0x01, 0x00);
45 const StaticByteBuffer kCCCNotifyValue(0x01, 0x00);
46 const StaticByteBuffer kCCCIndicateValue(0x02, 0x00);
47
48 // Constants used for initializing fake characteristic data.
49 constexpr att::Handle kStart = 1;
50 constexpr att::Handle kCharDecl = 2;
51 constexpr att::Handle kCharValue = 3;
52 constexpr att::Handle kDesc1 = 4;
53 constexpr att::Handle kDesc2 = 5;
54 constexpr att::Handle kEnd = 5;
55
NopStatusCallback(att::Result<>)56 void NopStatusCallback(att::Result<>) {}
NopMtuCallback(uint16_t)57 void NopMtuCallback(uint16_t) {}
NopValueCallback(const ByteBuffer &,bool)58 void NopValueCallback(const ByteBuffer& /*value*/, bool /*maybe_truncated*/) {}
59
60 class RemoteServiceManagerTest : public pw::async::test::FakeDispatcherFixture {
61 public:
62 RemoteServiceManagerTest() = default;
63 ~RemoteServiceManagerTest() override = default;
64
65 protected:
SetUp()66 void SetUp() override {
67 auto client = std::make_unique<testing::FakeClient>(dispatcher());
68 fake_client_ = client.get();
69
70 mgr_ = std::make_unique<RemoteServiceManager>(std::move(client));
71 }
72
TearDown()73 void TearDown() override {
74 // Clear any previous expectations that are based on the ATT Write Request,
75 // so that write requests sent during RemoteService::ShutDown() are ignored.
76 if (fake_client_) {
77 fake_client()->set_write_request_callback({});
78 }
79 mgr_ = nullptr;
80 }
81
82 // Initializes a RemoteService based on |data|.
SetUpFakeService(const ServiceData & data)83 RemoteService::WeakPtr SetUpFakeService(const ServiceData& data) {
84 std::vector<ServiceData> fake_services{{data}};
85 fake_client()->set_services(std::move(fake_services));
86
87 mgr()->Initialize(NopStatusCallback, NopMtuCallback);
88
89 ServiceList services;
90 mgr()->ListServices(std::vector<UUID>(),
91 [&services](auto status, ServiceList cb_services) {
92 services = std::move(cb_services);
93 });
94
95 RunUntilIdle();
96
97 BT_DEBUG_ASSERT(services.size() == 1u);
98 return services[0];
99 }
100
SetCharacteristicsAndDescriptors(std::vector<CharacteristicData> fake_chrs,std::vector<DescriptorData> fake_descrs=std::vector<DescriptorData> ())101 void SetCharacteristicsAndDescriptors(
102 std::vector<CharacteristicData> fake_chrs,
103 std::vector<DescriptorData> fake_descrs = std::vector<DescriptorData>()) {
104 fake_client()->set_characteristics(std::move(fake_chrs));
105 fake_client()->set_descriptors(std::move(fake_descrs));
106 fake_client()->set_characteristic_discovery_status(fit::ok());
107 }
108
109 // Discover the characteristics of |service| based on the given |fake_data|.
SetupCharacteristics(RemoteService::WeakPtr service,std::vector<CharacteristicData> fake_chrs,std::vector<DescriptorData> fake_descrs=std::vector<DescriptorData> ())110 void SetupCharacteristics(
111 RemoteService::WeakPtr service,
112 std::vector<CharacteristicData> fake_chrs,
113 std::vector<DescriptorData> fake_descrs = std::vector<DescriptorData>()) {
114 BT_DEBUG_ASSERT(service.is_alive());
115
116 SetCharacteristicsAndDescriptors(std::move(fake_chrs),
117 std::move(fake_descrs));
118
119 service->DiscoverCharacteristics([](auto, const auto&) {});
120 RunUntilIdle();
121 }
122
SetupServiceWithChrcs(const ServiceData & data,std::vector<CharacteristicData> fake_chrs,std::vector<DescriptorData> fake_descrs=std::vector<DescriptorData> ())123 RemoteService::WeakPtr SetupServiceWithChrcs(
124 const ServiceData& data,
125 std::vector<CharacteristicData> fake_chrs,
126 std::vector<DescriptorData> fake_descrs = std::vector<DescriptorData>()) {
127 auto service = SetUpFakeService(data);
128 SetupCharacteristics(service, fake_chrs, fake_descrs);
129 return service;
130 }
131
132 // Create a fake service with one notifiable characteristic.
SetupNotifiableService()133 RemoteService::WeakPtr SetupNotifiableService() {
134 ServiceData data(ServiceKind::PRIMARY, 1, 4, kTestServiceUuid1);
135 auto service = SetUpFakeService(data);
136
137 CharacteristicData chr(Property::kNotify, std::nullopt, 2, 3, kTestUuid3);
138 DescriptorData desc(4, types::kClientCharacteristicConfig);
139 SetupCharacteristics(service, {{chr}}, {{desc}});
140
141 fake_client()->set_write_request_callback(
142 [&](att::Handle, const auto&, auto status_callback) {
143 status_callback(fit::ok());
144 });
145
146 RunUntilIdle();
147
148 return service;
149 }
150
EnableNotifications(RemoteService::WeakPtr service,CharacteristicHandle chr_id,att::Result<> * out_status,IdType * out_id,RemoteService::ValueCallback callback=NopValueCallback)151 void EnableNotifications(
152 RemoteService::WeakPtr service,
153 CharacteristicHandle chr_id,
154 att::Result<>* out_status,
155 IdType* out_id,
156 RemoteService::ValueCallback callback = NopValueCallback) {
157 BT_DEBUG_ASSERT(out_status);
158 BT_DEBUG_ASSERT(out_id);
159 service->EnableNotifications(chr_id,
160 std::move(callback),
161 [&](att::Result<> cb_status, IdType cb_id) {
162 *out_status = cb_status;
163 *out_id = cb_id;
164 });
165 RunUntilIdle();
166 }
167
DestroyServiceManager()168 void DestroyServiceManager() {
169 mgr_.reset();
170 fake_client_ = nullptr;
171 }
172
mgr() const173 RemoteServiceManager* mgr() const { return mgr_.get(); }
fake_client() const174 testing::FakeClient* fake_client() const { return fake_client_; }
175
176 private:
177 std::unique_ptr<RemoteServiceManager> mgr_;
178
179 // The memory is owned by |mgr_|.
180 testing::FakeClient* fake_client_;
181
182 BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(RemoteServiceManagerTest);
183 };
184
TEST_F(RemoteServiceManagerTest,InitializeNoServices)185 TEST_F(RemoteServiceManagerTest, InitializeNoServices) {
186 ServiceList services;
187 mgr()->set_service_watcher(
188 [&services](auto /*removed*/, ServiceList added, auto /*modified*/) {
189 services.insert(services.end(), added.begin(), added.end());
190 });
191
192 att::Result<> status = ToResult(HostError::kFailed);
193 mgr()->Initialize([&status](att::Result<> val) { status = val; },
194 NopMtuCallback);
195
196 RunUntilIdle();
197
198 EXPECT_EQ(fit::ok(), status);
199 EXPECT_TRUE(services.empty());
200
201 mgr()->ListServices(std::vector<UUID>(),
202 [&services](auto status, ServiceList cb_services) {
203 services = std::move(cb_services);
204 });
205 EXPECT_TRUE(services.empty());
206 }
207
TEST_F(RemoteServiceManagerTest,Initialize)208 TEST_F(RemoteServiceManagerTest, Initialize) {
209 ServiceData svc1(ServiceKind::PRIMARY, 1, 1, kTestServiceUuid1);
210 ServiceData svc2(ServiceKind::PRIMARY, 2, 2, kTestServiceUuid2);
211 std::vector<ServiceData> fake_services{{svc1, svc2}};
212 fake_client()->set_services(std::move(fake_services));
213
214 ServiceList services;
215 mgr()->set_service_watcher(
216 [&services](auto /*removed*/, ServiceList added, auto /*modified*/) {
217 services.insert(services.end(), added.begin(), added.end());
218 });
219
220 const uint16_t kArbitraryMtu = att::kLEMinMTU + 10;
221 fake_client()->set_server_mtu(kArbitraryMtu);
222
223 uint16_t new_mtu = 0;
224 auto mtu_cb = [&](uint16_t cb_mtu) { new_mtu = cb_mtu; };
225
226 att::Result<> status = ToResult(HostError::kFailed);
227 mgr()->Initialize([&status](att::Result<> val) { status = val; },
228 std::move(mtu_cb));
229
230 RunUntilIdle();
231
232 EXPECT_EQ(kArbitraryMtu, new_mtu);
233
234 EXPECT_EQ(fit::ok(), status);
235 EXPECT_EQ(2u, services.size());
236 EXPECT_EQ(svc1.range_start, services[0]->handle());
237 EXPECT_EQ(svc2.range_start, services[1]->handle());
238 EXPECT_EQ(svc1.type, services[0]->uuid());
239 EXPECT_EQ(svc2.type, services[1]->uuid());
240 }
241
TEST_F(RemoteServiceManagerTest,InitializeFailure)242 TEST_F(RemoteServiceManagerTest, InitializeFailure) {
243 fake_client()->set_discover_services_callback([](ServiceKind kind) {
244 if (kind == ServiceKind::PRIMARY) {
245 return ToResult(att::ErrorCode::kRequestNotSupported);
246 }
247 return att::Result<>(fit::ok());
248 });
249
250 ServiceList watcher_services;
251 mgr()->set_service_watcher([&watcher_services](auto /*removed*/,
252 ServiceList added,
253 auto /*modified*/) {
254 watcher_services.insert(watcher_services.end(), added.begin(), added.end());
255 });
256
257 ServiceList services;
258 mgr()->ListServices(std::vector<UUID>(),
259 [&services](auto status, ServiceList cb_services) {
260 services = std::move(cb_services);
261 });
262 ASSERT_TRUE(services.empty());
263
264 att::Result<> status = ToResult(HostError::kFailed);
265 mgr()->Initialize([&status](att::Result<> val) { status = val; },
266 NopMtuCallback);
267
268 RunUntilIdle();
269
270 EXPECT_EQ(ToResult(att::ErrorCode::kRequestNotSupported), status);
271 EXPECT_TRUE(services.empty());
272 EXPECT_TRUE(watcher_services.empty());
273 }
274
TEST_F(RemoteServiceManagerTest,InitializeMtuExchangeNotSupportedSucceeds)275 TEST_F(RemoteServiceManagerTest, InitializeMtuExchangeNotSupportedSucceeds) {
276 ServiceData svc(ServiceKind::PRIMARY, 1, 1, kTestServiceUuid1);
277 fake_client()->set_services({svc});
278 // The MTU exchange is an optional procedure, so if the peer tells us that
279 // they do not support it, we should continue with initialization.
280 fake_client()->set_exchange_mtu_status(
281 ToResult(att::ErrorCode::kRequestNotSupported));
282
283 ServiceList services;
284 mgr()->set_service_watcher(
285 [&services](auto /*removed*/, ServiceList added, auto /*modified*/) {
286 services.insert(services.end(), added.begin(), added.end());
287 });
288
289 std::optional<uint16_t> mtu;
290 auto mtu_cb = [&mtu](uint16_t cb_mtu) { mtu = cb_mtu; };
291
292 att::Result<> status = ToResult(HostError::kFailed);
293 mgr()->Initialize([&status](att::Result<> val) { status = val; },
294 std::move(mtu_cb));
295
296 RunUntilIdle();
297
298 EXPECT_EQ(fit::ok(), status);
299 ASSERT_EQ(1u, services.size());
300 EXPECT_EQ(svc.range_start, services[0]->handle());
301 EXPECT_EQ(svc.type, services[0]->uuid());
302
303 // If the MTU exchange isn't supported, "the default MTU shall be used" (v5.3
304 // Vol. 3 Part G 4.3.1)
305 ASSERT_TRUE(mtu.has_value());
306 EXPECT_EQ(att::kLEMinMTU, *mtu);
307 }
308
TEST_F(RemoteServiceManagerTest,InitializeMtuExchangeFailure)309 TEST_F(RemoteServiceManagerTest, InitializeMtuExchangeFailure) {
310 fake_client()->set_exchange_mtu_status(
311 ToResult(att::ErrorCode::kUnlikelyError));
312
313 bool mtu_updated = false;
314 auto mtu_cb = [&](uint16_t /*ignore*/) { mtu_updated = true; };
315
316 att::Result<> status = fit::ok();
317 mgr()->Initialize([&status](att::Result<> val) { status = val; },
318 std::move(mtu_cb));
319
320 RunUntilIdle();
321
322 EXPECT_EQ(ToResult(att::ErrorCode::kUnlikelyError), status);
323 EXPECT_FALSE(mtu_updated);
324 }
325
TEST_F(RemoteServiceManagerTest,InitializeByUUIDNoServices)326 TEST_F(RemoteServiceManagerTest, InitializeByUUIDNoServices) {
327 ServiceList services;
328 mgr()->set_service_watcher(
329 [&services](auto /*removed*/, ServiceList added, auto /*modified*/) {
330 services.insert(services.end(), added.begin(), added.end());
331 });
332
333 att::Result<> status = ToResult(HostError::kFailed);
334 mgr()->Initialize([&status](att::Result<> val) { status = val; },
335 NopMtuCallback,
336 {kTestServiceUuid1});
337
338 RunUntilIdle();
339
340 EXPECT_EQ(fit::ok(), status);
341 EXPECT_TRUE(services.empty());
342
343 mgr()->ListServices(std::vector<UUID>(),
344 [&services](auto status, ServiceList cb_services) {
345 services = std::move(cb_services);
346 });
347 EXPECT_TRUE(services.empty());
348 }
349
TEST_F(RemoteServiceManagerTest,InitializeWithUuids)350 TEST_F(RemoteServiceManagerTest, InitializeWithUuids) {
351 ServiceData svc1(ServiceKind::PRIMARY, 1, 1, kTestServiceUuid1);
352 ServiceData svc2(ServiceKind::PRIMARY, 2, 2, kTestServiceUuid2);
353 ServiceData svc3(ServiceKind::PRIMARY, 3, 3, kTestServiceUuid3);
354 std::vector<ServiceData> fake_services{{svc1, svc2, svc3}};
355 fake_client()->set_services(std::move(fake_services));
356
357 ServiceList services;
358 mgr()->set_service_watcher(
359 [&services](auto /*removed*/, ServiceList added, auto /*modified*/) {
360 services.insert(services.end(), added.begin(), added.end());
361 });
362
363 att::Result<> status = ToResult(HostError::kFailed);
364 mgr()->Initialize([&status](att::Result<> val) { status = val; },
365 NopMtuCallback,
366 {kTestServiceUuid1, kTestServiceUuid3});
367
368 RunUntilIdle();
369
370 EXPECT_EQ(fit::ok(), status);
371 std::vector<ServiceData> found_services;
372 for (const auto& ptr : services) {
373 found_services.push_back(ptr->info());
374 }
375 EXPECT_THAT(found_services, UnorderedElementsAre(Eq(svc1), Eq(svc3)));
376 }
377
TEST_F(RemoteServiceManagerTest,InitializeByUUIDFailure)378 TEST_F(RemoteServiceManagerTest, InitializeByUUIDFailure) {
379 fake_client()->set_discover_services_callback([](ServiceKind kind) {
380 if (kind == ServiceKind::PRIMARY) {
381 return ToResult(att::ErrorCode::kRequestNotSupported);
382 }
383 return att::Result<>(fit::ok());
384 });
385
386 ServiceList watcher_services;
387 mgr()->set_service_watcher([&watcher_services](auto /*removed*/,
388 ServiceList added,
389 auto /*modified*/) {
390 watcher_services.insert(watcher_services.end(), added.begin(), added.end());
391 });
392
393 ServiceList services;
394 mgr()->ListServices(std::vector<UUID>(),
395 [&services](auto status, ServiceList cb_services) {
396 services = std::move(cb_services);
397 });
398 ASSERT_TRUE(services.empty());
399
400 att::Result<> status = ToResult(HostError::kFailed);
401 mgr()->Initialize([&status](att::Result<> val) { status = val; },
402 NopMtuCallback,
403 {kTestServiceUuid1});
404
405 RunUntilIdle();
406
407 EXPECT_EQ(ToResult(att::ErrorCode::kRequestNotSupported), status);
408 EXPECT_TRUE(services.empty());
409 EXPECT_TRUE(watcher_services.empty());
410 }
411
TEST_F(RemoteServiceManagerTest,InitializeSecondaryServices)412 TEST_F(RemoteServiceManagerTest, InitializeSecondaryServices) {
413 ServiceData svc(ServiceKind::SECONDARY, 1, 1, kTestServiceUuid1);
414 std::vector<ServiceData> fake_services{{svc}};
415 fake_client()->set_services(std::move(fake_services));
416
417 ServiceList services;
418 mgr()->set_service_watcher(
419 [&services](auto /*removed*/, ServiceList added, auto /*modified*/) {
420 services.insert(services.end(), added.begin(), added.end());
421 });
422
423 att::Result<> status = ToResult(HostError::kFailed);
424 mgr()->Initialize([&status](att::Result<> val) { status = val; },
425 NopMtuCallback);
426
427 RunUntilIdle();
428
429 EXPECT_EQ(fit::ok(), status);
430 ASSERT_EQ(1u, services.size());
431 EXPECT_EQ(svc.range_start, services[0]->handle());
432 EXPECT_EQ(svc.type, services[0]->uuid());
433 EXPECT_EQ(ServiceKind::SECONDARY, services[0]->info().kind);
434 }
435
TEST_F(RemoteServiceManagerTest,InitializePrimaryAndSecondaryServices)436 TEST_F(RemoteServiceManagerTest, InitializePrimaryAndSecondaryServices) {
437 ServiceData svc1(ServiceKind::PRIMARY, 1, 1, kTestServiceUuid1);
438 ServiceData svc2(ServiceKind::SECONDARY, 2, 2, kTestServiceUuid2);
439 std::vector<ServiceData> fake_services{{svc1, svc2}};
440 fake_client()->set_services(std::move(fake_services));
441
442 ServiceList services;
443 mgr()->set_service_watcher(
444 [&services](auto /*removed*/, ServiceList added, auto /*modified*/) {
445 services.insert(services.end(), added.begin(), added.end());
446 });
447
448 att::Result<> status = ToResult(HostError::kFailed);
449 mgr()->Initialize([&status](att::Result<> val) { status = val; },
450 NopMtuCallback);
451
452 RunUntilIdle();
453
454 EXPECT_EQ(fit::ok(), status);
455 EXPECT_EQ(2u, services.size());
456 EXPECT_EQ(ServiceKind::PRIMARY, services[0]->info().kind);
457 EXPECT_EQ(ServiceKind::SECONDARY, services[1]->info().kind);
458 }
459
TEST_F(RemoteServiceManagerTest,InitializePrimaryAndSecondaryServicesOutOfOrder)460 TEST_F(RemoteServiceManagerTest,
461 InitializePrimaryAndSecondaryServicesOutOfOrder) {
462 // RemoteServiceManager discovers primary services first, followed by
463 // secondary services. Test that the results are stored and represented in the
464 // correct order when a secondary service precedes a primary service.
465 ServiceData svc1(ServiceKind::SECONDARY, 1, 1, kTestServiceUuid1);
466 ServiceData svc2(ServiceKind::PRIMARY, 2, 2, kTestServiceUuid2);
467 fake_client()->set_services({{svc1, svc2}});
468
469 ServiceList services;
470 mgr()->set_service_watcher(
471 [&services](auto /*removed*/, ServiceList added, auto /*modified*/) {
472 services.insert(services.end(), added.begin(), added.end());
473 });
474
475 att::Result<> status = ToResult(HostError::kFailed);
476 mgr()->Initialize([&status](att::Result<> val) { status = val; },
477 NopMtuCallback);
478 RunUntilIdle();
479
480 EXPECT_EQ(fit::ok(), status);
481 EXPECT_EQ(2u, services.size());
482 EXPECT_EQ(ServiceKind::SECONDARY, services[0]->info().kind);
483 EXPECT_EQ(ServiceKind::PRIMARY, services[1]->info().kind);
484 }
485
486 // Tests that an ATT error that occurs during secondary service aborts
487 // initialization.
TEST_F(RemoteServiceManagerTest,InitializeSecondaryServicesFailure)488 TEST_F(RemoteServiceManagerTest, InitializeSecondaryServicesFailure) {
489 fake_client()->set_discover_services_callback([](ServiceKind kind) {
490 if (kind == ServiceKind::SECONDARY) {
491 return ToResult(att::ErrorCode::kRequestNotSupported);
492 }
493 return att::Result<>(fit::ok());
494 });
495
496 ServiceList services;
497 mgr()->set_service_watcher(
498 [&services](auto /*removed*/, ServiceList added, auto /*modified*/) {
499 services.insert(services.end(), added.begin(), added.end());
500 });
501
502 att::Result<> status = fit::ok();
503 mgr()->Initialize([&status](att::Result<> val) { status = val; },
504 NopMtuCallback);
505 RunUntilIdle();
506
507 EXPECT_EQ(ToResult(att::ErrorCode::kRequestNotSupported), status);
508 EXPECT_TRUE(services.empty());
509 }
510
511 // Tests that the "unsupported group type" error is treated as a failure for
512 // primary services.
TEST_F(RemoteServiceManagerTest,InitializePrimaryServicesErrorUnsupportedGroupType)513 TEST_F(RemoteServiceManagerTest,
514 InitializePrimaryServicesErrorUnsupportedGroupType) {
515 fake_client()->set_discover_services_callback([](ServiceKind kind) {
516 if (kind == ServiceKind::PRIMARY) {
517 return ToResult(att::ErrorCode::kUnsupportedGroupType);
518 }
519 return att::Result<>(fit::ok());
520 });
521
522 ServiceList services;
523 mgr()->set_service_watcher(
524 [&services](auto /*removed*/, ServiceList added, auto /*modified*/) {
525 services.insert(services.end(), added.begin(), added.end());
526 });
527
528 att::Result<> status = fit::ok();
529 mgr()->Initialize([&status](att::Result<> val) { status = val; },
530 NopMtuCallback);
531 RunUntilIdle();
532
533 EXPECT_EQ(ToResult(att::ErrorCode::kUnsupportedGroupType), status);
534 EXPECT_TRUE(services.empty());
535 }
536
537 // Tests that the "unsupported group type" error is NOT treated as a failure for
538 // secondary services.
TEST_F(RemoteServiceManagerTest,InitializeSecondaryServicesErrorUnsupportedGroupTypeIsIgnored)539 TEST_F(RemoteServiceManagerTest,
540 InitializeSecondaryServicesErrorUnsupportedGroupTypeIsIgnored) {
541 ServiceData svc1(ServiceKind::PRIMARY, 1, 1, kTestServiceUuid1);
542 fake_client()->set_services({{svc1}});
543 fake_client()->set_discover_services_callback([](ServiceKind kind) {
544 if (kind == ServiceKind::SECONDARY) {
545 return ToResult(att::ErrorCode::kUnsupportedGroupType);
546 }
547 return att::Result<>(fit::ok());
548 });
549
550 ServiceList services;
551 mgr()->set_service_watcher(
552 [&services](auto /*removed*/, ServiceList added, auto /*modified*/) {
553 services.insert(services.end(), added.begin(), added.end());
554 });
555
556 att::Result<> status = fit::ok();
557 mgr()->Initialize([&status](att::Result<> val) { status = val; },
558 NopMtuCallback);
559 RunUntilIdle();
560
561 EXPECT_EQ(fit::ok(), status);
562 ASSERT_EQ(1u, services.size());
563 EXPECT_EQ(svc1, services[0]->info());
564 }
565
TEST_F(RemoteServiceManagerTest,ListServicesBeforeInit)566 TEST_F(RemoteServiceManagerTest, ListServicesBeforeInit) {
567 ServiceData svc(ServiceKind::PRIMARY, 1, 1, kTestServiceUuid1);
568 std::vector<ServiceData> fake_services{{svc}};
569 fake_client()->set_services(std::move(fake_services));
570
571 ServiceList services;
572 mgr()->ListServices(std::vector<UUID>(),
573 [&services](auto status, ServiceList cb_services) {
574 services = std::move(cb_services);
575 });
576 EXPECT_TRUE(services.empty());
577
578 att::Result<> status = ToResult(HostError::kFailed);
579 mgr()->Initialize([&status](att::Result<> val) { status = val; },
580 NopMtuCallback);
581
582 RunUntilIdle();
583
584 EXPECT_EQ(fit::ok(), status);
585 ASSERT_EQ(1u, services.size());
586 EXPECT_EQ(svc.range_start, services[0]->handle());
587 EXPECT_EQ(svc.type, services[0]->uuid());
588 }
589
TEST_F(RemoteServiceManagerTest,ListServicesAfterInit)590 TEST_F(RemoteServiceManagerTest, ListServicesAfterInit) {
591 ServiceData svc(ServiceKind::PRIMARY, 1, 1, kTestServiceUuid1);
592 std::vector<ServiceData> fake_services{{svc}};
593 fake_client()->set_services(std::move(fake_services));
594
595 att::Result<> status = ToResult(HostError::kFailed);
596 mgr()->Initialize([&status](att::Result<> val) { status = val; },
597 NopMtuCallback);
598
599 RunUntilIdle();
600
601 ASSERT_EQ(fit::ok(), status);
602
603 ServiceList services;
604 mgr()->ListServices(std::vector<UUID>(),
605 [&services](auto status, ServiceList cb_services) {
606 services = std::move(cb_services);
607 });
608 ASSERT_EQ(1u, services.size());
609 EXPECT_EQ(svc.range_start, services[0]->handle());
610 EXPECT_EQ(svc.type, services[0]->uuid());
611 }
612
TEST_F(RemoteServiceManagerTest,ListServicesByUuid)613 TEST_F(RemoteServiceManagerTest, ListServicesByUuid) {
614 std::vector<UUID> uuids{kTestServiceUuid1};
615
616 ServiceData svc1(ServiceKind::PRIMARY, 1, 1, kTestServiceUuid1);
617 ServiceData svc2(ServiceKind::PRIMARY, 2, 2, kTestServiceUuid2);
618 std::vector<ServiceData> fake_services{{svc1, svc2}};
619 fake_client()->set_services(std::move(fake_services));
620
621 ServiceList service_watcher_services;
622 mgr()->set_service_watcher([&service_watcher_services](auto /*removed*/,
623 ServiceList added,
624 auto /*modified*/) {
625 service_watcher_services.insert(
626 service_watcher_services.end(), added.begin(), added.end());
627 });
628
629 att::Result<> list_services_status = fit::ok();
630 ServiceList list_services;
631 mgr()->ListServices(std::move(uuids),
632 [&](att::Result<> cb_status, ServiceList cb_services) {
633 list_services_status = cb_status;
634 list_services = std::move(cb_services);
635 });
636 ASSERT_TRUE(service_watcher_services.empty());
637
638 att::Result<> status = ToResult(HostError::kFailed);
639 mgr()->Initialize([&status](att::Result<> val) { status = val; },
640 NopMtuCallback);
641
642 RunUntilIdle();
643 EXPECT_EQ(fit::ok(), status);
644 EXPECT_EQ(fit::ok(), list_services_status);
645 // Only svc1 has a type in |uuids|.
646 EXPECT_EQ(1u, list_services.size());
647 EXPECT_EQ(svc1.range_start, list_services[0]->handle());
648 EXPECT_EQ(svc1.type, list_services[0]->uuid());
649 // All services should be discovered and returned to service watcher because
650 // Initialize() was not called with a list of uuids to discover.
651 EXPECT_EQ(2u, service_watcher_services.size());
652 }
653
TEST_F(RemoteServiceManagerTest,DiscoverCharacteristicsSuccess)654 TEST_F(RemoteServiceManagerTest, DiscoverCharacteristicsSuccess) {
655 auto data = ServiceData(ServiceKind::PRIMARY, 1, 5, kTestServiceUuid1);
656 auto service = SetUpFakeService(data);
657
658 CharacteristicData fake_chrc1(0, std::nullopt, 2, 3, kTestUuid3);
659 CharacteristicData fake_chrc2(0, std::nullopt, 4, 5, kTestUuid4);
660 std::vector<CharacteristicData> fake_chrcs{{fake_chrc1, fake_chrc2}};
661 fake_client()->set_characteristics(std::move(fake_chrcs));
662
663 std::map<
664 CharacteristicHandle,
665 std::pair<CharacteristicData, std::map<DescriptorHandle, DescriptorData>>>
666 expected = {{CharacteristicHandle(3), {fake_chrc1, {}}},
667 {CharacteristicHandle(5), {fake_chrc2, {}}}};
668
669 att::Result<> status1 = ToResult(HostError::kFailed);
670
671 auto cb = [expected](att::Result<>* status) {
672 return [status, expected](att::Result<> cb_status, const auto& chrcs) {
673 *status = cb_status;
674 EXPECT_EQ(expected, chrcs);
675 };
676 };
677
678 service->DiscoverCharacteristics(
679 [&](att::Result<> cb_status, const auto& chrcs) {
680 status1 = cb_status;
681 EXPECT_EQ(expected, chrcs);
682 });
683
684 // Queue a second request.
685 att::Result<> status2 = ToResult(HostError::kFailed);
686 service->DiscoverCharacteristics(
687 [&](att::Result<> cb_status, const auto& chrcs) {
688 status2 = cb_status;
689 EXPECT_EQ(expected, chrcs);
690 });
691
692 RunUntilIdle();
693 // Only one ATT request should have been made.
694 EXPECT_EQ(1u, fake_client()->chrc_discovery_count());
695 EXPECT_TRUE(service->IsDiscovered());
696 EXPECT_EQ(fit::ok(), status1);
697 EXPECT_EQ(fit::ok(), status2);
698 EXPECT_EQ(data.range_start,
699 fake_client()->last_chrc_discovery_start_handle());
700 EXPECT_EQ(data.range_end, fake_client()->last_chrc_discovery_end_handle());
701
702 // Request discovery again. This should succeed without an ATT request.
703 status1 = ToResult(HostError::kFailed);
704 service->DiscoverCharacteristics(
705 [&status1](att::Result<> cb_status, const auto&) {
706 status1 = cb_status;
707 });
708
709 RunUntilIdle();
710
711 EXPECT_EQ(fit::ok(), status1);
712 EXPECT_EQ(1u, fake_client()->chrc_discovery_count());
713 EXPECT_TRUE(service->IsDiscovered());
714 }
715
TEST_F(RemoteServiceManagerTest,DiscoverCharacteristicsError)716 TEST_F(RemoteServiceManagerTest, DiscoverCharacteristicsError) {
717 auto service = SetUpFakeService(
718 ServiceData(ServiceKind::PRIMARY, 1, 5, kTestServiceUuid1));
719
720 CharacteristicData chrc1(0, std::nullopt, 2, 3, kTestUuid3);
721 CharacteristicData chrc2(0, std::nullopt, 4, 5, kTestUuid4);
722 std::vector<CharacteristicData> fake_chrcs{{chrc1, chrc2}};
723 fake_client()->set_characteristics(std::move(fake_chrcs));
724
725 fake_client()->set_characteristic_discovery_status(
726 ToResult(HostError::kNotSupported));
727
728 att::Result<> status1 = fit::ok();
729 service->DiscoverCharacteristics(
730 [&](att::Result<> cb_status, const auto& chrcs) {
731 status1 = cb_status;
732 EXPECT_TRUE(chrcs.empty());
733 });
734
735 // Queue a second request.
736 att::Result<> status2 = fit::ok();
737 service->DiscoverCharacteristics(
738 [&](att::Result<> cb_status, const auto& chrcs) {
739 status2 = cb_status;
740 EXPECT_TRUE(chrcs.empty());
741 });
742
743 RunUntilIdle();
744 // Only one request should have been made.
745 EXPECT_EQ(1u, fake_client()->chrc_discovery_count());
746 EXPECT_FALSE(service->IsDiscovered());
747 EXPECT_EQ(ToResult(HostError::kNotSupported), status1);
748 EXPECT_EQ(ToResult(HostError::kNotSupported), status2);
749 }
750
751 // Discover descriptors of a service with one characteristic.
TEST_F(RemoteServiceManagerTest,DiscoverDescriptorsOfOneSuccess)752 TEST_F(RemoteServiceManagerTest, DiscoverDescriptorsOfOneSuccess) {
753 ServiceData data(ServiceKind::PRIMARY, kStart, kEnd, kTestServiceUuid1);
754 auto service = SetUpFakeService(data);
755
756 CharacteristicData fake_chrc(
757 0, std::nullopt, kCharDecl, kCharValue, kTestUuid3);
758 fake_client()->set_characteristics({{fake_chrc}});
759
760 DescriptorData fake_desc1(kDesc1, kTestUuid3);
761 DescriptorData fake_desc2(kDesc2, kTestUuid4);
762 fake_client()->set_descriptors({{fake_desc1, fake_desc2}});
763
764 att::Result<> status = ToResult(HostError::kFailed);
765 service->DiscoverCharacteristics(
766 [&](att::Result<> cb_status, const auto chrcs) {
767 status = cb_status;
768 EXPECT_EQ(1u, chrcs.size());
769
770 std::map<CharacteristicHandle,
771 std::pair<CharacteristicData,
772 std::map<DescriptorHandle, DescriptorData>>>
773 expected = {
774 {CharacteristicHandle(kCharValue),
775 {fake_chrc, {{kDesc1, fake_desc1}, {kDesc2, fake_desc2}}}}};
776
777 EXPECT_EQ(expected, chrcs);
778 });
779
780 RunUntilIdle();
781 EXPECT_EQ(1u, fake_client()->chrc_discovery_count());
782 EXPECT_EQ(1u, fake_client()->desc_discovery_count());
783 EXPECT_TRUE(service->IsDiscovered());
784 EXPECT_EQ(fit::ok(), status);
785 EXPECT_EQ(kDesc1, fake_client()->last_desc_discovery_start_handle());
786 EXPECT_EQ(kEnd, fake_client()->last_desc_discovery_end_handle());
787 }
788
789 // Discover descriptors of a service with one characteristic.
TEST_F(RemoteServiceManagerTest,DiscoverDescriptorsOfOneError)790 TEST_F(RemoteServiceManagerTest, DiscoverDescriptorsOfOneError) {
791 ServiceData data(ServiceKind::PRIMARY, kStart, kEnd, kTestServiceUuid1);
792 auto service = SetUpFakeService(data);
793
794 CharacteristicData fake_chrc(
795 0, std::nullopt, kCharDecl, kCharValue, kTestUuid3);
796 fake_client()->set_characteristics({{fake_chrc}});
797
798 DescriptorData fake_desc1(kDesc1, kTestUuid3);
799 DescriptorData fake_desc2(kDesc2, kTestUuid4);
800 fake_client()->set_descriptors({{fake_desc1, fake_desc2}});
801 fake_client()->set_descriptor_discovery_status(
802 ToResult(HostError::kNotSupported));
803
804 att::Result<> status = fit::ok();
805 service->DiscoverCharacteristics(
806 [&](att::Result<> cb_status, const auto& chrcs) {
807 status = cb_status;
808 EXPECT_TRUE(chrcs.empty());
809 });
810
811 RunUntilIdle();
812 EXPECT_EQ(1u, fake_client()->chrc_discovery_count());
813 EXPECT_EQ(1u, fake_client()->desc_discovery_count());
814 EXPECT_FALSE(service->IsDiscovered());
815 EXPECT_EQ(ToResult(HostError::kNotSupported), status);
816 }
817
818 // Discover descriptors of a service with multiple characteristics
TEST_F(RemoteServiceManagerTest,DiscoverDescriptorsOfMultipleSuccess)819 TEST_F(RemoteServiceManagerTest, DiscoverDescriptorsOfMultipleSuccess) {
820 // Has one descriptor
821 CharacteristicData fake_char1(0, std::nullopt, 2, 3, kTestUuid3);
822 DescriptorData fake_desc1(4, kTestUuid4);
823
824 // Has no descriptors
825 CharacteristicData fake_char2(0, std::nullopt, 5, 6, kTestUuid3);
826
827 // Has two descriptors
828 CharacteristicData fake_char3(0, std::nullopt, 7, 8, kTestUuid3);
829 DescriptorData fake_desc2(9, kTestUuid4);
830 DescriptorData fake_desc3(10, kTestUuid4);
831
832 ServiceData data(
833 ServiceKind::PRIMARY, 1, fake_desc3.handle, kTestServiceUuid1);
834 auto service = SetUpFakeService(data);
835 fake_client()->set_characteristics({{fake_char1, fake_char2, fake_char3}});
836 fake_client()->set_descriptors({{fake_desc1, fake_desc2, fake_desc3}});
837
838 att::Result<> status = ToResult(HostError::kFailed);
839 service->DiscoverCharacteristics([&](att::Result<> cb_status,
840 const auto& chrcs) {
841 status = cb_status;
842
843 std::map<CharacteristicHandle,
844 std::pair<CharacteristicData,
845 std::map<DescriptorHandle, DescriptorData>>>
846 expected = {{CharacteristicHandle(3), {fake_char1, {{4, fake_desc1}}}},
847 {CharacteristicHandle(6), {fake_char2, {}}},
848 {CharacteristicHandle(8),
849 {fake_char3, {{9, fake_desc2}, {10, fake_desc3}}}}};
850
851 EXPECT_EQ(expected, chrcs);
852 });
853
854 RunUntilIdle();
855 EXPECT_EQ(1u, fake_client()->chrc_discovery_count());
856 // There should have been two descriptor discovery requests as discovery
857 // should have been skipped for characteristic #2 due to its handles.
858 EXPECT_EQ(2u, fake_client()->desc_discovery_count());
859 EXPECT_TRUE(service->IsDiscovered());
860 EXPECT_EQ(fit::ok(), status);
861 }
862
863 // Discover descriptors of a service with multiple characteristics. The first
864 // request results in an error though others succeed.
TEST_F(RemoteServiceManagerTest,DiscoverDescriptorsOfMultipleEarlyFail)865 TEST_F(RemoteServiceManagerTest, DiscoverDescriptorsOfMultipleEarlyFail) {
866 // Has one descriptor
867 CharacteristicData fake_char1(0, std::nullopt, 2, 3, kTestUuid3);
868 DescriptorData fake_desc1(4, kTestUuid4);
869
870 // Has no descriptors
871 CharacteristicData fake_char2(0, std::nullopt, 5, 6, kTestUuid3);
872
873 // Has two descriptors
874 CharacteristicData fake_char3(0, std::nullopt, 7, 8, kTestUuid3);
875 DescriptorData fake_desc2(9, kTestUuid4);
876 DescriptorData fake_desc3(10, kTestUuid4);
877
878 ServiceData data(
879 ServiceKind::PRIMARY, 1, fake_desc3.handle, kTestServiceUuid1);
880 auto service = SetUpFakeService(data);
881 fake_client()->set_characteristics({{fake_char1, fake_char2, fake_char3}});
882 fake_client()->set_descriptors({{fake_desc1, fake_desc2, fake_desc3}});
883
884 // The first request will fail
885 fake_client()->set_descriptor_discovery_status(
886 ToResult(HostError::kNotSupported), 1);
887
888 att::Result<> status = ToResult(HostError::kFailed);
889 service->DiscoverCharacteristics(
890 [&](att::Result<> cb_status, const auto& chrcs) {
891 status = cb_status;
892 EXPECT_TRUE(chrcs.empty());
893 });
894
895 RunUntilIdle();
896 EXPECT_EQ(1u, fake_client()->chrc_discovery_count());
897 // There should have been two descriptor discovery requests as discovery
898 // should have been skipped for characteristic #2 due to its handles.
899 EXPECT_EQ(2u, fake_client()->desc_discovery_count());
900 EXPECT_FALSE(service->IsDiscovered());
901 EXPECT_EQ(ToResult(HostError::kNotSupported), status);
902 }
903
904 // Discover descriptors of a service with multiple characteristics. The last
905 // request results in an error while the preceding ones succeed.
TEST_F(RemoteServiceManagerTest,DiscoverDescriptorsOfMultipleLateFail)906 TEST_F(RemoteServiceManagerTest, DiscoverDescriptorsOfMultipleLateFail) {
907 // Has one descriptor
908 CharacteristicData fake_char1(0, std::nullopt, 2, 3, kTestUuid3);
909 DescriptorData fake_desc1(4, kTestUuid4);
910
911 // Has no descriptors
912 CharacteristicData fake_char2(0, std::nullopt, 5, 6, kTestUuid3);
913
914 // Has two descriptors
915 CharacteristicData fake_char3(0, std::nullopt, 7, 8, kTestUuid3);
916 DescriptorData fake_desc2(9, kTestUuid4);
917 DescriptorData fake_desc3(10, kTestUuid4);
918
919 ServiceData data(
920 ServiceKind::PRIMARY, 1, fake_desc3.handle, kTestServiceUuid1);
921 auto service = SetUpFakeService(data);
922 fake_client()->set_characteristics({{fake_char1, fake_char2, fake_char3}});
923 fake_client()->set_descriptors({{fake_desc1, fake_desc2, fake_desc3}});
924
925 // The last request will fail
926 fake_client()->set_descriptor_discovery_status(
927 ToResult(HostError::kNotSupported), 2);
928
929 att::Result<> status = ToResult(HostError::kFailed);
930 service->DiscoverCharacteristics(
931 [&](att::Result<> cb_status, const auto& chrcs) {
932 status = cb_status;
933 EXPECT_TRUE(chrcs.empty());
934 });
935
936 RunUntilIdle();
937 EXPECT_EQ(1u, fake_client()->chrc_discovery_count());
938 // There should have been two descriptor discovery requests as discovery
939 // should have been skipped for characteristic #2 due to its handles.
940 EXPECT_EQ(2u, fake_client()->desc_discovery_count());
941 EXPECT_FALSE(service->IsDiscovered());
942 EXPECT_EQ(ToResult(HostError::kNotSupported), status);
943 }
944
945 // Discover descriptors of a service with extended properties set.
TEST_F(RemoteServiceManagerTest,DiscoverDescriptorsWithExtendedPropertiesSuccess)946 TEST_F(RemoteServiceManagerTest,
947 DiscoverDescriptorsWithExtendedPropertiesSuccess) {
948 ServiceData data(ServiceKind::PRIMARY, kStart, kEnd, kTestServiceUuid1);
949 auto service = SetUpFakeService(data);
950
951 // The ExtendedProperties of the characteristic is set.
952 const Properties props = Property::kExtendedProperties;
953 CharacteristicData fake_chrc(
954 props, std::nullopt, kCharDecl, kCharValue, kTestUuid3);
955
956 DescriptorData fake_desc1(kDesc1, types::kCharacteristicExtProperties);
957 DescriptorData fake_desc2(kDesc2, kTestUuid4);
958
959 SetCharacteristicsAndDescriptors({fake_chrc}, {fake_desc1, fake_desc2});
960
961 // The callback should be triggered once to read the value of the descriptor
962 // containing the ExtendedProperties bitfield.
963 size_t read_cb_count = 0;
964 auto extended_prop_read_cb = [&](att::Handle handle, auto callback) {
965 EXPECT_EQ(kDesc1, handle);
966 callback(fit::ok(), kExtendedPropValue, /*maybe_truncated=*/false);
967 read_cb_count++;
968 };
969 fake_client()->set_read_request_callback(std::move(extended_prop_read_cb));
970
971 att::Result<> status = ToResult(HostError::kFailed);
972 service->DiscoverCharacteristics([&](att::Result<> cb_status,
973 const auto chrcs) {
974 status = cb_status;
975 EXPECT_EQ(1u, chrcs.size());
976
977 CharacteristicData expected_chrc(
978 props, kReliableWrite, kCharDecl, kCharValue, kTestUuid3);
979 std::map<CharacteristicHandle,
980 std::pair<CharacteristicData,
981 std::map<DescriptorHandle, DescriptorData>>>
982 expected = {
983 {CharacteristicHandle(kCharValue),
984 {expected_chrc, {{kDesc1, fake_desc1}, {kDesc2, fake_desc2}}}}};
985 EXPECT_EQ(expected, chrcs);
986
987 // Validate that the ExtendedProperties have been written to the |chrcs|
988 // returned in the callback.
989 CharacteristicData chrc_data =
990 chrcs.at(CharacteristicHandle(kCharValue)).first;
991 EXPECT_TRUE(chrc_data.extended_properties.has_value());
992 EXPECT_EQ(ExtendedProperty::kReliableWrite,
993 chrc_data.extended_properties.value());
994 });
995
996 RunUntilIdle();
997 EXPECT_EQ(1u, fake_client()->chrc_discovery_count());
998 EXPECT_EQ(1u, fake_client()->desc_discovery_count());
999 EXPECT_EQ(1u, read_cb_count);
1000 EXPECT_TRUE(service->IsDiscovered());
1001 EXPECT_EQ(fit::ok(), status);
1002 EXPECT_EQ(kDesc1, fake_client()->last_desc_discovery_start_handle());
1003 EXPECT_EQ(kEnd, fake_client()->last_desc_discovery_end_handle());
1004 }
1005
1006 // Discover descriptors of a service that doesn't contain the ExtendedProperties
1007 // bit set, but with a descriptor containing an ExtendedProperty value. This is
1008 // not invalid, as per the spec, and so discovery shouldn't fail.
TEST_F(RemoteServiceManagerTest,DiscoverDescriptorsExtendedPropertiesNotSet)1009 TEST_F(RemoteServiceManagerTest, DiscoverDescriptorsExtendedPropertiesNotSet) {
1010 ServiceData data(ServiceKind::PRIMARY, kStart, kEnd, kTestServiceUuid1);
1011 auto service = SetUpFakeService(data);
1012
1013 // The ExtendedProperties of the characteristic is not set.
1014 CharacteristicData fake_chrc(
1015 0, std::nullopt, kCharDecl, kCharValue, kTestUuid3);
1016 DescriptorData fake_desc1(kDesc1, types::kCharacteristicExtProperties);
1017 SetCharacteristicsAndDescriptors({fake_chrc}, {fake_desc1});
1018
1019 // Callback should not be executed.
1020 size_t read_cb_count = 0;
1021 auto extended_prop_read_cb = [&](att::Handle handle, auto callback) {
1022 callback(fit::ok(), kExtendedPropValue, /*maybe_truncated=*/false);
1023 read_cb_count++;
1024 };
1025 fake_client()->set_read_request_callback(std::move(extended_prop_read_cb));
1026
1027 att::Result<> status = ToResult(HostError::kFailed);
1028 service->DiscoverCharacteristics(
1029 [&](att::Result<> cb_status, const auto chrcs) {
1030 status = cb_status;
1031 EXPECT_EQ(1u, chrcs.size());
1032
1033 std::map<CharacteristicHandle,
1034 std::pair<CharacteristicData,
1035 std::map<DescriptorHandle, DescriptorData>>>
1036 expected = {{CharacteristicHandle(kCharValue),
1037 {fake_chrc, {{kDesc1, fake_desc1}}}}};
1038
1039 EXPECT_EQ(expected, chrcs);
1040
1041 // Validate that the ExtendedProperties has not been updated.
1042 CharacteristicData chrc_data =
1043 chrcs.at(CharacteristicHandle(kCharValue)).first;
1044 EXPECT_FALSE(chrc_data.extended_properties.has_value());
1045 });
1046
1047 RunUntilIdle();
1048 EXPECT_EQ(1u, fake_client()->chrc_discovery_count());
1049 EXPECT_EQ(1u, fake_client()->desc_discovery_count());
1050 EXPECT_EQ(0u, read_cb_count);
1051 EXPECT_TRUE(service->IsDiscovered());
1052 EXPECT_EQ(fit::ok(), status);
1053 }
1054
1055 // Discover descriptors of a service with two descriptors containing
1056 // ExtendedProperties. This is invalid, and discovery should fail.
TEST_F(RemoteServiceManagerTest,DiscoverDescriptorsMultipleExtendedPropertiesError)1057 TEST_F(RemoteServiceManagerTest,
1058 DiscoverDescriptorsMultipleExtendedPropertiesError) {
1059 ServiceData data(ServiceKind::PRIMARY, kStart, kEnd, kTestServiceUuid1);
1060 auto service = SetUpFakeService(data);
1061
1062 // The ExtendedProperties of the characteristic is set.
1063 const Properties props = Property::kExtendedProperties;
1064 CharacteristicData fake_chrc(
1065 props, std::nullopt, kCharDecl, kCharValue, kTestUuid3);
1066 // Two descriptors with ExtProperties.
1067 DescriptorData fake_desc1(kDesc1, types::kCharacteristicExtProperties);
1068 DescriptorData fake_desc2(kDesc2, types::kCharacteristicExtProperties);
1069 SetCharacteristicsAndDescriptors({fake_chrc}, {fake_desc1, fake_desc2});
1070
1071 size_t read_cb_count = 0;
1072 auto extended_prop_read_cb = [&](att::Handle handle, auto callback) {
1073 callback(fit::ok(), kExtendedPropValue, /*maybe_truncated=*/false);
1074 read_cb_count++;
1075 };
1076 fake_client()->set_read_request_callback(std::move(extended_prop_read_cb));
1077
1078 att::Result<> status = ToResult(HostError::kFailed);
1079 service->DiscoverCharacteristics(
1080 [&](att::Result<> cb_status, const auto chrcs) {
1081 status = cb_status;
1082 EXPECT_TRUE(chrcs.empty());
1083 });
1084
1085 RunUntilIdle();
1086 EXPECT_EQ(1u, fake_client()->chrc_discovery_count());
1087 EXPECT_EQ(1u, fake_client()->desc_discovery_count());
1088 EXPECT_EQ(0u, read_cb_count);
1089 EXPECT_FALSE(service->IsDiscovered());
1090 EXPECT_EQ(ToResult(HostError::kFailed), status);
1091 }
1092
1093 // Discover descriptors of a service with ExtendedProperties set, but with
1094 // an error when reading the descriptor value. Discovery should fail.
TEST_F(RemoteServiceManagerTest,DiscoverDescriptorsExtendedPropertiesReadDescValueError)1095 TEST_F(RemoteServiceManagerTest,
1096 DiscoverDescriptorsExtendedPropertiesReadDescValueError) {
1097 ServiceData data(ServiceKind::PRIMARY, kStart, kEnd, kTestServiceUuid1);
1098 auto service = SetUpFakeService(data);
1099
1100 // The ExtendedProperties of the characteristic is set.
1101 const Properties props = Property::kExtendedProperties;
1102 CharacteristicData fake_chrc(
1103 props, std::nullopt, kCharDecl, kCharValue, kTestUuid3);
1104 DescriptorData fake_desc1(kDesc1, types::kCharacteristicExtProperties);
1105 DescriptorData fake_desc2(kDesc2, kTestUuid4);
1106 SetCharacteristicsAndDescriptors({fake_chrc}, {fake_desc1, fake_desc2});
1107
1108 // The callback should be triggered once to read the value of the descriptor
1109 // containing the ExtendedProperties bitfield.
1110 size_t read_cb_count = 0;
1111 auto extended_prop_read_cb = [&](att::Handle handle, auto callback) {
1112 EXPECT_EQ(kDesc1, handle);
1113 callback(ToResult(att::ErrorCode::kReadNotPermitted),
1114 BufferView(),
1115 /*maybe_truncated=*/false);
1116 read_cb_count++;
1117 };
1118 fake_client()->set_read_request_callback(std::move(extended_prop_read_cb));
1119
1120 att::Result<> status = ToResult(HostError::kFailed);
1121 service->DiscoverCharacteristics(
1122 [&](att::Result<> cb_status, const auto chrcs) {
1123 status = cb_status;
1124 EXPECT_TRUE(chrcs.empty());
1125 });
1126
1127 RunUntilIdle();
1128
1129 EXPECT_EQ(1u, read_cb_count);
1130 EXPECT_FALSE(service->IsDiscovered());
1131 ASSERT_TRUE(status.is_error());
1132 EXPECT_TRUE(status.error_value().is_protocol_error());
1133 }
1134
1135 // Discover descriptors of a service with ExtendedProperties set, but with
1136 // a malformed response when reading the descriptor value. Discovery should
1137 // fail.
TEST_F(RemoteServiceManagerTest,DiscoverDescriptorsExtendedPropertiesReadDescInvalidValue)1138 TEST_F(RemoteServiceManagerTest,
1139 DiscoverDescriptorsExtendedPropertiesReadDescInvalidValue) {
1140 ServiceData data(ServiceKind::PRIMARY, kStart, kEnd, kTestServiceUuid1);
1141 auto service = SetUpFakeService(data);
1142
1143 // The ExtendedProperties of the characteristic is set.
1144 const Properties props = Property::kExtendedProperties;
1145 CharacteristicData fake_chrc(
1146 props, std::nullopt, kCharDecl, kCharValue, kTestUuid3);
1147 DescriptorData fake_desc1(kDesc1, types::kCharacteristicExtProperties);
1148 DescriptorData fake_desc2(kDesc2, kTestUuid4);
1149 SetCharacteristicsAndDescriptors({fake_chrc}, {fake_desc1, fake_desc2});
1150
1151 // The callback should be triggered once to read the value of the descriptor
1152 // containing the ExtendedProperties bitfield.
1153 size_t read_cb_count = 0;
1154 auto extended_prop_read_cb = [&](att::Handle handle, auto callback) {
1155 EXPECT_EQ(kDesc1, handle);
1156 callback(fit::ok(),
1157 BufferView(),
1158 /*maybe_truncated=*/false); // Invalid return buf
1159 read_cb_count++;
1160 };
1161 fake_client()->set_read_request_callback(std::move(extended_prop_read_cb));
1162
1163 att::Result<> status = ToResult(HostError::kFailed);
1164 service->DiscoverCharacteristics(
1165 [&](att::Result<> cb_status, const auto chrcs) {
1166 status = cb_status;
1167 EXPECT_TRUE(chrcs.empty());
1168 });
1169
1170 RunUntilIdle();
1171 EXPECT_EQ(1u, fake_client()->chrc_discovery_count());
1172 EXPECT_EQ(1u, fake_client()->desc_discovery_count());
1173 EXPECT_EQ(1u, read_cb_count);
1174 EXPECT_FALSE(service->IsDiscovered());
1175 EXPECT_EQ(ToResult(HostError::kPacketMalformed), status);
1176 }
1177
1178 constexpr CharacteristicHandle kDefaultCharacteristic(3);
1179 constexpr CharacteristicHandle kSecondCharacteristic(6);
1180 constexpr CharacteristicHandle kInvalidCharacteristic(1);
1181
1182 constexpr att::Handle kDefaultChrcValueHandle = 3;
1183
UnreadableChrc()1184 CharacteristicData UnreadableChrc() {
1185 return CharacteristicData(
1186 0, std::nullopt, 2, kDefaultChrcValueHandle, kTestUuid3);
1187 }
ReadableChrc()1188 CharacteristicData ReadableChrc() {
1189 return CharacteristicData(
1190 Property::kRead, std::nullopt, 2, kDefaultChrcValueHandle, kTestUuid3);
1191 }
WritableChrc()1192 CharacteristicData WritableChrc() {
1193 return CharacteristicData(
1194 Property::kWrite, std::nullopt, 2, kDefaultChrcValueHandle, kTestUuid3);
1195 }
WriteableExtendedPropChrc()1196 CharacteristicData WriteableExtendedPropChrc() {
1197 auto props = Property::kWrite | Property::kExtendedProperties;
1198 return CharacteristicData(
1199 props, std::nullopt, 2, kDefaultChrcValueHandle, kTestUuid3);
1200 }
1201
TEST_F(RemoteServiceManagerTest,ReadCharWhileNotReady)1202 TEST_F(RemoteServiceManagerTest, ReadCharWhileNotReady) {
1203 auto service = SetUpFakeService(
1204 ServiceData(ServiceKind::PRIMARY, 1, 2, kTestServiceUuid1));
1205
1206 att::Result<> status = fit::ok();
1207 service->ReadCharacteristic(
1208 kDefaultCharacteristic,
1209 [&](att::Result<> cb_status, const auto&, auto) { status = cb_status; });
1210
1211 RunUntilIdle();
1212 EXPECT_EQ(ToResult(HostError::kNotReady), status);
1213 }
1214
TEST_F(RemoteServiceManagerTest,ReadCharNotFound)1215 TEST_F(RemoteServiceManagerTest, ReadCharNotFound) {
1216 auto service = SetupServiceWithChrcs(
1217 ServiceData(ServiceKind::PRIMARY, 1, 2, kTestServiceUuid1), {});
1218 att::Result<> status = fit::ok();
1219 service->ReadCharacteristic(
1220 kDefaultCharacteristic,
1221 [&](att::Result<> cb_status, const auto&, auto) { status = cb_status; });
1222
1223 RunUntilIdle();
1224 EXPECT_EQ(ToResult(HostError::kNotFound), status);
1225 }
1226
TEST_F(RemoteServiceManagerTest,ReadCharNotSupported)1227 TEST_F(RemoteServiceManagerTest, ReadCharNotSupported) {
1228 auto service = SetupServiceWithChrcs(
1229 ServiceData(ServiceKind::PRIMARY, 1, 3, kTestServiceUuid1),
1230 {UnreadableChrc()});
1231 att::Result<> status = fit::ok();
1232 service->ReadCharacteristic(
1233 kDefaultCharacteristic,
1234 [&](att::Result<> cb_status, const auto&, auto) { status = cb_status; });
1235
1236 RunUntilIdle();
1237 EXPECT_EQ(ToResult(HostError::kNotSupported), status);
1238 }
1239
TEST_F(RemoteServiceManagerTest,ReadCharSendsReadRequest)1240 TEST_F(RemoteServiceManagerTest, ReadCharSendsReadRequest) {
1241 auto service = SetupServiceWithChrcs(
1242 ServiceData(
1243 ServiceKind::PRIMARY, 1, kDefaultChrcValueHandle, kTestServiceUuid1),
1244 {ReadableChrc()});
1245
1246 const StaticByteBuffer kValue('t', 'e', 's', 't');
1247
1248 fake_client()->set_read_request_callback(
1249 [&](att::Handle handle, auto callback) {
1250 EXPECT_EQ(kDefaultChrcValueHandle, handle);
1251 callback(fit::ok(), kValue, /*maybe_truncated=*/false);
1252 });
1253
1254 att::Result<> status = ToResult(HostError::kFailed);
1255 service->ReadCharacteristic(
1256 kDefaultCharacteristic,
1257 [&](att::Result<> cb_status, const auto& value, bool maybe_truncated) {
1258 status = cb_status;
1259 EXPECT_TRUE(ContainersEqual(kValue, value));
1260 EXPECT_FALSE(maybe_truncated);
1261 });
1262
1263 RunUntilIdle();
1264
1265 EXPECT_EQ(fit::ok(), status);
1266 }
1267
TEST_F(RemoteServiceManagerTest,ReadLongWhileNotReady)1268 TEST_F(RemoteServiceManagerTest, ReadLongWhileNotReady) {
1269 auto service = SetUpFakeService(
1270 ServiceData(ServiceKind::PRIMARY, 1, 2, kTestServiceUuid1));
1271
1272 att::Result<> status = fit::ok();
1273 service->ReadLongCharacteristic(
1274 CharacteristicHandle(0),
1275 0,
1276 512,
1277 [&](att::Result<> cb_status, const auto&, auto) { status = cb_status; });
1278
1279 RunUntilIdle();
1280
1281 EXPECT_EQ(ToResult(HostError::kNotReady), status);
1282 }
1283
TEST_F(RemoteServiceManagerTest,ReadLongNotFound)1284 TEST_F(RemoteServiceManagerTest, ReadLongNotFound) {
1285 auto service = SetupServiceWithChrcs(
1286 ServiceData(ServiceKind::PRIMARY, 1, 2, kTestServiceUuid1), {});
1287
1288 att::Result<> status = fit::ok();
1289 service->ReadLongCharacteristic(
1290 CharacteristicHandle(0),
1291 0,
1292 512,
1293 [&](att::Result<> cb_status, const auto&, auto) { status = cb_status; });
1294
1295 RunUntilIdle();
1296
1297 EXPECT_EQ(ToResult(HostError::kNotFound), status);
1298 }
1299
TEST_F(RemoteServiceManagerTest,ReadLongNotSupported)1300 TEST_F(RemoteServiceManagerTest, ReadLongNotSupported) {
1301 auto service = SetupServiceWithChrcs(
1302 ServiceData(ServiceKind::PRIMARY, 1, 3, kTestServiceUuid1),
1303 {UnreadableChrc()});
1304
1305 att::Result<> status = fit::ok();
1306 service->ReadLongCharacteristic(
1307 kDefaultCharacteristic,
1308 0,
1309 512,
1310 [&](att::Result<> cb_status, const auto&, auto) { status = cb_status; });
1311
1312 RunUntilIdle();
1313
1314 EXPECT_EQ(ToResult(HostError::kNotSupported), status);
1315 }
1316
1317 // 0 is not a valid parameter for the |max_size| field of ReadLongCharacteristic
TEST_F(RemoteServiceManagerTest,ReadLongMaxSizeZero)1318 TEST_F(RemoteServiceManagerTest, ReadLongMaxSizeZero) {
1319 auto service = SetupServiceWithChrcs(
1320 ServiceData(ServiceKind::PRIMARY, 1, 3, kTestServiceUuid1),
1321 {ReadableChrc()});
1322
1323 att::Result<> status = fit::ok();
1324 service->ReadLongCharacteristic(
1325 kDefaultCharacteristic,
1326 0,
1327 0,
1328 [&](att::Result<> cb_status, const auto&, auto) { status = cb_status; });
1329
1330 RunUntilIdle();
1331
1332 EXPECT_EQ(ToResult(HostError::kInvalidParameters), status);
1333 }
1334
1335 // The complete attribute value is read in a single request.
TEST_F(RemoteServiceManagerTest,ReadLongSingleBlob)1336 TEST_F(RemoteServiceManagerTest, ReadLongSingleBlob) {
1337 constexpr uint16_t kOffset = 0;
1338 constexpr size_t kMaxBytes = 1000;
1339
1340 auto service = SetupServiceWithChrcs(
1341 ServiceData(
1342 ServiceKind::PRIMARY, 1, kDefaultChrcValueHandle, kTestServiceUuid1),
1343 {ReadableChrc()});
1344
1345 const StaticByteBuffer kValue('t', 'e', 's', 't');
1346
1347 int request_count = 0;
1348 fake_client()->set_read_request_callback(
1349 [&](att::Handle handle, auto callback) {
1350 request_count++;
1351 EXPECT_EQ(request_count, 1);
1352 EXPECT_EQ(kDefaultChrcValueHandle, handle);
1353 callback(fit::ok(), kValue, /*maybe_truncated=*/false);
1354 });
1355
1356 att::Result<> status = ToResult(HostError::kFailed);
1357 service->ReadLongCharacteristic(
1358 kDefaultCharacteristic,
1359 kOffset,
1360 kMaxBytes,
1361 [&](att::Result<> cb_status, const auto& value, bool maybe_truncated) {
1362 status = cb_status;
1363 EXPECT_TRUE(ContainersEqual(kValue, value));
1364 EXPECT_FALSE(maybe_truncated);
1365 });
1366
1367 RunUntilIdle();
1368 EXPECT_EQ(fit::ok(), status);
1369 }
1370
TEST_F(RemoteServiceManagerTest,ReadLongMultipleBlobs)1371 TEST_F(RemoteServiceManagerTest, ReadLongMultipleBlobs) {
1372 constexpr uint16_t kOffset = 0;
1373 constexpr size_t kMaxBytes = 1000;
1374 constexpr int kExpectedBlobCount = 4;
1375
1376 auto service = SetupServiceWithChrcs(
1377 ServiceData(
1378 ServiceKind::PRIMARY, 1, kDefaultChrcValueHandle, kTestServiceUuid1),
1379 {ReadableChrc()});
1380
1381 // Create a buffer that will take 4 requests to read. Since the default MTU is
1382 // 23:
1383 // a. The size of |expected_value| is 69.
1384 // b. We should read 22 + 22 + 22 + 3 bytes across 4 requests.
1385 StaticByteBuffer<att::kLEMinMTU * 3> expected_value;
1386
1387 // Initialize the contents.
1388 for (size_t i = 0; i < expected_value.size(); ++i) {
1389 expected_value[i] = i;
1390 }
1391
1392 int read_count = 0;
1393 fake_client()->set_read_request_callback(
1394 [&](att::Handle handle, auto callback) {
1395 read_count++;
1396 EXPECT_EQ(read_count, 1);
1397 EXPECT_EQ(kDefaultChrcValueHandle, handle);
1398 auto blob = expected_value.view(0, att::kLEMinMTU - 1);
1399 callback(fit::ok(), blob, /*maybe_truncated=*/true);
1400 });
1401
1402 fake_client()->set_read_blob_request_callback(
1403 [&](att::Handle handle, uint16_t offset, auto callback) {
1404 read_count++;
1405 EXPECT_GT(read_count, 1);
1406 EXPECT_EQ(kDefaultChrcValueHandle, handle);
1407 bool maybe_truncated = true;
1408
1409 // Return a blob at the given offset with at most MTU - 1 bytes.
1410 auto blob = expected_value.view(offset, att::kLEMinMTU - 1);
1411 if (read_count == kExpectedBlobCount) {
1412 // The final blob should contain 3 bytes.
1413 EXPECT_EQ(3u, blob.size());
1414 maybe_truncated = false;
1415 }
1416
1417 callback(fit::ok(), blob, maybe_truncated);
1418 });
1419
1420 att::Result<> status = ToResult(HostError::kFailed);
1421 service->ReadLongCharacteristic(
1422 kDefaultCharacteristic,
1423 kOffset,
1424 kMaxBytes,
1425 [&](att::Result<> cb_status, const auto& value, bool maybe_truncated) {
1426 status = cb_status;
1427 EXPECT_TRUE(ContainersEqual(expected_value, value));
1428 EXPECT_FALSE(maybe_truncated);
1429 });
1430
1431 RunUntilIdle();
1432 EXPECT_EQ(fit::ok(), status);
1433 EXPECT_EQ(kExpectedBlobCount, read_count);
1434 }
1435
1436 // Simulates a peer that rejects a read blob request with a kAttributeNotLong
1437 // error. The initial read request completes successfully and contains the
1438 // entire value. The specification implies that the peer can either respond with
1439 // an empty buffer or a kAttributeNotLong error for the second request.
TEST_F(RemoteServiceManagerTest,ReadLongCharacteristicAttributeNotLongErrorIgnored)1440 TEST_F(RemoteServiceManagerTest,
1441 ReadLongCharacteristicAttributeNotLongErrorIgnored) {
1442 constexpr uint16_t kOffset = 0;
1443 constexpr size_t kMaxBytes = 1000;
1444 constexpr int kExpectedBlobCount = 2;
1445
1446 auto service = SetupServiceWithChrcs(
1447 ServiceData(
1448 ServiceKind::PRIMARY, 1, kDefaultChrcValueHandle, kTestServiceUuid1),
1449 {ReadableChrc()});
1450
1451 StaticByteBuffer<att::kLEMinMTU - 1> expected_value;
1452 for (size_t i = 0; i < expected_value.size(); ++i) {
1453 expected_value[i] = i;
1454 }
1455
1456 int read_count = 0;
1457 fake_client()->set_read_request_callback(
1458 [&](att::Handle handle, auto callback) {
1459 read_count++;
1460 EXPECT_EQ(read_count, 1);
1461 callback(fit::ok(), expected_value.view(), /*maybe_truncated=*/true);
1462 });
1463
1464 fake_client()->set_read_blob_request_callback(
1465 [&](att::Handle handle, uint16_t offset, auto callback) {
1466 read_count++;
1467 EXPECT_EQ(read_count, 2);
1468 callback(ToResult(att::ErrorCode::kAttributeNotLong),
1469 BufferView(),
1470 /*maybe_truncated=*/false);
1471 });
1472
1473 att::Result<> status = ToResult(HostError::kFailed);
1474 service->ReadLongCharacteristic(
1475 kDefaultCharacteristic,
1476 kOffset,
1477 kMaxBytes,
1478 [&](att::Result<> cb_status, const auto& value, bool maybe_truncated) {
1479 status = cb_status;
1480 EXPECT_TRUE(ContainersEqual(expected_value, value));
1481 EXPECT_FALSE(maybe_truncated);
1482 });
1483
1484 RunUntilIdle();
1485 EXPECT_EQ(fit::ok(), status);
1486 EXPECT_EQ(kExpectedBlobCount, read_count);
1487 }
1488
TEST_F(RemoteServiceManagerTest,ReadLongCharacteristicAttributeNotLongErrorOnFirstReadRequest)1489 TEST_F(RemoteServiceManagerTest,
1490 ReadLongCharacteristicAttributeNotLongErrorOnFirstReadRequest) {
1491 constexpr uint16_t kOffset = 0;
1492 constexpr size_t kMaxBytes = 1000;
1493 constexpr int kExpectedBlobCount = 1;
1494
1495 auto service = SetupServiceWithChrcs(
1496 ServiceData(
1497 ServiceKind::PRIMARY, 1, kDefaultChrcValueHandle, kTestServiceUuid1),
1498 {ReadableChrc()});
1499
1500 int read_count = 0;
1501 fake_client()->set_read_request_callback(
1502 [&](att::Handle handle, auto callback) {
1503 read_count++;
1504 EXPECT_EQ(read_count, 1);
1505 callback(ToResult(att::ErrorCode::kAttributeNotLong),
1506 BufferView(),
1507 /*maybe_truncated=*/false);
1508 });
1509 fake_client()->set_read_blob_request_callback(
1510 [&](auto, auto, auto) { FAIL(); });
1511
1512 att::Result<> status = fit::ok();
1513 service->ReadLongCharacteristic(
1514 kDefaultCharacteristic,
1515 kOffset,
1516 kMaxBytes,
1517 [&](att::Result<> cb_status, const auto& value, bool maybe_truncated) {
1518 status = cb_status;
1519 EXPECT_FALSE(maybe_truncated);
1520 });
1521
1522 RunUntilIdle();
1523 EXPECT_EQ(ToResult(att::ErrorCode::kAttributeNotLong), status);
1524 EXPECT_EQ(kExpectedBlobCount, read_count);
1525 }
1526
1527 // Same as ReadLongMultipleBlobs except the characteristic value has a size that
1528 // is a multiple of (ATT_MTU - 1), so that the last read blob request returns 0
1529 // bytes.
TEST_F(RemoteServiceManagerTest,ReadLongValueExactMultipleOfMTU)1530 TEST_F(RemoteServiceManagerTest, ReadLongValueExactMultipleOfMTU) {
1531 constexpr uint16_t kOffset = 0;
1532 constexpr size_t kMaxBytes = 1000;
1533 constexpr int kExpectedBlobCount = 4;
1534
1535 auto service = SetupServiceWithChrcs(
1536 ServiceData(
1537 ServiceKind::PRIMARY, 1, kDefaultChrcValueHandle, kTestServiceUuid1),
1538 {ReadableChrc()});
1539
1540 // Create a buffer that will take 4 requests to read. Since the default MTU is
1541 // 23:
1542 // a. The size of |expected_value| is 66.
1543 // b. We should read 22 + 22 + 22 + 0 bytes across 4 requests.
1544 StaticByteBuffer<(att::kLEMinMTU - 1) * 3> expected_value;
1545
1546 // Initialize the contents.
1547 for (size_t i = 0; i < expected_value.size(); ++i) {
1548 expected_value[i] = i;
1549 }
1550
1551 int read_count = 0;
1552 fake_client()->set_read_request_callback(
1553 [&](att::Handle handle, auto callback) {
1554 read_count++;
1555 EXPECT_EQ(read_count, 1);
1556 EXPECT_EQ(kDefaultChrcValueHandle, handle);
1557 auto blob = expected_value.view(0, att::kLEMinMTU - 1);
1558 callback(fit::ok(), blob, /*maybe_truncated=*/true);
1559 });
1560
1561 fake_client()->set_read_blob_request_callback(
1562 [&](att::Handle handle, uint16_t offset, auto callback) {
1563 read_count++;
1564 EXPECT_GT(read_count, 1);
1565 EXPECT_EQ(kDefaultChrcValueHandle, handle);
1566 bool maybe_truncated = true;
1567
1568 // Return a blob at the given offset with at most MTU - 1 bytes.
1569 auto blob = expected_value.view(offset, att::kLEMinMTU - 1);
1570 if (read_count == kExpectedBlobCount) {
1571 // The final blob should be empty.
1572 EXPECT_EQ(0u, blob.size());
1573 maybe_truncated = false;
1574 }
1575
1576 callback(fit::ok(), blob, maybe_truncated);
1577 });
1578
1579 att::Result<> status = ToResult(HostError::kFailed);
1580 service->ReadLongCharacteristic(
1581 kDefaultCharacteristic,
1582 kOffset,
1583 kMaxBytes,
1584 [&](att::Result<> cb_status, const auto& value, bool maybe_truncated) {
1585 status = cb_status;
1586 EXPECT_TRUE(ContainersEqual(expected_value, value));
1587 EXPECT_FALSE(maybe_truncated);
1588 });
1589
1590 RunUntilIdle();
1591 EXPECT_EQ(fit::ok(), status);
1592 EXPECT_EQ(kExpectedBlobCount, read_count);
1593 }
1594
1595 // Same as ReadLongMultipleBlobs but a maximum size is given that is smaller
1596 // than the size of the attribute value.
TEST_F(RemoteServiceManagerTest,ReadLongMultipleBlobsWithMaxSize)1597 TEST_F(RemoteServiceManagerTest, ReadLongMultipleBlobsWithMaxSize) {
1598 constexpr uint16_t kOffset = 0;
1599 constexpr size_t kMaxBytes = 40;
1600 constexpr int kExpectedBlobCount = 2;
1601
1602 auto service = SetupServiceWithChrcs(
1603 ServiceData(
1604 ServiceKind::PRIMARY, 1, kDefaultChrcValueHandle, kTestServiceUuid1),
1605 {ReadableChrc()});
1606
1607 // Reads will return 22 + 22 bytes across 2 requests, but only 18 bytes of the
1608 // second read will be reported to ReadLongCharacteristic (the value will be
1609 // truncated).
1610 StaticByteBuffer<att::kLEMinMTU * 3> expected_value;
1611
1612 // Initialize the contents.
1613 for (size_t i = 0; i < expected_value.size(); ++i) {
1614 expected_value[i] = i;
1615 }
1616
1617 int read_count = 0;
1618 fake_client()->set_read_request_callback(
1619 [&](att::Handle handle, auto callback) {
1620 read_count++;
1621 EXPECT_EQ(read_count, 1);
1622 EXPECT_EQ(kDefaultChrcValueHandle, handle);
1623 BufferView blob = expected_value.view(0, att::kLEMinMTU - 1);
1624 callback(fit::ok(), blob, /*maybe_truncated=*/true);
1625 });
1626
1627 fake_client()->set_read_blob_request_callback(
1628 [&](att::Handle handle, uint16_t offset, auto callback) {
1629 read_count++;
1630 EXPECT_GT(read_count, 1);
1631 EXPECT_EQ(kDefaultChrcValueHandle, handle);
1632 BufferView blob = expected_value.view(offset, att::kLEMinMTU - 1);
1633 callback(fit::ok(), blob, /*maybe_truncated=*/true);
1634 });
1635
1636 att::Result<> status = ToResult(HostError::kFailed);
1637 service->ReadLongCharacteristic(
1638 kDefaultCharacteristic,
1639 kOffset,
1640 kMaxBytes,
1641 [&](att::Result<> cb_status, const auto& value, bool maybe_truncated) {
1642 status = cb_status;
1643 EXPECT_TRUE(ContainersEqual(expected_value.view(0, kMaxBytes), value));
1644 EXPECT_TRUE(maybe_truncated);
1645 });
1646
1647 RunUntilIdle();
1648 EXPECT_EQ(fit::ok(), status);
1649 EXPECT_EQ(kExpectedBlobCount, read_count);
1650 }
1651
1652 // Same as ReadLongMultipleBlobs but a non-zero offset is given.
TEST_F(RemoteServiceManagerTest,ReadLongAtOffset)1653 TEST_F(RemoteServiceManagerTest, ReadLongAtOffset) {
1654 constexpr uint16_t kOffset = 30;
1655 constexpr size_t kMaxBytes = 1000;
1656 constexpr int kExpectedBlobCount = 2;
1657
1658 auto service = SetupServiceWithChrcs(
1659 ServiceData(
1660 ServiceKind::PRIMARY, 1, kDefaultChrcValueHandle, kTestServiceUuid1),
1661 {ReadableChrc()});
1662
1663 // Size: 69.
1664 // Reads starting at offset 30 will return 22 + 17 bytes across 2 requests.
1665 StaticByteBuffer<att::kLEMinMTU * 3> expected_value;
1666
1667 // Initialize the contents.
1668 for (size_t i = 0; i < expected_value.size(); ++i) {
1669 expected_value[i] = i;
1670 }
1671
1672 int read_blob_count = 0;
1673 fake_client()->set_read_blob_request_callback(
1674 [&](att::Handle handle, uint16_t offset, auto callback) {
1675 EXPECT_EQ(kDefaultChrcValueHandle, handle);
1676 read_blob_count++;
1677 BufferView blob = expected_value.view(offset, att::kLEMinMTU - 1);
1678 bool maybe_truncated = (read_blob_count != kExpectedBlobCount);
1679 callback(fit::ok(), blob, maybe_truncated);
1680 });
1681
1682 att::Result<> status = ToResult(HostError::kFailed);
1683 service->ReadLongCharacteristic(
1684 kDefaultCharacteristic,
1685 kOffset,
1686 kMaxBytes,
1687 [&](att::Result<> cb_status, const auto& value, bool maybe_truncated) {
1688 status = cb_status;
1689 EXPECT_TRUE(
1690 ContainersEqual(expected_value.view(kOffset, kMaxBytes), value));
1691 EXPECT_FALSE(maybe_truncated);
1692 });
1693
1694 RunUntilIdle();
1695 EXPECT_EQ(fit::ok(), status);
1696 EXPECT_EQ(kExpectedBlobCount, read_blob_count);
1697 }
1698
1699 // Same as ReadLongAtOffset but a very small max size is given.
TEST_F(RemoteServiceManagerTest,ReadLongAtOffsetWithMaxBytes)1700 TEST_F(RemoteServiceManagerTest, ReadLongAtOffsetWithMaxBytes) {
1701 constexpr uint16_t kOffset = 10;
1702 constexpr size_t kMaxBytes = 34;
1703 constexpr int kExpectedBlobCount = 2;
1704
1705 auto service = SetupServiceWithChrcs(
1706 ServiceData(
1707 ServiceKind::PRIMARY, 1, kDefaultChrcValueHandle, kTestServiceUuid1),
1708 {ReadableChrc()});
1709
1710 // Size: 69.
1711 // Reads starting at offset 10 will return 22 + 22 bytes across 2 requests,
1712 // but the second read value will be truncated to 12 bytes by RemoteService
1713 // due to |kMaxBytes|. A third read blob should not be sent since this should
1714 // satisfy |kMaxBytes|.
1715 StaticByteBuffer<att::kLEMinMTU * 3> expected_value;
1716
1717 // Initialize the contents.
1718 for (size_t i = 0; i < expected_value.size(); ++i) {
1719 expected_value[i] = static_cast<uint8_t>(i);
1720 }
1721
1722 int read_blob_count = 0;
1723 fake_client()->set_read_blob_request_callback(
1724 [&](att::Handle handle, uint16_t offset, auto callback) {
1725 EXPECT_EQ(kDefaultChrcValueHandle, handle);
1726 read_blob_count++;
1727 BufferView blob = expected_value.view(offset, att::kLEMinMTU - 1);
1728 callback(fit::ok(), blob, /*maybe_truncated=*/true);
1729 });
1730
1731 att::Result<> status = ToResult(HostError::kFailed);
1732 service->ReadLongCharacteristic(
1733 kDefaultCharacteristic,
1734 kOffset,
1735 kMaxBytes,
1736 [&](att::Result<> cb_status, const auto& value, bool maybe_truncated) {
1737 status = cb_status;
1738 EXPECT_TRUE(
1739 ContainersEqual(expected_value.view(kOffset, kMaxBytes), value));
1740 EXPECT_TRUE(maybe_truncated);
1741 });
1742
1743 RunUntilIdle();
1744 EXPECT_EQ(fit::ok(), status);
1745 EXPECT_EQ(kExpectedBlobCount, read_blob_count);
1746 }
1747
TEST_F(RemoteServiceManagerTest,ReadLongError)1748 TEST_F(RemoteServiceManagerTest, ReadLongError) {
1749 constexpr uint16_t kOffset = 0;
1750 constexpr size_t kMaxBytes = 1000;
1751 constexpr int kExpectedBlobCount = 2; // The second request will fail.
1752
1753 auto service = SetupServiceWithChrcs(
1754 ServiceData(
1755 ServiceKind::PRIMARY, 1, kDefaultChrcValueHandle, kTestServiceUuid1),
1756 {ReadableChrc()});
1757
1758 // Make the first blob large enough that it will cause a second read blob
1759 // request.
1760 StaticByteBuffer<att::kLEMinMTU - 1> first_blob;
1761
1762 int read_count = 0;
1763 fake_client()->set_read_request_callback(
1764 [&](att::Handle handle, auto callback) {
1765 read_count++;
1766 EXPECT_EQ(read_count, 1);
1767 EXPECT_EQ(kDefaultChrcValueHandle, handle);
1768 callback(fit::ok(), first_blob, /*maybe_truncated=*/true);
1769 });
1770
1771 fake_client()->set_read_blob_request_callback(
1772 [&](att::Handle handle, uint16_t offset, auto callback) {
1773 read_count++;
1774 EXPECT_EQ(read_count, 2);
1775 EXPECT_EQ(kDefaultChrcValueHandle, handle);
1776 callback(ToResult(att::ErrorCode::kInvalidOffset),
1777 BufferView(),
1778 /*maybe_truncated=*/false);
1779 });
1780
1781 att::Result<> status = fit::ok();
1782 service->ReadLongCharacteristic(
1783 kDefaultCharacteristic,
1784 kOffset,
1785 kMaxBytes,
1786 [&](att::Result<> cb_status, const auto& value, bool maybe_truncated) {
1787 status = cb_status;
1788 EXPECT_EQ(0u, value.size()); // No value should be returned on error.
1789 EXPECT_FALSE(maybe_truncated);
1790 });
1791
1792 RunUntilIdle();
1793 EXPECT_EQ(ToResult(att::ErrorCode::kInvalidOffset), status);
1794 EXPECT_EQ(kExpectedBlobCount, read_count);
1795 }
1796
TEST_F(RemoteServiceManagerTest,ReadByTypeSendsReadRequestsUntilAttributeNotFound)1797 TEST_F(RemoteServiceManagerTest,
1798 ReadByTypeSendsReadRequestsUntilAttributeNotFound) {
1799 constexpr att::Handle kStartHandle = 1;
1800 constexpr att::Handle kEndHandle = 5;
1801 auto service = SetUpFakeService(ServiceData(
1802 ServiceKind::PRIMARY, kStartHandle, kEndHandle, kTestServiceUuid1));
1803
1804 constexpr UUID kCharUuid(uint16_t{0xfefe});
1805
1806 constexpr att::Handle kHandle0 = 2;
1807 const StaticByteBuffer kValue0(0x00, 0x01, 0x02);
1808 const std::vector<Client::ReadByTypeValue> kValues0 = {
1809 {kHandle0, kValue0.view(), /*maybe_truncated=*/false}};
1810
1811 constexpr att::Handle kHandle1 = 3;
1812 const StaticByteBuffer kValue1(0x03, 0x04, 0x05);
1813 const std::vector<Client::ReadByTypeValue> kValues1 = {
1814 {kHandle1, kValue1.view(), /*maybe_truncated=*/true}};
1815
1816 size_t read_count = 0;
1817 fake_client()->set_read_by_type_request_callback(
1818 [&](const UUID& type, att::Handle start, att::Handle end, auto callback) {
1819 switch (read_count++) {
1820 case 0:
1821 EXPECT_EQ(kStartHandle, start);
1822 callback(fit::ok(kValues0));
1823 break;
1824 case 1:
1825 EXPECT_EQ(kHandle0 + 1, start);
1826 callback(fit::ok(kValues1));
1827 break;
1828 case 2:
1829 EXPECT_EQ(kHandle1 + 1, start);
1830 callback(fit::error(Client::ReadByTypeError{
1831 att::Error(att::ErrorCode::kAttributeNotFound), start}));
1832 break;
1833 default:
1834 FAIL();
1835 }
1836 });
1837
1838 std::optional<att::Result<>> status;
1839 service->ReadByType(
1840 kCharUuid,
1841 [&](att::Result<> cb_status,
1842 std::vector<RemoteService::ReadByTypeResult> values) {
1843 status = cb_status;
1844 EXPECT_EQ(fit::ok(), *status);
1845 ASSERT_EQ(2u, values.size());
1846 EXPECT_EQ(CharacteristicHandle(kHandle0), values[0].handle);
1847 ASSERT_EQ(fit::ok(), values[0].result);
1848 EXPECT_TRUE(ContainersEqual(kValue0, *values[0].result.value()));
1849 EXPECT_FALSE(values[0].maybe_truncated);
1850 EXPECT_EQ(CharacteristicHandle(kHandle1), values[1].handle);
1851 ASSERT_EQ(fit::ok(), values[1].result);
1852 EXPECT_TRUE(ContainersEqual(kValue1, *values[1].result.value()));
1853 EXPECT_TRUE(values[1].maybe_truncated);
1854 });
1855
1856 RunUntilIdle();
1857 ASSERT_TRUE(status.has_value());
1858 // kAttributeNotFound error should be treated as success.
1859 EXPECT_EQ(fit::ok(), *status);
1860 }
1861
TEST_F(RemoteServiceManagerTest,ReadByTypeSendsReadRequestsUntilServiceEndHandle)1862 TEST_F(RemoteServiceManagerTest,
1863 ReadByTypeSendsReadRequestsUntilServiceEndHandle) {
1864 constexpr att::Handle kStartHandle = 1;
1865 constexpr att::Handle kEndHandle = 2;
1866 auto service = SetUpFakeService(ServiceData(
1867 ServiceKind::PRIMARY, kStartHandle, kEndHandle, kTestServiceUuid1));
1868
1869 constexpr UUID kCharUuid(uint16_t{0xfefe});
1870
1871 constexpr att::Handle kHandle = kEndHandle;
1872 const StaticByteBuffer kValue(0x00, 0x01, 0x02);
1873 const std::vector<Client::ReadByTypeValue> kValues = {
1874 {kHandle, kValue.view(), /*maybe_truncated=*/false}};
1875
1876 size_t read_count = 0;
1877 fake_client()->set_read_by_type_request_callback(
1878 [&](const UUID& type, att::Handle start, att::Handle end, auto callback) {
1879 EXPECT_EQ(kStartHandle, start);
1880 EXPECT_EQ(0u, read_count++);
1881 callback(fit::ok(kValues));
1882 });
1883
1884 std::optional<att::Result<>> status;
1885 service->ReadByType(kCharUuid, [&](att::Result<> cb_status, auto values) {
1886 status = cb_status;
1887 ASSERT_EQ(1u, values.size());
1888 EXPECT_EQ(CharacteristicHandle(kHandle), values[0].handle);
1889 ASSERT_EQ(fit::ok(), values[0].result);
1890 EXPECT_TRUE(ContainersEqual(kValue, *values[0].result.value()));
1891 });
1892
1893 RunUntilIdle();
1894 ASSERT_TRUE(status.has_value());
1895 EXPECT_EQ(fit::ok(), *status);
1896 }
1897
TEST_F(RemoteServiceManagerTest,ReadByTypeReturnsReadErrorsWithResults)1898 TEST_F(RemoteServiceManagerTest, ReadByTypeReturnsReadErrorsWithResults) {
1899 constexpr att::Handle kStartHandle = 1;
1900 constexpr att::Handle kEndHandle = 5;
1901 auto service = SetUpFakeService(ServiceData(
1902 ServiceKind::PRIMARY, kStartHandle, kEndHandle, kTestServiceUuid1));
1903
1904 constexpr UUID kCharUuid(uint16_t{0xfefe});
1905
1906 const std::array<att::ErrorCode, 5> errors = {
1907 att::ErrorCode::kInsufficientAuthorization,
1908 att::ErrorCode::kInsufficientAuthentication,
1909 att::ErrorCode::kInsufficientEncryptionKeySize,
1910 att::ErrorCode::kInsufficientEncryption,
1911 att::ErrorCode::kReadNotPermitted};
1912
1913 size_t read_count = 0;
1914 fake_client()->set_read_by_type_request_callback(
1915 [&](const UUID& type, att::Handle start, att::Handle end, auto callback) {
1916 if (read_count < errors.size()) {
1917 EXPECT_EQ(kStartHandle + read_count, start);
1918 callback(fit::error(Client::ReadByTypeError{
1919 att::Error(errors[read_count++]), start}));
1920 } else {
1921 FAIL();
1922 }
1923 });
1924
1925 std::optional<att::Result<>> status;
1926 service->ReadByType(kCharUuid, [&](att::Result<> cb_status, auto values) {
1927 status = cb_status;
1928 ASSERT_EQ(errors.size(), values.size());
1929 for (size_t i = 0; i < values.size(); i++) {
1930 SCOPED_TRACE(bt_lib_cpp_string::StringPrintf("i: %zu", i));
1931 EXPECT_EQ(CharacteristicHandle(kStartHandle + i), values[i].handle);
1932 ASSERT_TRUE(values[i].result.is_error());
1933 EXPECT_EQ(errors[i], values[i].result.error_value());
1934 EXPECT_FALSE(values[i].maybe_truncated);
1935 }
1936 });
1937
1938 RunUntilIdle();
1939 ASSERT_TRUE(status.has_value());
1940 ASSERT_EQ(fit::ok(), *status);
1941 }
1942
TEST_F(RemoteServiceManagerTest,ReadByTypeReturnsProtocolErrorAfterRead)1943 TEST_F(RemoteServiceManagerTest, ReadByTypeReturnsProtocolErrorAfterRead) {
1944 constexpr att::Handle kStartHandle = 1;
1945 constexpr att::Handle kEndHandle = 5;
1946 auto service = SetUpFakeService(ServiceData(
1947 ServiceKind::PRIMARY, kStartHandle, kEndHandle, kTestServiceUuid1));
1948
1949 constexpr UUID kCharUuid(uint16_t{0xfefe});
1950
1951 constexpr att::Handle kHandle = kEndHandle;
1952 const auto kValue = StaticByteBuffer(0x00, 0x01, 0x02);
1953 const std::vector<Client::ReadByTypeValue> kValues = {
1954 {kHandle, kValue.view(), /*maybe_truncated=*/false}};
1955
1956 const std::vector<std::pair<const char*, att::ErrorCode>>
1957 general_protocol_errors = {
1958 {"kRequestNotSupported", att::ErrorCode::kRequestNotSupported},
1959 {"kInsufficientResources", att::ErrorCode::kInsufficientResources},
1960 {"kInvalidPDU", att::ErrorCode::kInvalidPDU}};
1961
1962 for (const auto& [name, code] : general_protocol_errors) {
1963 SCOPED_TRACE(bt_lib_cpp_string::StringPrintf("Error Code: %s", name));
1964 size_t read_count = 0;
1965 fake_client()->set_read_by_type_request_callback(
1966 [&, code = code](const UUID& type,
1967 att::Handle start,
1968 att::Handle end,
1969 auto callback) {
1970 ASSERT_EQ(0u, read_count++);
1971 switch (read_count++) {
1972 case 0:
1973 callback(fit::ok(kValues));
1974 break;
1975 case 1:
1976 callback(fit::error(
1977 Client::ReadByTypeError{att::Error(code), std::nullopt}));
1978 break;
1979 default:
1980 FAIL();
1981 }
1982 });
1983
1984 std::optional<att::Result<>> status;
1985 service->ReadByType(kCharUuid, [&](att::Result<> cb_status, auto values) {
1986 status = cb_status;
1987 EXPECT_EQ(0u, values.size());
1988 });
1989
1990 RunUntilIdle();
1991 ASSERT_TRUE(status.has_value());
1992 EXPECT_EQ(ToResult(code), status);
1993 }
1994 }
1995
TEST_F(RemoteServiceManagerTest,ReadByTypeHandlesReadErrorWithMissingHandle)1996 TEST_F(RemoteServiceManagerTest, ReadByTypeHandlesReadErrorWithMissingHandle) {
1997 constexpr att::Handle kStartHandle = 1;
1998 constexpr att::Handle kEndHandle = 5;
1999 auto service = SetUpFakeService(ServiceData(
2000 ServiceKind::PRIMARY, kStartHandle, kEndHandle, kTestServiceUuid1));
2001
2002 constexpr UUID kCharUuid(uint16_t{0xfefe});
2003
2004 size_t read_count = 0;
2005 fake_client()->set_read_by_type_request_callback(
2006 [&](const UUID& type, att::Handle start, att::Handle end, auto callback) {
2007 ASSERT_EQ(0u, read_count++);
2008 callback(fit::error(Client::ReadByTypeError{
2009 att::Error(att::ErrorCode::kReadNotPermitted), std::nullopt}));
2010 });
2011
2012 std::optional<att::Result<>> status;
2013 service->ReadByType(kCharUuid, [&](att::Result<> cb_status, auto values) {
2014 status = cb_status;
2015 });
2016 RunUntilIdle();
2017 ASSERT_TRUE(status.has_value());
2018 EXPECT_EQ(ToResult(att::ErrorCode::kReadNotPermitted), *status);
2019 }
2020
TEST_F(RemoteServiceManagerTest,ReadByTypeHandlesReadErrorWithOutOfRangeHandle)2021 TEST_F(RemoteServiceManagerTest,
2022 ReadByTypeHandlesReadErrorWithOutOfRangeHandle) {
2023 constexpr att::Handle kStartHandle = 1;
2024 constexpr att::Handle kEndHandle = 5;
2025 auto service = SetUpFakeService(ServiceData(
2026 ServiceKind::PRIMARY, kStartHandle, kEndHandle, kTestServiceUuid1));
2027
2028 constexpr UUID kCharUuid(uint16_t{0xfefe});
2029
2030 size_t read_count = 0;
2031 fake_client()->set_read_by_type_request_callback(
2032 [&](const UUID& type, att::Handle start, att::Handle end, auto callback) {
2033 ASSERT_EQ(0u, read_count++);
2034 callback(fit::error(Client::ReadByTypeError{
2035 att::Error(att::ErrorCode::kReadNotPermitted), kEndHandle + 1}));
2036 });
2037
2038 std::optional<att::Result<>> status;
2039 service->ReadByType(kCharUuid, [&](att::Result<> cb_status, auto values) {
2040 status = cb_status;
2041 });
2042 RunUntilIdle();
2043 ASSERT_TRUE(status.has_value());
2044 EXPECT_EQ(ToResult(HostError::kPacketMalformed), *status);
2045 }
2046
TEST_F(RemoteServiceManagerTest,ReadByTypeReturnsErrorIfUuidIsInternal)2047 TEST_F(RemoteServiceManagerTest, ReadByTypeReturnsErrorIfUuidIsInternal) {
2048 const std::array<UUID, 10> kInternalUuids = {
2049 types::kPrimaryService,
2050 types::kSecondaryService,
2051 types::kIncludeDeclaration,
2052 types::kCharacteristicDeclaration,
2053 types::kCharacteristicExtProperties,
2054 types::kCharacteristicUserDescription,
2055 types::kClientCharacteristicConfig,
2056 types::kServerCharacteristicConfig,
2057 types::kCharacteristicFormat,
2058 types::kCharacteristicAggregateFormat};
2059
2060 auto service = SetUpFakeService(ServiceData(
2061 ServiceKind::PRIMARY, 1, kDefaultChrcValueHandle, kTestServiceUuid1));
2062
2063 fake_client()->set_read_by_type_request_callback(
2064 [&](auto, auto, auto, auto) { ADD_FAILURE(); });
2065
2066 for (const UUID& uuid : kInternalUuids) {
2067 std::optional<att::Result<>> status;
2068 service->ReadByType(uuid, [&](att::Result<> cb_status, auto values) {
2069 status = cb_status;
2070 EXPECT_EQ(0u, values.size());
2071 });
2072
2073 RunUntilIdle();
2074 ASSERT_TRUE(status.has_value()) << "UUID: " << uuid;
2075 EXPECT_EQ(ToResult(HostError::kInvalidParameters), *status);
2076 }
2077 }
2078
TEST_F(RemoteServiceManagerTest,WriteCharWhileNotReady)2079 TEST_F(RemoteServiceManagerTest, WriteCharWhileNotReady) {
2080 auto service = SetUpFakeService(
2081 ServiceData(ServiceKind::PRIMARY, 1, 2, kTestServiceUuid1));
2082
2083 att::Result<> status = fit::ok();
2084 service->WriteCharacteristic(
2085 kDefaultCharacteristic,
2086 std::vector<uint8_t>(),
2087 [&](att::Result<> cb_status) { status = cb_status; });
2088
2089 RunUntilIdle();
2090
2091 EXPECT_EQ(ToResult(HostError::kNotReady), status);
2092 }
2093
TEST_F(RemoteServiceManagerTest,WriteCharNotFound)2094 TEST_F(RemoteServiceManagerTest, WriteCharNotFound) {
2095 auto service = SetupServiceWithChrcs(
2096 ServiceData(ServiceKind::PRIMARY, 1, 2, kTestServiceUuid1), {});
2097
2098 att::Result<> status = fit::ok();
2099 service->WriteCharacteristic(
2100 kDefaultCharacteristic,
2101 std::vector<uint8_t>(),
2102 [&](att::Result<> cb_status) { status = cb_status; });
2103
2104 RunUntilIdle();
2105
2106 EXPECT_EQ(ToResult(HostError::kNotFound), status);
2107 }
2108
TEST_F(RemoteServiceManagerTest,WriteCharNotSupported)2109 TEST_F(RemoteServiceManagerTest, WriteCharNotSupported) {
2110 // No "write" property set.
2111 auto service = SetupServiceWithChrcs(
2112 ServiceData(ServiceKind::PRIMARY, 1, 3, kTestServiceUuid1),
2113 {ReadableChrc()});
2114
2115 att::Result<> status = fit::ok();
2116 service->WriteCharacteristic(
2117 kDefaultCharacteristic,
2118 std::vector<uint8_t>(),
2119 [&](att::Result<> cb_status) { status = cb_status; });
2120
2121 RunUntilIdle();
2122
2123 EXPECT_EQ(ToResult(HostError::kNotSupported), status);
2124 }
2125
TEST_F(RemoteServiceManagerTest,WriteCharSendsWriteRequest)2126 TEST_F(RemoteServiceManagerTest, WriteCharSendsWriteRequest) {
2127 const std::vector<uint8_t> kValue{{'t', 'e', 's', 't'}};
2128 constexpr att::Result<> kStatus =
2129 ToResult(att::ErrorCode::kWriteNotPermitted);
2130
2131 auto service = SetupServiceWithChrcs(
2132 ServiceData(
2133 ServiceKind::PRIMARY, 1, kDefaultChrcValueHandle, kTestServiceUuid1),
2134 {WritableChrc()});
2135
2136 fake_client()->set_write_request_callback(
2137 [&](att::Handle handle, const auto& value, auto status_callback) {
2138 EXPECT_EQ(kDefaultChrcValueHandle, handle);
2139 EXPECT_TRUE(std::equal(
2140 kValue.begin(), kValue.end(), value.begin(), value.end()));
2141 status_callback(kStatus);
2142 });
2143
2144 att::Result<> status = fit::ok();
2145 service->WriteCharacteristic(
2146 kDefaultCharacteristic, kValue, [&](att::Result<> cb_status) {
2147 status = cb_status;
2148 });
2149
2150 RunUntilIdle();
2151
2152 EXPECT_EQ(kStatus, status);
2153 }
2154
2155 // Tests that a long write is chunked up properly into a series of QueuedWrites
2156 // that will be processed by the client. This tests a non-zero offset.
TEST_F(RemoteServiceManagerTest,WriteCharLongOffsetSuccess)2157 TEST_F(RemoteServiceManagerTest, WriteCharLongOffsetSuccess) {
2158 constexpr uint16_t kOffset = 5;
2159 constexpr uint16_t kExpectedQueueSize = 4;
2160 constexpr uint16_t kExpectedFullWriteSize = 18;
2161 constexpr uint16_t kExpectedFinalWriteSize = 15;
2162
2163 auto service = SetupServiceWithChrcs(
2164 ServiceData(
2165 ServiceKind::PRIMARY, 1, kDefaultChrcValueHandle, kTestServiceUuid1),
2166 {WritableChrc()});
2167
2168 // Create a vector that will take 4 requests to write. Since the default MTU
2169 // is 23:
2170 // a. The size of |full_write_value| is 69.
2171 // b. att:Handle, |kOffset|, and att::OpCode size is 5 bytes total.
2172 // c. We should write 18 + 18 + 18 + 15 bytes across 4 requests.
2173 // d. These bytes will be written with offset 5, from (5) to (5+69)
2174 std::vector<uint8_t> full_write_value(att::kLEMinMTU * 3);
2175
2176 // Initialize the contents.
2177 for (size_t i = 0; i < full_write_value.size(); ++i) {
2178 full_write_value[i] = i;
2179 }
2180
2181 uint8_t process_long_write_count = 0;
2182 fake_client()->set_execute_prepare_writes_callback(
2183 [&](att::PrepareWriteQueue write_queue,
2184 auto /*reliable_mode*/,
2185 auto callback) {
2186 EXPECT_EQ(write_queue.size(), kExpectedQueueSize);
2187
2188 for (int i = 0; i < kExpectedQueueSize; i++) {
2189 auto write = std::move(write_queue.front());
2190 write_queue.pop();
2191
2192 EXPECT_EQ(write.handle(), kDefaultChrcValueHandle);
2193 EXPECT_EQ(write.offset(), kOffset + (i * kExpectedFullWriteSize));
2194
2195 // All writes expect the final should be full, the final should be
2196 // the remainder.
2197 if (i < kExpectedQueueSize - 1) {
2198 EXPECT_EQ(write.value().size(), kExpectedFullWriteSize);
2199 } else {
2200 EXPECT_EQ(write.value().size(), kExpectedFinalWriteSize);
2201 }
2202 }
2203
2204 process_long_write_count++;
2205
2206 callback(fit::ok());
2207 });
2208
2209 ReliableMode mode = ReliableMode::kDisabled;
2210 att::Result<> status = ToResult(HostError::kFailed);
2211 service->WriteLongCharacteristic(
2212 kDefaultCharacteristic,
2213 kOffset,
2214 full_write_value,
2215 mode,
2216 [&](att::Result<> cb_status) { status = cb_status; });
2217
2218 RunUntilIdle();
2219 EXPECT_EQ(fit::ok(), status);
2220 EXPECT_EQ(1u, process_long_write_count);
2221 }
2222
TEST_F(RemoteServiceManagerTest,WriteCharLongAtExactMultipleOfMtu)2223 TEST_F(RemoteServiceManagerTest, WriteCharLongAtExactMultipleOfMtu) {
2224 constexpr uint16_t kOffset = 0;
2225 constexpr uint16_t kExpectedQueueSize = 4;
2226 constexpr uint16_t kExpectedFullWriteSize = 18;
2227
2228 auto service = SetupServiceWithChrcs(
2229 ServiceData(
2230 ServiceKind::PRIMARY, 1, kDefaultChrcValueHandle, kTestServiceUuid1),
2231 {WritableChrc()});
2232
2233 // Create a vector that will take 4 requests to write. Since the default MTU
2234 // is 23:
2235 // a. The size of |full_write_value| is 72.
2236 // b. att:Handle, |kOffset|, and att::OpCode size is 5 bytes total.
2237 // c. We should write 18 + 18 + 18 + 18 bytes across 4 requests.
2238 // d. These bytes will be written with offset 0, from (0) to (72)
2239 std::vector<uint8_t> full_write_value((att::kLEMinMTU - 5) * 4);
2240
2241 // Initialize the contents.
2242 for (size_t i = 0; i < full_write_value.size(); ++i) {
2243 full_write_value[i] = i;
2244 }
2245
2246 uint8_t process_long_write_count = 0;
2247 fake_client()->set_execute_prepare_writes_callback(
2248 [&](att::PrepareWriteQueue write_queue,
2249 auto /*reliable_mode*/,
2250 auto callback) {
2251 EXPECT_EQ(write_queue.size(), kExpectedQueueSize);
2252
2253 for (int i = 0; i < kExpectedQueueSize; i++) {
2254 auto write = std::move(write_queue.front());
2255 write_queue.pop();
2256
2257 EXPECT_EQ(write.handle(), kDefaultChrcValueHandle);
2258 EXPECT_EQ(write.offset(), kOffset + (i * kExpectedFullWriteSize));
2259
2260 // All writes should be full
2261 EXPECT_EQ(write.value().size(), kExpectedFullWriteSize);
2262 }
2263
2264 process_long_write_count++;
2265
2266 callback(fit::ok());
2267 });
2268
2269 ReliableMode mode = ReliableMode::kDisabled;
2270 att::Result<> status = ToResult(HostError::kFailed);
2271 service->WriteLongCharacteristic(
2272 kDefaultCharacteristic,
2273 kOffset,
2274 full_write_value,
2275 mode,
2276 [&](att::Result<> cb_status) { status = cb_status; });
2277
2278 RunUntilIdle();
2279 EXPECT_EQ(fit::ok(), status);
2280 EXPECT_EQ(1u, process_long_write_count);
2281 }
2282
2283 // Writing a long characteristic with ReliableMode::Enabled should succeed.
TEST_F(RemoteServiceManagerTest,WriteCharLongReliableWrite)2284 TEST_F(RemoteServiceManagerTest, WriteCharLongReliableWrite) {
2285 constexpr uint16_t kOffset = 0;
2286 constexpr uint16_t kExpectedQueueSize = 1;
2287
2288 DescriptorData fake_desc1(kDesc1, types::kCharacteristicExtProperties);
2289 DescriptorData fake_desc2(kDesc2, kTestUuid4);
2290
2291 // The callback should be triggered once to read the value of the descriptor
2292 // containing the ExtendedProperties bitfield.
2293 auto extended_prop_read_cb = [&](att::Handle handle, auto callback) {
2294 callback(fit::ok(), kExtendedPropValue, /*maybe_truncated=*/false);
2295 };
2296 fake_client()->set_read_request_callback(std::move(extended_prop_read_cb));
2297
2298 auto service = SetupServiceWithChrcs(
2299 ServiceData(ServiceKind::PRIMARY, kStart, kEnd, kTestServiceUuid1),
2300 {WriteableExtendedPropChrc()},
2301 {fake_desc1, fake_desc2});
2302
2303 // Create a vector that will take 1 request to write. Since the default MTU
2304 // is 23:
2305 // a. The size of |full_write_value| is 18.
2306 // b. att:Handle, |kOffset|, and att::OpCode size is 5 bytes total.
2307 // c. We should write 18 bytes.
2308 std::vector<uint8_t> full_write_value((att::kLEMinMTU - 5));
2309
2310 // Initialize the contents.
2311 for (size_t i = 0; i < full_write_value.size(); ++i) {
2312 full_write_value[i] = i;
2313 }
2314
2315 uint8_t process_long_write_count = 0;
2316 fake_client()->set_execute_prepare_writes_callback(
2317 [&](att::PrepareWriteQueue write_queue,
2318 auto /*reliable_mode*/,
2319 auto callback) {
2320 EXPECT_EQ(write_queue.size(), kExpectedQueueSize);
2321 process_long_write_count++;
2322 callback(fit::ok());
2323 });
2324
2325 ReliableMode mode = ReliableMode::kEnabled;
2326 att::Result<> status = ToResult(HostError::kFailed);
2327 service->WriteLongCharacteristic(
2328 kDefaultCharacteristic,
2329 kOffset,
2330 full_write_value,
2331 mode,
2332 [&](att::Result<> cb_status) { status = cb_status; });
2333
2334 RunUntilIdle();
2335 EXPECT_EQ(fit::ok(), status);
2336 EXPECT_EQ(1u, process_long_write_count);
2337 }
2338
TEST_F(RemoteServiceManagerTest,WriteWithoutResponseNotSupported)2339 TEST_F(RemoteServiceManagerTest, WriteWithoutResponseNotSupported) {
2340 ServiceData data(ServiceKind::PRIMARY, 1, 3, kTestServiceUuid1);
2341 auto service = SetUpFakeService(data);
2342
2343 // No "write" or "write without response" property.
2344 CharacteristicData chr(0, std::nullopt, 2, 3, kTestUuid3);
2345 SetupCharacteristics(service, {{chr}});
2346
2347 bool called = false;
2348 fake_client()->set_write_without_rsp_callback(
2349 [&](auto, const auto&, auto) { called = true; });
2350
2351 std::optional<att::Result<>> status;
2352 service->WriteCharacteristicWithoutResponse(
2353 kDefaultCharacteristic,
2354 std::vector<uint8_t>(),
2355 [&](att::Result<> cb_status) { status = cb_status; });
2356 RunUntilIdle();
2357 EXPECT_FALSE(called);
2358 ASSERT_TRUE(status.has_value());
2359 EXPECT_EQ(ToResult(HostError::kNotSupported), *status);
2360 }
2361
TEST_F(RemoteServiceManagerTest,WriteWithoutResponseBeforeCharacteristicDiscovery)2362 TEST_F(RemoteServiceManagerTest,
2363 WriteWithoutResponseBeforeCharacteristicDiscovery) {
2364 ServiceData data(ServiceKind::PRIMARY, 1, 3, kTestServiceUuid1);
2365 auto service = SetUpFakeService(data);
2366
2367 bool called = false;
2368 fake_client()->set_write_without_rsp_callback(
2369 [&](auto, const auto&, auto) { called = true; });
2370
2371 std::optional<att::Result<>> status;
2372 service->WriteCharacteristicWithoutResponse(
2373 kDefaultCharacteristic,
2374 std::vector<uint8_t>(),
2375 [&](att::Result<> cb_status) { status = cb_status; });
2376 RunUntilIdle();
2377 EXPECT_FALSE(called);
2378 ASSERT_TRUE(status.has_value());
2379 EXPECT_EQ(ToResult(HostError::kNotReady), *status);
2380 }
2381
TEST_F(RemoteServiceManagerTest,WriteWithoutResponseSuccessWithWriteWithoutResponseProperty)2382 TEST_F(RemoteServiceManagerTest,
2383 WriteWithoutResponseSuccessWithWriteWithoutResponseProperty) {
2384 const std::vector<uint8_t> kValue{{'t', 'e', 's', 't'}};
2385
2386 CharacteristicData chr(Property::kWriteWithoutResponse,
2387 std::nullopt,
2388 2,
2389 kDefaultChrcValueHandle,
2390 kTestUuid3);
2391 auto service = SetupServiceWithChrcs(
2392 ServiceData(
2393 ServiceKind::PRIMARY, 1, kDefaultChrcValueHandle, kTestServiceUuid1),
2394 {chr});
2395
2396 bool called = false;
2397 fake_client()->set_write_without_rsp_callback(
2398 [&](att::Handle handle, const auto& value, att::ResultFunction<> cb) {
2399 EXPECT_EQ(kDefaultChrcValueHandle, handle);
2400 EXPECT_TRUE(std::equal(
2401 kValue.begin(), kValue.end(), value.begin(), value.end()));
2402 called = true;
2403 cb(fit::ok());
2404 });
2405
2406 std::optional<att::Result<>> status;
2407 service->WriteCharacteristicWithoutResponse(
2408 kDefaultCharacteristic, kValue, [&](att::Result<> cb_status) {
2409 status = cb_status;
2410 });
2411 RunUntilIdle();
2412 EXPECT_TRUE(called);
2413 ASSERT_TRUE(status.has_value());
2414 EXPECT_EQ(fit::ok(), *status);
2415 }
2416
TEST_F(RemoteServiceManagerTest,WriteWithoutResponseSuccessWithWriteProperty)2417 TEST_F(RemoteServiceManagerTest, WriteWithoutResponseSuccessWithWriteProperty) {
2418 const std::vector<uint8_t> kValue{{'t', 'e', 's', 't'}};
2419
2420 CharacteristicData chr(
2421 Property::kWrite, std::nullopt, 2, kDefaultChrcValueHandle, kTestUuid3);
2422 auto service = SetupServiceWithChrcs(
2423 ServiceData(
2424 ServiceKind::PRIMARY, 1, kDefaultChrcValueHandle, kTestServiceUuid1),
2425 {chr});
2426
2427 bool called = false;
2428 fake_client()->set_write_without_rsp_callback(
2429 [&](att::Handle handle, const auto& value, att::ResultFunction<> cb) {
2430 EXPECT_EQ(kDefaultChrcValueHandle, handle);
2431 EXPECT_TRUE(std::equal(
2432 kValue.begin(), kValue.end(), value.begin(), value.end()));
2433 called = true;
2434 cb(fit::ok());
2435 });
2436
2437 std::optional<att::Result<>> status;
2438 service->WriteCharacteristicWithoutResponse(
2439 kDefaultCharacteristic, kValue, [&](att::Result<> cb_status) {
2440 status = cb_status;
2441 });
2442 RunUntilIdle();
2443
2444 EXPECT_TRUE(called);
2445 ASSERT_TRUE(status.has_value());
2446 EXPECT_EQ(fit::ok(), *status);
2447 }
2448
TEST_F(RemoteServiceManagerTest,ReadDescWhileNotReady)2449 TEST_F(RemoteServiceManagerTest, ReadDescWhileNotReady) {
2450 auto service = SetUpFakeService(
2451 ServiceData(ServiceKind::PRIMARY, 1, 2, kTestServiceUuid1));
2452
2453 att::Result<> status = fit::ok();
2454 service->ReadDescriptor(0, [&](att::Result<> cb_status, const auto&, auto) {
2455 status = cb_status;
2456 });
2457
2458 RunUntilIdle();
2459
2460 EXPECT_EQ(ToResult(HostError::kNotReady), status);
2461 }
2462
TEST_F(RemoteServiceManagerTest,ReadDescriptorNotFound)2463 TEST_F(RemoteServiceManagerTest, ReadDescriptorNotFound) {
2464 auto service = SetupServiceWithChrcs(
2465 ServiceData(ServiceKind::PRIMARY, 1, 2, kTestServiceUuid1), {});
2466
2467 att::Result<> status = fit::ok();
2468 service->ReadDescriptor(0, [&](att::Result<> cb_status, const auto&, auto) {
2469 status = cb_status;
2470 });
2471
2472 RunUntilIdle();
2473
2474 EXPECT_EQ(ToResult(HostError::kNotFound), status);
2475 }
2476
TEST_F(RemoteServiceManagerTest,ReadDescSendsReadRequest)2477 TEST_F(RemoteServiceManagerTest, ReadDescSendsReadRequest) {
2478 // TODO(armansito): Some of the service set up and |status| verification
2479 // boilerplate could be reduced by factoring them out into helpers on the test
2480 // harness (also see code review comment in
2481 // https://fuchsia-review.googlesource.com/c/garnet/+/213794/6/drivers/bluetooth/lib/gatt/remote_service_manager_test.cc).
2482 constexpr att::Handle kValueHandle1 = 3;
2483 constexpr att::Handle kValueHandle2 = 5;
2484 constexpr att::Handle kDescrHandle = 6;
2485
2486 ServiceData data(ServiceKind::PRIMARY, 1, kDescrHandle, kTestServiceUuid1);
2487 auto service = SetUpFakeService(data);
2488
2489 CharacteristicData chr1(
2490 Property::kRead, std::nullopt, 2, kValueHandle1, kTestUuid3);
2491 CharacteristicData chr2(
2492 Property::kRead, std::nullopt, 4, kValueHandle2, kTestUuid3);
2493 DescriptorData desc(kDescrHandle, kTestUuid4);
2494 SetupCharacteristics(service, {{chr1, chr2}}, {{desc}});
2495
2496 const StaticByteBuffer kValue('t', 'e', 's', 't');
2497
2498 fake_client()->set_read_request_callback(
2499 [&](att::Handle handle, auto callback) {
2500 EXPECT_EQ(kDescrHandle, handle);
2501 callback(fit::ok(), kValue, /*maybe_truncated=*/false);
2502 });
2503
2504 att::Result<> status = ToResult(HostError::kFailed);
2505 service->ReadDescriptor(
2506 DescriptorHandle(kDescrHandle),
2507 [&](att::Result<> cb_status, const auto& value, auto) {
2508 status = cb_status;
2509 EXPECT_TRUE(ContainersEqual(kValue, value));
2510 });
2511
2512 RunUntilIdle();
2513
2514 EXPECT_EQ(fit::ok(), status);
2515 }
2516
TEST_F(RemoteServiceManagerTest,ReadLongDescWhileNotReady)2517 TEST_F(RemoteServiceManagerTest, ReadLongDescWhileNotReady) {
2518 auto service = SetUpFakeService(
2519 ServiceData(ServiceKind::PRIMARY, 1, 2, kTestServiceUuid1));
2520
2521 att::Result<> status = fit::ok();
2522 service->ReadLongDescriptor(
2523 0, 0, 512, [&](att::Result<> cb_status, const auto&, auto) {
2524 status = cb_status;
2525 });
2526
2527 RunUntilIdle();
2528
2529 EXPECT_EQ(ToResult(HostError::kNotReady), status);
2530 }
2531
TEST_F(RemoteServiceManagerTest,ReadLongDescNotFound)2532 TEST_F(RemoteServiceManagerTest, ReadLongDescNotFound) {
2533 auto service = SetupServiceWithChrcs(
2534 ServiceData(ServiceKind::PRIMARY, 1, 2, kTestServiceUuid1), {});
2535
2536 att::Result<> status = fit::ok();
2537 service->ReadLongDescriptor(
2538 0, 0, 512, [&](att::Result<> cb_status, const auto&, auto) {
2539 status = cb_status;
2540 });
2541
2542 RunUntilIdle();
2543
2544 EXPECT_EQ(ToResult(HostError::kNotFound), status);
2545 }
2546
2547 // Tests that ReadLongDescriptor sends Read Blob requests. Other conditions
2548 // around the long read procedure are already covered by the tests for
2549 // ReadLongCharacteristic as the implementations are shared.
TEST_F(RemoteServiceManagerTest,ReadLongDescriptor)2550 TEST_F(RemoteServiceManagerTest, ReadLongDescriptor) {
2551 constexpr att::Handle kValueHandle = 3;
2552 constexpr att::Handle kDescrHandle = 4;
2553 constexpr uint16_t kOffset = 0;
2554 constexpr size_t kMaxBytes = 1000;
2555 constexpr int kExpectedBlobCount = 4;
2556
2557 ServiceData data(ServiceKind::PRIMARY, 1, kDescrHandle, kTestServiceUuid1);
2558 auto service = SetUpFakeService(data);
2559
2560 CharacteristicData chr(
2561 Property::kRead, std::nullopt, 2, kValueHandle, kTestUuid3);
2562 DescriptorData desc(kDescrHandle, kTestUuid4);
2563 SetupCharacteristics(service, {{chr}}, {{desc}});
2564
2565 // Create a buffer that will take 4 requests to read. Since the default MTU is
2566 // 23:
2567 // a. The size of |expected_value| is 69.
2568 // b. We should read 22 + 22 + 22 + 3 bytes across 4 requests.
2569 StaticByteBuffer<att::kLEMinMTU * 3> expected_value;
2570
2571 // Initialize the contents.
2572 for (size_t i = 0; i < expected_value.size(); ++i) {
2573 expected_value[i] = i;
2574 }
2575
2576 int read_count = 0;
2577 fake_client()->set_read_request_callback(
2578 [&](att::Handle handle, auto callback) {
2579 read_count++;
2580 EXPECT_EQ(read_count, 1);
2581 EXPECT_EQ(kDescrHandle, handle);
2582 auto blob = expected_value.view(0, att::kLEMinMTU - 1);
2583 callback(fit::ok(), blob, /*maybe_truncated=*/true);
2584 });
2585
2586 fake_client()->set_read_blob_request_callback(
2587 [&](att::Handle handle, uint16_t offset, auto callback) {
2588 read_count++;
2589 EXPECT_GT(read_count, 1);
2590 EXPECT_EQ(kDescrHandle, handle);
2591 bool maybe_truncated = true;
2592
2593 // Return a blob at the given offset with at most MTU - 1 bytes.
2594 auto blob = expected_value.view(offset, att::kLEMinMTU - 1);
2595 if (read_count == kExpectedBlobCount) {
2596 // The final blob should contain 3 bytes.
2597 EXPECT_EQ(3u, blob.size());
2598 maybe_truncated = false;
2599 }
2600
2601 callback(fit::ok(), blob, maybe_truncated);
2602 });
2603
2604 att::Result<> status = ToResult(HostError::kFailed);
2605 service->ReadLongDescriptor(
2606 DescriptorHandle(kDescrHandle),
2607 kOffset,
2608 kMaxBytes,
2609 [&](att::Result<> cb_status, const auto& value, bool maybe_truncated) {
2610 status = cb_status;
2611 EXPECT_TRUE(ContainersEqual(expected_value, value));
2612 EXPECT_FALSE(maybe_truncated);
2613 });
2614
2615 RunUntilIdle();
2616 EXPECT_EQ(fit::ok(), status);
2617 EXPECT_EQ(kExpectedBlobCount, read_count);
2618 }
2619
TEST_F(RemoteServiceManagerTest,WriteDescWhileNotReady)2620 TEST_F(RemoteServiceManagerTest, WriteDescWhileNotReady) {
2621 auto service = SetUpFakeService(
2622 ServiceData(ServiceKind::PRIMARY, 1, 2, kTestServiceUuid1));
2623
2624 att::Result<> status = fit::ok();
2625 service->WriteDescriptor(
2626 0, std::vector<uint8_t>(), [&](att::Result<> cb_status) {
2627 status = cb_status;
2628 });
2629
2630 RunUntilIdle();
2631
2632 EXPECT_EQ(ToResult(HostError::kNotReady), status);
2633 }
2634
TEST_F(RemoteServiceManagerTest,WriteDescNotFound)2635 TEST_F(RemoteServiceManagerTest, WriteDescNotFound) {
2636 auto service = SetUpFakeService(
2637 ServiceData(ServiceKind::PRIMARY, 1, 2, kTestServiceUuid1));
2638 SetupCharacteristics(service, std::vector<CharacteristicData>());
2639
2640 att::Result<> status = fit::ok();
2641 service->WriteDescriptor(
2642 0, std::vector<uint8_t>(), [&](att::Result<> cb_status) {
2643 status = cb_status;
2644 });
2645
2646 RunUntilIdle();
2647
2648 EXPECT_EQ(ToResult(HostError::kNotFound), status);
2649 }
2650
TEST_F(RemoteServiceManagerTest,WriteDescNotAllowed)2651 TEST_F(RemoteServiceManagerTest, WriteDescNotAllowed) {
2652 auto service = SetUpFakeService(
2653 ServiceData(ServiceKind::PRIMARY, 1, 4, kTestServiceUuid1));
2654
2655 // "CCC" characteristic cannot be written to.
2656 CharacteristicData chr(0, std::nullopt, 2, 3, kTestUuid3);
2657 DescriptorData desc(4, types::kClientCharacteristicConfig);
2658 SetupCharacteristics(service, {{chr}}, {{desc}});
2659
2660 att::Result<> status = fit::ok();
2661 service->WriteDescriptor(
2662 4, std::vector<uint8_t>(), [&](att::Result<> cb_status) {
2663 status = cb_status;
2664 });
2665
2666 RunUntilIdle();
2667
2668 EXPECT_EQ(ToResult(HostError::kNotSupported), status);
2669 }
2670
TEST_F(RemoteServiceManagerTest,WriteDescSendsWriteRequest)2671 TEST_F(RemoteServiceManagerTest, WriteDescSendsWriteRequest) {
2672 constexpr att::Handle kValueHandle = 3;
2673 constexpr att::Handle kDescrHandle = 4;
2674 const std::vector<uint8_t> kValue{{'t', 'e', 's', 't'}};
2675 const att::Result<> kStatus = ToResult(HostError::kNotSupported);
2676
2677 ServiceData data(ServiceKind::PRIMARY, 1, kDescrHandle, kTestServiceUuid1);
2678 auto service = SetUpFakeService(data);
2679
2680 CharacteristicData chr(
2681 Property::kWrite, std::nullopt, 2, kValueHandle, kTestUuid3);
2682 DescriptorData desc(kDescrHandle, kTestUuid4);
2683 SetupCharacteristics(service, {{chr}}, {{desc}});
2684
2685 fake_client()->set_write_request_callback(
2686 [&](att::Handle handle, const auto& value, auto status_callback) {
2687 EXPECT_EQ(kDescrHandle, handle);
2688 EXPECT_TRUE(std::equal(
2689 kValue.begin(), kValue.end(), value.begin(), value.end()));
2690 status_callback(kStatus);
2691 });
2692
2693 att::Result<> status = fit::ok();
2694 service->WriteDescriptor(kDescrHandle, kValue, [&](att::Result<> cb_status) {
2695 status = cb_status;
2696 });
2697
2698 RunUntilIdle();
2699 EXPECT_EQ(kStatus, status);
2700 }
2701
2702 // Tests that WriteDescriptor with a long vector is prepared correctly.
2703 // Other conditions around the long write procedure are already covered by the
2704 // tests for WriteCharacteristic as the implementations are shared.
TEST_F(RemoteServiceManagerTest,WriteDescLongSuccess)2705 TEST_F(RemoteServiceManagerTest, WriteDescLongSuccess) {
2706 constexpr att::Handle kValueHandle = 3;
2707 constexpr att::Handle kDescrHandle = 4;
2708 constexpr uint16_t kOffset = 0;
2709 constexpr uint16_t kExpectedQueueSize = 4;
2710 constexpr uint16_t kExpectedFullWriteSize = 18;
2711 constexpr uint16_t kExpectedFinalWriteSize = 15;
2712
2713 ServiceData data(ServiceKind::PRIMARY, 1, kDescrHandle, kTestServiceUuid1);
2714 auto service = SetUpFakeService(data);
2715
2716 CharacteristicData chr(
2717 Property::kWrite, std::nullopt, 2, kValueHandle, kTestUuid3);
2718 DescriptorData desc(kDescrHandle, kTestUuid4);
2719 SetupCharacteristics(service, {{chr}}, {{desc}});
2720
2721 // Create a vector that will take 4 requests to write. Since the default MTU
2722 // is 23:
2723 // a. The size of |full_write_value| is 69.
2724 // b. att:Handle, |kOffset|, and att::OpCode size is 5 bytes total.
2725 // c. We should write 18 + 18 + 18 + 15 bytes across 4 requests.
2726 // d. These bytes will be written with offset 5, from (5) to (5+69)
2727 std::vector<uint8_t> full_write_value(att::kLEMinMTU * 3);
2728
2729 // Initialize the contents.
2730 for (size_t i = 0; i < full_write_value.size(); ++i) {
2731 full_write_value[i] = i;
2732 }
2733
2734 uint8_t process_long_write_count = 0;
2735 fake_client()->set_execute_prepare_writes_callback(
2736 [&](att::PrepareWriteQueue write_queue,
2737 auto /*reliable_mode*/,
2738 auto callback) {
2739 EXPECT_EQ(write_queue.size(), kExpectedQueueSize);
2740
2741 att::QueuedWrite prepare_write;
2742 for (int i = 0; i < kExpectedQueueSize; i++) {
2743 auto write = std::move(write_queue.front());
2744 write_queue.pop();
2745
2746 EXPECT_EQ(write.handle(), kDescrHandle);
2747 EXPECT_EQ(write.offset(), kOffset + (i * kExpectedFullWriteSize));
2748
2749 // All writes expect the final should be full, the final should be
2750 // the remainder.
2751 if (i < kExpectedQueueSize - 1) {
2752 EXPECT_EQ(write.value().size(), kExpectedFullWriteSize);
2753 } else {
2754 EXPECT_EQ(write.value().size(), kExpectedFinalWriteSize);
2755 }
2756 }
2757
2758 process_long_write_count++;
2759
2760 callback(fit::ok());
2761 });
2762
2763 att::Result<> status = ToResult(HostError::kFailed);
2764 service->WriteLongDescriptor(
2765 DescriptorHandle(kDescrHandle),
2766 kOffset,
2767 full_write_value,
2768 [&](att::Result<> cb_status) { status = cb_status; });
2769
2770 RunUntilIdle();
2771 EXPECT_EQ(fit::ok(), status);
2772 EXPECT_EQ(1u, process_long_write_count);
2773 }
2774
TEST_F(RemoteServiceManagerTest,EnableNotificationsWhileNotReady)2775 TEST_F(RemoteServiceManagerTest, EnableNotificationsWhileNotReady) {
2776 auto service = SetUpFakeService(
2777 ServiceData(ServiceKind::PRIMARY, 1, 2, kTestServiceUuid1));
2778
2779 att::Result<> status = fit::ok();
2780 service->EnableNotifications(
2781 kDefaultCharacteristic,
2782 NopValueCallback,
2783 [&](att::Result<> cb_status, IdType) { status = cb_status; });
2784
2785 RunUntilIdle();
2786
2787 EXPECT_EQ(ToResult(HostError::kNotReady), status);
2788 }
2789
TEST_F(RemoteServiceManagerTest,EnableNotificationsCharNotFound)2790 TEST_F(RemoteServiceManagerTest, EnableNotificationsCharNotFound) {
2791 auto service = SetupServiceWithChrcs(
2792 ServiceData(ServiceKind::PRIMARY, 1, 2, kTestServiceUuid1), {});
2793
2794 att::Result<> status = fit::ok();
2795 service->EnableNotifications(
2796 kDefaultCharacteristic,
2797 NopValueCallback,
2798 [&](att::Result<> cb_status, IdType) { status = cb_status; });
2799
2800 RunUntilIdle();
2801
2802 EXPECT_EQ(ToResult(HostError::kNotFound), status);
2803 }
2804
TEST_F(RemoteServiceManagerTest,EnableNotificationsNoProperties)2805 TEST_F(RemoteServiceManagerTest, EnableNotificationsNoProperties) {
2806 auto service = SetUpFakeService(
2807 ServiceData(ServiceKind::PRIMARY, 1, 4, kTestServiceUuid1));
2808
2809 // Has neither the "notify" nor "indicate" property but has a CCC descriptor.
2810 CharacteristicData chr(Property::kRead, std::nullopt, 2, 3, kTestUuid3);
2811 DescriptorData desc(4, types::kClientCharacteristicConfig);
2812 SetupCharacteristics(service, {{chr}}, {{desc}});
2813
2814 att::Result<> status = fit::ok();
2815 service->EnableNotifications(
2816 kDefaultCharacteristic,
2817 NopValueCallback,
2818 [&](att::Result<> cb_status, IdType) { status = cb_status; });
2819 RunUntilIdle();
2820
2821 EXPECT_EQ(ToResult(HostError::kNotSupported), status);
2822 }
2823
TEST_F(RemoteServiceManagerTest,EnableNotificationsSuccess)2824 TEST_F(RemoteServiceManagerTest, EnableNotificationsSuccess) {
2825 constexpr att::Handle kCCCHandle = 4;
2826 auto service = SetUpFakeService(
2827 ServiceData(ServiceKind::PRIMARY, 1, kCCCHandle, kTestServiceUuid1));
2828
2829 CharacteristicData chr(Property::kNotify, std::nullopt, 2, 3, kTestUuid3);
2830 DescriptorData desc(kCCCHandle, types::kClientCharacteristicConfig);
2831 SetupCharacteristics(service, {{chr}}, {{desc}});
2832
2833 fake_client()->set_write_request_callback(
2834 [&](att::Handle handle, const auto& value, auto status_callback) {
2835 EXPECT_EQ(kCCCHandle, handle);
2836 EXPECT_TRUE(ContainersEqual(kCCCNotifyValue, value));
2837 status_callback(fit::ok());
2838 });
2839
2840 IdType id = kInvalidId;
2841 att::Result<> status = ToResult(HostError::kFailed);
2842 service->EnableNotifications(kDefaultCharacteristic,
2843 NopValueCallback,
2844 [&](att::Result<> cb_status, IdType cb_id) {
2845 status = cb_status;
2846 id = cb_id;
2847 });
2848
2849 RunUntilIdle();
2850
2851 EXPECT_EQ(fit::ok(), status);
2852 EXPECT_NE(kInvalidId, id);
2853 }
2854
TEST_F(RemoteServiceManagerTest,EnableIndications)2855 TEST_F(RemoteServiceManagerTest, EnableIndications) {
2856 constexpr att::Handle kCCCHandle = 4;
2857 auto service = SetUpFakeService(
2858 ServiceData(ServiceKind::PRIMARY, 1, kCCCHandle, kTestServiceUuid1));
2859
2860 CharacteristicData chr(Property::kIndicate, std::nullopt, 2, 3, kTestUuid3);
2861 DescriptorData desc(kCCCHandle, types::kClientCharacteristicConfig);
2862 SetupCharacteristics(service, {{chr}}, {{desc}});
2863
2864 fake_client()->set_write_request_callback(
2865 [&](att::Handle handle, const auto& value, auto status_callback) {
2866 EXPECT_EQ(kCCCHandle, handle);
2867 EXPECT_TRUE(ContainersEqual(kCCCIndicateValue, value));
2868 status_callback(fit::ok());
2869 });
2870
2871 IdType id = kInvalidId;
2872 att::Result<> status = ToResult(HostError::kFailed);
2873 service->EnableNotifications(kDefaultCharacteristic,
2874 NopValueCallback,
2875 [&](att::Result<> cb_status, IdType cb_id) {
2876 status = cb_status;
2877 id = cb_id;
2878 });
2879
2880 RunUntilIdle();
2881
2882 EXPECT_EQ(fit::ok(), status);
2883 EXPECT_NE(kInvalidId, id);
2884 }
2885
TEST_F(RemoteServiceManagerTest,EnableNotificationsError)2886 TEST_F(RemoteServiceManagerTest, EnableNotificationsError) {
2887 constexpr att::Handle kCCCHandle = 4;
2888
2889 auto service = SetUpFakeService(
2890 ServiceData(ServiceKind::PRIMARY, 1, 4, kTestServiceUuid1));
2891
2892 CharacteristicData chr(Property::kNotify, std::nullopt, 2, 3, kTestUuid3);
2893 DescriptorData desc(kCCCHandle, types::kClientCharacteristicConfig);
2894 SetupCharacteristics(service, {{chr}}, {{desc}});
2895
2896 // Should enable notifications
2897 const StaticByteBuffer kExpectedValue(0x01, 0x00);
2898
2899 fake_client()->set_write_request_callback(
2900 [&](att::Handle handle, const auto& value, auto status_callback) {
2901 EXPECT_EQ(kCCCHandle, handle);
2902 EXPECT_TRUE(ContainersEqual(kExpectedValue, value));
2903 status_callback(ToResult(att::ErrorCode::kUnlikelyError));
2904 });
2905
2906 IdType id = kInvalidId;
2907 att::Result<> status = fit::ok();
2908 service->EnableNotifications(kDefaultCharacteristic,
2909 NopValueCallback,
2910 [&](att::Result<> cb_status, IdType cb_id) {
2911 status = cb_status;
2912 id = cb_id;
2913 });
2914
2915 RunUntilIdle();
2916
2917 EXPECT_EQ(ToResult(att::ErrorCode::kUnlikelyError), status);
2918 EXPECT_EQ(kInvalidId, id);
2919 }
2920
TEST_F(RemoteServiceManagerTest,EnableNotificationsRequestMany)2921 TEST_F(RemoteServiceManagerTest, EnableNotificationsRequestMany) {
2922 constexpr att::Handle kCCCHandle1 = 4;
2923 constexpr att::Handle kCCCHandle2 = 7;
2924
2925 auto service = SetUpFakeService(
2926 ServiceData(ServiceKind::PRIMARY, 1, 7, kTestServiceUuid1));
2927
2928 // Set up two characteristics
2929 CharacteristicData chr1(Property::kNotify, std::nullopt, 2, 3, kTestUuid3);
2930 DescriptorData desc1(kCCCHandle1, types::kClientCharacteristicConfig);
2931
2932 CharacteristicData chr2(Property::kIndicate, std::nullopt, 5, 6, kTestUuid3);
2933 DescriptorData desc2(kCCCHandle2, types::kClientCharacteristicConfig);
2934
2935 SetupCharacteristics(service, {{chr1, chr2}}, {{desc1, desc2}});
2936
2937 int ccc_write_count = 0;
2938 att::ResultFunction<> status_callback1, status_callback2;
2939 fake_client()->set_write_request_callback(
2940 [&](att::Handle handle, const auto& value, auto status_cb) {
2941 if (handle == kCCCHandle1) {
2942 EXPECT_TRUE(ContainersEqual(kCCCNotifyValue, value));
2943 status_callback1 = std::move(status_cb);
2944 } else if (handle == kCCCHandle2) {
2945 EXPECT_TRUE(ContainersEqual(kCCCIndicateValue, value));
2946 status_callback2 = std::move(status_cb);
2947 } else {
2948 ADD_FAILURE() << "Unexpected handle: " << handle;
2949 }
2950 ccc_write_count++;
2951 });
2952
2953 size_t cb_count = 0u;
2954
2955 service->EnableNotifications(kDefaultCharacteristic,
2956 NopValueCallback,
2957 [&](att::Result<> status, IdType id) {
2958 cb_count++;
2959 EXPECT_EQ(1u, id);
2960 EXPECT_EQ(fit::ok(), status);
2961 });
2962 service->EnableNotifications(kDefaultCharacteristic,
2963 NopValueCallback,
2964 [&](att::Result<> status, IdType id) {
2965 cb_count++;
2966 EXPECT_EQ(2u, id);
2967 EXPECT_EQ(fit::ok(), status);
2968 });
2969 service->EnableNotifications(kSecondCharacteristic,
2970 NopValueCallback,
2971 [&](att::Result<> status, IdType id) {
2972 cb_count++;
2973 EXPECT_EQ(1u, id);
2974 EXPECT_EQ(fit::ok(), status);
2975 });
2976 service->EnableNotifications(kSecondCharacteristic,
2977 NopValueCallback,
2978 [&](att::Result<> status, IdType id) {
2979 cb_count++;
2980 EXPECT_EQ(2u, id);
2981 EXPECT_EQ(fit::ok(), status);
2982 });
2983 service->EnableNotifications(kSecondCharacteristic,
2984 NopValueCallback,
2985 [&](att::Result<> status, IdType id) {
2986 cb_count++;
2987 EXPECT_EQ(3u, id);
2988 EXPECT_EQ(fit::ok(), status);
2989 });
2990
2991 RunUntilIdle();
2992
2993 // ATT write requests should be sent but none of the notification requests
2994 // should be resolved.
2995 EXPECT_EQ(2, ccc_write_count);
2996 EXPECT_EQ(0u, cb_count);
2997
2998 // An ATT response should resolve all pending requests for the right
2999 // characteristic.
3000 status_callback1(fit::ok());
3001 EXPECT_EQ(2u, cb_count);
3002 status_callback2(fit::ok());
3003 EXPECT_EQ(5u, cb_count);
3004
3005 // An extra request should succeed without sending any PDUs.
3006 service->EnableNotifications(kDefaultCharacteristic,
3007 NopValueCallback,
3008 [&](att::Result<> status, IdType) {
3009 cb_count++;
3010 EXPECT_EQ(fit::ok(), status);
3011 });
3012
3013 RunUntilIdle();
3014
3015 EXPECT_EQ(2, ccc_write_count);
3016 EXPECT_EQ(6u, cb_count);
3017 }
3018
TEST_F(RemoteServiceManagerTest,EnableNotificationsRequestManyError)3019 TEST_F(RemoteServiceManagerTest, EnableNotificationsRequestManyError) {
3020 constexpr att::Handle kCCCHandle = 4;
3021
3022 auto service = SetUpFakeService(
3023 ServiceData(ServiceKind::PRIMARY, 1, 4, kTestServiceUuid1));
3024
3025 // Set up two characteristics
3026 CharacteristicData chr(Property::kNotify, std::nullopt, 2, 3, kTestUuid3);
3027 DescriptorData desc(kCCCHandle, types::kClientCharacteristicConfig);
3028
3029 SetupCharacteristics(service, {{chr}}, {{desc}});
3030
3031 int ccc_write_count = 0;
3032 att::ResultFunction<> status_callback;
3033 fake_client()->set_write_request_callback(
3034 [&](att::Handle handle, const auto& value, auto status_cb) {
3035 EXPECT_EQ(kCCCHandle, handle);
3036 EXPECT_TRUE(ContainersEqual(kCCCNotifyValue, value));
3037
3038 ccc_write_count++;
3039 status_callback = std::move(status_cb);
3040 });
3041
3042 int cb_count = 0;
3043 att::Result<> status = fit::ok();
3044 auto cb = [&](att::Result<> cb_status, IdType id) {
3045 status = cb_status;
3046 cb_count++;
3047 };
3048
3049 service->EnableNotifications(
3050 kDefaultCharacteristic, NopValueCallback, std::move(cb));
3051 service->EnableNotifications(
3052 kDefaultCharacteristic, NopValueCallback, std::move(cb));
3053 service->EnableNotifications(
3054 kDefaultCharacteristic, NopValueCallback, std::move(cb));
3055
3056 RunUntilIdle();
3057
3058 // Requests should be buffered and only one ATT request should have been sent
3059 // out.
3060 EXPECT_EQ(1, ccc_write_count);
3061 EXPECT_EQ(0, cb_count);
3062
3063 status_callback(ToResult(HostError::kNotSupported));
3064 EXPECT_EQ(3, cb_count);
3065 EXPECT_EQ(ToResult(HostError::kNotSupported), status);
3066
3067 // A new request should write to the descriptor again.
3068 service->EnableNotifications(
3069 kDefaultCharacteristic, NopValueCallback, std::move(cb));
3070
3071 RunUntilIdle();
3072
3073 EXPECT_EQ(2, ccc_write_count);
3074 EXPECT_EQ(3, cb_count);
3075
3076 status_callback(fit::ok());
3077 EXPECT_EQ(2, ccc_write_count);
3078 EXPECT_EQ(4, cb_count);
3079 EXPECT_EQ(fit::ok(), status);
3080 }
3081
3082 // Enabling notifications should succeed without a descriptor write.
TEST_F(RemoteServiceManagerTest,EnableNotificationsWithoutCCC)3083 TEST_F(RemoteServiceManagerTest, EnableNotificationsWithoutCCC) {
3084 // Has the "notify" property but no CCC descriptor.
3085 CharacteristicData chr(Property::kNotify, std::nullopt, 2, 3, kTestUuid3);
3086 auto service = SetupServiceWithChrcs(
3087 ServiceData(ServiceKind::PRIMARY, 1, 3, kTestServiceUuid1), {chr});
3088
3089 bool write_requested = false;
3090 fake_client()->set_write_request_callback(
3091 [&](auto, auto&, auto) { write_requested = true; });
3092
3093 int notify_count = 0;
3094 auto notify_cb = [&](const auto& value, bool /*maybe_truncated*/) {
3095 notify_count++;
3096 };
3097
3098 att::Result<> status = fit::ok();
3099 IdType id;
3100 service->EnableNotifications(kDefaultCharacteristic,
3101 std::move(notify_cb),
3102 [&](att::Result<> _status, IdType _id) {
3103 status = _status;
3104 id = _id;
3105 });
3106 RunUntilIdle();
3107
3108 EXPECT_EQ(fit::ok(), status);
3109 EXPECT_FALSE(write_requested);
3110
3111 fake_client()->SendNotification(/*indicate=*/false,
3112 3,
3113 StaticByteBuffer('y', 'e'),
3114 /*maybe_truncated=*/false);
3115 EXPECT_EQ(1, notify_count);
3116
3117 // Disabling notifications should not result in a write request.
3118 service->DisableNotifications(
3119 kDefaultCharacteristic, id, [&](auto _status) { status = _status; });
3120 RunUntilIdle();
3121 EXPECT_EQ(fit::ok(), status);
3122 EXPECT_FALSE(write_requested);
3123
3124 // The handler should no longer receive notifications.
3125 fake_client()->SendNotification(/*indicate=*/false,
3126 3,
3127 StaticByteBuffer('o', 'y', 'e'),
3128 /*maybe_truncated=*/false);
3129 EXPECT_EQ(1, notify_count);
3130 }
3131
3132 // Notifications received when the remote service database is empty should be
3133 // dropped and not cause a crash.
TEST_F(RemoteServiceManagerTest,NotificationWithoutServices)3134 TEST_F(RemoteServiceManagerTest, NotificationWithoutServices) {
3135 for (att::Handle i = 0; i < 10; ++i) {
3136 fake_client()->SendNotification(
3137 /*indicate=*/false,
3138 i,
3139 StaticByteBuffer('n', 'o', 't', 'i', 'f', 'y'),
3140 /*maybe_truncated=*/false);
3141 }
3142 RunUntilIdle();
3143 }
3144
TEST_F(RemoteServiceManagerTest,NotificationCallback)3145 TEST_F(RemoteServiceManagerTest, NotificationCallback) {
3146 auto service = SetUpFakeService(
3147 ServiceData(ServiceKind::PRIMARY, 1, 7, kTestServiceUuid1));
3148
3149 // Set up two characteristics
3150 CharacteristicData chr1(Property::kNotify, std::nullopt, 2, 3, kTestUuid3);
3151 DescriptorData desc1(4, types::kClientCharacteristicConfig);
3152
3153 CharacteristicData chr2(Property::kIndicate, std::nullopt, 5, 6, kTestUuid3);
3154 DescriptorData desc2(7, types::kClientCharacteristicConfig);
3155
3156 SetupCharacteristics(service, {{chr1, chr2}}, {{desc1, desc2}});
3157
3158 fake_client()->set_write_request_callback(
3159 [&](att::Handle, const auto&, auto status_callback) {
3160 status_callback(fit::ok());
3161 });
3162
3163 IdType handler_id = kInvalidId;
3164 att::Result<> status = ToResult(HostError::kFailed);
3165
3166 int chr1_count = 0;
3167 auto chr1_cb = [&](const ByteBuffer& value, bool maybe_truncated) {
3168 chr1_count++;
3169 EXPECT_EQ("notify", value.AsString());
3170 EXPECT_FALSE(maybe_truncated);
3171 };
3172
3173 int chr2_count = 0;
3174 auto chr2_cb = [&](const ByteBuffer& value, bool maybe_truncated) {
3175 chr2_count++;
3176 EXPECT_EQ("indicate", value.AsString());
3177 EXPECT_TRUE(maybe_truncated);
3178 };
3179
3180 // Notify both characteristics which should get dropped.
3181 fake_client()->SendNotification(
3182 /*indicate=*/false,
3183 3,
3184 StaticByteBuffer('n', 'o', 't', 'i', 'f', 'y'),
3185 /*maybe_truncated=*/false);
3186 fake_client()->SendNotification(
3187 /*indicate=*/true,
3188 6,
3189 StaticByteBuffer('i', 'n', 'd', 'i', 'c', 'a', 't', 'e'),
3190 /*maybe_truncated=*/true);
3191
3192 EnableNotifications(service,
3193 kDefaultCharacteristic,
3194 &status,
3195 &handler_id,
3196 std::move(chr1_cb));
3197 ASSERT_EQ(fit::ok(), status);
3198 EnableNotifications(
3199 service, kSecondCharacteristic, &status, &handler_id, std::move(chr2_cb));
3200 ASSERT_EQ(fit::ok(), status);
3201
3202 // Notify characteristic 1.
3203 fake_client()->SendNotification(
3204 /*indicate=*/false,
3205 3,
3206 StaticByteBuffer('n', 'o', 't', 'i', 'f', 'y'),
3207 /*maybe_truncated=*/false);
3208 EXPECT_EQ(1, chr1_count);
3209 EXPECT_EQ(0, chr2_count);
3210
3211 // Notify characteristic 2.
3212 fake_client()->SendNotification(
3213 /*indicate=*/true,
3214 6,
3215 StaticByteBuffer('i', 'n', 'd', 'i', 'c', 'a', 't', 'e'),
3216 /*maybe_truncated=*/true);
3217 EXPECT_EQ(1, chr1_count);
3218 EXPECT_EQ(1, chr2_count);
3219
3220 // Disable notifications from characteristic 1.
3221 status = ToResult(HostError::kFailed);
3222 service->DisableNotifications(
3223 kDefaultCharacteristic, handler_id, [&](att::Result<> cb_status) {
3224 status = cb_status;
3225 });
3226
3227 RunUntilIdle();
3228 EXPECT_EQ(fit::ok(), status);
3229
3230 // Notifications for characteristic 1 should get dropped.
3231 fake_client()->SendNotification(
3232 /*indicate=*/false,
3233 3,
3234 StaticByteBuffer('n', 'o', 't', 'i', 'f', 'y'),
3235 /*maybe_truncated=*/false);
3236 fake_client()->SendNotification(
3237 /*indicate=*/true,
3238 6,
3239 StaticByteBuffer('i', 'n', 'd', 'i', 'c', 'a', 't', 'e'),
3240 /*maybe_truncated=*/true);
3241 EXPECT_EQ(1, chr1_count);
3242 EXPECT_EQ(2, chr2_count);
3243 }
3244
TEST_F(RemoteServiceManagerTest,DisableNotificationsWhileNotReady)3245 TEST_F(RemoteServiceManagerTest, DisableNotificationsWhileNotReady) {
3246 ServiceData data(ServiceKind::PRIMARY, 1, 4, kTestServiceUuid1);
3247 auto service = SetUpFakeService(data);
3248
3249 att::Result<> status = fit::ok();
3250 service->DisableNotifications(
3251 kDefaultCharacteristic, 1, [&](att::Result<> cb_status) {
3252 status = cb_status;
3253 });
3254
3255 RunUntilIdle();
3256
3257 EXPECT_EQ(ToResult(HostError::kNotReady), status);
3258 }
3259
TEST_F(RemoteServiceManagerTest,DisableNotificationsCharNotFound)3260 TEST_F(RemoteServiceManagerTest, DisableNotificationsCharNotFound) {
3261 auto service = SetupNotifiableService();
3262
3263 IdType id = kInvalidId;
3264 att::Result<> status = ToResult(HostError::kFailed);
3265 EnableNotifications(service, kDefaultCharacteristic, &status, &id);
3266
3267 // "1" is an invalid characteristic ID.
3268 service->DisableNotifications(
3269 kInvalidCharacteristic, id, [&](att::Result<> cb_status) {
3270 status = cb_status;
3271 });
3272
3273 RunUntilIdle();
3274
3275 EXPECT_EQ(ToResult(HostError::kNotFound), status);
3276 }
3277
TEST_F(RemoteServiceManagerTest,DisableNotificationsIdNotFound)3278 TEST_F(RemoteServiceManagerTest, DisableNotificationsIdNotFound) {
3279 auto service = SetupNotifiableService();
3280
3281 IdType id = kInvalidId;
3282 att::Result<> status = ToResult(HostError::kFailed);
3283 EnableNotifications(service, kDefaultCharacteristic, &status, &id);
3284
3285 // Valid characteristic ID but invalid notification handler ID.
3286 service->DisableNotifications(
3287 kDefaultCharacteristic, id + 1, [&](att::Result<> cb_status) {
3288 status = cb_status;
3289 });
3290
3291 RunUntilIdle();
3292
3293 EXPECT_EQ(ToResult(HostError::kNotFound), status);
3294 }
3295
TEST_F(RemoteServiceManagerTest,DisableNotificationsSingleHandler)3296 TEST_F(RemoteServiceManagerTest, DisableNotificationsSingleHandler) {
3297 constexpr att::Handle kCCCHandle = 4;
3298 auto service = SetupNotifiableService();
3299
3300 IdType id = kInvalidId;
3301 att::Result<> status = ToResult(HostError::kFailed);
3302 EnableNotifications(service, kDefaultCharacteristic, &status, &id);
3303
3304 // Should disable notifications
3305 const StaticByteBuffer kExpectedValue(0x00, 0x00);
3306
3307 int ccc_write_count = 0;
3308 fake_client()->set_write_request_callback(
3309 [&](att::Handle handle, const auto& value, auto status_callback) {
3310 EXPECT_EQ(kCCCHandle, handle);
3311 EXPECT_TRUE(ContainersEqual(kExpectedValue, value));
3312 ccc_write_count++;
3313 status_callback(fit::ok());
3314 });
3315
3316 status = ToResult(HostError::kFailed);
3317 service->DisableNotifications(
3318 kDefaultCharacteristic, id, [&](att::Result<> cb_status) {
3319 status = cb_status;
3320 });
3321
3322 RunUntilIdle();
3323
3324 EXPECT_EQ(fit::ok(), status);
3325 EXPECT_EQ(1, ccc_write_count);
3326 }
3327
TEST_F(RemoteServiceManagerTest,DisableNotificationsOnDestruction)3328 TEST_F(RemoteServiceManagerTest, DisableNotificationsOnDestruction) {
3329 constexpr att::Handle kCCCHandle = 4;
3330 auto service = SetupNotifiableService();
3331
3332 IdType id = kInvalidId;
3333 att::Result<> status = ToResult(HostError::kFailed);
3334 EnableNotifications(service, kDefaultCharacteristic, &status, &id);
3335 ASSERT_EQ(fit::ok(), status);
3336
3337 // Should disable notifications
3338 const StaticByteBuffer kExpectedValue(0x00, 0x00);
3339
3340 int ccc_write_count = 0;
3341 fake_client()->set_write_request_callback(
3342 [&](att::Handle handle, const auto& value, auto status_callback) {
3343 EXPECT_EQ(kCCCHandle, handle);
3344 EXPECT_TRUE(ContainersEqual(kExpectedValue, value));
3345 ccc_write_count++;
3346 status_callback(fit::ok());
3347 });
3348
3349 // Destroying the service manager (which destroys the service characteristics)
3350 // should clear the CCC.
3351 DestroyServiceManager();
3352 RunUntilIdle();
3353 EXPECT_EQ(1, ccc_write_count);
3354 }
3355
TEST_F(RemoteServiceManagerTest,DisableNotificationsManyHandlers)3356 TEST_F(RemoteServiceManagerTest, DisableNotificationsManyHandlers) {
3357 auto service = SetupNotifiableService();
3358
3359 IdType id = kInvalidId;
3360 std::vector<IdType> handler_ids;
3361
3362 for (int i = 0; i < 2; i++) {
3363 att::Result<> status = ToResult(HostError::kFailed);
3364 EnableNotifications(service, kDefaultCharacteristic, &status, &id);
3365 ASSERT_EQ(fit::ok(), status);
3366 handler_ids.push_back(id);
3367 }
3368
3369 int ccc_write_count = 0;
3370 fake_client()->set_write_request_callback(
3371 [&](att::Handle handle, const auto& value, auto status_callback) {
3372 ccc_write_count++;
3373 status_callback(fit::ok());
3374 });
3375
3376 // Disabling should succeed without an ATT transaction.
3377 att::Result<> status = ToResult(HostError::kFailed);
3378 service->DisableNotifications(
3379 kDefaultCharacteristic, handler_ids.back(), [&](att::Result<> cb_status) {
3380 status = cb_status;
3381 });
3382 handler_ids.pop_back();
3383 RunUntilIdle();
3384 EXPECT_EQ(fit::ok(), status);
3385 EXPECT_EQ(0, ccc_write_count);
3386
3387 // Enabling should succeed without an ATT transaction.
3388 status = ToResult(HostError::kFailed);
3389 EnableNotifications(service, kDefaultCharacteristic, &status, &id);
3390 EXPECT_EQ(fit::ok(), status);
3391 EXPECT_EQ(0, ccc_write_count);
3392 handler_ids.push_back(id);
3393
3394 // Disabling all should send out an ATT transaction.
3395 while (!handler_ids.empty()) {
3396 att::Result<> status = ToResult(HostError::kFailed);
3397 service->DisableNotifications(
3398 kDefaultCharacteristic,
3399 handler_ids.back(),
3400 [&](att::Result<> cb_status) { status = cb_status; });
3401 handler_ids.pop_back();
3402 RunUntilIdle();
3403 EXPECT_EQ(fit::ok(), status);
3404 }
3405
3406 EXPECT_EQ(1, ccc_write_count);
3407 }
3408
TEST_F(RemoteServiceManagerTest,ReadByTypeErrorOnLastHandleDoesNotOverflowHandle)3409 TEST_F(RemoteServiceManagerTest,
3410 ReadByTypeErrorOnLastHandleDoesNotOverflowHandle) {
3411 constexpr att::Handle kStartHandle = 0xFFFE;
3412 constexpr att::Handle kEndHandle = 0xFFFF;
3413 auto service = SetUpFakeService(ServiceData(
3414 ServiceKind::PRIMARY, kStartHandle, kEndHandle, kTestServiceUuid1));
3415 constexpr UUID kCharUuid(uint16_t{0xfefe});
3416
3417 size_t read_count = 0;
3418 fake_client()->set_read_by_type_request_callback(
3419 [&](const UUID& type, att::Handle start, att::Handle end, auto callback) {
3420 ASSERT_EQ(0u, read_count++);
3421 EXPECT_EQ(kStartHandle, start);
3422 callback(fit::error(Client::ReadByTypeError{
3423 att::Error(att::ErrorCode::kReadNotPermitted), kEndHandle}));
3424 });
3425
3426 std::optional<att::Result<>> status;
3427 std::vector<RemoteService::ReadByTypeResult> results;
3428 service->ReadByType(kCharUuid, [&](att::Result<> cb_status, auto cb_results) {
3429 status = cb_status;
3430 results = std::move(cb_results);
3431 });
3432 RunUntilIdle();
3433 ASSERT_TRUE(status.has_value());
3434 EXPECT_EQ(fit::ok(), *status);
3435 ASSERT_EQ(1u, results.size());
3436 EXPECT_EQ(CharacteristicHandle(kEndHandle), results[0].handle);
3437 EXPECT_EQ(att::ErrorCode::kReadNotPermitted, results[0].result.error_value());
3438 }
3439
TEST_F(RemoteServiceManagerTest,ReadByTypeResultOnLastHandleDoesNotOverflowHandle)3440 TEST_F(RemoteServiceManagerTest,
3441 ReadByTypeResultOnLastHandleDoesNotOverflowHandle) {
3442 constexpr att::Handle kStartHandle = 0xFFFE;
3443 constexpr att::Handle kEndHandle = 0xFFFF;
3444 auto service = SetUpFakeService(ServiceData(
3445 ServiceKind::PRIMARY, kStartHandle, kEndHandle, kTestServiceUuid1));
3446
3447 constexpr UUID kCharUuid(uint16_t{0xfefe});
3448
3449 constexpr att::Handle kHandle = kEndHandle;
3450 const auto kValue = StaticByteBuffer(0x00, 0x01, 0x02);
3451 const std::vector<Client::ReadByTypeValue> kValues = {
3452 {kHandle, kValue.view(), /*maybe_truncated=*/false}};
3453
3454 size_t read_count = 0;
3455 fake_client()->set_read_by_type_request_callback(
3456 [&](const UUID& type, att::Handle start, att::Handle end, auto callback) {
3457 ASSERT_EQ(0u, read_count++);
3458 EXPECT_EQ(kStartHandle, start);
3459 callback(fit::ok(kValues));
3460 });
3461
3462 std::optional<att::Result<>> status;
3463 service->ReadByType(kCharUuid, [&](att::Result<> cb_status, auto values) {
3464 status = cb_status;
3465 ASSERT_EQ(1u, values.size());
3466 EXPECT_EQ(CharacteristicHandle(kHandle), values[0].handle);
3467 ASSERT_EQ(fit::ok(), values[0].result);
3468 EXPECT_TRUE(ContainersEqual(kValue, *values[0].result.value()));
3469 });
3470
3471 RunUntilIdle();
3472 ASSERT_TRUE(status.has_value());
3473 EXPECT_EQ(fit::ok(), *status);
3474 }
3475
3476 class RemoteServiceManagerServiceChangedTest : public RemoteServiceManagerTest {
3477 public:
3478 RemoteServiceManagerServiceChangedTest() = default;
3479 ~RemoteServiceManagerServiceChangedTest() override = default;
3480
3481 protected:
3482 struct ServiceWatcherData {
3483 std::vector<att::Handle> removed;
3484 ServiceList added;
3485 ServiceList modified;
3486 };
3487
SetUp()3488 void SetUp() override {
3489 RemoteServiceManagerTest::SetUp();
3490 fake_client()->set_services({gatt_service()});
3491 fake_client()->set_characteristics({service_changed_characteristic()});
3492 fake_client()->set_descriptors({ccc_descriptor()});
3493
3494 mgr()->set_service_watcher(
3495 [this](auto removed, ServiceList added, ServiceList modified) {
3496 svc_watcher_data_.push_back({removed, added, modified});
3497 });
3498
3499 // Expect a Service Changed Client Characteristic Config descriptor write
3500 // that enables indications.
3501 fake_client()->set_write_request_callback(
3502 [this](att::Handle handle, const auto& value, auto status_callback) {
3503 write_request_count_++;
3504 EXPECT_EQ(ccc_descriptor_handle_, handle);
3505 EXPECT_TRUE(ContainersEqual(kCCCIndicateValue, value));
3506 status_callback(fit::ok());
3507 });
3508
3509 att::Result<> status = ToResult(HostError::kFailed);
3510 mgr()->Initialize([&status](att::Result<> val) { status = val; },
3511 NopMtuCallback);
3512 RunUntilIdle();
3513 EXPECT_EQ(fit::ok(), status);
3514 EXPECT_EQ(write_request_count_, 1);
3515 ASSERT_EQ(1u, svc_watcher_data_.size());
3516 ASSERT_EQ(1u, svc_watcher_data_[0].added.size());
3517 EXPECT_EQ(gatt_svc_start_handle_, svc_watcher_data_[0].added[0]->handle());
3518 EXPECT_EQ(types::kGenericAttributeService,
3519 svc_watcher_data_[0].added[0]->uuid());
3520 // Clear data so that tests start with index 0
3521 svc_watcher_data_.clear();
3522 }
3523
TearDown()3524 void TearDown() override { RemoteServiceManagerTest::TearDown(); }
3525
gatt_service() const3526 ServiceData gatt_service() const {
3527 return ServiceData(ServiceKind::PRIMARY,
3528 gatt_svc_start_handle_,
3529 gatt_svc_end_handle_,
3530 types::kGenericAttributeService);
3531 }
3532
service_changed_characteristic() const3533 CharacteristicData service_changed_characteristic() const {
3534 return CharacteristicData(Property::kIndicate,
3535 std::nullopt,
3536 svc_changed_char_handle_,
3537 svc_changed_char_value_handle_,
3538 types::kServiceChangedCharacteristic);
3539 }
3540
ccc_descriptor() const3541 DescriptorData ccc_descriptor() const {
3542 return DescriptorData(ccc_descriptor_handle_,
3543 types::kClientCharacteristicConfig);
3544 }
3545
svc_watcher_data()3546 const std::vector<ServiceWatcherData>& svc_watcher_data() {
3547 return svc_watcher_data_;
3548 }
3549
service_changed_ccc_write_count() const3550 int service_changed_ccc_write_count() const { return write_request_count_; }
3551
3552 private:
3553 std::vector<ServiceWatcherData> svc_watcher_data_;
3554 int write_request_count_ = 0;
3555 const att::Handle gatt_svc_start_handle_ = 1;
3556 const att::Handle svc_changed_char_handle_ = 2;
3557 const att::Handle svc_changed_char_value_handle_ = 3;
3558 const att::Handle ccc_descriptor_handle_ = 4;
3559 const att::Handle gatt_svc_end_handle_ = 4;
3560 };
3561
TEST_F(RemoteServiceManagerServiceChangedTest,ServiceChangedNotificationWrongSizeBuffer)3562 TEST_F(RemoteServiceManagerServiceChangedTest,
3563 ServiceChangedNotificationWrongSizeBuffer) {
3564 const att::Handle kSvc1StartHandle(5);
3565 const att::Handle kSvc1EndHandle(kSvc1StartHandle);
3566 ServiceData svc1(ServiceKind::PRIMARY,
3567 kSvc1StartHandle,
3568 kSvc1EndHandle,
3569 kTestServiceUuid1);
3570 fake_client()->set_services({gatt_service(), svc1});
3571
3572 // Send a too small notification.
3573 auto svc_changed_range_buffer_too_small = StaticByteBuffer(0x01);
3574 fake_client()->SendNotification(/*indicate=*/true,
3575 service_changed_characteristic().value_handle,
3576 svc_changed_range_buffer_too_small,
3577 /*maybe_truncated=*/false);
3578 RunUntilIdle();
3579 // The notification should have been safely ignored.
3580 ASSERT_EQ(0u, svc_watcher_data().size());
3581
3582 // Send a too large notification.
3583 StaticByteBuffer<sizeof(ServiceChangedCharacteristicValue) + 1>
3584 svc_changed_range_buffer_too_large =
3585 StaticByteBuffer(0x01, 0x02, 0x03, 0x04, 0x05);
3586 fake_client()->SendNotification(/*indicate=*/true,
3587 service_changed_characteristic().value_handle,
3588 svc_changed_range_buffer_too_large,
3589 /*maybe_truncated=*/false);
3590 RunUntilIdle();
3591 // The notification should have been safely ignored.
3592 ASSERT_EQ(0u, svc_watcher_data().size());
3593 }
3594
TEST_F(RemoteServiceManagerServiceChangedTest,ServiceChangedNotificationRangeStartGreaterThanRangeEnd)3595 TEST_F(RemoteServiceManagerServiceChangedTest,
3596 ServiceChangedNotificationRangeStartGreaterThanRangeEnd) {
3597 const att::Handle kSvc1StartHandle(6);
3598 const att::Handle kSvc1EndHandle(7);
3599 ServiceData svc1(ServiceKind::PRIMARY,
3600 kSvc1StartHandle,
3601 kSvc1EndHandle,
3602 kTestServiceUuid1);
3603 fake_client()->set_services({gatt_service(), svc1});
3604
3605 // Send notification with start/end handles swapped.
3606 auto svc_changed_range_buffer = StaticByteBuffer(
3607 LowerBits(kSvc1EndHandle),
3608 UpperBits(kSvc1EndHandle), // start handle of affected range
3609 LowerBits(kSvc1StartHandle),
3610 UpperBits(kSvc1StartHandle) // end handle of affected range
3611 );
3612 fake_client()->SendNotification(/*indicate=*/true,
3613 service_changed_characteristic().value_handle,
3614 svc_changed_range_buffer,
3615 /*maybe_truncated=*/false);
3616 RunUntilIdle();
3617 // The notification should have been safely ignored.
3618 ASSERT_EQ(0u, svc_watcher_data().size());
3619 }
3620
TEST_F(RemoteServiceManagerServiceChangedTest,AddModifyAndRemoveService)3621 TEST_F(RemoteServiceManagerServiceChangedTest, AddModifyAndRemoveService) {
3622 // Add a test service to ensure that service discovery occurs after the
3623 // Service Changed characteristic is configured. The test service has a
3624 // characteristic that supports indications in order to test that
3625 // notifications aren't disabled when the service is modified or removed.
3626 const att::Handle kSvc1StartHandle(5);
3627 const att::Handle kSvc1ChrcHandle(6);
3628 const att::Handle kSvc1ChrcValueHandle(7);
3629 const att::Handle kSvc1CCCHandle(8);
3630 const UUID kSvc1ChrcUuid(kTestUuid3);
3631 const att::Handle kSvc1EndHandle(kSvc1CCCHandle);
3632
3633 ServiceData svc1(ServiceKind::PRIMARY,
3634 kSvc1StartHandle,
3635 kSvc1EndHandle,
3636 kTestServiceUuid1);
3637 CharacteristicData svc1_characteristic(Property::kIndicate,
3638 std::nullopt,
3639 kSvc1ChrcHandle,
3640 kSvc1ChrcValueHandle,
3641 kSvc1ChrcUuid);
3642 DescriptorData svc1_descriptor(kSvc1CCCHandle,
3643 types::kClientCharacteristicConfig);
3644 fake_client()->set_services({gatt_service(), svc1});
3645 fake_client()->set_characteristics(
3646 {service_changed_characteristic(), svc1_characteristic});
3647 fake_client()->set_descriptors({ccc_descriptor(), svc1_descriptor});
3648
3649 // Send a notification that svc1 has been added.
3650 auto svc_changed_range_buffer = StaticByteBuffer(
3651 LowerBits(kSvc1StartHandle),
3652 UpperBits(kSvc1StartHandle), // start handle of affected range
3653 LowerBits(kSvc1EndHandle),
3654 UpperBits(kSvc1EndHandle) // end handle of affected range
3655 );
3656 fake_client()->SendNotification(/*indicate=*/true,
3657 service_changed_characteristic().value_handle,
3658 svc_changed_range_buffer,
3659 /*maybe_truncated=*/false);
3660 RunUntilIdle();
3661 ASSERT_EQ(1u, svc_watcher_data().size());
3662 ASSERT_EQ(1u, svc_watcher_data()[0].added.size());
3663 EXPECT_EQ(0u, svc_watcher_data()[0].removed.size());
3664 EXPECT_EQ(0u, svc_watcher_data()[0].modified.size());
3665 EXPECT_EQ(kSvc1StartHandle, svc_watcher_data()[0].added[0]->handle());
3666 bool original_service_removed = false;
3667 svc_watcher_data()[0].added[0]->AddRemovedHandler(
3668 [&]() { original_service_removed = true; });
3669
3670 // Discover the characteristic with the CCC descriptor before enabling
3671 // characteristic value notifications.
3672 svc_watcher_data()[0].added[0]->DiscoverCharacteristics(
3673 [&](att::Result<> status, const CharacteristicMap& characteristics) {
3674 EXPECT_EQ(fit::ok(), status);
3675 EXPECT_EQ(characteristics.size(), 1u);
3676 });
3677 RunUntilIdle();
3678
3679 // Expect writes to the service's CCC descriptor when notifications are
3680 // enabled.
3681 int svc1_ccc_write_request_count = 0;
3682 fake_client()->set_write_request_callback(
3683 [&](att::Handle handle, const auto& value, auto status_callback) {
3684 svc1_ccc_write_request_count++;
3685 EXPECT_EQ(kSvc1CCCHandle, handle);
3686 EXPECT_TRUE(ContainersEqual(kCCCIndicateValue, value));
3687 status_callback(fit::ok());
3688 });
3689
3690 std::optional<att::Result<>> original_notification_status;
3691 svc_watcher_data()[0].added[0]->EnableNotifications(
3692 bt::gatt::CharacteristicHandle(kSvc1ChrcValueHandle),
3693 NopValueCallback,
3694 [&](att::Result<> cb_status, IdType cb_id) {
3695 original_notification_status = cb_status;
3696 });
3697 RunUntilIdle();
3698 ASSERT_TRUE(original_notification_status);
3699 EXPECT_EQ(fit::ok(), *original_notification_status);
3700 EXPECT_EQ(svc1_ccc_write_request_count, 1);
3701
3702 // Send a notification that svc1 has been modified. Service Changed
3703 // notifications guarantee that all services within their range have been
3704 // modified if they are still present after a fresh service discovery, so we
3705 // can just send the same range again. (Core Spec v5.3, Vol 3, Part G,
3706 // Sec 7.1)
3707 fake_client()->SendNotification(/*indicate=*/true,
3708 service_changed_characteristic().value_handle,
3709 svc_changed_range_buffer,
3710 /*maybe_truncated=*/false);
3711 RunUntilIdle();
3712 EXPECT_TRUE(original_service_removed);
3713 // CCC should not be written to when the service is modified.
3714 EXPECT_EQ(svc1_ccc_write_request_count, 1);
3715 ASSERT_EQ(2u, svc_watcher_data().size());
3716 EXPECT_EQ(0u, svc_watcher_data()[1].added.size());
3717 EXPECT_EQ(0u, svc_watcher_data()[1].removed.size());
3718 ASSERT_EQ(1u, svc_watcher_data()[1].modified.size());
3719 EXPECT_EQ(kSvc1StartHandle, svc_watcher_data()[1].modified[0]->handle());
3720 bool modified_service_removed = false;
3721 svc_watcher_data()[1].modified[0]->AddRemovedHandler(
3722 [&]() { modified_service_removed = true; });
3723
3724 svc_watcher_data()[1].modified[0]->DiscoverCharacteristics(
3725 [&](att::Result<> status, const CharacteristicMap& characteristics) {
3726 EXPECT_EQ(fit::ok(), status);
3727 EXPECT_EQ(characteristics.size(), 1u);
3728 });
3729 RunUntilIdle();
3730
3731 std::optional<att::Result<>> modified_notification_status;
3732 svc_watcher_data()[1].modified[0]->EnableNotifications(
3733 bt::gatt::CharacteristicHandle(kSvc1ChrcValueHandle),
3734 NopValueCallback,
3735 [&](att::Result<> cb_status, IdType cb_id) {
3736 modified_notification_status = cb_status;
3737 });
3738 RunUntilIdle();
3739 ASSERT_TRUE(modified_notification_status);
3740 EXPECT_EQ(fit::ok(), *modified_notification_status);
3741 EXPECT_EQ(svc1_ccc_write_request_count, 2);
3742
3743 // Remove svc1.
3744 fake_client()->set_services({gatt_service()});
3745
3746 // Send a notification that svc1 has been removed.
3747 fake_client()->SendNotification(/*indicate=*/true,
3748 service_changed_characteristic().value_handle,
3749 svc_changed_range_buffer,
3750 /*maybe_truncated=*/false);
3751 RunUntilIdle();
3752 EXPECT_TRUE(modified_service_removed);
3753 // CCC should not be written to when the service is removed.
3754 EXPECT_EQ(svc1_ccc_write_request_count, 2);
3755 ASSERT_EQ(3u, svc_watcher_data().size());
3756 EXPECT_EQ(0u, svc_watcher_data()[2].added.size());
3757 ASSERT_EQ(1u, svc_watcher_data()[2].removed.size());
3758 EXPECT_EQ(0u, svc_watcher_data()[2].modified.size());
3759 EXPECT_EQ(kSvc1StartHandle, svc_watcher_data()[2].removed[0]);
3760 EXPECT_EQ(svc1_ccc_write_request_count, 2);
3761 }
3762
3763 // A Service Changed notification received during initialization (service
3764 // discovery) should be queued and processed after service discovery completes
3765 // (as the last step of initialization). The service watcher should only be
3766 // called once.
TEST_F(RemoteServiceManagerTest,ServiceChangedDuringInitialization)3767 TEST_F(RemoteServiceManagerTest, ServiceChangedDuringInitialization) {
3768 const att::Handle kGattSvcStartHandle(1);
3769 const att::Handle kSvcChangedChrcHandle(2);
3770 const att::Handle kSvcChangedChrcValueHandle(3);
3771 const att::Handle kCCCDescriptorHandle(4);
3772 const att::Handle kGattSvcEndHandle(kCCCDescriptorHandle);
3773 const att::Handle kSvc1StartHandle(5);
3774 const att::Handle kSvc1EndHandle(kSvc1StartHandle);
3775
3776 ServiceData gatt_svc(ServiceKind::PRIMARY,
3777 kGattSvcStartHandle,
3778 kGattSvcEndHandle,
3779 types::kGenericAttributeService);
3780 CharacteristicData service_changed_chrc(Property::kIndicate,
3781 std::nullopt,
3782 kSvcChangedChrcHandle,
3783 kSvcChangedChrcValueHandle,
3784 types::kServiceChangedCharacteristic);
3785 DescriptorData ccc_descriptor(kCCCDescriptorHandle,
3786 types::kClientCharacteristicConfig);
3787 ServiceData svc1(ServiceKind::PRIMARY,
3788 kSvc1StartHandle,
3789 kSvc1EndHandle,
3790 kTestServiceUuid1);
3791 fake_client()->set_services({gatt_svc, svc1});
3792 fake_client()->set_characteristics({service_changed_chrc});
3793 fake_client()->set_descriptors({ccc_descriptor});
3794
3795 int svc_watcher_count = 0;
3796 mgr()->set_service_watcher([&](std::vector<att::Handle> removed,
3797 ServiceList added,
3798 ServiceList modified) {
3799 EXPECT_EQ(0u, removed.size());
3800 EXPECT_EQ(2u, added.size());
3801 EXPECT_EQ(0u, modified.size());
3802 svc_watcher_count++;
3803 });
3804
3805 // Send a notification during primary service discovery (i.e. the second
3806 // discovery, as the first is for discovering the GATT Service).
3807 int discover_services_count = 0;
3808 fake_client()->set_discover_services_callback([&](ServiceKind /*kind*/) {
3809 if (discover_services_count == 1) {
3810 auto svc_changed_range_buffer = StaticByteBuffer(
3811 LowerBits(kSvc1StartHandle),
3812 UpperBits(kSvc1StartHandle), // start handle of affected range
3813 LowerBits(kSvc1EndHandle),
3814 UpperBits(kSvc1EndHandle) // end handle of affected range
3815 );
3816 fake_client()->SendNotification(/*indicate=*/true,
3817 kSvcChangedChrcValueHandle,
3818 svc_changed_range_buffer,
3819 /*maybe_truncated=*/false);
3820 }
3821 discover_services_count++;
3822 return fit::ok();
3823 });
3824
3825 // Expect a Service Changed Client Characteristic Config descriptor write that
3826 // enables indications.
3827 int write_request_count = 0;
3828 fake_client()->set_write_request_callback(
3829 [&](att::Handle handle, const auto& value, auto status_callback) {
3830 write_request_count++;
3831 EXPECT_EQ(kCCCDescriptorHandle, handle);
3832 EXPECT_TRUE(ContainersEqual(kCCCIndicateValue, value));
3833 status_callback(fit::ok());
3834 });
3835
3836 att::Result<> status = ToResult(HostError::kFailed);
3837 mgr()->Initialize(
3838 [&](att::Result<> val) {
3839 status = val;
3840 EXPECT_EQ(1, svc_watcher_count);
3841 },
3842 NopMtuCallback);
3843 RunUntilIdle();
3844 EXPECT_EQ(fit::ok(), status);
3845 EXPECT_EQ(1, write_request_count);
3846 EXPECT_EQ(1, svc_watcher_count);
3847 }
3848
TEST_F(RemoteServiceManagerServiceChangedTest,SecondServiceChangedNotificationIsQueued)3849 TEST_F(RemoteServiceManagerServiceChangedTest,
3850 SecondServiceChangedNotificationIsQueued) {
3851 const att::Handle kSvc1StartHandle(5);
3852 const att::Handle kSvc1EndHandle(kSvc1StartHandle);
3853
3854 // Add a test service to ensure that service discovery occurs after the
3855 // Service Changed characteristic is configured.
3856 ServiceData svc1(ServiceKind::PRIMARY,
3857 kSvc1StartHandle,
3858 kSvc1EndHandle,
3859 kTestServiceUuid1);
3860 fake_client()->set_services({gatt_service(), svc1});
3861
3862 // Send a notification that svc1 has been added.
3863 auto svc_changed_range_buffer = StaticByteBuffer(
3864 LowerBits(kSvc1StartHandle),
3865 UpperBits(kSvc1StartHandle), // start handle of affected range
3866 LowerBits(kSvc1EndHandle),
3867 UpperBits(kSvc1EndHandle) // end handle of affected range
3868 );
3869 fake_client()->SendNotification(/*indicate=*/true,
3870 service_changed_characteristic().value_handle,
3871 svc_changed_range_buffer,
3872 /*maybe_truncated=*/false);
3873 // Send a notification that svc1 has been modified.
3874 fake_client()->SendNotification(/*indicate=*/true,
3875 service_changed_characteristic().value_handle,
3876 svc_changed_range_buffer,
3877 /*maybe_truncated=*/false);
3878
3879 RunUntilIdle();
3880 ASSERT_EQ(2u, svc_watcher_data().size());
3881
3882 ASSERT_EQ(1u, svc_watcher_data()[0].added.size());
3883 EXPECT_EQ(0u, svc_watcher_data()[0].removed.size());
3884 EXPECT_EQ(0u, svc_watcher_data()[0].modified.size());
3885 EXPECT_FALSE(svc_watcher_data()[0]
3886 .added[0]
3887 .is_alive()); // WeakPtr should already be invalidated
3888
3889 EXPECT_EQ(0u, svc_watcher_data()[1].added.size());
3890 EXPECT_EQ(0u, svc_watcher_data()[1].removed.size());
3891 ASSERT_EQ(1u, svc_watcher_data()[1].modified.size());
3892 EXPECT_EQ(kSvc1StartHandle, svc_watcher_data()[1].modified[0]->handle());
3893 }
3894
TEST_F(RemoteServiceManagerServiceChangedTest,ServiceUuidChanged)3895 TEST_F(RemoteServiceManagerServiceChangedTest, ServiceUuidChanged) {
3896 const att::Handle kSvcStartHandle(5);
3897 const att::Handle kSvcEndHandle(kSvcStartHandle);
3898
3899 ServiceData svc1(
3900 ServiceKind::PRIMARY, kSvcStartHandle, kSvcEndHandle, kTestServiceUuid1);
3901 fake_client()->set_services({gatt_service(), svc1});
3902
3903 // Send a notification that svc1 has been added.
3904 auto svc_changed_range_buffer = StaticByteBuffer(
3905 LowerBits(kSvcStartHandle),
3906 UpperBits(kSvcStartHandle), // start handle of affected range
3907 LowerBits(kSvcEndHandle),
3908 UpperBits(kSvcEndHandle) // end handle of affected range
3909 );
3910 fake_client()->SendNotification(/*indicate=*/true,
3911 service_changed_characteristic().value_handle,
3912 svc_changed_range_buffer,
3913 /*maybe_truncated=*/false);
3914
3915 RunUntilIdle();
3916 ASSERT_EQ(1u, svc_watcher_data().size());
3917
3918 ASSERT_EQ(1u, svc_watcher_data()[0].added.size());
3919 EXPECT_EQ(0u, svc_watcher_data()[0].removed.size());
3920 EXPECT_EQ(0u, svc_watcher_data()[0].modified.size());
3921 EXPECT_EQ(kSvcStartHandle, svc_watcher_data()[0].added[0]->handle());
3922 EXPECT_EQ(kTestServiceUuid1, svc_watcher_data()[0].added[0]->uuid());
3923
3924 ServiceData svc2(
3925 ServiceKind::PRIMARY, kSvcStartHandle, kSvcEndHandle, kTestServiceUuid2);
3926 fake_client()->set_services({gatt_service(), svc2});
3927
3928 // Send a notification that svc2 has replaced svc1.
3929 fake_client()->SendNotification(/*indicate=*/true,
3930 service_changed_characteristic().value_handle,
3931 svc_changed_range_buffer,
3932 /*maybe_truncated=*/false);
3933 RunUntilIdle();
3934 ASSERT_EQ(2u, svc_watcher_data().size());
3935
3936 ASSERT_EQ(1u, svc_watcher_data()[1].added.size());
3937 ASSERT_EQ(1u, svc_watcher_data()[1].removed.size());
3938 EXPECT_EQ(0u, svc_watcher_data()[1].modified.size());
3939 EXPECT_EQ(kSvcStartHandle, svc_watcher_data()[1].removed[0]);
3940 EXPECT_EQ(kSvcStartHandle, svc_watcher_data()[1].added[0]->handle());
3941 EXPECT_EQ(kTestServiceUuid2, svc_watcher_data()[1].added[0]->uuid());
3942 }
3943
TEST_F(RemoteServiceManagerServiceChangedTest,AddServiceThenRemoveServiceAndAddTwoMoreServicesBeforeAndAfterRemovedServiceWithSameNotification)3944 TEST_F(
3945 RemoteServiceManagerServiceChangedTest,
3946 AddServiceThenRemoveServiceAndAddTwoMoreServicesBeforeAndAfterRemovedServiceWithSameNotification) {
3947 const att::Handle kSvc1StartHandle(7);
3948 const att::Handle kSvc1EndHandle(kSvc1StartHandle);
3949 const att::Handle kSvc2StartHandle(6);
3950 const att::Handle kSvc2EndHandle(kSvc2StartHandle);
3951 const att::Handle kSvc3StartHandle(8);
3952 const att::Handle kSvc3EndHandle(kSvc3StartHandle);
3953
3954 ServiceData svc1(ServiceKind::PRIMARY,
3955 kSvc1StartHandle,
3956 kSvc1EndHandle,
3957 kTestServiceUuid1);
3958 fake_client()->set_services({gatt_service(), svc1});
3959
3960 // Send a notification that svc1 has been added.
3961 auto svc_changed_range_buffer_0 = StaticByteBuffer(
3962 LowerBits(kSvc1StartHandle),
3963 UpperBits(kSvc1StartHandle), // start handle of affected range
3964 LowerBits(kSvc1EndHandle),
3965 UpperBits(kSvc1EndHandle) // end handle of affected range
3966 );
3967 fake_client()->SendNotification(/*indicate=*/true,
3968 service_changed_characteristic().value_handle,
3969 svc_changed_range_buffer_0,
3970 /*maybe_truncated=*/false);
3971
3972 RunUntilIdle();
3973 ASSERT_EQ(1u, svc_watcher_data().size());
3974 ASSERT_EQ(1u, svc_watcher_data()[0].added.size());
3975 EXPECT_EQ(0u, svc_watcher_data()[0].removed.size());
3976 EXPECT_EQ(0u, svc_watcher_data()[0].modified.size());
3977 EXPECT_EQ(kSvc1StartHandle, svc_watcher_data()[0].added[0]->handle());
3978
3979 ServiceData svc2(ServiceKind::PRIMARY,
3980 kSvc2StartHandle,
3981 kSvc2EndHandle,
3982 kTestServiceUuid2);
3983 ServiceData svc3(ServiceKind::PRIMARY,
3984 kSvc3StartHandle,
3985 kSvc3EndHandle,
3986 kTestServiceUuid3);
3987 fake_client()->set_services({gatt_service(), svc2, svc3});
3988
3989 // Range includes all 3 services.
3990 auto svc_changed_range_buffer_1 = StaticByteBuffer(
3991 LowerBits(kSvc2StartHandle),
3992 UpperBits(kSvc2StartHandle), // start handle of affected range
3993 LowerBits(kSvc3EndHandle),
3994 UpperBits(kSvc3EndHandle) // end handle of affected range
3995 );
3996 fake_client()->SendNotification(/*indicate=*/true,
3997 service_changed_characteristic().value_handle,
3998 svc_changed_range_buffer_1,
3999 /*maybe_truncated=*/false);
4000
4001 RunUntilIdle();
4002 ASSERT_EQ(2u, svc_watcher_data().size());
4003 ASSERT_EQ(2u, svc_watcher_data()[1].added.size());
4004 ASSERT_EQ(1u, svc_watcher_data()[1].removed.size());
4005 EXPECT_EQ(0u, svc_watcher_data()[1].modified.size());
4006 EXPECT_EQ(kSvc1StartHandle, svc_watcher_data()[1].removed[0]);
4007 EXPECT_EQ(kSvc2StartHandle, svc_watcher_data()[1].added[0]->handle());
4008 EXPECT_EQ(kSvc3StartHandle, svc_watcher_data()[1].added[1]->handle());
4009 }
4010
4011 class RemoteServiceManagerServiceChangedTestWithServiceKindParam
4012 : public RemoteServiceManagerServiceChangedTest,
4013 public ::testing::WithParamInterface<ServiceKind> {};
4014
TEST_P(RemoteServiceManagerServiceChangedTestWithServiceKindParam,ServiceChangedServiceDiscoveryFailureThenSuccess)4015 TEST_P(RemoteServiceManagerServiceChangedTestWithServiceKindParam,
4016 ServiceChangedServiceDiscoveryFailureThenSuccess) {
4017 const ServiceKind kKind = GetParam();
4018
4019 const att::Handle kSvc1StartHandle(5);
4020 const att::Handle kSvc1EndHandle(kSvc1StartHandle);
4021 ServiceData svc1(kKind, kSvc1StartHandle, kSvc1EndHandle, kTestServiceUuid1);
4022 const att::Handle kSvc2StartHandle(7);
4023 const att::Handle kSvc2EndHandle(kSvc2StartHandle);
4024 ServiceData svc2(kKind, kSvc2StartHandle, kSvc2EndHandle, kTestServiceUuid2);
4025 fake_client()->set_services({gatt_service(), svc1, svc2});
4026
4027 // Cause only the first service discovery to fail.
4028 int discover_services_count = 0;
4029 fake_client()->set_discover_services_callback(
4030 [&](ServiceKind kind) -> att::Result<> {
4031 if (kind == kKind) {
4032 discover_services_count++;
4033 if (discover_services_count == 1) {
4034 return ToResult(HostError::kFailed);
4035 }
4036 }
4037 return fit::ok();
4038 });
4039
4040 auto svc1_changed_range_buffer = StaticByteBuffer(
4041 LowerBits(kSvc1StartHandle),
4042 UpperBits(kSvc1StartHandle), // start handle of affected range
4043 LowerBits(kSvc1EndHandle),
4044 UpperBits(kSvc1EndHandle) // end handle of affected range
4045 );
4046 fake_client()->SendNotification(/*indicate=*/true,
4047 service_changed_characteristic().value_handle,
4048 svc1_changed_range_buffer,
4049 /*maybe_truncated=*/false);
4050
4051 // This second notification should be queued and processed after the first
4052 // service discovery fails.
4053 auto svc2_changed_range_buffer = StaticByteBuffer(
4054 LowerBits(kSvc2StartHandle),
4055 UpperBits(kSvc2StartHandle), // start handle of affected range
4056 LowerBits(kSvc2EndHandle),
4057 UpperBits(kSvc2EndHandle) // end handle of affected range
4058 );
4059 fake_client()->SendNotification(/*indicate=*/true,
4060 service_changed_characteristic().value_handle,
4061 svc2_changed_range_buffer,
4062 /*maybe_truncated=*/false);
4063
4064 RunUntilIdle();
4065 ASSERT_EQ(1u, svc_watcher_data().size());
4066 ASSERT_EQ(1u, svc_watcher_data()[0].added.size());
4067 EXPECT_EQ(0u, svc_watcher_data()[0].removed.size());
4068 EXPECT_EQ(0u, svc_watcher_data()[0].modified.size());
4069 EXPECT_EQ(kSvc2StartHandle, svc_watcher_data()[0].added[0]->handle());
4070 }
4071
4072 INSTANTIATE_TEST_SUITE_P(
4073 ServiceKind,
4074 RemoteServiceManagerServiceChangedTestWithServiceKindParam,
4075 ::testing::Values(ServiceKind::PRIMARY, ServiceKind::SECONDARY));
4076
TEST_F(RemoteServiceManagerServiceChangedTest,SecondaryServiceDiscoveryIgnoresUnsupportedGroupTypeError)4077 TEST_F(RemoteServiceManagerServiceChangedTest,
4078 SecondaryServiceDiscoveryIgnoresUnsupportedGroupTypeError) {
4079 const att::Handle kSvc1StartHandle(5);
4080 const att::Handle kSvc1EndHandle(kSvc1StartHandle);
4081
4082 ServiceData svc1(ServiceKind::PRIMARY,
4083 kSvc1StartHandle,
4084 kSvc1EndHandle,
4085 kTestServiceUuid1);
4086 fake_client()->set_services({gatt_service(), svc1});
4087
4088 fake_client()->set_discover_services_callback([](ServiceKind kind) {
4089 if (kind == ServiceKind::SECONDARY) {
4090 return ToResult(att::ErrorCode::kUnsupportedGroupType);
4091 }
4092 return att::Result<>(fit::ok());
4093 });
4094
4095 // Send a notification that svc1 has been added.
4096 auto svc_changed_range_buffer = StaticByteBuffer(
4097 LowerBits(kSvc1StartHandle),
4098 UpperBits(kSvc1StartHandle), // start handle of affected range
4099 LowerBits(kSvc1EndHandle),
4100 UpperBits(kSvc1EndHandle) // end handle of affected range
4101 );
4102 fake_client()->SendNotification(/*indicate=*/true,
4103 service_changed_characteristic().value_handle,
4104 svc_changed_range_buffer,
4105 /*maybe_truncated=*/false);
4106 RunUntilIdle();
4107 ASSERT_EQ(1u, svc_watcher_data().size());
4108 ASSERT_EQ(1u, svc_watcher_data()[0].added.size());
4109 EXPECT_EQ(0u, svc_watcher_data()[0].removed.size());
4110 EXPECT_EQ(0u, svc_watcher_data()[0].modified.size());
4111 EXPECT_EQ(kSvc1StartHandle, svc_watcher_data()[0].added[0]->handle());
4112 }
4113
TEST_F(RemoteServiceManagerServiceChangedTest,GattProfileServiceChanged)4114 TEST_F(RemoteServiceManagerServiceChangedTest, GattProfileServiceChanged) {
4115 EXPECT_EQ(1, service_changed_ccc_write_count());
4116
4117 StaticByteBuffer svc_changed_range_buffer(
4118 LowerBits(gatt_service().range_start),
4119 UpperBits(gatt_service().range_start), // start handle of affected range
4120 LowerBits(gatt_service().range_end),
4121 UpperBits(gatt_service().range_end) // end handle of affected range
4122 );
4123 fake_client()->SendNotification(/*indicate=*/true,
4124 service_changed_characteristic().value_handle,
4125 svc_changed_range_buffer,
4126 /*maybe_truncated=*/false);
4127 RunUntilIdle();
4128 ASSERT_EQ(1u, svc_watcher_data().size());
4129 EXPECT_EQ(0u, svc_watcher_data()[0].added.size());
4130 EXPECT_EQ(0u, svc_watcher_data()[0].removed.size());
4131 ASSERT_EQ(1u, svc_watcher_data()[0].modified.size());
4132 EXPECT_EQ(gatt_service().range_start,
4133 svc_watcher_data()[0].modified[0]->handle());
4134 EXPECT_EQ(1, service_changed_ccc_write_count());
4135
4136 // The handler for notifications should remain configured.
4137 fake_client()->SendNotification(/*indicate=*/true,
4138 service_changed_characteristic().value_handle,
4139 svc_changed_range_buffer,
4140 /*maybe_truncated=*/false);
4141 RunUntilIdle();
4142 ASSERT_EQ(2u, svc_watcher_data().size());
4143 EXPECT_EQ(0u, svc_watcher_data()[1].added.size());
4144 EXPECT_EQ(0u, svc_watcher_data()[1].removed.size());
4145 ASSERT_EQ(1u, svc_watcher_data()[1].modified.size());
4146 EXPECT_EQ(gatt_service().range_start,
4147 svc_watcher_data()[1].modified[0]->handle());
4148 EXPECT_EQ(1, service_changed_ccc_write_count());
4149 // A new service should not have been created for the modified GATT Profile
4150 // service.
4151 EXPECT_EQ(&svc_watcher_data()[0].modified[0].get(),
4152 &svc_watcher_data()[1].modified[0].get());
4153 }
4154
TEST_F(RemoteServiceManagerTest,ErrorDiscoveringGattProfileService)4155 TEST_F(RemoteServiceManagerTest, ErrorDiscoveringGattProfileService) {
4156 ServiceData gatt_svc(
4157 ServiceKind::PRIMARY, 1, 1, types::kGenericAttributeService);
4158 ServiceData svc1(ServiceKind::PRIMARY, 2, 2, kTestServiceUuid1);
4159 std::vector<ServiceData> fake_services{{gatt_svc, svc1}};
4160 fake_client()->set_services(std::move(fake_services));
4161
4162 fake_client()->set_discover_services_callback([](ServiceKind kind) {
4163 if (kind == ServiceKind::PRIMARY) {
4164 return ToResult(att::ErrorCode::kRequestNotSupported);
4165 }
4166 return att::Result<>(fit::ok());
4167 });
4168
4169 std::optional<att::Result<>> status;
4170 mgr()->Initialize([&status](att::Result<> val) { status = val; },
4171 NopMtuCallback);
4172 RunUntilIdle();
4173 EXPECT_EQ(ToResult(att::ErrorCode::kRequestNotSupported), *status);
4174 }
4175
TEST_F(RemoteServiceManagerTest,MultipleGattProfileServicesFailsInitialization)4176 TEST_F(RemoteServiceManagerTest,
4177 MultipleGattProfileServicesFailsInitialization) {
4178 ServiceData gatt_svc0(
4179 ServiceKind::PRIMARY, 1, 1, types::kGenericAttributeService);
4180 ServiceData gatt_svc1(
4181 ServiceKind::PRIMARY, 2, 2, types::kGenericAttributeService);
4182 std::vector<ServiceData> fake_services{{gatt_svc0, gatt_svc1}};
4183 fake_client()->set_services(std::move(fake_services));
4184
4185 std::optional<att::Result<>> status;
4186 mgr()->Initialize([&status](att::Result<> val) { status = val; },
4187 NopMtuCallback);
4188 RunUntilIdle();
4189 EXPECT_EQ(ToResult(HostError::kFailed), *status);
4190 }
4191
TEST_F(RemoteServiceManagerTest,InitializeEmptyGattProfileService)4192 TEST_F(RemoteServiceManagerTest, InitializeEmptyGattProfileService) {
4193 ServiceData gatt_svc(
4194 ServiceKind::PRIMARY, 1, 1, types::kGenericAttributeService);
4195 ServiceData svc1(ServiceKind::PRIMARY, 2, 2, kTestServiceUuid1);
4196 std::vector<ServiceData> fake_services{{gatt_svc, svc1}};
4197 fake_client()->set_services(std::move(fake_services));
4198
4199 ServiceList services;
4200 mgr()->set_service_watcher(
4201 [&services](auto /*removed*/, ServiceList added, auto /*modified*/) {
4202 services.insert(services.end(), added.begin(), added.end());
4203 });
4204
4205 att::Result<> status = ToResult(HostError::kFailed);
4206 mgr()->Initialize([&status](att::Result<> val) { status = val; },
4207 NopMtuCallback);
4208 RunUntilIdle();
4209 EXPECT_EQ(fit::ok(), status);
4210 ASSERT_EQ(2u, services.size());
4211 EXPECT_EQ(gatt_svc.range_start, services[0]->handle());
4212 EXPECT_EQ(gatt_svc.type, services[0]->uuid());
4213 EXPECT_EQ(svc1.range_start, services[1]->handle());
4214 EXPECT_EQ(svc1.type, services[1]->uuid());
4215 }
4216
TEST_F(RemoteServiceManagerTest,EnableServiceChangedNotificationsReturnsError)4217 TEST_F(RemoteServiceManagerTest,
4218 EnableServiceChangedNotificationsReturnsError) {
4219 const att::Handle kGattSvcStartHandle(1);
4220 const att::Handle kSvcChangedChrcHandle(2);
4221 const att::Handle kSvcChangedChrcValueHandle(3);
4222 const att::Handle kCCCDescriptorHandle(4);
4223 const att::Handle kGattSvcEndHandle(kCCCDescriptorHandle);
4224
4225 ServiceData gatt_svc(ServiceKind::PRIMARY,
4226 kGattSvcStartHandle,
4227 kGattSvcEndHandle,
4228 types::kGenericAttributeService);
4229 CharacteristicData service_changed_chrc(Property::kIndicate,
4230 std::nullopt,
4231 kSvcChangedChrcHandle,
4232 kSvcChangedChrcValueHandle,
4233 types::kServiceChangedCharacteristic);
4234 DescriptorData ccc_descriptor(kCCCDescriptorHandle,
4235 types::kClientCharacteristicConfig);
4236 fake_client()->set_services({gatt_svc});
4237 fake_client()->set_characteristics({service_changed_chrc});
4238 fake_client()->set_descriptors({ccc_descriptor});
4239
4240 ServiceList services;
4241 mgr()->set_service_watcher(
4242 [&services](auto /*removed*/, ServiceList added, auto /*modified*/) {
4243 services.insert(services.end(), added.begin(), added.end());
4244 });
4245
4246 // Return an error when a Service Changed Client Characteristic Config
4247 // descriptor write is performed.
4248 int write_request_count = 0;
4249 fake_client()->set_write_request_callback(
4250 [&](att::Handle handle, const auto& value, auto status_callback) {
4251 write_request_count++;
4252 EXPECT_EQ(kCCCDescriptorHandle, handle);
4253 status_callback(ToResult(att::ErrorCode::kWriteNotPermitted));
4254 });
4255
4256 std::optional<att::Result<>> status;
4257 mgr()->Initialize([&status](att::Result<> val) { status = val; },
4258 NopMtuCallback);
4259 RunUntilIdle();
4260 EXPECT_EQ(ToResult(att::ErrorCode::kWriteNotPermitted), *status);
4261 EXPECT_EQ(write_request_count, 1);
4262 }
4263
TEST_F(RemoteServiceManagerTest,ErrorDiscoveringGattProfileServiceCharacteristics)4264 TEST_F(RemoteServiceManagerTest,
4265 ErrorDiscoveringGattProfileServiceCharacteristics) {
4266 ServiceData gatt_svc(
4267 ServiceKind::PRIMARY, 1, 3, types::kGenericAttributeService);
4268 ServiceData svc1(ServiceKind::PRIMARY, 4, 4, kTestServiceUuid1);
4269 std::vector<ServiceData> fake_services{{gatt_svc, svc1}};
4270 fake_client()->set_services(std::move(fake_services));
4271
4272 fake_client()->set_characteristic_discovery_status(
4273 ToResult(att::ErrorCode::kRequestNotSupported));
4274
4275 std::optional<att::Result<>> status;
4276 mgr()->Initialize([&status](att::Result<> val) { status = val; },
4277 NopMtuCallback);
4278 RunUntilIdle();
4279 EXPECT_EQ(ToResult(att::ErrorCode::kRequestNotSupported), *status);
4280 }
4281
TEST_F(RemoteServiceManagerTest,DisableNotificationInHandlerCallback)4282 TEST_F(RemoteServiceManagerTest, DisableNotificationInHandlerCallback) {
4283 const CharacteristicHandle kChrcValueHandle(3);
4284 RemoteService::WeakPtr svc = SetupNotifiableService();
4285 std::optional<IdType> handler_id;
4286 RemoteCharacteristic::NotifyStatusCallback status_cb =
4287 [&](att::Result<> status, IdType cb_handler_id) {
4288 EXPECT_EQ(fit::ok(), status);
4289 handler_id = cb_handler_id;
4290 };
4291
4292 int value_cb_count = 0;
4293 RemoteCharacteristic::ValueCallback value_cb = [&](auto&, auto) {
4294 value_cb_count++;
4295 ASSERT_TRUE(handler_id);
4296 // Disabling notifications in handler should not crash.
4297 svc->DisableNotifications(
4298 kChrcValueHandle, handler_id.value(), [](auto) {});
4299 };
4300 svc->EnableNotifications(
4301 kChrcValueHandle, std::move(value_cb), std::move(status_cb));
4302
4303 fake_client()->SendNotification(/*indicate=*/false,
4304 kChrcValueHandle.value,
4305 StaticByteBuffer('y', 'e'),
4306 /*maybe_truncated=*/false);
4307 RunUntilIdle();
4308 EXPECT_EQ(value_cb_count, 1);
4309
4310 // Second notification should not notify disabled handler.
4311 fake_client()->SendNotification(/*indicate=*/false,
4312 kChrcValueHandle.value,
4313 StaticByteBuffer('y', 'e'),
4314 /*maybe_truncated=*/false);
4315 RunUntilIdle();
4316 EXPECT_EQ(value_cb_count, 1);
4317 }
4318
TEST_F(RemoteServiceManagerServiceChangedTest,ServiceRemovedDuringReadLongCharacteristic)4319 TEST_F(RemoteServiceManagerServiceChangedTest,
4320 ServiceRemovedDuringReadLongCharacteristic) {
4321 const att::Handle kSvc1StartHandle(5);
4322 const att::Handle kSvc1ChrcHandle(6);
4323 const att::Handle kSvc1ChrcValueHandle(7);
4324 const att::Handle kSvc1EndHandle(kSvc1ChrcValueHandle);
4325 ServiceData svc1(ServiceKind::PRIMARY,
4326 kSvc1StartHandle,
4327 kSvc1EndHandle,
4328 kTestServiceUuid1);
4329 const UUID kSvc1ChrcUuid(kTestUuid3);
4330 CharacteristicData svc1_characteristic(Property::kRead,
4331 std::nullopt,
4332 kSvc1ChrcHandle,
4333 kSvc1ChrcValueHandle,
4334 kSvc1ChrcUuid);
4335 fake_client()->set_services({gatt_service(), svc1});
4336 fake_client()->set_characteristics(
4337 {service_changed_characteristic(), svc1_characteristic});
4338 fake_client()->set_descriptors({ccc_descriptor()});
4339
4340 // Send a notification that svc1 has been added.
4341 auto svc_changed_range_buffer = StaticByteBuffer(
4342 LowerBits(kSvc1StartHandle),
4343 UpperBits(kSvc1StartHandle), // start handle of affected range
4344 LowerBits(kSvc1EndHandle),
4345 UpperBits(kSvc1EndHandle) // end handle of affected range
4346 );
4347 fake_client()->SendNotification(/*indicate=*/true,
4348 service_changed_characteristic().value_handle,
4349 svc_changed_range_buffer,
4350 /*maybe_truncated=*/false);
4351 RunUntilIdle();
4352 ASSERT_EQ(1u, svc_watcher_data().size());
4353 ASSERT_EQ(1u, svc_watcher_data()[0].added.size());
4354 EXPECT_EQ(kSvc1StartHandle, svc_watcher_data()[0].added[0]->handle());
4355
4356 RemoteService::WeakPtr service = svc_watcher_data()[0].added[0];
4357 service->DiscoverCharacteristics([](auto, const auto&) {});
4358 RunUntilIdle();
4359
4360 int read_req_count = 0;
4361 RemoteService::ReadValueCallback read_callback = nullptr;
4362 fake_client()->set_read_request_callback(
4363 [&](auto, RemoteService::ReadValueCallback callback) {
4364 EXPECT_EQ(read_req_count, 0);
4365 read_req_count++;
4366 read_callback = std::move(callback);
4367 });
4368 fake_client()->set_read_blob_request_callback(
4369 [](auto, auto, auto) { FAIL(); });
4370
4371 int read_long_cb_count = 0;
4372 service->ReadLongCharacteristic(
4373 CharacteristicHandle(kSvc1ChrcValueHandle),
4374 /*offset=*/0,
4375 att::kMaxAttributeValueLength,
4376 [&](auto, auto&, auto) { read_long_cb_count++; });
4377
4378 // Remove svc1.
4379 fake_client()->set_services({gatt_service()});
4380 fake_client()->SendNotification(/*indicate=*/true,
4381 service_changed_characteristic().value_handle,
4382 svc_changed_range_buffer,
4383 /*maybe_truncated=*/false);
4384 RunUntilIdle();
4385 EXPECT_FALSE(service.is_alive());
4386 ASSERT_EQ(2u, svc_watcher_data().size());
4387 ASSERT_EQ(1u, svc_watcher_data()[1].removed.size());
4388 EXPECT_EQ(read_req_count, 1);
4389 ASSERT_TRUE(read_callback);
4390
4391 // Now that the service has been destroyed, the read long procedure should be
4392 // aborted when the first read request callback is called.
4393 StaticByteBuffer<att::kLEMinMTU - 1> expected_value;
4394 expected_value.Fill(0x02);
4395 read_callback(fit::ok(), expected_value.view(), /*maybe_truncated=*/true);
4396 RunUntilIdle();
4397 EXPECT_EQ(read_long_cb_count, 0);
4398 }
4399
4400 } // namespace
4401 } // namespace bt::gatt::internal
4402