xref: /aosp_15_r20/external/pigweed/pw_bluetooth_sapphire/host/gatt/client_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/client.h"
16 
17 #include "pw_bluetooth_sapphire/internal/host/att/att.h"
18 #include "pw_bluetooth_sapphire/internal/host/l2cap/mock_channel_test.h"
19 #include "pw_bluetooth_sapphire/internal/host/testing/test_helpers.h"
20 
21 namespace bt::gatt {
22 namespace {
23 
24 constexpr UUID kTestUuid1(uint16_t{0xDEAD});
25 constexpr UUID kTestUuid2(uint16_t{0xBEEF});
26 constexpr UUID kTestUuid3(
27     {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15});
28 
MtuResultFromErrCode(att::ErrorCode ecode)29 att::Result<uint16_t> MtuResultFromErrCode(att::ErrorCode ecode) {
30   return fit::error(att::Error(ecode));
31 }
32 
MtuResultFromHostErrCode(HostError ecode)33 att::Result<uint16_t> MtuResultFromHostErrCode(HostError ecode) {
34   return fit::error(att::Error(ecode));
35 }
36 
37 // clang-format off
38 const StaticByteBuffer kDiscoverPrimaryRequest(
39     0x10,        // opcode: read by group type request
40     0x01, 0x00,  // start handle: 0x0001
41     0xFF, 0xFF,  // end handle: 0xFFFF
42     0x00, 0x28   // type: primary service (0x2800)
43 );
44 
45 const StaticByteBuffer kDiscoverPrimary16ByUUID(
46     0x06,        // opcode: find by type value request
47     0x01, 0x00,  // start handle: 0x0001
48     0xFF, 0xFF,  // end handle: 0xFFFF
49     0x00, 0x28,  // type: primary service (0x2800)
50     0xAD, 0xDE  // UUID
51 );
52 
53 const StaticByteBuffer kDiscoverPrimary128ByUUID(
54     0x06,        // opcode: find by type value request
55     0x01, 0x00,  // start handle: 0x0001
56     0xFF, 0xFF,  // end handle: 0xFFFF
57     0x00, 0x28,  // type: primary service (0x2800)
58     0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 // UUID
59 );
60 // clang-format on
61 
MakeFindInformation(att::Handle range_start=0x0001,att::Handle range_end=0xFFFF)62 auto MakeFindInformation(att::Handle range_start = 0x0001,
63                          att::Handle range_end = 0xFFFF) {
64   return StaticByteBuffer(att::kFindInformationRequest,  // opcode
65                           LowerBits(range_start),
66                           UpperBits(range_start),  // start handle
67                           LowerBits(range_end),
68                           UpperBits(range_end)  // end handle
69   );
70 }
71 
NopSvcCallback(const gatt::ServiceData &)72 void NopSvcCallback(const gatt::ServiceData&) {}
NopChrcCallback(const gatt::CharacteristicData &)73 void NopChrcCallback(const gatt::CharacteristicData&) {}
NopDescCallback(const gatt::DescriptorData &)74 void NopDescCallback(const gatt::DescriptorData&) {}
75 
76 class ClientTest : public l2cap::testing::MockChannelTest {
77  public:
78   ClientTest() = default;
79   ~ClientTest() override = default;
80 
81  protected:
SetUp()82   void SetUp() override {
83     ChannelOptions options(l2cap::kATTChannelId);
84     auto fake_chan = CreateFakeChannel(options);
85     att_ = att::Bearer::Create(fake_chan->GetWeakPtr(), dispatcher());
86     client_ = Client::Create(att_->GetWeakPtr());
87   }
88 
TearDown()89   void TearDown() override {
90     client_ = nullptr;
91     att_ = nullptr;
92   }
93 
94   // |out_status| must remain valid.
SendDiscoverDescriptors(att::Result<> * out_status,Client::DescriptorCallback desc_callback,att::Handle range_start=0x0001,att::Handle range_end=0xFFFF)95   void SendDiscoverDescriptors(att::Result<>* out_status,
96                                Client::DescriptorCallback desc_callback,
97                                att::Handle range_start = 0x0001,
98                                att::Handle range_end = 0xFFFF) {
99     client()->DiscoverDescriptors(
100         range_start,
101         range_end,
102         std::move(desc_callback),
103         [out_status](att::Result<> val) { *out_status = val; });
104   }
105 
att() const106   att::Bearer* att() const { return att_.get(); }
client() const107   Client* client() const { return client_.get(); }
108 
109  private:
110   std::unique_ptr<att::Bearer> att_;
111   std::unique_ptr<Client> client_;
112 
113   BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(ClientTest);
114 };
115 
TEST_F(ClientTest,ExchangeMTUMalformedResponse)116 TEST_F(ClientTest, ExchangeMTUMalformedResponse) {
117   constexpr uint16_t kPreferredMTU = 100;
118   const StaticByteBuffer kExpectedRequest(0x02,  // opcode: exchange MTU
119                                           kPreferredMTU,
120                                           0x00  // client rx mtu: kPreferredMTU
121   );
122 
123   std::optional<att::Result<uint16_t>> result;
124   auto mtu_cb = [&](att::Result<uint16_t> cb_result) { result = cb_result; };
125 
126   att()->set_preferred_mtu(kPreferredMTU);
127 
128   EXPECT_PACKET_OUT(kExpectedRequest);
129   client()->ExchangeMTU(mtu_cb);
130   EXPECT_TRUE(AllExpectedPacketsSent());
131   ASSERT_FALSE(fake_chan()->link_error());
132 
133   // Respond back with a malformed PDU. This should cause a link error and the
134   // MTU request should fail.
135   fake_chan()->Receive(StaticByteBuffer(
136       0x03,  // opcode: exchange MTU response
137       30     // server rx mtu is one octet too short
138       ));
139 
140   RunUntilIdle();
141 
142   ASSERT_TRUE(result.has_value());
143   EXPECT_EQ(MtuResultFromHostErrCode(HostError::kPacketMalformed), *result);
144   EXPECT_TRUE(fake_chan()->link_error());
145 }
146 
147 // Tests that the ATT "Request Not Supported" error results in the default MTU.
TEST_F(ClientTest,ExchangeMTUErrorNotSupported)148 TEST_F(ClientTest, ExchangeMTUErrorNotSupported) {
149   constexpr uint16_t kPreferredMTU = 100;
150   constexpr uint16_t kInitialMTU = 50;
151   const StaticByteBuffer kExpectedRequest(0x02,  // opcode: exchange MTU
152                                           kPreferredMTU,
153                                           0x00  // client rx mtu: kPreferredMTU
154   );
155 
156   std::optional<att::Result<uint16_t>> result;
157   auto mtu_cb = [&](att::Result<uint16_t> cb_result) { result = cb_result; };
158 
159   // Set the initial MTU to something other than the default LE MTU since we
160   // want to confirm that the MTU changes to the default.
161   att()->set_mtu(kInitialMTU);
162   att()->set_preferred_mtu(kPreferredMTU);
163 
164   EXPECT_PACKET_OUT(kExpectedRequest);
165   client()->ExchangeMTU(mtu_cb);
166   EXPECT_TRUE(AllExpectedPacketsSent());
167 
168   // Respond with "Request Not Supported". This will cause us to switch to the
169   // default MTU.
170   fake_chan()->Receive(
171       StaticByteBuffer(att::kErrorResponse,       // opcode
172                        att::kExchangeMTURequest,  // request opcode
173                        0x00,
174                        0x00,  // handle: 0
175                        att::ErrorCode::kRequestNotSupported));
176 
177   RunUntilIdle();
178 
179   ASSERT_TRUE(result.has_value());
180   EXPECT_EQ(MtuResultFromErrCode(att::ErrorCode::kRequestNotSupported),
181             *result);
182   EXPECT_EQ(att::kLEMinMTU, att()->mtu());
183 }
184 
TEST_F(ClientTest,ExchangeMTUErrorOther)185 TEST_F(ClientTest, ExchangeMTUErrorOther) {
186   constexpr uint16_t kPreferredMTU = 100;
187   const auto kExpectedRequest =
188       StaticByteBuffer(0x02,  // opcode: exchange MTU
189                        kPreferredMTU,
190                        0x00  // client rx mtu: kPreferredMTU
191       );
192 
193   std::optional<att::Result<uint16_t>> result;
194   auto mtu_cb = [&](att::Result<uint16_t> cb_result) { result = cb_result; };
195 
196   att()->set_preferred_mtu(kPreferredMTU);
197   EXPECT_EQ(att::kLEMinMTU, att()->mtu());
198 
199   EXPECT_PACKET_OUT(kExpectedRequest);
200   client()->ExchangeMTU(mtu_cb);
201   EXPECT_TRUE(AllExpectedPacketsSent());
202 
203   // Respond with an error. The MTU should remain unchanged.
204   fake_chan()->Receive(
205       StaticByteBuffer(att::kErrorResponse,       // opcode
206                        att::kExchangeMTURequest,  // request opcode
207                        0x00,
208                        0x00,  // handle: 0
209                        att::ErrorCode::kUnlikelyError));
210 
211   RunUntilIdle();
212 
213   ASSERT_TRUE(result.has_value());
214   EXPECT_EQ(MtuResultFromErrCode(att::ErrorCode::kUnlikelyError), *result);
215   EXPECT_EQ(att::kLEMinMTU, att()->mtu());
216 }
217 
218 // Tests that the client rx MTU is selected when smaller.
TEST_F(ClientTest,ExchangeMTUSelectLocal)219 TEST_F(ClientTest, ExchangeMTUSelectLocal) {
220   constexpr uint16_t kPreferredMTU = 100;
221   constexpr uint16_t kServerRxMTU = kPreferredMTU + 1;
222 
223   const auto kExpectedRequest =
224       StaticByteBuffer(0x02,  // opcode: exchange MTU
225                        kPreferredMTU,
226                        0x00  // client rx mtu: kPreferredMTU
227       );
228 
229   std::optional<att::Result<uint16_t>> result;
230   auto mtu_cb = [&](att::Result<uint16_t> cb_result) { result = cb_result; };
231 
232   att()->set_preferred_mtu(kPreferredMTU);
233 
234   EXPECT_PACKET_OUT(kExpectedRequest);
235   client()->ExchangeMTU(mtu_cb);
236   EXPECT_TRUE(AllExpectedPacketsSent());
237   ASSERT_EQ(att::kLEMinMTU, att()->mtu());
238 
239   // Respond with an error. The MTU should remain unchanged.
240   fake_chan()->Receive(StaticByteBuffer(0x03,  // opcode: exchange MTU response
241                                         kServerRxMTU,
242                                         0x00  // server rx mtu
243                                         ));
244 
245   RunUntilIdle();
246   ASSERT_TRUE(result.has_value());
247   EXPECT_EQ(att::Result<uint16_t>(fit::ok(kPreferredMTU)), *result);
248   EXPECT_EQ(kPreferredMTU, att()->mtu());
249 }
250 
251 // Tests that the server rx MTU is selected when smaller.
TEST_F(ClientTest,ExchangeMTUSelectRemote)252 TEST_F(ClientTest, ExchangeMTUSelectRemote) {
253   constexpr uint16_t kPreferredMTU = 100;
254   constexpr uint16_t kServerRxMTU = kPreferredMTU - 1;
255 
256   const auto kExpectedRequest =
257       StaticByteBuffer(0x02,  // opcode: exchange MTU
258                        kPreferredMTU,
259                        0x00  // client rx mtu: kPreferredMTU
260       );
261 
262   std::optional<att::Result<uint16_t>> result;
263   auto mtu_cb = [&](att::Result<uint16_t> cb_result) { result = cb_result; };
264 
265   att()->set_preferred_mtu(kPreferredMTU);
266 
267   EXPECT_PACKET_OUT(kExpectedRequest);
268   client()->ExchangeMTU(mtu_cb);
269   EXPECT_TRUE(AllExpectedPacketsSent());
270   ASSERT_EQ(att::kLEMinMTU, att()->mtu());
271 
272   // Respond with an error. The MTU should remain unchanged.
273   fake_chan()->Receive(StaticByteBuffer(0x03,  // opcode: exchange MTU response
274                                         kServerRxMTU,
275                                         0x00  // server rx mtu
276                                         ));
277 
278   RunUntilIdle();
279 
280   ASSERT_TRUE(result.has_value());
281   EXPECT_EQ(att::Result<uint16_t>(fit::ok(kServerRxMTU)), *result);
282   EXPECT_EQ(kServerRxMTU, att()->mtu());
283 }
284 
285 // Tests that the default MTU is selected when one of the MTUs is too small.
TEST_F(ClientTest,ExchangeMTUSelectDefault)286 TEST_F(ClientTest, ExchangeMTUSelectDefault) {
287   constexpr uint16_t kPreferredMTU = 100;
288   constexpr uint16_t kServerRxMTU = 5;  // Smaller than the LE default MTU
289 
290   const auto kExpectedRequest =
291       StaticByteBuffer(0x02,  // opcode: exchange MTU
292                        kPreferredMTU,
293                        0x00  // client rx mtu: kPreferredMTU
294       );
295 
296   std::optional<att::Result<uint16_t>> result;
297   auto mtu_cb = [&](att::Result<uint16_t> cb_result) { result = cb_result; };
298 
299   att()->set_preferred_mtu(kPreferredMTU);
300 
301   EXPECT_PACKET_OUT(kExpectedRequest);
302   client()->ExchangeMTU(mtu_cb);
303   EXPECT_TRUE(AllExpectedPacketsSent());
304   ASSERT_EQ(att::kLEMinMTU, att()->mtu());
305 
306   // Respond with an error. The MTU should remain unchanged.
307   fake_chan()->Receive(StaticByteBuffer(0x03,  // opcode: exchange MTU response
308                                         kServerRxMTU,
309                                         0x00  // server rx mtu
310                                         ));
311 
312   RunUntilIdle();
313 
314   ASSERT_TRUE(result.has_value());
315   EXPECT_EQ(att::Result<uint16_t>(fit::ok(att::kLEMinMTU)), *result);
316   EXPECT_EQ(att::kLEMinMTU, att()->mtu());
317 }
318 
TEST_F(ClientTest,DiscoverPrimaryResponseTooShort)319 TEST_F(ClientTest, DiscoverPrimaryResponseTooShort) {
320   att::Result<> status = fit::ok();
321   auto res_cb = [&status](att::Result<> val) { status = val; };
322 
323   EXPECT_PACKET_OUT(kDiscoverPrimaryRequest);
324   client()->DiscoverServices(ServiceKind::PRIMARY, NopSvcCallback, res_cb);
325   EXPECT_TRUE(AllExpectedPacketsSent());
326 
327   // Respond back with a malformed payload.
328   fake_chan()->Receive(StaticByteBuffer(0x11));
329 
330   RunUntilIdle();
331 
332   EXPECT_EQ(ToResult(HostError::kPacketMalformed), status);
333 }
334 
TEST_F(ClientTest,DiscoverPrimaryMalformedDataLength)335 TEST_F(ClientTest, DiscoverPrimaryMalformedDataLength) {
336   att::Result<> status = fit::ok();
337   auto res_cb = [&status](att::Result<> val) { status = val; };
338 
339   EXPECT_PACKET_OUT(kDiscoverPrimaryRequest);
340   client()->DiscoverServices(ServiceKind::PRIMARY, NopSvcCallback, res_cb);
341   EXPECT_TRUE(AllExpectedPacketsSent());
342 
343   // Respond back with an unexpected data length. This is 6 for services with a
344   // 16-bit UUID (start (2) + end (2) + uuid (2)) and 20 for 128-bit
345   // (start (2) + end (2) + uuid (16)).
346   fake_chan()->Receive(StaticByteBuffer(
347       0x11,  // opcode: read by group type response
348       7,     // data length: 7 (not 6 or 20)
349       0,
350       1,
351       2,
352       3,
353       4,
354       5,
355       6  // one entry of length 7, which will be ignored
356       ));
357 
358   RunUntilIdle();
359 
360   EXPECT_EQ(ToResult(HostError::kPacketMalformed), status);
361 }
362 
TEST_F(ClientTest,DiscoverPrimaryMalformedAttrDataList)363 TEST_F(ClientTest, DiscoverPrimaryMalformedAttrDataList) {
364   att::Result<> status = fit::ok();
365   auto res_cb = [&status](att::Result<> val) { status = val; };
366 
367   EXPECT_PACKET_OUT(kDiscoverPrimaryRequest);
368   client()->DiscoverServices(ServiceKind::PRIMARY, NopSvcCallback, res_cb);
369   EXPECT_TRUE(AllExpectedPacketsSent());
370 
371   fake_chan()->Receive(StaticByteBuffer(
372       0x11,  // opcode: read by group type response
373       6,     // data length: 6 (16-bit UUIDs)
374       0,
375       1,
376       2,
377       3,
378       4,
379       5,  // entry 1: correct size
380       0,
381       1,
382       2,
383       3,
384       4  // entry 2: incorrect size
385       ));
386 
387   RunUntilIdle();
388 
389   EXPECT_EQ(ToResult(HostError::kPacketMalformed), status);
390 }
391 
TEST_F(ClientTest,DiscoverPrimaryResultsOutOfOrder)392 TEST_F(ClientTest, DiscoverPrimaryResultsOutOfOrder) {
393   att::Result<> status = fit::ok();
394   auto res_cb = [&status](att::Result<> val) { status = val; };
395 
396   EXPECT_PACKET_OUT(kDiscoverPrimaryRequest);
397   client()->DiscoverServices(ServiceKind::PRIMARY, NopSvcCallback, res_cb);
398   EXPECT_TRUE(AllExpectedPacketsSent());
399 
400   fake_chan()->Receive(StaticByteBuffer(
401       0x11,  // opcode: read by group type response
402       6,     // data length: 6 (16-bit UUIDs)
403       0x12,
404       0x00,  // svc 0 start: 0x0012
405       0x13,
406       0x00,  // svc 0 end: 0x0013
407       0xEF,
408       0xBE,  // svc 0 uuid: 0xBEEF
409       0x10,
410       0x00,  // svc 1 start: 0x0010
411       0x11,
412       0x00,  // svc 1 end: 0x0011
413       0xAD,
414       0xDE  // svc 1 uuid: 0xDEAD
415       ));
416 
417   RunUntilIdle();
418 
419   EXPECT_EQ(ToResult(HostError::kPacketMalformed), status);
420 }
421 
422 // Tests that we handle an empty attribute data list. In practice, the
423 // server would send an "Attribute Not Found" error instead but our stack treats
424 // an empty data list as not an error.
TEST_F(ClientTest,DiscoverPrimaryEmptyDataList)425 TEST_F(ClientTest, DiscoverPrimaryEmptyDataList) {
426   att::Result<> status = ToResult(HostError::kFailed);
427   auto res_cb = [&status](att::Result<> val) { status = val; };
428 
429   EXPECT_PACKET_OUT(kDiscoverPrimaryRequest);
430   client()->DiscoverServices(ServiceKind::PRIMARY, NopSvcCallback, res_cb);
431   EXPECT_TRUE(AllExpectedPacketsSent());
432 
433   fake_chan()->Receive(StaticByteBuffer(
434       0x11,  // opcode: read by group type response
435       6      // data length: 6 (16-bit UUIDs)
436              // data list is empty
437       ));
438 
439   RunUntilIdle();
440   EXPECT_EQ(fit::ok(), status);
441 }
442 
443 // The first request results in "Attribute Not Found".
TEST_F(ClientTest,DiscoverPrimaryAttributeNotFound)444 TEST_F(ClientTest, DiscoverPrimaryAttributeNotFound) {
445   att::Result<> status = ToResult(HostError::kFailed);
446   auto res_cb = [&status](att::Result<> val) { status = val; };
447 
448   EXPECT_PACKET_OUT(kDiscoverPrimaryRequest);
449   client()->DiscoverServices(ServiceKind::PRIMARY, NopSvcCallback, res_cb);
450   EXPECT_TRUE(AllExpectedPacketsSent());
451 
452   fake_chan()->Receive(StaticByteBuffer(0x01,  // opcode: error response
453                                         0x10,  // request: read by group type
454                                         0x01,
455                                         0x00,  // handle: 0x0001
456                                         0x0A   // error: Attribute Not Found
457                                         ));
458 
459   RunUntilIdle();
460 
461   // The procedure succeeds with no services.
462   EXPECT_EQ(fit::ok(), status);
463 }
464 
465 // The first request results in an error.
TEST_F(ClientTest,DiscoverPrimaryError)466 TEST_F(ClientTest, DiscoverPrimaryError) {
467   att::Result<> status = ToResult(HostError::kFailed);
468   auto res_cb = [&status](att::Result<> val) { status = val; };
469 
470   EXPECT_PACKET_OUT(kDiscoverPrimaryRequest);
471   client()->DiscoverServices(ServiceKind::PRIMARY, NopSvcCallback, res_cb);
472   EXPECT_TRUE(AllExpectedPacketsSent());
473 
474   fake_chan()->Receive(StaticByteBuffer(0x01,  // opcode: error response
475                                         0x10,  // request: read by group type
476                                         0x01,
477                                         0x00,  // handle: 0x0001
478                                         0x06   // error: Request Not Supported
479                                         ));
480 
481   RunUntilIdle();
482 
483   EXPECT_EQ(ToResult(att::ErrorCode::kRequestNotSupported), status);
484 }
485 
TEST_F(ClientTest,DiscoverPrimaryMalformedServiceRange)486 TEST_F(ClientTest, DiscoverPrimaryMalformedServiceRange) {
487   att::Result<> status = ToResult(HostError::kFailed);
488   auto res_cb = [&status](att::Result<> val) { status = val; };
489 
490   EXPECT_PACKET_OUT(kDiscoverPrimaryRequest);
491   client()->DiscoverServices(ServiceKind::PRIMARY, NopSvcCallback, res_cb);
492   EXPECT_TRUE(AllExpectedPacketsSent());
493 
494   // Return a service where start > end.
495   fake_chan()->Receive(StaticByteBuffer(
496       0x11,  // opcode: read by group type response
497       0x06,  // data length: 6 (16-bit UUIDs)
498       0x02,
499       0x00,  // svc 1 start: 0x0002
500       0x01,
501       0x00  // svc 1 end: 0x0001
502       ));
503 
504   RunUntilIdle();
505 
506   // The procedure should be over since the last service in the payload has
507   // end handle 0xFFFF.
508   EXPECT_EQ(ToResult(HostError::kPacketMalformed), status);
509 }
510 
TEST_F(ClientTest,DiscoverPrimary16BitResultsSingleRequest)511 TEST_F(ClientTest, DiscoverPrimary16BitResultsSingleRequest) {
512   att::Result<> status = ToResult(HostError::kFailed);
513   auto res_cb = [&status](att::Result<> val) { status = val; };
514 
515   std::vector<ServiceData> services;
516   auto svc_cb = [&services](const ServiceData& svc) {
517     services.push_back(svc);
518   };
519 
520   EXPECT_PACKET_OUT(kDiscoverPrimaryRequest);
521   client()->DiscoverServices(ServiceKind::PRIMARY, svc_cb, res_cb);
522   EXPECT_TRUE(AllExpectedPacketsSent());
523 
524   fake_chan()->Receive(StaticByteBuffer(
525       0x11,  // opcode: read by group type response
526       0x06,  // data length: 6 (16-bit UUIDs)
527       0x01,
528       0x00,  // svc 1 start: 0x0001
529       0x05,
530       0x00,  // svc 1 end: 0x0005
531       0xAD,
532       0xDE,  // svc 1 uuid: 0xDEAD
533       0x06,
534       0x00,  // svc 2 start: 0x0006
535       0xFF,
536       0xFF,  // svc 2 end: 0xFFFF
537       0xEF,
538       0xBE  // svc 2 uuid: 0xBEEF
539       ));
540 
541   RunUntilIdle();
542 
543   // The procedure should be over since the last service in the payload has
544   // end handle 0xFFFF.
545   EXPECT_EQ(fit::ok(), status);
546   EXPECT_EQ(2u, services.size());
547   EXPECT_EQ(0x0001, services[0].range_start);
548   EXPECT_EQ(0x0005, services[0].range_end);
549   EXPECT_EQ(kTestUuid1, services[0].type);
550   EXPECT_EQ(0x0006, services[1].range_start);
551   EXPECT_EQ(0xFFFF, services[1].range_end);
552   EXPECT_EQ(kTestUuid2, services[1].type);
553 }
554 
TEST_F(ClientTest,DiscoverPrimary128BitResultSingleRequest)555 TEST_F(ClientTest, DiscoverPrimary128BitResultSingleRequest) {
556   att::Result<> status = ToResult(HostError::kFailed);
557   auto res_cb = [&status](att::Result<> val) { status = val; };
558 
559   std::vector<ServiceData> services;
560   auto svc_cb = [&services](const ServiceData& svc) {
561     services.push_back(svc);
562   };
563 
564   EXPECT_PACKET_OUT(kDiscoverPrimaryRequest);
565   client()->DiscoverServices(ServiceKind::PRIMARY, svc_cb, res_cb);
566   EXPECT_TRUE(AllExpectedPacketsSent());
567 
568   fake_chan()->Receive(
569       StaticByteBuffer(0x11,  // opcode: read by group type response
570                        0x14,  // data length: 20 (128-bit UUIDs)
571                        0x01,
572                        0x00,  // svc 1 start: 0x0008
573                        0xFF,
574                        0xFF,  // svc 1 end: 0xFFFF
575 
576                        // UUID matches |kTestUuid3| declared above.
577                        0,
578                        1,
579                        2,
580                        3,
581                        4,
582                        5,
583                        6,
584                        7,
585                        8,
586                        9,
587                        10,
588                        11,
589                        12,
590                        13,
591                        14,
592                        15));
593 
594   RunUntilIdle();
595 
596   // The procedure should be over since the last service in the payload has
597   // end handle 0xFFFF.
598   EXPECT_EQ(fit::ok(), status);
599   EXPECT_EQ(1u, services.size());
600   EXPECT_EQ(0x0001, services[0].range_start);
601   EXPECT_EQ(0xFFFF, services[0].range_end);
602   EXPECT_EQ(kTestUuid3, services[0].type);
603 }
604 
TEST_F(ClientTest,DiscoverAllPrimaryMultipleRequests)605 TEST_F(ClientTest, DiscoverAllPrimaryMultipleRequests) {
606   const auto kExpectedRequest0 =
607       StaticByteBuffer(0x10,  // opcode: read by group type request
608                        0x01,
609                        0x00,  // start handle: 0x0001
610                        0xFF,
611                        0xFF,  // end handle: 0xFFFF
612                        0x00,
613                        0x28  // type: primary service (0x2800)
614       );
615   const StaticByteBuffer kResponse0(
616       0x11,  // opcode: read by group type response
617       0x06,  // data length: 6 (16-bit UUIDs)
618       0x01,
619       0x00,  // svc 1 start: 0x0001
620       0x05,
621       0x00,  // svc 1 end: 0x0005
622       0xAD,
623       0xDE,  // svc 1 uuid: 0xDEAD
624       0x06,
625       0x00,  // svc 2 start: 0x0006
626       0x07,
627       0x00,  // svc 2 end: 0x0007
628       0xEF,
629       0xBE  // svc 2 uuid: 0xBEEF
630   );
631   const auto kExpectedRequest1 =
632       StaticByteBuffer(0x10,  // opcode: read by group type request
633                        0x08,
634                        0x00,  // start handle: 0x0008
635                        0xFF,
636                        0xFF,  // end handle: 0xFFFF
637                        0x00,
638                        0x28  // type: primary service (0x2800)
639       );
640   // Respond with one 128-bit service UUID.
641   const StaticByteBuffer kResponse1(
642       0x11,  // opcode: read by group type response
643       0x14,  // data length: 20 (128-bit UUIDs)
644       0x08,
645       0x00,  // svc 1 start: 0x0008
646       0x09,
647       0x00,  // svc 1 end: 0x0009
648 
649       // UUID matches |kTestUuid3| declared above.
650       0,
651       1,
652       2,
653       3,
654       4,
655       5,
656       6,
657       7,
658       8,
659       9,
660       10,
661       11,
662       12,
663       13,
664       14,
665       15);
666   const auto kExpectedRequest2 =
667       StaticByteBuffer(0x10,  // opcode: read by group type request
668                        0x0A,
669                        0x00,  // start handle: 0x000A
670                        0xFF,
671                        0xFF,  // end handle: 0xFFFF
672                        0x00,
673                        0x28  // type: primary service (0x2800)
674       );
675   // Terminate the procedure with an error response.
676   const StaticByteBuffer kResponse2(0x01,  // opcode: error response
677                                     0x10,  // request: read by group type
678                                     0x0A,
679                                     0x00,  // handle: 0x000A
680                                     0x0A   // error: Attribute Not Found
681   );
682 
683   att::Result<> status = ToResult(HostError::kFailed);
684   auto res_cb = [&status](att::Result<> val) { status = val; };
685 
686   std::vector<ServiceData> services;
687   auto svc_cb = [&services](const ServiceData& svc) {
688     services.push_back(svc);
689   };
690 
691   EXPECT_PACKET_OUT(kExpectedRequest0, &kResponse0);
692   EXPECT_PACKET_OUT(kExpectedRequest1, &kResponse1);
693   EXPECT_PACKET_OUT(kExpectedRequest2, &kResponse2);
694   client()->DiscoverServices(ServiceKind::PRIMARY, svc_cb, res_cb);
695   RunUntilIdle();
696   EXPECT_TRUE(AllExpectedPacketsSent());
697 
698   // The procedure should be over since the last service in the payload has
699   // end handle 0xFFFF.
700   EXPECT_EQ(fit::ok(), status);
701   EXPECT_EQ(3u, services.size());
702 
703   EXPECT_EQ(0x0001, services[0].range_start);
704   EXPECT_EQ(0x0005, services[0].range_end);
705   EXPECT_EQ(kTestUuid1, services[0].type);
706 
707   EXPECT_EQ(0x0006, services[1].range_start);
708   EXPECT_EQ(0x0007, services[1].range_end);
709   EXPECT_EQ(kTestUuid2, services[1].type);
710 
711   EXPECT_EQ(0x0008, services[2].range_start);
712   EXPECT_EQ(0x0009, services[2].range_end);
713   EXPECT_EQ(kTestUuid3, services[2].type);
714 }
715 
TEST_F(ClientTest,DiscoverServicesInRangeMultipleRequests)716 TEST_F(ClientTest, DiscoverServicesInRangeMultipleRequests) {
717   const att::Handle kRangeStart = 0x0010;
718   const att::Handle kRangeEnd = 0x0020;
719 
720   const StaticByteBuffer kExpectedRequest0(
721       0x10,  // opcode: read by group type request
722       LowerBits(kRangeStart),
723       UpperBits(kRangeStart),  // start handle
724       LowerBits(kRangeEnd),
725       UpperBits(kRangeEnd),  // end handle
726       0x00,
727       0x28  // type: primary service (0x2800)
728   );
729 
730   const StaticByteBuffer kResponse0(
731       0x11,  // opcode: read by group type response
732       0x06,  // data length: 6 (16-bit UUIDs)
733       0x10,
734       0x00,  // svc 0 start: 0x0010
735       0x11,
736       0x00,  // svc 0 end: 0x0011
737       0xAD,
738       0xDE,  // svc 0 uuid: 0xDEAD
739       0x12,
740       0x00,  // svc 1 start: 0x0012
741       0x13,
742       0x00,  // svc 1 end: 0x0013
743       0xEF,
744       0xBE  // svc 1 uuid: 0xBEEF
745   );
746   const auto kExpectedRequest1 =
747       StaticByteBuffer(0x10,  // opcode: read by group type request
748                        0x14,
749                        0x00,  // start handle: 0x0014
750                        LowerBits(kRangeEnd),
751                        UpperBits(kRangeEnd),  // end handle
752                        0x00,
753                        0x28  // type: primary service (0x2800)
754       );
755   // Respond with one 128-bit service UUID.
756   const auto kResponse1 =
757       StaticByteBuffer(0x11,  // opcode: read by group type response
758                        0x14,  // data length: 20 (128-bit UUIDs)
759                        0x14,
760                        0x00,  // svc 2 start: 0x0014
761                        0x15,
762                        0x00,  // svc 2 end: 0x0015
763 
764                        // UUID matches |kTestUuid3| declared above.
765                        0,
766                        1,
767                        2,
768                        3,
769                        4,
770                        5,
771                        6,
772                        7,
773                        8,
774                        9,
775                        10,
776                        11,
777                        12,
778                        13,
779                        14,
780                        15);
781   const auto kExpectedRequest2 =
782       StaticByteBuffer(0x10,  // opcode: read by group type request
783                        0x16,
784                        0x00,  // start handle: 0x0016
785                        LowerBits(kRangeEnd),
786                        UpperBits(kRangeEnd),  // end handle
787                        0x00,
788                        0x28  // type: primary service (0x2800)
789       );
790   // Terminate the procedure with an error response.
791   const auto kNotFoundResponse2 =
792       StaticByteBuffer(0x01,  // opcode: error response
793                        0x10,  // request: read by group type
794                        0x16,
795                        0x00,  // start handle: 0x0016
796                        0x0A   // error: Attribute Not Found
797       );
798 
799   att::Result<> status = ToResult(HostError::kFailed);
800   auto res_cb = [&status](att::Result<> val) { status = val; };
801 
802   std::vector<ServiceData> services;
803   auto svc_cb = [&services](const ServiceData& svc) {
804     services.push_back(svc);
805   };
806 
807   EXPECT_PACKET_OUT(kExpectedRequest0, &kResponse0);
808   EXPECT_PACKET_OUT(kExpectedRequest1, &kResponse1);
809   EXPECT_PACKET_OUT(kExpectedRequest2, &kNotFoundResponse2);
810   client()->DiscoverServicesInRange(
811       ServiceKind::PRIMARY, kRangeStart, kRangeEnd, svc_cb, res_cb);
812   RunUntilIdle();
813   EXPECT_TRUE(AllExpectedPacketsSent());
814   EXPECT_EQ(fit::ok(), status);
815   EXPECT_EQ(3u, services.size());
816 
817   EXPECT_EQ(0x0010, services[0].range_start);
818   EXPECT_EQ(0x0011, services[0].range_end);
819   EXPECT_EQ(kTestUuid1, services[0].type);
820 
821   EXPECT_EQ(0x0012, services[1].range_start);
822   EXPECT_EQ(0x0013, services[1].range_end);
823   EXPECT_EQ(kTestUuid2, services[1].type);
824 
825   EXPECT_EQ(0x0014, services[2].range_start);
826   EXPECT_EQ(0x0015, services[2].range_end);
827   EXPECT_EQ(kTestUuid3, services[2].type);
828 }
829 
TEST_F(ClientTest,DiscoverServicesInRangeFailsIfServiceResultIsOutOfRange)830 TEST_F(ClientTest, DiscoverServicesInRangeFailsIfServiceResultIsOutOfRange) {
831   const att::Handle kRangeStart = 0x0010;
832   const att::Handle kRangeEnd = 0x0020;
833   const att::Handle kServiceStart = 0x0001;
834   const att::Handle kServiceEnd = 0x0011;
835 
836   const auto kExpectedRequest =
837       StaticByteBuffer(0x10,  // opcode: read by group type request
838                        LowerBits(kRangeStart),
839                        UpperBits(kRangeStart),  // start handle
840                        LowerBits(kRangeEnd),
841                        UpperBits(kRangeEnd),  // end handle
842                        0x00,
843                        0x28  // type: primary service (0x2800)
844       );
845 
846   const auto kResponse =
847       StaticByteBuffer(0x11,  // opcode: read by group type response
848                        0x06,  // data length: 6 (16-bit UUIDs)
849                        LowerBits(kServiceStart),
850                        UpperBits(kServiceStart),  // svc start
851                        LowerBits(kServiceEnd),
852                        UpperBits(kServiceEnd),  // svc end
853                        0xAD,
854                        0xDE  // svc uuid: 0xDEAD
855       );
856 
857   std::optional<att::Result<>> status;
858   auto res_cb = [&status](att::Result<> val) { status = val; };
859 
860   std::vector<ServiceData> services;
861   auto svc_cb = [&services](const ServiceData& svc) {
862     services.push_back(svc);
863   };
864 
865   EXPECT_PACKET_OUT(kExpectedRequest);
866   client()->DiscoverServicesInRange(
867       ServiceKind::PRIMARY, kRangeStart, kRangeEnd, svc_cb, res_cb);
868   EXPECT_TRUE(AllExpectedPacketsSent());
869 
870   fake_chan()->Receive(kResponse);
871   RunUntilIdle();
872   ASSERT_TRUE(status.has_value());
873   EXPECT_EQ(ToResult(HostError::kPacketMalformed), *status);
874   EXPECT_EQ(0u, services.size());
875 }
876 
TEST_F(ClientTest,DiscoverPrimaryWithUuidsByResponseTooShort)877 TEST_F(ClientTest, DiscoverPrimaryWithUuidsByResponseTooShort) {
878   att::Result<> status = fit::ok();
879   auto res_cb = [&status](att::Result<> val) { status = val; };
880 
881   // Respond back with a malformed payload.
882   const StaticByteBuffer kResponse(0x7, 0x0);
883   EXPECT_PACKET_OUT(kDiscoverPrimary16ByUUID, &kResponse);
884   client()->DiscoverServicesWithUuids(
885       ServiceKind::PRIMARY, NopSvcCallback, res_cb, {kTestUuid1});
886   EXPECT_TRUE(AllExpectedPacketsSent());
887   RunUntilIdle();
888   EXPECT_EQ(ToResult(HostError::kPacketMalformed), status);
889 }
890 
891 // Tests that we handle an empty handle information list properly. In practice,
892 // the server would send an "Attribute Not Found" error instead.  A handle list
893 // that is empty is an error.
TEST_F(ClientTest,DiscoverPrimaryWithUuidsEmptyDataList)894 TEST_F(ClientTest, DiscoverPrimaryWithUuidsEmptyDataList) {
895   att::Result<> status = ToResult(HostError::kFailed);
896   auto res_cb = [&status](att::Result<> val) { status = val; };
897 
898   const StaticByteBuffer kResponse(0x07  // opcode: find by value type response
899                                          // data list is empty
900   );
901   EXPECT_PACKET_OUT(kDiscoverPrimary16ByUUID, &kResponse);
902   client()->DiscoverServicesWithUuids(
903       ServiceKind::PRIMARY, NopSvcCallback, res_cb, {kTestUuid1});
904   EXPECT_TRUE(AllExpectedPacketsSent());
905   RunUntilIdle();
906   EXPECT_TRUE(status.is_error());
907 }
908 
909 // The first request results in "Attribute Not Found".
TEST_F(ClientTest,DiscoverPrimaryWithUuidsAttributeNotFound)910 TEST_F(ClientTest, DiscoverPrimaryWithUuidsAttributeNotFound) {
911   att::Result<> status = ToResult(HostError::kFailed);
912   auto res_cb = [&status](att::Result<> val) { status = val; };
913 
914   const StaticByteBuffer kResponse(0x01,  // opcode: error response
915                                    0x06,  // request: find by type value
916                                    0x01,
917                                    0x00,  // handle: 0x0001
918                                    0x0A   // error: Attribute Not Found
919   );
920 
921   EXPECT_PACKET_OUT(kDiscoverPrimary16ByUUID, &kResponse);
922   client()->DiscoverServicesWithUuids(
923       ServiceKind::PRIMARY, NopSvcCallback, res_cb, {kTestUuid1});
924   EXPECT_TRUE(AllExpectedPacketsSent());
925   RunUntilIdle();
926   // The procedure succeeds with no services.
927   EXPECT_EQ(fit::ok(), status);
928 }
929 
930 // The first request results in an error.
TEST_F(ClientTest,DiscoverPrimaryWithUuidsError)931 TEST_F(ClientTest, DiscoverPrimaryWithUuidsError) {
932   att::Result<> status = ToResult(HostError::kFailed);
933   auto res_cb = [&status](att::Result<> val) { status = val; };
934 
935   const StaticByteBuffer kResponse(0x01,  // opcode: error response
936                                    0x06,  // request: find by type value
937                                    0x01,
938                                    0x00,  // handle: 0x0001
939                                    0x06   // error: Request Not Supported
940   );
941 
942   EXPECT_PACKET_OUT(kDiscoverPrimary16ByUUID, &kResponse);
943   client()->DiscoverServicesWithUuids(
944       ServiceKind::PRIMARY, NopSvcCallback, res_cb, {kTestUuid1});
945   EXPECT_TRUE(AllExpectedPacketsSent());
946   RunUntilIdle();
947   EXPECT_EQ(ToResult(att::ErrorCode::kRequestNotSupported), status);
948 }
949 
TEST_F(ClientTest,DiscoverPrimaryWithUuidsMalformedServiceRange)950 TEST_F(ClientTest, DiscoverPrimaryWithUuidsMalformedServiceRange) {
951   att::Result<> status = ToResult(HostError::kFailed);
952   auto res_cb = [&status](att::Result<> val) { status = val; };
953 
954   // Return a service where start > end.
955   const StaticByteBuffer kResponse(0x07,  // opcode: find by type value response
956                                    0x02,
957                                    0x00,  // svc 1 start: 0x0002
958                                    0x01,
959                                    0x00  // svc 1 end: 0x0001
960   );
961   EXPECT_PACKET_OUT(kDiscoverPrimary16ByUUID, &kResponse);
962   client()->DiscoverServicesWithUuids(
963       ServiceKind::PRIMARY, NopSvcCallback, res_cb, {kTestUuid1});
964   RunUntilIdle();
965   EXPECT_TRUE(AllExpectedPacketsSent());
966   // The procedure should be over since the last service in the payload has
967   // end handle 0xFFFF.
968   EXPECT_EQ(ToResult(HostError::kPacketMalformed), status);
969 }
970 
TEST_F(ClientTest,DiscoverPrimaryWithUuidsServicesOutOfOrder)971 TEST_F(ClientTest, DiscoverPrimaryWithUuidsServicesOutOfOrder) {
972   std::optional<att::Result<>> status;
973   auto res_cb = [&status](att::Result<> val) { status = val; };
974 
975   // Return services out of order.
976   const StaticByteBuffer kResponse(0x07,  // opcode: find by type value response
977                                    0x05,
978                                    0x00,  // svc 0 start: 0x0005
979                                    0x06,
980                                    0x00,  // svc 0 end: 0x0006
981                                    0x01,
982                                    0x00,  // svc 1 start: 0x0001
983                                    0x02,
984                                    0x00  // svc 1 end: 0x0002
985   );
986   EXPECT_PACKET_OUT(kDiscoverPrimary16ByUUID, &kResponse);
987   client()->DiscoverServicesWithUuids(
988       ServiceKind::PRIMARY, NopSvcCallback, res_cb, {kTestUuid1});
989   RunUntilIdle();
990   EXPECT_TRUE(AllExpectedPacketsSent());
991   ASSERT_TRUE(status.has_value());
992   EXPECT_EQ(ToResult(HostError::kPacketMalformed), *status);
993 }
994 
TEST_F(ClientTest,DiscoverPrimaryWithUuids16BitResultsSingleRequest)995 TEST_F(ClientTest, DiscoverPrimaryWithUuids16BitResultsSingleRequest) {
996   att::Result<> status = ToResult(HostError::kFailed);
997   auto res_cb = [&status](att::Result<> val) { status = val; };
998 
999   std::vector<ServiceData> services;
1000   auto svc_cb = [&services](const ServiceData& svc) {
1001     services.push_back(svc);
1002   };
1003 
1004   const StaticByteBuffer kResponse(0x07,  // opcode: find by type value response
1005                                    0x01,
1006                                    0x00,  // svc 1 start: 0x0001
1007                                    0x05,
1008                                    0x00,  // svc 1 end: 0x0005
1009                                    0x06,
1010                                    0x00,  // svc 2 start: 0x0006
1011                                    0xFF,
1012                                    0xFF  // svc 2 end: 0xFFFF
1013   );
1014 
1015   EXPECT_PACKET_OUT(kDiscoverPrimary16ByUUID, &kResponse);
1016   client()->DiscoverServicesWithUuids(
1017       ServiceKind::PRIMARY, svc_cb, res_cb, {kTestUuid1});
1018   RunUntilIdle();
1019   EXPECT_TRUE(AllExpectedPacketsSent());
1020 
1021   // The procedure should be over since the last service in the payload has
1022   // end handle 0xFFFF.
1023   EXPECT_EQ(fit::ok(), status);
1024   EXPECT_EQ(2u, services.size());
1025   EXPECT_EQ(0x0001, services[0].range_start);
1026   EXPECT_EQ(0x0005, services[0].range_end);
1027   EXPECT_EQ(kTestUuid1, services[0].type);
1028   EXPECT_EQ(0x0006, services[1].range_start);
1029   EXPECT_EQ(0xFFFF, services[1].range_end);
1030   EXPECT_EQ(kTestUuid1, services[1].type);
1031 }
1032 
TEST_F(ClientTest,DiscoverPrimaryWithUuids128BitResultSingleRequest)1033 TEST_F(ClientTest, DiscoverPrimaryWithUuids128BitResultSingleRequest) {
1034   att::Result<> status = ToResult(HostError::kFailed);
1035   auto res_cb = [&status](att::Result<> val) { status = val; };
1036 
1037   std::vector<ServiceData> services;
1038   auto svc_cb = [&services](const ServiceData& svc) {
1039     services.push_back(svc);
1040   };
1041 
1042   const StaticByteBuffer kResponse(0x07,  // opcode: find by type value response
1043                                    0x01,
1044                                    0x00,  // svc 1 start: 0x0008
1045                                    0xFF,
1046                                    0xFF  // svc 1 end: 0xFFFF
1047   );
1048   EXPECT_PACKET_OUT(kDiscoverPrimary128ByUUID, &kResponse);
1049   client()->DiscoverServicesWithUuids(
1050       ServiceKind::PRIMARY, svc_cb, res_cb, {kTestUuid3});
1051   EXPECT_TRUE(AllExpectedPacketsSent());
1052   RunUntilIdle();
1053 
1054   // The procedure should be over since the last service in the payload has
1055   // end handle 0xFFFF.
1056   EXPECT_EQ(fit::ok(), status);
1057   EXPECT_EQ(1u, services.size());
1058   EXPECT_EQ(0x0001, services[0].range_start);
1059   EXPECT_EQ(0xFFFF, services[0].range_end);
1060   EXPECT_EQ(kTestUuid3, services[0].type);
1061 }
1062 
TEST_F(ClientTest,DiscoverAllPrimaryWithUuidsMultipleRequests)1063 TEST_F(ClientTest, DiscoverAllPrimaryWithUuidsMultipleRequests) {
1064   const auto kExpectedRequest0 =
1065       StaticByteBuffer(0x06,  // opcode: find by type value request
1066                        0x01,
1067                        0x00,  // start handle: 0x0001
1068                        0xFF,
1069                        0xFF,  // end handle: 0xFFFF
1070                        0x00,
1071                        0x28,  // type: primary service (0x2800)
1072                        0xAD,
1073                        0xDE  // svc 1 uuid: 0xDEAD
1074       );
1075   const auto kResponse0 =
1076       StaticByteBuffer(0x07,  // opcode: find by type value response
1077                        0x01,
1078                        0x00,  // svc 1 start: 0x0001
1079                        0x05,
1080                        0x00,  // svc 1 end: 0x0005
1081                        0x06,
1082                        0x00,  // svc 2 start: 0x0006
1083                        0x07,
1084                        0x00  // svc 2 end: 0x0007
1085       );
1086   const auto kExpectedRequest1 =
1087       StaticByteBuffer(0x06,  // opcode: find by type value request
1088                        0x08,
1089                        0x00,  // start handle: 0x0008
1090                        0xFF,
1091                        0xFF,  // end handle: 0xFFFF
1092                        0x00,
1093                        0x28,  // type: primary service (0x2800)
1094                        0xAD,
1095                        0xDE  // svc 1 uuid: 0xDEAD
1096       );
1097   // Respond with one 128-bit service UUID.
1098   const auto kResponse1 =
1099       StaticByteBuffer(0x07,  // opcode: find by type value response
1100                        0x08,
1101                        0x00,  // svc 1 start: 0x0008
1102                        0x09,
1103                        0x00  // svc 1 end: 0x0009
1104       );
1105   const auto kExpectedRequest2 =
1106       StaticByteBuffer(0x06,  // opcode: find by type value request
1107                        0x0A,
1108                        0x00,  // start handle: 0x000A
1109                        0xFF,
1110                        0xFF,  // end handle: 0xFFFF
1111                        0x00,
1112                        0x28,  // type: primary service (0x2800)
1113                        0xAD,
1114                        0xDE  // svc 1 uuid: 0xDEAD
1115       );
1116   // Terminate the procedure with an error response.
1117   const StaticByteBuffer kResponse2(0x01,  // opcode: error response
1118                                     0x06,  // request: find by type value
1119                                     0x0A,
1120                                     0x00,  // handle: 0x000A
1121                                     0x0A   // error: Attribute Not Found
1122   );
1123 
1124   att::Result<> status = ToResult(HostError::kFailed);
1125   auto res_cb = [&status](att::Result<> val) { status = val; };
1126 
1127   std::vector<ServiceData> services;
1128   auto svc_cb = [&services](const ServiceData& svc) {
1129     services.push_back(svc);
1130   };
1131 
1132   EXPECT_PACKET_OUT(kExpectedRequest0, &kResponse0);
1133   EXPECT_PACKET_OUT(kExpectedRequest1, &kResponse1);
1134   EXPECT_PACKET_OUT(kExpectedRequest2, &kResponse2);
1135   client()->DiscoverServicesWithUuids(
1136       ServiceKind::PRIMARY, svc_cb, res_cb, {kTestUuid1});
1137   RunUntilIdle();
1138   EXPECT_TRUE(AllExpectedPacketsSent());
1139 
1140   // The procedure should be over since the last service in the payload has end
1141   // handle 0xFFFF.
1142   EXPECT_EQ(fit::ok(), status);
1143   EXPECT_EQ(3u, services.size());
1144 
1145   EXPECT_EQ(0x0001, services[0].range_start);
1146   EXPECT_EQ(0x0005, services[0].range_end);
1147   EXPECT_EQ(kTestUuid1, services[0].type);
1148 
1149   EXPECT_EQ(0x0006, services[1].range_start);
1150   EXPECT_EQ(0x0007, services[1].range_end);
1151   EXPECT_EQ(kTestUuid1, services[1].type);
1152 
1153   EXPECT_EQ(0x0008, services[2].range_start);
1154   EXPECT_EQ(0x0009, services[2].range_end);
1155   EXPECT_EQ(kTestUuid1, services[2].type);
1156 }
1157 
TEST_F(ClientTest,DiscoverPrimaryWithUuidsMultipleUuids)1158 TEST_F(ClientTest, DiscoverPrimaryWithUuidsMultipleUuids) {
1159   const auto kExpectedRequest0 =
1160       StaticByteBuffer(0x06,  // opcode: find by type value request
1161                        0x01,
1162                        0x00,  // start handle: 0x0001
1163                        0xFF,
1164                        0xFF,  // end handle: 0xFFFF
1165                        0x00,
1166                        0x28,  // type: primary service (0x2800)
1167                        0xAD,
1168                        0xDE  // kTestUuid1
1169       );
1170   const auto kResponse0 =
1171       StaticByteBuffer(0x07,  // opcode: find by type value response
1172                        0x01,
1173                        0x00,  // svc 1 start: 0x0001
1174                        0x05,
1175                        0x00  // svc 1 end: 0x0005
1176       );
1177   const auto kExpectedRequest1 =
1178       StaticByteBuffer(0x06,  // opcode: find by type value request
1179                        0x06,
1180                        0x00,  // start handle: 0x0006
1181                        0xFF,
1182                        0xFF,  // end handle: 0xFFFF
1183                        0x00,
1184                        0x28,  // type: primary service (0x2800)
1185                        0xAD,
1186                        0xDE  // kTestUuid1
1187       );
1188   const auto kNotFoundResponse1 =
1189       StaticByteBuffer(0x01,  // opcode: error response
1190                        0x06,  // request: find by type value
1191                        0x06,
1192                        0x00,  // handle: 0x0006
1193                        0x0A   // error: Attribute Not Found
1194       );
1195   const auto kExpectedRequest2 =
1196       StaticByteBuffer(0x06,  // opcode: find by type value request
1197                        0x01,
1198                        0x00,  // start handle: 0x0001
1199                        0xFF,
1200                        0xFF,  // end handle: 0xFFFF
1201                        0x00,
1202                        0x28,  // type: primary service (0x2800)
1203                        0xEF,
1204                        0xBE  // kTestUuid2
1205       );
1206   const auto kResponse2 =
1207       StaticByteBuffer(0x07,  // opcode: find by type value response
1208                        0x06,
1209                        0x00,  // svc 1 start: 0x0006
1210                        0x09,
1211                        0x00  // svc 1 end: 0x0009
1212       );
1213   const auto kExpectedRequest3 =
1214       StaticByteBuffer(0x06,  // opcode: find by type value request
1215                        0x0A,
1216                        0x00,  // start handle: 0x000A
1217                        0xFF,
1218                        0xFF,  // end handle: 0xFFFF
1219                        0x00,
1220                        0x28,  // type: primary service (0x2800)
1221                        0xEF,
1222                        0xBE  // kTestUuid2
1223       );
1224   const auto kNotFoundResponse3 =
1225       StaticByteBuffer(0x01,  // opcode: error response
1226                        0x06,  // request: find by type value
1227                        0x0A,
1228                        0x00,  // handle: 0x000A
1229                        0x0A   // error: Attribute Not Found
1230       );
1231 
1232   att::Result<> status = ToResult(HostError::kFailed);
1233   auto res_cb = [&status](att::Result<> val) { status = val; };
1234 
1235   std::vector<ServiceData> services;
1236   auto svc_cb = [&services](const ServiceData& svc) {
1237     services.push_back(svc);
1238   };
1239 
1240   EXPECT_PACKET_OUT(kExpectedRequest0, &kResponse0);
1241   EXPECT_PACKET_OUT(kExpectedRequest1, &kNotFoundResponse1);
1242   EXPECT_PACKET_OUT(kExpectedRequest2, &kResponse2);
1243   EXPECT_PACKET_OUT(kExpectedRequest3, &kNotFoundResponse3);
1244   client()->DiscoverServicesWithUuids(
1245       ServiceKind::PRIMARY, svc_cb, res_cb, {kTestUuid2, kTestUuid1});
1246   RunUntilIdle();
1247   EXPECT_TRUE(AllExpectedPacketsSent());
1248 
1249   EXPECT_EQ(fit::ok(), status);
1250   EXPECT_EQ(2u, services.size());
1251 
1252   EXPECT_EQ(0x0001, services[0].range_start);
1253   EXPECT_EQ(0x0005, services[0].range_end);
1254   EXPECT_EQ(kTestUuid1, services[0].type);
1255 
1256   EXPECT_EQ(0x0006, services[1].range_start);
1257   EXPECT_EQ(0x0009, services[1].range_end);
1258   EXPECT_EQ(kTestUuid2, services[1].type);
1259 }
1260 
TEST_F(ClientTest,DiscoverServicesWithUuidsInRangeMultipleUuids)1261 TEST_F(ClientTest, DiscoverServicesWithUuidsInRangeMultipleUuids) {
1262   const att::Handle kRangeStart = 0x0002;
1263   const att::Handle kRangeEnd = 0x0020;
1264   const auto kExpectedRequest0 =
1265       StaticByteBuffer(0x06,  // opcode: find by type value request
1266                        LowerBits(kRangeStart),
1267                        UpperBits(kRangeStart),  // start handle
1268                        LowerBits(kRangeEnd),
1269                        UpperBits(kRangeEnd),  // end handle
1270                        0x00,
1271                        0x28,  // type: primary service (0x2800)
1272                        0xAD,
1273                        0xDE  // kTestUuid1
1274       );
1275   const auto kResponse0 =
1276       StaticByteBuffer(0x07,  // opcode: find by type value response
1277                        0x02,
1278                        0x00,  // svc 0 start: 0x0002
1279                        0x05,
1280                        0x00  // svc 0 end: 0x0005
1281       );
1282   const auto kExpectedRequest1 =
1283       StaticByteBuffer(0x06,  // opcode: find by type value request
1284                        0x06,
1285                        0x00,  // start handle: 0x0006
1286                        LowerBits(kRangeEnd),
1287                        UpperBits(kRangeEnd),  // end handle
1288                        0x00,
1289                        0x28,  // type: primary service (0x2800)
1290                        0xAD,
1291                        0xDE  // kTestUuid1
1292       );
1293   const auto kNotFoundResponse1 =
1294       StaticByteBuffer(0x01,  // opcode: error response
1295                        0x06,  // request: find by type value
1296                        0x06,
1297                        0x00,  // handle: 0x0006
1298                        0x0A   // error: Attribute Not Found
1299       );
1300   const auto kExpectedRequest2 =
1301       StaticByteBuffer(0x06,  // opcode: find by type value request
1302                        LowerBits(kRangeStart),
1303                        UpperBits(kRangeStart),  // start handle
1304                        LowerBits(kRangeEnd),
1305                        UpperBits(kRangeEnd),  // end handle
1306                        0x00,
1307                        0x28,  // type: primary service (0x2800)
1308                        0xEF,
1309                        0xBE  // kTestUuid2
1310       );
1311   const auto kResponse2 =
1312       StaticByteBuffer(0x07,  // opcode: find by type value response
1313                        0x06,
1314                        0x00,  // svc 1 start: 0x0006
1315                        0x09,
1316                        0x00  // svc 1 end: 0x0009
1317       );
1318   const auto kExpectedRequest3 =
1319       StaticByteBuffer(0x06,  // opcode: find by type value request
1320                        0x0A,
1321                        0x00,  // start handle: 0x000A
1322                        LowerBits(kRangeEnd),
1323                        UpperBits(kRangeEnd),  // end handle
1324                        0x00,
1325                        0x28,  // type: primary service (0x2800)
1326                        0xEF,
1327                        0xBE  // kTestUuid2
1328       );
1329   const auto kNotFoundResponse3 =
1330       StaticByteBuffer(0x01,  // opcode: error response
1331                        0x06,  // request: find by type value
1332                        0x0A,
1333                        0x00,  // handle: 0x000A
1334                        0x0A   // error: Attribute Not Found
1335       );
1336 
1337   att::Result<> status = ToResult(HostError::kFailed);
1338   auto res_cb = [&status](att::Result<> val) { status = val; };
1339 
1340   std::vector<ServiceData> services;
1341   auto svc_cb = [&services](const ServiceData& svc) {
1342     services.push_back(svc);
1343   };
1344 
1345   EXPECT_PACKET_OUT(kExpectedRequest0, &kResponse0);
1346   EXPECT_PACKET_OUT(kExpectedRequest1, &kNotFoundResponse1);
1347   EXPECT_PACKET_OUT(kExpectedRequest2, &kResponse2);
1348   EXPECT_PACKET_OUT(kExpectedRequest3, &kNotFoundResponse3);
1349   client()->DiscoverServicesWithUuidsInRange(ServiceKind::PRIMARY,
1350                                              kRangeStart,
1351                                              kRangeEnd,
1352                                              svc_cb,
1353                                              res_cb,
1354                                              {kTestUuid2, kTestUuid1});
1355   RunUntilIdle();
1356   EXPECT_TRUE(AllExpectedPacketsSent());
1357 
1358   EXPECT_EQ(fit::ok(), status);
1359   EXPECT_EQ(2u, services.size());
1360 
1361   EXPECT_EQ(0x0002, services[0].range_start);
1362   EXPECT_EQ(0x0005, services[0].range_end);
1363   EXPECT_EQ(kTestUuid1, services[0].type);
1364 
1365   EXPECT_EQ(0x0006, services[1].range_start);
1366   EXPECT_EQ(0x0009, services[1].range_end);
1367   EXPECT_EQ(kTestUuid2, services[1].type);
1368 }
1369 
TEST_F(ClientTest,DiscoverServicesWithUuidsInRangeFailsOnResultNotInRequestedRange)1370 TEST_F(ClientTest,
1371        DiscoverServicesWithUuidsInRangeFailsOnResultNotInRequestedRange) {
1372   const att::Handle kRangeStart = 0x0010;
1373   const att::Handle kRangeEnd = 0x0020;
1374   const att::Handle kServiceStart = 0x0002;
1375   const att::Handle kServiceEnd = 0x0011;
1376 
1377   const auto kExpectedRequest =
1378       StaticByteBuffer(0x06,  // opcode: find by type value request
1379                        LowerBits(kRangeStart),
1380                        UpperBits(kRangeStart),  // start handle
1381                        LowerBits(kRangeEnd),
1382                        UpperBits(kRangeEnd),  // end handle
1383                        0x00,
1384                        0x28,  // type: primary service (0x2800)
1385                        0xAD,
1386                        0xDE  // kTestUuid1
1387       );
1388   const auto kResponse =
1389       StaticByteBuffer(0x07,  // opcode: find by type value response
1390                        LowerBits(kServiceStart),
1391                        UpperBits(kServiceStart),  // svc start
1392                        LowerBits(kServiceEnd),
1393                        UpperBits(kServiceEnd)  // svc end
1394       );
1395 
1396   std::optional<att::Result<>> status;
1397   auto res_cb = [&status](att::Result<> val) { status = val; };
1398 
1399   std::vector<ServiceData> services;
1400   auto svc_cb = [&services](const ServiceData& svc) {
1401     services.push_back(svc);
1402   };
1403 
1404   EXPECT_PACKET_OUT(kExpectedRequest, &kResponse);
1405   client()->DiscoverServicesWithUuidsInRange(ServiceKind::PRIMARY,
1406                                              kRangeStart,
1407                                              kRangeEnd,
1408                                              svc_cb,
1409                                              res_cb,
1410                                              {kTestUuid1});
1411   RunUntilIdle();
1412   ASSERT_TRUE(status.has_value());
1413   EXPECT_EQ(ToResult(HostError::kPacketMalformed), *status);
1414   EXPECT_EQ(0u, services.size());
1415 }
1416 
TEST_F(ClientTest,CharacteristicDiscoveryHandlesEqual)1417 TEST_F(ClientTest, CharacteristicDiscoveryHandlesEqual) {
1418   constexpr att::Handle kStart = 0x0001;
1419   constexpr att::Handle kEnd = 0x0001;
1420 
1421   att::Result<> status = ToResult(HostError::kFailed);  // Initialize as error
1422   auto res_cb = [&status](att::Result<> val) { status = val; };
1423 
1424   // Should succeed immediately.
1425   client()->DiscoverCharacteristics(kStart, kEnd, NopChrcCallback, res_cb);
1426   EXPECT_EQ(fit::ok(), status);
1427 }
1428 
TEST_F(ClientTest,CharacteristicDiscoveryResponseTooShort)1429 TEST_F(ClientTest, CharacteristicDiscoveryResponseTooShort) {
1430   constexpr att::Handle kStart = 0x0001;
1431   constexpr att::Handle kEnd = 0xFFFF;
1432 
1433   const auto kExpectedRequest =
1434       StaticByteBuffer(0x08,  // opcode: read by type request
1435                        0x01,
1436                        0x00,  // start handle: 0x0001
1437                        0xFF,
1438                        0xFF,  // end handle: 0xFFFF
1439                        0x03,
1440                        0x28  // type: characteristic decl. (0x2803)
1441       );
1442   const StaticByteBuffer kMalformedResponse(0x09);
1443 
1444   att::Result<> status = fit::ok();
1445   auto res_cb = [&status](att::Result<> val) { status = val; };
1446 
1447   EXPECT_PACKET_OUT(kExpectedRequest, &kMalformedResponse);
1448   client()->DiscoverCharacteristics(kStart, kEnd, NopChrcCallback, res_cb);
1449   RunUntilIdle();
1450   EXPECT_EQ(ToResult(HostError::kPacketMalformed), status);
1451 }
1452 
TEST_F(ClientTest,CharacteristicDiscoveryMalformedDataLength)1453 TEST_F(ClientTest, CharacteristicDiscoveryMalformedDataLength) {
1454   constexpr att::Handle kStart = 0x0001;
1455   constexpr att::Handle kEnd = 0xFFFF;
1456 
1457   const auto kExpectedRequest =
1458       StaticByteBuffer(0x08,  // opcode: read by type request
1459                        0x01,
1460                        0x00,  // start handle: 0x0001
1461                        0xFF,
1462                        0xFF,  // end handle: 0xFFFF
1463                        0x03,
1464                        0x28  // type: characteristic decl. (0x2803)
1465       );
1466   // Respond back with an unexpected data length. This is 7 for characteristics
1467   // with a 16-bit UUID (handle (2) + props (1) + value handle (2) + uuid (2))
1468   // and 21 for 128-bit (handle (2) + props (1) + value handle (2) + uuid (16)).
1469   const StaticByteBuffer kResponse(
1470       0x09,  // opcode: read by type response
1471       8,     // data length: 8 (not 7 or 21)
1472       0,
1473       1,
1474       2,
1475       3,
1476       4,
1477       5,
1478       6,
1479       7  // one entry of length 8, which will be ignored
1480   );
1481 
1482   att::Result<> status = fit::ok();
1483   auto res_cb = [&status](att::Result<> val) { status = val; };
1484 
1485   EXPECT_PACKET_OUT(kExpectedRequest, &kResponse);
1486   client()->DiscoverCharacteristics(kStart, kEnd, NopChrcCallback, res_cb);
1487   RunUntilIdle();
1488   EXPECT_EQ(ToResult(HostError::kPacketMalformed), status);
1489 }
1490 
TEST_F(ClientTest,CharacteristicDiscoveryMalformedAttrDataList)1491 TEST_F(ClientTest, CharacteristicDiscoveryMalformedAttrDataList) {
1492   constexpr att::Handle kStart = 0x0001;
1493   constexpr att::Handle kEnd = 0xFFFF;
1494 
1495   const auto kExpectedRequest =
1496       StaticByteBuffer(0x08,  // opcode: read by type request
1497                        0x01,
1498                        0x00,  // start handle: 0x0001
1499                        0xFF,
1500                        0xFF,  // end handle: 0xFFFF
1501                        0x03,
1502                        0x28  // type: characteristic decl. (0x2803)
1503       );
1504 
1505   // Respond back with an unexpected data length. This is 7 for characteristics
1506   // with a 16-bit UUID (handle (2) + props (1) + value handle (2) + uuid (2))
1507   // and 21 for 128-bit (handle (2) + props (1) + value handle (2) + uuid (16)).
1508   const StaticByteBuffer kResponse(0x09,  // opcode: read by type response
1509                                    7,     // data length: 7 (16-bit UUIDs)
1510                                    0,
1511                                    1,
1512                                    2,
1513                                    3,
1514                                    4,
1515                                    5,
1516                                    6,  // entry 1: correct size
1517                                    0,
1518                                    1,
1519                                    2,
1520                                    3,
1521                                    4,
1522                                    5  // entry 2: incorrect size
1523   );
1524 
1525   att::Result<> status = fit::ok();
1526   auto res_cb = [&status](att::Result<> val) { status = val; };
1527 
1528   EXPECT_PACKET_OUT(kExpectedRequest, &kResponse);
1529   client()->DiscoverCharacteristics(kStart, kEnd, NopChrcCallback, res_cb);
1530   EXPECT_TRUE(AllExpectedPacketsSent());
1531   RunUntilIdle();
1532   EXPECT_EQ(ToResult(HostError::kPacketMalformed), status);
1533 }
1534 
TEST_F(ClientTest,CharacteristicDiscoveryEmptyDataList)1535 TEST_F(ClientTest, CharacteristicDiscoveryEmptyDataList) {
1536   constexpr att::Handle kStart = 0x0001;
1537   constexpr att::Handle kEnd = 0xFFFF;
1538 
1539   const auto kExpectedRequest =
1540       StaticByteBuffer(0x08,  // opcode: read by type request
1541                        0x01,
1542                        0x00,  // start handle: 0x0001
1543                        0xFF,
1544                        0xFF,  // end handle: 0xFFFF
1545                        0x03,
1546                        0x28  // type: characteristic decl. (0x2803)
1547       );
1548   const StaticByteBuffer kResponse(0x09,  // opcode: read by type response
1549                                    7      // data length: 7 (16-bit UUIDs)
1550                                           // data list empty
1551   );
1552 
1553   att::Result<> status = fit::ok();
1554   auto res_cb = [&status](att::Result<> val) { status = val; };
1555 
1556   EXPECT_PACKET_OUT(kExpectedRequest, &kResponse);
1557   client()->DiscoverCharacteristics(kStart, kEnd, NopChrcCallback, res_cb);
1558   RunUntilIdle();
1559   EXPECT_EQ(status, ToResult(HostError::kPacketMalformed));
1560 }
1561 
TEST_F(ClientTest,CharacteristicDiscoveryAttributeNotFound)1562 TEST_F(ClientTest, CharacteristicDiscoveryAttributeNotFound) {
1563   constexpr att::Handle kStart = 0x0001;
1564   constexpr att::Handle kEnd = 0xFFFF;
1565 
1566   const auto kExpectedRequest =
1567       StaticByteBuffer(0x08,  // opcode: read by type request
1568                        0x01,
1569                        0x00,  // start handle: 0x0001
1570                        0xFF,
1571                        0xFF,  // end handle: 0xFFFF
1572                        0x03,
1573                        0x28  // type: characteristic decl. (0x2803)
1574       );
1575   const StaticByteBuffer kResponse(0x01,  // opcode: error response
1576                                    0x08,  // request: read by type
1577                                    0x01,
1578                                    0x00,  // handle: 0x0001
1579                                    0x0A   // error: Attribute Not Found
1580   );
1581 
1582   att::Result<> status = fit::ok();
1583   auto res_cb = [&status](att::Result<> val) { status = val; };
1584 
1585   EXPECT_PACKET_OUT(kExpectedRequest, &kResponse);
1586   client()->DiscoverCharacteristics(kStart, kEnd, NopChrcCallback, res_cb);
1587   RunUntilIdle();
1588   // Attribute Not Found error means the procedure is over.
1589   EXPECT_EQ(fit::ok(), status);
1590 }
1591 
TEST_F(ClientTest,CharacteristicDiscoveryError)1592 TEST_F(ClientTest, CharacteristicDiscoveryError) {
1593   constexpr att::Handle kStart = 0x0001;
1594   constexpr att::Handle kEnd = 0xFFFF;
1595 
1596   const auto kExpectedRequest =
1597       StaticByteBuffer(0x08,  // opcode: read by type request
1598                        0x01,
1599                        0x00,  // start handle: 0x0001
1600                        0xFF,
1601                        0xFF,  // end handle: 0xFFFF
1602                        0x03,
1603                        0x28  // type: characteristic decl. (0x2803)
1604       );
1605   const StaticByteBuffer kResponse(0x01,  // opcode: error response
1606                                    0x08,  // request: read by type
1607                                    0x01,
1608                                    0x00,  // handle: 0x0001
1609                                    0x06   // error: Request Not Supported
1610   );
1611 
1612   att::Result<> status = fit::ok();
1613   auto res_cb = [&status](att::Result<> val) { status = val; };
1614 
1615   EXPECT_PACKET_OUT(kExpectedRequest, &kResponse);
1616   client()->DiscoverCharacteristics(kStart, kEnd, NopChrcCallback, res_cb);
1617   RunUntilIdle();
1618   EXPECT_EQ(ToResult(att::ErrorCode::kRequestNotSupported), status);
1619 }
1620 
TEST_F(ClientTest,CharacteristicDiscovery16BitResultsSingleRequest)1621 TEST_F(ClientTest, CharacteristicDiscovery16BitResultsSingleRequest) {
1622   constexpr att::Handle kStart = 0x0001;
1623   constexpr att::Handle kEnd = 0x0005;
1624 
1625   const auto kExpectedRequest =
1626       StaticByteBuffer(0x08,  // opcode: read by type request
1627                        0x01,
1628                        0x00,  // start handle: 0x0001
1629                        0x05,
1630                        0x00,  // end handle: 0x0005
1631                        0x03,
1632                        0x28  // type: characteristic decl. (0x2803)
1633       );
1634   const StaticByteBuffer kResponse(
1635       0x09,  // opcode: read by type response
1636       0x07,  // data length: 7 (16-bit UUIDs)
1637       0x03,
1638       0x00,  // chrc 1 handle
1639       0x00,  // chrc 1 properties
1640       0x04,
1641       0x00,  // chrc 1 value handle
1642       0xAD,
1643       0xDE,  // chrc 1 uuid: 0xDEAD
1644       0x05,
1645       0x00,  // chrc 2 handle (0x0005 is the end of the requested range)
1646       0x01,  // chrc 2 properties
1647       0x06,
1648       0x00,  // chrc 2 value handle
1649       0xEF,
1650       0xBE  // chrc 2 uuid: 0xBEEF
1651   );
1652 
1653   att::Result<> status = fit::ok();
1654   auto res_cb = [&status](att::Result<> val) { status = val; };
1655 
1656   std::vector<CharacteristicData> chrcs;
1657   auto chrc_cb = [&chrcs](const CharacteristicData& chrc) {
1658     chrcs.push_back(chrc);
1659   };
1660 
1661   EXPECT_PACKET_OUT(kExpectedRequest, &kResponse);
1662   client()->DiscoverCharacteristics(kStart, kEnd, chrc_cb, res_cb);
1663   RunUntilIdle();
1664   EXPECT_EQ(fit::ok(), status);
1665   ASSERT_EQ(2u, chrcs.size());
1666   EXPECT_EQ(0x0003, chrcs[0].handle);
1667   EXPECT_EQ(0, chrcs[0].properties);
1668   EXPECT_EQ(0x0004, chrcs[0].value_handle);
1669   EXPECT_EQ(kTestUuid1, chrcs[0].type);
1670   EXPECT_EQ(0x0005, chrcs[1].handle);
1671   EXPECT_EQ(1, chrcs[1].properties);
1672   EXPECT_EQ(0x0006, chrcs[1].value_handle);
1673   EXPECT_EQ(kTestUuid2, chrcs[1].type);
1674 }
1675 
TEST_F(ClientTest,CharacteristicDiscovery128BitResultsSingleRequest)1676 TEST_F(ClientTest, CharacteristicDiscovery128BitResultsSingleRequest) {
1677   constexpr att::Handle kStart = 0x0001;
1678   constexpr att::Handle kEnd = 0x0005;
1679 
1680   const auto kExpectedRequest =
1681       StaticByteBuffer(0x08,  // opcode: read by type request
1682                        0x01,
1683                        0x00,  // start handle: 0x0001
1684                        0x05,
1685                        0x00,  // end handle: 0x0005
1686                        0x03,
1687                        0x28  // type: characteristic decl. (0x2803)
1688       );
1689   const StaticByteBuffer kResponse(0x09,  // opcode: read by type response
1690                                    0x15,  // data length: 21 (128-bit UUIDs)
1691                                    0x05,
1692                                    0x00,  // chrc handle
1693                                    0x00,  // chrc properties
1694                                    0x06,
1695                                    0x00,  // chrc value handle
1696 
1697                                    // UUID matches |kTestUuid3| declared above.
1698                                    0,
1699                                    1,
1700                                    2,
1701                                    3,
1702                                    4,
1703                                    5,
1704                                    6,
1705                                    7,
1706                                    8,
1707                                    9,
1708                                    10,
1709                                    11,
1710                                    12,
1711                                    13,
1712                                    14,
1713                                    15);
1714 
1715   att::Result<> status = fit::ok();
1716   auto res_cb = [&status](att::Result<> val) { status = val; };
1717 
1718   std::vector<CharacteristicData> chrcs;
1719   auto chrc_cb = [&chrcs](const CharacteristicData& chrc) {
1720     chrcs.push_back(chrc);
1721   };
1722 
1723   EXPECT_PACKET_OUT(kExpectedRequest, &kResponse);
1724   client()->DiscoverCharacteristics(kStart, kEnd, chrc_cb, res_cb);
1725   RunUntilIdle();
1726   EXPECT_EQ(fit::ok(), status);
1727   EXPECT_EQ(1u, chrcs.size());
1728   EXPECT_EQ(0x0005, chrcs[0].handle);
1729   EXPECT_EQ(0, chrcs[0].properties);
1730   EXPECT_EQ(0x0006, chrcs[0].value_handle);
1731   EXPECT_EQ(kTestUuid3, chrcs[0].type);
1732 }
1733 
TEST_F(ClientTest,CharacteristicDiscoveryMultipleRequests)1734 TEST_F(ClientTest, CharacteristicDiscoveryMultipleRequests) {
1735   constexpr att::Handle kStart = 0x0001;
1736   constexpr att::Handle kEnd = 0xFFFF;
1737 
1738   const auto kExpectedRequest0 =
1739       StaticByteBuffer(0x08,  // opcode: read by type request
1740                        0x01,
1741                        0x00,  // start handle: 0x0001
1742                        0xFF,
1743                        0xFF,  // end handle: 0xFFFF
1744                        0x03,
1745                        0x28  // type: characteristic decl. (0x2803)
1746       );
1747   const auto kResponse0 =
1748       StaticByteBuffer(0x09,  // opcode: read by type response
1749                        0x07,  // data length: 7 (16-bit UUIDs)
1750                        0x03,
1751                        0x00,  // chrc 1 handle
1752                        0x00,  // chrc 1 properties
1753                        0x04,
1754                        0x00,  // chrc 1 value handle
1755                        0xAD,
1756                        0xDE,  // chrc 1 uuid: 0xDEAD
1757                        0x05,
1758                        0x00,  // chrc 2 handle
1759                        0x01,  // chrc 2 properties
1760                        0x06,
1761                        0x00,  // chrc 2 value handle
1762                        0xEF,
1763                        0xBE  // chrc 2 uuid: 0xBEEF
1764       );
1765   const auto kExpectedRequest1 =
1766       StaticByteBuffer(0x08,  // opcode: read by type request
1767                        0x06,
1768                        0x00,  // start handle: 0x0006
1769                        0xFF,
1770                        0xFF,  // end handle: 0xFFFF
1771                        0x03,
1772                        0x28  // type: characteristic decl. (0x2803)
1773       );
1774   // Respond with one characteristic with a 128-bit UUID
1775   const auto kResponse1 =
1776       StaticByteBuffer(0x09,  // opcode: read by type response
1777                        0x15,  // data length: 21 (128-bit UUIDs)
1778                        0x07,
1779                        0x00,  // chrc handle
1780                        0x00,  // chrc properties
1781                        0x08,
1782                        0x00,  // chrc value handle
1783                        // UUID matches |kTestUuid3| declared above.
1784                        0,
1785                        1,
1786                        2,
1787                        3,
1788                        4,
1789                        5,
1790                        6,
1791                        7,
1792                        8,
1793                        9,
1794                        10,
1795                        11,
1796                        12,
1797                        13,
1798                        14,
1799                        15);
1800   const auto kExpectedRequest2 =
1801       StaticByteBuffer(0x08,  // opcode: read by type request
1802                        0x08,
1803                        0x00,  // start handle: 0x0008
1804                        0xFF,
1805                        0xFF,  // end handle: 0xFFFF
1806                        0x03,
1807                        0x28  // type: characteristic decl. (0x2803)
1808       );
1809   // Terminate the procedure with an error response.
1810   const StaticByteBuffer kResponse2(0x01,  // opcode: error response
1811                                     0x08,  // request: read by type
1812                                     0x0A,
1813                                     0x00,  // handle: 0x000A
1814                                     0x0A   // error: Attribute Not Found
1815   );
1816 
1817   att::Result<> status = fit::ok();
1818   auto res_cb = [&status](att::Result<> val) { status = val; };
1819 
1820   std::vector<CharacteristicData> chrcs;
1821   auto chrc_cb = [&chrcs](const CharacteristicData& chrc) {
1822     chrcs.push_back(chrc);
1823   };
1824 
1825   EXPECT_PACKET_OUT(kExpectedRequest0, &kResponse0);
1826   EXPECT_PACKET_OUT(kExpectedRequest1, &kResponse1);
1827   EXPECT_PACKET_OUT(kExpectedRequest2, &kResponse2);
1828   client()->DiscoverCharacteristics(kStart, kEnd, chrc_cb, res_cb);
1829   RunUntilIdle();
1830   EXPECT_TRUE(AllExpectedPacketsSent());
1831 
1832   EXPECT_EQ(fit::ok(), status);
1833   EXPECT_EQ(3u, chrcs.size());
1834 
1835   EXPECT_EQ(0x0003, chrcs[0].handle);
1836   EXPECT_EQ(0, chrcs[0].properties);
1837   EXPECT_EQ(0x0004, chrcs[0].value_handle);
1838   EXPECT_EQ(kTestUuid1, chrcs[0].type);
1839 
1840   EXPECT_EQ(0x0005, chrcs[1].handle);
1841   EXPECT_EQ(1, chrcs[1].properties);
1842   EXPECT_EQ(0x0006, chrcs[1].value_handle);
1843   EXPECT_EQ(kTestUuid2, chrcs[1].type);
1844 
1845   EXPECT_EQ(0x0007, chrcs[2].handle);
1846   EXPECT_EQ(0, chrcs[2].properties);
1847   EXPECT_EQ(0x0008, chrcs[2].value_handle);
1848   EXPECT_EQ(kTestUuid3, chrcs[2].type);
1849 }
1850 
1851 // Expects the discovery procedure to end with an error if a batch contains
1852 // results that are from before requested range.
TEST_F(ClientTest,CharacteristicDiscoveryResultsBeforeRange)1853 TEST_F(ClientTest, CharacteristicDiscoveryResultsBeforeRange) {
1854   constexpr att::Handle kStart = 0x0002;
1855   constexpr att::Handle kEnd = 0x0005;
1856 
1857   const auto kExpectedRequest =
1858       StaticByteBuffer(0x08,  // opcode: read by type request
1859                        0x02,
1860                        0x00,  // start handle: 0x0002
1861                        0x05,
1862                        0x00,  // end handle: 0x0005
1863                        0x03,
1864                        0x28  // type: characteristic decl. (0x2803)
1865       );
1866   const StaticByteBuffer kResponse(
1867       0x09,  // opcode: read by type response
1868       0x07,  // data length: 7 (16-bit UUIDs)
1869       0x01,
1870       0x00,  // chrc 1 handle (handle is before the range)
1871       0x00,  // chrc 1 properties
1872       0x02,
1873       0x00,  // chrc 1 value handle
1874       0xAD,
1875       0xDE  // chrc 1 uuid: 0xDEAD
1876   );
1877 
1878   att::Result<> status = fit::ok();
1879   auto res_cb = [&status](att::Result<> val) { status = val; };
1880 
1881   std::vector<CharacteristicData> chrcs;
1882   auto chrc_cb = [&chrcs](const CharacteristicData& chrc) {
1883     chrcs.push_back(chrc);
1884   };
1885 
1886   EXPECT_PACKET_OUT(kExpectedRequest, &kResponse);
1887   client()->DiscoverCharacteristics(kStart, kEnd, chrc_cb, res_cb);
1888   RunUntilIdle();
1889   EXPECT_EQ(ToResult(HostError::kPacketMalformed), status);
1890   EXPECT_TRUE(chrcs.empty());
1891 }
1892 
1893 // Expects the discovery procedure to end with an error if a batch contains
1894 // results that are from beyond the requested range.
TEST_F(ClientTest,CharacteristicDiscoveryResultsBeyondRange)1895 TEST_F(ClientTest, CharacteristicDiscoveryResultsBeyondRange) {
1896   constexpr att::Handle kStart = 0x0002;
1897   constexpr att::Handle kEnd = 0x0005;
1898 
1899   const auto kExpectedRequest =
1900       StaticByteBuffer(0x08,  // opcode: read by type request
1901                        0x02,
1902                        0x00,  // start handle: 0x0002
1903                        0x05,
1904                        0x00,  // end handle: 0x0005
1905                        0x03,
1906                        0x28  // type: characteristic decl. (0x2803)
1907       );
1908   const StaticByteBuffer kResponse(
1909       0x09,  // opcode: read by type response
1910       0x07,  // data length: 7 (16-bit UUIDs)
1911       0x06,
1912       0x00,  // chrc 1 handle (handle is beyond the range)
1913       0x00,  // chrc 1 properties
1914       0x07,
1915       0x00,  // chrc 1 value handle
1916       0xAD,
1917       0xDE  // chrc 1 uuid: 0xDEAD
1918   );
1919 
1920   att::Result<> status = fit::ok();
1921   auto res_cb = [&status](att::Result<> val) { status = val; };
1922 
1923   std::vector<CharacteristicData> chrcs;
1924   auto chrc_cb = [&chrcs](const CharacteristicData& chrc) {
1925     chrcs.push_back(chrc);
1926   };
1927 
1928   EXPECT_PACKET_OUT(kExpectedRequest, &kResponse);
1929   client()->DiscoverCharacteristics(kStart, kEnd, chrc_cb, res_cb);
1930   RunUntilIdle();
1931   EXPECT_EQ(ToResult(HostError::kPacketMalformed), status);
1932   EXPECT_TRUE(chrcs.empty());
1933 }
1934 
1935 // Expects the characteristic value handle to immediately follow the
1936 // declaration as specified in Vol 3, Part G, 3.3.
TEST_F(ClientTest,CharacteristicDiscoveryValueNotContiguous)1937 TEST_F(ClientTest, CharacteristicDiscoveryValueNotContiguous) {
1938   constexpr att::Handle kStart = 0x0002;
1939   constexpr att::Handle kEnd = 0x0005;
1940 
1941   const auto kExpectedRequest =
1942       StaticByteBuffer(0x08,  // opcode: read by type request
1943                        0x02,
1944                        0x00,  // start handle: 0x0002
1945                        0x05,
1946                        0x00,  // end handle: 0x0005
1947                        0x03,
1948                        0x28  // type: characteristic decl. (0x2803)
1949       );
1950   const StaticByteBuffer kResponse(0x09,  // opcode: read by type response
1951                                    0x07,  // data length: 7 (16-bit UUIDs)
1952                                    0x02,
1953                                    0x00,  // chrc 1 handle
1954                                    0x00,  // chrc 1 properties
1955                                    0x04,
1956                                    0x00,  // chrc 1 value handle (not immediate)
1957                                    0xAD,
1958                                    0xDE  // chrc 1 uuid: 0xDEAD
1959   );
1960 
1961   att::Result<> status = fit::ok();
1962   auto res_cb = [&status](att::Result<> val) { status = val; };
1963 
1964   std::vector<CharacteristicData> chrcs;
1965   auto chrc_cb = [&chrcs](const CharacteristicData& chrc) {
1966     chrcs.push_back(chrc);
1967   };
1968 
1969   EXPECT_PACKET_OUT(kExpectedRequest, &kResponse);
1970   client()->DiscoverCharacteristics(kStart, kEnd, chrc_cb, res_cb);
1971   RunUntilIdle();
1972   EXPECT_EQ(ToResult(HostError::kPacketMalformed), status);
1973   EXPECT_TRUE(chrcs.empty());
1974 }
1975 
TEST_F(ClientTest,CharacteristicDiscoveryHandlesNotIncreasing)1976 TEST_F(ClientTest, CharacteristicDiscoveryHandlesNotIncreasing) {
1977   constexpr att::Handle kStart = 0x0002;
1978   constexpr att::Handle kEnd = 0x0005;
1979 
1980   const auto kExpectedRequest =
1981       StaticByteBuffer(0x08,  // opcode: read by type request
1982                        0x02,
1983                        0x00,  // start handle: 0x0002
1984                        0x05,
1985                        0x00,  // end handle: 0x0005
1986                        0x03,
1987                        0x28  // type: characteristic decl. (0x2803)
1988       );
1989   const StaticByteBuffer kResponse(0x09,  // opcode: read by type response
1990                                    0x07,  // data length: 7 (16-bit UUIDs)
1991                                    0x02,
1992                                    0x00,  // chrc 1 handle
1993                                    0x00,  // chrc 1 properties
1994                                    0x03,
1995                                    0x00,  // chrc 1 value handle
1996                                    0xAD,
1997                                    0xDE,  // chrc 1 uuid: 0xDEAD
1998                                    0x02,
1999                                    0x00,  // chrc 1 handle (repeated)
2000                                    0x00,  // chrc 1 properties
2001                                    0x03,
2002                                    0x00,  // chrc 1 value handle
2003                                    0xEF,
2004                                    0xBE  // chrc 1 uuid: 0xBEEF
2005   );
2006 
2007   att::Result<> status = fit::ok();
2008   auto res_cb = [&status](att::Result<> val) { status = val; };
2009 
2010   std::vector<CharacteristicData> chrcs;
2011   auto chrc_cb = [&chrcs](const CharacteristicData& chrc) {
2012     chrcs.push_back(chrc);
2013   };
2014 
2015   EXPECT_PACKET_OUT(kExpectedRequest, &kResponse);
2016   client()->DiscoverCharacteristics(kStart, kEnd, chrc_cb, res_cb);
2017   RunUntilIdle();
2018   EXPECT_EQ(ToResult(HostError::kPacketMalformed), status);
2019   // No Characteristics should be reported.
2020   EXPECT_EQ(0u, chrcs.size());
2021 }
2022 
2023 // Equal handles should not short-circuit and should result in a request.
TEST_F(ClientTest,DescriptorDiscoveryHandlesEqual)2024 TEST_F(ClientTest, DescriptorDiscoveryHandlesEqual) {
2025   constexpr att::Handle kStart = 0x0001;
2026   constexpr att::Handle kEnd = 0x0001;
2027 
2028   att::Result<> status = ToResult(HostError::kFailed);  // Initialize as error
2029   EXPECT_PACKET_OUT(MakeFindInformation(kStart, kEnd));
2030   SendDiscoverDescriptors(&status, NopDescCallback, kStart, kEnd);
2031   EXPECT_TRUE(AllExpectedPacketsSent());
2032 }
2033 
TEST_F(ClientTest,DescriptorDiscoveryResponseTooShort)2034 TEST_F(ClientTest, DescriptorDiscoveryResponseTooShort) {
2035   att::Result<> status = fit::ok();
2036   // Respond back with a malformed payload.
2037   const StaticByteBuffer kResponse(0x05);
2038   EXPECT_PACKET_OUT(MakeFindInformation(), &kResponse);
2039   SendDiscoverDescriptors(&status, NopDescCallback);
2040   RunUntilIdle();
2041   EXPECT_EQ(ToResult(HostError::kPacketMalformed), status);
2042 }
2043 
TEST_F(ClientTest,DescriptorDiscoveryMalformedDataLength)2044 TEST_F(ClientTest, DescriptorDiscoveryMalformedDataLength) {
2045   att::Result<> status = fit::ok();
2046   const StaticByteBuffer kResponse(0x05,  // opcode: find information response
2047                                    0x03   // format (must be 1 or 2)
2048   );
2049   EXPECT_PACKET_OUT(MakeFindInformation(), &kResponse);
2050   SendDiscoverDescriptors(&status, NopDescCallback);
2051   RunUntilIdle();
2052   EXPECT_EQ(ToResult(HostError::kPacketMalformed), status);
2053 }
2054 
TEST_F(ClientTest,DescriptorDiscoveryMalformedAttrDataList16)2055 TEST_F(ClientTest, DescriptorDiscoveryMalformedAttrDataList16) {
2056   att::Result<> status = fit::ok();
2057   const StaticByteBuffer kResponse(
2058       0x05,  // opcode: find information response
2059       0x01,  // format: 16-bit. Data length must be 4
2060       1,
2061       2,
2062       3,
2063       4,
2064       5);
2065   EXPECT_PACKET_OUT(MakeFindInformation(), &kResponse);
2066   SendDiscoverDescriptors(&status, NopDescCallback);
2067   RunUntilIdle();
2068   EXPECT_EQ(ToResult(HostError::kPacketMalformed), status);
2069 }
2070 
TEST_F(ClientTest,DescriptorDiscoveryMalformedAttrDataList128)2071 TEST_F(ClientTest, DescriptorDiscoveryMalformedAttrDataList128) {
2072   att::Result<> status = fit::ok();
2073   const StaticByteBuffer kResponse(
2074       0x05,  // opcode: find information response
2075       0x02,  // format: 128-bit. Data length must be 18
2076       1,
2077       2,
2078       3,
2079       4,
2080       5,
2081       6,
2082       7,
2083       8,
2084       9,
2085       10,
2086       11,
2087       12,
2088       13,
2089       14,
2090       15,
2091       16,
2092       17);
2093   EXPECT_PACKET_OUT(MakeFindInformation(), &kResponse);
2094   SendDiscoverDescriptors(&status, NopDescCallback);
2095   RunUntilIdle();
2096   EXPECT_EQ(ToResult(HostError::kPacketMalformed), status);
2097 }
2098 
TEST_F(ClientTest,DescriptorDiscoveryEmptyDataList)2099 TEST_F(ClientTest, DescriptorDiscoveryEmptyDataList) {
2100   att::Result<> status = ToResult(HostError::kFailed);
2101   const StaticByteBuffer kResponse(0x05,  // opcode: find information response
2102                                    0x01   // format: 16-bit.
2103                                           // data list empty
2104   );
2105   EXPECT_PACKET_OUT(MakeFindInformation(), &kResponse);
2106   SendDiscoverDescriptors(&status, NopDescCallback);
2107   RunUntilIdle();
2108   EXPECT_EQ(fit::ok(), status);
2109 }
2110 
TEST_F(ClientTest,DescriptorDiscoveryAttributeNotFound)2111 TEST_F(ClientTest, DescriptorDiscoveryAttributeNotFound) {
2112   att::Result<> status = ToResult(HostError::kFailed);
2113   const StaticByteBuffer kResponse(0x01,  // opcode: error response
2114                                    0x04,  // request: find information
2115                                    0x01,
2116                                    0x00,  // handle: 0x0001
2117                                    0x0A   // error: Attribute Not Found
2118   );
2119   EXPECT_PACKET_OUT(MakeFindInformation(), &kResponse);
2120   SendDiscoverDescriptors(&status, NopDescCallback);
2121   RunUntilIdle();
2122   EXPECT_EQ(fit::ok(), status);
2123 }
2124 
TEST_F(ClientTest,DescriptorDiscoveryError)2125 TEST_F(ClientTest, DescriptorDiscoveryError) {
2126   att::Result<> status = ToResult(HostError::kFailed);
2127   const StaticByteBuffer kResponse(0x01,  // opcode: error response
2128                                    0x04,  // request: find information
2129                                    0x01,
2130                                    0x00,  // handle: 0x0001
2131                                    0x06   // error: Request Not Supported
2132   );
2133   EXPECT_PACKET_OUT(MakeFindInformation(), &kResponse);
2134   SendDiscoverDescriptors(&status, NopDescCallback);
2135   RunUntilIdle();
2136   EXPECT_EQ(ToResult(att::ErrorCode::kRequestNotSupported), status);
2137 }
2138 
TEST_F(ClientTest,DescriptorDiscovery16BitResultsSingleRequest)2139 TEST_F(ClientTest, DescriptorDiscovery16BitResultsSingleRequest) {
2140   constexpr att::Handle kStart = 0x0001;
2141   constexpr att::Handle kEnd = 0x0003;
2142 
2143   const StaticByteBuffer kResponse(
2144       0x05,  // opcode: find information response
2145       0x01,  // format: 16-bit. Data length must be 4
2146       0x01,
2147       0x00,  // desc 1 handle
2148       0xEF,
2149       0xBE,  // desc 1 uuid
2150       0x02,
2151       0x00,  // desc 2 handle
2152       0xAD,
2153       0xDE,  // desc 2 uuid
2154       0x03,
2155       0x00,  // desc 3 handle
2156       0xFE,
2157       0xFE  // desc 3 uuid
2158   );
2159 
2160   std::vector<DescriptorData> descrs;
2161   auto desc_cb = [&descrs](const DescriptorData& desc) {
2162     descrs.push_back(desc);
2163   };
2164 
2165   att::Result<> status = ToResult(HostError::kFailed);
2166   EXPECT_PACKET_OUT(MakeFindInformation(kStart, kEnd), &kResponse);
2167   SendDiscoverDescriptors(&status, std::move(desc_cb), kStart, kEnd);
2168   RunUntilIdle();
2169   EXPECT_EQ(fit::ok(), status);
2170   ASSERT_EQ(3u, descrs.size());
2171   EXPECT_EQ(0x0001, descrs[0].handle);
2172   EXPECT_EQ(0x0002, descrs[1].handle);
2173   EXPECT_EQ(0x0003, descrs[2].handle);
2174   EXPECT_EQ(uint16_t{0xBEEF}, descrs[0].type);
2175   EXPECT_EQ(uint16_t{0xDEAD}, descrs[1].type);
2176   EXPECT_EQ(uint16_t{0xFEFE}, descrs[2].type);
2177 }
2178 
TEST_F(ClientTest,DescriptorDiscovery128BitResultsSingleRequest)2179 TEST_F(ClientTest, DescriptorDiscovery128BitResultsSingleRequest) {
2180   constexpr att::Handle kStart = 0x0001;
2181   constexpr att::Handle kEnd = 0x0002;
2182 
2183   const StaticByteBuffer kResponse(
2184       0x05,  // opcode: find information response
2185       0x02,  // format: 128-bit. Data length must be 18
2186       0x01,
2187       0x00,  // desc 1 handle
2188       0xFB,
2189       0x34,
2190       0x9B,
2191       0x5F,
2192       0x80,
2193       0x00,
2194       0x00,
2195       0x80,
2196       0x00,
2197       0x10,
2198       0x00,
2199       0x00,
2200       0xEF,
2201       0xBE,
2202       0x00,
2203       0x00,  // desc 1 uuid
2204       0x02,
2205       0x00,  // desc 2 handle
2206       0xFB,
2207       0x34,
2208       0x9B,
2209       0x5F,
2210       0x80,
2211       0x00,
2212       0x00,
2213       0x80,
2214       0x00,
2215       0x10,
2216       0x00,
2217       0x00,
2218       0xAD,
2219       0xDE,
2220       0x00,
2221       0x00  // desc 2 uuid
2222   );
2223 
2224   std::vector<DescriptorData> descrs;
2225   auto desc_cb = [&descrs](const DescriptorData& desc) {
2226     descrs.push_back(desc);
2227   };
2228   att::Result<> status = ToResult(HostError::kFailed);
2229   att()->set_mtu(512);
2230 
2231   EXPECT_PACKET_OUT(MakeFindInformation(kStart, kEnd), &kResponse);
2232   SendDiscoverDescriptors(&status, std::move(desc_cb), kStart, kEnd);
2233   RunUntilIdle();
2234   EXPECT_EQ(fit::ok(), status);
2235   ASSERT_EQ(2u, descrs.size());
2236   EXPECT_EQ(0x0001, descrs[0].handle);
2237   EXPECT_EQ(0x0002, descrs[1].handle);
2238   EXPECT_EQ(uint16_t{0xBEEF}, descrs[0].type);
2239   EXPECT_EQ(uint16_t{0xDEAD}, descrs[1].type);
2240 }
2241 
TEST_F(ClientTest,DescriptorDiscoveryMultipleRequests)2242 TEST_F(ClientTest, DescriptorDiscoveryMultipleRequests) {
2243   constexpr att::Handle kEnd = 0x0005;
2244   constexpr att::Handle kStart0 = 0x0001;
2245   const StaticByteBuffer kRequest0 = MakeFindInformation(kStart0, kEnd);
2246   const StaticByteBuffer kResponse0(
2247       att::kFindInformationResponse,  // opcode: find information response
2248       0x01,                           // format: 16-bit. Data length must be 4
2249       0x01,
2250       0x00,  // desc 1 handle
2251       0xEF,
2252       0xBE,  // desc 1 uuid
2253       0x02,
2254       0x00,  // desc 2 handle
2255       0xAD,
2256       0xDE  // desc 2 uuid
2257   );
2258   constexpr att::Handle kStart1 = 0x0003;
2259   const StaticByteBuffer kRequest1 = MakeFindInformation(kStart1, kEnd);
2260   const StaticByteBuffer kResponse1(
2261       att::kFindInformationResponse,  // opcode: find information response
2262       0x02,                           // format: 128-bit. Data length must be 18
2263       0x03,
2264       0x00,  // desc 3 handle
2265       0xFB,
2266       0x34,
2267       0x9B,
2268       0x5F,
2269       0x80,
2270       0x00,
2271       0x00,
2272       0x80,
2273       0x00,
2274       0x10,
2275       0x00,
2276       0x00,
2277       0xFE,
2278       0xFE,
2279       0x00,
2280       0x00  // desc 3 uuid
2281   );
2282   constexpr att::Handle kStart2 = 0x0004;
2283   const StaticByteBuffer kRequest2 = MakeFindInformation(kStart2, kEnd);
2284   const StaticByteBuffer kResponse2(
2285       att::kErrorResponse,           // response opcode
2286       att::kFindInformationRequest,  // request opcode that generated error
2287       0x04,
2288       0x00,  // handle: kStart2
2289       0x0A   // error: Attribute Not Found
2290   );
2291 
2292   std::vector<DescriptorData> descrs;
2293   auto desc_cb = [&descrs](const DescriptorData& desc) {
2294     descrs.push_back(desc);
2295   };
2296   att::Result<> status = ToResult(HostError::kFailed);
2297 
2298   EXPECT_PACKET_OUT(kRequest0, &kResponse0);
2299   EXPECT_PACKET_OUT(kRequest1, &kResponse1);
2300   EXPECT_PACKET_OUT(kRequest2, &kResponse2);
2301   SendDiscoverDescriptors(&status, std::move(desc_cb), kStart0, kEnd);
2302   RunUntilIdle();
2303   EXPECT_TRUE(AllExpectedPacketsSent());
2304   EXPECT_EQ(fit::ok(), status);
2305   ASSERT_EQ(3u, descrs.size());
2306   EXPECT_EQ(0x0001, descrs[0].handle);
2307   EXPECT_EQ(0x0002, descrs[1].handle);
2308   EXPECT_EQ(0x0003, descrs[2].handle);
2309   EXPECT_EQ(uint16_t{0xBEEF}, descrs[0].type);
2310   EXPECT_EQ(uint16_t{0xDEAD}, descrs[1].type);
2311   EXPECT_EQ(uint16_t{0xFEFE}, descrs[2].type);
2312 }
2313 
TEST_F(ClientTest,DescriptorDiscoveryResultsBeforeRange)2314 TEST_F(ClientTest, DescriptorDiscoveryResultsBeforeRange) {
2315   constexpr att::Handle kStart = 0x0002;
2316   const StaticByteBuffer kResponse(0x05,  // opcode: find information response
2317                                    0x01,  // format: 16-bit.
2318                                    0x01,
2319                                    0x00,  // handle is before kStart
2320                                    0xEF,
2321                                    0xBE  // uuid
2322   );
2323   att::Result<> status = fit::ok();
2324   EXPECT_PACKET_OUT(MakeFindInformation(kStart), &kResponse);
2325   SendDiscoverDescriptors(&status, NopDescCallback, kStart);
2326   RunUntilIdle();
2327   EXPECT_EQ(ToResult(HostError::kPacketMalformed), status);
2328 }
2329 
TEST_F(ClientTest,DescriptorDiscoveryResultsBeyondRange)2330 TEST_F(ClientTest, DescriptorDiscoveryResultsBeyondRange) {
2331   constexpr att::Handle kStart = 0x0001;
2332   constexpr att::Handle kEnd = 0x0002;
2333   const StaticByteBuffer kResponse(0x05,  // opcode: find information response
2334                                    0x01,  // format: 16-bit.
2335                                    0x03,
2336                                    0x00,  // handle is beyond kEnd
2337                                    0xEF,
2338                                    0xBE  // uuid
2339   );
2340   att::Result<> status = fit::ok();
2341   EXPECT_PACKET_OUT(MakeFindInformation(kStart, kEnd), &kResponse);
2342   SendDiscoverDescriptors(&status, NopDescCallback, kStart, kEnd);
2343   RunUntilIdle();
2344   EXPECT_EQ(ToResult(HostError::kPacketMalformed), status);
2345 }
2346 
TEST_F(ClientTest,DescriptorDiscoveryHandlesNotIncreasing)2347 TEST_F(ClientTest, DescriptorDiscoveryHandlesNotIncreasing) {
2348   att::Result<> status = fit::ok();
2349   const StaticByteBuffer kResponse(0x05,  // opcode: find information response
2350                                    0x01,  // format: 16-bit.
2351                                    0x01,
2352                                    0x00,  // handle: 0x0001
2353                                    0xEF,
2354                                    0xBE,  // uuid
2355                                    0x01,
2356                                    0x00,  // handle: 0x0001 (repeats)
2357                                    0xAD,
2358                                    0xDE  // uuid
2359   );
2360   EXPECT_PACKET_OUT(MakeFindInformation(), &kResponse);
2361   SendDiscoverDescriptors(&status, NopDescCallback);
2362   RunUntilIdle();
2363   EXPECT_EQ(ToResult(HostError::kPacketMalformed), status);
2364 }
2365 
TEST_F(ClientTest,WriteRequestMalformedResponse)2366 TEST_F(ClientTest, WriteRequestMalformedResponse) {
2367   const StaticByteBuffer kValue('f', 'o', 'o');
2368   const auto kHandle = 0x0001;
2369   const StaticByteBuffer kExpectedRequest(0x12,  // opcode: write request
2370                                           0x01,
2371                                           0x00,  // handle: 0x0001
2372                                           'f',
2373                                           'o',
2374                                           'o'  // value: "foo"
2375   );
2376   // Respond back with a malformed PDU. This should result in a link error.
2377   const StaticByteBuffer kResponse(
2378       0x013,  // opcode: write response
2379       0       // One byte payload. The write request has no parameters.
2380   );
2381 
2382   att::Result<> status = fit::ok();
2383   auto cb = [&status](att::Result<> cb_status) { status = cb_status; };
2384 
2385   ASSERT_FALSE(fake_chan()->link_error());
2386   EXPECT_PACKET_OUT(kExpectedRequest, &kResponse);
2387   client()->WriteRequest(kHandle, kValue, cb);
2388   RunUntilIdle();
2389   EXPECT_EQ(ToResult(HostError::kPacketMalformed), status);
2390   EXPECT_TRUE(fake_chan()->link_error());
2391 }
2392 
TEST_F(ClientTest,WriteRequestExceedsMtu)2393 TEST_F(ClientTest, WriteRequestExceedsMtu) {
2394   const StaticByteBuffer kValue('f', 'o', 'o');
2395   constexpr att::Handle kHandle = 0x0001;
2396   constexpr size_t kMtu = 5;
2397   const StaticByteBuffer kExpectedRequest(0x12,  // opcode: write request
2398                                           0x01,
2399                                           0x00,  // handle: 0x0001
2400                                           'f',
2401                                           'o',
2402                                           'o'  // value: "foo"
2403   );
2404   ASSERT_EQ(kMtu + 1, kExpectedRequest.size());
2405 
2406   att()->set_mtu(kMtu);
2407 
2408   att::Result<> status = fit::ok();
2409   auto cb = [&status](att::Result<> cb_status) { status = cb_status; };
2410 
2411   client()->WriteRequest(kHandle, kValue, cb);
2412 
2413   RunUntilIdle();
2414 
2415   EXPECT_EQ(ToResult(HostError::kPacketMalformed), status);
2416 }
2417 
TEST_F(ClientTest,WriteRequestError)2418 TEST_F(ClientTest, WriteRequestError) {
2419   const StaticByteBuffer kValue('f', 'o', 'o');
2420   const auto kHandle = 0x0001;
2421   const StaticByteBuffer kExpectedRequest(0x12,  // opcode: write request
2422                                           0x01,
2423                                           0x00,  // handle: 0x0001
2424                                           'f',
2425                                           'o',
2426                                           'o'  // value: "foo"
2427   );
2428   const StaticByteBuffer kResponse(0x01,  // opcode: error response
2429                                    0x12,  // request: write request
2430                                    0x01,
2431                                    0x00,  // handle: 0x0001
2432                                    0x06   // error: Request Not Supported
2433   );
2434 
2435   att::Result<> status = fit::ok();
2436   auto cb = [&status](att::Result<> cb_status) { status = cb_status; };
2437 
2438   EXPECT_PACKET_OUT(kExpectedRequest, &kResponse);
2439   client()->WriteRequest(kHandle, kValue, cb);
2440   RunUntilIdle();
2441   EXPECT_EQ(ToResult(att::ErrorCode::kRequestNotSupported), status);
2442   EXPECT_FALSE(fake_chan()->link_error());
2443 }
2444 
TEST_F(ClientTest,WriteRequestSuccess)2445 TEST_F(ClientTest, WriteRequestSuccess) {
2446   const StaticByteBuffer kValue('f', 'o', 'o');
2447   const auto kHandle = 0x0001;
2448   const StaticByteBuffer kExpectedRequest(0x12,  // opcode: write request
2449                                           0x01,
2450                                           0x00,  // handle: 0x0001
2451                                           'f',
2452                                           'o',
2453                                           'o'  // value: "foo"
2454   );
2455   const StaticByteBuffer kResponse(0x13  // opcode: write response
2456   );
2457   att::Result<> status = fit::ok();
2458   auto cb = [&status](att::Result<> cb_status) { status = cb_status; };
2459   EXPECT_PACKET_OUT(kExpectedRequest, &kResponse);
2460   client()->WriteRequest(kHandle, kValue, cb);
2461   RunUntilIdle();
2462   EXPECT_EQ(fit::ok(), status);
2463   EXPECT_FALSE(fake_chan()->link_error());
2464 }
2465 
TEST_F(ClientTest,PrepareWriteRequestExceedsMtu)2466 TEST_F(ClientTest, PrepareWriteRequestExceedsMtu) {
2467   const StaticByteBuffer kValue('f', 'o', 'o');
2468   constexpr att::Handle kHandle = 0x0001;
2469   constexpr auto kOffset = 0;
2470   constexpr size_t kMtu = 7;
2471   const StaticByteBuffer kExpectedRequest(
2472       0x16,  // opcode: prepare write request
2473       0x01,
2474       0x00,  // handle: 0x0001
2475       0x00,
2476       0x00,  // offset: 0x0000
2477       'f',
2478       'o',
2479       'o'  // value: "foo"
2480   );
2481   ASSERT_EQ(kMtu + 1, kExpectedRequest.size());
2482 
2483   att()->set_mtu(kMtu);
2484 
2485   att::Result<> status = fit::ok();
2486   auto cb = [&status](att::Result<> cb_status, const ByteBuffer&) {
2487     status = cb_status;
2488   };
2489 
2490   client()->PrepareWriteRequest(kHandle, kOffset, kValue, cb);
2491 
2492   RunUntilIdle();
2493 
2494   EXPECT_EQ(ToResult(HostError::kPacketMalformed), status);
2495 }
2496 
TEST_F(ClientTest,PrepareWriteRequestError)2497 TEST_F(ClientTest, PrepareWriteRequestError) {
2498   const StaticByteBuffer kValue('f', 'o', 'o');
2499   const auto kHandle = 0x0001;
2500   const auto kOffset = 5;
2501   const StaticByteBuffer kExpectedRequest(
2502       0x16,  // opcode: prepare write request
2503       0x01,
2504       0x00,  // handle: 0x0001
2505       0x05,
2506       0x00,  // offset: 0x0005
2507       'f',
2508       'o',
2509       'o'  // value: "foo"
2510   );
2511   const StaticByteBuffer kResponse(0x01,  // opcode: error response
2512                                    0x16,  // request: prepare write request
2513                                    0x01,
2514                                    0x00,  // handle: 0x0001
2515                                    0x06   // error: Request Not Supported
2516   );
2517   std::optional<att::Result<>> status;
2518   auto cb = [&status](att::Result<> cb_status, const ByteBuffer&) {
2519     status = cb_status;
2520   };
2521   EXPECT_PACKET_OUT(kExpectedRequest, &kResponse);
2522   client()->PrepareWriteRequest(kHandle, kOffset, kValue, cb);
2523   RunUntilIdle();
2524   ASSERT_TRUE(status.has_value());
2525   EXPECT_EQ(ToResult(att::ErrorCode::kRequestNotSupported), status.value());
2526   EXPECT_FALSE(fake_chan()->link_error());
2527 }
2528 
TEST_F(ClientTest,PrepareWriteRequestSuccess)2529 TEST_F(ClientTest, PrepareWriteRequestSuccess) {
2530   const StaticByteBuffer kValue('f', 'o', 'o');
2531   const auto kHandle = 0x0001;
2532   const auto kOffset = 0;
2533   const StaticByteBuffer kExpectedRequest(
2534       0x16,  // opcode: prepare write request
2535       0x01,
2536       0x00,  // handle: 0x0001
2537       0x00,
2538       0x00,  // offset: 0x0000
2539       'f',
2540       'o',
2541       'o'  // value: "foo"
2542   );
2543   const StaticByteBuffer kResponse(0x17,  // opcode: prepare write response
2544                                    0x01,
2545                                    0x00,  // handle: 0x0001
2546                                    0x00,
2547                                    0x00,  // offset: 0x0000
2548                                    'f',
2549                                    'o',
2550                                    'o'  // value: "foo"
2551   );
2552   att::Result<> status = fit::ok();
2553   auto cb = [&status](att::Result<> cb_status, const ByteBuffer&) {
2554     status = cb_status;
2555   };
2556   EXPECT_PACKET_OUT(kExpectedRequest, &kResponse);
2557   client()->PrepareWriteRequest(kHandle, kOffset, kValue, cb);
2558   RunUntilIdle();
2559   EXPECT_EQ(fit::ok(), status);
2560   EXPECT_FALSE(fake_chan()->link_error());
2561 }
2562 
TEST_F(ClientTest,ExecuteWriteRequestPendingSuccess)2563 TEST_F(ClientTest, ExecuteWriteRequestPendingSuccess) {
2564   const auto kFlag = att::ExecuteWriteFlag::kWritePending;
2565   const StaticByteBuffer kExpectedRequest(
2566       0x18,  // opcode: execute write request
2567       0x01   // flag: write pending
2568   );
2569   const StaticByteBuffer kResponse(0x19);  // opcode: execute write response
2570   att::Result<> status = fit::ok();
2571   auto cb = [&status](att::Result<> cb_status) { status = cb_status; };
2572   EXPECT_PACKET_OUT(kExpectedRequest, &kResponse);
2573   client()->ExecuteWriteRequest(kFlag, cb);
2574   RunUntilIdle();
2575   EXPECT_EQ(fit::ok(), status);
2576   EXPECT_FALSE(fake_chan()->link_error());
2577 }
2578 
TEST_F(ClientTest,ExecuteWriteRequestCancelSuccess)2579 TEST_F(ClientTest, ExecuteWriteRequestCancelSuccess) {
2580   const auto kFlag = att::ExecuteWriteFlag::kCancelAll;
2581   const StaticByteBuffer kExpectedRequest(
2582       0x18,  // opcode: execute write request
2583       0x00   // flag: cancel all
2584   );
2585   const StaticByteBuffer kResponse(0x19);  // opcode: execute write response
2586   att::Result<> status = fit::ok();
2587   auto cb = [&status](att::Result<> cb_status) { status = cb_status; };
2588   EXPECT_PACKET_OUT(kExpectedRequest, &kResponse);
2589   client()->ExecuteWriteRequest(kFlag, cb);
2590   RunUntilIdle();
2591   EXPECT_EQ(fit::ok(), status);
2592   EXPECT_FALSE(fake_chan()->link_error());
2593 }
2594 
2595 // ExecutePrepareWrites should send each QueuedWrite request in the
2596 // PrepareWriteQueue as a PrepareWriteRequest then finally send an ExecuteWrite.
TEST_F(ClientTest,ExecutePrepareWritesSuccess)2597 TEST_F(ClientTest, ExecutePrepareWritesSuccess) {
2598   const auto kHandle = 0x0001;
2599   const auto kOffset = 0;
2600   const StaticByteBuffer kValue1('f', 'o', 'o');
2601   const StaticByteBuffer kValue2('b', 'a', 'r');
2602 
2603   const StaticByteBuffer kExpectedPrep1(0x16,  // opcode: prepare write request
2604                                         0x01,
2605                                         0x00,  // handle: 0x0001
2606                                         0x00,
2607                                         0x00,  // offset: 0x0000
2608                                         'f',
2609                                         'o',
2610                                         'o'  // value: "foo"
2611   );
2612   const auto kResponse1 =
2613       StaticByteBuffer(0x17,  // opcode: prepare write response
2614                        0x01,
2615                        0x00,  // handle: 0x0001
2616                        0x00,
2617                        0x00,  // offset: 0x0000
2618                        'f',
2619                        'o',
2620                        'o'  // value: "foo"
2621       );
2622   const StaticByteBuffer kExpectedPrep2(0x16,  // opcode: prepare write request
2623                                         0x01,
2624                                         0x00,  // handle: 0x0001
2625                                         0x03,
2626                                         0x00,  // offset: 0x0003
2627                                         'b',
2628                                         'a',
2629                                         'r'  // value: "bar"
2630   );
2631   const auto kResponse2 =
2632       StaticByteBuffer(0x17,  // opcode: prepare write response
2633                        0x01,
2634                        0x00,  // handle: 0x0001
2635                        0x03,
2636                        0x00,  // offset: 0x0003
2637                        'b',
2638                        'a',
2639                        'r'  // value: "bar"
2640       );
2641   const StaticByteBuffer kExpectedExec(0x18,  // opcode: execute write request
2642                                        0x01   // flag: write pending
2643   );
2644   const StaticByteBuffer kExecResponse(0x19);  // opcode: execute write response
2645 
2646   att::Result<> status = fit::ok();
2647   auto cb = [&status](att::Result<> cb_status) { status = cb_status; };
2648 
2649   att::PrepareWriteQueue prep_write_queue;
2650   prep_write_queue.push(att::QueuedWrite(kHandle, kOffset, kValue1));
2651   prep_write_queue.push(att::QueuedWrite(
2652       kHandle, static_cast<uint16_t>(kOffset + kValue1.size()), kValue2));
2653 
2654   EXPECT_PACKET_OUT(kExpectedPrep1, &kResponse1);
2655   EXPECT_PACKET_OUT(kExpectedPrep2, &kResponse2);
2656   EXPECT_PACKET_OUT(kExpectedExec, &kExecResponse);
2657   client()->ExecutePrepareWrites(
2658       std::move(prep_write_queue), ReliableMode::kDisabled, cb);
2659   RunUntilIdle();
2660   EXPECT_TRUE(AllExpectedPacketsSent());
2661   EXPECT_EQ(fit::ok(), status);
2662   EXPECT_FALSE(fake_chan()->link_error());
2663 }
2664 
2665 // When the PreparedWrite request exceeds the mtu, the client should
2666 // automatically send a kCancellAll request.
TEST_F(ClientTest,ExecutePrepareWritesMalformedFailure)2667 TEST_F(ClientTest, ExecutePrepareWritesMalformedFailure) {
2668   const auto kHandle = 0x0001;
2669   const auto kOffset = 0;
2670   constexpr size_t kMtu = 7;
2671   const StaticByteBuffer kValue1('f', 'o');
2672   const StaticByteBuffer kValue2('b', 'a', 'r');
2673 
2674   const StaticByteBuffer kExpectedPrep1(0x16,  // opcode: prepare write request
2675                                         0x01,
2676                                         0x00,  // handle: 0x0001
2677                                         0x00,
2678                                         0x00,  // offset: 0x0000
2679                                         'f',
2680                                         'o'  // value: "fo"
2681   );
2682   const auto kResponse1 =
2683       StaticByteBuffer(0x17,  // opcode: prepare write response
2684                        0x01,
2685                        0x00,  // handle: 0x0001
2686                        0x00,
2687                        0x00,  // offset: 0x0000
2688                        'f',
2689                        'o'  // value: "fo"
2690       );
2691   // The second request is malformed, the client should send an ExecuteWrite
2692   // instead of the malformed PrepareWrite.
2693   const StaticByteBuffer kExpectedPrep2(0x16,  // opcode: prepare write request
2694                                         0x01,
2695                                         0x00,  // handle: 0x0001
2696                                         0x02,
2697                                         0x00,  // offset: 0x0002
2698                                         'b',
2699                                         'a',
2700                                         'r'  // value: "bar"
2701   );
2702   const StaticByteBuffer kExpectedExec(0x18,  // opcode: execute write request
2703                                        0x00   // flag: kCancelAll
2704   );
2705   const StaticByteBuffer kExecResponse(0x19);  // opcode: execute write response
2706 
2707   ASSERT_EQ(kMtu, kExpectedPrep1.size());
2708   ASSERT_EQ(kMtu + 1, kExpectedPrep2.size());
2709 
2710   att()->set_mtu(kMtu);
2711 
2712   att::Result<> status = fit::ok();
2713   auto cb = [&status](att::Result<> cb_status) { status = cb_status; };
2714 
2715   att::PrepareWriteQueue prep_write_queue;
2716   prep_write_queue.push(att::QueuedWrite(kHandle, kOffset, kValue1));
2717   prep_write_queue.push(att::QueuedWrite(
2718       kHandle, static_cast<uint16_t>(kOffset + kValue1.size()), kValue2));
2719 
2720   EXPECT_PACKET_OUT(kExpectedPrep1, &kResponse1);
2721   EXPECT_PACKET_OUT(kExpectedExec, &kExecResponse);
2722   client()->ExecutePrepareWrites(
2723       std::move(prep_write_queue), ReliableMode::kDisabled, cb);
2724   RunUntilIdle();
2725   EXPECT_EQ(ToResult(HostError::kPacketMalformed), status);
2726 }
2727 
2728 // When the PreparedWrite receives an error response, the client should
2729 // automatically send a kCancellAll request.
TEST_F(ClientTest,ExecutePrepareWritesErrorFailure)2730 TEST_F(ClientTest, ExecutePrepareWritesErrorFailure) {
2731   const auto kHandle = 0x0001;
2732   const auto kOffset = 0;
2733   const StaticByteBuffer kValue1('f', 'o', 'o');
2734   const StaticByteBuffer kValue2('b', 'a', 'r');
2735 
2736   const StaticByteBuffer kExpectedPrep1(0x16,  // opcode: prepare write request
2737                                         0x01,
2738                                         0x00,  // handle: 0x0001
2739                                         0x00,
2740                                         0x00,  // offset: 0x0000
2741                                         'f',
2742                                         'o',
2743                                         'o'  // value: "fo"
2744   );
2745   const auto kResponse1 =
2746       StaticByteBuffer(0x01,  // opcode: error response
2747                        0x16,  // request: prepare write request
2748                        0x01,
2749                        0x00,  // handle: 0x0001
2750                        0x06   // error: Request Not Supported
2751       );
2752   // The first request returned an error, the client should send an ExecuteWrite
2753   // instead of the second PrepareWrite.
2754   const StaticByteBuffer kExpectedExec(0x18,  // opcode: execute write request
2755                                        0x00   // flag: kCancelAll
2756   );
2757   const StaticByteBuffer kExecResponse(0x19);  // opcode: execute write response
2758 
2759   att::Result<> status = fit::ok();
2760   auto cb = [&status](att::Result<> cb_status) { status = cb_status; };
2761 
2762   // Create the PrepareWriteQueue of requests to pass to the client
2763   att::PrepareWriteQueue prep_write_queue;
2764   prep_write_queue.push(att::QueuedWrite(kHandle, kOffset, kValue1));
2765   prep_write_queue.push(att::QueuedWrite(
2766       kHandle, static_cast<uint16_t>(kOffset + kValue1.size()), kValue2));
2767 
2768   EXPECT_PACKET_OUT(kExpectedPrep1, &kResponse1);
2769   EXPECT_PACKET_OUT(kExpectedExec, &kExecResponse);
2770   client()->ExecutePrepareWrites(
2771       std::move(prep_write_queue), ReliableMode::kDisabled, cb);
2772   RunUntilIdle();
2773   EXPECT_EQ(ToResult(att::ErrorCode::kRequestNotSupported), status);
2774   EXPECT_FALSE(fake_chan()->link_error());
2775 }
2776 
2777 // ExecutePrepareWrites should enqueue immediately and send both long writes,
2778 // one after the other.
TEST_F(ClientTest,ExecutePrepareWritesEnqueueRequestSuccess)2779 TEST_F(ClientTest, ExecutePrepareWritesEnqueueRequestSuccess) {
2780   const auto kHandle1 = 0x0001;
2781   const auto kHandle2 = 0x0002;
2782   const auto kOffset = 0;
2783   const StaticByteBuffer kValue1('f', 'o', 'o');
2784   const StaticByteBuffer kValue2('b', 'a', 'r');
2785 
2786   const StaticByteBuffer kExpectedPrep1(0x16,  // opcode: prepare write request
2787                                         0x01,
2788                                         0x00,  // handle: 0x0001
2789                                         0x00,
2790                                         0x00,  // offset: 0x0000
2791                                         'f',
2792                                         'o',
2793                                         'o'  // value: "foo"
2794   );
2795   const auto kResponse1 =
2796       StaticByteBuffer(0x17,  // opcode: prepare write response
2797                        0x01,
2798                        0x00,  // handle: 0x0001
2799                        0x00,
2800                        0x00,  // offset: 0x0000
2801                        'f',
2802                        'o',
2803                        'o'  // value: "foo"
2804       );
2805   const StaticByteBuffer kExpectedPrep2(0x16,  // opcode: prepare write request
2806                                         0x01,
2807                                         0x00,  // handle: 0x0001
2808                                         0x03,
2809                                         0x00,  // offset: 0x0003
2810                                         'b',
2811                                         'a',
2812                                         'r'  // value: "bar"
2813   );
2814   const auto kResponse2 =
2815       StaticByteBuffer(0x17,  // opcode: prepare write response
2816                        0x01,
2817                        0x00,  // handle: 0x0001
2818                        0x03,
2819                        0x00,  // offset: 0x0003
2820                        'b',
2821                        'a',
2822                        'r'  // value: "bar"
2823       );
2824   // Start second write:
2825   const StaticByteBuffer kExpectedPrep3(0x16,  // opcode: prepare write request
2826                                         0x02,
2827                                         0x00,  // handle: 0x0002
2828                                         0x00,
2829                                         0x00,  // offset: 0x0000
2830                                         'f',
2831                                         'o',
2832                                         'o'  // value: "foo"
2833   );
2834   const auto kResponse3 =
2835       StaticByteBuffer(0x17,  // opcode: prepare write response
2836                        0x02,
2837                        0x00,  // handle: 0x0002
2838                        0x00,
2839                        0x00,  // offset: 0x0000
2840                        'f',
2841                        'o',
2842                        'o'  // value: "foo"
2843       );
2844   const StaticByteBuffer kExpectedPrep4(0x16,  // opcode: prepare write request
2845                                         0x02,
2846                                         0x00,  // handle: 0x0002
2847                                         0x03,
2848                                         0x00,  // offset: 0x0003
2849                                         'b',
2850                                         'a',
2851                                         'r'  // value: "bar"
2852   );
2853   const auto kResponse4 =
2854       StaticByteBuffer(0x17,  // opcode: prepare write response
2855                        0x02,
2856                        0x00,  // handle: 0x0002
2857                        0x03,
2858                        0x00,  // offset: 0x0003
2859                        'b',
2860                        'a',
2861                        'r'  // value: "bar"
2862       );
2863   const StaticByteBuffer kExpectedExec(0x18,  // opcode: execute write request
2864                                        0x01   // flag: write pending
2865   );
2866   const auto kExecuteWriteResponse =
2867       StaticByteBuffer(0x19);  // opcode: execute write response
2868 
2869   att::Result<> status1 = fit::ok();
2870   auto cb1 = [&status1](att::Result<> cb_status) { status1 = cb_status; };
2871   att::PrepareWriteQueue prep_write_queue1;
2872   prep_write_queue1.push(att::QueuedWrite(kHandle1, kOffset, kValue1));
2873   prep_write_queue1.push(att::QueuedWrite(
2874       kHandle1, static_cast<uint16_t>(kOffset + kValue1.size()), kValue2));
2875   EXPECT_PACKET_OUT(kExpectedPrep1, &kResponse1);
2876   client()->ExecutePrepareWrites(
2877       std::move(prep_write_queue1), ReliableMode::kDisabled, cb1);
2878   EXPECT_TRUE(AllExpectedPacketsSent());
2879 
2880   att::Result<> status2 = fit::ok();
2881   auto cb2 = [&status2](att::Result<> cb_status) { status2 = cb_status; };
2882   att::PrepareWriteQueue prep_write_queue2;
2883   prep_write_queue2.push(att::QueuedWrite(kHandle2, kOffset, kValue1));
2884   prep_write_queue2.push(att::QueuedWrite(
2885       kHandle2, static_cast<uint16_t>(kOffset + kValue1.size()), kValue2));
2886   client()->ExecutePrepareWrites(
2887       std::move(prep_write_queue2), ReliableMode::kDisabled, cb2);
2888 
2889   EXPECT_PACKET_OUT(kExpectedPrep2, &kResponse2);
2890   EXPECT_PACKET_OUT(
2891       kExpectedExec);  // Delay sending response so the status can be checked
2892   RunUntilIdle();
2893   EXPECT_TRUE(AllExpectedPacketsSent());
2894   // The first request should be fully complete now, and should trigger the
2895   // second.
2896   EXPECT_EQ(fit::ok(), status1);
2897 
2898   EXPECT_PACKET_OUT(kExpectedPrep3, &kResponse3);
2899   EXPECT_PACKET_OUT(kExpectedPrep4, &kResponse4);
2900   EXPECT_PACKET_OUT(kExpectedExec, &kExecuteWriteResponse);
2901   // Responding to the first execute request should start the second write
2902   // request.
2903   fake_chan()->Receive(kExecuteWriteResponse);
2904   RunUntilIdle();
2905   EXPECT_EQ(fit::ok(), status2);
2906   EXPECT_FALSE(fake_chan()->link_error());
2907 }
2908 
2909 // ExecutePrepareWrites should send each QueuedWrite request in the
2910 // PrepareWriteQueue as a PrepareWriteRequest and then send an ExecuteWrite.
2911 // Test that a WriteRequest succeeds if ReliableMode is disabled even when the
2912 // echoed response is different.
TEST_F(ClientTest,ExecutePrepareWritesDifferingResponseSuccess)2913 TEST_F(ClientTest, ExecutePrepareWritesDifferingResponseSuccess) {
2914   const auto kHandle = 0x0001;
2915   const auto kOffset = 0;
2916   const StaticByteBuffer kValue1('f', 'o', 'o');
2917   const StaticByteBuffer kValue2('b', 'a', 'r');
2918 
2919   const StaticByteBuffer kExpectedPrep1(0x16,  // opcode: prepare write request
2920                                         0x01,
2921                                         0x00,  // handle: 0x0001
2922                                         0x00,
2923                                         0x00,  // offset: 0x0000
2924                                         'f',
2925                                         'o',
2926                                         'o'  // value: "foo"
2927   );
2928   const auto kResponse1 =
2929       StaticByteBuffer(0x17,  // opcode: prepare write response
2930                        0x01,
2931                        0x00,  // handle: 0x0001
2932                        0x00,
2933                        0x00,  // offset: 0x0000
2934                        'f',
2935                        'l'  // value: "fl" -> different, but OK.
2936       );
2937   const StaticByteBuffer kExpectedPrep2(0x16,  // opcode: prepare write request
2938                                         0x01,
2939                                         0x00,  // handle: 0x0001
2940                                         0x03,
2941                                         0x00,  // offset: 0x0003
2942                                         'b',
2943                                         'a',
2944                                         'r'  // value: "bar"
2945   );
2946   const auto kResponse2 =
2947       StaticByteBuffer(0x17,  // opcode: prepare write response
2948                        0x01,
2949                        0x00,  // handle: 0x0001
2950                        0x03,
2951                        0x00,  // offset: 0x0003
2952                        'b',
2953                        'a',
2954                        'r'  // value: "bar"
2955       );
2956   const StaticByteBuffer kExpectedExec(0x18,  // opcode: execute write request
2957                                        0x01   // flag: write pending
2958   );
2959   const StaticByteBuffer kExecResponse(0x19);  // opcode: execute write response
2960 
2961   att::Result<> status = fit::ok();
2962   auto cb = [&status](att::Result<> cb_status) { status = cb_status; };
2963 
2964   // Create the PrepareWriteQueue of requests to pass to the client
2965   att::PrepareWriteQueue prep_write_queue;
2966   prep_write_queue.push(att::QueuedWrite(kHandle, kOffset, kValue1));
2967   prep_write_queue.push(att::QueuedWrite(
2968       kHandle, static_cast<uint16_t>(kOffset + kValue1.size()), kValue2));
2969 
2970   EXPECT_PACKET_OUT(kExpectedPrep1, &kResponse1);
2971   client()->ExecutePrepareWrites(
2972       std::move(prep_write_queue), ReliableMode::kDisabled, cb);
2973   EXPECT_PACKET_OUT(kExpectedPrep2, &kResponse2);
2974   EXPECT_PACKET_OUT(kExpectedExec, &kExecResponse);
2975   RunUntilIdle();
2976   EXPECT_EQ(fit::ok(), status);
2977   EXPECT_FALSE(fake_chan()->link_error());
2978 }
2979 
2980 // ExecutePrepareWrites should send each QueuedWrite request in the
2981 // PrepareWriteQueue as a PrepareWriteRequest, validate the responses,
2982 // then finally send an ExecuteWrite.
TEST_F(ClientTest,ExecutePrepareWritesReliableWriteSuccess)2983 TEST_F(ClientTest, ExecutePrepareWritesReliableWriteSuccess) {
2984   const auto kHandle = 0x0001;
2985   const auto kOffset = 0;
2986   const StaticByteBuffer kValue1('f', 'o', 'o');
2987   const StaticByteBuffer kValue2('b', 'a', 'r');
2988 
2989   const StaticByteBuffer kExpectedPrep1(0x16,  // opcode: prepare write request
2990                                         0x01,
2991                                         0x00,  // handle: 0x0001
2992                                         0x00,
2993                                         0x00,  // offset: 0x0000
2994                                         'f',
2995                                         'o',
2996                                         'o'  // value: "foo"
2997   );
2998   const auto kResponse1 =
2999       StaticByteBuffer(0x17,  // opcode: prepare write response
3000                        0x01,
3001                        0x00,  // handle: 0x0001
3002                        0x00,
3003                        0x00,  // offset: 0x0000
3004                        'f',
3005                        'o',
3006                        'o'  // value: "foo"
3007       );
3008   const StaticByteBuffer kExpectedPrep2(0x16,  // opcode: prepare write request
3009                                         0x01,
3010                                         0x00,  // handle: 0x0001
3011                                         0x03,
3012                                         0x00,  // offset: 0x0003
3013                                         'b',
3014                                         'a',
3015                                         'r'  // value: "bar"
3016   );
3017   const auto kResponse2 =
3018       StaticByteBuffer(0x17,  // opcode: prepare write response
3019                        0x01,
3020                        0x00,  // handle: 0x0001
3021                        0x03,
3022                        0x00,  // offset: 0x0003
3023                        'b',
3024                        'a',
3025                        'r'  // value: "bar"
3026       );
3027   const StaticByteBuffer kExpectedExec(0x18,  // opcode: execute write request
3028                                        0x01   // flag: write pending
3029   );
3030   const StaticByteBuffer kExecResponse(0x19);  // opcode: execute write response
3031 
3032   att::Result<> status = fit::ok();
3033   auto cb = [&status](att::Result<> cb_status) { status = cb_status; };
3034 
3035   // Create the PrepareWriteQueue of requests to pass to the client
3036   att::PrepareWriteQueue prep_write_queue;
3037   prep_write_queue.push(att::QueuedWrite(kHandle, kOffset, kValue1));
3038   prep_write_queue.push(att::QueuedWrite(
3039       kHandle, static_cast<uint16_t>(kOffset + kValue1.size()), kValue2));
3040 
3041   EXPECT_PACKET_OUT(kExpectedPrep1, &kResponse1);
3042   client()->ExecutePrepareWrites(
3043       std::move(prep_write_queue), ReliableMode::kEnabled, cb);
3044   EXPECT_PACKET_OUT(kExpectedPrep2, &kResponse2);
3045   EXPECT_PACKET_OUT(kExpectedExec, &kExecResponse);
3046   RunUntilIdle();
3047   EXPECT_EQ(fit::ok(), status);
3048   EXPECT_FALSE(fake_chan()->link_error());
3049 }
3050 
3051 // If ReliableMode is enabled:
3052 // When the requested buffer is empty, the reliability check should
3053 // succeed when vailidating the echoed response.
TEST_F(ClientTest,ExecutePrepareWritesReliableEmptyBufSuccess)3054 TEST_F(ClientTest, ExecutePrepareWritesReliableEmptyBufSuccess) {
3055   const auto kHandle = 0x0001;
3056   const auto kOffset = 0;
3057   const auto kValue1 = BufferView();
3058 
3059   const StaticByteBuffer kExpectedPrep1(0x16,  // opcode: prepare write request
3060                                         0x01,
3061                                         0x00,  // handle: 0x0001
3062                                         0x00,
3063                                         0x00  // offset: 0x0000
3064   );
3065   const auto kResponse1 =
3066       StaticByteBuffer(0x17,  // opcode: prepare write response
3067                        0x01,
3068                        0x00,  // handle: 0x0001
3069                        0x00,
3070                        0x00  // offset: 0x0000
3071       );
3072   const StaticByteBuffer kExpectedExec(0x18,  // opcode: execute write request
3073                                        0x01   // flag: write pending
3074   );
3075   const StaticByteBuffer kExecResponse(0x19);  // opcode: execute write response
3076 
3077   att::Result<> status = fit::ok();
3078   auto cb = [&status](att::Result<> cb_status) { status = cb_status; };
3079 
3080   att::PrepareWriteQueue prep_write_queue;
3081   prep_write_queue.push(att::QueuedWrite(kHandle, kOffset, kValue1));
3082 
3083   EXPECT_PACKET_OUT(kExpectedPrep1, &kResponse1);
3084   client()->ExecutePrepareWrites(
3085       std::move(prep_write_queue), ReliableMode::kEnabled, cb);
3086   EXPECT_PACKET_OUT(kExpectedExec, &kExecResponse);
3087   RunUntilIdle();
3088   EXPECT_EQ(fit::ok(), status);
3089   EXPECT_FALSE(fake_chan()->link_error());
3090 }
3091 
3092 // If ReliableMode is enabled:
3093 // When the PreparedWrite response differs from the PreparedWrite request,
3094 // the client should automatically send a kCancellAll request.
TEST_F(ClientTest,ExecutePrepareWritesReliableDifferingResponseError)3095 TEST_F(ClientTest, ExecutePrepareWritesReliableDifferingResponseError) {
3096   const auto kHandle = 0x0001;
3097   const auto kOffset = 0;
3098   const StaticByteBuffer kValue1('f', 'o', 'o');
3099   const StaticByteBuffer kValue2('b', 'a', 'r');
3100 
3101   const StaticByteBuffer kExpectedPrep1(0x16,  // opcode: prepare write request
3102                                         0x01,
3103                                         0x00,  // handle: 0x0001
3104                                         0x00,
3105                                         0x00,  // offset: 0x0000
3106                                         'f',
3107                                         'o',
3108                                         'o'  // value: "foo"
3109   );
3110   const auto kResponse1 =
3111       StaticByteBuffer(0x17,  // opcode: prepare write response
3112                        0x01,
3113                        0x00,  // handle: 0x0001
3114                        0x00,
3115                        0x00,  // offset: 0x0000
3116                        'f',
3117                        'o',
3118                        'b',
3119                        '1'  // value: "fob1" -> invalid
3120       );
3121   // The first response was invalid, the client should send an ExecuteWrite
3122   // instead of the second PrepareWrite.
3123   const StaticByteBuffer kExpectedExec(0x18,  // opcode: execute write request
3124                                        0x00   // flag: kCancelAll
3125   );
3126   const StaticByteBuffer kExecResponse(0x19);  // opcode: execute write response
3127 
3128   att::Result<> status = fit::ok();
3129   auto cb = [&status](att::Result<> cb_status) { status = cb_status; };
3130 
3131   att::PrepareWriteQueue prep_write_queue;
3132   prep_write_queue.push(att::QueuedWrite(kHandle, kOffset, kValue1));
3133   prep_write_queue.push(att::QueuedWrite(
3134       kHandle, static_cast<uint16_t>(kOffset + kValue1.size()), kValue2));
3135 
3136   EXPECT_PACKET_OUT(kExpectedPrep1, &kResponse1);
3137   client()->ExecutePrepareWrites(
3138       std::move(prep_write_queue), ReliableMode::kEnabled, cb);
3139   EXPECT_PACKET_OUT(kExpectedExec, &kExecResponse);
3140   RunUntilIdle();
3141   EXPECT_EQ(ToResult(HostError::kNotReliable), status);
3142   EXPECT_FALSE(fake_chan()->link_error());
3143 }
3144 
3145 // If ReliableMode is enabled:
3146 // When the PreparedWrite response is malformed, the client should
3147 // automatically send a kCancellAll request.
TEST_F(ClientTest,ExecutePrepareWritesReliableMalformedResponseError)3148 TEST_F(ClientTest, ExecutePrepareWritesReliableMalformedResponseError) {
3149   const auto kHandle = 0x0001;
3150   const auto kOffset = 0;
3151   const StaticByteBuffer kValue1('f', 'o', 'o');
3152   const StaticByteBuffer kValue2('b', 'a', 'r');
3153 
3154   const StaticByteBuffer kExpectedPrep1(0x16,  // opcode: prepare write request
3155                                         0x01,
3156                                         0x00,  // handle: 0x0001
3157                                         0x00,
3158                                         0x00,  // offset: 0x0000
3159                                         'f',
3160                                         'o',
3161                                         'o'  // value: "foo"
3162   );
3163   const auto kResponse1 =
3164       StaticByteBuffer(0x17,  // opcode: prepare write response
3165                        0x01,
3166                        0x00,  // handle: 0x0001
3167                        0x00   // offset: malformed
3168       );
3169   // The first response was malformed, the client should send an ExecuteWrite
3170   // instead of the second PrepareWrite.
3171   const StaticByteBuffer kExpectedExec(0x18,  // opcode: execute write request
3172                                        0x00   // flag: kCancelAll
3173   );
3174   const StaticByteBuffer kExecResponse(0x19);  // opcode: execute write response
3175 
3176   att::Result<> status = fit::ok();
3177   auto cb = [&status](att::Result<> cb_status) { status = cb_status; };
3178 
3179   att::PrepareWriteQueue prep_write_queue;
3180   prep_write_queue.push(att::QueuedWrite(kHandle, kOffset, kValue1));
3181   prep_write_queue.push(att::QueuedWrite(
3182       kHandle, static_cast<uint16_t>(kOffset + kValue1.size()), kValue2));
3183 
3184   EXPECT_PACKET_OUT(kExpectedPrep1, &kResponse1);
3185   client()->ExecutePrepareWrites(
3186       std::move(prep_write_queue), ReliableMode::kEnabled, cb);
3187   EXPECT_PACKET_OUT(kExpectedExec, &kExecResponse);
3188   RunUntilIdle();
3189   EXPECT_EQ(ToResult(HostError::kNotReliable), status);
3190   EXPECT_FALSE(fake_chan()->link_error());
3191 }
3192 
3193 // If ReliableMode is enabled:
3194 // When the PreparedWrite response contains an incorrect offset, but correct
3195 // value, the client should automatically send a kCancellAll request.
TEST_F(ClientTest,ExecutePrepareWritesReliableOffsetMismatchError)3196 TEST_F(ClientTest, ExecutePrepareWritesReliableOffsetMismatchError) {
3197   const auto kHandle = 0x0001;
3198   const auto kOffset = 0;
3199   const StaticByteBuffer kValue1('f', 'o', 'o');
3200 
3201   const StaticByteBuffer kExpectedPrep1(0x16,  // opcode: prepare write request
3202                                         0x01,
3203                                         0x00,  // handle: 0x0001
3204                                         0x00,
3205                                         0x00,  // offset: 0x0000
3206                                         'f',
3207                                         'o',
3208                                         'o'  // value: "foo"
3209   );
3210   const auto kResponse1 =
3211       StaticByteBuffer(0x17,  // opcode: prepare write response
3212                        0x01,
3213                        0x00,  // handle: 0x0001
3214                        0x01,
3215                        0x00,  // offset: incorrect
3216                        'f',
3217                        'o',
3218                        'o'  // value: 'foo'
3219       );
3220   // The first response was malformed, the client should send an ExecuteWrite
3221   // instead of the second PrepareWrite.
3222   const StaticByteBuffer kExpectedExec(0x18,  // opcode: execute write request
3223                                        0x00   // flag: kCancelAll
3224   );
3225   const StaticByteBuffer kExecResponse(0x19);  // opcode: execute write response
3226 
3227   att::Result<> status = fit::ok();
3228   auto cb = [&status](att::Result<> cb_status) { status = cb_status; };
3229 
3230   att::PrepareWriteQueue prep_write_queue;
3231   prep_write_queue.push(att::QueuedWrite(kHandle, kOffset, kValue1));
3232 
3233   EXPECT_PACKET_OUT(kExpectedPrep1, &kResponse1);
3234   client()->ExecutePrepareWrites(
3235       std::move(prep_write_queue), ReliableMode::kEnabled, cb);
3236   EXPECT_PACKET_OUT(kExpectedExec, &kExecResponse);
3237   RunUntilIdle();
3238   EXPECT_EQ(ToResult(HostError::kNotReliable), status);
3239   EXPECT_FALSE(fake_chan()->link_error());
3240 }
3241 
3242 // If ReliableMode is enabled:
3243 // When the PreparedWrite response contains an incorrect empty value,
3244 // the client should automatically send a kCancellAll request.
TEST_F(ClientTest,ExecutePrepareWritesReliableEmptyValueError)3245 TEST_F(ClientTest, ExecutePrepareWritesReliableEmptyValueError) {
3246   const auto kHandle = 0x0001;
3247   const auto kOffset = 0;
3248   const StaticByteBuffer kValue1('f', 'o', 'o');
3249 
3250   const StaticByteBuffer kExpectedPrep1(0x16,  // opcode: prepare write request
3251                                         0x01,
3252                                         0x00,  // handle: 0x0001
3253                                         0x00,
3254                                         0x00,  // offset: 0x0000
3255                                         'f',
3256                                         'o',
3257                                         'o'  // value: "foo"
3258   );
3259   const auto kResponse1 =
3260       StaticByteBuffer(0x17,  // opcode: prepare write response
3261                        0x01,
3262                        0x00,  // handle: 0x0001
3263                        0x00,
3264                        0x00  // offset: 0x0000
3265       );
3266   // The first response was malformed (empty value), the client should send an
3267   // ExecuteWrite instead of the second PrepareWrite.
3268   const StaticByteBuffer kExpectedExec(0x18,  // opcode: execute write request
3269                                        0x00   // flag: kCancelAll
3270   );
3271   const StaticByteBuffer kExecResponse(0x19);  // opcode: execute write response
3272 
3273   att::Result<> status = fit::ok();
3274   auto cb = [&status](att::Result<> cb_status) { status = cb_status; };
3275 
3276   att::PrepareWriteQueue prep_write_queue;
3277   prep_write_queue.push(att::QueuedWrite(kHandle, kOffset, kValue1));
3278 
3279   EXPECT_PACKET_OUT(kExpectedPrep1, &kResponse1);
3280   client()->ExecutePrepareWrites(
3281       std::move(prep_write_queue), ReliableMode::kEnabled, cb);
3282   EXPECT_PACKET_OUT(kExpectedExec, &kExecResponse);
3283   RunUntilIdle();
3284   EXPECT_EQ(ToResult(HostError::kNotReliable), status);
3285   EXPECT_FALSE(fake_chan()->link_error());
3286 }
3287 
TEST_F(ClientTest,WriteWithoutResponseExceedsMtu)3288 TEST_F(ClientTest, WriteWithoutResponseExceedsMtu) {
3289   const StaticByteBuffer kValue('f', 'o', 'o');
3290   constexpr att::Handle kHandle = 0x0001;
3291   constexpr size_t kMtu = 5;
3292   att()->set_mtu(kMtu);
3293   const StaticByteBuffer kExpectedRequest(0x52,  // opcode: write command
3294                                           0x01,
3295                                           0x00,  // handle: 0x0001
3296                                           'f',
3297                                           'o',
3298                                           'o'  // value: "foo"
3299   );
3300   ASSERT_EQ(kMtu + 1, kExpectedRequest.size());
3301 
3302   std::optional<att::Result<>> status;
3303   // No packet should be sent.
3304   client()->WriteWithoutResponse(
3305       kHandle, kValue, [&](att::Result<> cb_status) { status = cb_status; });
3306   RunUntilIdle();
3307   ASSERT_TRUE(status.has_value());
3308   EXPECT_EQ(ToResult(HostError::kFailed), *status);
3309 }
3310 
TEST_F(ClientTest,WriteWithoutResponseSuccess)3311 TEST_F(ClientTest, WriteWithoutResponseSuccess) {
3312   const StaticByteBuffer kValue('f', 'o', 'o');
3313   const auto kHandle = 0x0001;
3314   const StaticByteBuffer kExpectedRequest(0x52,  // opcode: write request
3315                                           0x01,
3316                                           0x00,  // handle: 0x0001
3317                                           'f',
3318                                           'o',
3319                                           'o'  // value: "foo"
3320   );
3321   std::optional<att::Result<>> status;
3322   EXPECT_PACKET_OUT(kExpectedRequest);
3323   client()->WriteWithoutResponse(
3324       kHandle, kValue, [&](att::Result<> cb_status) { status = cb_status; });
3325   ASSERT_TRUE(status.has_value());
3326   ASSERT_EQ(fit::ok(), *status);
3327 }
3328 
TEST_F(ClientTest,ReadRequestEmptyResponse)3329 TEST_F(ClientTest, ReadRequestEmptyResponse) {
3330   constexpr att::Handle kHandle = 0x0001;
3331   const StaticByteBuffer kExpectedRequest(0x0A,  // opcode: read request
3332                                           0x01,
3333                                           0x00  // handle: 0x0001
3334   );
3335   // ATT Read Response with no payload.
3336   const StaticByteBuffer kResponse(0x0B);
3337 
3338   att::Result<> status = ToResult(HostError::kFailed);
3339   auto cb = [&status](att::Result<> cb_status,
3340                       const ByteBuffer& value,
3341                       bool maybe_truncated) {
3342     status = cb_status;
3343 
3344     // We expect an empty value
3345     EXPECT_EQ(0u, value.size());
3346     EXPECT_FALSE(maybe_truncated);
3347   };
3348 
3349   EXPECT_PACKET_OUT(kExpectedRequest, &kResponse);
3350   client()->ReadRequest(kHandle, cb);
3351   RunUntilIdle();
3352   EXPECT_EQ(fit::ok(), status);
3353   EXPECT_FALSE(fake_chan()->link_error());
3354 }
3355 
TEST_F(ClientTest,ReadRequestSuccess)3356 TEST_F(ClientTest, ReadRequestSuccess) {
3357   constexpr att::Handle kHandle = 0x0001;
3358   const StaticByteBuffer kExpectedRequest(0x0A,  // opcode: read request
3359                                           0x01,
3360                                           0x00  // handle: 0x0001
3361   );
3362 
3363   const StaticByteBuffer kExpectedResponse(0x0B,  // opcode: read response
3364                                            't',
3365                                            'e',
3366                                            's',
3367                                            't'  // value: "test"
3368   );
3369 
3370   att::Result<> status = ToResult(HostError::kFailed);
3371   auto cb = [&](att::Result<> cb_status,
3372                 const ByteBuffer& value,
3373                 bool maybe_truncated) {
3374     status = cb_status;
3375     EXPECT_TRUE(ContainersEqual(kExpectedResponse.view(1), value));
3376     EXPECT_FALSE(maybe_truncated);
3377   };
3378 
3379   EXPECT_PACKET_OUT(kExpectedRequest, &kExpectedResponse);
3380   client()->ReadRequest(kHandle, cb);
3381   RunUntilIdle();
3382   EXPECT_EQ(fit::ok(), status);
3383   EXPECT_FALSE(fake_chan()->link_error());
3384 }
3385 
TEST_F(ClientTest,ReadRequestSuccessMaybeTruncatedDueToMtu)3386 TEST_F(ClientTest, ReadRequestSuccessMaybeTruncatedDueToMtu) {
3387   constexpr att::Handle kHandle = 0x0001;
3388   const auto kExpectedRequest = StaticByteBuffer(0x0A,  // opcode: read request
3389                                                  LowerBits(kHandle),
3390                                                  UpperBits(kHandle)  // handle
3391   );
3392 
3393   DynamicByteBuffer expected_response(att()->mtu());
3394   expected_response.Fill(0);
3395   expected_response.WriteObj(att::kReadResponse);  // opcode: read response
3396 
3397   att::Result<> status = ToResult(HostError::kFailed);
3398   auto cb = [&](att::Result<> cb_status,
3399                 const ByteBuffer& value,
3400                 bool maybe_truncated) {
3401     status = cb_status;
3402     EXPECT_TRUE(ContainersEqual(expected_response.view(1), value));
3403     EXPECT_TRUE(maybe_truncated);
3404   };
3405 
3406   EXPECT_PACKET_OUT(kExpectedRequest, &expected_response);
3407   client()->ReadRequest(kHandle, cb);
3408   RunUntilIdle();
3409   EXPECT_EQ(fit::ok(), status);
3410   EXPECT_FALSE(fake_chan()->link_error());
3411 }
3412 
TEST_F(ClientTest,ReadRequestSuccessNotTruncatedWhenMtuAllowsMaxValueLength)3413 TEST_F(ClientTest, ReadRequestSuccessNotTruncatedWhenMtuAllowsMaxValueLength) {
3414   constexpr uint16_t kPreferredMTU =
3415       att::kMaxAttributeValueLength + sizeof(att::OpCode);
3416   att()->set_preferred_mtu(kPreferredMTU);
3417   constexpr uint16_t kServerRxMTU = kPreferredMTU;
3418 
3419   const auto kExpectedMtuRequest =
3420       StaticByteBuffer(0x02,  // opcode: exchange MTU
3421                        LowerBits(kPreferredMTU),
3422                        UpperBits(kPreferredMTU)  // client rx mtu
3423       );
3424 
3425   std::optional<att::Result<uint16_t>> result;
3426   auto mtu_cb = [&](att::Result<uint16_t> cb_result) { result = cb_result; };
3427 
3428   EXPECT_PACKET_OUT(kExpectedMtuRequest);
3429   client()->ExchangeMTU(mtu_cb);
3430   ASSERT_EQ(att::kLEMinMTU, att()->mtu());
3431   fake_chan()->Receive(StaticByteBuffer(
3432       0x03,  // opcode: exchange MTU response
3433       LowerBits(kServerRxMTU),
3434       UpperBits(kServerRxMTU)  // server rx mtu
3435       ));
3436   RunUntilIdle();
3437   ASSERT_TRUE(result.has_value());
3438   EXPECT_EQ(att::Result<uint16_t>(fit::ok(kPreferredMTU)), *result);
3439   EXPECT_EQ(kPreferredMTU, att()->mtu());
3440 
3441   constexpr att::Handle kHandle = 0x0001;
3442   const auto kExpectedReadRequest =
3443       StaticByteBuffer(0x0A,  // opcode: read request
3444                        LowerBits(kHandle),
3445                        UpperBits(kHandle)  // handle
3446       );
3447 
3448   DynamicByteBuffer expected_response(att()->mtu());
3449   expected_response.Fill(0);
3450   expected_response.WriteObj(att::kReadResponse);  // opcode: read response
3451 
3452   att::Result<> status = ToResult(HostError::kFailed);
3453   auto cb = [&](att::Result<> cb_status,
3454                 const ByteBuffer& value,
3455                 bool maybe_truncated) {
3456     status = cb_status;
3457     EXPECT_TRUE(ContainersEqual(expected_response.view(1), value));
3458     EXPECT_FALSE(maybe_truncated);
3459   };
3460 
3461   EXPECT_PACKET_OUT(kExpectedReadRequest, &expected_response);
3462   client()->ReadRequest(kHandle, cb);
3463   RunUntilIdle();
3464   EXPECT_EQ(fit::ok(), status);
3465   EXPECT_FALSE(fake_chan()->link_error());
3466 }
3467 
TEST_F(ClientTest,ReadRequestError)3468 TEST_F(ClientTest, ReadRequestError) {
3469   constexpr att::Handle kHandle = 0x0001;
3470   const StaticByteBuffer kExpectedRequest(0x0A,  // opcode: read request
3471                                           0x01,
3472                                           0x00  // handle: 0x0001
3473   );
3474   const StaticByteBuffer kErrorResponse(0x01,  // opcode: error response
3475                                         0x0A,  // request: read request
3476                                         0x01,
3477                                         0x00,  // handle: 0x0001
3478                                         0x06   // error: Request Not Supported
3479   );
3480 
3481   att::Result<> status = fit::ok();
3482   auto cb = [&](att::Result<> cb_status,
3483                 const ByteBuffer& value,
3484                 bool maybe_truncated) {
3485     status = cb_status;
3486 
3487     // Value should be empty due to the error.
3488     EXPECT_EQ(0u, value.size());
3489     EXPECT_FALSE(maybe_truncated);
3490   };
3491 
3492   EXPECT_PACKET_OUT(kExpectedRequest, &kErrorResponse);
3493   client()->ReadRequest(kHandle, cb);
3494   RunUntilIdle();
3495   EXPECT_EQ(ToResult(att::ErrorCode::kRequestNotSupported), status);
3496   EXPECT_FALSE(fake_chan()->link_error());
3497 }
3498 
TEST_F(ClientTest,ReadByTypeRequestSuccess16BitUUID)3499 TEST_F(ClientTest, ReadByTypeRequestSuccess16BitUUID) {
3500   const UUID kUuid16(uint16_t{0xBEEF});
3501   constexpr att::Handle kStartHandle = 0x0001;
3502   constexpr att::Handle kEndHandle = 0xFFFF;
3503   const auto kExpectedRequest =
3504       StaticByteBuffer(att::kReadByTypeRequest,  // opcode
3505                        LowerBits(kStartHandle),
3506                        UpperBits(kStartHandle),  // start handle
3507                        LowerBits(kEndHandle),
3508                        UpperBits(kEndHandle),  // end handle
3509                        // UUID
3510                        0xEF,
3511                        0xBE);
3512 
3513   constexpr att::Handle kHandle0 = 0x0002;
3514   constexpr att::Handle kHandle1 = 0x0003;
3515   const auto kExpectedResponse = StaticByteBuffer(att::kReadByTypeResponse,
3516                                                   0x03,  // pair length
3517                                                   LowerBits(kHandle0),
3518                                                   UpperBits(kHandle0),
3519                                                   0x00,  // attribute pair 0
3520                                                   LowerBits(kHandle1),
3521                                                   UpperBits(kHandle1),
3522                                                   0x01  // attribute pair 1
3523   );
3524 
3525   bool cb_called = false;
3526   auto cb = [&](Client::ReadByTypeResult result) {
3527     cb_called = true;
3528     ASSERT_EQ(fit::ok(), result);
3529     const auto& values = result.value();
3530     ASSERT_EQ(2u, values.size());
3531     EXPECT_EQ(kHandle0, values[0].handle);
3532     EXPECT_TRUE(ContainersEqual(StaticByteBuffer(0x00), values[0].value));
3533     EXPECT_FALSE(values[0].maybe_truncated);
3534     EXPECT_EQ(kHandle1, values[1].handle);
3535     EXPECT_TRUE(ContainersEqual(StaticByteBuffer(0x01), values[1].value));
3536     EXPECT_FALSE(values[1].maybe_truncated);
3537   };
3538 
3539   EXPECT_PACKET_OUT(kExpectedRequest, &kExpectedResponse);
3540   client()->ReadByTypeRequest(kUuid16, kStartHandle, kEndHandle, cb);
3541   RunUntilIdle();
3542   EXPECT_TRUE(cb_called);
3543   EXPECT_FALSE(fake_chan()->link_error());
3544 }
3545 
TEST_F(ClientTest,ReadByTypeRequestSuccess128BitUUID)3546 TEST_F(ClientTest, ReadByTypeRequestSuccess128BitUUID) {
3547   const UUID kUuid128({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15});
3548   constexpr att::Handle kStartHandle = 0x0001;
3549   constexpr att::Handle kEndHandle = 0xFFFF;
3550   const auto kExpectedRequest =
3551       StaticByteBuffer(att::kReadByTypeRequest,  // opcode
3552                        LowerBits(kStartHandle),
3553                        UpperBits(kStartHandle),  // start handle
3554                        LowerBits(kEndHandle),
3555                        UpperBits(kEndHandle),  // end handle
3556                        // UUID
3557                        0,
3558                        1,
3559                        2,
3560                        3,
3561                        4,
3562                        5,
3563                        6,
3564                        7,
3565                        8,
3566                        9,
3567                        10,
3568                        11,
3569                        12,
3570                        13,
3571                        14,
3572                        15);
3573 
3574   constexpr att::Handle kHandle0 = 0x0002;
3575   constexpr att::Handle kHandle1 = 0x0003;
3576   const auto kExpectedResponse = StaticByteBuffer(att::kReadByTypeResponse,
3577                                                   0x03,  // pair length
3578                                                   LowerBits(kHandle0),
3579                                                   UpperBits(kHandle0),
3580                                                   0x00,  // attribute pair 0
3581                                                   LowerBits(kHandle1),
3582                                                   UpperBits(kHandle1),
3583                                                   0x01  // attribute pair 1
3584   );
3585 
3586   bool cb_called = false;
3587   auto cb = [&](Client::ReadByTypeResult result) {
3588     cb_called = true;
3589     ASSERT_EQ(fit::ok(), result);
3590     const auto& values = result.value();
3591     ASSERT_EQ(2u, values.size());
3592     EXPECT_EQ(kHandle0, values[0].handle);
3593     EXPECT_TRUE(ContainersEqual(StaticByteBuffer(0x00), values[0].value));
3594     EXPECT_EQ(kHandle1, values[1].handle);
3595     EXPECT_TRUE(ContainersEqual(StaticByteBuffer(0x01), values[1].value));
3596   };
3597 
3598   EXPECT_PACKET_OUT(kExpectedRequest, &kExpectedResponse);
3599   client()->ReadByTypeRequest(kUuid128, kStartHandle, kEndHandle, cb);
3600   RunUntilIdle();
3601   EXPECT_TRUE(cb_called);
3602   EXPECT_FALSE(fake_chan()->link_error());
3603 }
3604 
TEST_F(ClientTest,ReadByTypeRequestError)3605 TEST_F(ClientTest, ReadByTypeRequestError) {
3606   constexpr att::Handle kStartHandle = 0x0001;
3607   constexpr att::Handle kEndHandle = 0xFFFF;
3608   const auto kExpectedRequest =
3609       StaticByteBuffer(att::kReadByTypeRequest,  // opcode
3610                        LowerBits(kStartHandle),
3611                        UpperBits(kStartHandle),  // start handle
3612                        LowerBits(kEndHandle),
3613                        UpperBits(kEndHandle),  // end handle
3614                        // UUID matches |kTestUuid3| declared above.
3615                        0,
3616                        1,
3617                        2,
3618                        3,
3619                        4,
3620                        5,
3621                        6,
3622                        7,
3623                        8,
3624                        9,
3625                        10,
3626                        11,
3627                        12,
3628                        13,
3629                        14,
3630                        15);
3631 
3632   const auto kErrorResponse = StaticByteBuffer(
3633       att::kErrorResponse,      // opcode
3634       att::kReadByTypeRequest,  // request opcode
3635       LowerBits(kStartHandle),
3636       UpperBits(kStartHandle),                                  // start handle
3637       static_cast<uint8_t>(att::ErrorCode::kAttributeNotFound)  // error code
3638   );
3639 
3640   std::optional<att::Error> error;
3641   std::optional<att::Handle> handle;
3642   auto cb = [&](Client::ReadByTypeResult result) {
3643     ASSERT_TRUE(result.is_error());
3644     error = result.error_value().error;
3645     handle = result.error_value().handle;
3646   };
3647 
3648   EXPECT_PACKET_OUT(kExpectedRequest, &kErrorResponse);
3649   client()->ReadByTypeRequest(kTestUuid3, kStartHandle, kEndHandle, cb);
3650   RunUntilIdle();
3651   ASSERT_TRUE(error.has_value());
3652   EXPECT_EQ(att::Error(att::ErrorCode::kAttributeNotFound), *error);
3653   ASSERT_TRUE(handle.has_value());
3654   EXPECT_EQ(kStartHandle, handle.value());
3655   EXPECT_FALSE(fake_chan()->link_error());
3656 }
3657 
TEST_F(ClientTest,ReadByTypeRequestInvalidResponses)3658 TEST_F(ClientTest, ReadByTypeRequestInvalidResponses) {
3659   constexpr att::Handle kStartHandle = 0x0002;
3660   constexpr att::Handle kEndHandle = 0xFF00;
3661   constexpr att::Handle kHandle0 = 0x0005;
3662   constexpr att::Handle kHandle1 = 0x0006;
3663 
3664   const auto kResponseEmptyPayload = StaticByteBuffer(att::kReadByTypeResponse);
3665   const auto kResponseLengthGreaterThanListLength =
3666       StaticByteBuffer(att::kReadByTypeResponse,
3667                        0x02,   // length
3668                        0x01);  // invalid list (too small)
3669   const auto kResponseWithInvalidLength =
3670       StaticByteBuffer(att::kReadByTypeResponse,
3671                        0x00,  // invalid pair length (less than handle size)
3672                        LowerBits(kHandle0),
3673                        UpperBits(kHandle0),
3674                        0x00);  // attribute pair 0
3675   const auto kResponseWithEmptyList = StaticByteBuffer(att::kReadByTypeResponse,
3676                                                        0x03);  // pair length
3677   const auto kResponseWithInvalidList = StaticByteBuffer(
3678       att::kReadByTypeResponse,
3679       0x03,  // length
3680       LowerBits(kHandle0),
3681       UpperBits(kHandle0));  // invalid attribute pair 0 (invalid length)
3682   const auto kResponseWithInvalidAttributeHandleLessThanStart =
3683       StaticByteBuffer(att::kReadByTypeResponse,
3684                        0x02,  // length
3685                        // invalid attribute pair 0 (handle out of range)
3686                        LowerBits(kStartHandle - 1),
3687                        UpperBits(kStartHandle - 1));
3688   const auto kResponseWithInvalidAttributeHandleGreaterThanEnd =
3689       StaticByteBuffer(att::kReadByTypeResponse,
3690                        0x02,  // length
3691                        // invalid attribute pair 0 (handle out of range)
3692                        LowerBits(kEndHandle + 1),
3693                        UpperBits(kEndHandle + 1));
3694   const auto kResponseWithInvalidListWithDecreasingHandles =
3695       StaticByteBuffer(att::kReadByTypeResponse,
3696                        0x02,  // length
3697                        LowerBits(kHandle1),
3698                        UpperBits(kHandle1),  // attribute pair 0
3699                        LowerBits(kHandle0),
3700                        UpperBits(kHandle0));  // attribute pair 1
3701   const auto kResponseWithInvalidListWithDuplicateHandles =
3702       StaticByteBuffer(att::kReadByTypeResponse,
3703                        0x02,  // length
3704                        LowerBits(kHandle0),
3705                        UpperBits(kHandle0),  // attribute pair 0
3706                        LowerBits(kHandle0),
3707                        UpperBits(kHandle0));  // attribute pair 1
3708 
3709   const std::vector<std::pair<const char*, const ByteBuffer&>>
3710       kInvalidResponses = {
3711           {"kResponseEmptyPayload", kResponseEmptyPayload},
3712           {"kResponseLengthGreaterThanListLength",
3713            kResponseLengthGreaterThanListLength},
3714           {"kResponseWithInvalidLength", kResponseWithInvalidLength},
3715           {"kResponseWithEmptyList", kResponseWithEmptyList},
3716           {"kResponseWithInvalidList", kResponseWithInvalidList},
3717           {"kResponseWithInvalidAttributeHandleLessThanStart",
3718            kResponseWithInvalidAttributeHandleLessThanStart},
3719           {"kResponseWithInvalidAttributeHandleGreaterThanEnd",
3720            kResponseWithInvalidAttributeHandleGreaterThanEnd},
3721           {"kResponseWithInvalidListWithDecreasingHandles",
3722            kResponseWithInvalidListWithDecreasingHandles},
3723           {"kResponseWithInvalidListWithDuplicateHandles",
3724            kResponseWithInvalidListWithDuplicateHandles}};
3725 
3726   const auto kExpectedRequest =
3727       StaticByteBuffer(att::kReadByTypeRequest,  // opcode
3728                        LowerBits(kStartHandle),
3729                        UpperBits(kStartHandle),  // start handle
3730                        LowerBits(kEndHandle),
3731                        UpperBits(kEndHandle),  // end handle
3732                        // UUID matches |kTestUuid3| declared above.
3733                        0,
3734                        1,
3735                        2,
3736                        3,
3737                        4,
3738                        5,
3739                        6,
3740                        7,
3741                        8,
3742                        9,
3743                        10,
3744                        11,
3745                        12,
3746                        13,
3747                        14,
3748                        15);
3749 
3750   for (const auto& [name, invalid_rsp] : kInvalidResponses) {
3751     SCOPED_TRACE(bt_lib_cpp_string::StringPrintf("Invalid Response: %s", name));
3752 
3753     std::optional<att::Error> error;
3754     auto cb = [&](Client::ReadByTypeResult result) {
3755       ASSERT_TRUE(result.is_error());
3756       error = result.error_value().error;
3757       EXPECT_FALSE(result.error_value().handle.has_value());
3758     };
3759 
3760     EXPECT_PACKET_OUT(kExpectedRequest, &invalid_rsp);
3761     client()->ReadByTypeRequest(kTestUuid3, kStartHandle, kEndHandle, cb);
3762     RunUntilIdle();
3763     ASSERT_TRUE(error.has_value());
3764     EXPECT_EQ(Error(HostError::kPacketMalformed), *error);
3765     EXPECT_FALSE(fake_chan()->link_error());
3766   }
3767 }
3768 
TEST_F(ClientTest,ReadBlobRequestEmptyResponse)3769 TEST_F(ClientTest, ReadBlobRequestEmptyResponse) {
3770   constexpr att::Handle kHandle = 1;
3771   constexpr uint16_t kOffset = 5;
3772   const StaticByteBuffer kExpectedRequest(0x0C,  // opcode: read blob request
3773                                           0x01,
3774                                           0x00,  // handle: 1
3775                                           0x05,
3776                                           0x00  // offset: 5
3777   );
3778   // ATT Read Blob Response with no payload.
3779   const StaticByteBuffer kResponse(0x0D);
3780 
3781   att::Result<> status = ToResult(HostError::kFailed);
3782   auto cb = [&](att::Result<> cb_status,
3783                 const ByteBuffer& value,
3784                 bool maybe_truncated) {
3785     status = cb_status;
3786 
3787     // We expect an empty value
3788     EXPECT_EQ(0u, value.size());
3789     EXPECT_FALSE(maybe_truncated);
3790   };
3791 
3792   EXPECT_PACKET_OUT(kExpectedRequest, &kResponse);
3793   client()->ReadBlobRequest(kHandle, kOffset, cb);
3794   RunUntilIdle();
3795   EXPECT_EQ(fit::ok(), status);
3796   EXPECT_FALSE(fake_chan()->link_error());
3797 }
3798 
TEST_F(ClientTest,ReadBlobRequestSuccess)3799 TEST_F(ClientTest, ReadBlobRequestSuccess) {
3800   constexpr att::Handle kHandle = 1;
3801   constexpr uint16_t kOffset = 5;
3802   const StaticByteBuffer kExpectedRequest(0x0C,  // opcode: read blob request
3803                                           0x01,
3804                                           0x00,  // handle: 1
3805                                           0x05,
3806                                           0x00  // offset: 5
3807   );
3808   const StaticByteBuffer kExpectedResponse(0x0D,  // opcode: read blob response
3809                                            't',
3810                                            'e',
3811                                            's',
3812                                            't'  // value: "test"
3813   );
3814 
3815   att::Result<> status = ToResult(HostError::kFailed);
3816   auto cb = [&](att::Result<> cb_status,
3817                 const ByteBuffer& value,
3818                 bool maybe_truncated) {
3819     status = cb_status;
3820 
3821     // We expect an empty value
3822     EXPECT_TRUE(ContainersEqual(kExpectedResponse.view(1), value));
3823     EXPECT_FALSE(maybe_truncated);
3824   };
3825 
3826   EXPECT_PACKET_OUT(kExpectedRequest, &kExpectedResponse);
3827   client()->ReadBlobRequest(kHandle, kOffset, cb);
3828   RunUntilIdle();
3829   EXPECT_EQ(fit::ok(), status);
3830   EXPECT_FALSE(fake_chan()->link_error());
3831 }
3832 
TEST_F(ClientTest,ReadBlobRequestMaybeTruncated)3833 TEST_F(ClientTest, ReadBlobRequestMaybeTruncated) {
3834   constexpr att::Handle kHandle = 0x0001;
3835   constexpr uint16_t kOffset = 5;
3836   const auto kExpectedRequest =
3837       StaticByteBuffer(0x0C,  // opcode: read blob request
3838                        LowerBits(kHandle),
3839                        UpperBits(kHandle),  // handle
3840                        LowerBits(kOffset),
3841                        UpperBits(kOffset)  // offset
3842       );
3843 
3844   DynamicByteBuffer expected_response(att()->mtu());
3845   expected_response.Fill(0);
3846   expected_response.WriteObj(
3847       att::kReadBlobResponse);  // opcode: read blob response
3848 
3849   att::Result<> status = ToResult(HostError::kFailed);
3850   auto cb = [&](att::Result<> cb_status,
3851                 const ByteBuffer& value,
3852                 bool maybe_truncated) {
3853     status = cb_status;
3854     EXPECT_TRUE(ContainersEqual(expected_response.view(1), value));
3855     EXPECT_TRUE(maybe_truncated);
3856   };
3857 
3858   EXPECT_PACKET_OUT(kExpectedRequest, &expected_response);
3859   client()->ReadBlobRequest(kHandle, kOffset, cb);
3860   RunUntilIdle();
3861   EXPECT_EQ(fit::ok(), status);
3862   EXPECT_FALSE(fake_chan()->link_error());
3863 }
3864 
TEST_F(ClientTest,ReadBlobRequestSuccessNotTruncatedWhenOffsetPlusMtuEqualsMaxValueLength)3865 TEST_F(
3866     ClientTest,
3867     ReadBlobRequestSuccessNotTruncatedWhenOffsetPlusMtuEqualsMaxValueLength) {
3868   constexpr att::Handle kHandle = 0x0001;
3869   const uint16_t kOffset =
3870       att::kMaxAttributeValueLength - (att()->mtu() - sizeof(att::OpCode));
3871   const auto kExpectedRequest =
3872       StaticByteBuffer(0x0C,  // opcode: read blob request
3873                        LowerBits(kHandle),
3874                        UpperBits(kHandle),  // handle
3875                        LowerBits(kOffset),
3876                        UpperBits(kOffset)  // offset
3877       );
3878 
3879   // The blob should both max out the MTU and max out the value length.
3880   DynamicByteBuffer expected_response(att()->mtu());
3881   expected_response.Fill(0);
3882   expected_response.WriteObj(
3883       att::kReadBlobResponse);  // opcode: read blob response
3884 
3885   att::Result<> status = ToResult(HostError::kFailed);
3886   auto cb = [&](att::Result<> cb_status,
3887                 const ByteBuffer& value,
3888                 bool maybe_truncated) {
3889     status = cb_status;
3890     EXPECT_TRUE(ContainersEqual(expected_response.view(1), value));
3891     EXPECT_FALSE(maybe_truncated);
3892   };
3893 
3894   EXPECT_PACKET_OUT(kExpectedRequest, &expected_response);
3895   client()->ReadBlobRequest(kHandle, kOffset, cb);
3896   RunUntilIdle();
3897   EXPECT_EQ(fit::ok(), status);
3898   EXPECT_FALSE(fake_chan()->link_error());
3899 }
3900 
TEST_F(ClientTest,ReadBlobRequestError)3901 TEST_F(ClientTest, ReadBlobRequestError) {
3902   constexpr att::Handle kHandle = 1;
3903   constexpr uint16_t kOffset = 5;
3904   const StaticByteBuffer kExpectedRequest(0x0C,  // opcode: read blob request
3905                                           0x01,
3906                                           0x00,  // handle: 1
3907                                           0x05,
3908                                           0x00  // offset: 5
3909   );
3910   const StaticByteBuffer kErrorResponse(0x01,  // opcode: error response
3911                                         0x0C,  // request: read blob request
3912                                         0x01,
3913                                         0x00,  // handle: 0x0001
3914                                         0x07   // error: Invalid Offset
3915   );
3916 
3917   att::Result<> status = ToResult(HostError::kFailed);
3918   auto cb = [&](att::Result<> cb_status,
3919                 const ByteBuffer& value,
3920                 bool maybe_truncated) {
3921     status = cb_status;
3922 
3923     // We expect an empty value
3924     EXPECT_EQ(0u, value.size());
3925     EXPECT_FALSE(maybe_truncated);
3926   };
3927 
3928   EXPECT_PACKET_OUT(kExpectedRequest, &kErrorResponse);
3929   client()->ReadBlobRequest(kHandle, kOffset, cb);
3930   RunUntilIdle();
3931   EXPECT_EQ(ToResult(att::ErrorCode::kInvalidOffset), status);
3932   EXPECT_FALSE(fake_chan()->link_error());
3933 }
3934 
TEST_F(ClientTest,EmptyNotification)3935 TEST_F(ClientTest, EmptyNotification) {
3936   constexpr att::Handle kHandle = 1;
3937 
3938   bool called = false;
3939   client()->SetNotificationHandler(
3940       [&](bool ind, auto handle, const auto& value, bool /*maybe_truncated*/) {
3941         called = true;
3942         EXPECT_FALSE(ind);
3943         EXPECT_EQ(kHandle, handle);
3944         EXPECT_EQ(0u, value.size());
3945       });
3946 
3947   // clang-format off
3948   fake_chan()->Receive(StaticByteBuffer(
3949       0x1B,       // opcode: notification
3950       0x01, 0x00  // handle: 1
3951       ));
3952   // clang-format on
3953 
3954   RunUntilIdle();
3955   EXPECT_TRUE(called);
3956 }
3957 
TEST_F(ClientTest,Notification)3958 TEST_F(ClientTest, Notification) {
3959   constexpr att::Handle kHandle = 1;
3960 
3961   bool called = false;
3962   client()->SetNotificationHandler(
3963       [&](bool ind, auto handle, const auto& value, bool maybe_truncated) {
3964         called = true;
3965         EXPECT_FALSE(ind);
3966         EXPECT_EQ(kHandle, handle);
3967         EXPECT_EQ("test", value.AsString());
3968         EXPECT_FALSE(maybe_truncated);
3969       });
3970 
3971   // clang-format off
3972   fake_chan()->Receive(StaticByteBuffer(
3973       0x1B,               // opcode: notification
3974       0x01, 0x00,         // handle: 1
3975       't', 'e', 's', 't'  // value: "test"
3976   ));
3977   // clang-format on
3978 
3979   RunUntilIdle();
3980   EXPECT_TRUE(called);
3981 }
3982 
TEST_F(ClientTest,NotificationTruncated)3983 TEST_F(ClientTest, NotificationTruncated) {
3984   constexpr att::Handle kHandle = 1;
3985   StaticByteBuffer pdu_header(0x1B,  // opcode: notification
3986                               0x01,
3987                               0x00  // handle: 1
3988 
3989   );
3990   DynamicByteBuffer pdu(att()->mtu());
3991   pdu.Fill(0);
3992   pdu_header.Copy(&pdu);
3993 
3994   bool called = false;
3995   client()->SetNotificationHandler([&](bool ind,
3996                                        auto handle,
3997                                        const ByteBuffer& value,
3998                                        bool maybe_truncated) {
3999     called = true;
4000     EXPECT_FALSE(ind);
4001     EXPECT_EQ(kHandle, handle);
4002     EXPECT_EQ(value.size(), att()->mtu() - pdu_header.size());
4003     EXPECT_TRUE(maybe_truncated);
4004   });
4005   fake_chan()->Receive(pdu);
4006 
4007   RunUntilIdle();
4008   EXPECT_TRUE(called);
4009 }
4010 
TEST_F(ClientTest,Indication)4011 TEST_F(ClientTest, Indication) {
4012   constexpr att::Handle kHandle = 1;
4013 
4014   bool called = false;
4015   client()->SetNotificationHandler(
4016       [&](bool ind, auto handle, const auto& value, bool maybe_truncated) {
4017         called = true;
4018         EXPECT_TRUE(ind);
4019         EXPECT_EQ(kHandle, handle);
4020         EXPECT_EQ("test", value.AsString());
4021         EXPECT_FALSE(maybe_truncated);
4022       });
4023 
4024   const auto kIndication = StaticByteBuffer(0x1D,  // opcode: indication
4025                                             0x01,
4026                                             0x00,  // handle: 1
4027                                             't',
4028                                             'e',
4029                                             's',
4030                                             't'  // value: "test"
4031   );
4032 
4033   // Wait until a confirmation gets sent.
4034   const auto kConfirmation = StaticByteBuffer(0x1E);
4035   EXPECT_PACKET_OUT(kConfirmation);
4036   fake_chan()->Receive(kIndication);
4037   EXPECT_TRUE(called);
4038 }
4039 
4040 // Maxing out the length parameter of a Read By Type request is not possible
4041 // with the current max preferred MTU. If the max MTU is increased, this test
4042 // will need to be updated to test that ReadByTypeValue.maybe_truncated is true
4043 // for read by type responses with values that max out the length parameter.
TEST_F(ClientTest,ReadByTypeRequestSuccessValueTruncatedByLengthParam)4044 TEST_F(ClientTest, ReadByTypeRequestSuccessValueTruncatedByLengthParam) {
4045   const uint16_t kSizeOfReadByTypeResponseWithValueThatMaxesOutLengthParam =
4046       sizeof(att::kReadByTypeResponse) + sizeof(att::ReadByTypeResponseParams) +
4047       std::numeric_limits<
4048           decltype(att::ReadByTypeResponseParams::length)>::max();
4049   EXPECT_LT(att()->preferred_mtu(),
4050             kSizeOfReadByTypeResponseWithValueThatMaxesOutLengthParam);
4051   EXPECT_LT(att::kLEMaxMTU,
4052             kSizeOfReadByTypeResponseWithValueThatMaxesOutLengthParam);
4053 }
4054 
TEST_F(ClientTest,ReadByTypeRequestSuccessValueTruncatedByMtu)4055 TEST_F(ClientTest, ReadByTypeRequestSuccessValueTruncatedByMtu) {
4056   EXPECT_EQ(att()->mtu(), att::kLEMinMTU);
4057 
4058   const UUID kUuid16(uint16_t{0xBEEF});
4059   constexpr att::Handle kStartHandle = 0x0001;
4060   constexpr att::Handle kEndHandle = 0xFFFF;
4061   const auto kExpectedRequest =
4062       StaticByteBuffer(att::kReadByTypeRequest,  // opcode
4063                        LowerBits(kStartHandle),
4064                        UpperBits(kStartHandle),  // start handle
4065                        LowerBits(kEndHandle),
4066                        UpperBits(kEndHandle),  // end handle
4067                        // UUID
4068                        0xEF,
4069                        0xBE);
4070 
4071   constexpr att::Handle kHandle = 0x0002;
4072   const uint8_t kMaxReadByTypeValueLengthWithMinMtu = att::kLEMinMTU - 4;
4073   const auto kExpectedResponseHeader = StaticByteBuffer(
4074       att::kReadByTypeResponse,
4075       sizeof(kHandle) + kMaxReadByTypeValueLengthWithMinMtu,  // pair length
4076       LowerBits(kHandle),
4077       UpperBits(kHandle)  // attribute handle
4078   );
4079   DynamicByteBuffer expected_response(kExpectedResponseHeader.size() +
4080                                       kMaxReadByTypeValueLengthWithMinMtu);
4081   expected_response.Fill(0);
4082   kExpectedResponseHeader.Copy(&expected_response);
4083 
4084   bool cb_called = false;
4085   auto cb = [&](Client::ReadByTypeResult result) {
4086     cb_called = true;
4087     ASSERT_EQ(fit::ok(), result);
4088     const auto& values = result.value();
4089     ASSERT_EQ(1u, values.size());
4090     EXPECT_EQ(kHandle, values[0].handle);
4091     EXPECT_EQ(values[0].value.size(), kMaxReadByTypeValueLengthWithMinMtu);
4092     EXPECT_TRUE(values[0].maybe_truncated);
4093   };
4094 
4095   EXPECT_PACKET_OUT(kExpectedRequest, &expected_response);
4096   client()->ReadByTypeRequest(kUuid16, kStartHandle, kEndHandle, cb);
4097   RunUntilIdle();
4098   EXPECT_TRUE(cb_called);
4099   EXPECT_FALSE(fake_chan()->link_error());
4100 }
4101 
4102 }  // namespace
4103 }  // namespace bt::gatt
4104