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