• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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