• 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/server.h"
16 
17 #include "pw_bluetooth_sapphire/internal/host/att/att.h"
18 #include "pw_bluetooth_sapphire/internal/host/att/attribute.h"
19 #include "pw_bluetooth_sapphire/internal/host/att/database.h"
20 #include "pw_bluetooth_sapphire/internal/host/common/macros.h"
21 #include "pw_bluetooth_sapphire/internal/host/common/uuid.h"
22 #include "pw_bluetooth_sapphire/internal/host/gatt/gatt_defs.h"
23 #include "pw_bluetooth_sapphire/internal/host/gatt/local_service_manager.h"
24 #include "pw_bluetooth_sapphire/internal/host/l2cap/mock_channel_test.h"
25 #include "pw_bluetooth_sapphire/internal/host/testing/test_helpers.h"
26 
27 #pragma clang diagnostic ignored "-Wshadow"
28 
29 namespace bt::gatt {
30 namespace {
31 
32 constexpr UUID kTestSvcType(uint16_t{0xDEAD});
33 constexpr UUID kTestChrcType(uint16_t{0xFEED});
34 constexpr IdType kTestChrcId{0xFADE};
35 constexpr PeerId kTestPeerId(1);
36 constexpr UUID kTestType16(uint16_t{0xBEEF});
37 constexpr UUID kTestType128(
38     {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15});
39 
40 const StaticByteBuffer kTestValue1('f', 'o', 'o');
41 const StaticByteBuffer kTestValue2('b', 'a', 'r');
42 const StaticByteBuffer kTestValue3('b', 'a', 'z');
43 const StaticByteBuffer kTestValue4('l', 'o', 'l');
44 
45 const StaticByteBuffer kTestValueLong('l', 'o', 'n', 'g');
46 
AllowedNoSecurity()47 inline att::AccessRequirements AllowedNoSecurity() {
48   return att::AccessRequirements(/*encryption=*/false,
49                                  /*authentication=*/false,
50                                  /*authorization=*/false);
51 }
52 
53 class ServerTest : public l2cap::testing::MockChannelTest {
54  public:
55   ServerTest() = default;
56   ~ServerTest() override = default;
57 
58  protected:
SetUp()59   void SetUp() override {
60     local_services_ = std::make_unique<LocalServiceManager>();
61 
62     ChannelOptions options(l2cap::kATTChannelId);
63     fake_att_chan_ = CreateFakeChannel(options);
64     att_ = att::Bearer::Create(fake_att_chan_->GetWeakPtr(), dispatcher());
65     server_ = gatt::Server::Create(
66         kTestPeerId, local_services_->GetWeakPtr(), att_->GetWeakPtr());
67   }
68 
TearDown()69   void TearDown() override {
70     RunUntilIdle();
71     server_ = nullptr;
72     att_ = nullptr;
73     fake_att_chan_ = l2cap::testing::FakeChannel::WeakPtr();
74     local_services_ = nullptr;
75   }
76 
77   // Registers a service with UUID |svc_type| containing a single characteristic
78   // of UUID |chrc_type| and represented by |chrc_id|. The characteristic
79   // supports the indicate and notify properties, but has not configured them
80   // via the CCC. Returns the ID of the registered service.
RegisterSvcWithSingleChrc(UUID svc_type,IdType chrc_id,UUID chrc_type)81   IdType RegisterSvcWithSingleChrc(UUID svc_type,
82                                    IdType chrc_id,
83                                    UUID chrc_type) {
84     ServicePtr svc = std::make_unique<Service>(/*primary=*/true, svc_type);
85     CharacteristicPtr chr = std::make_unique<Characteristic>(
86         chrc_id,
87         chrc_type,
88         Property::kIndicate | Property::kNotify,
89         /*extended_properties=*/0u,
90         /*read_permission=*/att::AccessRequirements(),
91         /*write_permissions=*/att::AccessRequirements(),
92         /*update_permisisons=*/AllowedNoSecurity());
93     svc->AddCharacteristic(std::move(chr));
94     return local_services_->RegisterService(
95         std::move(svc), NopReadHandler, NopWriteHandler, NopCCCallback);
96   }
97 
98   struct SvcIdAndChrcHandle {
99     IdType svc_id;
100     att::Handle chrc_val_handle;
101   };
102   // RegisterSvcWithSingleChrc, but the CCC is configured to |ccc_val| for
103   // kTestPeerId. Returns the ID of the service alongside the handle of the
104   // registered characteristic value.
RegisterSvcWithConfiguredChrc(UUID svc_type,IdType chrc_id,UUID chrc_type,uint16_t ccc_val=kCCCIndicationBit|kCCCNotificationBit)105   SvcIdAndChrcHandle RegisterSvcWithConfiguredChrc(
106       UUID svc_type,
107       IdType chrc_id,
108       UUID chrc_type,
109       uint16_t ccc_val = kCCCIndicationBit | kCCCNotificationBit) {
110     IdType svc_id = RegisterSvcWithSingleChrc(svc_type, chrc_id, chrc_type);
111     std::vector<att::Handle> chrc_val_handle =
112         SetCCCs(kTestPeerId, chrc_type, ccc_val);
113     EXPECT_EQ(1u, chrc_val_handle.size());
114     return SvcIdAndChrcHandle{.svc_id = svc_id,
115                               .chrc_val_handle = chrc_val_handle[0]};
116   }
server() const117   Server* server() const { return server_.get(); }
118 
db() const119   att::Database::WeakPtr db() const { return local_services_->database(); }
120 
121   // TODO(armansito): Consider introducing a FakeBearer for testing
122   // (fxbug.dev/42142784).
att() const123   att::Bearer* att() const { return att_.get(); }
124 
125  private:
126   enum CCCSearchState {
127     kSearching,
128     kChrcDeclarationFound,
129     kCorrectChrcUuidFound,
130   };
131   // Sets |local_services_|' CCCs for |peer_id| to |ccc_val| for all
132   // characteristics of |chrc_type|, and returns the handles of the
133   // characteristic values for which the CCC was modified.
SetCCCs(PeerId peer_id,bt::UUID chrc_type,uint16_t ccc_val)134   std::vector<att::Handle> SetCCCs(PeerId peer_id,
135                                    bt::UUID chrc_type,
136                                    uint16_t ccc_val) {
137     std::vector<att::Handle> modified_attrs;
138     CCCSearchState state = kSearching;
139     for (auto& grouping : db()->groupings()) {
140       att::Handle matching_chrc_value_handle = att::kInvalidHandle;
141       for (auto& attr : grouping.attributes()) {
142         if (attr.type() == types::kCharacteristicDeclaration) {
143           EXPECT_NE(state, kChrcDeclarationFound)
144               << "unexpectedly found two consecutive characteristic "
145                  "declarations";
146           state = kChrcDeclarationFound;
147         } else if (state == kChrcDeclarationFound && attr.type() == chrc_type) {
148           state = kCorrectChrcUuidFound;
149           matching_chrc_value_handle = attr.handle();
150         } else if (state == kChrcDeclarationFound) {
151           state = kSearching;
152         } else if (state == kCorrectChrcUuidFound &&
153                    attr.type() == types::kClientCharacteristicConfig) {
154           BT_ASSERT(matching_chrc_value_handle != att::kInvalidHandle);
155           DynamicByteBuffer new_ccc(sizeof(ccc_val));
156           new_ccc.WriteObj(ccc_val);
157           fit::result<att::ErrorCode> write_status =
158               fit::error(att::ErrorCode::kReadNotPermitted);
159           EXPECT_TRUE(attr.WriteAsync(peer_id,
160                                       /*offset=*/0,
161                                       new_ccc,
162                                       [&](fit::result<att::ErrorCode> status) {
163                                         write_status = status;
164                                       }));
165           // Not strictly necessary with the current WriteAsync implementation,
166           // but running the loop here makes this more future-proof.
167           RunUntilIdle();
168           EXPECT_EQ(fit::ok(), write_status);
169           modified_attrs.push_back(matching_chrc_value_handle);
170         }
171       }
172     }
173     EXPECT_NE(0u, modified_attrs.size()) << "Couldn't find CCC attribute!";
174     return modified_attrs;
175   }
176 
177   std::unique_ptr<LocalServiceManager> local_services_;
178   l2cap::testing::FakeChannel::WeakPtr fake_att_chan_;
179   std::unique_ptr<att::Bearer> att_;
180   std::unique_ptr<Server> server_;
181 
182   BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(ServerTest);
183 };
184 
TEST_F(ServerTest,ExchangeMTURequestInvalidPDU)185 TEST_F(ServerTest, ExchangeMTURequestInvalidPDU) {
186   // Just opcode
187   // clang-format off
188   const StaticByteBuffer kInvalidPDU(0x02);
189   const StaticByteBuffer kExpected(
190       0x01,        // opcode: error response
191       0x02,        // request: exchange MTU
192       0x00, 0x00,  // handle: 0
193       0x04         // error: Invalid PDU
194   );
195   // clang-format on
196 
197   EXPECT_PACKET_OUT(kExpected);
198   fake_chan()->Receive(kInvalidPDU);
199 }
200 
TEST_F(ServerTest,ExchangeMTURequestValueTooSmall)201 TEST_F(ServerTest, ExchangeMTURequestValueTooSmall) {
202   const uint16_t kServerMTU = att::kLEMaxMTU;
203   constexpr uint16_t kClientMTU = 1;
204 
205   // clang-format off
206   const StaticByteBuffer kRequest(
207     0x02,             // opcode: exchange MTU
208     kClientMTU, 0x00  // client rx mtu: |kClientMTU|
209   );
210 
211   const StaticByteBuffer kExpected(
212     0x03,       // opcode: exchange MTU response
213     0xF7, 0x00  // server rx mtu: |kServerMTU|
214   );
215   // clang-format on
216 
217   ASSERT_EQ(kServerMTU, att()->preferred_mtu());
218 
219   EXPECT_PACKET_OUT(kExpected);
220   fake_chan()->Receive(kRequest);
221   // Should default to kLEMinMTU since kClientMTU is too small.
222   EXPECT_EQ(att::kLEMinMTU, att()->mtu());
223 }
224 
TEST_F(ServerTest,ExchangeMTURequest)225 TEST_F(ServerTest, ExchangeMTURequest) {
226   constexpr uint16_t kServerMTU = att::kLEMaxMTU;
227   constexpr uint16_t kClientMTU = 0x64;
228 
229   // clang-format off
230   const StaticByteBuffer kRequest(
231     0x02,             // opcode: exchange MTU
232     kClientMTU, 0x00  // client rx mtu: |kClientMTU|
233   );
234 
235   const StaticByteBuffer kExpected(
236     0x03,       // opcode: exchange MTU response
237     0xF7, 0x00  // server rx mtu: |kServerMTU|
238   );
239   // clang-format on
240 
241   ASSERT_EQ(kServerMTU, att()->preferred_mtu());
242 
243   EXPECT_PACKET_OUT(kExpected);
244   fake_chan()->Receive(kRequest);
245   EXPECT_EQ(kClientMTU, att()->mtu());
246 }
247 
TEST_F(ServerTest,FindInformationInvalidPDU)248 TEST_F(ServerTest, FindInformationInvalidPDU) {
249   // Just opcode
250   // clang-format off
251   const StaticByteBuffer kInvalidPDU(0x04);
252   const StaticByteBuffer kExpected(
253       0x01,        // opcode: error response
254       0x04,        // request: find information
255       0x00, 0x00,  // handle: 0
256       0x04         // error: Invalid PDU
257   );
258   // clang-format on
259 
260   EXPECT_PACKET_OUT(kExpected);
261   fake_chan()->Receive(kInvalidPDU);
262 }
263 
TEST_F(ServerTest,FindInformationInvalidHandle)264 TEST_F(ServerTest, FindInformationInvalidHandle) {
265   // Start handle is 0
266   // clang-format off
267   const StaticByteBuffer kInvalidStartHandle(
268       0x04,        // opcode: find information
269       0x00, 0x00,  // start: 0x0000
270       0xFF, 0xFF   // end: 0xFFFF
271   );
272 
273   const StaticByteBuffer kExpected1(
274       0x01,        // opcode: error response
275       0x04,        // request: find information
276       0x00, 0x00,  // handle: 0x0000 (start handle in request)
277       0x01         // error: Invalid handle
278   );
279 
280   // End handle is smaller than start handle
281   const StaticByteBuffer kInvalidEndHandle(
282       0x04,        // opcode: find information
283       0x02, 0x00,  // start: 0x0002
284       0x01, 0x00   // end: 0x0001
285   );
286 
287   const StaticByteBuffer kExpected2(
288       0x01,        // opcode: error response
289       0x04,        // request: find information
290       0x02, 0x00,  // handle: 0x0002 (start handle in request)
291       0x01         // error: Invalid handle
292   );
293   // clang-format on
294 
295   EXPECT_PACKET_OUT(kExpected1);
296   fake_chan()->Receive(kInvalidStartHandle);
297   EXPECT_PACKET_OUT(kExpected2);
298   fake_chan()->Receive(kInvalidEndHandle);
299 }
300 
TEST_F(ServerTest,FindInformationAttributeNotFound)301 TEST_F(ServerTest, FindInformationAttributeNotFound) {
302   // clang-format off
303   const StaticByteBuffer kRequest(
304       0x04,        // opcode: find information request
305       0x01, 0x00,  // start: 0x0001
306       0xFF, 0xFF   // end: 0xFFFF
307   );
308 
309   const StaticByteBuffer kExpected(
310       0x01,        // opcode: error response
311       0x04,        // request: find information
312       0x01, 0x00,  // handle: 0x0001 (start handle in request)
313       0x0A         // error: Attribute not found
314   );
315   // clang-format on
316 
317   EXPECT_PACKET_OUT(kExpected);
318   fake_chan()->Receive(kRequest);
319 }
320 
TEST_F(ServerTest,FindInformation16)321 TEST_F(ServerTest, FindInformation16) {
322   auto* grp = db()->NewGrouping(types::kPrimaryService, 2, kTestValue1);
323   grp->AddAttribute(kTestType16);
324   grp->AddAttribute(kTestType16);
325   grp->set_active(true);
326 
327   // clang-format off
328   const StaticByteBuffer kRequest(
329       0x04,        // opcode: find information request
330       0x01, 0x00,  // start: 0x0001
331       0xFF, 0xFF   // end: 0xFFFF
332   );
333 
334   const StaticByteBuffer kExpected(
335       0x05,        // opcode: find information response
336       0x01,        // format: 16-bit
337       0x01, 0x00,  // handle: 0x0001
338       0x00, 0x28,  // uuid: primary service group type
339       0x02, 0x00,  // handle: 0x0002
340       0xEF, 0xBE,  // uuid: 0xBEEF
341       0x03, 0x00,  // handle: 0x0003
342       0xEF, 0xBE   // uuid: 0xBEEF
343   );
344   // clang-format on
345 
346   EXPECT_PACKET_OUT(kExpected);
347   fake_chan()->Receive(kRequest);
348 }
349 
TEST_F(ServerTest,FindInformation128)350 TEST_F(ServerTest, FindInformation128) {
351   auto* grp = db()->NewGrouping(kTestType128, 0, kTestValue1);
352   grp->set_active(true);
353 
354   // clang-format off
355   const StaticByteBuffer kRequest(
356       0x04,        // opcode: find information request
357       0x01, 0x00,  // start: 0x0001
358       0xFF, 0xFF   // end: 0xFFFF
359   );
360 
361   const StaticByteBuffer kExpected(
362       0x05,        // opcode: find information response
363       0x02,        // format: 128-bit
364       0x01, 0x00,  // handle: 0x0001
365 
366       // uuid: 0F0E0D0C-0B0A-0908-0706-050403020100
367       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
368       0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F);
369   // clang-format on
370 
371   EXPECT_PACKET_OUT(kExpected);
372   fake_chan()->Receive(kRequest);
373 }
374 
TEST_F(ServerTest,FindByTypeValueSuccess)375 TEST_F(ServerTest, FindByTypeValueSuccess) {
376   // handle: 1 (active)
377   db()->NewGrouping(types::kPrimaryService, 0, kTestValue1)->set_active(true);
378 
379   // handle: 2 (active)
380   db()->NewGrouping(types::kPrimaryService, 0, kTestValue2)->set_active(true);
381 
382   // handle: 3 (active)
383   db()->NewGrouping(types::kPrimaryService, 0, kTestValue1)->set_active(true);
384 
385   // clang-format off
386   const StaticByteBuffer kRequest(
387       0x06,          // opcode: find by type value request
388       0x01, 0x00,    // start: 0x0001
389       0xFF, 0xFF,    // end: 0xFFFF
390       0x00, 0x28,    // uuid: primary service group type
391       'f', 'o', 'o'  // value: foo
392   );
393 
394   const StaticByteBuffer kExpected(
395       0x07,        // opcode: find by type value response
396       0x01, 0x00,  // handle: 0x0001
397       0x01, 0x00,  // group handle: 0x0001
398       0x03, 0x00,  // handle: 0x0003
399       0x03, 0x00   // group handle: 0x0003
400   );
401   // clang-format on
402 
403   EXPECT_PACKET_OUT(kExpected);
404   fake_chan()->Receive(kRequest);
405 }
406 
TEST_F(ServerTest,FindByTypeValueFail)407 TEST_F(ServerTest, FindByTypeValueFail) {
408   // handle: 1 (active)
409   db()->NewGrouping(types::kPrimaryService, 0, kTestValue1)->set_active(true);
410 
411   // clang-format off
412   const StaticByteBuffer kRequest(
413       0x06,          // opcode: find by type value request
414       0x01, 0x00,    // start: 0x0001
415       0xFF, 0xFF,    // end: 0xFFFF
416       0x00, 0x28,    // uuid: primary service group type
417       'n', 'o'       // value: no
418   );
419 
420   const StaticByteBuffer kExpected(
421       0x01,          // Error
422       0x06,          // opcode: find by type value
423       0x00, 0x00,    // group handle: 0x0000
424       0x0a           // Attribute Not Found
425   );
426   // clang-format on
427 
428   EXPECT_PACKET_OUT(kExpected);
429   fake_chan()->Receive(kRequest);
430 }
431 
TEST_F(ServerTest,FindByTypeValueEmptyDB)432 TEST_F(ServerTest, FindByTypeValueEmptyDB) {
433   // clang-format off
434   const StaticByteBuffer kRequest(
435       0x06,          // opcode: find by type value request
436       0x01, 0x00,    // start: 0x0001
437       0xFF, 0xFF,    // end: 0xFFFF
438       0x00, 0x28,    // uuid: primary service group type
439       'n', 'o'       // value: no
440   );
441 
442   const StaticByteBuffer kExpected(
443       0x01,          // Error
444       0x06,          // opcode: find by type value
445       0x00, 0x00,    // group handle: 0x0000
446       0x0a           // Attribute Not Found
447   );
448   // clang-format on
449 
450   EXPECT_PACKET_OUT(kExpected);
451   fake_chan()->Receive(kRequest);
452 }
453 
TEST_F(ServerTest,FindByTypeValueInvalidHandle)454 TEST_F(ServerTest, FindByTypeValueInvalidHandle) {
455   // clang-format off
456   const StaticByteBuffer kRequest(
457       0x06,          // opcode: find by type value request
458       0x02, 0x00,    // start: 0x0002
459       0x01, 0x00,    // end: 0x0001
460       0x00, 0x28,    // uuid: primary service group type
461       'n', 'o'       // value: no
462   );
463 
464   const StaticByteBuffer kExpected(
465       0x01,          // Error
466       0x06,          // opcode: find by type value
467       0x00, 0x00,    // group handle: 0x0000
468       0x01           // Invalid Handle
469   );
470   // clang-format on
471 
472   EXPECT_PACKET_OUT(kExpected);
473   fake_chan()->Receive(kRequest);
474 }
475 
TEST_F(ServerTest,FindByTypeValueInvalidPDUError)476 TEST_F(ServerTest, FindByTypeValueInvalidPDUError) {
477   // handle: 1 (active)
478   db()->NewGrouping(types::kPrimaryService, 0, kTestValue1)->set_active(true);
479 
480   // clang-format off
481   const StaticByteBuffer kInvalidPDU(0x06);
482 
483   const StaticByteBuffer kExpected(
484       0x01,          // Error
485       0x06,          // opcode: find by type value
486       0x00, 0x00,    // group handle: 0x0000
487       0x04           // Invalid PDU
488   );
489   // clang-format on
490 
491   EXPECT_PACKET_OUT(kExpected);
492   fake_chan()->Receive(kInvalidPDU);
493 }
494 
TEST_F(ServerTest,FindByTypeValueZeroLengthValueError)495 TEST_F(ServerTest, FindByTypeValueZeroLengthValueError) {
496   // handle: 1 (active)
497   db()->NewGrouping(types::kPrimaryService, 0, kTestValue1)->set_active(true);
498 
499   // clang-format off
500   const StaticByteBuffer kRequest(
501       0x06,          // opcode: find by type value request
502       0x01, 0x00,    // start: 0x0001
503       0xFF, 0xFF,    // end: 0xFFFF
504       0x00, 0x28     // uuid: primary service group type
505   );
506 
507   const StaticByteBuffer kExpected(
508       0x01,          // Error
509       0x06,          // opcode: find by type value
510       0x00, 0x00,    // group handle: 0x0000
511       0x0a           // Attribute Not Found
512   );
513   // clang-format on
514 
515   EXPECT_PACKET_OUT(kExpected);
516   fake_chan()->Receive(kRequest);
517 }
518 
TEST_F(ServerTest,FindByTypeValueOutsideRangeError)519 TEST_F(ServerTest, FindByTypeValueOutsideRangeError) {
520   // handle: 1 (active)
521   auto* grp = db()->NewGrouping(kTestType16, 2, kTestValue2);
522 
523   // handle: 2 - value: "long"
524   grp->AddAttribute(kTestType16, AllowedNoSecurity())->SetValue(kTestValue2);
525 
526   // handle: 3 - value: "foo"
527   grp->AddAttribute(kTestType16, AllowedNoSecurity())->SetValue(kTestValue1);
528   grp->set_active(true);
529 
530   // clang-format off
531   const StaticByteBuffer kRequest(
532       0x06,          // opcode: find by type value request
533       0x01, 0x00,    // start: 0x0001
534       0x02, 0x00,    // end: 0xFFFF
535       0x00, 0x28,    // uuid: primary service group type
536       'f', 'o', 'o'  // value: foo
537   );
538 
539   const StaticByteBuffer kExpected(
540       0x01,          // Error
541       0x06,          // opcode: find by type value
542       0x00, 0x00,    // group handle: 0x0000
543       0x0a           // Attribute Not Found
544   );
545   // clang-format on
546 
547   EXPECT_PACKET_OUT(kExpected);
548   fake_chan()->Receive(kRequest);
549 }
550 
TEST_F(ServerTest,FindInfomationInactive)551 TEST_F(ServerTest, FindInfomationInactive) {
552   // handle: 1 (active)
553   db()->NewGrouping(types::kPrimaryService, 0, kTestValue1)->set_active(true);
554 
555   // handle: 2, 3, 4 (inactive)
556   auto* grp = db()->NewGrouping(types::kPrimaryService, 2, kTestValue1);
557   grp->AddAttribute(kTestType16);
558   grp->AddAttribute(kTestType16);
559 
560   // handle: 5 (active)
561   db()->NewGrouping(types::kPrimaryService, 0, kTestValue1)->set_active(true);
562 
563   // clang-format off
564   const StaticByteBuffer kRequest(
565       0x04,        // opcode: find information request
566       0x01, 0x00,  // start: 0x0001
567       0xFF, 0xFF   // end: 0xFFFF
568   );
569 
570   const StaticByteBuffer kExpected(
571       0x05,        // opcode: find information response
572       0x01,        // format: 16-bit
573       0x01, 0x00,  // handle: 0x0001
574       0x00, 0x28,  // uuid: primary service group type
575       0x05, 0x00,  // handle: 0x0005
576       0x00, 0x28  // uuid: primary service group type
577   );
578   // clang-format on
579 
580   EXPECT_PACKET_OUT(kExpected);
581   fake_chan()->Receive(kRequest);
582 }
583 
TEST_F(ServerTest,FindInfomationRange)584 TEST_F(ServerTest, FindInfomationRange) {
585   auto* grp = db()->NewGrouping(types::kPrimaryService, 2, kTestValue1);
586   grp->AddAttribute(kTestType16);
587   grp->AddAttribute(kTestType16);
588   grp->set_active(true);
589 
590   // handle: 5 (active)
591   db()->NewGrouping(types::kPrimaryService, 0, kTestValue1)->set_active(true);
592 
593   // clang-format off
594   const StaticByteBuffer kRequest(
595       0x04,        // opcode: find information request
596       0x02, 0x00,  // start: 0x0002
597       0x02, 0x00   // end: 0x0002
598   );
599 
600   const StaticByteBuffer kExpected(
601       0x05,        // opcode: find information response
602       0x01,        // format: 16-bit
603       0x02, 0x00,  // handle: 0x0001
604       0xEF, 0xBE   // uuid: 0xBEEF
605   );
606   // clang-format on
607 
608   EXPECT_PACKET_OUT(kExpected);
609   fake_chan()->Receive(kRequest);
610 }
611 
TEST_F(ServerTest,ReadByGroupTypeInvalidPDU)612 TEST_F(ServerTest, ReadByGroupTypeInvalidPDU) {
613   // Just opcode
614   // clang-format off
615   const StaticByteBuffer kInvalidPDU(0x10);
616   const StaticByteBuffer kExpected(
617       0x01,        // opcode: error response
618       0x10,        // request: read by group type
619       0x00, 0x00,  // handle: 0
620       0x04         // error: Invalid PDU
621   );
622   // clang-format on
623 
624   EXPECT_PACKET_OUT(kExpected);
625   fake_chan()->Receive(kInvalidPDU);
626 }
627 
TEST_F(ServerTest,ReadByGroupTypeUnsupportedGroupType)628 TEST_F(ServerTest, ReadByGroupTypeUnsupportedGroupType) {
629   // 16-bit UUID
630   // clang-format off
631   const StaticByteBuffer kUsing16BitType(
632       0x10,        // opcode: read by group type
633       0x01, 0x00,  // start: 0x0001
634       0xFF, 0xFF,  // end: 0xFFFF
635       0x01, 0x00   // group type: 1 (unsupported)
636   );
637 
638   // 128-bit UUID
639   const StaticByteBuffer kUsing128BitType(
640       0x10,        // opcode: read by group type
641       0x01, 0x00,  // start: 0x0001
642       0xFF, 0xFF,  // end: 0xFFFF
643 
644       // group type: 00112233-4455-6677-8899-AABBCCDDEEFF (unsupported)
645       0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88,
646       0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00);
647 
648   const StaticByteBuffer kExpected(
649       0x01,        // opcode: error response
650       0x10,        // request: read by group type
651       0x01, 0x00,  // handle: 0x0001 (start handle in request)
652       0x10         // error: Unsupported Group Type
653   );
654   // clang-format on
655 
656   EXPECT_PACKET_OUT(kExpected);
657   fake_chan()->Receive(kUsing16BitType);
658   EXPECT_PACKET_OUT(kExpected);
659   fake_chan()->Receive(kUsing128BitType);
660 }
661 
TEST_F(ServerTest,ReadByGroupTypeInvalidHandle)662 TEST_F(ServerTest, ReadByGroupTypeInvalidHandle) {
663   // Start handle is 0
664   // clang-format off
665   const StaticByteBuffer kInvalidStartHandle(
666       0x10,        // opcode: read by group type
667       0x00, 0x00,  // start: 0x0000
668       0xFF, 0xFF,  // end: 0xFFFF
669       0x00, 0x28   // group type: 0x2800 (primary service)
670   );
671 
672   const StaticByteBuffer kExpected1(
673       0x01,        // opcode: error response
674       0x10,        // request: read by group type
675       0x00, 0x00,  // handle: 0x0000 (start handle in request)
676       0x01         // error: Invalid handle
677   );
678 
679   // End handle is smaller than start handle
680   const StaticByteBuffer kInvalidEndHandle(
681       0x10,        // opcode: read by group type
682       0x02, 0x00,  // start: 0x0002
683       0x01, 0x00,  // end: 0x0001
684       0x00, 0x28   // group type: 0x2800 (primary service)
685   );
686 
687   const StaticByteBuffer kExpected2(
688       0x01,        // opcode: error response
689       0x10,        // request: read by group type
690       0x02, 0x00,  // handle: 0x0002 (start handle in request)
691       0x01         // error: Invalid handle
692   );
693   // clang-format on
694 
695   EXPECT_PACKET_OUT(kExpected1);
696   fake_chan()->Receive(kInvalidStartHandle);
697   EXPECT_PACKET_OUT(kExpected2);
698   fake_chan()->Receive(kInvalidEndHandle);
699 }
700 
TEST_F(ServerTest,ReadByGroupTypeAttributeNotFound)701 TEST_F(ServerTest, ReadByGroupTypeAttributeNotFound) {
702   // clang-format off
703   const StaticByteBuffer kRequest(
704       0x10,        // opcode: read by group type
705       0x01, 0x00,  // start: 0x0001
706       0xFF, 0xFF,  // end: 0xFFFF
707       0x00, 0x28   // group type: 0x2800 (primary service)
708   );
709 
710   const StaticByteBuffer kExpected(
711       0x01,        // opcode: error response
712       0x10,        // request: read by group type
713       0x01, 0x00,  // handle: 0x0001 (start handle in request)
714       0x0A         // error: Attribute not found
715   );
716   // clang-format on
717 
718   // Database is empty.
719   EXPECT_PACKET_OUT(kExpected);
720   fake_chan()->Receive(kRequest);
721 
722   // Group type does not match.
723   db()->NewGrouping(types::kSecondaryService, 0, kTestValue1)->set_active(true);
724   EXPECT_PACKET_OUT(kExpected);
725   fake_chan()->Receive(kRequest);
726 }
727 
TEST_F(ServerTest,ReadByGroupTypeSingle)728 TEST_F(ServerTest, ReadByGroupTypeSingle) {
729   const StaticByteBuffer kTestValue('t', 'e', 's', 't');
730 
731   // Start: 1, end: 2
732   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue);
733   grp->AddAttribute(
734       UUID(), att::AccessRequirements(), att::AccessRequirements());
735   grp->set_active(true);
736 
737   // clang-format off
738   const StaticByteBuffer kRequest(
739       0x10,        // opcode: read by group type
740       0x01, 0x00,  // start: 0x0001
741       0xFF, 0xFF,  // end: 0xFFFF
742       0x00, 0x28   // group type: 0x2800 (primary service)
743   );
744 
745   const StaticByteBuffer kExpected(
746       0x11,               // opcode: read by group type response
747       0x08,               // length: 8 (strlen("test") + 4)
748       0x01, 0x00,         // start: 0x0001
749       0x02, 0x00,         // end: 0x0002
750       't', 'e', 's', 't'  // value: "test"
751   );
752   // clang-format on
753 
754   EXPECT_PACKET_OUT(kExpected);
755   fake_chan()->Receive(kRequest);
756 }
757 
TEST_F(ServerTest,ReadByGroupTypeSingle128)758 TEST_F(ServerTest, ReadByGroupTypeSingle128) {
759   const StaticByteBuffer kTestValue('t', 'e', 's', 't');
760 
761   // Start: 1, end: 2
762   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue);
763   grp->AddAttribute(
764       UUID(), att::AccessRequirements(), att::AccessRequirements());
765   grp->set_active(true);
766 
767   // clang-format off
768   const StaticByteBuffer kRequest(
769       0x10,        // opcode: read by group type
770       0x01, 0x00,  // start: 0x0001
771       0xFF, 0xFF,  // end: 0xFFFF
772 
773       // group type: 00002800-0000-1000-8000-00805F9B34FB (primary service)
774       0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
775       0x00, 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00);
776 
777   const StaticByteBuffer kExpected(
778       0x11,               // opcode: read by group type response
779       0x08,               // length: 8 (strlen("test") + 4)
780       0x01, 0x00,         // start: 0x0001
781       0x02, 0x00,         // end: 0x0002
782       't', 'e', 's', 't'  // value: "test"
783   );
784   // clang-format on
785 
786   EXPECT_PACKET_OUT(kExpected);
787   fake_chan()->Receive(kRequest);
788 }
789 
TEST_F(ServerTest,ReadByGroupTypeSingleTruncated)790 TEST_F(ServerTest, ReadByGroupTypeSingleTruncated) {
791   const StaticByteBuffer kTestValue('t', 'e', 's', 't');
792 
793   // Start: 1, end: 1
794   auto* grp = db()->NewGrouping(types::kPrimaryService, 0, kTestValue);
795   grp->set_active(true);
796 
797   // clang-format off
798   const StaticByteBuffer kRequest(
799       0x10,        // opcode: read by group type
800       0x01, 0x00,  // start: 0x0001
801       0xFF, 0xFF,  // end: 0xFFFF
802       0x00, 0x28   // group type: 0x2800 (primary service)
803   );
804 
805   const StaticByteBuffer kExpected(
806       0x11,        // opcode: read by group type response
807       0x06,        // length: 6 (strlen("te") + 4)
808       0x01, 0x00,  // start: 0x0001
809       0x01, 0x00,  // end: 0x0001
810       't', 'e'     // value: "te"
811   );
812   // clang-format on
813 
814   // Force the MTU to exactly fit |kExpected| which partially contains
815   // |kTestValue|.
816   att()->set_mtu(kExpected.size());
817 
818   EXPECT_PACKET_OUT(kExpected);
819   fake_chan()->Receive(kRequest);
820 }
821 
TEST_F(ServerTest,ReadByGroupTypeMultipleSameValueSize)822 TEST_F(ServerTest, ReadByGroupTypeMultipleSameValueSize) {
823   // Start: 1, end: 1
824   db()->NewGrouping(types::kPrimaryService, 0, kTestValue1)->set_active(true);
825 
826   // Start: 2, end: 2
827   auto* grp2 = db()->NewGrouping(types::kPrimaryService, 0, kTestValue2);
828   grp2->set_active(true);
829 
830   // Start: 3, end: 3
831   db()->NewGrouping(types::kSecondaryService, 0, kTestValue3)->set_active(true);
832 
833   // Start: 4, end: 4
834   db()->NewGrouping(types::kPrimaryService, 0, kTestValue3)->set_active(true);
835 
836   // Start: 5, end: 5
837   db()->NewGrouping(types::kPrimaryService, 0, kTestValue4)->set_active(true);
838 
839   // clang-format off
840   const StaticByteBuffer kRequest1(
841       0x10,        // opcode: read by group type
842       0x01, 0x00,  // start: 0x0001
843       0xFF, 0xFF,  // end: 0xFFFF
844       0x00, 0x28   // group type: 0x2800 (primary service)
845   );
846 
847   const StaticByteBuffer kExpected1(
848       0x11,           // opcode: read by group type response
849       0x07,           // length: 7 (strlen("foo") + 4)
850       0x01, 0x00,     // start: 0x0001
851       0x01, 0x00,     // end: 0x0001
852       'f', 'o', 'o',  // value: "foo"
853       0x02, 0x00,     // start: 0x0002
854       0x02, 0x00,     // end: 0x0002
855       'b', 'a', 'r',  // value: "bar"
856       0x04, 0x00,     // start: 0x0004
857       0x04, 0x00,     // end: 0x0004
858       'b', 'a', 'z'   // value: "baz"
859   );
860   // clang-format on
861 
862   // Set the MTU to be one byte too short to include the 5th attribute group.
863   // The 3rd group is omitted as its group type does not match.
864   att()->set_mtu(kExpected1.size() + 6);
865 
866   EXPECT_PACKET_OUT(kExpected1);
867   fake_chan()->Receive(kRequest1);
868 
869   // Search a narrower range. Only two groups should be returned even with room
870   // in MTU.
871   // clang-format off
872   const StaticByteBuffer kRequest2(
873       0x10,        // opcode: read by group type
874       0x02, 0x00,  // start: 0x0002
875       0x04, 0x00,  // end: 0x0004
876       0x00, 0x28   // group type: 0x2800 (primary service)
877   );
878 
879   const StaticByteBuffer kExpected2(
880       0x11,           // opcode: read by group type response
881       0x07,           // length: 7 (strlen("foo") + 4)
882       0x02, 0x00,     // start: 0x0002
883       0x02, 0x00,     // end: 0x0002
884       'b', 'a', 'r',  // value: "bar"
885       0x04, 0x00,     // start: 0x0004
886       0x04, 0x00,     // end: 0x0004
887       'b', 'a', 'z'   // value: "baz"
888   );
889   // clang-format on
890 
891   EXPECT_PACKET_OUT(kExpected2);
892   fake_chan()->Receive(kRequest2);
893 
894   // Make the second group inactive. It should get omitted.
895   // clang-format off
896   const StaticByteBuffer kExpected3(
897       0x11,           // opcode: read by group type response
898       0x07,           // length: 7 (strlen("foo") + 4)
899       0x04, 0x00,     // start: 0x0004
900       0x04, 0x00,     // end: 0x0004
901       'b', 'a', 'z'   // value: "baz"
902   );
903   // clang-format on
904 
905   grp2->set_active(false);
906   EXPECT_PACKET_OUT(kExpected3);
907   fake_chan()->Receive(kRequest2);
908 }
909 
910 // The responses should only include 1 value because the next value has a
911 // different length.
TEST_F(ServerTest,ReadByGroupTypeMultipleVaryingLengths)912 TEST_F(ServerTest, ReadByGroupTypeMultipleVaryingLengths) {
913   // Start: 1, end: 1
914   db()->NewGrouping(types::kPrimaryService, 0, kTestValue1)->set_active(true);
915   // Start: 2, end: 2
916   db()->NewGrouping(types::kPrimaryService, 0, kTestValueLong)
917       ->set_active(true);
918   // Start: 3, end: 3
919   db()->NewGrouping(types::kPrimaryService, 0, kTestValue1)->set_active(true);
920 
921   // clang-format off
922   const StaticByteBuffer kRequest1(
923       0x10,        // opcode: read by group type
924       0x01, 0x00,  // start: 0x0001
925       0xFF, 0xFF,  // end: 0xFFFF
926       0x00, 0x28   // group type: 0x2800 (primary service)
927   );
928 
929   const StaticByteBuffer kExpected1(
930       0x11,           // opcode: read by group type response
931       0x07,           // length: 7 (strlen("foo") + 4)
932       0x01, 0x00,     // start: 0x0001
933       0x01, 0x00,     // end: 0x0001
934       'f', 'o', 'o'  // value: "foo"
935   );
936 
937   const StaticByteBuffer kRequest2(
938       0x10,        // opcode: read by group type
939       0x02, 0x00,  // start: 0x0002
940       0xFF, 0xFF,  // end: 0xFFFF
941       0x00, 0x28   // group type: 0x2800 (primary service)
942   );
943 
944   const StaticByteBuffer kExpected2(
945       0x11,               // opcode: read by group type response
946       0x08,               // length: 8 (strlen("long") + 4)
947       0x02, 0x00,         // start: 0x0002
948       0x02, 0x00,         // end: 0x0002
949       'l', 'o', 'n', 'g'  // value
950   );
951 
952   const StaticByteBuffer kRequest3(
953       0x10,        // opcode: read by group type
954       0x03, 0x00,  // start: 0x0003
955       0xFF, 0xFF,  // end: 0xFFFF
956       0x00, 0x28   // group type: 0x2800 (primary service)
957   );
958 
959   const StaticByteBuffer kExpected3(
960       0x11,           // opcode: read by group type response
961       0x07,           // length: 7 (strlen("foo") + 4)
962       0x03, 0x00,     // start: 0x0003
963       0x03, 0x00,     // end: 0x0003
964       'f', 'o', 'o'  // value: "foo"
965   );
966   // clang-format on
967 
968   EXPECT_PACKET_OUT(kExpected1);
969   fake_chan()->Receive(kRequest1);
970   EXPECT_PACKET_OUT(kExpected2);
971   fake_chan()->Receive(kRequest2);
972   EXPECT_PACKET_OUT(kExpected3);
973   fake_chan()->Receive(kRequest3);
974 }
975 
TEST_F(ServerTest,ReadByTypeInvalidPDU)976 TEST_F(ServerTest, ReadByTypeInvalidPDU) {
977   // Just opcode
978   // clang-format off
979   const StaticByteBuffer kInvalidPDU(0x08);
980   const StaticByteBuffer kExpected(
981       0x01,        // opcode: error response
982       0x08,        // request: read by type
983       0x00, 0x00,  // handle: 0
984       0x04         // error: Invalid PDU
985   );
986   // clang-format on
987 
988   EXPECT_PACKET_OUT(kExpected);
989   fake_chan()->Receive(kInvalidPDU);
990 }
991 
TEST_F(ServerTest,ReadByTypeInvalidHandle)992 TEST_F(ServerTest, ReadByTypeInvalidHandle) {
993   // Start handle is 0
994   // clang-format off
995   const StaticByteBuffer kInvalidStartHandle(
996       0x08,        // opcode: read by type
997       0x00, 0x00,  // start: 0x0000
998       0xFF, 0xFF,  // end: 0xFFFF
999       0x00, 0x28   // group type: 0x2800 (primary service)
1000   );
1001 
1002   const StaticByteBuffer kExpected1(
1003       0x01,        // opcode: error response
1004       0x08,        // request: read by type
1005       0x00, 0x00,  // handle: 0x0000 (start handle in request)
1006       0x01         // error: Invalid handle
1007   );
1008 
1009   // End handle is smaller than start handle
1010   const StaticByteBuffer kInvalidEndHandle(
1011       0x08,        // opcode: read by type
1012       0x02, 0x00,  // start: 0x0002
1013       0x01, 0x00,  // end: 0x0001
1014       0x00, 0x28   // group type: 0x2800 (primary service)
1015   );
1016 
1017   const StaticByteBuffer kExpected2(
1018       0x01,        // opcode: error response
1019       0x08,        // request: read by type
1020       0x02, 0x00,  // handle: 0x0002 (start handle in request)
1021       0x01         // error: Invalid handle
1022   );
1023   // clang-format on
1024 
1025   EXPECT_PACKET_OUT(kExpected1);
1026   fake_chan()->Receive(kInvalidStartHandle);
1027   EXPECT_PACKET_OUT(kExpected2);
1028   fake_chan()->Receive(kInvalidEndHandle);
1029 }
1030 
TEST_F(ServerTest,ReadByTypeAttributeNotFound)1031 TEST_F(ServerTest, ReadByTypeAttributeNotFound) {
1032   // clang-format off
1033   const StaticByteBuffer kRequest(
1034       0x08,        // opcode: read by type
1035       0x01, 0x00,  // start: 0x0001
1036       0xFF, 0xFF,  // end: 0xFFFF
1037       0xEF, 0xBE   // type: 0xBEEF
1038   );
1039 
1040   const StaticByteBuffer kExpected(
1041       0x01,        // opcode: error response
1042       0x08,        // request: read by type
1043       0x01, 0x00,  // handle: 0x0001 (start handle in request)
1044       0x0A         // error: Attribute not found
1045   );
1046   // clang-format on
1047 
1048   // Database is empty.
1049   EXPECT_PACKET_OUT(kExpected);
1050   fake_chan()->Receive(kRequest);
1051 
1052   // Attribute type does not match.
1053   db()->NewGrouping(types::kSecondaryService, 0, kTestValue1)->set_active(true);
1054   EXPECT_PACKET_OUT(kExpected);
1055   fake_chan()->Receive(kRequest);
1056 }
1057 
TEST_F(ServerTest,ReadByTypeDynamicValueNoHandler)1058 TEST_F(ServerTest, ReadByTypeDynamicValueNoHandler) {
1059   const StaticByteBuffer kTestValue('t', 'e', 's', 't');
1060 
1061   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue);
1062   grp->AddAttribute(
1063       kTestType16, AllowedNoSecurity(), att::AccessRequirements());
1064   grp->set_active(true);
1065 
1066   // clang-format off
1067   const StaticByteBuffer kRequest(
1068       0x08,        // opcode: read by type
1069       0x01, 0x00,  // start: 0x0001
1070       0xFF, 0xFF,  // end: 0xFFFF
1071       0xEF, 0xBE   // type: 0xBEEF
1072   );
1073 
1074   const StaticByteBuffer kExpected(
1075       0x01,        // opcode: error response
1076       0x08,        // request: read by type
1077       0x02, 0x00,  // handle: 0x0002 (the attribute causing the error)
1078       0x02         // error: Read not permitted
1079   );
1080   // clang-format on
1081 
1082   EXPECT_PACKET_OUT(kExpected);
1083   fake_chan()->Receive(kRequest);
1084 }
1085 
TEST_F(ServerTest,ReadByTypeDynamicValue)1086 TEST_F(ServerTest, ReadByTypeDynamicValue) {
1087   auto* grp = db()->NewGrouping(types::kPrimaryService, 2, kTestValue1);
1088   auto* attr = grp->AddAttribute(kTestType16, AllowedNoSecurity());
1089   attr->set_read_handler(
1090       [attr](PeerId peer_id, auto handle, uint16_t offset, auto result_cb) {
1091         EXPECT_EQ(attr->handle(), handle);
1092         EXPECT_EQ(0u, offset);
1093         result_cb(fit::ok(), StaticByteBuffer('f', 'o', 'r', 'k'));
1094       });
1095 
1096   // Add a second dynamic attribute, which should be omitted.
1097   attr = grp->AddAttribute(kTestType16, AllowedNoSecurity());
1098   grp->set_active(true);
1099 
1100   // clang-format off
1101   const StaticByteBuffer kRequest(
1102       0x08,        // opcode: read by type
1103       0x01, 0x00,  // start: 0x0001
1104       0xFF, 0xFF,  // end: 0xFFFF
1105       0xEF, 0xBE   // type: 0xBEEF
1106   );
1107 
1108   const StaticByteBuffer kExpected(
1109       0x09,               // opcode: read by type response
1110       0x06,               // length: 6 (strlen("fork") + 2)
1111       0x02, 0x00,         // handle: 0x0002
1112       'f', 'o', 'r', 'k'  // value: "fork"
1113   );
1114   // clang-format on
1115 
1116   EXPECT_PACKET_OUT(kExpected);
1117   fake_chan()->Receive(kRequest);
1118 
1119   // Assign a static value to the second attribute. It should still be omitted
1120   // as the first attribute is dynamic.
1121   attr->SetValue(kTestValue1);
1122   EXPECT_PACKET_OUT(kExpected);
1123   fake_chan()->Receive(kRequest);
1124 }
1125 
TEST_F(ServerTest,ReadByTypeDynamicValueError)1126 TEST_F(ServerTest, ReadByTypeDynamicValueError) {
1127   const StaticByteBuffer kTestValue('t', 'e', 's', 't');
1128 
1129   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue);
1130   auto* attr = grp->AddAttribute(
1131       kTestType16, AllowedNoSecurity(), att::AccessRequirements());
1132   attr->set_read_handler(
1133       [](PeerId peer_id, auto handle, uint16_t offset, auto result_cb) {
1134         result_cb(fit::error(att::ErrorCode::kUnlikelyError), BufferView());
1135       });
1136   grp->set_active(true);
1137 
1138   // clang-format off
1139   const StaticByteBuffer kRequest(
1140       0x08,        // opcode: read by type
1141       0x01, 0x00,  // start: 0x0001
1142       0xFF, 0xFF,  // end: 0xFFFF
1143       0xEF, 0xBE   // type: 0xBEEF
1144   );
1145 
1146   const StaticByteBuffer kExpected(
1147       0x01,        // opcode: error response
1148       0x08,        // request: read by type
1149       0x02, 0x00,  // handle: 0x0002 (the attribute causing the error)
1150       0x0E         // error: Unlikely error
1151   );
1152   // clang-format on
1153 
1154   EXPECT_PACKET_OUT(kExpected);
1155   fake_chan()->Receive(kRequest);
1156 }
1157 
TEST_F(ServerTest,ReadByTypeSingle)1158 TEST_F(ServerTest, ReadByTypeSingle) {
1159   const StaticByteBuffer kTestValue1('f', 'o', 'o');
1160   const StaticByteBuffer kTestValue2('t', 'e', 's', 't');
1161 
1162   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue1);
1163   grp->AddAttribute(kTestType16, AllowedNoSecurity(), att::AccessRequirements())
1164       ->SetValue(kTestValue2);
1165   grp->set_active(true);
1166 
1167   // clang-format off
1168   const StaticByteBuffer kRequest(
1169       0x08,        // opcode: read by type
1170       0x01, 0x00,  // start: 0x0001
1171       0xFF, 0xFF,  // end: 0xFFFF
1172       0xEF, 0xBE   // type: 0xBEEF
1173   );
1174 
1175   const StaticByteBuffer kExpected(
1176       0x09,               // opcode: read by type response
1177       0x06,               // length: 6 (strlen("test") + 2)
1178       0x02, 0x00,         // handle: 0x0002
1179       't', 'e', 's', 't'  // value: "test"
1180   );
1181 
1182   // clang-format on
1183 
1184   EXPECT_PACKET_OUT(kExpected);
1185   fake_chan()->Receive(kRequest);
1186 }
1187 
TEST_F(ServerTest,ReadByTypeSingle128)1188 TEST_F(ServerTest, ReadByTypeSingle128) {
1189   const StaticByteBuffer kTestValue1('f', 'o', 'o');
1190   const StaticByteBuffer kTestValue2('t', 'e', 's', 't');
1191 
1192   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue1);
1193   grp->AddAttribute(
1194          kTestType128, AllowedNoSecurity(), att::AccessRequirements())
1195       ->SetValue(kTestValue2);
1196   grp->set_active(true);
1197 
1198   // clang-format off
1199   const StaticByteBuffer kRequest(
1200       0x08,        // opcode: read by type
1201       0x01, 0x00,  // start: 0x0001
1202       0xFF, 0xFF,  // end: 0xFFFF
1203 
1204       // type: 0F0E0D0C-0B0A-0908-0706-050403020100
1205       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1206       0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F);
1207 
1208   const StaticByteBuffer kExpected(
1209       0x09,               // opcode: read by type response
1210       0x06,               // length: 6 (strlen("test") + 2)
1211       0x02, 0x00,         // handle: 0x0002
1212       't', 'e', 's', 't'  // value: "test"
1213   );
1214   // clang-format on
1215 
1216   EXPECT_PACKET_OUT(kExpected);
1217   fake_chan()->Receive(kRequest);
1218 }
1219 
TEST_F(ServerTest,ReadByTypeSingleTruncated)1220 TEST_F(ServerTest, ReadByTypeSingleTruncated) {
1221   const StaticByteBuffer kVeryLongValue(
1222       't', 'e', 's', 't', 'i', 'n', 'g', ' ', 'i', 's', ' ', 'f', 'u', 'n');
1223 
1224   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue1);
1225   grp->AddAttribute(kTestType16, AllowedNoSecurity(), att::AccessRequirements())
1226       ->SetValue(kVeryLongValue);
1227   grp->set_active(true);
1228 
1229   // clang-format off
1230   const StaticByteBuffer kRequest(
1231       0x08,        // opcode: read by type
1232       0x01, 0x00,  // start: 0x0001
1233       0xFF, 0xFF,  // end: 0xFFFF
1234       0xEF, 0xBE   // type: 0xBEEF
1235   );
1236 
1237   const StaticByteBuffer kExpected(
1238       0x09,          // opcode: read by type response
1239       0x05,          // length: 5 (strlen("tes") + 2)
1240       0x02, 0x00,    // handle: 0x0002
1241       't', 'e', 's'  // value: "tes"
1242   );
1243   // clang-format on
1244 
1245   // Force the MTU to exactly fit |kExpected| which partially contains
1246   // |kTestValue2| (the packet is crafted so that both |kRequest| and
1247   // |kExpected| fit within the MTU).
1248   att()->set_mtu(kExpected.size());
1249 
1250   EXPECT_PACKET_OUT(kExpected);
1251   fake_chan()->Receive(kRequest);
1252 }
1253 
1254 // When there are more than one matching attributes, the list should end at the
1255 // first attribute that causes an error.
TEST_F(ServerTest,ReadByTypeMultipleExcludeFirstError)1256 TEST_F(ServerTest, ReadByTypeMultipleExcludeFirstError) {
1257   // handle 1: readable
1258   auto* grp = db()->NewGrouping(kTestType16, 1, kTestValue1);
1259 
1260   // handle 2: not readable.
1261   grp->AddAttribute(kTestType16)->SetValue(kTestValue1);
1262   grp->set_active(true);
1263 
1264   // clang-format off
1265   const StaticByteBuffer kRequest(
1266       0x08,        // opcode: read by type
1267       0x01, 0x00,  // start: 0x0001
1268       0xFF, 0xFF,  // end: 0xFFFF
1269       0xEF, 0xBE   // type: 0xBEEF
1270   );
1271   const StaticByteBuffer kExpected(
1272       0x09,          // opcode: read by type response
1273       0x05,          // length: 5 (strlen("foo") + 2)
1274       0x01, 0x00,    // handle: 0x0001
1275       'f', 'o', 'o'  // value: "foo"
1276   );
1277   // clang-format on
1278 
1279   EXPECT_PACKET_OUT(kExpected);
1280   fake_chan()->Receive(kRequest);
1281 }
1282 
TEST_F(ServerTest,ReadByTypeMultipleSameValueSize)1283 TEST_F(ServerTest, ReadByTypeMultipleSameValueSize) {
1284   // handle: 1, value: foo
1285   auto* grp = db()->NewGrouping(types::kPrimaryService, 2, kTestValue1);
1286 
1287   // handle: 2, value: foo
1288   grp->AddAttribute(kTestType16, AllowedNoSecurity(), att::AccessRequirements())
1289       ->SetValue(kTestValue1);
1290 
1291   // handle: 3, value: bar
1292   grp->AddAttribute(kTestType16, AllowedNoSecurity(), att::AccessRequirements())
1293       ->SetValue(kTestValue2);
1294   grp->set_active(true);
1295 
1296   // handle: 4, value: foo (new grouping)
1297   grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue1);
1298 
1299   // handle: 5, value: baz
1300   grp->AddAttribute(kTestType16, AllowedNoSecurity(), att::AccessRequirements())
1301       ->SetValue(kTestValue3);
1302   grp->set_active(true);
1303 
1304   // clang-format off
1305   const StaticByteBuffer kRequest1(
1306       0x08,        // opcode: read by type
1307       0x01, 0x00,  // start: 0x0001
1308       0xFF, 0xFF,  // end: 0xFFFF
1309       0xEF, 0xBE   // type: 0xBEEF
1310   );
1311 
1312   const StaticByteBuffer kExpected1(
1313       0x09,           // opcode: read by type response
1314       0x05,           // length: 5 (strlen("foo") + 2)
1315       0x02, 0x00,     // handle: 0x0002
1316       'f', 'o', 'o',  // value: "foo"
1317       0x03, 0x00,     // handle: 0x0003
1318       'b', 'a', 'r',  // value: "bar"
1319       0x05, 0x00,     // handle: 0x0005
1320       'b', 'a', 'z'   // value: "baz"
1321   );
1322   // clang-format on
1323 
1324   EXPECT_PACKET_OUT(kExpected1);
1325   fake_chan()->Receive(kRequest1);
1326 
1327   // Set the MTU 1 byte too short for |kExpected1|.
1328   att()->set_mtu(kExpected1.size() - 1);
1329 
1330   // clang-format off
1331   const StaticByteBuffer kExpected2(
1332       0x09,           // opcode: read by type response
1333       0x05,           // length: 5 (strlen("foo") + 2)
1334       0x02, 0x00,     // handle: 0x0002
1335       'f', 'o', 'o',  // value: "foo"
1336       0x03, 0x00,     // handle: 0x0003
1337       'b', 'a', 'r'   // value: "bar"
1338   );
1339   // clang-format on
1340 
1341   EXPECT_PACKET_OUT(kExpected2);
1342   fake_chan()->Receive(kRequest1);
1343 
1344   // Try a different range.
1345   // clang-format off
1346   const StaticByteBuffer kRequest2(
1347       0x08,        // opcode: read by type
1348       0x03, 0x00,  // start: 0x0003
1349       0x05, 0x00,  // end: 0x0005
1350       0xEF, 0xBE   // type: 0xBEEF
1351   );
1352 
1353   const StaticByteBuffer kExpected3(
1354       0x09,           // opcode: read by type response
1355       0x05,           // length: 5 (strlen("bar") + 2)
1356       0x03, 0x00,     // handle: 0x0003
1357       'b', 'a', 'r',  // value: "bar"
1358       0x05, 0x00,     // handle: 0x0005
1359       'b', 'a', 'z'   // value: "baz"
1360   );
1361   // clang-format on
1362 
1363   EXPECT_PACKET_OUT(kExpected3);
1364   fake_chan()->Receive(kRequest2);
1365 
1366   // Make the second group inactive.
1367   grp->set_active(false);
1368 
1369   // clang-format off
1370   const StaticByteBuffer kExpected4(
1371       0x09,           // opcode: read by type response
1372       0x05,           // length: 5 (strlen("bar") + 2)
1373       0x03, 0x00,     // handle: 0x0003
1374       'b', 'a', 'r'   // value: "bar"
1375   );
1376   // clang-format on
1377 
1378   EXPECT_PACKET_OUT(kExpected4);
1379   fake_chan()->Receive(kRequest2);
1380 }
1381 
1382 // A response packet should only include consecutive attributes with the same
1383 // value size.
TEST_F(ServerTest,ReadByTypeMultipleVaryingLengths)1384 TEST_F(ServerTest, ReadByTypeMultipleVaryingLengths) {
1385   // handle: 1 - value: "foo"
1386   auto* grp = db()->NewGrouping(kTestType16, 2, kTestValue1);
1387 
1388   // handle: 2 - value: "long"
1389   grp->AddAttribute(kTestType16, AllowedNoSecurity())->SetValue(kTestValueLong);
1390 
1391   // handle: 3 - value: "foo"
1392   grp->AddAttribute(kTestType16, AllowedNoSecurity())->SetValue(kTestValue1);
1393   grp->set_active(true);
1394 
1395   // Even though we have 3 attributes with a matching type, the requests below
1396   // will always return one attribute at a time as their values have different
1397   // sizes.
1398 
1399   // clang-format off
1400   const StaticByteBuffer kRequest1(
1401       0x08,        // opcode: read by type
1402       0x01, 0x00,  // start: 0x0001
1403       0xFF, 0xFF,  // end: 0xFFFF
1404       0xEF, 0xBE   // type: 0xBEEF
1405   );
1406   const StaticByteBuffer kExpected1(
1407       0x09,          // opcode: read by type response
1408       0x05,          // length: 5 (strlen("foo") + 2)
1409       0x01, 0x00,    // handle: 0x0001
1410       'f', 'o', 'o'  // value: "foo"
1411   );
1412   const StaticByteBuffer kRequest2(
1413       0x08,        // opcode: read by type
1414       0x02, 0x00,  // start: 0x0002
1415       0xFF, 0xFF,  // end: 0xFFFF
1416       0xEF, 0xBE   // type: 0xBEEF
1417   );
1418   const StaticByteBuffer kExpected2(
1419       0x09,               // opcode: read by type response
1420       0x06,               // length: 6 (strlen("long") + 2)
1421       0x02, 0x00,         // handle: 0x0002
1422       'l', 'o', 'n', 'g'  // value: "long"
1423   );
1424   const StaticByteBuffer kRequest3(
1425       0x08,        // opcode: read by type
1426       0x03, 0x00,  // start: 0x0003
1427       0xFF, 0xFF,  // end: 0xFFFF
1428       0xEF, 0xBE   // type: 0xBEEF
1429   );
1430   const StaticByteBuffer kExpected3(
1431       0x09,          // opcode: read by type response
1432       0x05,          // length: 5 (strlen("foo") + 2)
1433       0x03, 0x00,    // handle: 0x0003
1434       'f', 'o', 'o'  // value: "foo"
1435   );
1436   // clang-format on
1437 
1438   EXPECT_PACKET_OUT(kExpected1);
1439   fake_chan()->Receive(kRequest1);
1440   EXPECT_PACKET_OUT(kExpected2);
1441   fake_chan()->Receive(kRequest2);
1442   EXPECT_PACKET_OUT(kExpected3);
1443   fake_chan()->Receive(kRequest3);
1444 }
1445 
1446 // When there are more than one matching attributes, the list should end at the
1447 // first attribute with a dynamic value.
TEST_F(ServerTest,ReadByTypeMultipleExcludeFirstDynamic)1448 TEST_F(ServerTest, ReadByTypeMultipleExcludeFirstDynamic) {
1449   // handle: 1 - value: "foo"
1450   auto* grp = db()->NewGrouping(kTestType16, 1, kTestValue1);
1451 
1452   // handle: 2 - value: dynamic
1453   grp->AddAttribute(kTestType16, AllowedNoSecurity());
1454   grp->set_active(true);
1455 
1456   // clang-format off
1457   const StaticByteBuffer kRequest(
1458       0x08,        // opcode: read by type
1459       0x01, 0x00,  // start: 0x0001
1460       0xFF, 0xFF,  // end: 0xFFFF
1461       0xEF, 0xBE   // type: 0xBEEF
1462   );
1463   const StaticByteBuffer kExpected(
1464       0x09,          // opcode: read by type response
1465       0x05,          // length: 5 (strlen("foo") + 2)
1466       0x01, 0x00,    // handle: 0x0001
1467       'f', 'o', 'o'  // value: "foo"
1468   );
1469   // clang-format on
1470 
1471   EXPECT_PACKET_OUT(kExpected);
1472   fake_chan()->Receive(kRequest);
1473 }
1474 
TEST_F(ServerTest,WriteRequestInvalidPDU)1475 TEST_F(ServerTest, WriteRequestInvalidPDU) {
1476   // Just opcode
1477   // clang-format off
1478   const StaticByteBuffer kInvalidPDU(0x12);
1479   const StaticByteBuffer kExpected(
1480       0x01,        // opcode: error response
1481       0x12,        // request: write request
1482       0x00, 0x00,  // handle: 0
1483       0x04         // error: Invalid PDU
1484   );
1485   // clang-format on
1486 
1487   EXPECT_PACKET_OUT(kExpected);
1488   fake_chan()->Receive(kInvalidPDU);
1489 }
1490 
TEST_F(ServerTest,WriteRequestInvalidHandle)1491 TEST_F(ServerTest, WriteRequestInvalidHandle) {
1492   // clang-format off
1493   const StaticByteBuffer kRequest(
1494       0x12,        // opcode: write request
1495       0x01, 0x00,  // handle: 0x0001
1496 
1497       // value: "test"
1498       't', 'e', 's', 't');
1499 
1500   const StaticByteBuffer kExpected(
1501       0x01,        // opcode: error response
1502       0x12,        // request: write request
1503       0x01, 0x00,  // handle: 0x0001
1504       0x01         // error: invalid handle
1505   );
1506   // clang-format on
1507 
1508   EXPECT_PACKET_OUT(kExpected);
1509   fake_chan()->Receive(kRequest);
1510 }
1511 
TEST_F(ServerTest,WriteRequestSecurity)1512 TEST_F(ServerTest, WriteRequestSecurity) {
1513   const StaticByteBuffer kTestValue('f', 'o', 'o');
1514   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue);
1515 
1516   // Requires encryption
1517   grp->AddAttribute(kTestType16,
1518                     att::AccessRequirements(),
1519                     att::AccessRequirements(/*encryption=*/true,
1520                                             /*authentication=*/false,
1521                                             /*authorization=*/false));
1522   grp->set_active(true);
1523 
1524   // We send two write requests:
1525   //   1. 0x0001: not writable
1526   //   2. 0x0002: writable but requires encryption
1527   //
1528   // clang-format off
1529   const StaticByteBuffer kRequest1(
1530       0x12,        // opcode: write request
1531       0x01, 0x00,  // handle: 0x0001
1532 
1533       // value: "test"
1534       't', 'e', 's', 't');
1535 
1536   const StaticByteBuffer kExpected1(
1537       0x01,        // opcode: error response
1538       0x12,        // request: write request
1539       0x01, 0x00,  // handle: 0x0001
1540       0x03         // error: write not permitted
1541   );
1542   const StaticByteBuffer kRequest2(
1543       0x12,        // opcode: write request
1544       0x02, 0x00,  // handle: 0x0002
1545 
1546       // value: "test"
1547       't', 'e', 's', 't');
1548 
1549   const StaticByteBuffer kExpected2(
1550       0x01,        // opcode: error response
1551       0x12,        // request: write request
1552       0x02, 0x00,  // handle: 0x0002
1553       0x05         // error: insufficient authentication
1554   );
1555   // clang-format on
1556 
1557   EXPECT_PACKET_OUT(kExpected1);
1558   fake_chan()->Receive(kRequest1);
1559   EXPECT_PACKET_OUT(kExpected2);
1560   fake_chan()->Receive(kRequest2);
1561 }
1562 
TEST_F(ServerTest,WriteRequestNoHandler)1563 TEST_F(ServerTest, WriteRequestNoHandler) {
1564   const StaticByteBuffer kTestValue('f', 'o', 'o');
1565   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue);
1566 
1567   grp->AddAttribute(
1568       kTestType16, att::AccessRequirements(), AllowedNoSecurity());
1569   grp->set_active(true);
1570 
1571   // clang-format off
1572   const StaticByteBuffer kRequest(
1573       0x12,        // opcode: write request
1574       0x02, 0x00,  // handle: 0x0002
1575 
1576       // value: "test"
1577       't', 'e', 's', 't');
1578 
1579   const StaticByteBuffer kExpected(
1580       0x01,        // opcode: error response
1581       0x12,        // request: write request
1582       0x02, 0x00,  // handle: 0x0002
1583       0x03         // error: write not permitted
1584   );
1585   // clang-format on
1586 
1587   EXPECT_PACKET_OUT(kExpected);
1588   fake_chan()->Receive(kRequest);
1589 }
1590 
TEST_F(ServerTest,WriteRequestError)1591 TEST_F(ServerTest, WriteRequestError) {
1592   const StaticByteBuffer kTestValue('f', 'o', 'o');
1593   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue);
1594   auto* attr = grp->AddAttribute(
1595       kTestType16, att::AccessRequirements(), AllowedNoSecurity());
1596 
1597   attr->set_write_handler([&](PeerId peer_id,
1598                               att::Handle handle,
1599                               uint16_t offset,
1600                               const auto& value,
1601                               auto result_cb) {
1602     EXPECT_EQ(kTestPeerId, peer_id);
1603     EXPECT_EQ(attr->handle(), handle);
1604     EXPECT_EQ(0u, offset);
1605     EXPECT_TRUE(ContainersEqual(StaticByteBuffer('t', 'e', 's', 't'), value));
1606 
1607     result_cb(fit::error(att::ErrorCode::kUnlikelyError));
1608   });
1609   grp->set_active(true);
1610 
1611   // clang-format off
1612   const StaticByteBuffer kRequest(
1613       0x12,        // opcode: write request
1614       0x02, 0x00,  // handle: 0x0002
1615 
1616       // value: "test"
1617       't', 'e', 's', 't');
1618 
1619   const StaticByteBuffer kExpected(
1620       0x01,        // opcode: error response
1621       0x12,        // request: write request
1622       0x02, 0x00,  // handle: 0x0002
1623       0x0E         // error: unlikely error
1624   );
1625   // clang-format on
1626 
1627   EXPECT_PACKET_OUT(kExpected);
1628   fake_chan()->Receive(kRequest);
1629 }
1630 
TEST_F(ServerTest,WriteRequestSuccess)1631 TEST_F(ServerTest, WriteRequestSuccess) {
1632   const StaticByteBuffer kTestValue('f', 'o', 'o');
1633   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue);
1634   auto* attr = grp->AddAttribute(
1635       kTestType16, att::AccessRequirements(), AllowedNoSecurity());
1636 
1637   attr->set_write_handler([&](PeerId peer_id,
1638                               att::Handle handle,
1639                               uint16_t offset,
1640                               const auto& value,
1641                               auto result_cb) {
1642     EXPECT_EQ(kTestPeerId, peer_id);
1643     EXPECT_EQ(attr->handle(), handle);
1644     EXPECT_EQ(0u, offset);
1645     EXPECT_TRUE(ContainersEqual(StaticByteBuffer('t', 'e', 's', 't'), value));
1646 
1647     result_cb(fit::ok());
1648   });
1649   grp->set_active(true);
1650 
1651   // clang-format off
1652   const StaticByteBuffer kRequest(
1653       0x12,        // opcode: write request
1654       0x02, 0x00,  // handle: 0x0002
1655 
1656       // value: "test"
1657       't', 'e', 's', 't');
1658   // clang-format on
1659 
1660   // opcode: write response
1661   const StaticByteBuffer kExpected(0x13);
1662 
1663   EXPECT_PACKET_OUT(kExpected);
1664   fake_chan()->Receive(kRequest);
1665 }
1666 
1667 // TODO(bwb): Add test cases for the error conditions involved in a Write
1668 // Command (fxbug.dev/42146420)
1669 
TEST_F(ServerTest,WriteCommandSuccess)1670 TEST_F(ServerTest, WriteCommandSuccess) {
1671   const StaticByteBuffer kTestValue('f', 'o', 'o');
1672   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue);
1673   auto* attr = grp->AddAttribute(
1674       kTestType16, att::AccessRequirements(), AllowedNoSecurity());
1675 
1676   attr->set_write_handler([&](PeerId peer_id,
1677                               att::Handle handle,
1678                               uint16_t offset,
1679                               const auto& value,
1680                               const auto& result_cb) {
1681     EXPECT_EQ(kTestPeerId, peer_id);
1682     EXPECT_EQ(attr->handle(), handle);
1683     EXPECT_EQ(0u, offset);
1684     EXPECT_TRUE(ContainersEqual(StaticByteBuffer('t', 'e', 's', 't'), value));
1685   });
1686   grp->set_active(true);
1687 
1688   // clang-format off
1689   const StaticByteBuffer kCmd(
1690       0x52,        // opcode: write command
1691       0x02, 0x00,  // handle: 0x0002
1692       't', 'e', 's', 't');
1693   // clang-format on
1694 
1695   fake_chan()->Receive(kCmd);
1696 }
1697 
TEST_F(ServerTest,ReadRequestInvalidPDU)1698 TEST_F(ServerTest, ReadRequestInvalidPDU) {
1699   // Just opcode
1700   // clang-format off
1701   const StaticByteBuffer kInvalidPDU(0x0A);
1702   const StaticByteBuffer kExpected(
1703       0x01,        // opcode: error response
1704       0x0A,        // request: read request
1705       0x00, 0x00,  // handle: 0
1706       0x04         // error: Invalid PDU
1707   );
1708   // clang-format on
1709 
1710   EXPECT_PACKET_OUT(kExpected);
1711   fake_chan()->Receive(kInvalidPDU);
1712 }
1713 
TEST_F(ServerTest,ReadRequestInvalidHandle)1714 TEST_F(ServerTest, ReadRequestInvalidHandle) {
1715   // clang-format off
1716   const StaticByteBuffer kRequest(
1717       0x0A,       // opcode: read request
1718       0x01, 0x00  // handle: 0x0001
1719   );
1720 
1721   const StaticByteBuffer kExpected(
1722       0x01,        // opcode: error response
1723       0x0A,        // request: read request
1724       0x01, 0x00,  // handle: 0x0001
1725       0x01         // error: invalid handle
1726   );
1727   // clang-format on
1728 
1729   EXPECT_PACKET_OUT(kExpected);
1730   fake_chan()->Receive(kRequest);
1731 }
1732 
TEST_F(ServerTest,ReadRequestSecurity)1733 TEST_F(ServerTest, ReadRequestSecurity) {
1734   const StaticByteBuffer kTestValue('f', 'o', 'o');
1735   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue);
1736 
1737   // Requires encryption
1738   grp->AddAttribute(kTestType16,
1739                     att::AccessRequirements(/*encryption=*/true,
1740                                             /*authentication=*/false,
1741                                             /*authorization=*/false),
1742                     att::AccessRequirements());
1743   grp->set_active(true);
1744 
1745   // clang-format off
1746   const StaticByteBuffer kRequest(
1747       0x0A,       // opcode: read request
1748       0x02, 0x00  // handle: 0x0002
1749   );
1750   const StaticByteBuffer kExpected(
1751       0x01,        // opcode: error response
1752       0x0A,        // request: read request
1753       0x02, 0x00,  // handle: 0x0002
1754       0x05         // error: insufficient authentication
1755   );
1756   // clang-format on
1757 
1758   EXPECT_PACKET_OUT(kExpected);
1759   fake_chan()->Receive(kRequest);
1760 }
1761 
TEST_F(ServerTest,ReadRequestCached)1762 TEST_F(ServerTest, ReadRequestCached) {
1763   const StaticByteBuffer kDeclValue('d', 'e', 'c', 'l');
1764   const StaticByteBuffer kTestValue('f', 'o', 'o');
1765   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kDeclValue);
1766   auto* attr = grp->AddAttribute(
1767       kTestType16, AllowedNoSecurity(), att::AccessRequirements());
1768   attr->SetValue(kTestValue);
1769   grp->set_active(true);
1770 
1771   // clang-format off
1772   const StaticByteBuffer kRequest1(
1773       0x0A,       // opcode: read request
1774       0x01, 0x00  // handle: 0x0001
1775   );
1776   const StaticByteBuffer kExpected1(
1777       0x0B,               // opcode: read response
1778       'd', 'e', 'c', 'l'  // value: kDeclValue
1779   );
1780   const StaticByteBuffer kRequest2(
1781       0x0A,       // opcode: read request
1782       0x02, 0x00  // handle: 0x0002
1783   );
1784   const StaticByteBuffer kExpected2(
1785       0x0B,          // opcode: read response
1786       'f', 'o', 'o'  // value: kTestValue
1787   );
1788   // clang-format on
1789 
1790   EXPECT_PACKET_OUT(kExpected1);
1791   fake_chan()->Receive(kRequest1);
1792   EXPECT_PACKET_OUT(kExpected2);
1793   fake_chan()->Receive(kRequest2);
1794 }
1795 
TEST_F(ServerTest,ReadRequestNoHandler)1796 TEST_F(ServerTest, ReadRequestNoHandler) {
1797   const StaticByteBuffer kTestValue('f', 'o', 'o');
1798   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue);
1799 
1800   grp->AddAttribute(
1801       kTestType16, AllowedNoSecurity(), att::AccessRequirements());
1802   grp->set_active(true);
1803 
1804   // clang-format off
1805   const StaticByteBuffer kRequest(
1806       0x0A,       // opcode: read request
1807       0x02, 0x00  // handle: 0x0002
1808   );
1809 
1810   const StaticByteBuffer kExpected(
1811       0x01,        // opcode: error response
1812       0x0A,        // request: read request
1813       0x02, 0x00,  // handle: 0x0002
1814       0x02         // error: read not permitted
1815   );
1816   // clang-format on
1817 
1818   EXPECT_PACKET_OUT(kExpected);
1819   fake_chan()->Receive(kRequest);
1820 }
1821 
TEST_F(ServerTest,ReadRequestError)1822 TEST_F(ServerTest, ReadRequestError) {
1823   const StaticByteBuffer kTestValue('f', 'o', 'o');
1824   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue);
1825   auto* attr = grp->AddAttribute(
1826       kTestType16, AllowedNoSecurity(), att::AccessRequirements());
1827   attr->set_read_handler(
1828       [&](PeerId peer_id, att::Handle handle, uint16_t offset, auto result_cb) {
1829         EXPECT_EQ(kTestPeerId, peer_id);
1830         EXPECT_EQ(attr->handle(), handle);
1831         EXPECT_EQ(0u, offset);
1832 
1833         result_cb(fit::error(att::ErrorCode::kUnlikelyError), BufferView());
1834       });
1835   grp->set_active(true);
1836 
1837   // clang-format off
1838   const StaticByteBuffer kRequest(
1839       0x0A,       // opcode: read request
1840       0x02, 0x00  // handle: 0x0002
1841   );
1842 
1843   const StaticByteBuffer kExpected(
1844       0x01,        // opcode: error response
1845       0x0A,        // request: read request
1846       0x02, 0x00,  // handle: 0x0002
1847       0x0E         // error: unlikely error
1848   );
1849   // clang-format on
1850 
1851   EXPECT_PACKET_OUT(kExpected);
1852   fake_chan()->Receive(kRequest);
1853 }
1854 
TEST_F(ServerTest,ReadBlobRequestInvalidPDU)1855 TEST_F(ServerTest, ReadBlobRequestInvalidPDU) {
1856   // Just opcode
1857   // clang-format off
1858   const StaticByteBuffer kInvalidPDU(0x0C);
1859   const StaticByteBuffer kExpected(
1860       0x01,        // opcode: error response
1861       0x0C,        // request: read blob request
1862       0x00, 0x00,  // handle: 0
1863       0x04         // error: Invalid PDU
1864   );
1865   // clang-format on
1866 
1867   EXPECT_PACKET_OUT(kExpected);
1868   fake_chan()->Receive(kInvalidPDU);
1869 }
1870 
TEST_F(ServerTest,ReadBlobRequestDynamicSuccess)1871 TEST_F(ServerTest, ReadBlobRequestDynamicSuccess) {
1872   const StaticByteBuffer kDeclValue('d', 'e', 'c', 'l');
1873   const StaticByteBuffer kTestValue('A',
1874                                     ' ',
1875                                     'V',
1876                                     'e',
1877                                     'r',
1878                                     'y',
1879                                     ' ',
1880                                     'L',
1881                                     'o',
1882                                     'n',
1883                                     'g',
1884                                     ' ',
1885                                     'D',
1886                                     'e',
1887                                     'v',
1888                                     'i',
1889                                     'c',
1890                                     'e',
1891                                     ' ',
1892                                     'N',
1893                                     'a',
1894                                     'm',
1895                                     'e',
1896                                     ' ',
1897                                     'U',
1898                                     's',
1899                                     'i',
1900                                     'n',
1901                                     'g',
1902                                     ' ',
1903                                     'A',
1904                                     ' ',
1905                                     'L',
1906                                     'o',
1907                                     'n',
1908                                     'g',
1909                                     ' ',
1910                                     'A',
1911                                     't',
1912                                     't',
1913                                     'r',
1914                                     'i',
1915                                     'b',
1916                                     'u',
1917                                     't',
1918                                     'e');
1919 
1920   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue);
1921   auto* attr = grp->AddAttribute(
1922       kTestType16, AllowedNoSecurity(), att::AccessRequirements());
1923 
1924   attr->set_read_handler(
1925       [&](PeerId peer_id, att::Handle handle, uint16_t offset, auto result_cb) {
1926         EXPECT_EQ(kTestPeerId, peer_id);
1927         EXPECT_EQ(attr->handle(), handle);
1928         EXPECT_EQ(22u, offset);
1929         result_cb(fit::ok(),
1930                   StaticByteBuffer('e',
1931                                    ' ',
1932                                    'U',
1933                                    's',
1934                                    'i',
1935                                    'n',
1936                                    'g',
1937                                    ' ',
1938                                    'A',
1939                                    ' ',
1940                                    'L',
1941                                    'o',
1942                                    'n',
1943                                    'g',
1944                                    ' ',
1945                                    'A',
1946                                    't',
1947                                    't',
1948                                    'r',
1949                                    'i',
1950                                    'b',
1951                                    'u'));
1952       });
1953   grp->set_active(true);
1954 
1955   // clang-format off
1956   const StaticByteBuffer kRequest(
1957       0x0C,       // opcode: read blob request
1958       0x02, 0x00, // handle: 0x0002
1959       0x16, 0x00  // offset: 0x0016
1960   );
1961   const StaticByteBuffer kExpected(
1962       0x0D,          // opcode: read blob response
1963       // Read Request response
1964       'e', ' ', 'U', 's', 'i', 'n', 'g', ' ', 'A', ' ', 'L',
1965       'o', 'n', 'g', ' ', 'A', 't', 't', 'r', 'i', 'b', 'u'
1966   );
1967   // clang-format on
1968 
1969   EXPECT_PACKET_OUT(kExpected);
1970   fake_chan()->Receive(kRequest);
1971 }
1972 
TEST_F(ServerTest,ReadBlobDynamicRequestError)1973 TEST_F(ServerTest, ReadBlobDynamicRequestError) {
1974   const StaticByteBuffer kTestValue('A',
1975                                     ' ',
1976                                     'V',
1977                                     'e',
1978                                     'r',
1979                                     'y',
1980                                     ' ',
1981                                     'L',
1982                                     'o',
1983                                     'n',
1984                                     'g',
1985                                     ' ',
1986                                     'D',
1987                                     'e',
1988                                     'v',
1989                                     'i',
1990                                     'c',
1991                                     'e',
1992                                     ' ',
1993                                     'N',
1994                                     'a',
1995                                     'm',
1996                                     'e',
1997                                     ' ',
1998                                     'U',
1999                                     's',
2000                                     'i',
2001                                     'n',
2002                                     'g',
2003                                     ' ',
2004                                     'A',
2005                                     ' ',
2006                                     'L',
2007                                     'o',
2008                                     'n',
2009                                     'g',
2010                                     ' ',
2011                                     'A',
2012                                     't',
2013                                     't',
2014                                     'r',
2015                                     'i',
2016                                     'b',
2017                                     'u',
2018                                     't',
2019                                     'e');
2020   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue);
2021   auto* attr = grp->AddAttribute(
2022       kTestType16, AllowedNoSecurity(), att::AccessRequirements());
2023   attr->set_read_handler(
2024       [&](PeerId peer_id, att::Handle handle, uint16_t offset, auto result_cb) {
2025         EXPECT_EQ(kTestPeerId, peer_id);
2026         EXPECT_EQ(attr->handle(), handle);
2027 
2028         result_cb(fit::error(att::ErrorCode::kUnlikelyError), BufferView());
2029       });
2030   grp->set_active(true);
2031 
2032   // clang-format off
2033   const StaticByteBuffer kRequest(
2034       0x0C,       // opcode: read blob request
2035       0x02, 0x00, // handle: 0x0002
2036       0x16, 0x00  // offset: 0x0016
2037       );
2038   const StaticByteBuffer kExpected(
2039       0x01,        // opcode: error response
2040       0x0C,        // request: read by type
2041       0x02, 0x00,  // handle: 0x0002 (the attribute causing the error)
2042       0x0E         // error: Unlikely error
2043   );
2044   // clang-format on
2045 
2046   EXPECT_PACKET_OUT(kExpected);
2047   fake_chan()->Receive(kRequest);
2048 }
2049 
TEST_F(ServerTest,ReadBlobRequestStaticSuccess)2050 TEST_F(ServerTest, ReadBlobRequestStaticSuccess) {
2051   const StaticByteBuffer kTestValue('A',
2052                                     ' ',
2053                                     'V',
2054                                     'e',
2055                                     'r',
2056                                     'y',
2057                                     ' ',
2058                                     'L',
2059                                     'o',
2060                                     'n',
2061                                     'g',
2062                                     ' ',
2063                                     'D',
2064                                     'e',
2065                                     'v',
2066                                     'i',
2067                                     'c',
2068                                     'e',
2069                                     ' ',
2070                                     'N',
2071                                     'a',
2072                                     'm',
2073                                     'e',
2074                                     ' ',
2075                                     'U',
2076                                     's',
2077                                     'i',
2078                                     'n',
2079                                     'g',
2080                                     ' ',
2081                                     'A',
2082                                     ' ',
2083                                     'L',
2084                                     'o',
2085                                     'n',
2086                                     'g',
2087                                     ' ',
2088                                     'A',
2089                                     't',
2090                                     't',
2091                                     'r',
2092                                     'i',
2093                                     'b',
2094                                     'u',
2095                                     't',
2096                                     'e');
2097 
2098   auto* grp = db()->NewGrouping(types::kPrimaryService, 0, kTestValue);
2099   grp->set_active(true);
2100 
2101   // clang-format off
2102   const StaticByteBuffer kRequest(
2103       0x0C,       // opcode: read blob request
2104       0x01, 0x00, // handle: 0x0002
2105       0x16, 0x00  // offset: 0x0016
2106   );
2107   const StaticByteBuffer kExpected(
2108       0x0D,          // opcode: read blob response
2109       // Read Request response
2110       'e', ' ', 'U', 's', 'i', 'n', 'g', ' ', 'A', ' ', 'L',
2111       'o', 'n', 'g', ' ', 'A', 't', 't', 'r', 'i', 'b', 'u'
2112   );
2113   // clang-format on
2114 
2115   EXPECT_PACKET_OUT(kExpected);
2116   fake_chan()->Receive(kRequest);
2117 }
2118 
TEST_F(ServerTest,ReadBlobRequestStaticOverflowError)2119 TEST_F(ServerTest, ReadBlobRequestStaticOverflowError) {
2120   const StaticByteBuffer kTestValue('s', 'h', 'o', 'r', 't', 'e', 'r');
2121 
2122   auto* grp = db()->NewGrouping(types::kPrimaryService, 0, kTestValue);
2123   grp->set_active(true);
2124 
2125   // clang-format off
2126   const StaticByteBuffer kRequest(
2127       0x0C,       // opcode: read blob request
2128       0x01, 0x00, // handle: 0x0001
2129       0x16, 0x10  // offset: 0x1016
2130   );
2131   const StaticByteBuffer kExpected(
2132       0x01,       // Error
2133       0x0C,       // opcode
2134       0x01, 0x00, // handle: 0x0001
2135       0x07        // InvalidOffset
2136   );
2137   // clang-format on
2138 
2139   EXPECT_PACKET_OUT(kExpected);
2140   fake_chan()->Receive(kRequest);
2141 }
2142 
TEST_F(ServerTest,ReadBlobRequestInvalidHandleError)2143 TEST_F(ServerTest, ReadBlobRequestInvalidHandleError) {
2144   const StaticByteBuffer kTestValue('A',
2145                                     ' ',
2146                                     'V',
2147                                     'e',
2148                                     'r',
2149                                     'y',
2150                                     ' ',
2151                                     'L',
2152                                     'o',
2153                                     'n',
2154                                     'g',
2155                                     ' ',
2156                                     'D',
2157                                     'e',
2158                                     'v',
2159                                     'i',
2160                                     'c',
2161                                     'e',
2162                                     ' ',
2163                                     'N',
2164                                     'a',
2165                                     'm',
2166                                     'e',
2167                                     ' ',
2168                                     'U',
2169                                     's',
2170                                     'i',
2171                                     'n',
2172                                     'g',
2173                                     ' ',
2174                                     'A',
2175                                     ' ',
2176                                     'L',
2177                                     'o',
2178                                     'n',
2179                                     'g',
2180                                     ' ',
2181                                     'A',
2182                                     't',
2183                                     't',
2184                                     'r',
2185                                     'i',
2186                                     'b',
2187                                     'u',
2188                                     't',
2189                                     'e');
2190   auto* grp = db()->NewGrouping(types::kPrimaryService, 0, kTestValue);
2191   grp->set_active(true);
2192 
2193   // clang-format off
2194   const StaticByteBuffer kRequest(
2195       0x0C,       // opcode: read blob request
2196       0x02, 0x30, // handle: 0x0002
2197       0x16, 0x00  // offset: 0x0016
2198       );
2199   const StaticByteBuffer kExpected(
2200       0x01,        // opcode: error response
2201       0x0C,        // request: read blob request
2202       0x02, 0x30,  // handle: 0x0001
2203       0x01         // error: invalid handle
2204   );
2205   // clang-format on
2206 
2207   EXPECT_PACKET_OUT(kExpected);
2208   fake_chan()->Receive(kRequest);
2209 }
2210 
TEST_F(ServerTest,ReadBlobRequestNotPermitedError)2211 TEST_F(ServerTest, ReadBlobRequestNotPermitedError) {
2212   const StaticByteBuffer kTestValue('A',
2213                                     ' ',
2214                                     'V',
2215                                     'e',
2216                                     'r',
2217                                     'y',
2218                                     ' ',
2219                                     'L',
2220                                     'o',
2221                                     'n',
2222                                     'g',
2223                                     ' ',
2224                                     'D',
2225                                     'e',
2226                                     'v',
2227                                     'i',
2228                                     'c',
2229                                     'e',
2230                                     ' ',
2231                                     'N',
2232                                     'a',
2233                                     'm',
2234                                     'e',
2235                                     ' ',
2236                                     'U',
2237                                     's',
2238                                     'i',
2239                                     'n',
2240                                     'g',
2241                                     ' ',
2242                                     'A',
2243                                     ' ',
2244                                     'L',
2245                                     'o',
2246                                     'n',
2247                                     'g',
2248                                     ' ',
2249                                     'A',
2250                                     't',
2251                                     't',
2252                                     'r',
2253                                     'i',
2254                                     'b',
2255                                     'u',
2256                                     't',
2257                                     'e');
2258   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue);
2259   auto* attr =
2260       grp->AddAttribute(kTestType16,
2261                         att::AccessRequirements(),
2262                         att::AccessRequirements(/*encryption=*/true,
2263                                                 /*authentication=*/false,
2264                                                 /*authorization=*/false));
2265   attr->set_read_handler(
2266       [&](PeerId peer_id, att::Handle handle, uint16_t offset, auto result_cb) {
2267         EXPECT_EQ(kTestPeerId, peer_id);
2268         EXPECT_EQ(attr->handle(), handle);
2269 
2270         result_cb(fit::error(att::ErrorCode::kUnlikelyError), BufferView());
2271       });
2272   grp->set_active(true);
2273 
2274   // clang-format off
2275   const StaticByteBuffer kRequest(
2276       0x0C,       // opcode: read blob request
2277       0x02, 0x00, // handle: 0x0002
2278       0x16, 0x00  // offset: 0x0016
2279       );
2280   const StaticByteBuffer kExpected(
2281       0x01,        // opcode: error response
2282       0x0C,        // request: read by type
2283       0x02, 0x00,  // handle: 0x0002 (the attribute causing the error)
2284       0x02         // error: Not Permitted
2285   );
2286   // clang-format on
2287 
2288   EXPECT_PACKET_OUT(kExpected);
2289   fake_chan()->Receive(kRequest);
2290 }
2291 
TEST_F(ServerTest,ReadBlobRequestInvalidOffsetError)2292 TEST_F(ServerTest, ReadBlobRequestInvalidOffsetError) {
2293   const StaticByteBuffer kTestValue('A',
2294                                     ' ',
2295                                     'V',
2296                                     'e',
2297                                     'r',
2298                                     'y',
2299                                     ' ',
2300                                     'L',
2301                                     'o',
2302                                     'n',
2303                                     'g',
2304                                     ' ',
2305                                     'D',
2306                                     'e',
2307                                     'v',
2308                                     'i',
2309                                     'c',
2310                                     'e',
2311                                     ' ',
2312                                     'N',
2313                                     'a',
2314                                     'm',
2315                                     'e',
2316                                     ' ',
2317                                     'U',
2318                                     's',
2319                                     'i',
2320                                     'n',
2321                                     'g',
2322                                     ' ',
2323                                     'A',
2324                                     ' ',
2325                                     'L',
2326                                     'o',
2327                                     'n',
2328                                     'g',
2329                                     ' ',
2330                                     'A',
2331                                     't',
2332                                     't',
2333                                     'r',
2334                                     'i',
2335                                     'b',
2336                                     'u',
2337                                     't',
2338                                     'e');
2339 
2340   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue);
2341   auto* attr = grp->AddAttribute(
2342       kTestType16, AllowedNoSecurity(), att::AccessRequirements());
2343   attr->set_read_handler(
2344       [&](PeerId peer_id, att::Handle handle, uint16_t offset, auto result_cb) {
2345         EXPECT_EQ(kTestPeerId, peer_id);
2346         EXPECT_EQ(attr->handle(), handle);
2347 
2348         result_cb(fit::error(att::ErrorCode::kInvalidOffset), BufferView());
2349       });
2350   grp->set_active(true);
2351 
2352   // clang-format off
2353   const StaticByteBuffer kRequest(
2354       0x0C,       // opcode: read blob request
2355       0x02, 0x00, // handle: 0x0002
2356       0x16, 0x40  // offset: 0x4016
2357       );
2358   const StaticByteBuffer kExpected(
2359       0x01,        // opcode: error response
2360       0x0C,        // request: read by type
2361       0x02, 0x00,  // handle: 0x0002 (the attribute causing the error)
2362       0x07         // error: Invalid Offset Error
2363   );
2364   // clang-format on
2365 
2366   EXPECT_PACKET_OUT(kExpected);
2367   fake_chan()->Receive(kRequest);
2368 }
2369 
TEST_F(ServerTest,ReadRequestSuccess)2370 TEST_F(ServerTest, ReadRequestSuccess) {
2371   const StaticByteBuffer kDeclValue('d', 'e', 'c', 'l');
2372   const StaticByteBuffer kTestValue('f', 'o', 'o');
2373   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue);
2374   auto* attr = grp->AddAttribute(
2375       kTestType16, AllowedNoSecurity(), att::AccessRequirements());
2376   attr->set_read_handler(
2377       [&](PeerId peer_id, att::Handle handle, uint16_t offset, auto result_cb) {
2378         EXPECT_EQ(kTestPeerId, peer_id);
2379         EXPECT_EQ(attr->handle(), handle);
2380         EXPECT_EQ(0u, offset);
2381 
2382         result_cb(fit::ok(), kTestValue);
2383       });
2384   grp->set_active(true);
2385 
2386   // clang-format off
2387   const StaticByteBuffer kRequest(
2388       0x0A,       // opcode: read request
2389       0x02, 0x00  // handle: 0x0002
2390   );
2391   const StaticByteBuffer kExpected(
2392       0x0B,          // opcode: read response
2393       'f', 'o', 'o'  // value: kTestValue
2394   );
2395   // clang-format on
2396 
2397   EXPECT_PACKET_OUT(kExpected);
2398   fake_chan()->Receive(kRequest);
2399 }
2400 
TEST_F(ServerTest,PrepareWriteRequestInvalidPDU)2401 TEST_F(ServerTest, PrepareWriteRequestInvalidPDU) {
2402   // Payload is one byte too short.
2403   // clang-format off
2404   const StaticByteBuffer kInvalidPDU(
2405       0x16,        // opcode: prepare write request
2406       0x01, 0x00,  // handle: 0x0001
2407       0x01         // offset (should be 2 bytes).
2408   );
2409   const StaticByteBuffer kExpected(
2410       0x01,        // opcode: error response
2411       0x16,        // request: prepare write request
2412       0x00, 0x00,  // handle: 0
2413       0x04         // error: Invalid PDU
2414   );
2415   // clang-format on
2416 
2417   EXPECT_PACKET_OUT(kExpected);
2418   fake_chan()->Receive(kInvalidPDU);
2419 }
2420 
TEST_F(ServerTest,PrepareWriteRequestInvalidHandle)2421 TEST_F(ServerTest, PrepareWriteRequestInvalidHandle) {
2422   // clang-format off
2423   const StaticByteBuffer kRequest(
2424       0x16,              // opcode: prepare write request
2425       0x01, 0x00,         // handle: 0x0001
2426       0x00, 0x00,         // offset: 0
2427       't', 'e', 's', 't'  // value: "test"
2428   );
2429   const StaticByteBuffer kResponse(
2430       0x01,        // opcode: error response
2431       0x16,        // request: prepare write request
2432       0x01, 0x00,  // handle: 0x0001
2433       0x01         // error: invalid handle
2434   );
2435   // clang-format on
2436 
2437   EXPECT_PACKET_OUT(kResponse);
2438   fake_chan()->Receive(kRequest);
2439 }
2440 
TEST_F(ServerTest,PrepareWriteRequestSucceeds)2441 TEST_F(ServerTest, PrepareWriteRequestSucceeds) {
2442   const StaticByteBuffer kTestValue('f', 'o', 'o');
2443   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue);
2444 
2445   // No security requirement
2446   auto* attr =
2447       grp->AddAttribute(kTestType16,
2448                         att::AccessRequirements(),
2449                         att::AccessRequirements(/*encryption=*/false,
2450                                                 /*authentication=*/false,
2451                                                 /*authorization=*/false));
2452   grp->set_active(true);
2453 
2454   int write_count = 0;
2455   attr->set_write_handler(
2456       [&](PeerId, att::Handle, uint16_t, const auto&, const auto&) {
2457         write_count++;
2458       });
2459 
2460   ASSERT_EQ(0x0002, attr->handle());
2461 
2462   // clang-format off
2463   const StaticByteBuffer kRequest(
2464       0x16,              // opcode: prepare write request
2465       0x02, 0x00,         // handle: 0x0002
2466       0x00, 0x00,         // offset: 0
2467       't', 'e', 's', 't'  // value: "test"
2468   );
2469   const StaticByteBuffer kResponse(
2470       0x17,              // opcode: prepare write response
2471       0x02, 0x00,         // handle: 0x0002
2472       0x00, 0x00,         // offset: 0
2473       't', 'e', 's', 't'  // value: "test"
2474   );
2475   // clang-format on
2476 
2477   EXPECT_PACKET_OUT(kResponse);
2478   fake_chan()->Receive(kRequest);
2479   // The attribute should not have been written yet.
2480   EXPECT_EQ(0, write_count);
2481 }
2482 
TEST_F(ServerTest,PrepareWriteRequestPrepareQueueFull)2483 TEST_F(ServerTest, PrepareWriteRequestPrepareQueueFull) {
2484   const StaticByteBuffer kTestValue('f', 'o', 'o');
2485   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue);
2486 
2487   // No security requirement
2488   const auto* attr =
2489       grp->AddAttribute(kTestType16,
2490                         att::AccessRequirements(),
2491                         att::AccessRequirements(/*encryption=*/false,
2492                                                 /*authentication=*/false,
2493                                                 /*authorization=*/false));
2494   grp->set_active(true);
2495 
2496   ASSERT_EQ(0x0002, attr->handle());
2497 
2498   // clang-format off
2499   const StaticByteBuffer kRequest(
2500       0x16,              // opcode: prepare write request
2501       0x02, 0x00,         // handle: 0x0002
2502       0x00, 0x00,         // offset: 0
2503       't', 'e', 's', 't'  // value: "test"
2504   );
2505   const StaticByteBuffer kSuccessResponse(
2506       0x17,              // opcode: prepare write response
2507       0x02, 0x00,         // handle: 0x0002
2508       0x00, 0x00,         // offset: 0
2509       't', 'e', 's', 't'  // value: "test"
2510   );
2511   const StaticByteBuffer kErrorResponse(
2512       0x01,        // opcode: error response
2513       0x16,        // request: prepare write request
2514       0x02, 0x00,  // handle: 0x0002
2515       0x09         // error: prepare queue full
2516   );
2517   // clang-format on
2518 
2519   // Write requests should succeed until capacity is filled.
2520   for (unsigned i = 0; i < att::kPrepareQueueMaxCapacity; i++) {
2521     EXPECT_PACKET_OUT(kSuccessResponse);
2522     fake_chan()->Receive(kRequest);
2523     ASSERT_TRUE(AllExpectedPacketsSent())
2524         << "Unexpected failure at attempt: " << i;
2525   }
2526 
2527   // The next request should fail with a capacity error.
2528   EXPECT_PACKET_OUT(kErrorResponse);
2529   fake_chan()->Receive(kRequest);
2530 }
2531 
TEST_F(ServerTest,ExecuteWriteMalformedPayload)2532 TEST_F(ServerTest, ExecuteWriteMalformedPayload) {
2533   // Payload is one byte too short.
2534   // clang-format off
2535   const StaticByteBuffer kInvalidPDU(
2536       0x18  // opcode: execute write request
2537   );
2538   const StaticByteBuffer kExpected(
2539       0x01,        // opcode: error response
2540       0x18,        // request: execute write request
2541       0x00, 0x00,  // handle: 0
2542       0x04         // error: Invalid PDU
2543   );
2544   // clang-format on
2545 
2546   EXPECT_PACKET_OUT(kExpected);
2547   fake_chan()->Receive(kInvalidPDU);
2548 }
2549 
TEST_F(ServerTest,ExecuteWriteInvalidFlag)2550 TEST_F(ServerTest, ExecuteWriteInvalidFlag) {
2551   // Payload is one byte too short.
2552   // clang-format off
2553   const StaticByteBuffer kInvalidPDU(
2554       0x18,  // opcode: execute write request
2555       0xFF   // flag: invalid
2556   );
2557   const StaticByteBuffer kExpected(
2558       0x01,        // opcode: error response
2559       0x18,        // request: execute write request
2560       0x00, 0x00,  // handle: 0
2561       0x04         // error: Invalid PDU
2562   );
2563   // clang-format on
2564 
2565   EXPECT_PACKET_OUT(kExpected);
2566   fake_chan()->Receive(kInvalidPDU);
2567 }
2568 
2569 // Tests that an "execute write request" without any prepared writes returns
2570 // success without writing to any attributes.
TEST_F(ServerTest,ExecuteWriteQueueEmpty)2571 TEST_F(ServerTest, ExecuteWriteQueueEmpty) {
2572   // clang-format off
2573   const StaticByteBuffer kExecute(
2574     0x18,  // opcode: execute write request
2575     0x01   // flag: "write pending"
2576   );
2577   const StaticByteBuffer kExecuteResponse(
2578     0x19  // opcode: execute write response
2579   );
2580   // clang-format on
2581 
2582   // |buffer| should contain the partial writes.
2583   EXPECT_PACKET_OUT(kExecuteResponse);
2584   fake_chan()->Receive(kExecute);
2585 }
2586 
TEST_F(ServerTest,ExecuteWriteSuccess)2587 TEST_F(ServerTest, ExecuteWriteSuccess) {
2588   StaticByteBuffer buffer('x', 'x', 'x', 'x', 'x', 'x');
2589 
2590   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue1);
2591   auto* attr = grp->AddAttribute(
2592       kTestType16, att::AccessRequirements(), AllowedNoSecurity());
2593   attr->set_write_handler([&](const auto& peer_id,
2594                               att::Handle handle,
2595                               uint16_t offset,
2596                               const auto& value,
2597                               auto result_cb) {
2598     EXPECT_EQ(kTestPeerId, peer_id);
2599     EXPECT_EQ(attr->handle(), handle);
2600 
2601     // Write the contents into |buffer|.
2602     buffer.Write(value, offset);
2603     result_cb(fit::ok());
2604   });
2605   grp->set_active(true);
2606 
2607   // Prepare two partial writes of the string "hello!".
2608   // clang-format off
2609   const StaticByteBuffer kPrepare1(
2610     0x016,              // opcode: prepare write request
2611     0x02, 0x00,         // handle: 0x0002
2612     0x00, 0x00,         // offset: 0
2613     'h', 'e', 'l', 'l'  // value: "hell"
2614   );
2615   const StaticByteBuffer kPrepareResponse1(
2616     0x017,              // opcode: prepare write response
2617     0x02, 0x00,         // handle: 0x0002
2618     0x00, 0x00,         // offset: 0
2619     'h', 'e', 'l', 'l'  // value: "hell"
2620   );
2621   const StaticByteBuffer kPrepare2(
2622     0x016,              // opcode: prepare write request
2623     0x02, 0x00,         // handle: 0x0002
2624     0x04, 0x00,         // offset: 4
2625     'o', '!'            // value: "o!"
2626   );
2627   const StaticByteBuffer kPrepareResponse2(
2628     0x017,              // opcode: prepare write response
2629     0x02, 0x00,         // handle: 0x0002
2630     0x04, 0x00,         // offset: 4
2631     'o', '!'            // value: "o!"
2632   );
2633 
2634   // Add an overlapping write that partial overwrites data from previous
2635   // payloads.
2636   const StaticByteBuffer kPrepare3(
2637     0x016,              // opcode: prepare write request
2638     0x02, 0x00,         // handle: 0x0002
2639     0x02, 0x00,         // offset: 2
2640     'r', 'p', '?'       // value: "rp?"
2641   );
2642   const StaticByteBuffer kPrepareResponse3(
2643     0x017,              // opcode: prepare write response
2644     0x02, 0x00,         // handle: 0x0002
2645     0x02, 0x00,         // offset: 2
2646     'r', 'p', '?'       // value: "rp?"
2647   );
2648 
2649   // clang-format on
2650 
2651   EXPECT_PACKET_OUT(kPrepareResponse1);
2652   fake_chan()->Receive(kPrepare1);
2653   EXPECT_PACKET_OUT(kPrepareResponse2);
2654   fake_chan()->Receive(kPrepare2);
2655   EXPECT_PACKET_OUT(kPrepareResponse3);
2656   fake_chan()->Receive(kPrepare3);
2657 
2658   // The writes should not be committed yet.
2659   EXPECT_EQ("xxxxxx", buffer.AsString());
2660 
2661   // clang-format off
2662   const StaticByteBuffer kExecute(
2663     0x18,  // opcode: execute write request
2664     0x01   // flag: "write pending"
2665   );
2666   const StaticByteBuffer kExecuteResponse(
2667     0x19  // opcode: execute write response
2668   );
2669   // clang-format on
2670 
2671   // |buffer| should contain the partial writes.
2672   EXPECT_PACKET_OUT(kExecuteResponse);
2673   fake_chan()->Receive(kExecute);
2674   EXPECT_EQ("herp?!", buffer.AsString());
2675 }
2676 
2677 // Tests that the rest of the queue is dropped if a prepared write fails.
TEST_F(ServerTest,ExecuteWriteError)2678 TEST_F(ServerTest, ExecuteWriteError) {
2679   StaticByteBuffer buffer('x', 'x', 'x', 'x', 'x', 'x');
2680 
2681   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue1);
2682   auto* attr = grp->AddAttribute(
2683       kTestType16, att::AccessRequirements(), AllowedNoSecurity());
2684   attr->set_write_handler([&](const auto& peer_id,
2685                               att::Handle handle,
2686                               uint16_t offset,
2687                               const auto& value,
2688                               auto result_cb) {
2689     EXPECT_EQ(kTestPeerId, peer_id);
2690     EXPECT_EQ(attr->handle(), handle);
2691 
2692     // Make the write to non-zero offsets fail (this corresponds to the second
2693     // partial write we prepare below.
2694     if (offset) {
2695       result_cb(fit::error(att::ErrorCode::kUnlikelyError));
2696     } else {
2697       buffer.Write(value);
2698       result_cb(fit::ok());
2699     }
2700   });
2701   grp->set_active(true);
2702 
2703   // Prepare two partial writes of the string "hello!".
2704   // clang-format off
2705   const StaticByteBuffer kPrepare1(
2706     0x016,              // opcode: prepare write request
2707     0x02, 0x00,         // handle: 0x0002
2708     0x00, 0x00,         // offset: 0
2709     'h', 'e', 'l', 'l'  // value: "hell"
2710   );
2711   const StaticByteBuffer kPrepareResponse1(
2712     0x017,              // opcode: prepare write response
2713     0x02, 0x00,         // handle: 0x0002
2714     0x00, 0x00,         // offset: 0
2715     'h', 'e', 'l', 'l'  // value: "hell"
2716   );
2717   const StaticByteBuffer kPrepare2(
2718     0x016,              // opcode: prepare write request
2719     0x02, 0x00,         // handle: 0x0002
2720     0x04, 0x00,         // offset: 4
2721     'o', '!'            // value: "o!"
2722   );
2723   const StaticByteBuffer kPrepareResponse2(
2724     0x017,              // opcode: prepare write response
2725     0x02, 0x00,         // handle: 0x0002
2726     0x04, 0x00,         // offset: 4
2727     'o', '!'            // value: "o!"
2728   );
2729   // clang-format on
2730 
2731   EXPECT_PACKET_OUT(kPrepareResponse1);
2732   fake_chan()->Receive(kPrepare1);
2733   EXPECT_PACKET_OUT(kPrepareResponse2);
2734   fake_chan()->Receive(kPrepare2);
2735 
2736   // The writes should not be committed yet.
2737   EXPECT_EQ("xxxxxx", buffer.AsString());
2738 
2739   // clang-format off
2740   const StaticByteBuffer kExecute(
2741     0x18,  // opcode: execute write request
2742     0x01   // flag: "write pending"
2743   );
2744   const StaticByteBuffer kExecuteResponse(
2745     0x01,        // opcode: error response
2746     0x18,        // request: execute write request
2747     0x02, 0x00,  // handle: 2 (the attribute in error)
2748     0x0E         // error: Unlikely Error (returned by callback above).
2749   );
2750   // clang-format on
2751 
2752   // Only the first partial write should have gone through as the second one
2753   // is expected to fail.
2754   EXPECT_PACKET_OUT(kExecuteResponse);
2755   fake_chan()->Receive(kExecute);
2756   EXPECT_EQ("hellxx", buffer.AsString());
2757 }
2758 
TEST_F(ServerTest,ExecuteWriteAbort)2759 TEST_F(ServerTest, ExecuteWriteAbort) {
2760   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue1);
2761   // |attr| has handle "2".
2762   auto* attr = grp->AddAttribute(
2763       kTestType16, att::AccessRequirements(), AllowedNoSecurity());
2764 
2765   int write_count = 0;
2766   attr->set_write_handler([&](const auto& peer_id,
2767                               att::Handle handle,
2768                               uint16_t offset,
2769                               const auto& value,
2770                               auto result_cb) {
2771     write_count++;
2772 
2773     EXPECT_EQ(kTestPeerId, peer_id);
2774     EXPECT_EQ(attr->handle(), handle);
2775     EXPECT_EQ(0u, offset);
2776     EXPECT_TRUE(ContainersEqual(StaticByteBuffer('l', 'o', 'l'), value));
2777     result_cb(fit::ok());
2778   });
2779   grp->set_active(true);
2780 
2781   // clang-format off
2782   const StaticByteBuffer kPrepareToAbort(
2783     0x016,              // opcode: prepare write request
2784     0x02, 0x00,         // handle: 0x0002
2785     0x00, 0x00,         // offset: 0
2786     't', 'e', 's', 't'  // value: "test"
2787   );
2788   const StaticByteBuffer kPrepareToAbortResponse(
2789     0x017,              // opcode: prepare write response
2790     0x02, 0x00,         // handle: 0x0002
2791     0x00, 0x00,         // offset: 0
2792     't', 'e', 's', 't'  // value: "test"
2793   );
2794   // clang-format on
2795 
2796   // Prepare writes. These should get committed right away.
2797   EXPECT_PACKET_OUT(kPrepareToAbortResponse);
2798   fake_chan()->Receive(kPrepareToAbort);
2799   EXPECT_PACKET_OUT(kPrepareToAbortResponse);
2800   fake_chan()->Receive(kPrepareToAbort);
2801   EXPECT_PACKET_OUT(kPrepareToAbortResponse);
2802   fake_chan()->Receive(kPrepareToAbort);
2803   EXPECT_PACKET_OUT(kPrepareToAbortResponse);
2804   fake_chan()->Receive(kPrepareToAbort);
2805   EXPECT_TRUE(AllExpectedPacketsSent());
2806   EXPECT_EQ(0, write_count);
2807 
2808   // Abort the writes. They should get dropped.
2809   // clang-format off
2810   const StaticByteBuffer kAbort(
2811     0x18,  // opcode: execute write request
2812     0x00   // flag: "cancel all"
2813   );
2814   const StaticByteBuffer kAbortResponse(
2815     0x19  // opcode: execute write response
2816   );
2817   // clang-format on
2818   EXPECT_PACKET_OUT(kAbortResponse);
2819   fake_chan()->Receive(kAbort);
2820   EXPECT_EQ(0, write_count);
2821 
2822   // Prepare and commit a new write request. This one should take effect without
2823   // involving the previously aborted writes.
2824   // clang-format off
2825   const StaticByteBuffer kPrepareToCommit(
2826     0x016,              // opcode: prepare write request
2827     0x02, 0x00,         // handle: 0x0002
2828     0x00, 0x00,         // offset: 0
2829     'l', 'o', 'l'       // value: "lol"
2830   );
2831   const StaticByteBuffer kPrepareToCommitResponse(
2832     0x017,              // opcode: prepare write response
2833     0x02, 0x00,         // handle: 0x0002
2834     0x00, 0x00,         // offset: 0
2835     'l', 'o', 'l'       // value: "lol"
2836   );
2837   const StaticByteBuffer kCommit(
2838     0x18,  // opcode: execute write request
2839     0x01   // flag: "write pending"
2840   );
2841   const StaticByteBuffer kCommitResponse(
2842     0x19  // opcode: execute write response
2843   );
2844   // clang-format on
2845 
2846   EXPECT_PACKET_OUT(kPrepareToCommitResponse);
2847   fake_chan()->Receive(kPrepareToCommit);
2848   EXPECT_PACKET_OUT(kCommitResponse);
2849   fake_chan()->Receive(kCommit);
2850   EXPECT_EQ(1, write_count);
2851 }
2852 
TEST_F(ServerTest,TrySendNotificationNoCccConfig)2853 TEST_F(ServerTest, TrySendNotificationNoCccConfig) {
2854   IdType svc_id =
2855       RegisterSvcWithSingleChrc(kTestSvcType, kTestChrcId, kTestChrcType);
2856   const BufferView kTestValue;
2857   server()->SendUpdate(
2858       svc_id, kTestChrcId, kTestValue, /*indicate_cb=*/nullptr);
2859 }
2860 
TEST_F(ServerTest,TrySendNotificationConfiguredForIndicationsOnly)2861 TEST_F(ServerTest, TrySendNotificationConfiguredForIndicationsOnly) {
2862   SvcIdAndChrcHandle registered = RegisterSvcWithConfiguredChrc(
2863       kTestSvcType, kTestChrcId, kTestChrcType, kCCCIndicationBit);
2864   const BufferView kTestValue;
2865   server()->SendUpdate(
2866       registered.svc_id, kTestChrcId, kTestValue, /*indicate_cb=*/nullptr);
2867 }
2868 
TEST_F(ServerTest,SendNotificationEmpty)2869 TEST_F(ServerTest, SendNotificationEmpty) {
2870   SvcIdAndChrcHandle registered =
2871       RegisterSvcWithConfiguredChrc(kTestSvcType, kTestChrcId, kTestChrcType);
2872   const BufferView kTestValue;
2873 
2874   // clang-format off
2875   const StaticByteBuffer kExpected{
2876     att::kNotification,  // Opcode
2877     // Handle of the characteristic value being notified
2878     LowerBits(registered.chrc_val_handle), UpperBits(registered.chrc_val_handle)
2879   };
2880   // clang-format on
2881 
2882   EXPECT_PACKET_OUT(kExpected);
2883   server()->SendUpdate(
2884       registered.svc_id, kTestChrcId, kTestValue, /*indicate_cb=*/nullptr);
2885 }
2886 
TEST_F(ServerTest,SendNotification)2887 TEST_F(ServerTest, SendNotification) {
2888   SvcIdAndChrcHandle registered =
2889       RegisterSvcWithConfiguredChrc(kTestSvcType, kTestChrcId, kTestChrcType);
2890   const StaticByteBuffer kTestValue('f', 'o', 'o');
2891 
2892   // clang-format off
2893   const StaticByteBuffer kExpected{
2894     att::kNotification,  // Opcode
2895     // Handle of the characteristic value being notified
2896     LowerBits(registered.chrc_val_handle), UpperBits(registered.chrc_val_handle),
2897     kTestValue[0], kTestValue[1], kTestValue[2]
2898   };
2899   // clang-format on
2900 
2901   EXPECT_PACKET_OUT(kExpected);
2902   server()->SendUpdate(registered.svc_id,
2903                        kTestChrcId,
2904                        kTestValue.view(),
2905                        /*indicate_cb=*/nullptr);
2906 }
2907 
TEST_F(ServerTest,TrySendIndicationNoCccConfig)2908 TEST_F(ServerTest, TrySendIndicationNoCccConfig) {
2909   IdType svc_id =
2910       RegisterSvcWithSingleChrc(kTestSvcType, kTestChrcId, kTestChrcType);
2911   const BufferView kTestValue;
2912 
2913   att::Result<> indicate_res = fit::ok();
2914   auto indicate_cb = [&](att::Result<> res) { indicate_res = res; };
2915 
2916   server()->SendUpdate(svc_id, kTestChrcId, kTestValue, std::move(indicate_cb));
2917   EXPECT_EQ(fit::failed(), indicate_res);
2918 }
2919 
TEST_F(ServerTest,TrySendIndicationConfiguredForNotificationsOnly)2920 TEST_F(ServerTest, TrySendIndicationConfiguredForNotificationsOnly) {
2921   SvcIdAndChrcHandle registered = RegisterSvcWithConfiguredChrc(
2922       kTestSvcType, kTestChrcId, kTestChrcType, kCCCNotificationBit);
2923   const BufferView kTestValue;
2924 
2925   att::Result<> indicate_res = fit::ok();
2926   auto indicate_cb = [&](att::Result<> res) { indicate_res = res; };
2927 
2928   server()->SendUpdate(
2929       registered.svc_id, kTestChrcId, kTestValue, std::move(indicate_cb));
2930   EXPECT_EQ(fit::failed(), indicate_res);
2931 }
2932 
TEST_F(ServerTest,SendIndicationEmpty)2933 TEST_F(ServerTest, SendIndicationEmpty) {
2934   SvcIdAndChrcHandle registered =
2935       RegisterSvcWithConfiguredChrc(kTestSvcType, kTestChrcId, kTestChrcType);
2936   const BufferView kTestValue;
2937 
2938   att::Result<> indicate_res = ToResult(HostError::kFailed);
2939   auto indicate_cb = [&](att::Result<> res) { indicate_res = res; };
2940 
2941   // clang-format off
2942   const StaticByteBuffer kExpected{
2943     att::kIndication,  // Opcode
2944     // Handle of the characteristic value being notified
2945     LowerBits(registered.chrc_val_handle), UpperBits(registered.chrc_val_handle)
2946   };
2947   // clang-format on
2948 
2949   EXPECT_PACKET_OUT(kExpected);
2950   server()->SendUpdate(
2951       registered.svc_id, kTestChrcId, kTestValue, std::move(indicate_cb));
2952   EXPECT_TRUE(AllExpectedPacketsSent());
2953 
2954   const StaticByteBuffer kIndicationConfirmation{att::kConfirmation};
2955   fake_chan()->Receive(kIndicationConfirmation);
2956   EXPECT_EQ(fit::ok(), indicate_res);
2957 }
2958 
TEST_F(ServerTest,SendIndication)2959 TEST_F(ServerTest, SendIndication) {
2960   SvcIdAndChrcHandle registered =
2961       RegisterSvcWithConfiguredChrc(kTestSvcType, kTestChrcId, kTestChrcType);
2962   const StaticByteBuffer kTestValue('f', 'o', 'o');
2963 
2964   att::Result<> indicate_res = ToResult(HostError::kFailed);
2965   auto indicate_cb = [&](att::Result<> res) { indicate_res = res; };
2966 
2967   // clang-format off
2968   const StaticByteBuffer kExpected{
2969     att::kIndication,  // Opcode
2970     // Handle of the characteristic value being notified
2971     LowerBits(registered.chrc_val_handle), UpperBits(registered.chrc_val_handle),
2972     kTestValue[0], kTestValue[1], kTestValue[2]
2973   };
2974   // clang-format on
2975 
2976   EXPECT_PACKET_OUT(kExpected);
2977   server()->SendUpdate(registered.svc_id,
2978                        kTestChrcId,
2979                        kTestValue.view(),
2980                        std::move(indicate_cb));
2981   EXPECT_TRUE(AllExpectedPacketsSent());
2982 
2983   const StaticByteBuffer kIndicationConfirmation{att::kConfirmation};
2984   fake_chan()->Receive(kIndicationConfirmation);
2985   EXPECT_EQ(fit::ok(), indicate_res);
2986 }
2987 
2988 class ServerTestSecurity : public ServerTest {
2989  protected:
InitializeAttributesForReading()2990   void InitializeAttributesForReading() {
2991     auto* grp = db()->NewGrouping(types::kPrimaryService, 4, kTestValue1);
2992 
2993     const att::AccessRequirements encryption(/*encryption=*/true,
2994                                              /*authentication=*/false,
2995                                              /*authorization=*/false);
2996     const att::AccessRequirements authentication(/*encryption=*/false,
2997                                                  /*authentication=*/true,
2998                                                  /*authorization=*/false);
2999     const att::AccessRequirements authorization(/*encryption=*/false,
3000                                                 /*authentication=*/false,
3001                                                 /*authorization=*/true);
3002 
3003     not_permitted_attr_ = grp->AddAttribute(kTestType16);
3004     encryption_required_attr_ = grp->AddAttribute(kTestType16, encryption);
3005     authentication_required_attr_ =
3006         grp->AddAttribute(kTestType16, authentication);
3007     authorization_required_attr_ =
3008         grp->AddAttribute(kTestType16, authorization);
3009 
3010     // Assigns all tests attributes a static value. Intended to be used by read
3011     // requests. (Note: assigning a static value makes an attribute
3012     // non-writable). All attributes are assigned kTestValue1 as their static
3013     // value.
3014     not_permitted_attr_->SetValue(kTestValue1);
3015     encryption_required_attr_->SetValue(kTestValue1);
3016     authentication_required_attr_->SetValue(kTestValue1);
3017     authorization_required_attr_->SetValue(kTestValue1);
3018 
3019     grp->set_active(true);
3020   }
3021 
InitializeAttributesForWriting()3022   void InitializeAttributesForWriting() {
3023     auto* grp = db()->NewGrouping(types::kPrimaryService, 4, kTestValue1);
3024 
3025     const att::AccessRequirements encryption(/*encryption=*/true,
3026                                              /*authentication=*/false,
3027                                              /*authorization=*/false);
3028     const att::AccessRequirements authentication(/*encryption=*/false,
3029                                                  /*authentication=*/true,
3030                                                  /*authorization=*/false);
3031     const att::AccessRequirements authorization(/*encryption=*/false,
3032                                                 /*authentication=*/false,
3033                                                 /*authorization=*/true);
3034 
3035     auto write_handler = [this](const auto&,
3036                                 att::Handle,
3037                                 uint16_t,
3038                                 const auto& value,
3039                                 auto responder) {
3040       write_count_++;
3041       if (responder) {
3042         responder(fit::ok());
3043       }
3044     };
3045 
3046     not_permitted_attr_ = grp->AddAttribute(kTestType16);
3047     not_permitted_attr_->set_write_handler(write_handler);
3048 
3049     encryption_required_attr_ =
3050         grp->AddAttribute(kTestType16, att::AccessRequirements(), encryption);
3051     encryption_required_attr_->set_write_handler(write_handler);
3052 
3053     authentication_required_attr_ = grp->AddAttribute(
3054         kTestType16, att::AccessRequirements(), authentication);
3055     authentication_required_attr_->set_write_handler(write_handler);
3056 
3057     authorization_required_attr_ = grp->AddAttribute(
3058         kTestType16, att::AccessRequirements(), authorization);
3059     authorization_required_attr_->set_write_handler(write_handler);
3060 
3061     grp->set_active(true);
3062   }
3063 
MakeAttError(att::OpCode request,att::Handle handle,att::ErrorCode ecode)3064   auto MakeAttError(att::OpCode request,
3065                     att::Handle handle,
3066                     att::ErrorCode ecode) {
3067     return StaticByteBuffer(0x01,     // opcode: error response
3068                             request,  // request opcode
3069                             LowerBits(handle),
3070                             UpperBits(handle),  // handle
3071                             ecode               // error code
3072     );
3073   }
3074 
3075   // Helpers for emulating the receipt of an ATT read/write request PDU and
3076   // expecting back a security error. Expects a successful response if
3077   // |expected_status| is fit::ok().
EmulateReadByTypeRequest(att::Handle handle,fit::result<att::ErrorCode> expected_status)3078   bool EmulateReadByTypeRequest(att::Handle handle,
3079                                 fit::result<att::ErrorCode> expected_status) {
3080     const StaticByteBuffer kReadByTypeRequestPdu(
3081         0x08,  // opcode: read by type
3082         LowerBits(handle),
3083         UpperBits(handle),  // start handle
3084         LowerBits(handle),
3085         UpperBits(handle),  // end handle
3086         0xEF,
3087         0xBE);  // type: 0xBEEF, i.e. kTestType16
3088     if (expected_status.is_ok()) {
3089       EXPECT_PACKET_OUT(StaticByteBuffer(0x09,  // opcode: read by type response
3090                                          0x05,  // length: 5 (strlen("foo") + 2)
3091                                          LowerBits(handle),
3092                                          UpperBits(handle),  // handle
3093                                          'f',
3094                                          'o',
3095                                          'o'  // value: "foo", i.e. kTestValue1
3096                                          ));
3097     } else {
3098       EXPECT_PACKET_OUT(
3099           MakeAttError(0x08, handle, expected_status.error_value()));
3100     }
3101     fake_chan()->Receive(kReadByTypeRequestPdu);
3102     return AllExpectedPacketsSent();
3103   }
3104 
EmulateReadBlobRequest(att::Handle handle,fit::result<att::ErrorCode> expected_status)3105   bool EmulateReadBlobRequest(att::Handle handle,
3106                               fit::result<att::ErrorCode> expected_status) {
3107     const StaticByteBuffer kReadBlobRequestPdu(0x0C,  // opcode: read blob
3108                                                LowerBits(handle),
3109                                                UpperBits(handle),  // handle
3110                                                0x00,
3111                                                0x00);  // offset: 0
3112     if (expected_status.is_ok()) {
3113       EXPECT_PACKET_OUT(StaticByteBuffer(0x0D,  // opcode: read blob response
3114                                          'f',
3115                                          'o',
3116                                          'o'  // value: "foo", i.e. kTestValue1
3117                                          ));
3118     } else {
3119       EXPECT_PACKET_OUT(
3120           MakeAttError(0x0C, handle, expected_status.error_value()));
3121     }
3122     fake_chan()->Receive(kReadBlobRequestPdu);
3123     return AllExpectedPacketsSent();
3124   }
3125 
EmulateReadRequest(att::Handle handle,fit::result<att::ErrorCode> expected_status)3126   bool EmulateReadRequest(att::Handle handle,
3127                           fit::result<att::ErrorCode> expected_status) {
3128     const StaticByteBuffer kReadRequestPdu(0x0A,  // opcode: read request
3129                                            LowerBits(handle),
3130                                            UpperBits(handle));  // handle
3131     if (expected_status.is_ok()) {
3132       EXPECT_PACKET_OUT(StaticByteBuffer(0x0B,  // opcode: read response
3133                                          'f',
3134                                          'o',
3135                                          'o'  // value: "foo", i.e. kTestValue1
3136                                          ));
3137     } else {
3138       EXPECT_PACKET_OUT(
3139           MakeAttError(0x0A, handle, expected_status.error_value()));
3140     }
3141     fake_chan()->Receive(kReadRequestPdu);
3142     return AllExpectedPacketsSent();
3143   }
3144 
EmulateWriteRequest(att::Handle handle,fit::result<att::ErrorCode> expected_status)3145   bool EmulateWriteRequest(att::Handle handle,
3146                            fit::result<att::ErrorCode> expected_status) {
3147     const StaticByteBuffer kWriteRequestPdu(0x12,  // opcode: write request
3148                                             LowerBits(handle),
3149                                             UpperBits(handle),  // handle
3150                                             't',
3151                                             'e',
3152                                             's',
3153                                             't');  // value: "test"
3154     if (expected_status.is_ok()) {
3155       EXPECT_PACKET_OUT(StaticByteBuffer(0x13));
3156     } else {
3157       EXPECT_PACKET_OUT(
3158           MakeAttError(0x12, handle, expected_status.error_value()));
3159     }
3160     fake_chan()->Receive(kWriteRequestPdu);
3161     return AllExpectedPacketsSent();
3162   }
3163 
EmulatePrepareWriteRequest(att::Handle handle,fit::result<att::ErrorCode> expected_status)3164   bool EmulatePrepareWriteRequest(att::Handle handle,
3165                                   fit::result<att::ErrorCode> expected_status) {
3166     const auto kPrepareWriteRequestPdu =
3167         StaticByteBuffer(0x16,  // opcode: prepare write request
3168                          LowerBits(handle),
3169                          UpperBits(handle),  // handle
3170                          0x00,
3171                          0x00,  // offset: 0
3172                          't',
3173                          'e',
3174                          's',
3175                          't'  // value: "test"
3176         );
3177     if (expected_status.is_ok()) {
3178       EXPECT_PACKET_OUT(StaticByteBuffer(0x17,  // prepare write response
3179                                          LowerBits(handle),
3180                                          UpperBits(handle),  // handle
3181                                          0x00,
3182                                          0x00,  // offset: 0
3183                                          't',
3184                                          'e',
3185                                          's',
3186                                          't'  // value: "test"
3187                                          ));
3188     } else {
3189       EXPECT_PACKET_OUT(
3190           MakeAttError(0x16, handle, expected_status.error_value()));
3191     }
3192     fake_chan()->Receive(kPrepareWriteRequestPdu);
3193     return AllExpectedPacketsSent();
3194   }
3195 
3196   // Emulates the receipt of a Write Command. The expected error code parameter
3197   // is unused since ATT commands do not have a response.
EmulateWriteCommand(att::Handle handle,fit::result<att::ErrorCode>)3198   bool EmulateWriteCommand(att::Handle handle, fit::result<att::ErrorCode>) {
3199     fake_chan()->Receive(StaticByteBuffer(0x52,  // opcode: write command
3200                                           LowerBits(handle),
3201                                           UpperBits(handle),  // handle
3202                                           't',
3203                                           'e',
3204                                           's',
3205                                           't'  // value: "test"
3206                                           ));
3207     RunUntilIdle();
3208     return true;
3209   }
3210 
3211   template <bool (ServerTestSecurity::* EmulateMethod)(
3212                 att::Handle, fit::result<att::ErrorCode>),
3213             bool IsWrite>
RunTest()3214   void RunTest() {
3215     const fit::error<att::ErrorCode> kNotPermittedError =
3216         fit::error(IsWrite ? att::ErrorCode::kWriteNotPermitted
3217                            : att::ErrorCode::kReadNotPermitted);
3218 
3219     // No security.
3220     EXPECT_TRUE((this->*EmulateMethod)(not_permitted_attr()->handle(),
3221                                        fit::error(kNotPermittedError)));
3222     EXPECT_TRUE((this->*EmulateMethod)(
3223         encryption_required_attr()->handle(),
3224         fit::error(att::ErrorCode::kInsufficientAuthentication)));
3225     EXPECT_TRUE((this->*EmulateMethod)(
3226         authentication_required_attr()->handle(),
3227         fit::error(att::ErrorCode::kInsufficientAuthentication)));
3228     EXPECT_TRUE((this->*EmulateMethod)(
3229         authorization_required_attr()->handle(),
3230         fit::error(att::ErrorCode::kInsufficientAuthentication)));
3231 
3232     // Link encrypted.
3233     fake_chan()->set_security(sm::SecurityProperties(
3234         sm::SecurityLevel::kEncrypted, 16, /*secure_connections=*/false));
3235     EXPECT_TRUE((this->*EmulateMethod)(not_permitted_attr()->handle(),
3236                                        kNotPermittedError));
3237     EXPECT_TRUE((this->*EmulateMethod)(encryption_required_attr()->handle(),
3238                                        fit::ok()));
3239     EXPECT_TRUE((this->*EmulateMethod)(
3240         authentication_required_attr()->handle(),
3241         fit::error(att::ErrorCode::kInsufficientAuthentication)));
3242     EXPECT_TRUE((this->*EmulateMethod)(
3243         authorization_required_attr()->handle(),
3244         fit::error(att::ErrorCode::kInsufficientAuthentication)));
3245 
3246     // inclusive-language: ignore
3247     // Link encrypted w/ MITM.
3248     fake_chan()->set_security(
3249         sm::SecurityProperties(sm::SecurityLevel::kAuthenticated,
3250                                16,
3251                                /*secure_connections=*/false));
3252     EXPECT_TRUE((this->*EmulateMethod)(not_permitted_attr()->handle(),
3253                                        kNotPermittedError));
3254     EXPECT_TRUE((this->*EmulateMethod)(encryption_required_attr()->handle(),
3255                                        fit::ok()));
3256     EXPECT_TRUE((this->*EmulateMethod)(authentication_required_attr()->handle(),
3257                                        fit::ok()));
3258     EXPECT_TRUE((this->*EmulateMethod)(authorization_required_attr()->handle(),
3259                                        fit::ok()));
3260   }
3261 
RunReadByTypeTest()3262   void RunReadByTypeTest() {
3263     RunTest<&ServerTestSecurity::EmulateReadByTypeRequest, false>();
3264   }
RunReadBlobTest()3265   void RunReadBlobTest() {
3266     RunTest<&ServerTestSecurity::EmulateReadBlobRequest, false>();
3267   }
RunReadRequestTest()3268   void RunReadRequestTest() {
3269     RunTest<&ServerTestSecurity::EmulateReadRequest, false>();
3270   }
RunWriteRequestTest()3271   void RunWriteRequestTest() {
3272     RunTest<&ServerTestSecurity::EmulateWriteRequest, true>();
3273   }
RunPrepareWriteRequestTest()3274   void RunPrepareWriteRequestTest() {
3275     RunTest<&ServerTestSecurity::EmulatePrepareWriteRequest, true>();
3276   }
RunWriteCommandTest()3277   void RunWriteCommandTest() {
3278     RunTest<&ServerTestSecurity::EmulateWriteCommand, true>();
3279   }
3280 
not_permitted_attr() const3281   const att::Attribute* not_permitted_attr() const {
3282     return not_permitted_attr_;
3283   }
encryption_required_attr() const3284   const att::Attribute* encryption_required_attr() const {
3285     return encryption_required_attr_;
3286   }
authentication_required_attr() const3287   const att::Attribute* authentication_required_attr() const {
3288     return authentication_required_attr_;
3289   }
authorization_required_attr() const3290   const att::Attribute* authorization_required_attr() const {
3291     return authorization_required_attr_;
3292   }
3293 
write_count() const3294   size_t write_count() const { return write_count_; }
3295 
3296  private:
3297   att::Attribute* not_permitted_attr_ = nullptr;
3298   att::Attribute* encryption_required_attr_ = nullptr;
3299   att::Attribute* authentication_required_attr_ = nullptr;
3300   att::Attribute* authorization_required_attr_ = nullptr;
3301 
3302   size_t write_count_ = 0u;
3303 };
3304 
3305 // Tests receiving a Read By Type error under 3 possible link security levels.
TEST_F(ServerTestSecurity,ReadByTypeErrorSecurity)3306 TEST_F(ServerTestSecurity, ReadByTypeErrorSecurity) {
3307   InitializeAttributesForReading();
3308   RunReadByTypeTest();
3309 }
3310 
TEST_F(ServerTestSecurity,ReadBlobErrorSecurity)3311 TEST_F(ServerTestSecurity, ReadBlobErrorSecurity) {
3312   InitializeAttributesForReading();
3313   RunReadBlobTest();
3314 }
3315 
TEST_F(ServerTestSecurity,ReadErrorSecurity)3316 TEST_F(ServerTestSecurity, ReadErrorSecurity) {
3317   InitializeAttributesForReading();
3318   RunReadRequestTest();
3319 }
3320 
TEST_F(ServerTestSecurity,WriteErrorSecurity)3321 TEST_F(ServerTestSecurity, WriteErrorSecurity) {
3322   InitializeAttributesForWriting();
3323   RunWriteRequestTest();
3324 
3325   // Only 4 writes should have gone through.
3326   EXPECT_EQ(4u, write_count());
3327 }
3328 
TEST_F(ServerTestSecurity,WriteCommandErrorSecurity)3329 TEST_F(ServerTestSecurity, WriteCommandErrorSecurity) {
3330   InitializeAttributesForWriting();
3331   RunWriteCommandTest();
3332 
3333   // Only 4 writes should have gone through.
3334   EXPECT_EQ(4u, write_count());
3335 }
3336 
TEST_F(ServerTestSecurity,PrepareWriteRequestSecurity)3337 TEST_F(ServerTestSecurity, PrepareWriteRequestSecurity) {
3338   InitializeAttributesForWriting();
3339   RunPrepareWriteRequestTest();
3340 
3341   // None of the write handlers should have been called since no execute write
3342   // request has been sent.
3343   EXPECT_EQ(0u, write_count());
3344 }
3345 
3346 }  // namespace
3347 }  // namespace bt::gatt
3348