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/local_service_manager.h"
16
17 #include "pw_bluetooth_sapphire/internal/host/att/att.h"
18 #include "pw_bluetooth_sapphire/internal/host/common/assert.h"
19 #include "pw_bluetooth_sapphire/internal/host/gatt/gatt_defs.h"
20 #include "pw_bluetooth_sapphire/internal/host/testing/test_helpers.h"
21 #include "pw_unit_test/framework.h"
22
23 namespace bt::gatt {
24 namespace {
25
26 constexpr PeerId kTestPeerId(1);
27 constexpr PeerId kTestPeerId2(2);
28 constexpr UUID kTestType16(uint16_t{0xdead});
29 constexpr UUID kTestType32(uint32_t{0xdeadbeef});
30
31 // The first characteristic value attribute of the first service has handle
32 // number 3.
33 constexpr att::Handle kFirstChrcValueHandle = 0x0003;
34
35 // The first descroptor of the first characteristic of the first service has
36 // handle number 4.
37 constexpr att::Handle kFirstDescrHandle = 0x0004;
38
AllowedNoSecurity()39 inline att::AccessRequirements AllowedNoSecurity() {
40 return att::AccessRequirements(/*encryption=*/false,
41 /*authentication=*/false,
42 /*authorization=*/false);
43 }
44
45 // Convenience function that registers |service| with |mgr| using the NOP
46 // handlers above by default.
RegisterService(LocalServiceManager * mgr,ServicePtr service,ReadHandler read_handler=NopReadHandler,WriteHandler write_handler=NopWriteHandler,ClientConfigCallback ccc_callback=NopCCCallback)47 IdType RegisterService(LocalServiceManager* mgr,
48 ServicePtr service,
49 ReadHandler read_handler = NopReadHandler,
50 WriteHandler write_handler = NopWriteHandler,
51 ClientConfigCallback ccc_callback = NopCCCallback) {
52 return mgr->RegisterService(std::move(service),
53 std::move(read_handler),
54 std::move(write_handler),
55 std::move(ccc_callback));
56 }
57
TEST(LocalServiceManagerTest,EmptyService)58 TEST(LocalServiceManagerTest, EmptyService) {
59 LocalServiceManager mgr;
60
61 auto service = std::make_unique<Service>(/*primary=*/true, kTestType16);
62 auto id1 = RegisterService(&mgr, std::move(service));
63 EXPECT_NE(0u, id1);
64
65 service = std::make_unique<Service>(/*primary=*/false, kTestType32);
66 auto id2 = RegisterService(&mgr, std::move(service));
67 EXPECT_NE(0u, id2);
68
69 EXPECT_EQ(2u, mgr.database()->groupings().size());
70
71 auto iter = mgr.database()->groupings().begin();
72
73 EXPECT_TRUE(iter->complete());
74 EXPECT_EQ(1u, iter->attributes().size());
75 EXPECT_TRUE(iter->active());
76 EXPECT_EQ(0x0001, iter->start_handle());
77 EXPECT_EQ(0x0001, iter->end_handle());
78 EXPECT_EQ(types::kPrimaryService, iter->group_type());
79 EXPECT_TRUE(
80 ContainersEqual(StaticByteBuffer(0xad, 0xde), iter->decl_value()));
81
82 iter++;
83
84 EXPECT_TRUE(iter->complete());
85 EXPECT_EQ(1u, iter->attributes().size());
86 EXPECT_TRUE(iter->active());
87 EXPECT_EQ(0x0002, iter->start_handle());
88 EXPECT_EQ(0x0002, iter->end_handle());
89 EXPECT_EQ(types::kSecondaryService, iter->group_type());
90 EXPECT_TRUE(ContainersEqual(StaticByteBuffer(0xFB,
91 0x34,
92 0x9B,
93 0x5F,
94 0x80,
95 0x00,
96 0x00,
97 0x80,
98 0x00,
99 0x10,
100 0x00,
101 0x00,
102 0xef,
103 0xbe,
104 0xad,
105 0xde),
106 iter->decl_value()));
107 }
108
TEST(LocalServiceManagerTest,UnregisterService)109 TEST(LocalServiceManagerTest, UnregisterService) {
110 LocalServiceManager mgr;
111
112 auto service = std::make_unique<Service>(/*primary=*/true, kTestType16);
113 auto id1 = RegisterService(&mgr, std::move(service));
114 EXPECT_NE(0u, id1);
115 EXPECT_EQ(1u, mgr.database()->groupings().size());
116
117 // Unknown id
118 EXPECT_FALSE(mgr.UnregisterService(id1 + 1));
119
120 // Success
121 EXPECT_TRUE(mgr.UnregisterService(id1));
122 EXPECT_TRUE(mgr.database()->groupings().empty());
123
124 // |id1| becomes unknown
125 EXPECT_FALSE(mgr.UnregisterService(id1));
126 }
127
TEST(LocalServiceManagerTest,RegisterCharacteristic)128 TEST(LocalServiceManagerTest, RegisterCharacteristic) {
129 LocalServiceManager mgr;
130
131 constexpr IdType kChrcId = 0;
132 constexpr uint8_t kChrcProps = Property::kRead;
133 constexpr UUID kTestChrcType(uint16_t{0xabcd});
134 const att::AccessRequirements kReadReqs(/*encryption=*/true,
135 /*authentication=*/true,
136 /*authorization=*/true);
137 const att::AccessRequirements kWriteReqs, kUpdateReqs;
138
139 auto service = std::make_unique<Service>(/*primary=*/true, kTestType16);
140 service->AddCharacteristic(std::make_unique<Characteristic>(kChrcId,
141 kTestChrcType,
142 kChrcProps,
143 0,
144 kReadReqs,
145 kWriteReqs,
146 kUpdateReqs));
147 auto id1 = RegisterService(&mgr, std::move(service));
148 EXPECT_NE(0u, id1);
149
150 ASSERT_EQ(1u, mgr.database()->groupings().size());
151 const auto& grouping = mgr.database()->groupings().front();
152 EXPECT_TRUE(grouping.complete());
153
154 const auto& attrs = grouping.attributes();
155 ASSERT_EQ(3u, attrs.size());
156
157 att::Handle srvc_handle = attrs[0].handle();
158 EXPECT_EQ(att::kHandleMin, srvc_handle);
159
160 // Characteristic declaration
161 EXPECT_EQ(srvc_handle + 1, attrs[1].handle());
162 EXPECT_EQ(types::kCharacteristicDeclaration, attrs[1].type());
163 EXPECT_EQ(AllowedNoSecurity(), attrs[1].read_reqs());
164 EXPECT_EQ(att::AccessRequirements(), attrs[1].write_reqs());
165 EXPECT_TRUE(attrs[1].value());
166
167 // clang-format off
168 const StaticByteBuffer kDeclValue(
169 0x02, // properties
170 0x03, 0x00, // value handle
171 0xcd, 0xab // UUID
172 );
173 // clang-format on
174 EXPECT_TRUE(ContainersEqual(kDeclValue, *attrs[1].value()));
175
176 // Characteristic value
177 EXPECT_EQ(srvc_handle + 2, attrs[2].handle());
178 EXPECT_EQ(kTestChrcType, attrs[2].type());
179 EXPECT_EQ(kReadReqs, attrs[2].read_reqs());
180 EXPECT_EQ(kWriteReqs, attrs[2].write_reqs());
181
182 // This value is dynamic.
183 EXPECT_FALSE(attrs[2].value());
184 }
185
TEST(LocalServiceManagerTest,RegisterCharacteristic32)186 TEST(LocalServiceManagerTest, RegisterCharacteristic32) {
187 LocalServiceManager mgr;
188
189 constexpr IdType kChrcId = 0;
190 constexpr uint8_t kChrcProps = Property::kRead;
191 constexpr UUID kTestChrcType(uint32_t{0xdeadbeef});
192 const att::AccessRequirements kReadReqs(/*encryption=*/true,
193 /*authentication=*/true,
194 /*authorization=*/true);
195 const att::AccessRequirements kWriteReqs, kUpdateReqs;
196
197 auto service = std::make_unique<Service>(/*primary=*/true, kTestType16);
198 service->AddCharacteristic(std::make_unique<Characteristic>(kChrcId,
199 kTestChrcType,
200 kChrcProps,
201 0,
202 kReadReqs,
203 kWriteReqs,
204 kUpdateReqs));
205 auto id1 = RegisterService(&mgr, std::move(service));
206 EXPECT_NE(0u, id1);
207
208 ASSERT_EQ(1u, mgr.database()->groupings().size());
209 const auto& grouping = mgr.database()->groupings().front();
210 EXPECT_TRUE(grouping.complete());
211
212 const auto& attrs = grouping.attributes();
213 ASSERT_EQ(3u, attrs.size());
214
215 att::Handle srvc_handle = attrs[0].handle();
216 EXPECT_EQ(att::kHandleMin, srvc_handle);
217
218 // Characteristic declaration
219 EXPECT_EQ(srvc_handle + 1, attrs[1].handle());
220 EXPECT_EQ(types::kCharacteristicDeclaration, attrs[1].type());
221 EXPECT_EQ(AllowedNoSecurity(), attrs[1].read_reqs());
222 EXPECT_EQ(att::AccessRequirements(), attrs[1].write_reqs());
223 EXPECT_TRUE(attrs[1].value());
224
225 const StaticByteBuffer kDeclValue(0x02, // properties
226 0x03,
227 0x00, // value handle
228
229 // The 32-bit UUID will be stored as 128-bit
230 0xFB,
231 0x34,
232 0x9B,
233 0x5F,
234 0x80,
235 0x00,
236 0x00,
237 0x80,
238 0x00,
239 0x10,
240 0x00,
241 0x00,
242 0xef,
243 0xbe,
244 0xad,
245 0xde);
246 EXPECT_TRUE(ContainersEqual(kDeclValue, *attrs[1].value()));
247
248 // Characteristic value
249 EXPECT_EQ(srvc_handle + 2, attrs[2].handle());
250 EXPECT_EQ(kTestChrcType, attrs[2].type());
251 EXPECT_EQ(kReadReqs, attrs[2].read_reqs());
252 EXPECT_EQ(kWriteReqs, attrs[2].write_reqs());
253
254 // This value is dynamic.
255 EXPECT_FALSE(attrs[2].value());
256 }
257
TEST(LocalServiceManagerTest,RegisterCharacteristic128)258 TEST(LocalServiceManagerTest, RegisterCharacteristic128) {
259 LocalServiceManager mgr;
260
261 constexpr IdType kChrcId = 0;
262 constexpr uint8_t kChrcProps = Property::kRead;
263 UUID kTestChrcType;
264 EXPECT_TRUE(
265 StringToUuid("00112233-4455-6677-8899-AABBCCDDEEFF", &kTestChrcType));
266 const att::AccessRequirements kReadReqs(/*encryption=*/true,
267 /*authentication=*/true,
268 /*authorization=*/true);
269 const att::AccessRequirements kWriteReqs, kUpdateReqs;
270
271 auto service = std::make_unique<Service>(/*primary=*/true, kTestType16);
272 service->AddCharacteristic(std::make_unique<Characteristic>(kChrcId,
273 kTestChrcType,
274 kChrcProps,
275 0,
276 kReadReqs,
277 kWriteReqs,
278 kUpdateReqs));
279 auto id1 = RegisterService(&mgr, std::move(service));
280 EXPECT_NE(0u, id1);
281
282 ASSERT_EQ(1u, mgr.database()->groupings().size());
283 const auto& grouping = mgr.database()->groupings().front();
284 EXPECT_TRUE(grouping.complete());
285
286 const auto& attrs = grouping.attributes();
287 ASSERT_EQ(3u, attrs.size());
288
289 att::Handle srvc_handle = attrs[0].handle();
290 EXPECT_EQ(att::kHandleMin, srvc_handle);
291
292 // Characteristic declaration
293 EXPECT_EQ(srvc_handle + 1, attrs[1].handle());
294 EXPECT_EQ(types::kCharacteristicDeclaration, attrs[1].type());
295 EXPECT_EQ(AllowedNoSecurity(), attrs[1].read_reqs());
296 EXPECT_EQ(att::AccessRequirements(), attrs[1].write_reqs());
297 EXPECT_TRUE(attrs[1].value());
298
299 const StaticByteBuffer kDeclValue(0x02, // properties
300 0x03,
301 0x00, // value handle
302
303 // 128-bit UUID
304 0xFF,
305 0xEE,
306 0xDD,
307 0xCC,
308 0xBB,
309 0xAA,
310 0x99,
311 0x88,
312 0x77,
313 0x66,
314 0x55,
315 0x44,
316 0x33,
317 0x22,
318 0x11,
319 0x00);
320 EXPECT_TRUE(ContainersEqual(kDeclValue, *attrs[1].value()));
321
322 // Characteristic value
323 EXPECT_EQ(srvc_handle + 2, attrs[2].handle());
324 EXPECT_EQ(kTestChrcType, attrs[2].type());
325 EXPECT_EQ(kReadReqs, attrs[2].read_reqs());
326 EXPECT_EQ(kWriteReqs, attrs[2].write_reqs());
327
328 // This value is dynamic.
329 EXPECT_FALSE(attrs[2].value());
330 }
331
TEST(LocalServiceManagerTest,ExtPropSetSuccess)332 TEST(LocalServiceManagerTest, ExtPropSetSuccess) {
333 LocalServiceManager mgr;
334 const att::AccessRequirements kReadReqs, kWriteReqs, kUpdateReqs;
335 constexpr UUID kChrcType16(uint16_t{0x1234});
336 constexpr IdType kChrcId = 5;
337
338 auto service = std::make_unique<Service>(/*primary=*/true, kTestType16);
339
340 constexpr uint8_t kChrcProps = Property::kRead;
341 constexpr uint8_t kExtChrcProps = ExtendedProperty::kReliableWrite;
342 auto chrc = std::make_unique<Characteristic>(kChrcId,
343 kChrcType16,
344 kChrcProps,
345 kExtChrcProps,
346 kReadReqs,
347 kWriteReqs,
348 kUpdateReqs);
349 service->AddCharacteristic(std::move(chrc));
350
351 ASSERT_TRUE(RegisterService(&mgr, std::move(service)));
352 ASSERT_NE(0u, mgr.database()->groupings().size());
353 const auto& grouping = mgr.database()->groupings().front();
354 const auto& attrs = grouping.attributes();
355 ASSERT_EQ(4u, attrs.size());
356 EXPECT_EQ(types::kCharacteristicExtProperties, attrs[3].type());
357 EXPECT_TRUE(ContainersEqual( // Reliable Write property
358 StaticByteBuffer(0x01, 0x00),
359 *attrs[3].value()));
360 }
361
362 // tests that the extended properties descriptor cannot be set externally
TEST(LocalServiceManagerTest,ExtPropSetFailure)363 TEST(LocalServiceManagerTest, ExtPropSetFailure) {
364 LocalServiceManager mgr;
365 const att::AccessRequirements kReadReqs, kWriteReqs, kUpdateReqs;
366
367 constexpr UUID kChrcType16(uint16_t{0x1234});
368 constexpr UUID kDescType16(uint16_t{0x2900}); // UUID for Ext Prop
369
370 auto service = std::make_unique<Service>(/*primary=*/true, kTestType16);
371 auto chrc = std::make_unique<Characteristic>(
372 0, kChrcType16, 0, 0, kReadReqs, kWriteReqs, kUpdateReqs);
373 chrc->AddDescriptor(
374 std::make_unique<Descriptor>(1, kDescType16, kReadReqs, kWriteReqs));
375 service->AddCharacteristic(std::move(chrc));
376
377 EXPECT_EQ(false, RegisterService(&mgr, std::move(service)));
378 }
379
TEST(LocalServiceManagerTest,RegisterCharacteristicSorted)380 TEST(LocalServiceManagerTest, RegisterCharacteristicSorted) {
381 LocalServiceManager mgr;
382 const att::AccessRequirements kReadReqs, kWriteReqs, kUpdateReqs;
383
384 constexpr UUID kType16(uint16_t{0xbeef});
385 constexpr UUID kType128(uint32_t{0xdeadbeef});
386
387 constexpr IdType kChrcId0 = 0;
388 constexpr uint8_t kChrcProps0 = 0;
389 constexpr IdType kChrcId1 = 1;
390 constexpr uint8_t kChrcProps1 = 1;
391 constexpr IdType kChrcId2 = 2;
392 constexpr uint8_t kChrcProps2 = 2;
393 constexpr IdType kChrcId3 = 3;
394 constexpr uint8_t kChrcProps3 = 3;
395
396 auto service = std::make_unique<Service>(/*primary=*/true, kTestType16);
397 service->AddCharacteristic(std::make_unique<Characteristic>(
398 kChrcId0, kType128, kChrcProps0, 0, kReadReqs, kWriteReqs, kUpdateReqs));
399 service->AddCharacteristic(std::make_unique<Characteristic>(
400 kChrcId1, kType16, kChrcProps1, 0, kReadReqs, kWriteReqs, kUpdateReqs));
401 service->AddCharacteristic(std::make_unique<Characteristic>(
402 kChrcId2, kType128, kChrcProps2, 0, kReadReqs, kWriteReqs, kUpdateReqs));
403 service->AddCharacteristic(std::make_unique<Characteristic>(
404 kChrcId3, kType16, kChrcProps3, 0, kReadReqs, kWriteReqs, kUpdateReqs));
405 auto id1 = RegisterService(&mgr, std::move(service));
406 EXPECT_NE(0u, id1);
407
408 ASSERT_EQ(1u, mgr.database()->groupings().size());
409 const auto& grouping = mgr.database()->groupings().front();
410 EXPECT_TRUE(grouping.complete());
411
412 const auto& attrs = grouping.attributes();
413 ASSERT_EQ(9u, attrs.size());
414
415 // The declaration attributes should be sorted by service type (16-bit UUIDs
416 // first).
417 ASSERT_TRUE(attrs[1].value());
418 EXPECT_EQ(kChrcProps1, (*attrs[1].value())[0]);
419 ASSERT_TRUE(attrs[3].value());
420 EXPECT_EQ(kChrcProps3, (*attrs[3].value())[0]);
421 ASSERT_TRUE(attrs[5].value());
422 EXPECT_EQ(kChrcProps0, (*attrs[5].value())[0]);
423 ASSERT_TRUE(attrs[7].value());
424 EXPECT_EQ(kChrcProps2, (*attrs[7].value())[0]);
425 }
426
TEST(LocalServiceManagerTest,RegisterDescriptor)427 TEST(LocalServiceManagerTest, RegisterDescriptor) {
428 LocalServiceManager mgr;
429 const att::AccessRequirements kReadReqs, kWriteReqs, kUpdateReqs;
430
431 constexpr UUID kChrcType16(uint16_t{0x1234});
432 constexpr UUID kDescType16(uint16_t{0x5678});
433
434 auto service = std::make_unique<Service>(/*primary=*/true, kTestType16);
435 auto chrc = std::make_unique<Characteristic>(
436 0, kChrcType16, 0, 0, kReadReqs, kWriteReqs, kUpdateReqs);
437 chrc->AddDescriptor(
438 std::make_unique<Descriptor>(1, kDescType16, kReadReqs, kWriteReqs));
439 service->AddCharacteristic(std::move(chrc));
440
441 EXPECT_NE(0u, RegisterService(&mgr, std::move(service)));
442 ASSERT_EQ(1u, mgr.database()->groupings().size());
443 const auto& grouping = mgr.database()->groupings().front();
444 EXPECT_TRUE(grouping.complete());
445
446 const auto& attrs = grouping.attributes();
447 ASSERT_EQ(4u, attrs.size());
448 EXPECT_EQ(types::kCharacteristicDeclaration, attrs[1].type());
449 EXPECT_EQ(kChrcType16, attrs[2].type());
450 EXPECT_EQ(kDescType16, attrs[3].type());
451 EXPECT_FALSE(attrs[3].value());
452 }
453
TEST(LocalServiceManagerTest,DuplicateChrcIds)454 TEST(LocalServiceManagerTest, DuplicateChrcIds) {
455 LocalServiceManager mgr;
456 const att::AccessRequirements kReadReqs, kWriteReqs, kUpdateReqs;
457
458 constexpr UUID kChrcType16(uint16_t{0x1234});
459
460 auto service = std::make_unique<Service>(/*primary=*/true, kTestType16);
461
462 // Use same characteristic ID twice.
463 service->AddCharacteristic(std::make_unique<Characteristic>(
464 0, kChrcType16, 0, 0, kReadReqs, kWriteReqs, kUpdateReqs));
465 service->AddCharacteristic(std::make_unique<Characteristic>(
466 0, kChrcType16, 0, 0, kReadReqs, kWriteReqs, kUpdateReqs));
467
468 EXPECT_EQ(0u, RegisterService(&mgr, std::move(service)));
469 }
470
TEST(LocalServiceManagerTest,DuplicateDescIds)471 TEST(LocalServiceManagerTest, DuplicateDescIds) {
472 LocalServiceManager mgr;
473 const att::AccessRequirements kReadReqs, kWriteReqs, kUpdateReqs;
474
475 constexpr UUID kChrcType16(uint16_t{0x1234});
476 constexpr UUID kDescType16(uint16_t{0x5678});
477
478 auto service = std::make_unique<Service>(/*primary=*/true, kTestType16);
479
480 // Use same descriptor ID twice.
481 auto chrc = std::make_unique<Characteristic>(
482 0, kChrcType16, 0, 0, kReadReqs, kWriteReqs, kUpdateReqs);
483 chrc->AddDescriptor(
484 std::make_unique<Descriptor>(1, kDescType16, kReadReqs, kWriteReqs));
485 chrc->AddDescriptor(
486 std::make_unique<Descriptor>(1, kDescType16, kReadReqs, kWriteReqs));
487 service->AddCharacteristic(std::move(chrc));
488
489 EXPECT_EQ(0u, RegisterService(&mgr, std::move(service)));
490 }
491
TEST(LocalServiceManagerTest,DuplicateChrcAndDescIds)492 TEST(LocalServiceManagerTest, DuplicateChrcAndDescIds) {
493 LocalServiceManager mgr;
494 const att::AccessRequirements kReadReqs, kWriteReqs, kUpdateReqs;
495
496 constexpr UUID kChrcType16(uint16_t{0x1234});
497 constexpr UUID kDescType16(uint16_t{0x5678});
498
499 auto service = std::make_unique<Service>(/*primary=*/true, kTestType16);
500
501 // Use same descriptor ID twice.
502 auto chrc = std::make_unique<Characteristic>(
503 0, kChrcType16, 0, 0, kReadReqs, kWriteReqs, kUpdateReqs);
504 chrc->AddDescriptor(
505 std::make_unique<Descriptor>(0, kDescType16, kReadReqs, kWriteReqs));
506 service->AddCharacteristic(std::move(chrc));
507
508 EXPECT_EQ(0u, RegisterService(&mgr, std::move(service)));
509 }
510
TEST(LocalServiceManagerTest,ReadCharacteristicNoReadPermission)511 TEST(LocalServiceManagerTest, ReadCharacteristicNoReadPermission) {
512 LocalServiceManager mgr;
513 const att::AccessRequirements kReadReqs, kWriteReqs, kUpdateReqs;
514 constexpr UUID kChrcType16(uint16_t{0x1234});
515 constexpr IdType kChrcId = 5;
516
517 auto service = std::make_unique<Service>(/*primary=*/true, kTestType16);
518 service->AddCharacteristic(std::make_unique<Characteristic>(kChrcId,
519 kChrcType16,
520 Property::kRead,
521 0,
522 kReadReqs,
523 kWriteReqs,
524 kUpdateReqs));
525
526 bool called = false;
527 auto read_cb = [&called](auto, auto, auto, auto, auto) { called = true; };
528
529 EXPECT_NE(0u, RegisterService(&mgr, std::move(service), std::move(read_cb)));
530
531 auto* attr = mgr.database()->FindAttribute(kFirstChrcValueHandle);
532 ASSERT_TRUE(attr);
533 EXPECT_EQ(kChrcType16, attr->type());
534
535 bool result_called = false;
536 auto result_cb = [&result_called](auto, const auto&) {
537 result_called = true;
538 };
539
540 EXPECT_FALSE(attr->ReadAsync(kTestPeerId, 0, std::move(result_cb)));
541 EXPECT_FALSE(called);
542 EXPECT_FALSE(result_called);
543 }
544
TEST(LocalServiceManagerTest,ReadCharacteristicNoReadProperty)545 TEST(LocalServiceManagerTest, ReadCharacteristicNoReadProperty) {
546 LocalServiceManager mgr;
547 constexpr UUID kChrcType16(uint16_t{0x1234});
548 constexpr IdType kChrcId = 5;
549
550 // Characteristic is readable but doesn't have the "read" property.
551 auto kReadReqs = AllowedNoSecurity();
552 const att::AccessRequirements kWriteReqs, kUpdateReqs;
553
554 auto service = std::make_unique<Service>(/*primary=*/true, kTestType16);
555 service->AddCharacteristic(std::make_unique<Characteristic>(
556 kChrcId, kChrcType16, 0, 0, kReadReqs, kWriteReqs, kUpdateReqs));
557
558 bool called = false;
559 auto read_cb = [&called](auto, auto, auto, auto, auto) { called = true; };
560
561 EXPECT_NE(0u, RegisterService(&mgr, std::move(service), std::move(read_cb)));
562
563 auto* attr = mgr.database()->FindAttribute(kFirstChrcValueHandle);
564 ASSERT_TRUE(attr);
565 EXPECT_EQ(kChrcType16, attr->type());
566
567 fit::result<att::ErrorCode> status = fit::ok();
568 auto result_cb = [&status](auto cb_status, const auto&) {
569 status = cb_status;
570 };
571
572 EXPECT_TRUE(attr->ReadAsync(kTestPeerId, 0, std::move(result_cb)));
573
574 // The error should be handled internally and not reach |read_cb|.
575 EXPECT_FALSE(called);
576 ASSERT_TRUE(status.is_error());
577 EXPECT_EQ(att::ErrorCode::kReadNotPermitted, status.error_value());
578 }
579
TEST(LocalServiceManagerTest,ReadCharacteristic)580 TEST(LocalServiceManagerTest, ReadCharacteristic) {
581 LocalServiceManager mgr;
582 constexpr UUID kChrcType16(uint16_t{0x1234});
583 constexpr IdType kChrcId = 5;
584 constexpr uint16_t kOffset = 10;
585
586 const StaticByteBuffer kTestValue('f', 'o', 'o');
587
588 auto kReadReqs = AllowedNoSecurity();
589 const att::AccessRequirements kWriteReqs, kUpdateReqs;
590
591 auto service = std::make_unique<Service>(/*primary=*/true, kTestType16);
592 service->AddCharacteristic(std::make_unique<Characteristic>(kChrcId,
593 kChrcType16,
594 Property::kRead,
595 0,
596 kReadReqs,
597 kWriteReqs,
598 kUpdateReqs));
599
600 bool called = false;
601 IdType svc_id;
602 auto read_cb = [&](PeerId peer_id,
603 auto cb_svc_id,
604 auto id,
605 auto offset,
606 auto responder) {
607 called = true;
608 EXPECT_EQ(kTestPeerId, peer_id);
609 EXPECT_EQ(svc_id, cb_svc_id);
610 EXPECT_EQ(kChrcId, id);
611 EXPECT_EQ(kOffset, offset);
612 responder(fit::ok(), kTestValue);
613 };
614
615 svc_id = RegisterService(&mgr, std::move(service), std::move(read_cb));
616 ASSERT_NE(0u, svc_id);
617
618 auto* attr = mgr.database()->FindAttribute(kFirstChrcValueHandle);
619 ASSERT_TRUE(attr);
620 EXPECT_EQ(kChrcType16, attr->type());
621
622 fit::result<att::ErrorCode> status =
623 fit::error(att::ErrorCode::kUnlikelyError);
624 auto result_cb = [&status, &kTestValue](auto cb_status, const auto& value) {
625 status = cb_status;
626 EXPECT_TRUE(ContainersEqual(kTestValue, value));
627 };
628
629 EXPECT_TRUE(attr->ReadAsync(kTestPeerId, kOffset, std::move(result_cb)));
630
631 EXPECT_TRUE(called);
632 EXPECT_EQ(fit::ok(), status);
633 }
634
TEST(LocalServiceManagerTest,WriteCharacteristicNoWritePermission)635 TEST(LocalServiceManagerTest, WriteCharacteristicNoWritePermission) {
636 LocalServiceManager mgr;
637 const att::AccessRequirements kReadReqs, kWriteReqs, kUpdateReqs;
638 constexpr UUID kChrcType16(uint16_t{0x1234});
639 constexpr IdType kChrcId = 5;
640 const BufferView kTestValue;
641
642 auto service = std::make_unique<Service>(/*primary=*/true, kTestType16);
643 service->AddCharacteristic(std::make_unique<Characteristic>(kChrcId,
644 kChrcType16,
645 Property::kWrite,
646 0,
647 kReadReqs,
648 kWriteReqs,
649 kUpdateReqs));
650
651 bool called = false;
652 auto write_cb = [&called](auto, auto, auto, auto, auto&, auto) {
653 called = true;
654 };
655
656 EXPECT_NE(0u,
657 RegisterService(
658 &mgr, std::move(service), NopReadHandler, std::move(write_cb)));
659
660 auto* attr = mgr.database()->FindAttribute(kFirstChrcValueHandle);
661 ASSERT_TRUE(attr);
662 EXPECT_EQ(kChrcType16, attr->type());
663
664 bool result_called = false;
665 auto result_cb = [&result_called](auto) { result_called = true; };
666
667 EXPECT_FALSE(
668 attr->WriteAsync(kTestPeerId, 0, kTestValue, std::move(result_cb)));
669 EXPECT_FALSE(called);
670 EXPECT_FALSE(result_called);
671 }
672
TEST(LocalServiceManagerTest,WriteCharacteristicNoWriteProperty)673 TEST(LocalServiceManagerTest, WriteCharacteristicNoWriteProperty) {
674 LocalServiceManager mgr;
675 constexpr UUID kChrcType16(uint16_t{0x1234});
676 constexpr IdType kChrcId = 5;
677 const BufferView kTestValue;
678
679 const att::AccessRequirements kReadReqs, kUpdateReqs;
680 auto kWriteReqs = AllowedNoSecurity();
681
682 auto service = std::make_unique<Service>(/*primary=*/true, kTestType16);
683 service->AddCharacteristic(std::make_unique<Characteristic>(
684 kChrcId, kChrcType16, 0, 0, kReadReqs, kWriteReqs, kUpdateReqs));
685
686 bool called = false;
687 auto write_cb = [&called](auto, auto, auto, auto, auto&, auto) {
688 called = true;
689 };
690
691 EXPECT_NE(0u,
692 RegisterService(
693 &mgr, std::move(service), NopReadHandler, std::move(write_cb)));
694
695 auto* attr = mgr.database()->FindAttribute(kFirstChrcValueHandle);
696 ASSERT_TRUE(attr);
697 EXPECT_EQ(kChrcType16, attr->type());
698
699 fit::result<att::ErrorCode> status = fit::ok();
700 auto result_cb = [&status](auto cb_status) { status = cb_status; };
701
702 EXPECT_TRUE(
703 attr->WriteAsync(kTestPeerId, 0, kTestValue, std::move(result_cb)));
704
705 // The error should be handled internally and not reach |write_cb|.
706 EXPECT_FALSE(called);
707 ASSERT_TRUE(status.is_error());
708 EXPECT_EQ(att::ErrorCode::kWriteNotPermitted, status.error_value());
709 }
710
TEST(LocalServiceManagerTest,WriteCharacteristic)711 TEST(LocalServiceManagerTest, WriteCharacteristic) {
712 LocalServiceManager mgr;
713 constexpr UUID kChrcType16(uint16_t{0x1234});
714 constexpr IdType kChrcId = 5;
715 constexpr uint16_t kOffset = 10;
716
717 const StaticByteBuffer kTestValue('f', 'o', 'o');
718
719 const att::AccessRequirements kReadReqs, kUpdateReqs;
720 auto kWriteReqs = AllowedNoSecurity();
721
722 auto service = std::make_unique<Service>(/*primary=*/true, kTestType16);
723 service->AddCharacteristic(std::make_unique<Characteristic>(kChrcId,
724 kChrcType16,
725 Property::kWrite,
726 0,
727 kReadReqs,
728 kWriteReqs,
729 kUpdateReqs));
730
731 bool called = false;
732 IdType svc_id;
733 auto write_cb = [&](PeerId peer_id,
734 auto cb_svc_id,
735 auto id,
736 auto offset,
737 const auto& value,
738 auto responder) {
739 called = true;
740 EXPECT_EQ(kTestPeerId, peer_id);
741 EXPECT_EQ(svc_id, cb_svc_id);
742 EXPECT_EQ(kChrcId, id);
743 EXPECT_EQ(kOffset, offset);
744 EXPECT_TRUE(ContainersEqual(kTestValue, value));
745 responder(fit::ok());
746 };
747
748 svc_id = RegisterService(
749 &mgr, std::move(service), NopReadHandler, std::move(write_cb));
750 ASSERT_NE(0u, svc_id);
751
752 auto* attr = mgr.database()->FindAttribute(kFirstChrcValueHandle);
753 ASSERT_TRUE(attr);
754 EXPECT_EQ(kChrcType16, attr->type());
755
756 fit::result<att::ErrorCode> status =
757 fit::error(att::ErrorCode::kUnlikelyError);
758 auto result_cb = [&status](auto cb_status) { status = cb_status; };
759
760 EXPECT_TRUE(
761 attr->WriteAsync(kTestPeerId, kOffset, kTestValue, std::move(result_cb)));
762
763 EXPECT_TRUE(called);
764 EXPECT_EQ(fit::ok(), status);
765 }
766
TEST(LocalServiceManagerTest,ReadDescriptorNoReadPermission)767 TEST(LocalServiceManagerTest, ReadDescriptorNoReadPermission) {
768 LocalServiceManager mgr;
769 const att::AccessRequirements kReadReqs, kWriteReqs, kUpdateReqs;
770 constexpr UUID kChrcType16(uint16_t{0x1234});
771 constexpr UUID kDescType16(uint16_t{0x5678});
772 constexpr IdType kChrcId = 0;
773 constexpr IdType kDescId = 1;
774
775 auto service = std::make_unique<Service>(/*primary=*/true, kTestType16);
776 auto chrc = std::make_unique<Characteristic>(
777 kChrcId, kChrcType16, 0, 0, kReadReqs, kWriteReqs, kUpdateReqs);
778 chrc->AddDescriptor(std::make_unique<Descriptor>(
779 kDescId, kDescType16, kReadReqs, kWriteReqs));
780 service->AddCharacteristic(std::move(chrc));
781
782 bool called = false;
783 auto read_cb = [&called](auto, auto, auto, auto, auto) { called = true; };
784
785 EXPECT_NE(0u, RegisterService(&mgr, std::move(service), std::move(read_cb)));
786
787 auto* attr = mgr.database()->FindAttribute(kFirstDescrHandle);
788 ASSERT_TRUE(attr);
789 EXPECT_EQ(kDescType16, attr->type());
790
791 bool result_called = false;
792 auto result_cb = [&result_called](auto, const auto&) {
793 result_called = true;
794 };
795
796 EXPECT_FALSE(attr->ReadAsync(kTestPeerId, 0, std::move(result_cb)));
797 EXPECT_FALSE(called);
798 EXPECT_FALSE(result_called);
799 }
800
TEST(LocalServiceManagerTest,ReadDescriptor)801 TEST(LocalServiceManagerTest, ReadDescriptor) {
802 LocalServiceManager mgr;
803 constexpr UUID kChrcType16(uint16_t{0x1234});
804 constexpr UUID kDescType16(uint16_t{0x5678});
805 constexpr IdType kChrcId = 0;
806 constexpr IdType kDescId = 1;
807 constexpr uint16_t kOffset = 10;
808
809 const StaticByteBuffer kTestValue('f', 'o', 'o');
810
811 auto kReadReqs = AllowedNoSecurity();
812 const att::AccessRequirements kWriteReqs, kUpdateReqs;
813
814 auto service = std::make_unique<Service>(/*primary=*/true, kTestType16);
815 auto chrc = std::make_unique<Characteristic>(
816 kChrcId, kChrcType16, 0, 0, kReadReqs, kWriteReqs, kUpdateReqs);
817 chrc->AddDescriptor(
818 std::make_unique<Descriptor>(kDescId, kDescType16, kReadReqs, kReadReqs));
819 service->AddCharacteristic(std::move(chrc));
820
821 bool called = false;
822 IdType svc_id;
823 auto read_cb = [&](PeerId peer_id,
824 auto cb_svc_id,
825 auto id,
826 auto offset,
827 auto responder) {
828 called = true;
829 EXPECT_EQ(kTestPeerId, peer_id);
830 EXPECT_EQ(svc_id, cb_svc_id);
831 EXPECT_EQ(kDescId, id);
832 EXPECT_EQ(kOffset, offset);
833 responder(fit::ok(), kTestValue);
834 };
835
836 svc_id = RegisterService(&mgr, std::move(service), std::move(read_cb));
837 ASSERT_NE(0u, svc_id);
838
839 auto* attr = mgr.database()->FindAttribute(kFirstDescrHandle);
840 ASSERT_TRUE(attr);
841 EXPECT_EQ(kDescType16, attr->type());
842
843 fit::result<att::ErrorCode> status =
844 fit::error(att::ErrorCode::kUnlikelyError);
845 auto result_cb = [&status, &kTestValue](auto cb_status, const auto& value) {
846 status = cb_status;
847 EXPECT_TRUE(ContainersEqual(kTestValue, value));
848 };
849
850 EXPECT_TRUE(attr->ReadAsync(kTestPeerId, kOffset, std::move(result_cb)));
851
852 EXPECT_TRUE(called);
853 EXPECT_EQ(fit::ok(), status);
854 }
855
TEST(LocalServiceManagerTest,WriteDescriptorNoWritePermission)856 TEST(LocalServiceManagerTest, WriteDescriptorNoWritePermission) {
857 LocalServiceManager mgr;
858 const att::AccessRequirements kReadReqs, kWriteReqs, kUpdateReqs;
859 constexpr UUID kChrcType16(uint16_t{0x1234});
860 constexpr UUID kDescType16(uint16_t{0x5678});
861 constexpr IdType kChrcId = 0;
862 constexpr IdType kDescId = 1;
863 const BufferView kTestValue;
864
865 auto service = std::make_unique<Service>(/*primary=*/true, kTestType16);
866 auto chrc = std::make_unique<Characteristic>(
867 kChrcId, kChrcType16, 0, 0, kReadReqs, kWriteReqs, kUpdateReqs);
868 chrc->AddDescriptor(std::make_unique<Descriptor>(
869 kDescId, kDescType16, kReadReqs, kWriteReqs));
870 service->AddCharacteristic(std::move(chrc));
871
872 bool called = false;
873 auto write_cb = [&called](auto, auto, auto, auto, auto&, auto) {
874 called = true;
875 };
876
877 EXPECT_NE(
878 0u, RegisterService(&mgr, std::move(service), NopReadHandler, write_cb));
879
880 auto* attr = mgr.database()->FindAttribute(kFirstDescrHandle);
881 ASSERT_TRUE(attr);
882 EXPECT_EQ(kDescType16, attr->type());
883
884 bool result_called = false;
885 auto result_cb = [&result_called](auto) { result_called = true; };
886
887 EXPECT_FALSE(attr->WriteAsync(kTestPeerId, 0, kTestValue, result_cb));
888 EXPECT_FALSE(called);
889 EXPECT_FALSE(result_called);
890 }
891
TEST(LocalServiceManagerTest,WriteDescriptor)892 TEST(LocalServiceManagerTest, WriteDescriptor) {
893 LocalServiceManager mgr;
894 constexpr UUID kChrcType16(uint16_t{0x1234});
895 constexpr UUID kDescType16(uint16_t{0x5678});
896 constexpr IdType kChrcId = 0;
897 constexpr IdType kDescId = 1;
898 constexpr uint16_t kOffset = 10;
899
900 const StaticByteBuffer kTestValue('f', 'o', 'o');
901
902 const att::AccessRequirements kReadReqs, kUpdateReqs;
903 auto kWriteReqs = AllowedNoSecurity();
904
905 auto service = std::make_unique<Service>(/*primary=*/true, kTestType16);
906 auto chrc = std::make_unique<Characteristic>(
907 kChrcId, kChrcType16, 0, 0, kReadReqs, kWriteReqs, kUpdateReqs);
908 chrc->AddDescriptor(std::make_unique<Descriptor>(
909 kDescId, kDescType16, kReadReqs, kWriteReqs));
910 service->AddCharacteristic(std::move(chrc));
911
912 bool called = false;
913 IdType svc_id;
914 auto write_cb = [&](PeerId peer_id,
915 auto cb_svc_id,
916 auto id,
917 auto offset,
918 const auto& value,
919 auto responder) {
920 called = true;
921 EXPECT_EQ(kTestPeerId, peer_id);
922 EXPECT_EQ(svc_id, cb_svc_id);
923 EXPECT_EQ(kDescId, id);
924 EXPECT_EQ(kOffset, offset);
925 EXPECT_TRUE(ContainersEqual(kTestValue, value));
926 responder(fit::ok());
927 };
928
929 svc_id = RegisterService(&mgr, std::move(service), NopReadHandler, write_cb);
930 ASSERT_NE(0u, svc_id);
931
932 auto* attr = mgr.database()->FindAttribute(kFirstDescrHandle);
933 ASSERT_TRUE(attr);
934 EXPECT_EQ(kDescType16, attr->type());
935
936 fit::result<att::ErrorCode> status =
937 fit::error(att::ErrorCode::kUnlikelyError);
938 auto result_cb = [&status](auto cb_status) { status = cb_status; };
939
940 EXPECT_TRUE(attr->WriteAsync(kTestPeerId, kOffset, kTestValue, result_cb));
941
942 EXPECT_TRUE(called);
943 EXPECT_EQ(fit::ok(), status);
944 }
945
TEST(LocalServiceManagerTest,ServiceChanged)946 TEST(LocalServiceManagerTest, ServiceChanged) {
947 IdType expected_id;
948 att::Handle expected_start, expected_end;
949 int callback_count = 0;
950 ServiceChangedCallback service_changed_callback =
951 [&](IdType id, att::Handle start, att::Handle end) {
952 callback_count++;
953 EXPECT_EQ(expected_id, id);
954 EXPECT_EQ(expected_start, start);
955 EXPECT_EQ(expected_end, end);
956 };
957
958 LocalServiceManager mgr;
959
960 // Other tests add and remove services without the callback so there is
961 // already the expectation that they work.
962 mgr.set_service_changed_callback(std::move(service_changed_callback));
963
964 expected_id = 1u;
965 expected_start = 1u;
966 expected_end = 1u;
967 auto service = std::make_unique<Service>(/*primary=*/true, kTestType16);
968 auto id1 = RegisterService(&mgr, std::move(service));
969 EXPECT_NE(0u, id1);
970 EXPECT_EQ(1, callback_count);
971
972 expected_start = 2u;
973 expected_end = 2u;
974 service = std::make_unique<Service>(/*primary=*/false, kTestType32);
975
976 constexpr IdType kChrcId = 0;
977 constexpr uint8_t kChrcProps = Property::kRead;
978 constexpr UUID kTestChrcType(uint32_t{0xdeadbeef});
979 const att::AccessRequirements kReadReqs(/*encryption=*/true,
980 /*authentication=*/true,
981 /*authorization=*/true);
982 const att::AccessRequirements kWriteReqs, kUpdateReqs;
983 service->AddCharacteristic(std::make_unique<Characteristic>(kChrcId,
984 kTestChrcType,
985 kChrcProps,
986 0,
987 kReadReqs,
988 kWriteReqs,
989 kUpdateReqs));
990 expected_id = 2u;
991 expected_start = 2u;
992 expected_end = 4u;
993 auto id2 = RegisterService(&mgr, std::move(service));
994 EXPECT_NE(0u, id2);
995 EXPECT_EQ(2, callback_count);
996
997 expected_id = id1;
998 expected_start = 1u;
999 expected_end = 1u;
1000 EXPECT_TRUE(mgr.UnregisterService(id1));
1001 EXPECT_EQ(3, callback_count);
1002
1003 expected_id = id2;
1004 expected_start = 2u;
1005 expected_end = 4u;
1006 EXPECT_TRUE(mgr.UnregisterService(id2));
1007 EXPECT_EQ(4, callback_count);
1008 }
1009
1010 // TODO(armansito): Some functional groupings of tests above (such as
1011 // ReadCharacteristic, WriteCharacteristic, etc) should each use a common test
1012 // harness to reduce code duplication.
1013 class LocalClientCharacteristicConfigurationTest : public ::testing::Test {
1014 protected:
1015 LocalServiceManager mgr;
1016
1017 // The CCC descriptor is set up as the first descriptor of the first
1018 // characteristic of the first service:
1019 // 0x0001: service decl.
1020 // 0x0002: characteristic decl.
1021 // 0x0003: characteristic value
1022 // 0x0004: CCC descriptor
1023 const att::Handle kChrcHandle = 0x0003;
1024 const att::Handle kCCCHandle = 0x0004;
1025
1026 const IdType kChrcId = 0;
1027
1028 const uint16_t kEnableNot = 0x0001;
1029 const uint16_t kEnableInd = 0x0002;
1030
1031 int ccc_callback_count = 0;
1032 IdType last_service_id = 0u;
1033 PeerId last_peer_id = PeerId(kInvalidId);
1034 bool last_notify = false;
1035 bool last_indicate = false;
1036
BuildService(uint8_t props,const att::AccessRequirements & update_reqs)1037 void BuildService(uint8_t props, const att::AccessRequirements& update_reqs) {
1038 const att::AccessRequirements kReqs;
1039 auto service = std::make_unique<Service>(/*is_primary=*/true, kTestType16);
1040 service->AddCharacteristic(std::make_unique<Characteristic>(
1041 kChrcId, kTestType32, props, 0, kReqs, kReqs, update_reqs));
1042 auto ccc_callback = [this](IdType cb_svc_id,
1043 IdType id,
1044 PeerId peer_id,
1045 bool notify,
1046 bool indicate) {
1047 ccc_callback_count++;
1048 EXPECT_EQ(last_service_id, cb_svc_id);
1049 EXPECT_EQ(kChrcId, id);
1050 last_peer_id = peer_id;
1051 last_notify = notify;
1052 last_indicate = indicate;
1053 };
1054
1055 const size_t last_service_count = mgr.database()->groupings().size();
1056 last_service_id = mgr.RegisterService(
1057 std::move(service), NopReadHandler, NopWriteHandler, ccc_callback);
1058 EXPECT_NE(0u, last_service_id);
1059 EXPECT_EQ(last_service_count + 1u, mgr.database()->groupings().size());
1060 }
1061
ReadCcc(const att::Attribute * attr,PeerId peer_id,fit::result<att::ErrorCode> * out_status,uint16_t * out_value)1062 bool ReadCcc(const att::Attribute* attr,
1063 PeerId peer_id,
1064 fit::result<att::ErrorCode>* out_status,
1065 uint16_t* out_value) {
1066 BT_ASSERT(attr);
1067 BT_ASSERT(out_status);
1068 BT_ASSERT(out_value);
1069
1070 auto result_cb = [&out_status, &out_value](auto cb_status,
1071 const auto& value) {
1072 *out_status = cb_status;
1073 EXPECT_EQ(2u, value.size());
1074
1075 if (value.size() == 2u) {
1076 *out_value = le16toh(value.template To<uint16_t>());
1077 }
1078 };
1079
1080 return attr->ReadAsync(peer_id, 0u, result_cb);
1081 }
1082
WriteCcc(const att::Attribute * attr,PeerId peer_id,uint16_t ccc_value,fit::result<att::ErrorCode> * out_status)1083 bool WriteCcc(const att::Attribute* attr,
1084 PeerId peer_id,
1085 uint16_t ccc_value,
1086 fit::result<att::ErrorCode>* out_status) {
1087 BT_ASSERT(attr);
1088 BT_ASSERT(out_status);
1089
1090 auto result_cb = [&out_status](auto cb_status) { *out_status = cb_status; };
1091 uint16_t value = htole16(ccc_value);
1092 return attr->WriteAsync(
1093 peer_id, 0u, BufferView(&value, sizeof(value)), result_cb);
1094 }
1095 };
1096
TEST_F(LocalClientCharacteristicConfigurationTest,UpdatePermissions)1097 TEST_F(LocalClientCharacteristicConfigurationTest, UpdatePermissions) {
1098 // Require authentication. This should have no bearing on reads but it should
1099 // prevent writes.
1100 const att::AccessRequirements kUpdateReqs(/*encryption=*/false,
1101 /*authentication=*/true,
1102 /*authorization=*/false);
1103 constexpr uint8_t kProps = Property::kNotify;
1104 BuildService(kProps, kUpdateReqs);
1105
1106 auto* attr = mgr.database()->FindAttribute(kCCCHandle);
1107 ASSERT_TRUE(attr);
1108 EXPECT_EQ(types::kClientCharacteristicConfig, attr->type());
1109
1110 EXPECT_FALSE(attr->read_reqs().authentication_required());
1111 EXPECT_TRUE(attr->write_reqs().authentication_required());
1112 }
1113
TEST_F(LocalClientCharacteristicConfigurationTest,IndicationNotSupported)1114 TEST_F(LocalClientCharacteristicConfigurationTest, IndicationNotSupported) {
1115 // No security required to enable notifications.
1116 auto kUpdateReqs = AllowedNoSecurity();
1117 constexpr uint8_t kProps = Property::kNotify;
1118 BuildService(kProps, kUpdateReqs);
1119
1120 auto* attr = mgr.database()->FindAttribute(kCCCHandle);
1121 ASSERT_TRUE(attr);
1122 EXPECT_EQ(types::kClientCharacteristicConfig, attr->type());
1123
1124 // Enabling indications should fail as the characteristic only supports
1125 // notifications.
1126 fit::result<att::ErrorCode> status = fit::ok();
1127 EXPECT_TRUE(WriteCcc(attr, kTestPeerId, kEnableInd, &status));
1128 ASSERT_TRUE(status.is_error());
1129 EXPECT_EQ(att::ErrorCode::kWriteNotPermitted, status.error_value());
1130
1131 uint16_t ccc_value;
1132
1133 // Notifications and indications for this device should remain disabled.
1134 EXPECT_TRUE(ReadCcc(attr, kTestPeerId, &status, &ccc_value));
1135 EXPECT_EQ(fit::ok(), status);
1136 EXPECT_EQ(0x0000, ccc_value);
1137 }
1138
TEST_F(LocalClientCharacteristicConfigurationTest,NotificationNotSupported)1139 TEST_F(LocalClientCharacteristicConfigurationTest, NotificationNotSupported) {
1140 // No security.
1141 auto kUpdateReqs = AllowedNoSecurity();
1142 constexpr uint8_t kProps = Property::kIndicate;
1143 BuildService(kProps, kUpdateReqs);
1144
1145 auto* attr = mgr.database()->FindAttribute(kCCCHandle);
1146 ASSERT_TRUE(attr);
1147 EXPECT_EQ(types::kClientCharacteristicConfig, attr->type());
1148
1149 // Enabling notifications should fail as the characteristic only supports
1150 // indications.
1151 fit::result<att::ErrorCode> status = fit::ok();
1152 EXPECT_TRUE(WriteCcc(attr, kTestPeerId, kEnableNot, &status));
1153 ASSERT_TRUE(status.is_error());
1154 EXPECT_EQ(att::ErrorCode::kWriteNotPermitted, status.error_value());
1155
1156 uint16_t ccc_value;
1157
1158 // Notifications and indications for this device should remain disabled.
1159 EXPECT_TRUE(ReadCcc(attr, kTestPeerId, &status, &ccc_value));
1160 EXPECT_EQ(fit::ok(), status);
1161 EXPECT_EQ(0x0000, ccc_value);
1162 }
1163
TEST_F(LocalClientCharacteristicConfigurationTest,EnableNotify)1164 TEST_F(LocalClientCharacteristicConfigurationTest, EnableNotify) {
1165 // No security.
1166 auto kUpdateReqs = AllowedNoSecurity();
1167 constexpr uint8_t kProps = Property::kNotify;
1168 BuildService(kProps, kUpdateReqs);
1169
1170 auto* attr = mgr.database()->FindAttribute(kCCCHandle);
1171 ASSERT_TRUE(attr);
1172 EXPECT_EQ(types::kClientCharacteristicConfig, attr->type());
1173
1174 LocalServiceManager::ClientCharacteristicConfig config;
1175 EXPECT_FALSE(mgr.GetCharacteristicConfig(
1176 last_service_id, kChrcId, kTestPeerId, &config));
1177
1178 fit::result<att::ErrorCode> status =
1179 fit::error(att::ErrorCode::kUnlikelyError);
1180 EXPECT_TRUE(WriteCcc(attr, kTestPeerId, kEnableNot, &status));
1181 EXPECT_EQ(fit::ok(), status);
1182
1183 uint16_t ccc_value;
1184
1185 // Notifications should be enabled for kTestPeerId.
1186 EXPECT_TRUE(ReadCcc(attr, kTestPeerId, &status, &ccc_value));
1187 EXPECT_EQ(fit::ok(), status);
1188 EXPECT_EQ(kEnableNot, ccc_value);
1189
1190 EXPECT_TRUE(mgr.GetCharacteristicConfig(
1191 last_service_id, kChrcId, kTestPeerId, &config));
1192 EXPECT_EQ(kChrcHandle, config.handle);
1193 EXPECT_TRUE(config.notify);
1194 EXPECT_FALSE(config.indicate);
1195
1196 // ..but not for kTestPeerId2.
1197 EXPECT_TRUE(ReadCcc(attr, kTestPeerId2, &status, &ccc_value));
1198 EXPECT_EQ(fit::ok(), status);
1199 EXPECT_EQ(0x0000, ccc_value);
1200
1201 // A set configurations now exists for |kChrcId| but kTestPeerId2 should
1202 // appear as unsubscribed.
1203 EXPECT_TRUE(mgr.GetCharacteristicConfig(
1204 last_service_id, kChrcId, kTestPeerId2, &config));
1205 EXPECT_EQ(kChrcHandle, config.handle);
1206 EXPECT_FALSE(config.notify);
1207 EXPECT_FALSE(config.indicate);
1208
1209 // The callback should have been notified.
1210 EXPECT_EQ(1, ccc_callback_count);
1211 EXPECT_EQ(kTestPeerId, last_peer_id);
1212 EXPECT_TRUE(last_notify);
1213 EXPECT_FALSE(last_indicate);
1214
1215 // Enable notifications again. The write should succeed but the callback
1216 // should not get called as the value will remain unchanged.
1217 EXPECT_TRUE(WriteCcc(attr, kTestPeerId, kEnableNot, &status));
1218 EXPECT_EQ(fit::ok(), status);
1219 EXPECT_EQ(1, ccc_callback_count);
1220 }
1221
TEST_F(LocalClientCharacteristicConfigurationTest,EnableIndicate)1222 TEST_F(LocalClientCharacteristicConfigurationTest, EnableIndicate) {
1223 // No security.
1224 auto kUpdateReqs = AllowedNoSecurity();
1225 constexpr uint8_t kProps = Property::kIndicate;
1226 BuildService(kProps, kUpdateReqs);
1227
1228 auto* attr = mgr.database()->FindAttribute(kCCCHandle);
1229 ASSERT_TRUE(attr);
1230 EXPECT_EQ(types::kClientCharacteristicConfig, attr->type());
1231
1232 fit::result<att::ErrorCode> status =
1233 fit::error(att::ErrorCode::kUnlikelyError);
1234 EXPECT_TRUE(WriteCcc(attr, kTestPeerId, kEnableInd, &status));
1235 EXPECT_EQ(fit::ok(), status);
1236
1237 uint16_t ccc_value;
1238
1239 // Indications should be enabled for kTestPeerId.
1240 EXPECT_TRUE(ReadCcc(attr, kTestPeerId, &status, &ccc_value));
1241 EXPECT_EQ(fit::ok(), status);
1242 EXPECT_EQ(kEnableInd, ccc_value);
1243
1244 LocalServiceManager::ClientCharacteristicConfig config;
1245 EXPECT_TRUE(mgr.GetCharacteristicConfig(
1246 last_service_id, kChrcId, kTestPeerId, &config));
1247 EXPECT_EQ(kChrcHandle, config.handle);
1248 EXPECT_FALSE(config.notify);
1249 EXPECT_TRUE(config.indicate);
1250
1251 // ..but not for kTestPeerId2.
1252 EXPECT_TRUE(ReadCcc(attr, kTestPeerId2, &status, &ccc_value));
1253 EXPECT_EQ(fit::ok(), status);
1254 EXPECT_EQ(0x0000, ccc_value);
1255
1256 // A set configurations now exists for |kChrcId| but kTestPeerId2 should
1257 // appear as unsubscribed.
1258 EXPECT_TRUE(mgr.GetCharacteristicConfig(
1259 last_service_id, kChrcId, kTestPeerId2, &config));
1260 EXPECT_EQ(kChrcHandle, config.handle);
1261 EXPECT_FALSE(config.notify);
1262 EXPECT_FALSE(config.indicate);
1263
1264 // The callback should have been notified.
1265 EXPECT_EQ(1, ccc_callback_count);
1266 EXPECT_EQ(kTestPeerId, last_peer_id);
1267 EXPECT_FALSE(last_notify);
1268 EXPECT_TRUE(last_indicate);
1269
1270 // Enable indications again. The write should succeed but the callback
1271 // should not get called as the value will remain unchanged.
1272 EXPECT_TRUE(WriteCcc(attr, kTestPeerId, kEnableInd, &status));
1273 EXPECT_EQ(fit::ok(), status);
1274 EXPECT_EQ(1, ccc_callback_count);
1275 }
1276
TEST_F(LocalClientCharacteristicConfigurationTest,DisconnectCleanup)1277 TEST_F(LocalClientCharacteristicConfigurationTest, DisconnectCleanup) {
1278 // No security.
1279 auto kUpdateReqs = AllowedNoSecurity();
1280 constexpr uint8_t kProps = Property::kNotify;
1281 BuildService(kProps, kUpdateReqs);
1282
1283 auto* attr = mgr.database()->FindAttribute(kCCCHandle);
1284 ASSERT_TRUE(attr);
1285 EXPECT_EQ(types::kClientCharacteristicConfig, attr->type());
1286
1287 LocalServiceManager::ClientCharacteristicConfig config;
1288 EXPECT_FALSE(mgr.GetCharacteristicConfig(
1289 last_service_id, kChrcId, kTestPeerId, &config));
1290
1291 fit::result<att::ErrorCode> status =
1292 fit::error(att::ErrorCode::kUnlikelyError);
1293 EXPECT_TRUE(WriteCcc(attr, kTestPeerId, kEnableNot, &status));
1294 EXPECT_EQ(fit::ok(), status);
1295
1296 // The callback should have been notified.
1297 EXPECT_EQ(1, ccc_callback_count);
1298 EXPECT_EQ(kTestPeerId, last_peer_id);
1299 EXPECT_TRUE(last_notify);
1300 EXPECT_FALSE(last_indicate);
1301
1302 mgr.DisconnectClient(kTestPeerId);
1303
1304 uint16_t ccc_value;
1305 // Reads should succeed but notifications should be disabled.
1306 EXPECT_TRUE(ReadCcc(attr, kTestPeerId, &status, &ccc_value));
1307 EXPECT_EQ(fit::ok(), status);
1308 EXPECT_EQ(0x0000, ccc_value);
1309
1310 // The callback should not have been called on client disconnect.
1311 EXPECT_EQ(1, ccc_callback_count);
1312 EXPECT_EQ(kTestPeerId, last_peer_id);
1313 EXPECT_TRUE(last_notify);
1314 EXPECT_FALSE(last_indicate);
1315
1316 mgr.DisconnectClient(kTestPeerId2);
1317
1318 // The callback should not be called on client disconnect.
1319 EXPECT_EQ(1, ccc_callback_count);
1320 EXPECT_EQ(kTestPeerId, last_peer_id);
1321 }
1322
1323 } // namespace
1324 } // namespace bt::gatt
1325