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