xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/host/test/src/ble_gatt_read_test.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *  http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 #include <string.h>
21 #include <errno.h>
22 #include <limits.h>
23 #include "testutil/testutil.h"
24 #include "nimble/ble.h"
25 #include "host/ble_hs_test.h"
26 #include "host/ble_uuid.h"
27 #include "ble_hs_test_util.h"
28 
29 struct ble_gatt_read_test_attr {
30     uint16_t conn_handle;
31     uint16_t handle;
32     uint8_t value_len;
33     uint8_t value[BLE_ATT_ATTR_MAX_LEN];
34 };
35 
36 #define BLE_GATT_READ_TEST_MAX_ATTRS    256
37 
38 struct ble_gatt_read_test_attr
39     ble_gatt_read_test_attrs[BLE_GATT_READ_TEST_MAX_ATTRS];
40 int ble_gatt_read_test_num_attrs;
41 int ble_gatt_read_test_complete;
42 
43 uint16_t ble_gatt_read_test_bad_conn_handle;
44 int ble_gatt_read_test_bad_status;
45 
46 static void
ble_gatt_read_test_misc_init(void)47 ble_gatt_read_test_misc_init(void)
48 {
49     ble_hs_test_util_init();
50     ble_gatt_read_test_num_attrs = 0;
51     ble_gatt_read_test_complete = 0;
52     ble_gatt_read_test_bad_conn_handle = 0;
53     ble_gatt_read_test_bad_status = 0;
54 
55     memset(&ble_gatt_read_test_attrs[0], 0,
56            sizeof ble_gatt_read_test_attrs[0]);
57 }
58 
59 static int
ble_gatt_read_test_cb(uint16_t conn_handle,const struct ble_gatt_error * error,struct ble_gatt_attr * attr,void * arg)60 ble_gatt_read_test_cb(uint16_t conn_handle, const struct ble_gatt_error *error,
61                       struct ble_gatt_attr *attr, void *arg)
62 {
63     struct ble_gatt_read_test_attr *dst;
64     int *stop_after;
65     int rc;
66 
67     stop_after = arg;
68 
69     TEST_ASSERT_FATAL(error != NULL);
70 
71     if (error->status != 0) {
72         ble_gatt_read_test_bad_conn_handle = conn_handle;
73         ble_gatt_read_test_bad_status = error->status;
74         ble_gatt_read_test_complete = 1;
75         return 0;
76     }
77 
78     if (attr == NULL) {
79         ble_gatt_read_test_complete = 1;
80         return 0;
81     }
82 
83     TEST_ASSERT_FATAL(ble_gatt_read_test_num_attrs <
84                       BLE_GATT_READ_TEST_MAX_ATTRS);
85     dst = ble_gatt_read_test_attrs + ble_gatt_read_test_num_attrs++;
86 
87     TEST_ASSERT_FATAL(OS_MBUF_PKTLEN(attr->om) <= sizeof dst->value);
88 
89     dst->conn_handle = conn_handle;
90     dst->handle = attr->handle;
91     dst->value_len = OS_MBUF_PKTLEN(attr->om);
92     rc = os_mbuf_copydata(attr->om, 0, OS_MBUF_PKTLEN(attr->om), dst->value);
93     TEST_ASSERT_FATAL(rc == 0);
94 
95     if (stop_after != NULL && *stop_after > 0) {
96         (*stop_after)--;
97         if (*stop_after == 0) {
98             ble_gatt_read_test_complete = 1;
99             return 1;
100         }
101     } else {
102         ble_gatt_read_test_complete = 1;
103     }
104 
105     return 0;
106 }
107 
108 static int
ble_gatt_read_test_long_cb(uint16_t conn_handle,const struct ble_gatt_error * error,struct ble_gatt_attr * attr,void * arg)109 ble_gatt_read_test_long_cb(uint16_t conn_handle,
110                            const struct ble_gatt_error *error,
111                            struct ble_gatt_attr *attr, void *arg)
112 {
113     struct ble_gatt_read_test_attr *dst;
114     int *reads_left;
115     int rc;
116 
117     reads_left = arg;
118 
119     TEST_ASSERT_FATAL(error != NULL);
120 
121     if (error->status != 0) {
122         ble_gatt_read_test_bad_conn_handle = conn_handle;
123         ble_gatt_read_test_bad_status = error->status;
124         ble_gatt_read_test_complete = 1;
125         return 0;
126     }
127 
128     if (attr == NULL) {
129         ble_gatt_read_test_complete = 1;
130         return 0;
131     }
132 
133     dst = ble_gatt_read_test_attrs + 0;
134 
135     TEST_ASSERT_FATAL(OS_MBUF_PKTLEN(attr->om) <=
136         dst->value_len + sizeof dst->value);
137     TEST_ASSERT(attr->offset == dst->value_len);
138 
139     if (attr->offset == 0) {
140         dst->conn_handle = conn_handle;
141         dst->handle = attr->handle;
142     } else {
143         TEST_ASSERT(conn_handle == dst->conn_handle);
144         TEST_ASSERT(attr->handle == dst->handle);
145     }
146     rc = os_mbuf_copydata(attr->om, 0, OS_MBUF_PKTLEN(attr->om),
147                           dst->value + dst->value_len);
148     TEST_ASSERT_FATAL(rc == 0);
149     dst->value_len += OS_MBUF_PKTLEN(attr->om);
150 
151     if (reads_left != NULL && *reads_left > 0) {
152         (*reads_left)--;
153         if (*reads_left == 0) {
154             ble_gatt_read_test_complete = 1;
155             return 1;
156         }
157     }
158 
159     return 0;
160 }
161 
162 static void
ble_gatt_read_test_misc_rx_rsp_good_raw(uint16_t conn_handle,uint8_t att_op,const void * data,int data_len)163 ble_gatt_read_test_misc_rx_rsp_good_raw(uint16_t conn_handle,
164                                         uint8_t att_op,
165                                         const void *data, int data_len)
166 {
167     uint8_t buf[1024];
168     int rc;
169 
170     TEST_ASSERT_FATAL(data_len <= sizeof buf);
171 
172     /* Send the pending ATT Read Request. */
173 
174     buf[0] = att_op;
175     memcpy(buf + 1, data, data_len);
176 
177     rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
178                                                 buf, 1 + data_len);
179     TEST_ASSERT(rc == 0);
180 }
181 
182 static void
ble_gatt_read_test_misc_rx_rsp_good(uint16_t conn_handle,struct ble_hs_test_util_flat_attr * attr)183 ble_gatt_read_test_misc_rx_rsp_good(uint16_t conn_handle,
184                                     struct ble_hs_test_util_flat_attr *attr)
185 {
186     ble_gatt_read_test_misc_rx_rsp_good_raw(conn_handle, BLE_ATT_OP_READ_RSP,
187                                             attr->value,
188                                             attr->value_len);
189 }
190 
191 static void
ble_gatt_read_test_misc_rx_rsp_bad(uint16_t conn_handle,uint8_t att_error,uint16_t err_handle)192 ble_gatt_read_test_misc_rx_rsp_bad(uint16_t conn_handle,
193                                    uint8_t att_error, uint16_t err_handle)
194 {
195     /* Send the pending ATT Read Request. */
196 
197     ble_hs_test_util_rx_att_err_rsp(conn_handle, BLE_ATT_OP_READ_REQ,
198                                     att_error, err_handle);
199 }
200 
201 static int
ble_gatt_read_test_misc_uuid_rx_rsp_good(uint16_t conn_handle,struct ble_hs_test_util_flat_attr * attrs)202 ble_gatt_read_test_misc_uuid_rx_rsp_good(
203     uint16_t conn_handle, struct ble_hs_test_util_flat_attr *attrs)
204 {
205     struct ble_att_read_type_rsp rsp;
206     uint8_t buf[1024];
207     int prev_len;
208     int off;
209     int rc;
210     int i;
211 
212     if (ble_gatt_read_test_complete || attrs[0].handle == 0) {
213         return 0;
214     }
215 
216     /* Send the pending ATT Read By Type Request. */
217 
218     rsp.batp_length = 2 + attrs[0].value_len;
219     ble_att_read_type_rsp_write(buf, sizeof buf, &rsp);
220 
221     prev_len = 0;
222     off = BLE_ATT_READ_TYPE_RSP_BASE_SZ;
223     for (i = 0; attrs[i].handle != 0; i++) {
224         if (prev_len != 0 && prev_len != attrs[i].value_len) {
225             break;
226         }
227         prev_len = attrs[i].value_len;
228 
229         put_le16(buf + off, attrs[i].handle);
230         off += 2;
231 
232         memcpy(buf + off, attrs[i].value, attrs[i].value_len);
233         off += attrs[i].value_len;
234     }
235 
236     rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
237                                                 buf, off);
238     TEST_ASSERT(rc == 0);
239 
240     return i;
241 }
242 
243 static void
ble_gatt_read_test_misc_verify_good(struct ble_hs_test_util_flat_attr * attr)244 ble_gatt_read_test_misc_verify_good(struct ble_hs_test_util_flat_attr *attr)
245 {
246     int rc;
247 
248     ble_gatt_read_test_misc_init();
249     ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
250                                  NULL, NULL);
251 
252     /* Exchange MTU: We need plus 1 for the read response opcode */
253     ble_hs_test_util_set_att_mtu(2, attr->value_len + 1);
254 
255     rc = ble_gattc_read(2, attr->handle, ble_gatt_read_test_cb, NULL);
256     TEST_ASSERT_FATAL(rc == 0);
257 
258     ble_gatt_read_test_misc_rx_rsp_good(2, attr);
259 
260     TEST_ASSERT(ble_gatt_read_test_num_attrs == 1);
261     TEST_ASSERT(ble_gatt_read_test_attrs[0].conn_handle == 2);
262     TEST_ASSERT(ble_gatt_read_test_attrs[0].handle == attr->handle);
263     TEST_ASSERT(ble_gatt_read_test_attrs[0].value_len == attr->value_len);
264     TEST_ASSERT(memcmp(ble_gatt_read_test_attrs[0].value, attr->value,
265                        attr->value_len) == 0);
266 }
267 
268 static void
ble_gatt_read_test_misc_verify_bad(uint8_t att_status,struct ble_hs_test_util_flat_attr * attr)269 ble_gatt_read_test_misc_verify_bad(uint8_t att_status,
270                                    struct ble_hs_test_util_flat_attr *attr)
271 {
272     int rc;
273 
274     ble_gatt_read_test_misc_init();
275     ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
276                                  NULL, NULL);
277 
278     rc = ble_gattc_read(2, attr->handle, ble_gatt_read_test_cb, NULL);
279     TEST_ASSERT_FATAL(rc == 0);
280 
281     ble_gatt_read_test_misc_rx_rsp_bad(2, att_status, attr->handle);
282 
283     TEST_ASSERT(ble_gatt_read_test_num_attrs == 0);
284     TEST_ASSERT(ble_gatt_read_test_bad_conn_handle == 2);
285     TEST_ASSERT(ble_gatt_read_test_bad_status ==
286                 BLE_HS_ERR_ATT_BASE + att_status);
287     TEST_ASSERT(!ble_gattc_any_jobs());
288 }
289 
290 static void
ble_gatt_read_test_misc_uuid_verify_good(uint16_t start_handle,uint16_t end_handle,const ble_uuid_t * uuid,int stop_after,struct ble_hs_test_util_flat_attr * attrs)291 ble_gatt_read_test_misc_uuid_verify_good(
292     uint16_t start_handle, uint16_t end_handle, const ble_uuid_t *uuid,
293     int stop_after, struct ble_hs_test_util_flat_attr *attrs)
294 {
295     int num_read;
296     int idx;
297     int rc;
298     int i;
299 
300     ble_gatt_read_test_misc_init();
301     ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
302                                  NULL, NULL);
303 
304     rc = ble_gattc_read_by_uuid(2, start_handle, end_handle, uuid,
305                                 ble_gatt_read_test_cb, &stop_after);
306     TEST_ASSERT_FATAL(rc == 0);
307 
308     idx = 0;
309     while (1) {
310         num_read = ble_gatt_read_test_misc_uuid_rx_rsp_good(2, attrs + idx);
311         if (num_read == 0) {
312             ble_hs_test_util_rx_att_err_rsp(2, BLE_ATT_OP_READ_TYPE_REQ,
313                                             BLE_ATT_ERR_ATTR_NOT_FOUND,
314                                             start_handle);
315             break;
316         }
317 
318         idx += num_read;
319     }
320 
321     TEST_ASSERT(ble_gatt_read_test_complete);
322     TEST_ASSERT(idx == ble_gatt_read_test_num_attrs);
323 
324     for (i = 0; i < idx; i++) {
325         TEST_ASSERT(ble_gatt_read_test_attrs[i].conn_handle == 2);
326         TEST_ASSERT(ble_gatt_read_test_attrs[i].handle == attrs[i].handle);
327         TEST_ASSERT(ble_gatt_read_test_attrs[i].value_len ==
328                     attrs[i].value_len);
329         TEST_ASSERT(memcmp(ble_gatt_read_test_attrs[i].value, attrs[i].value,
330                            attrs[i].value_len) == 0);
331     }
332     TEST_ASSERT(!ble_gattc_any_jobs());
333 }
334 
335 static void
ble_gatt_read_test_misc_long_verify_good(int max_reads,struct ble_hs_test_util_flat_attr * attr)336 ble_gatt_read_test_misc_long_verify_good(
337     int max_reads, struct ble_hs_test_util_flat_attr *attr)
338 {
339     int reads_left;
340     int chunk_sz;
341     int rem_len;
342     int att_op;
343     uint16_t offset = 0;
344     int off;
345     int rc;
346 
347     ble_gatt_read_test_misc_init();
348     ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
349                                  NULL, NULL);
350 
351     if (max_reads == 0) {
352         max_reads = INT_MAX;
353     }
354     reads_left = max_reads;
355     rc = ble_gattc_read_long(2, attr->handle, offset,
356                              ble_gatt_read_test_long_cb, &reads_left);
357     TEST_ASSERT_FATAL(rc == 0);
358 
359     off = 0;
360     rem_len = attr->value_len;
361     do {
362         if (rem_len > BLE_ATT_MTU_DFLT - 1) {
363             chunk_sz = BLE_ATT_MTU_DFLT - 1;
364         } else {
365             chunk_sz = rem_len;
366         }
367         if (off == 0) {
368             att_op = BLE_ATT_OP_READ_RSP;
369         } else {
370             att_op = BLE_ATT_OP_READ_BLOB_RSP;
371         }
372         ble_gatt_read_test_misc_rx_rsp_good_raw(2, att_op,
373                                                 attr->value + off, chunk_sz);
374         rem_len -= chunk_sz;
375         off += chunk_sz;
376     } while (rem_len > 0 && reads_left > 0);
377 
378     TEST_ASSERT(ble_gatt_read_test_complete);
379     TEST_ASSERT(!ble_gattc_any_jobs());
380     TEST_ASSERT(ble_gatt_read_test_attrs[0].conn_handle == 2);
381     TEST_ASSERT(ble_gatt_read_test_attrs[0].handle == attr->handle);
382     if (reads_left > 0) {
383         TEST_ASSERT(ble_gatt_read_test_attrs[0].value_len == attr->value_len);
384     }
385     TEST_ASSERT(memcmp(ble_gatt_read_test_attrs[0].value, attr->value,
386                        ble_gatt_read_test_attrs[0].value_len) == 0);
387 }
388 
389 static void
ble_gatt_read_test_misc_long_verify_bad(uint8_t att_status,struct ble_hs_test_util_flat_attr * attr)390 ble_gatt_read_test_misc_long_verify_bad(
391     uint8_t att_status, struct ble_hs_test_util_flat_attr *attr)
392 {
393     uint16_t offset = 0;
394     int rc;
395 
396     ble_gatt_read_test_misc_init();
397     ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
398                                  NULL, NULL);
399 
400     rc = ble_gattc_read_long(2, attr->handle, offset,
401                              ble_gatt_read_test_long_cb, NULL);
402     TEST_ASSERT_FATAL(rc == 0);
403 
404     ble_gatt_read_test_misc_rx_rsp_bad(2, att_status, attr->handle);
405 
406     TEST_ASSERT(ble_gatt_read_test_num_attrs == 0);
407     TEST_ASSERT(ble_gatt_read_test_bad_conn_handle == 2);
408     TEST_ASSERT(ble_gatt_read_test_bad_status ==
409                 BLE_HS_ERR_ATT_BASE + att_status);
410     TEST_ASSERT(!ble_gattc_any_jobs());
411 }
412 
413 static int
ble_gatt_read_test_misc_extract_handles(struct ble_hs_test_util_flat_attr * attrs,uint16_t * handles)414 ble_gatt_read_test_misc_extract_handles(
415     struct ble_hs_test_util_flat_attr *attrs, uint16_t *handles)
416 {
417     int i;
418 
419     for (i = 0; attrs[i].handle != 0; i++) {
420         handles[i] = attrs[i].handle;
421     }
422     return i;
423 }
424 
425 static void
ble_gatt_read_test_misc_mult_verify_good(struct ble_hs_test_util_flat_attr * attrs)426 ble_gatt_read_test_misc_mult_verify_good(
427     struct ble_hs_test_util_flat_attr *attrs)
428 {
429     uint8_t expected_value[512];
430     uint16_t handles[256];
431     int num_attrs;
432     int chunk_sz;
433     int off;
434     int rc;
435     int i;
436 
437     ble_gatt_read_test_misc_init();
438     ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
439                                  NULL, NULL);
440 
441     num_attrs = ble_gatt_read_test_misc_extract_handles(attrs, handles);
442 
443     off = 0;
444     for (i = 0; i < num_attrs; i++) {
445         if (attrs[i].value_len > BLE_ATT_MTU_DFLT - 1 - off) {
446             chunk_sz = BLE_ATT_MTU_DFLT - 1 - off;
447         } else {
448             chunk_sz = attrs[i].value_len;
449         }
450 
451         if (chunk_sz > 0) {
452             memcpy(expected_value + off, attrs[i].value, chunk_sz);
453             off += chunk_sz;
454         }
455     }
456 
457     rc = ble_gattc_read_mult(2, handles, num_attrs,
458                              ble_gatt_read_test_cb, NULL);
459     TEST_ASSERT_FATAL(rc == 0);
460 
461     ble_gatt_read_test_misc_rx_rsp_good_raw(2, BLE_ATT_OP_READ_MULT_RSP,
462                                             expected_value, off);
463 
464     TEST_ASSERT(ble_gatt_read_test_complete);
465     TEST_ASSERT(!ble_gattc_any_jobs());
466     TEST_ASSERT(ble_gatt_read_test_attrs[0].conn_handle == 2);
467     TEST_ASSERT(ble_gatt_read_test_attrs[0].value_len == off);
468     TEST_ASSERT(memcmp(ble_gatt_read_test_attrs[0].value, expected_value,
469                        off) == 0);
470 }
471 
472 static void
ble_gatt_read_test_misc_mult_verify_bad(uint8_t att_status,uint16_t err_handle,struct ble_hs_test_util_flat_attr * attrs)473 ble_gatt_read_test_misc_mult_verify_bad(
474     uint8_t att_status, uint16_t err_handle,
475     struct ble_hs_test_util_flat_attr *attrs)
476 {
477     uint16_t handles[256];
478     int num_attrs;
479     int rc;
480 
481     ble_gatt_read_test_misc_init();
482     ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
483                                  NULL, NULL);
484 
485     num_attrs = ble_gatt_read_test_misc_extract_handles(attrs, handles);
486 
487     rc = ble_gattc_read_mult(2, handles, num_attrs,
488                              ble_gatt_read_test_cb, NULL);
489     TEST_ASSERT_FATAL(rc == 0);
490 
491     ble_gatt_read_test_misc_rx_rsp_bad(2, att_status, err_handle);
492 
493     TEST_ASSERT(ble_gatt_read_test_num_attrs == 0);
494     TEST_ASSERT(ble_gatt_read_test_bad_conn_handle == 2);
495     TEST_ASSERT(ble_gatt_read_test_bad_status ==
496                 BLE_HS_ERR_ATT_BASE + att_status);
497     TEST_ASSERT(!ble_gattc_any_jobs());
498 }
499 
TEST_CASE(ble_gatt_read_test_by_handle)500 TEST_CASE(ble_gatt_read_test_by_handle)
501 {
502     /* Read a seven-byte attribute. */
503     ble_gatt_read_test_misc_verify_good(
504         (struct ble_hs_test_util_flat_attr[]) { {
505         .handle = 43,
506         .value = { 1,2,3,4,5,6,7 },
507         .value_len = 7
508     } });
509 
510     /* Read a one-byte attribute. */
511     ble_gatt_read_test_misc_verify_good(
512         (struct ble_hs_test_util_flat_attr[]) { {
513         .handle = 0x5432,
514         .value = { 0xff },
515         .value_len = 1
516     } });
517 
518     /* Read a 200-byte attribute. */
519     ble_gatt_read_test_misc_verify_good(
520         (struct ble_hs_test_util_flat_attr[]) { {
521         .handle = 815,
522         .value = { 0 },
523         .value_len = 200,
524     } });
525 
526     /* Fail due to attribute not found. */
527     ble_gatt_read_test_misc_verify_bad(BLE_ATT_ERR_ATTR_NOT_FOUND,
528         (struct ble_hs_test_util_flat_attr[]) { {
529             .handle = 719,
530             .value = { 1,2,3,4,5,6,7 },
531             .value_len = 7
532         } });
533 
534     /* Fail due to invalid PDU. */
535     ble_gatt_read_test_misc_verify_bad(BLE_ATT_ERR_INVALID_PDU,
536         (struct ble_hs_test_util_flat_attr[]) { {
537             .handle = 65,
538             .value = { 0xfa, 0x4c },
539             .value_len = 2
540         } });
541 }
542 
TEST_CASE(ble_gatt_read_test_by_uuid)543 TEST_CASE(ble_gatt_read_test_by_uuid)
544 {
545     /* Read a single seven-byte attribute. */
546     ble_gatt_read_test_misc_uuid_verify_good(1, 100, BLE_UUID16_DECLARE(0x1234), 0,
547         (struct ble_hs_test_util_flat_attr[]) { {
548             .handle = 43,
549             .value = { 1,2,3,4,5,6,7 },
550             .value_len = 7
551         }, {
552             0,
553         } });
554 
555     /* Read two seven-byte attributes; one response. */
556     ble_gatt_read_test_misc_uuid_verify_good(1, 100, BLE_UUID16_DECLARE(0x1234), 0,
557         (struct ble_hs_test_util_flat_attr[]) { {
558             .handle = 43,
559             .value = { 1,2,3,4,5,6,7 },
560             .value_len = 7
561         }, {
562             .handle = 44,
563             .value = { 2,3,4,5,6,7,8 },
564             .value_len = 7
565         }, {
566             0,
567         } });
568 
569     /* Read two attributes; two responses. */
570     ble_gatt_read_test_misc_uuid_verify_good(1, 100, BLE_UUID16_DECLARE(0x1234), 0,
571         (struct ble_hs_test_util_flat_attr[]) { {
572             .handle = 43,
573             .value = { 1,2,3,4,5,6,7 },
574             .value_len = 7
575         }, {
576             .handle = 44,
577             .value = { 2,3,4 },
578             .value_len = 3
579         }, {
580             0,
581         } });
582 
583     /* Stop after three reads. */
584     ble_gatt_read_test_misc_uuid_verify_good(1, 100, BLE_UUID16_DECLARE(0x1234), 3,
585         (struct ble_hs_test_util_flat_attr[]) { {
586             .handle = 43,
587             .value = { 1,2,3,4,5,6,7 },
588             .value_len = 7
589         }, {
590             .handle = 44,
591             .value = { 2,3,4 },
592             .value_len = 3
593         }, {
594             .handle = 45,
595             .value = { 2,3,4 },
596             .value_len = 3
597         }, {
598             .handle = 46,
599             .value = { 3,4,5,6 },
600             .value_len = 4
601         }, {
602             .handle = 47,
603             .value = { 2,3,4 },
604             .value_len = 3
605         }, {
606             0,
607         } });
608 }
609 
TEST_CASE(ble_gatt_read_test_long)610 TEST_CASE(ble_gatt_read_test_long)
611 {
612     uint8_t data512[512];
613     int i;
614 
615     for (i = 0; i < sizeof data512; i++) {
616         data512[i] = i;
617     }
618 
619     /* Read a seven-byte attribute. */
620     ble_gatt_read_test_misc_long_verify_good(0,
621         (struct ble_hs_test_util_flat_attr[]) { {
622         .handle = 43,
623         .value = { 1,2,3,4,5,6,7 },
624         .value_len = 7
625     } });
626 
627     /* Read a zero-byte attribute. */
628     ble_gatt_read_test_misc_long_verify_good(0,
629         (struct ble_hs_test_util_flat_attr[]) { {
630         .handle = 43,
631         .value = { 0 },
632         .value_len = 0
633     } });
634 
635     /* Read a 60-byte attribute; three requests. */
636     ble_gatt_read_test_misc_long_verify_good(0,
637         (struct ble_hs_test_util_flat_attr[]) { {
638         .handle = 34,
639         .value = {
640             1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
641             17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
642             33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
643             49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60
644         },
645         .value_len = 60
646     } });
647 
648     /* Stop after two reads. */
649     ble_gatt_read_test_misc_long_verify_good(2,
650         (struct ble_hs_test_util_flat_attr[]) { {
651         .handle = 34,
652         .value = {
653             1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
654             17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
655             33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
656             49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60
657         },
658         .value_len = 60
659     } });
660 
661     /* Fail due to attribute not found. */
662     ble_gatt_read_test_misc_long_verify_bad(BLE_ATT_ERR_ATTR_NOT_FOUND,
663         (struct ble_hs_test_util_flat_attr[]) { {
664             .handle = 719,
665             .value = { 1, 2, 3, 4, 5, 6, 7 },
666             .value_len = 7
667         } });
668 }
669 
TEST_CASE(ble_gatt_read_test_mult)670 TEST_CASE(ble_gatt_read_test_mult)
671 {
672     uint8_t data512[512];
673     int i;
674 
675     for (i = 0; i < sizeof data512; i++) {
676         data512[i] = i;
677     }
678 
679     /* Read one attribute. */
680     ble_gatt_read_test_misc_mult_verify_good(
681         (struct ble_hs_test_util_flat_attr[]) { {
682         .handle = 43,
683         .value = { 0, 1, 2, 3, 4, 5, 6, 7 },
684         .value_len = 7
685     }, {
686         0
687     } });
688 
689     /* Read two attributes. */
690     ble_gatt_read_test_misc_mult_verify_good(
691         (struct ble_hs_test_util_flat_attr[]) { {
692         .handle = 43,
693         .value = { 0, 1, 2, 3, 4, 5, 6, 7 },
694         .value_len = 7,
695     }, {
696         .handle = 44,
697         .value = { 8, 9, 10, 11 },
698         .value_len = 4,
699     }, {
700         0
701     } });
702 
703     /* Read two attributes (swap order). */
704     ble_gatt_read_test_misc_mult_verify_good(
705         (struct ble_hs_test_util_flat_attr[]) { {
706         .handle = 44,
707         .value = { 8, 9, 10, 11 },
708         .value_len = 4,
709     }, {
710         .handle = 43,
711         .value = { 0, 1, 2, 3, 4, 5, 6, 7 },
712         .value_len = 7,
713     }, {
714         0
715     } });
716 
717     /* Read five attributes. */
718     ble_gatt_read_test_misc_mult_verify_good(
719         (struct ble_hs_test_util_flat_attr[]) { {
720         .handle = 43,
721         .value = { 0, 1, 2, 3, 4, 5, 6, 7 },
722         .value_len = 7,
723     }, {
724         .handle = 44,
725         .value = { 8, 9, 10, 11 },
726         .value_len = 4,
727     }, {
728         .handle = 145,
729         .value = { 12, 13 },
730         .value_len = 2,
731     }, {
732         .handle = 191,
733         .value = { 14, 15, 16 },
734         .value_len = 3,
735     }, {
736         .handle = 352,
737         .value = { 17, 18, 19, 20 },
738         .value_len = 4,
739     }, {
740         0
741     } });
742 
743     /* Fail due to attribute not found. */
744     ble_gatt_read_test_misc_mult_verify_bad(BLE_ATT_ERR_ATTR_NOT_FOUND, 719,
745         (struct ble_hs_test_util_flat_attr[]) { {
746             .handle = 719,
747             .value = { 1,2,3,4,5,6,7 },
748             .value_len = 7
749         }, {
750             0
751         } });
752 }
753 
TEST_CASE(ble_gatt_read_test_concurrent)754 TEST_CASE(ble_gatt_read_test_concurrent)
755 {
756     int rc;
757     int i;
758 
759     ble_gatt_read_test_misc_init();
760     ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
761                                  NULL, NULL);
762 
763     /***
764      * Perform three concurrent reads.  Assert that each response is correctly
765      * matched up with its corresponding GATT procedure.
766      */
767 
768     struct ble_hs_test_util_flat_attr attrs[3] = {
769         {
770             .handle = 1,
771             .offset = 0,
772             .value_len = 3,
773             .value = { 1, 2, 3 },
774         },
775         {
776             .handle = 2,
777             .offset = 0,
778             .value_len = 4,
779             .value = { 2, 3, 4, 5 },
780         },
781         {
782             .handle = 3,
783             .offset = 0,
784             .value_len = 5,
785             .value = { 3, 4, 5, 6, 7 },
786         },
787     };
788 
789     rc = ble_gattc_read(2, attrs[0].handle, ble_gatt_read_test_cb, NULL);
790     TEST_ASSERT_FATAL(rc == 0);
791     rc = ble_gattc_read(2, attrs[1].handle, ble_gatt_read_test_cb, NULL);
792     TEST_ASSERT_FATAL(rc == 0);
793     rc = ble_gattc_read(2, attrs[2].handle, ble_gatt_read_test_cb, NULL);
794     TEST_ASSERT_FATAL(rc == 0);
795 
796     ble_gatt_read_test_misc_rx_rsp_good(2, attrs + 0);
797     ble_gatt_read_test_misc_rx_rsp_good(2, attrs + 1);
798     ble_gatt_read_test_misc_rx_rsp_good(2, attrs + 2);
799 
800     TEST_ASSERT(ble_gatt_read_test_num_attrs == 3);
801 
802     for (i = 0; i < 3; i++) {
803         TEST_ASSERT(ble_gatt_read_test_attrs[i].handle == attrs[i].handle);
804         TEST_ASSERT(ble_gatt_read_test_attrs[i].value_len ==
805                     attrs[i].value_len);
806         TEST_ASSERT(memcmp(ble_gatt_read_test_attrs[i].value, attrs[i].value,
807                            attrs[i].value_len) == 0);
808     }
809 }
810 
TEST_CASE(ble_gatt_read_test_long_oom)811 TEST_CASE(ble_gatt_read_test_long_oom)
812 {
813     static const struct ble_hs_test_util_flat_attr attr = {
814         .handle = 34,
815         .value = {
816             1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
817             17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
818             33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
819             49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60
820         },
821         .value_len = 60,
822     };
823 
824     struct os_mbuf *oms;
825     int32_t ticks_until;
826     int reads_left;
827     int chunk_sz;
828     uint16_t offset = 0;
829     int off;
830     int rc;
831 
832     ble_gatt_read_test_misc_init();
833     ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
834                                  NULL, NULL);
835 
836     /* Initiate a read long procedure. */
837     off = 0;
838     reads_left = 0;
839     rc = ble_gattc_read_long(2, attr.handle, offset, ble_gatt_read_test_long_cb,
840                              &reads_left);
841     TEST_ASSERT_FATAL(rc == 0);
842 
843     /* Exhaust the msys pool.  Leave one mbuf for the forthcoming response. */
844     oms = ble_hs_test_util_mbuf_alloc_all_but(1);
845     chunk_sz = ble_att_mtu(2) - BLE_ATT_READ_RSP_BASE_SZ;
846     ble_gatt_read_test_misc_rx_rsp_good_raw(2, BLE_ATT_OP_READ_RSP,
847                                             attr.value + off, chunk_sz);
848     off += chunk_sz;
849 
850     /* Ensure no follow-up request got sent.  It should not have gotten sent
851      * due to mbuf exhaustion.
852      */
853     ble_hs_test_util_prev_tx_queue_clear();
854     TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue_pullup() == NULL);
855 
856     /* Verify that we will resume the stalled GATT procedure in one second. */
857     ticks_until = ble_gattc_timer();
858     TEST_ASSERT(ticks_until == os_time_ms_to_ticks32(MYNEWT_VAL(BLE_GATT_RESUME_RATE)));
859 
860     /* Verify the procedure proceeds after mbufs become available. */
861     rc = os_mbuf_free_chain(oms);
862     TEST_ASSERT_FATAL(rc == 0);
863     os_time_advance(ticks_until);
864     ble_gattc_timer();
865 
866     /* Exhaust the msys pool.  Leave one mbuf for the forthcoming response. */
867     oms = ble_hs_test_util_mbuf_alloc_all_but(1);
868     chunk_sz = ble_att_mtu(2) - BLE_ATT_READ_RSP_BASE_SZ;
869     ble_gatt_read_test_misc_rx_rsp_good_raw(2, BLE_ATT_OP_READ_RSP,
870                                             attr.value + off, chunk_sz);
871     off += chunk_sz;
872 
873     /* Ensure no follow-up request got sent.  It should not have gotten sent
874      * due to mbuf exhaustion.
875      */
876     ble_hs_test_util_prev_tx_queue_clear();
877     TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue_pullup() == NULL);
878 
879     /* Verify that we will resume the stalled GATT procedure in one second. */
880     ticks_until = ble_gattc_timer();
881     TEST_ASSERT(ticks_until == os_time_ms_to_ticks32(MYNEWT_VAL(BLE_GATT_RESUME_RATE)));
882 
883     /* Verify that procedure completes when mbufs are available. */
884     rc = os_mbuf_free_chain(oms);
885     TEST_ASSERT_FATAL(rc == 0);
886     os_time_advance(ticks_until);
887     ble_gattc_timer();
888 
889     chunk_sz = attr.value_len - off;
890     ble_gatt_read_test_misc_rx_rsp_good_raw(2, BLE_ATT_OP_READ_RSP,
891                                             attr.value + off, chunk_sz);
892     off += chunk_sz;
893 
894     TEST_ASSERT(ble_gatt_read_test_complete);
895     TEST_ASSERT(!ble_gattc_any_jobs());
896     TEST_ASSERT(ble_gatt_read_test_attrs[0].conn_handle == 2);
897     TEST_ASSERT(ble_gatt_read_test_attrs[0].handle == attr.handle);
898     TEST_ASSERT(ble_gatt_read_test_attrs[0].value_len == attr.value_len);
899     TEST_ASSERT(memcmp(ble_gatt_read_test_attrs[0].value, attr.value,
900                        ble_gatt_read_test_attrs[0].value_len) == 0);
901 }
902 
TEST_SUITE(ble_gatt_read_test_suite)903 TEST_SUITE(ble_gatt_read_test_suite)
904 {
905     tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
906 
907     ble_gatt_read_test_by_handle();
908     ble_gatt_read_test_by_uuid();
909     ble_gatt_read_test_long();
910     ble_gatt_read_test_mult();
911     ble_gatt_read_test_concurrent();
912     ble_gatt_read_test_long_oom();
913 }
914 
915 int
ble_gatt_read_test_all(void)916 ble_gatt_read_test_all(void)
917 {
918     ble_gatt_read_test_suite();
919 
920     return tu_any_failed;
921 }
922