• 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_assert/check.h>
18 
19 #include "pw_bluetooth_sapphire/internal/host/att/att.h"
20 #include "pw_bluetooth_sapphire/internal/host/att/attribute.h"
21 #include "pw_bluetooth_sapphire/internal/host/att/database.h"
22 #include "pw_bluetooth_sapphire/internal/host/common/macros.h"
23 #include "pw_bluetooth_sapphire/internal/host/common/uuid.h"
24 #include "pw_bluetooth_sapphire/internal/host/gatt/gatt_defs.h"
25 #include "pw_bluetooth_sapphire/internal/host/gatt/local_service_manager.h"
26 #include "pw_bluetooth_sapphire/internal/host/l2cap/mock_channel_test.h"
27 #include "pw_bluetooth_sapphire/internal/host/testing/test_helpers.h"
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           PW_CHECK(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(static_cast<uint16_t>(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(static_cast<uint16_t>(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, 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([](PeerId, auto, uint16_t, auto result_cb) {
1133     result_cb(fit::error(att::ErrorCode::kUnlikelyError), BufferView());
1134   });
1135   grp->set_active(true);
1136 
1137   // clang-format off
1138   const StaticByteBuffer kRequest(
1139       0x08,        // opcode: read by type
1140       0x01, 0x00,  // start: 0x0001
1141       0xFF, 0xFF,  // end: 0xFFFF
1142       0xEF, 0xBE   // type: 0xBEEF
1143   );
1144 
1145   const StaticByteBuffer kExpected(
1146       0x01,        // opcode: error response
1147       0x08,        // request: read by type
1148       0x02, 0x00,  // handle: 0x0002 (the attribute causing the error)
1149       0x0E         // error: Unlikely error
1150   );
1151   // clang-format on
1152 
1153   EXPECT_PACKET_OUT(kExpected);
1154   fake_chan()->Receive(kRequest);
1155 }
1156 
TEST_F(ServerTest,ReadByTypeSingle)1157 TEST_F(ServerTest, ReadByTypeSingle) {
1158   const StaticByteBuffer kTestValue('t', 'e', 's', 't');
1159 
1160   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue1);
1161   grp->AddAttribute(kTestType16, AllowedNoSecurity(), att::AccessRequirements())
1162       ->SetValue(kTestValue);
1163   grp->set_active(true);
1164 
1165   // clang-format off
1166   const StaticByteBuffer kRequest(
1167       0x08,        // opcode: read by type
1168       0x01, 0x00,  // start: 0x0001
1169       0xFF, 0xFF,  // end: 0xFFFF
1170       0xEF, 0xBE   // type: 0xBEEF
1171   );
1172 
1173   const StaticByteBuffer kExpected(
1174       0x09,               // opcode: read by type response
1175       0x06,               // length: 6 (strlen("test") + 2)
1176       0x02, 0x00,         // handle: 0x0002
1177       't', 'e', 's', 't'  // value: "test"
1178   );
1179 
1180   // clang-format on
1181 
1182   EXPECT_PACKET_OUT(kExpected);
1183   fake_chan()->Receive(kRequest);
1184 }
1185 
TEST_F(ServerTest,ReadByTypeSingle128)1186 TEST_F(ServerTest, ReadByTypeSingle128) {
1187   const StaticByteBuffer kTestValue('t', 'e', 's', 't');
1188 
1189   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue1);
1190   grp->AddAttribute(
1191          kTestType128, AllowedNoSecurity(), att::AccessRequirements())
1192       ->SetValue(kTestValue);
1193   grp->set_active(true);
1194 
1195   // clang-format off
1196   const StaticByteBuffer kRequest(
1197       0x08,        // opcode: read by type
1198       0x01, 0x00,  // start: 0x0001
1199       0xFF, 0xFF,  // end: 0xFFFF
1200 
1201       // type: 0F0E0D0C-0B0A-0908-0706-050403020100
1202       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1203       0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F);
1204 
1205   const StaticByteBuffer kExpected(
1206       0x09,               // opcode: read by type response
1207       0x06,               // length: 6 (strlen("test") + 2)
1208       0x02, 0x00,         // handle: 0x0002
1209       't', 'e', 's', 't'  // value: "test"
1210   );
1211   // clang-format on
1212 
1213   EXPECT_PACKET_OUT(kExpected);
1214   fake_chan()->Receive(kRequest);
1215 }
1216 
TEST_F(ServerTest,ReadByTypeSingleTruncated)1217 TEST_F(ServerTest, ReadByTypeSingleTruncated) {
1218   const StaticByteBuffer kVeryLongValue(
1219       't', 'e', 's', 't', 'i', 'n', 'g', ' ', 'i', 's', ' ', 'f', 'u', 'n');
1220 
1221   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue1);
1222   grp->AddAttribute(kTestType16, AllowedNoSecurity(), att::AccessRequirements())
1223       ->SetValue(kVeryLongValue);
1224   grp->set_active(true);
1225 
1226   // clang-format off
1227   const StaticByteBuffer kRequest(
1228       0x08,        // opcode: read by type
1229       0x01, 0x00,  // start: 0x0001
1230       0xFF, 0xFF,  // end: 0xFFFF
1231       0xEF, 0xBE   // type: 0xBEEF
1232   );
1233 
1234   const StaticByteBuffer kExpected(
1235       0x09,          // opcode: read by type response
1236       0x05,          // length: 5 (strlen("tes") + 2)
1237       0x02, 0x00,    // handle: 0x0002
1238       't', 'e', 's'  // value: "tes"
1239   );
1240   // clang-format on
1241 
1242   // Force the MTU to exactly fit |kExpected| which partially contains
1243   // |kTestValue2| (the packet is crafted so that both |kRequest| and
1244   // |kExpected| fit within the MTU).
1245   att()->set_mtu(static_cast<uint16_t>(kExpected.size()));
1246 
1247   EXPECT_PACKET_OUT(kExpected);
1248   fake_chan()->Receive(kRequest);
1249 }
1250 
1251 // When there are more than one matching attributes, the list should end at the
1252 // first attribute that causes an error.
TEST_F(ServerTest,ReadByTypeMultipleExcludeFirstError)1253 TEST_F(ServerTest, ReadByTypeMultipleExcludeFirstError) {
1254   // handle 1: readable
1255   auto* grp = db()->NewGrouping(kTestType16, 1, kTestValue1);
1256 
1257   // handle 2: not readable.
1258   grp->AddAttribute(kTestType16)->SetValue(kTestValue1);
1259   grp->set_active(true);
1260 
1261   // clang-format off
1262   const StaticByteBuffer kRequest(
1263       0x08,        // opcode: read by type
1264       0x01, 0x00,  // start: 0x0001
1265       0xFF, 0xFF,  // end: 0xFFFF
1266       0xEF, 0xBE   // type: 0xBEEF
1267   );
1268   const StaticByteBuffer kExpected(
1269       0x09,          // opcode: read by type response
1270       0x05,          // length: 5 (strlen("foo") + 2)
1271       0x01, 0x00,    // handle: 0x0001
1272       'f', 'o', 'o'  // value: "foo"
1273   );
1274   // clang-format on
1275 
1276   EXPECT_PACKET_OUT(kExpected);
1277   fake_chan()->Receive(kRequest);
1278 }
1279 
TEST_F(ServerTest,ReadByTypeMultipleSameValueSize)1280 TEST_F(ServerTest, ReadByTypeMultipleSameValueSize) {
1281   // handle: 1, value: foo
1282   auto* grp = db()->NewGrouping(types::kPrimaryService, 2, kTestValue1);
1283 
1284   // handle: 2, value: foo
1285   grp->AddAttribute(kTestType16, AllowedNoSecurity(), att::AccessRequirements())
1286       ->SetValue(kTestValue1);
1287 
1288   // handle: 3, value: bar
1289   grp->AddAttribute(kTestType16, AllowedNoSecurity(), att::AccessRequirements())
1290       ->SetValue(kTestValue2);
1291   grp->set_active(true);
1292 
1293   // handle: 4, value: foo (new grouping)
1294   grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue1);
1295 
1296   // handle: 5, value: baz
1297   grp->AddAttribute(kTestType16, AllowedNoSecurity(), att::AccessRequirements())
1298       ->SetValue(kTestValue3);
1299   grp->set_active(true);
1300 
1301   // clang-format off
1302   const StaticByteBuffer kRequest1(
1303       0x08,        // opcode: read by type
1304       0x01, 0x00,  // start: 0x0001
1305       0xFF, 0xFF,  // end: 0xFFFF
1306       0xEF, 0xBE   // type: 0xBEEF
1307   );
1308 
1309   const StaticByteBuffer kExpected1(
1310       0x09,           // opcode: read by type response
1311       0x05,           // length: 5 (strlen("foo") + 2)
1312       0x02, 0x00,     // handle: 0x0002
1313       'f', 'o', 'o',  // value: "foo"
1314       0x03, 0x00,     // handle: 0x0003
1315       'b', 'a', 'r',  // value: "bar"
1316       0x05, 0x00,     // handle: 0x0005
1317       'b', 'a', 'z'   // value: "baz"
1318   );
1319   // clang-format on
1320 
1321   EXPECT_PACKET_OUT(kExpected1);
1322   fake_chan()->Receive(kRequest1);
1323 
1324   // Set the MTU 1 byte too short for |kExpected1|.
1325   att()->set_mtu(static_cast<uint16_t>(kExpected1.size() - 1));
1326 
1327   // clang-format off
1328   const StaticByteBuffer kExpected2(
1329       0x09,           // opcode: read by type response
1330       0x05,           // length: 5 (strlen("foo") + 2)
1331       0x02, 0x00,     // handle: 0x0002
1332       'f', 'o', 'o',  // value: "foo"
1333       0x03, 0x00,     // handle: 0x0003
1334       'b', 'a', 'r'   // value: "bar"
1335   );
1336   // clang-format on
1337 
1338   EXPECT_PACKET_OUT(kExpected2);
1339   fake_chan()->Receive(kRequest1);
1340 
1341   // Try a different range.
1342   // clang-format off
1343   const StaticByteBuffer kRequest2(
1344       0x08,        // opcode: read by type
1345       0x03, 0x00,  // start: 0x0003
1346       0x05, 0x00,  // end: 0x0005
1347       0xEF, 0xBE   // type: 0xBEEF
1348   );
1349 
1350   const StaticByteBuffer kExpected3(
1351       0x09,           // opcode: read by type response
1352       0x05,           // length: 5 (strlen("bar") + 2)
1353       0x03, 0x00,     // handle: 0x0003
1354       'b', 'a', 'r',  // value: "bar"
1355       0x05, 0x00,     // handle: 0x0005
1356       'b', 'a', 'z'   // value: "baz"
1357   );
1358   // clang-format on
1359 
1360   EXPECT_PACKET_OUT(kExpected3);
1361   fake_chan()->Receive(kRequest2);
1362 
1363   // Make the second group inactive.
1364   grp->set_active(false);
1365 
1366   // clang-format off
1367   const StaticByteBuffer kExpected4(
1368       0x09,           // opcode: read by type response
1369       0x05,           // length: 5 (strlen("bar") + 2)
1370       0x03, 0x00,     // handle: 0x0003
1371       'b', 'a', 'r'   // value: "bar"
1372   );
1373   // clang-format on
1374 
1375   EXPECT_PACKET_OUT(kExpected4);
1376   fake_chan()->Receive(kRequest2);
1377 }
1378 
1379 // A response packet should only include consecutive attributes with the same
1380 // value size.
TEST_F(ServerTest,ReadByTypeMultipleVaryingLengths)1381 TEST_F(ServerTest, ReadByTypeMultipleVaryingLengths) {
1382   // handle: 1 - value: "foo"
1383   auto* grp = db()->NewGrouping(kTestType16, 2, kTestValue1);
1384 
1385   // handle: 2 - value: "long"
1386   grp->AddAttribute(kTestType16, AllowedNoSecurity())->SetValue(kTestValueLong);
1387 
1388   // handle: 3 - value: "foo"
1389   grp->AddAttribute(kTestType16, AllowedNoSecurity())->SetValue(kTestValue1);
1390   grp->set_active(true);
1391 
1392   // Even though we have 3 attributes with a matching type, the requests below
1393   // will always return one attribute at a time as their values have different
1394   // sizes.
1395 
1396   // clang-format off
1397   const StaticByteBuffer kRequest1(
1398       0x08,        // opcode: read by type
1399       0x01, 0x00,  // start: 0x0001
1400       0xFF, 0xFF,  // end: 0xFFFF
1401       0xEF, 0xBE   // type: 0xBEEF
1402   );
1403   const StaticByteBuffer kExpected1(
1404       0x09,          // opcode: read by type response
1405       0x05,          // length: 5 (strlen("foo") + 2)
1406       0x01, 0x00,    // handle: 0x0001
1407       'f', 'o', 'o'  // value: "foo"
1408   );
1409   const StaticByteBuffer kRequest2(
1410       0x08,        // opcode: read by type
1411       0x02, 0x00,  // start: 0x0002
1412       0xFF, 0xFF,  // end: 0xFFFF
1413       0xEF, 0xBE   // type: 0xBEEF
1414   );
1415   const StaticByteBuffer kExpected2(
1416       0x09,               // opcode: read by type response
1417       0x06,               // length: 6 (strlen("long") + 2)
1418       0x02, 0x00,         // handle: 0x0002
1419       'l', 'o', 'n', 'g'  // value: "long"
1420   );
1421   const StaticByteBuffer kRequest3(
1422       0x08,        // opcode: read by type
1423       0x03, 0x00,  // start: 0x0003
1424       0xFF, 0xFF,  // end: 0xFFFF
1425       0xEF, 0xBE   // type: 0xBEEF
1426   );
1427   const StaticByteBuffer kExpected3(
1428       0x09,          // opcode: read by type response
1429       0x05,          // length: 5 (strlen("foo") + 2)
1430       0x03, 0x00,    // handle: 0x0003
1431       'f', 'o', 'o'  // value: "foo"
1432   );
1433   // clang-format on
1434 
1435   EXPECT_PACKET_OUT(kExpected1);
1436   fake_chan()->Receive(kRequest1);
1437   EXPECT_PACKET_OUT(kExpected2);
1438   fake_chan()->Receive(kRequest2);
1439   EXPECT_PACKET_OUT(kExpected3);
1440   fake_chan()->Receive(kRequest3);
1441 }
1442 
1443 // When there are more than one matching attributes, the list should end at the
1444 // first attribute with a dynamic value.
TEST_F(ServerTest,ReadByTypeMultipleExcludeFirstDynamic)1445 TEST_F(ServerTest, ReadByTypeMultipleExcludeFirstDynamic) {
1446   // handle: 1 - value: "foo"
1447   auto* grp = db()->NewGrouping(kTestType16, 1, kTestValue1);
1448 
1449   // handle: 2 - value: dynamic
1450   grp->AddAttribute(kTestType16, AllowedNoSecurity());
1451   grp->set_active(true);
1452 
1453   // clang-format off
1454   const StaticByteBuffer kRequest(
1455       0x08,        // opcode: read by type
1456       0x01, 0x00,  // start: 0x0001
1457       0xFF, 0xFF,  // end: 0xFFFF
1458       0xEF, 0xBE   // type: 0xBEEF
1459   );
1460   const StaticByteBuffer kExpected(
1461       0x09,          // opcode: read by type response
1462       0x05,          // length: 5 (strlen("foo") + 2)
1463       0x01, 0x00,    // handle: 0x0001
1464       'f', 'o', 'o'  // value: "foo"
1465   );
1466   // clang-format on
1467 
1468   EXPECT_PACKET_OUT(kExpected);
1469   fake_chan()->Receive(kRequest);
1470 }
1471 
TEST_F(ServerTest,WriteRequestInvalidPDU)1472 TEST_F(ServerTest, WriteRequestInvalidPDU) {
1473   // Just opcode
1474   // clang-format off
1475   const StaticByteBuffer kInvalidPDU(0x12);
1476   const StaticByteBuffer kExpected(
1477       0x01,        // opcode: error response
1478       0x12,        // request: write request
1479       0x00, 0x00,  // handle: 0
1480       0x04         // error: Invalid PDU
1481   );
1482   // clang-format on
1483 
1484   EXPECT_PACKET_OUT(kExpected);
1485   fake_chan()->Receive(kInvalidPDU);
1486 }
1487 
TEST_F(ServerTest,WriteRequestInvalidHandle)1488 TEST_F(ServerTest, WriteRequestInvalidHandle) {
1489   // clang-format off
1490   const StaticByteBuffer kRequest(
1491       0x12,        // opcode: write request
1492       0x01, 0x00,  // handle: 0x0001
1493 
1494       // value: "test"
1495       't', 'e', 's', 't');
1496 
1497   const StaticByteBuffer kExpected(
1498       0x01,        // opcode: error response
1499       0x12,        // request: write request
1500       0x01, 0x00,  // handle: 0x0001
1501       0x01         // error: invalid handle
1502   );
1503   // clang-format on
1504 
1505   EXPECT_PACKET_OUT(kExpected);
1506   fake_chan()->Receive(kRequest);
1507 }
1508 
TEST_F(ServerTest,WriteRequestSecurity)1509 TEST_F(ServerTest, WriteRequestSecurity) {
1510   const StaticByteBuffer kTestValue('f', 'o', 'o');
1511   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue);
1512 
1513   // Requires encryption
1514   grp->AddAttribute(kTestType16,
1515                     att::AccessRequirements(),
1516                     att::AccessRequirements(/*encryption=*/true,
1517                                             /*authentication=*/false,
1518                                             /*authorization=*/false));
1519   grp->set_active(true);
1520 
1521   // We send two write requests:
1522   //   1. 0x0001: not writable
1523   //   2. 0x0002: writable but requires encryption
1524   //
1525   // clang-format off
1526   const StaticByteBuffer kRequest1(
1527       0x12,        // opcode: write request
1528       0x01, 0x00,  // handle: 0x0001
1529 
1530       // value: "test"
1531       't', 'e', 's', 't');
1532 
1533   const StaticByteBuffer kExpected1(
1534       0x01,        // opcode: error response
1535       0x12,        // request: write request
1536       0x01, 0x00,  // handle: 0x0001
1537       0x03         // error: write not permitted
1538   );
1539   const StaticByteBuffer kRequest2(
1540       0x12,        // opcode: write request
1541       0x02, 0x00,  // handle: 0x0002
1542 
1543       // value: "test"
1544       't', 'e', 's', 't');
1545 
1546   const StaticByteBuffer kExpected2(
1547       0x01,        // opcode: error response
1548       0x12,        // request: write request
1549       0x02, 0x00,  // handle: 0x0002
1550       0x05         // error: insufficient authentication
1551   );
1552   // clang-format on
1553 
1554   EXPECT_PACKET_OUT(kExpected1);
1555   fake_chan()->Receive(kRequest1);
1556   EXPECT_PACKET_OUT(kExpected2);
1557   fake_chan()->Receive(kRequest2);
1558 }
1559 
TEST_F(ServerTest,WriteRequestNoHandler)1560 TEST_F(ServerTest, WriteRequestNoHandler) {
1561   const StaticByteBuffer kTestValue('f', 'o', 'o');
1562   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue);
1563 
1564   grp->AddAttribute(
1565       kTestType16, att::AccessRequirements(), AllowedNoSecurity());
1566   grp->set_active(true);
1567 
1568   // clang-format off
1569   const StaticByteBuffer kRequest(
1570       0x12,        // opcode: write request
1571       0x02, 0x00,  // handle: 0x0002
1572 
1573       // value: "test"
1574       't', 'e', 's', 't');
1575 
1576   const StaticByteBuffer kExpected(
1577       0x01,        // opcode: error response
1578       0x12,        // request: write request
1579       0x02, 0x00,  // handle: 0x0002
1580       0x03         // error: write not permitted
1581   );
1582   // clang-format on
1583 
1584   EXPECT_PACKET_OUT(kExpected);
1585   fake_chan()->Receive(kRequest);
1586 }
1587 
TEST_F(ServerTest,WriteRequestError)1588 TEST_F(ServerTest, WriteRequestError) {
1589   const StaticByteBuffer kTestValue('f', 'o', 'o');
1590   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue);
1591   auto* attr = grp->AddAttribute(
1592       kTestType16, att::AccessRequirements(), AllowedNoSecurity());
1593 
1594   attr->set_write_handler([&](PeerId peer_id,
1595                               att::Handle handle,
1596                               uint16_t offset,
1597                               const auto& value,
1598                               auto result_cb) {
1599     EXPECT_EQ(kTestPeerId, peer_id);
1600     EXPECT_EQ(attr->handle(), handle);
1601     EXPECT_EQ(0u, offset);
1602     EXPECT_TRUE(ContainersEqual(StaticByteBuffer('t', 'e', 's', 't'), value));
1603 
1604     result_cb(fit::error(att::ErrorCode::kUnlikelyError));
1605   });
1606   grp->set_active(true);
1607 
1608   // clang-format off
1609   const StaticByteBuffer kRequest(
1610       0x12,        // opcode: write request
1611       0x02, 0x00,  // handle: 0x0002
1612 
1613       // value: "test"
1614       't', 'e', 's', 't');
1615 
1616   const StaticByteBuffer kExpected(
1617       0x01,        // opcode: error response
1618       0x12,        // request: write request
1619       0x02, 0x00,  // handle: 0x0002
1620       0x0E         // error: unlikely error
1621   );
1622   // clang-format on
1623 
1624   EXPECT_PACKET_OUT(kExpected);
1625   fake_chan()->Receive(kRequest);
1626 }
1627 
TEST_F(ServerTest,WriteRequestSuccess)1628 TEST_F(ServerTest, WriteRequestSuccess) {
1629   const StaticByteBuffer kTestValue('f', 'o', 'o');
1630   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue);
1631   auto* attr = grp->AddAttribute(
1632       kTestType16, att::AccessRequirements(), AllowedNoSecurity());
1633 
1634   attr->set_write_handler([&](PeerId peer_id,
1635                               att::Handle handle,
1636                               uint16_t offset,
1637                               const auto& value,
1638                               auto result_cb) {
1639     EXPECT_EQ(kTestPeerId, peer_id);
1640     EXPECT_EQ(attr->handle(), handle);
1641     EXPECT_EQ(0u, offset);
1642     EXPECT_TRUE(ContainersEqual(StaticByteBuffer('t', 'e', 's', 't'), value));
1643 
1644     result_cb(fit::ok());
1645   });
1646   grp->set_active(true);
1647 
1648   // clang-format off
1649   const StaticByteBuffer kRequest(
1650       0x12,        // opcode: write request
1651       0x02, 0x00,  // handle: 0x0002
1652 
1653       // value: "test"
1654       't', 'e', 's', 't');
1655   // clang-format on
1656 
1657   // opcode: write response
1658   const StaticByteBuffer kExpected(0x13);
1659 
1660   EXPECT_PACKET_OUT(kExpected);
1661   fake_chan()->Receive(kRequest);
1662 }
1663 
1664 // TODO(bwb): Add test cases for the error conditions involved in a Write
1665 // Command (fxbug.dev/42146420)
1666 
TEST_F(ServerTest,WriteCommandSuccess)1667 TEST_F(ServerTest, WriteCommandSuccess) {
1668   const StaticByteBuffer kTestValue('f', 'o', 'o');
1669   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue);
1670   auto* attr = grp->AddAttribute(
1671       kTestType16, att::AccessRequirements(), AllowedNoSecurity());
1672 
1673   attr->set_write_handler([&](PeerId peer_id,
1674                               att::Handle handle,
1675                               uint16_t offset,
1676                               const auto& value,
1677                               const auto&) {
1678     EXPECT_EQ(kTestPeerId, peer_id);
1679     EXPECT_EQ(attr->handle(), handle);
1680     EXPECT_EQ(0u, offset);
1681     EXPECT_TRUE(ContainersEqual(StaticByteBuffer('t', 'e', 's', 't'), value));
1682   });
1683   grp->set_active(true);
1684 
1685   // clang-format off
1686   const StaticByteBuffer kCmd(
1687       0x52,        // opcode: write command
1688       0x02, 0x00,  // handle: 0x0002
1689       't', 'e', 's', 't');
1690   // clang-format on
1691 
1692   fake_chan()->Receive(kCmd);
1693 }
1694 
TEST_F(ServerTest,ReadRequestInvalidPDU)1695 TEST_F(ServerTest, ReadRequestInvalidPDU) {
1696   // Just opcode
1697   // clang-format off
1698   const StaticByteBuffer kInvalidPDU(0x0A);
1699   const StaticByteBuffer kExpected(
1700       0x01,        // opcode: error response
1701       0x0A,        // request: read request
1702       0x00, 0x00,  // handle: 0
1703       0x04         // error: Invalid PDU
1704   );
1705   // clang-format on
1706 
1707   EXPECT_PACKET_OUT(kExpected);
1708   fake_chan()->Receive(kInvalidPDU);
1709 }
1710 
TEST_F(ServerTest,ReadRequestInvalidHandle)1711 TEST_F(ServerTest, ReadRequestInvalidHandle) {
1712   // clang-format off
1713   const StaticByteBuffer kRequest(
1714       0x0A,       // opcode: read request
1715       0x01, 0x00  // handle: 0x0001
1716   );
1717 
1718   const StaticByteBuffer kExpected(
1719       0x01,        // opcode: error response
1720       0x0A,        // request: read request
1721       0x01, 0x00,  // handle: 0x0001
1722       0x01         // error: invalid handle
1723   );
1724   // clang-format on
1725 
1726   EXPECT_PACKET_OUT(kExpected);
1727   fake_chan()->Receive(kRequest);
1728 }
1729 
TEST_F(ServerTest,ReadRequestSecurity)1730 TEST_F(ServerTest, ReadRequestSecurity) {
1731   const StaticByteBuffer kTestValue('f', 'o', 'o');
1732   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue);
1733 
1734   // Requires encryption
1735   grp->AddAttribute(kTestType16,
1736                     att::AccessRequirements(/*encryption=*/true,
1737                                             /*authentication=*/false,
1738                                             /*authorization=*/false),
1739                     att::AccessRequirements());
1740   grp->set_active(true);
1741 
1742   // clang-format off
1743   const StaticByteBuffer kRequest(
1744       0x0A,       // opcode: read request
1745       0x02, 0x00  // handle: 0x0002
1746   );
1747   const StaticByteBuffer kExpected(
1748       0x01,        // opcode: error response
1749       0x0A,        // request: read request
1750       0x02, 0x00,  // handle: 0x0002
1751       0x05         // error: insufficient authentication
1752   );
1753   // clang-format on
1754 
1755   EXPECT_PACKET_OUT(kExpected);
1756   fake_chan()->Receive(kRequest);
1757 }
1758 
TEST_F(ServerTest,ReadRequestCached)1759 TEST_F(ServerTest, ReadRequestCached) {
1760   const StaticByteBuffer kDeclValue('d', 'e', 'c', 'l');
1761   const StaticByteBuffer kTestValue('f', 'o', 'o');
1762   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kDeclValue);
1763   auto* attr = grp->AddAttribute(
1764       kTestType16, AllowedNoSecurity(), att::AccessRequirements());
1765   attr->SetValue(kTestValue);
1766   grp->set_active(true);
1767 
1768   // clang-format off
1769   const StaticByteBuffer kRequest1(
1770       0x0A,       // opcode: read request
1771       0x01, 0x00  // handle: 0x0001
1772   );
1773   const StaticByteBuffer kExpected1(
1774       0x0B,               // opcode: read response
1775       'd', 'e', 'c', 'l'  // value: kDeclValue
1776   );
1777   const StaticByteBuffer kRequest2(
1778       0x0A,       // opcode: read request
1779       0x02, 0x00  // handle: 0x0002
1780   );
1781   const StaticByteBuffer kExpected2(
1782       0x0B,          // opcode: read response
1783       'f', 'o', 'o'  // value: kTestValue
1784   );
1785   // clang-format on
1786 
1787   EXPECT_PACKET_OUT(kExpected1);
1788   fake_chan()->Receive(kRequest1);
1789   EXPECT_PACKET_OUT(kExpected2);
1790   fake_chan()->Receive(kRequest2);
1791 }
1792 
TEST_F(ServerTest,ReadRequestNoHandler)1793 TEST_F(ServerTest, ReadRequestNoHandler) {
1794   const StaticByteBuffer kTestValue('f', 'o', 'o');
1795   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue);
1796 
1797   grp->AddAttribute(
1798       kTestType16, AllowedNoSecurity(), att::AccessRequirements());
1799   grp->set_active(true);
1800 
1801   // clang-format off
1802   const StaticByteBuffer kRequest(
1803       0x0A,       // opcode: read request
1804       0x02, 0x00  // handle: 0x0002
1805   );
1806 
1807   const StaticByteBuffer kExpected(
1808       0x01,        // opcode: error response
1809       0x0A,        // request: read request
1810       0x02, 0x00,  // handle: 0x0002
1811       0x02         // error: read not permitted
1812   );
1813   // clang-format on
1814 
1815   EXPECT_PACKET_OUT(kExpected);
1816   fake_chan()->Receive(kRequest);
1817 }
1818 
TEST_F(ServerTest,ReadRequestError)1819 TEST_F(ServerTest, ReadRequestError) {
1820   const StaticByteBuffer kTestValue('f', 'o', 'o');
1821   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue);
1822   auto* attr = grp->AddAttribute(
1823       kTestType16, AllowedNoSecurity(), att::AccessRequirements());
1824   attr->set_read_handler(
1825       [&](PeerId peer_id, att::Handle handle, uint16_t offset, auto result_cb) {
1826         EXPECT_EQ(kTestPeerId, peer_id);
1827         EXPECT_EQ(attr->handle(), handle);
1828         EXPECT_EQ(0u, offset);
1829 
1830         result_cb(fit::error(att::ErrorCode::kUnlikelyError), BufferView());
1831       });
1832   grp->set_active(true);
1833 
1834   // clang-format off
1835   const StaticByteBuffer kRequest(
1836       0x0A,       // opcode: read request
1837       0x02, 0x00  // handle: 0x0002
1838   );
1839 
1840   const StaticByteBuffer kExpected(
1841       0x01,        // opcode: error response
1842       0x0A,        // request: read request
1843       0x02, 0x00,  // handle: 0x0002
1844       0x0E         // error: unlikely error
1845   );
1846   // clang-format on
1847 
1848   EXPECT_PACKET_OUT(kExpected);
1849   fake_chan()->Receive(kRequest);
1850 }
1851 
TEST_F(ServerTest,ReadBlobRequestInvalidPDU)1852 TEST_F(ServerTest, ReadBlobRequestInvalidPDU) {
1853   // Just opcode
1854   // clang-format off
1855   const StaticByteBuffer kInvalidPDU(0x0C);
1856   const StaticByteBuffer kExpected(
1857       0x01,        // opcode: error response
1858       0x0C,        // request: read blob request
1859       0x00, 0x00,  // handle: 0
1860       0x04         // error: Invalid PDU
1861   );
1862   // clang-format on
1863 
1864   EXPECT_PACKET_OUT(kExpected);
1865   fake_chan()->Receive(kInvalidPDU);
1866 }
1867 
TEST_F(ServerTest,ReadBlobRequestDynamicSuccess)1868 TEST_F(ServerTest, ReadBlobRequestDynamicSuccess) {
1869   const StaticByteBuffer kDeclValue('d', 'e', 'c', 'l');
1870   const StaticByteBuffer kTestValue('A',
1871                                     ' ',
1872                                     'V',
1873                                     'e',
1874                                     'r',
1875                                     'y',
1876                                     ' ',
1877                                     'L',
1878                                     'o',
1879                                     'n',
1880                                     'g',
1881                                     ' ',
1882                                     'D',
1883                                     'e',
1884                                     'v',
1885                                     'i',
1886                                     'c',
1887                                     'e',
1888                                     ' ',
1889                                     'N',
1890                                     'a',
1891                                     'm',
1892                                     'e',
1893                                     ' ',
1894                                     'U',
1895                                     's',
1896                                     'i',
1897                                     'n',
1898                                     'g',
1899                                     ' ',
1900                                     'A',
1901                                     ' ',
1902                                     'L',
1903                                     'o',
1904                                     'n',
1905                                     'g',
1906                                     ' ',
1907                                     'A',
1908                                     't',
1909                                     't',
1910                                     'r',
1911                                     'i',
1912                                     'b',
1913                                     'u',
1914                                     't',
1915                                     'e');
1916 
1917   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue);
1918   auto* attr = grp->AddAttribute(
1919       kTestType16, AllowedNoSecurity(), att::AccessRequirements());
1920 
1921   attr->set_read_handler(
1922       [&](PeerId peer_id, att::Handle handle, uint16_t offset, auto result_cb) {
1923         EXPECT_EQ(kTestPeerId, peer_id);
1924         EXPECT_EQ(attr->handle(), handle);
1925         EXPECT_EQ(22u, offset);
1926         result_cb(fit::ok(),
1927                   StaticByteBuffer('e',
1928                                    ' ',
1929                                    'U',
1930                                    's',
1931                                    'i',
1932                                    'n',
1933                                    'g',
1934                                    ' ',
1935                                    'A',
1936                                    ' ',
1937                                    'L',
1938                                    'o',
1939                                    'n',
1940                                    'g',
1941                                    ' ',
1942                                    'A',
1943                                    't',
1944                                    't',
1945                                    'r',
1946                                    'i',
1947                                    'b',
1948                                    'u'));
1949       });
1950   grp->set_active(true);
1951 
1952   // clang-format off
1953   const StaticByteBuffer kRequest(
1954       0x0C,       // opcode: read blob request
1955       0x02, 0x00, // handle: 0x0002
1956       0x16, 0x00  // offset: 0x0016
1957   );
1958   const StaticByteBuffer kExpected(
1959       0x0D,          // opcode: read blob response
1960       // Read Request response
1961       'e', ' ', 'U', 's', 'i', 'n', 'g', ' ', 'A', ' ', 'L',
1962       'o', 'n', 'g', ' ', 'A', 't', 't', 'r', 'i', 'b', 'u'
1963   );
1964   // clang-format on
1965 
1966   EXPECT_PACKET_OUT(kExpected);
1967   fake_chan()->Receive(kRequest);
1968 }
1969 
TEST_F(ServerTest,ReadBlobDynamicRequestError)1970 TEST_F(ServerTest, ReadBlobDynamicRequestError) {
1971   const StaticByteBuffer kTestValue('A',
1972                                     ' ',
1973                                     'V',
1974                                     'e',
1975                                     'r',
1976                                     'y',
1977                                     ' ',
1978                                     'L',
1979                                     'o',
1980                                     'n',
1981                                     'g',
1982                                     ' ',
1983                                     'D',
1984                                     'e',
1985                                     'v',
1986                                     'i',
1987                                     'c',
1988                                     'e',
1989                                     ' ',
1990                                     'N',
1991                                     'a',
1992                                     'm',
1993                                     'e',
1994                                     ' ',
1995                                     'U',
1996                                     's',
1997                                     'i',
1998                                     'n',
1999                                     'g',
2000                                     ' ',
2001                                     'A',
2002                                     ' ',
2003                                     'L',
2004                                     'o',
2005                                     'n',
2006                                     'g',
2007                                     ' ',
2008                                     'A',
2009                                     't',
2010                                     't',
2011                                     'r',
2012                                     'i',
2013                                     'b',
2014                                     'u',
2015                                     't',
2016                                     'e');
2017   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue);
2018   auto* attr = grp->AddAttribute(
2019       kTestType16, AllowedNoSecurity(), att::AccessRequirements());
2020   attr->set_read_handler(
2021       [&](PeerId peer_id, att::Handle handle, uint16_t, auto result_cb) {
2022         EXPECT_EQ(kTestPeerId, peer_id);
2023         EXPECT_EQ(attr->handle(), handle);
2024 
2025         result_cb(fit::error(att::ErrorCode::kUnlikelyError), BufferView());
2026       });
2027   grp->set_active(true);
2028 
2029   // clang-format off
2030   const StaticByteBuffer kRequest(
2031       0x0C,       // opcode: read blob request
2032       0x02, 0x00, // handle: 0x0002
2033       0x16, 0x00  // offset: 0x0016
2034       );
2035   const StaticByteBuffer kExpected(
2036       0x01,        // opcode: error response
2037       0x0C,        // request: read by type
2038       0x02, 0x00,  // handle: 0x0002 (the attribute causing the error)
2039       0x0E         // error: Unlikely error
2040   );
2041   // clang-format on
2042 
2043   EXPECT_PACKET_OUT(kExpected);
2044   fake_chan()->Receive(kRequest);
2045 }
2046 
TEST_F(ServerTest,ReadBlobRequestStaticSuccess)2047 TEST_F(ServerTest, ReadBlobRequestStaticSuccess) {
2048   const StaticByteBuffer kTestValue('A',
2049                                     ' ',
2050                                     'V',
2051                                     'e',
2052                                     'r',
2053                                     'y',
2054                                     ' ',
2055                                     'L',
2056                                     'o',
2057                                     'n',
2058                                     'g',
2059                                     ' ',
2060                                     'D',
2061                                     'e',
2062                                     'v',
2063                                     'i',
2064                                     'c',
2065                                     'e',
2066                                     ' ',
2067                                     'N',
2068                                     'a',
2069                                     'm',
2070                                     'e',
2071                                     ' ',
2072                                     'U',
2073                                     's',
2074                                     'i',
2075                                     'n',
2076                                     'g',
2077                                     ' ',
2078                                     'A',
2079                                     ' ',
2080                                     'L',
2081                                     'o',
2082                                     'n',
2083                                     'g',
2084                                     ' ',
2085                                     'A',
2086                                     't',
2087                                     't',
2088                                     'r',
2089                                     'i',
2090                                     'b',
2091                                     'u',
2092                                     't',
2093                                     'e');
2094 
2095   auto* grp = db()->NewGrouping(types::kPrimaryService, 0, kTestValue);
2096   grp->set_active(true);
2097 
2098   // clang-format off
2099   const StaticByteBuffer kRequest(
2100       0x0C,       // opcode: read blob request
2101       0x01, 0x00, // handle: 0x0002
2102       0x16, 0x00  // offset: 0x0016
2103   );
2104   const StaticByteBuffer kExpected(
2105       0x0D,          // opcode: read blob response
2106       // Read Request response
2107       'e', ' ', 'U', 's', 'i', 'n', 'g', ' ', 'A', ' ', 'L',
2108       'o', 'n', 'g', ' ', 'A', 't', 't', 'r', 'i', 'b', 'u'
2109   );
2110   // clang-format on
2111 
2112   EXPECT_PACKET_OUT(kExpected);
2113   fake_chan()->Receive(kRequest);
2114 }
2115 
TEST_F(ServerTest,ReadBlobRequestStaticOverflowError)2116 TEST_F(ServerTest, ReadBlobRequestStaticOverflowError) {
2117   const StaticByteBuffer kTestValue('s', 'h', 'o', 'r', 't', 'e', 'r');
2118 
2119   auto* grp = db()->NewGrouping(types::kPrimaryService, 0, kTestValue);
2120   grp->set_active(true);
2121 
2122   // clang-format off
2123   const StaticByteBuffer kRequest(
2124       0x0C,       // opcode: read blob request
2125       0x01, 0x00, // handle: 0x0001
2126       0x16, 0x10  // offset: 0x1016
2127   );
2128   const StaticByteBuffer kExpected(
2129       0x01,       // Error
2130       0x0C,       // opcode
2131       0x01, 0x00, // handle: 0x0001
2132       0x07        // InvalidOffset
2133   );
2134   // clang-format on
2135 
2136   EXPECT_PACKET_OUT(kExpected);
2137   fake_chan()->Receive(kRequest);
2138 }
2139 
TEST_F(ServerTest,ReadBlobRequestInvalidHandleError)2140 TEST_F(ServerTest, ReadBlobRequestInvalidHandleError) {
2141   const StaticByteBuffer kTestValue('A',
2142                                     ' ',
2143                                     'V',
2144                                     'e',
2145                                     'r',
2146                                     'y',
2147                                     ' ',
2148                                     'L',
2149                                     'o',
2150                                     'n',
2151                                     'g',
2152                                     ' ',
2153                                     'D',
2154                                     'e',
2155                                     'v',
2156                                     'i',
2157                                     'c',
2158                                     'e',
2159                                     ' ',
2160                                     'N',
2161                                     'a',
2162                                     'm',
2163                                     'e',
2164                                     ' ',
2165                                     'U',
2166                                     's',
2167                                     'i',
2168                                     'n',
2169                                     'g',
2170                                     ' ',
2171                                     'A',
2172                                     ' ',
2173                                     'L',
2174                                     'o',
2175                                     'n',
2176                                     'g',
2177                                     ' ',
2178                                     'A',
2179                                     't',
2180                                     't',
2181                                     'r',
2182                                     'i',
2183                                     'b',
2184                                     'u',
2185                                     't',
2186                                     'e');
2187   auto* grp = db()->NewGrouping(types::kPrimaryService, 0, kTestValue);
2188   grp->set_active(true);
2189 
2190   // clang-format off
2191   const StaticByteBuffer kRequest(
2192       0x0C,       // opcode: read blob request
2193       0x02, 0x30, // handle: 0x0002
2194       0x16, 0x00  // offset: 0x0016
2195       );
2196   const StaticByteBuffer kExpected(
2197       0x01,        // opcode: error response
2198       0x0C,        // request: read blob request
2199       0x02, 0x30,  // handle: 0x0001
2200       0x01         // error: invalid handle
2201   );
2202   // clang-format on
2203 
2204   EXPECT_PACKET_OUT(kExpected);
2205   fake_chan()->Receive(kRequest);
2206 }
2207 
TEST_F(ServerTest,ReadBlobRequestNotPermitedError)2208 TEST_F(ServerTest, ReadBlobRequestNotPermitedError) {
2209   const StaticByteBuffer kTestValue('A',
2210                                     ' ',
2211                                     'V',
2212                                     'e',
2213                                     'r',
2214                                     'y',
2215                                     ' ',
2216                                     'L',
2217                                     'o',
2218                                     'n',
2219                                     'g',
2220                                     ' ',
2221                                     'D',
2222                                     'e',
2223                                     'v',
2224                                     'i',
2225                                     'c',
2226                                     'e',
2227                                     ' ',
2228                                     'N',
2229                                     'a',
2230                                     'm',
2231                                     'e',
2232                                     ' ',
2233                                     'U',
2234                                     's',
2235                                     'i',
2236                                     'n',
2237                                     'g',
2238                                     ' ',
2239                                     'A',
2240                                     ' ',
2241                                     'L',
2242                                     'o',
2243                                     'n',
2244                                     'g',
2245                                     ' ',
2246                                     'A',
2247                                     't',
2248                                     't',
2249                                     'r',
2250                                     'i',
2251                                     'b',
2252                                     'u',
2253                                     't',
2254                                     'e');
2255   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue);
2256   auto* attr =
2257       grp->AddAttribute(kTestType16,
2258                         att::AccessRequirements(),
2259                         att::AccessRequirements(/*encryption=*/true,
2260                                                 /*authentication=*/false,
2261                                                 /*authorization=*/false));
2262   attr->set_read_handler(
2263       [&](PeerId peer_id, att::Handle handle, uint16_t, auto result_cb) {
2264         EXPECT_EQ(kTestPeerId, peer_id);
2265         EXPECT_EQ(attr->handle(), handle);
2266 
2267         result_cb(fit::error(att::ErrorCode::kUnlikelyError), BufferView());
2268       });
2269   grp->set_active(true);
2270 
2271   // clang-format off
2272   const StaticByteBuffer kRequest(
2273       0x0C,       // opcode: read blob request
2274       0x02, 0x00, // handle: 0x0002
2275       0x16, 0x00  // offset: 0x0016
2276       );
2277   const StaticByteBuffer kExpected(
2278       0x01,        // opcode: error response
2279       0x0C,        // request: read by type
2280       0x02, 0x00,  // handle: 0x0002 (the attribute causing the error)
2281       0x02         // error: Not Permitted
2282   );
2283   // clang-format on
2284 
2285   EXPECT_PACKET_OUT(kExpected);
2286   fake_chan()->Receive(kRequest);
2287 }
2288 
TEST_F(ServerTest,ReadBlobRequestInvalidOffsetError)2289 TEST_F(ServerTest, ReadBlobRequestInvalidOffsetError) {
2290   const StaticByteBuffer kTestValue('A',
2291                                     ' ',
2292                                     'V',
2293                                     'e',
2294                                     'r',
2295                                     'y',
2296                                     ' ',
2297                                     'L',
2298                                     'o',
2299                                     'n',
2300                                     'g',
2301                                     ' ',
2302                                     'D',
2303                                     'e',
2304                                     'v',
2305                                     'i',
2306                                     'c',
2307                                     'e',
2308                                     ' ',
2309                                     'N',
2310                                     'a',
2311                                     'm',
2312                                     'e',
2313                                     ' ',
2314                                     'U',
2315                                     's',
2316                                     'i',
2317                                     'n',
2318                                     'g',
2319                                     ' ',
2320                                     'A',
2321                                     ' ',
2322                                     'L',
2323                                     'o',
2324                                     'n',
2325                                     'g',
2326                                     ' ',
2327                                     'A',
2328                                     't',
2329                                     't',
2330                                     'r',
2331                                     'i',
2332                                     'b',
2333                                     'u',
2334                                     't',
2335                                     'e');
2336 
2337   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue);
2338   auto* attr = grp->AddAttribute(
2339       kTestType16, AllowedNoSecurity(), att::AccessRequirements());
2340   attr->set_read_handler(
2341       [&](PeerId peer_id, att::Handle handle, uint16_t, auto result_cb) {
2342         EXPECT_EQ(kTestPeerId, peer_id);
2343         EXPECT_EQ(attr->handle(), handle);
2344 
2345         result_cb(fit::error(att::ErrorCode::kInvalidOffset), BufferView());
2346       });
2347   grp->set_active(true);
2348 
2349   // clang-format off
2350   const StaticByteBuffer kRequest(
2351       0x0C,       // opcode: read blob request
2352       0x02, 0x00, // handle: 0x0002
2353       0x16, 0x40  // offset: 0x4016
2354       );
2355   const StaticByteBuffer kExpected(
2356       0x01,        // opcode: error response
2357       0x0C,        // request: read by type
2358       0x02, 0x00,  // handle: 0x0002 (the attribute causing the error)
2359       0x07         // error: Invalid Offset Error
2360   );
2361   // clang-format on
2362 
2363   EXPECT_PACKET_OUT(kExpected);
2364   fake_chan()->Receive(kRequest);
2365 }
2366 
TEST_F(ServerTest,ReadRequestSuccess)2367 TEST_F(ServerTest, ReadRequestSuccess) {
2368   const StaticByteBuffer kDeclValue('d', 'e', 'c', 'l');
2369   const StaticByteBuffer kTestValue('f', 'o', 'o');
2370   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue);
2371   auto* attr = grp->AddAttribute(
2372       kTestType16, AllowedNoSecurity(), att::AccessRequirements());
2373   attr->set_read_handler(
2374       [&](PeerId peer_id, att::Handle handle, uint16_t offset, auto result_cb) {
2375         EXPECT_EQ(kTestPeerId, peer_id);
2376         EXPECT_EQ(attr->handle(), handle);
2377         EXPECT_EQ(0u, offset);
2378 
2379         result_cb(fit::ok(), kTestValue);
2380       });
2381   grp->set_active(true);
2382 
2383   // clang-format off
2384   const StaticByteBuffer kRequest(
2385       0x0A,       // opcode: read request
2386       0x02, 0x00  // handle: 0x0002
2387   );
2388   const StaticByteBuffer kExpected(
2389       0x0B,          // opcode: read response
2390       'f', 'o', 'o'  // value: kTestValue
2391   );
2392   // clang-format on
2393 
2394   EXPECT_PACKET_OUT(kExpected);
2395   fake_chan()->Receive(kRequest);
2396 }
2397 
TEST_F(ServerTest,PrepareWriteRequestInvalidPDU)2398 TEST_F(ServerTest, PrepareWriteRequestInvalidPDU) {
2399   // Payload is one byte too short.
2400   // clang-format off
2401   const StaticByteBuffer kInvalidPDU(
2402       0x16,        // opcode: prepare write request
2403       0x01, 0x00,  // handle: 0x0001
2404       0x01         // offset (should be 2 bytes).
2405   );
2406   const StaticByteBuffer kExpected(
2407       0x01,        // opcode: error response
2408       0x16,        // request: prepare write request
2409       0x00, 0x00,  // handle: 0
2410       0x04         // error: Invalid PDU
2411   );
2412   // clang-format on
2413 
2414   EXPECT_PACKET_OUT(kExpected);
2415   fake_chan()->Receive(kInvalidPDU);
2416 }
2417 
TEST_F(ServerTest,PrepareWriteRequestInvalidHandle)2418 TEST_F(ServerTest, PrepareWriteRequestInvalidHandle) {
2419   // clang-format off
2420   const StaticByteBuffer kRequest(
2421       0x16,              // opcode: prepare write request
2422       0x01, 0x00,         // handle: 0x0001
2423       0x00, 0x00,         // offset: 0
2424       't', 'e', 's', 't'  // value: "test"
2425   );
2426   const StaticByteBuffer kResponse(
2427       0x01,        // opcode: error response
2428       0x16,        // request: prepare write request
2429       0x01, 0x00,  // handle: 0x0001
2430       0x01         // error: invalid handle
2431   );
2432   // clang-format on
2433 
2434   EXPECT_PACKET_OUT(kResponse);
2435   fake_chan()->Receive(kRequest);
2436 }
2437 
TEST_F(ServerTest,PrepareWriteRequestSucceeds)2438 TEST_F(ServerTest, PrepareWriteRequestSucceeds) {
2439   const StaticByteBuffer kTestValue('f', 'o', 'o');
2440   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue);
2441 
2442   // No security requirement
2443   auto* attr =
2444       grp->AddAttribute(kTestType16,
2445                         att::AccessRequirements(),
2446                         att::AccessRequirements(/*encryption=*/false,
2447                                                 /*authentication=*/false,
2448                                                 /*authorization=*/false));
2449   grp->set_active(true);
2450 
2451   int write_count = 0;
2452   attr->set_write_handler(
2453       [&](PeerId, att::Handle, uint16_t, const auto&, const auto&) {
2454         write_count++;
2455       });
2456 
2457   ASSERT_EQ(0x0002, attr->handle());
2458 
2459   // clang-format off
2460   const StaticByteBuffer kRequest(
2461       0x16,              // opcode: prepare write request
2462       0x02, 0x00,         // handle: 0x0002
2463       0x00, 0x00,         // offset: 0
2464       't', 'e', 's', 't'  // value: "test"
2465   );
2466   const StaticByteBuffer kResponse(
2467       0x17,              // opcode: prepare write response
2468       0x02, 0x00,         // handle: 0x0002
2469       0x00, 0x00,         // offset: 0
2470       't', 'e', 's', 't'  // value: "test"
2471   );
2472   // clang-format on
2473 
2474   EXPECT_PACKET_OUT(kResponse);
2475   fake_chan()->Receive(kRequest);
2476   // The attribute should not have been written yet.
2477   EXPECT_EQ(0, write_count);
2478 }
2479 
TEST_F(ServerTest,PrepareWriteRequestPrepareQueueFull)2480 TEST_F(ServerTest, PrepareWriteRequestPrepareQueueFull) {
2481   const StaticByteBuffer kTestValue('f', 'o', 'o');
2482   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue);
2483 
2484   // No security requirement
2485   const auto* attr =
2486       grp->AddAttribute(kTestType16,
2487                         att::AccessRequirements(),
2488                         att::AccessRequirements(/*encryption=*/false,
2489                                                 /*authentication=*/false,
2490                                                 /*authorization=*/false));
2491   grp->set_active(true);
2492 
2493   ASSERT_EQ(0x0002, attr->handle());
2494 
2495   // clang-format off
2496   const StaticByteBuffer kRequest(
2497       0x16,              // opcode: prepare write request
2498       0x02, 0x00,         // handle: 0x0002
2499       0x00, 0x00,         // offset: 0
2500       't', 'e', 's', 't'  // value: "test"
2501   );
2502   const StaticByteBuffer kSuccessResponse(
2503       0x17,              // opcode: prepare write response
2504       0x02, 0x00,         // handle: 0x0002
2505       0x00, 0x00,         // offset: 0
2506       't', 'e', 's', 't'  // value: "test"
2507   );
2508   const StaticByteBuffer kErrorResponse(
2509       0x01,        // opcode: error response
2510       0x16,        // request: prepare write request
2511       0x02, 0x00,  // handle: 0x0002
2512       0x09         // error: prepare queue full
2513   );
2514   // clang-format on
2515 
2516   // Write requests should succeed until capacity is filled.
2517   for (unsigned i = 0; i < att::kPrepareQueueMaxCapacity; i++) {
2518     EXPECT_PACKET_OUT(kSuccessResponse);
2519     fake_chan()->Receive(kRequest);
2520     ASSERT_TRUE(AllExpectedPacketsSent())
2521         << "Unexpected failure at attempt: " << i;
2522   }
2523 
2524   // The next request should fail with a capacity error.
2525   EXPECT_PACKET_OUT(kErrorResponse);
2526   fake_chan()->Receive(kRequest);
2527 }
2528 
TEST_F(ServerTest,ExecuteWriteMalformedPayload)2529 TEST_F(ServerTest, ExecuteWriteMalformedPayload) {
2530   // Payload is one byte too short.
2531   // clang-format off
2532   const StaticByteBuffer kInvalidPDU(
2533       0x18  // opcode: execute write request
2534   );
2535   const StaticByteBuffer kExpected(
2536       0x01,        // opcode: error response
2537       0x18,        // request: execute write request
2538       0x00, 0x00,  // handle: 0
2539       0x04         // error: Invalid PDU
2540   );
2541   // clang-format on
2542 
2543   EXPECT_PACKET_OUT(kExpected);
2544   fake_chan()->Receive(kInvalidPDU);
2545 }
2546 
TEST_F(ServerTest,ExecuteWriteInvalidFlag)2547 TEST_F(ServerTest, ExecuteWriteInvalidFlag) {
2548   // Payload is one byte too short.
2549   // clang-format off
2550   const StaticByteBuffer kInvalidPDU(
2551       0x18,  // opcode: execute write request
2552       0xFF   // flag: invalid
2553   );
2554   const StaticByteBuffer kExpected(
2555       0x01,        // opcode: error response
2556       0x18,        // request: execute write request
2557       0x00, 0x00,  // handle: 0
2558       0x04         // error: Invalid PDU
2559   );
2560   // clang-format on
2561 
2562   EXPECT_PACKET_OUT(kExpected);
2563   fake_chan()->Receive(kInvalidPDU);
2564 }
2565 
2566 // Tests that an "execute write request" without any prepared writes returns
2567 // success without writing to any attributes.
TEST_F(ServerTest,ExecuteWriteQueueEmpty)2568 TEST_F(ServerTest, ExecuteWriteQueueEmpty) {
2569   // clang-format off
2570   const StaticByteBuffer kExecute(
2571     0x18,  // opcode: execute write request
2572     0x01   // flag: "write pending"
2573   );
2574   const StaticByteBuffer kExecuteResponse(
2575     0x19  // opcode: execute write response
2576   );
2577   // clang-format on
2578 
2579   // |buffer| should contain the partial writes.
2580   EXPECT_PACKET_OUT(kExecuteResponse);
2581   fake_chan()->Receive(kExecute);
2582 }
2583 
TEST_F(ServerTest,ExecuteWriteSuccess)2584 TEST_F(ServerTest, ExecuteWriteSuccess) {
2585   StaticByteBuffer buffer('x', 'x', 'x', 'x', 'x', 'x');
2586 
2587   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue1);
2588   auto* attr = grp->AddAttribute(
2589       kTestType16, att::AccessRequirements(), AllowedNoSecurity());
2590   attr->set_write_handler([&](const auto& peer_id,
2591                               att::Handle handle,
2592                               uint16_t offset,
2593                               const auto& value,
2594                               auto result_cb) {
2595     EXPECT_EQ(kTestPeerId, peer_id);
2596     EXPECT_EQ(attr->handle(), handle);
2597 
2598     // Write the contents into |buffer|.
2599     buffer.Write(value, offset);
2600     result_cb(fit::ok());
2601   });
2602   grp->set_active(true);
2603 
2604   // Prepare two partial writes of the string "hello!".
2605   // clang-format off
2606   const StaticByteBuffer kPrepare1(
2607     0x016,              // opcode: prepare write request
2608     0x02, 0x00,         // handle: 0x0002
2609     0x00, 0x00,         // offset: 0
2610     'h', 'e', 'l', 'l'  // value: "hell"
2611   );
2612   const StaticByteBuffer kPrepareResponse1(
2613     0x017,              // opcode: prepare write response
2614     0x02, 0x00,         // handle: 0x0002
2615     0x00, 0x00,         // offset: 0
2616     'h', 'e', 'l', 'l'  // value: "hell"
2617   );
2618   const StaticByteBuffer kPrepare2(
2619     0x016,              // opcode: prepare write request
2620     0x02, 0x00,         // handle: 0x0002
2621     0x04, 0x00,         // offset: 4
2622     'o', '!'            // value: "o!"
2623   );
2624   const StaticByteBuffer kPrepareResponse2(
2625     0x017,              // opcode: prepare write response
2626     0x02, 0x00,         // handle: 0x0002
2627     0x04, 0x00,         // offset: 4
2628     'o', '!'            // value: "o!"
2629   );
2630 
2631   // Add an overlapping write that partial overwrites data from previous
2632   // payloads.
2633   const StaticByteBuffer kPrepare3(
2634     0x016,              // opcode: prepare write request
2635     0x02, 0x00,         // handle: 0x0002
2636     0x02, 0x00,         // offset: 2
2637     'r', 'p', '?'       // value: "rp?"
2638   );
2639   const StaticByteBuffer kPrepareResponse3(
2640     0x017,              // opcode: prepare write response
2641     0x02, 0x00,         // handle: 0x0002
2642     0x02, 0x00,         // offset: 2
2643     'r', 'p', '?'       // value: "rp?"
2644   );
2645 
2646   // clang-format on
2647 
2648   EXPECT_PACKET_OUT(kPrepareResponse1);
2649   fake_chan()->Receive(kPrepare1);
2650   EXPECT_PACKET_OUT(kPrepareResponse2);
2651   fake_chan()->Receive(kPrepare2);
2652   EXPECT_PACKET_OUT(kPrepareResponse3);
2653   fake_chan()->Receive(kPrepare3);
2654 
2655   // The writes should not be committed yet.
2656   EXPECT_EQ("xxxxxx", buffer.AsString());
2657 
2658   // clang-format off
2659   const StaticByteBuffer kExecute(
2660     0x18,  // opcode: execute write request
2661     0x01   // flag: "write pending"
2662   );
2663   const StaticByteBuffer kExecuteResponse(
2664     0x19  // opcode: execute write response
2665   );
2666   // clang-format on
2667 
2668   // |buffer| should contain the partial writes.
2669   EXPECT_PACKET_OUT(kExecuteResponse);
2670   fake_chan()->Receive(kExecute);
2671   EXPECT_EQ("herp?!", buffer.AsString());
2672 }
2673 
2674 // Tests that the rest of the queue is dropped if a prepared write fails.
TEST_F(ServerTest,ExecuteWriteError)2675 TEST_F(ServerTest, ExecuteWriteError) {
2676   StaticByteBuffer buffer('x', 'x', 'x', 'x', 'x', 'x');
2677 
2678   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue1);
2679   auto* attr = grp->AddAttribute(
2680       kTestType16, att::AccessRequirements(), AllowedNoSecurity());
2681   attr->set_write_handler([&](const auto& peer_id,
2682                               att::Handle handle,
2683                               uint16_t offset,
2684                               const auto& value,
2685                               auto result_cb) {
2686     EXPECT_EQ(kTestPeerId, peer_id);
2687     EXPECT_EQ(attr->handle(), handle);
2688 
2689     // Make the write to non-zero offsets fail (this corresponds to the second
2690     // partial write we prepare below.
2691     if (offset) {
2692       result_cb(fit::error(att::ErrorCode::kUnlikelyError));
2693     } else {
2694       buffer.Write(value);
2695       result_cb(fit::ok());
2696     }
2697   });
2698   grp->set_active(true);
2699 
2700   // Prepare two partial writes of the string "hello!".
2701   // clang-format off
2702   const StaticByteBuffer kPrepare1(
2703     0x016,              // opcode: prepare write request
2704     0x02, 0x00,         // handle: 0x0002
2705     0x00, 0x00,         // offset: 0
2706     'h', 'e', 'l', 'l'  // value: "hell"
2707   );
2708   const StaticByteBuffer kPrepareResponse1(
2709     0x017,              // opcode: prepare write response
2710     0x02, 0x00,         // handle: 0x0002
2711     0x00, 0x00,         // offset: 0
2712     'h', 'e', 'l', 'l'  // value: "hell"
2713   );
2714   const StaticByteBuffer kPrepare2(
2715     0x016,              // opcode: prepare write request
2716     0x02, 0x00,         // handle: 0x0002
2717     0x04, 0x00,         // offset: 4
2718     'o', '!'            // value: "o!"
2719   );
2720   const StaticByteBuffer kPrepareResponse2(
2721     0x017,              // opcode: prepare write response
2722     0x02, 0x00,         // handle: 0x0002
2723     0x04, 0x00,         // offset: 4
2724     'o', '!'            // value: "o!"
2725   );
2726   // clang-format on
2727 
2728   EXPECT_PACKET_OUT(kPrepareResponse1);
2729   fake_chan()->Receive(kPrepare1);
2730   EXPECT_PACKET_OUT(kPrepareResponse2);
2731   fake_chan()->Receive(kPrepare2);
2732 
2733   // The writes should not be committed yet.
2734   EXPECT_EQ("xxxxxx", buffer.AsString());
2735 
2736   // clang-format off
2737   const StaticByteBuffer kExecute(
2738     0x18,  // opcode: execute write request
2739     0x01   // flag: "write pending"
2740   );
2741   const StaticByteBuffer kExecuteResponse(
2742     0x01,        // opcode: error response
2743     0x18,        // request: execute write request
2744     0x02, 0x00,  // handle: 2 (the attribute in error)
2745     0x0E         // error: Unlikely Error (returned by callback above).
2746   );
2747   // clang-format on
2748 
2749   // Only the first partial write should have gone through as the second one
2750   // is expected to fail.
2751   EXPECT_PACKET_OUT(kExecuteResponse);
2752   fake_chan()->Receive(kExecute);
2753   EXPECT_EQ("hellxx", buffer.AsString());
2754 }
2755 
TEST_F(ServerTest,ExecuteWriteAbort)2756 TEST_F(ServerTest, ExecuteWriteAbort) {
2757   auto* grp = db()->NewGrouping(types::kPrimaryService, 1, kTestValue1);
2758   // |attr| has handle "2".
2759   auto* attr = grp->AddAttribute(
2760       kTestType16, att::AccessRequirements(), AllowedNoSecurity());
2761 
2762   int write_count = 0;
2763   attr->set_write_handler([&](const auto& peer_id,
2764                               att::Handle handle,
2765                               uint16_t offset,
2766                               const auto& value,
2767                               auto result_cb) {
2768     write_count++;
2769 
2770     EXPECT_EQ(kTestPeerId, peer_id);
2771     EXPECT_EQ(attr->handle(), handle);
2772     EXPECT_EQ(0u, offset);
2773     EXPECT_TRUE(ContainersEqual(StaticByteBuffer('l', 'o', 'l'), value));
2774     result_cb(fit::ok());
2775   });
2776   grp->set_active(true);
2777 
2778   // clang-format off
2779   const StaticByteBuffer kPrepareToAbort(
2780     0x016,              // opcode: prepare write request
2781     0x02, 0x00,         // handle: 0x0002
2782     0x00, 0x00,         // offset: 0
2783     't', 'e', 's', 't'  // value: "test"
2784   );
2785   const StaticByteBuffer kPrepareToAbortResponse(
2786     0x017,              // opcode: prepare write response
2787     0x02, 0x00,         // handle: 0x0002
2788     0x00, 0x00,         // offset: 0
2789     't', 'e', 's', 't'  // value: "test"
2790   );
2791   // clang-format on
2792 
2793   // Prepare writes. These should get committed right away.
2794   EXPECT_PACKET_OUT(kPrepareToAbortResponse);
2795   fake_chan()->Receive(kPrepareToAbort);
2796   EXPECT_PACKET_OUT(kPrepareToAbortResponse);
2797   fake_chan()->Receive(kPrepareToAbort);
2798   EXPECT_PACKET_OUT(kPrepareToAbortResponse);
2799   fake_chan()->Receive(kPrepareToAbort);
2800   EXPECT_PACKET_OUT(kPrepareToAbortResponse);
2801   fake_chan()->Receive(kPrepareToAbort);
2802   EXPECT_TRUE(AllExpectedPacketsSent());
2803   EXPECT_EQ(0, write_count);
2804 
2805   // Abort the writes. They should get dropped.
2806   // clang-format off
2807   const StaticByteBuffer kAbort(
2808     0x18,  // opcode: execute write request
2809     0x00   // flag: "cancel all"
2810   );
2811   const StaticByteBuffer kAbortResponse(
2812     0x19  // opcode: execute write response
2813   );
2814   // clang-format on
2815   EXPECT_PACKET_OUT(kAbortResponse);
2816   fake_chan()->Receive(kAbort);
2817   EXPECT_EQ(0, write_count);
2818 
2819   // Prepare and commit a new write request. This one should take effect without
2820   // involving the previously aborted writes.
2821   // clang-format off
2822   const StaticByteBuffer kPrepareToCommit(
2823     0x016,              // opcode: prepare write request
2824     0x02, 0x00,         // handle: 0x0002
2825     0x00, 0x00,         // offset: 0
2826     'l', 'o', 'l'       // value: "lol"
2827   );
2828   const StaticByteBuffer kPrepareToCommitResponse(
2829     0x017,              // opcode: prepare write response
2830     0x02, 0x00,         // handle: 0x0002
2831     0x00, 0x00,         // offset: 0
2832     'l', 'o', 'l'       // value: "lol"
2833   );
2834   const StaticByteBuffer kCommit(
2835     0x18,  // opcode: execute write request
2836     0x01   // flag: "write pending"
2837   );
2838   const StaticByteBuffer kCommitResponse(
2839     0x19  // opcode: execute write response
2840   );
2841   // clang-format on
2842 
2843   EXPECT_PACKET_OUT(kPrepareToCommitResponse);
2844   fake_chan()->Receive(kPrepareToCommit);
2845   EXPECT_PACKET_OUT(kCommitResponse);
2846   fake_chan()->Receive(kCommit);
2847   EXPECT_EQ(1, write_count);
2848 }
2849 
TEST_F(ServerTest,TrySendNotificationNoCccConfig)2850 TEST_F(ServerTest, TrySendNotificationNoCccConfig) {
2851   IdType svc_id =
2852       RegisterSvcWithSingleChrc(kTestSvcType, kTestChrcId, kTestChrcType);
2853   const BufferView kTestValue;
2854   server()->SendUpdate(
2855       svc_id, kTestChrcId, kTestValue, /*indicate_cb=*/nullptr);
2856 }
2857 
TEST_F(ServerTest,TrySendNotificationConfiguredForIndicationsOnly)2858 TEST_F(ServerTest, TrySendNotificationConfiguredForIndicationsOnly) {
2859   SvcIdAndChrcHandle registered = RegisterSvcWithConfiguredChrc(
2860       kTestSvcType, kTestChrcId, kTestChrcType, kCCCIndicationBit);
2861   const BufferView kTestValue;
2862   server()->SendUpdate(
2863       registered.svc_id, kTestChrcId, kTestValue, /*indicate_cb=*/nullptr);
2864 }
2865 
TEST_F(ServerTest,SendNotificationEmpty)2866 TEST_F(ServerTest, SendNotificationEmpty) {
2867   SvcIdAndChrcHandle registered =
2868       RegisterSvcWithConfiguredChrc(kTestSvcType, kTestChrcId, kTestChrcType);
2869   const BufferView kTestValue;
2870 
2871   // clang-format off
2872   const StaticByteBuffer kExpected{
2873     att::kNotification,  // Opcode
2874     // Handle of the characteristic value being notified
2875     LowerBits(registered.chrc_val_handle), UpperBits(registered.chrc_val_handle)
2876   };
2877   // clang-format on
2878 
2879   EXPECT_PACKET_OUT(kExpected);
2880   server()->SendUpdate(
2881       registered.svc_id, kTestChrcId, kTestValue, /*indicate_cb=*/nullptr);
2882 }
2883 
TEST_F(ServerTest,SendNotification)2884 TEST_F(ServerTest, SendNotification) {
2885   SvcIdAndChrcHandle registered =
2886       RegisterSvcWithConfiguredChrc(kTestSvcType, kTestChrcId, kTestChrcType);
2887   const StaticByteBuffer kTestValue('f', 'o', 'o');
2888 
2889   // clang-format off
2890   const StaticByteBuffer kExpected{
2891     att::kNotification,  // Opcode
2892     // Handle of the characteristic value being notified
2893     LowerBits(registered.chrc_val_handle), UpperBits(registered.chrc_val_handle),
2894     kTestValue[0], kTestValue[1], kTestValue[2]
2895   };
2896   // clang-format on
2897 
2898   EXPECT_PACKET_OUT(kExpected);
2899   server()->SendUpdate(registered.svc_id,
2900                        kTestChrcId,
2901                        kTestValue.view(),
2902                        /*indicate_cb=*/nullptr);
2903 }
2904 
TEST_F(ServerTest,TrySendIndicationNoCccConfig)2905 TEST_F(ServerTest, TrySendIndicationNoCccConfig) {
2906   IdType svc_id =
2907       RegisterSvcWithSingleChrc(kTestSvcType, kTestChrcId, kTestChrcType);
2908   const BufferView kTestValue;
2909 
2910   att::Result<> indicate_res = fit::ok();
2911   auto indicate_cb = [&](att::Result<> res) { indicate_res = res; };
2912 
2913   server()->SendUpdate(svc_id, kTestChrcId, kTestValue, std::move(indicate_cb));
2914   EXPECT_EQ(fit::failed(), indicate_res);
2915 }
2916 
TEST_F(ServerTest,TrySendIndicationConfiguredForNotificationsOnly)2917 TEST_F(ServerTest, TrySendIndicationConfiguredForNotificationsOnly) {
2918   SvcIdAndChrcHandle registered = RegisterSvcWithConfiguredChrc(
2919       kTestSvcType, kTestChrcId, kTestChrcType, kCCCNotificationBit);
2920   const BufferView kTestValue;
2921 
2922   att::Result<> indicate_res = fit::ok();
2923   auto indicate_cb = [&](att::Result<> res) { indicate_res = res; };
2924 
2925   server()->SendUpdate(
2926       registered.svc_id, kTestChrcId, kTestValue, std::move(indicate_cb));
2927   EXPECT_EQ(fit::failed(), indicate_res);
2928 }
2929 
TEST_F(ServerTest,SendIndicationEmpty)2930 TEST_F(ServerTest, SendIndicationEmpty) {
2931   SvcIdAndChrcHandle registered =
2932       RegisterSvcWithConfiguredChrc(kTestSvcType, kTestChrcId, kTestChrcType);
2933   const BufferView kTestValue;
2934 
2935   att::Result<> indicate_res = ToResult(HostError::kFailed);
2936   auto indicate_cb = [&](att::Result<> res) { indicate_res = res; };
2937 
2938   // clang-format off
2939   const StaticByteBuffer kExpected{
2940     att::kIndication,  // Opcode
2941     // Handle of the characteristic value being notified
2942     LowerBits(registered.chrc_val_handle), UpperBits(registered.chrc_val_handle)
2943   };
2944   // clang-format on
2945 
2946   EXPECT_PACKET_OUT(kExpected);
2947   server()->SendUpdate(
2948       registered.svc_id, kTestChrcId, kTestValue, std::move(indicate_cb));
2949   EXPECT_TRUE(AllExpectedPacketsSent());
2950 
2951   const StaticByteBuffer kIndicationConfirmation{att::kConfirmation};
2952   fake_chan()->Receive(kIndicationConfirmation);
2953   EXPECT_EQ(fit::ok(), indicate_res);
2954 }
2955 
TEST_F(ServerTest,SendIndication)2956 TEST_F(ServerTest, SendIndication) {
2957   SvcIdAndChrcHandle registered =
2958       RegisterSvcWithConfiguredChrc(kTestSvcType, kTestChrcId, kTestChrcType);
2959   const StaticByteBuffer kTestValue('f', 'o', 'o');
2960 
2961   att::Result<> indicate_res = ToResult(HostError::kFailed);
2962   auto indicate_cb = [&](att::Result<> res) { indicate_res = res; };
2963 
2964   // clang-format off
2965   const StaticByteBuffer kExpected{
2966     att::kIndication,  // Opcode
2967     // Handle of the characteristic value being notified
2968     LowerBits(registered.chrc_val_handle), UpperBits(registered.chrc_val_handle),
2969     kTestValue[0], kTestValue[1], kTestValue[2]
2970   };
2971   // clang-format on
2972 
2973   EXPECT_PACKET_OUT(kExpected);
2974   server()->SendUpdate(registered.svc_id,
2975                        kTestChrcId,
2976                        kTestValue.view(),
2977                        std::move(indicate_cb));
2978   EXPECT_TRUE(AllExpectedPacketsSent());
2979 
2980   const StaticByteBuffer kIndicationConfirmation{att::kConfirmation};
2981   fake_chan()->Receive(kIndicationConfirmation);
2982   EXPECT_EQ(fit::ok(), indicate_res);
2983 }
2984 
2985 class ServerTestSecurity : public ServerTest {
2986  protected:
InitializeAttributesForReading()2987   void InitializeAttributesForReading() {
2988     auto* grp = db()->NewGrouping(types::kPrimaryService, 4, kTestValue1);
2989 
2990     const att::AccessRequirements encryption(/*encryption=*/true,
2991                                              /*authentication=*/false,
2992                                              /*authorization=*/false);
2993     const att::AccessRequirements authentication(/*encryption=*/false,
2994                                                  /*authentication=*/true,
2995                                                  /*authorization=*/false);
2996     const att::AccessRequirements authorization(/*encryption=*/false,
2997                                                 /*authentication=*/false,
2998                                                 /*authorization=*/true);
2999 
3000     not_permitted_attr_ = grp->AddAttribute(kTestType16);
3001     encryption_required_attr_ = grp->AddAttribute(kTestType16, encryption);
3002     authentication_required_attr_ =
3003         grp->AddAttribute(kTestType16, authentication);
3004     authorization_required_attr_ =
3005         grp->AddAttribute(kTestType16, authorization);
3006 
3007     // Assigns all tests attributes a static value. Intended to be used by read
3008     // requests. (Note: assigning a static value makes an attribute
3009     // non-writable). All attributes are assigned kTestValue1 as their static
3010     // value.
3011     not_permitted_attr_->SetValue(kTestValue1);
3012     encryption_required_attr_->SetValue(kTestValue1);
3013     authentication_required_attr_->SetValue(kTestValue1);
3014     authorization_required_attr_->SetValue(kTestValue1);
3015 
3016     grp->set_active(true);
3017   }
3018 
InitializeAttributesForWriting()3019   void InitializeAttributesForWriting() {
3020     auto* grp = db()->NewGrouping(types::kPrimaryService, 4, kTestValue1);
3021 
3022     const att::AccessRequirements encryption(/*encryption=*/true,
3023                                              /*authentication=*/false,
3024                                              /*authorization=*/false);
3025     const att::AccessRequirements authentication(/*encryption=*/false,
3026                                                  /*authentication=*/true,
3027                                                  /*authorization=*/false);
3028     const att::AccessRequirements authorization(/*encryption=*/false,
3029                                                 /*authentication=*/false,
3030                                                 /*authorization=*/true);
3031 
3032     auto write_handler =
3033         [this](
3034             const auto&, att::Handle, uint16_t, const auto&, auto responder) {
3035           write_count_++;
3036           if (responder) {
3037             responder(fit::ok());
3038           }
3039         };
3040 
3041     not_permitted_attr_ = grp->AddAttribute(kTestType16);
3042     not_permitted_attr_->set_write_handler(write_handler);
3043 
3044     encryption_required_attr_ =
3045         grp->AddAttribute(kTestType16, att::AccessRequirements(), encryption);
3046     encryption_required_attr_->set_write_handler(write_handler);
3047 
3048     authentication_required_attr_ = grp->AddAttribute(
3049         kTestType16, att::AccessRequirements(), authentication);
3050     authentication_required_attr_->set_write_handler(write_handler);
3051 
3052     authorization_required_attr_ = grp->AddAttribute(
3053         kTestType16, att::AccessRequirements(), authorization);
3054     authorization_required_attr_->set_write_handler(write_handler);
3055 
3056     grp->set_active(true);
3057   }
3058 
MakeAttError(att::OpCode request,att::Handle handle,att::ErrorCode ecode)3059   auto MakeAttError(att::OpCode request,
3060                     att::Handle handle,
3061                     att::ErrorCode ecode) {
3062     return StaticByteBuffer(0x01,     // opcode: error response
3063                             request,  // request opcode
3064                             LowerBits(handle),
3065                             UpperBits(handle),  // handle
3066                             ecode               // error code
3067     );
3068   }
3069 
3070   // Helpers for emulating the receipt of an ATT read/write request PDU and
3071   // expecting back a security error. Expects a successful response if
3072   // |expected_status| is fit::ok().
EmulateReadByTypeRequest(att::Handle handle,fit::result<att::ErrorCode> expected_status)3073   bool EmulateReadByTypeRequest(att::Handle handle,
3074                                 fit::result<att::ErrorCode> expected_status) {
3075     const StaticByteBuffer kReadByTypeRequestPdu(
3076         0x08,  // opcode: read by type
3077         LowerBits(handle),
3078         UpperBits(handle),  // start handle
3079         LowerBits(handle),
3080         UpperBits(handle),  // end handle
3081         0xEF,
3082         0xBE);  // type: 0xBEEF, i.e. kTestType16
3083     if (expected_status.is_ok()) {
3084       EXPECT_PACKET_OUT(StaticByteBuffer(0x09,  // opcode: read by type response
3085                                          0x05,  // length: 5 (strlen("foo") + 2)
3086                                          LowerBits(handle),
3087                                          UpperBits(handle),  // handle
3088                                          'f',
3089                                          'o',
3090                                          'o'  // value: "foo", i.e. kTestValue1
3091                                          ));
3092     } else {
3093       EXPECT_PACKET_OUT(
3094           MakeAttError(0x08, handle, expected_status.error_value()));
3095     }
3096     fake_chan()->Receive(kReadByTypeRequestPdu);
3097     return AllExpectedPacketsSent();
3098   }
3099 
EmulateReadBlobRequest(att::Handle handle,fit::result<att::ErrorCode> expected_status)3100   bool EmulateReadBlobRequest(att::Handle handle,
3101                               fit::result<att::ErrorCode> expected_status) {
3102     const StaticByteBuffer kReadBlobRequestPdu(0x0C,  // opcode: read blob
3103                                                LowerBits(handle),
3104                                                UpperBits(handle),  // handle
3105                                                0x00,
3106                                                0x00);  // offset: 0
3107     if (expected_status.is_ok()) {
3108       EXPECT_PACKET_OUT(StaticByteBuffer(0x0D,  // opcode: read blob response
3109                                          'f',
3110                                          'o',
3111                                          'o'  // value: "foo", i.e. kTestValue1
3112                                          ));
3113     } else {
3114       EXPECT_PACKET_OUT(
3115           MakeAttError(0x0C, handle, expected_status.error_value()));
3116     }
3117     fake_chan()->Receive(kReadBlobRequestPdu);
3118     return AllExpectedPacketsSent();
3119   }
3120 
EmulateReadRequest(att::Handle handle,fit::result<att::ErrorCode> expected_status)3121   bool EmulateReadRequest(att::Handle handle,
3122                           fit::result<att::ErrorCode> expected_status) {
3123     const StaticByteBuffer kReadRequestPdu(0x0A,  // opcode: read request
3124                                            LowerBits(handle),
3125                                            UpperBits(handle));  // handle
3126     if (expected_status.is_ok()) {
3127       EXPECT_PACKET_OUT(StaticByteBuffer(0x0B,  // opcode: read response
3128                                          'f',
3129                                          'o',
3130                                          'o'  // value: "foo", i.e. kTestValue1
3131                                          ));
3132     } else {
3133       EXPECT_PACKET_OUT(
3134           MakeAttError(0x0A, handle, expected_status.error_value()));
3135     }
3136     fake_chan()->Receive(kReadRequestPdu);
3137     return AllExpectedPacketsSent();
3138   }
3139 
EmulateWriteRequest(att::Handle handle,fit::result<att::ErrorCode> expected_status)3140   bool EmulateWriteRequest(att::Handle handle,
3141                            fit::result<att::ErrorCode> expected_status) {
3142     const StaticByteBuffer kWriteRequestPdu(0x12,  // opcode: write request
3143                                             LowerBits(handle),
3144                                             UpperBits(handle),  // handle
3145                                             't',
3146                                             'e',
3147                                             's',
3148                                             't');  // value: "test"
3149     if (expected_status.is_ok()) {
3150       EXPECT_PACKET_OUT(StaticByteBuffer(0x13));
3151     } else {
3152       EXPECT_PACKET_OUT(
3153           MakeAttError(0x12, handle, expected_status.error_value()));
3154     }
3155     fake_chan()->Receive(kWriteRequestPdu);
3156     return AllExpectedPacketsSent();
3157   }
3158 
EmulatePrepareWriteRequest(att::Handle handle,fit::result<att::ErrorCode> expected_status)3159   bool EmulatePrepareWriteRequest(att::Handle handle,
3160                                   fit::result<att::ErrorCode> expected_status) {
3161     const auto kPrepareWriteRequestPdu =
3162         StaticByteBuffer(0x16,  // opcode: prepare write request
3163                          LowerBits(handle),
3164                          UpperBits(handle),  // handle
3165                          0x00,
3166                          0x00,  // offset: 0
3167                          't',
3168                          'e',
3169                          's',
3170                          't'  // value: "test"
3171         );
3172     if (expected_status.is_ok()) {
3173       EXPECT_PACKET_OUT(StaticByteBuffer(0x17,  // prepare write response
3174                                          LowerBits(handle),
3175                                          UpperBits(handle),  // handle
3176                                          0x00,
3177                                          0x00,  // offset: 0
3178                                          't',
3179                                          'e',
3180                                          's',
3181                                          't'  // value: "test"
3182                                          ));
3183     } else {
3184       EXPECT_PACKET_OUT(
3185           MakeAttError(0x16, handle, expected_status.error_value()));
3186     }
3187     fake_chan()->Receive(kPrepareWriteRequestPdu);
3188     return AllExpectedPacketsSent();
3189   }
3190 
3191   // Emulates the receipt of a Write Command. The expected error code parameter
3192   // is unused since ATT commands do not have a response.
EmulateWriteCommand(att::Handle handle,fit::result<att::ErrorCode>)3193   bool EmulateWriteCommand(att::Handle handle, fit::result<att::ErrorCode>) {
3194     fake_chan()->Receive(StaticByteBuffer(0x52,  // opcode: write command
3195                                           LowerBits(handle),
3196                                           UpperBits(handle),  // handle
3197                                           't',
3198                                           'e',
3199                                           's',
3200                                           't'  // value: "test"
3201                                           ));
3202     RunUntilIdle();
3203     return true;
3204   }
3205 
3206   template <bool (ServerTestSecurity::*EmulateMethod)(
3207                 att::Handle, fit::result<att::ErrorCode>),
3208             bool IsWrite>
RunTest()3209   void RunTest() {
3210     const fit::error<att::ErrorCode> kNotPermittedError =
3211         fit::error(IsWrite ? att::ErrorCode::kWriteNotPermitted
3212                            : att::ErrorCode::kReadNotPermitted);
3213 
3214     // No security.
3215     EXPECT_TRUE((this->*EmulateMethod)(not_permitted_attr()->handle(),
3216                                        fit::error(kNotPermittedError)));
3217     EXPECT_TRUE((this->*EmulateMethod)(
3218         encryption_required_attr()->handle(),
3219         fit::error(att::ErrorCode::kInsufficientAuthentication)));
3220     EXPECT_TRUE((this->*EmulateMethod)(
3221         authentication_required_attr()->handle(),
3222         fit::error(att::ErrorCode::kInsufficientAuthentication)));
3223     EXPECT_TRUE((this->*EmulateMethod)(
3224         authorization_required_attr()->handle(),
3225         fit::error(att::ErrorCode::kInsufficientAuthentication)));
3226 
3227     // Link encrypted.
3228     fake_chan()->set_security(sm::SecurityProperties(
3229         sm::SecurityLevel::kEncrypted, 16, /*secure_connections=*/false));
3230     EXPECT_TRUE((this->*EmulateMethod)(not_permitted_attr()->handle(),
3231                                        kNotPermittedError));
3232     EXPECT_TRUE((this->*EmulateMethod)(encryption_required_attr()->handle(),
3233                                        fit::ok()));
3234     EXPECT_TRUE((this->*EmulateMethod)(
3235         authentication_required_attr()->handle(),
3236         fit::error(att::ErrorCode::kInsufficientAuthentication)));
3237     EXPECT_TRUE((this->*EmulateMethod)(
3238         authorization_required_attr()->handle(),
3239         fit::error(att::ErrorCode::kInsufficientAuthentication)));
3240 
3241     // inclusive-language: ignore
3242     // Link encrypted w/ MITM.
3243     fake_chan()->set_security(
3244         sm::SecurityProperties(sm::SecurityLevel::kAuthenticated,
3245                                16,
3246                                /*secure_connections=*/false));
3247     EXPECT_TRUE((this->*EmulateMethod)(not_permitted_attr()->handle(),
3248                                        kNotPermittedError));
3249     EXPECT_TRUE((this->*EmulateMethod)(encryption_required_attr()->handle(),
3250                                        fit::ok()));
3251     EXPECT_TRUE((this->*EmulateMethod)(authentication_required_attr()->handle(),
3252                                        fit::ok()));
3253     EXPECT_TRUE((this->*EmulateMethod)(authorization_required_attr()->handle(),
3254                                        fit::ok()));
3255   }
3256 
RunReadByTypeTest()3257   void RunReadByTypeTest() {
3258     RunTest<&ServerTestSecurity::EmulateReadByTypeRequest, false>();
3259   }
RunReadBlobTest()3260   void RunReadBlobTest() {
3261     RunTest<&ServerTestSecurity::EmulateReadBlobRequest, false>();
3262   }
RunReadRequestTest()3263   void RunReadRequestTest() {
3264     RunTest<&ServerTestSecurity::EmulateReadRequest, false>();
3265   }
RunWriteRequestTest()3266   void RunWriteRequestTest() {
3267     RunTest<&ServerTestSecurity::EmulateWriteRequest, true>();
3268   }
RunPrepareWriteRequestTest()3269   void RunPrepareWriteRequestTest() {
3270     RunTest<&ServerTestSecurity::EmulatePrepareWriteRequest, true>();
3271   }
RunWriteCommandTest()3272   void RunWriteCommandTest() {
3273     RunTest<&ServerTestSecurity::EmulateWriteCommand, true>();
3274   }
3275 
not_permitted_attr() const3276   const att::Attribute* not_permitted_attr() const {
3277     return not_permitted_attr_;
3278   }
encryption_required_attr() const3279   const att::Attribute* encryption_required_attr() const {
3280     return encryption_required_attr_;
3281   }
authentication_required_attr() const3282   const att::Attribute* authentication_required_attr() const {
3283     return authentication_required_attr_;
3284   }
authorization_required_attr() const3285   const att::Attribute* authorization_required_attr() const {
3286     return authorization_required_attr_;
3287   }
3288 
write_count() const3289   size_t write_count() const { return write_count_; }
3290 
3291  private:
3292   att::Attribute* not_permitted_attr_ = nullptr;
3293   att::Attribute* encryption_required_attr_ = nullptr;
3294   att::Attribute* authentication_required_attr_ = nullptr;
3295   att::Attribute* authorization_required_attr_ = nullptr;
3296 
3297   size_t write_count_ = 0u;
3298 };
3299 
3300 // Tests receiving a Read By Type error under 3 possible link security levels.
TEST_F(ServerTestSecurity,ReadByTypeErrorSecurity)3301 TEST_F(ServerTestSecurity, ReadByTypeErrorSecurity) {
3302   InitializeAttributesForReading();
3303   RunReadByTypeTest();
3304 }
3305 
TEST_F(ServerTestSecurity,ReadBlobErrorSecurity)3306 TEST_F(ServerTestSecurity, ReadBlobErrorSecurity) {
3307   InitializeAttributesForReading();
3308   RunReadBlobTest();
3309 }
3310 
TEST_F(ServerTestSecurity,ReadErrorSecurity)3311 TEST_F(ServerTestSecurity, ReadErrorSecurity) {
3312   InitializeAttributesForReading();
3313   RunReadRequestTest();
3314 }
3315 
TEST_F(ServerTestSecurity,WriteErrorSecurity)3316 TEST_F(ServerTestSecurity, WriteErrorSecurity) {
3317   InitializeAttributesForWriting();
3318   RunWriteRequestTest();
3319 
3320   // Only 4 writes should have gone through.
3321   EXPECT_EQ(4u, write_count());
3322 }
3323 
TEST_F(ServerTestSecurity,WriteCommandErrorSecurity)3324 TEST_F(ServerTestSecurity, WriteCommandErrorSecurity) {
3325   InitializeAttributesForWriting();
3326   RunWriteCommandTest();
3327 
3328   // Only 4 writes should have gone through.
3329   EXPECT_EQ(4u, write_count());
3330 }
3331 
TEST_F(ServerTestSecurity,PrepareWriteRequestSecurity)3332 TEST_F(ServerTestSecurity, PrepareWriteRequestSecurity) {
3333   InitializeAttributesForWriting();
3334   RunPrepareWriteRequestTest();
3335 
3336   // None of the write handlers should have been called since no execute write
3337   // request has been sent.
3338   EXPECT_EQ(0u, write_count());
3339 }
3340 
3341 }  // namespace
3342 }  // namespace bt::gatt
3343