xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/host/test/src/ble_gatt_disc_c_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_gatt.h"
27 #include "host/ble_uuid.h"
28 #include "ble_hs_test_util.h"
29 
30 struct ble_gatt_disc_c_test_char {
31     uint16_t def_handle;
32     uint16_t val_handle;
33     uint8_t properties;
34     const ble_uuid_t *uuid;
35 };
36 
37 #define BLE_GATT_DISC_C_TEST_MAX_CHARS  256
38 static struct ble_gatt_chr
39     ble_gatt_disc_c_test_chars[BLE_GATT_DISC_C_TEST_MAX_CHARS];
40 static int ble_gatt_disc_c_test_num_chars;
41 static int ble_gatt_disc_c_test_rx_complete;
42 
43 static void
ble_gatt_disc_c_test_init(void)44 ble_gatt_disc_c_test_init(void)
45 {
46     ble_hs_test_util_init();
47 
48     ble_gatt_disc_c_test_num_chars = 0;
49     ble_gatt_disc_c_test_rx_complete = 0;
50 }
51 
52 static int
ble_gatt_disc_c_test_misc_rx_rsp_once(uint16_t conn_handle,struct ble_gatt_disc_c_test_char * chars)53 ble_gatt_disc_c_test_misc_rx_rsp_once(
54     uint16_t conn_handle, struct ble_gatt_disc_c_test_char *chars)
55 {
56     struct ble_att_read_type_rsp rsp;
57     uint8_t buf[1024];
58     int off;
59     int rc;
60     int i;
61 
62     /* Send the pending ATT Read By Type Request. */
63 
64     if (chars[0].uuid->type == BLE_UUID_TYPE_16) {
65        rsp.batp_length = BLE_ATT_READ_TYPE_ADATA_BASE_SZ +
66                          BLE_GATT_CHR_DECL_SZ_16;
67     } else {
68        rsp.batp_length = BLE_ATT_READ_TYPE_ADATA_BASE_SZ +
69                          BLE_GATT_CHR_DECL_SZ_128;
70     }
71 
72     ble_att_read_type_rsp_write(buf, BLE_ATT_READ_TYPE_RSP_BASE_SZ, &rsp);
73 
74     off = BLE_ATT_READ_TYPE_RSP_BASE_SZ;
75     for (i = 0; ; i++) {
76         if (chars[i].def_handle == 0) {
77             /* No more services. */
78             break;
79         }
80 
81         /* If the value length is changing, we need a separate response. */
82         if (((chars[i].uuid->type == BLE_UUID_TYPE_16) ^
83             (chars[0].uuid->type == BLE_UUID_TYPE_16)) != 0) {
84             break;
85         }
86 
87         if (chars[i].uuid->type == BLE_UUID_TYPE_16) {
88             if (off + BLE_ATT_READ_TYPE_ADATA_SZ_16 >
89                 ble_att_mtu(conn_handle)) {
90 
91                 /* Can't fit any more entries. */
92                 break;
93             }
94         } else {
95             if (off + BLE_ATT_READ_TYPE_ADATA_SZ_128 >
96                 ble_att_mtu(conn_handle)) {
97 
98                 /* Can't fit any more entries. */
99                 break;
100             }
101         }
102 
103         put_le16(buf + off, chars[i].def_handle);
104         off += 2;
105 
106         buf[off] = chars[i].properties;
107         off++;
108 
109         put_le16(buf + off, chars[i].val_handle);
110         off += 2;
111 
112         ble_uuid_flat(chars[i].uuid, buf + off);
113         off += ble_uuid_length(chars[i].uuid);
114     }
115 
116     rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
117                                                 buf, off);
118     TEST_ASSERT(rc == 0);
119 
120     return i;
121 }
122 
123 static void
ble_gatt_disc_c_test_misc_rx_rsp(uint16_t conn_handle,uint16_t end_handle,struct ble_gatt_disc_c_test_char * chars)124 ble_gatt_disc_c_test_misc_rx_rsp(uint16_t conn_handle,
125                                  uint16_t end_handle,
126                                  struct ble_gatt_disc_c_test_char *chars)
127 {
128     int count;
129     int idx;
130 
131     idx = 0;
132     while (chars[idx].def_handle != 0) {
133         count = ble_gatt_disc_c_test_misc_rx_rsp_once(conn_handle,
134                                                       chars + idx);
135         if (count == 0) {
136             break;
137         }
138         idx += count;
139     }
140 
141     if (chars[idx - 1].def_handle != end_handle) {
142         /* Send the pending ATT Request. */
143         ble_hs_test_util_rx_att_err_rsp(conn_handle, BLE_ATT_OP_READ_TYPE_REQ,
144                                         BLE_ATT_ERR_ATTR_NOT_FOUND,
145                                         chars[idx - 1].def_handle);
146     }
147 }
148 
149 static void
ble_gatt_disc_c_test_misc_verify_chars(struct ble_gatt_disc_c_test_char * chars,int stop_after)150 ble_gatt_disc_c_test_misc_verify_chars(struct ble_gatt_disc_c_test_char *chars,
151                                        int stop_after)
152 {
153     int i;
154 
155     if (stop_after == 0) {
156         stop_after = BLE_GATT_DISC_C_TEST_MAX_CHARS;
157     }
158 
159     for (i = 0; i < stop_after && chars[i].def_handle != 0; i++) {
160         TEST_ASSERT(chars[i].def_handle ==
161                     ble_gatt_disc_c_test_chars[i].def_handle);
162         TEST_ASSERT(chars[i].val_handle ==
163                     ble_gatt_disc_c_test_chars[i].val_handle);
164         TEST_ASSERT(ble_uuid_cmp(chars[i].uuid,
165                                  &ble_gatt_disc_c_test_chars[i].uuid.u) == 0);
166     }
167 
168     TEST_ASSERT(i == ble_gatt_disc_c_test_num_chars);
169     TEST_ASSERT(ble_gatt_disc_c_test_rx_complete);
170 }
171 
172 static int
ble_gatt_disc_c_test_misc_cb(uint16_t conn_handle,const struct ble_gatt_error * error,const struct ble_gatt_chr * chr,void * arg)173 ble_gatt_disc_c_test_misc_cb(uint16_t conn_handle,
174                              const struct ble_gatt_error *error,
175                              const struct ble_gatt_chr *chr, void *arg)
176 {
177     struct ble_gatt_chr *dst;
178     int *stop_after;
179 
180     TEST_ASSERT(error != NULL);
181     TEST_ASSERT(!ble_gatt_disc_c_test_rx_complete);
182 
183     stop_after = arg;
184 
185     switch (error->status) {
186     case 0:
187         TEST_ASSERT_FATAL(ble_gatt_disc_c_test_num_chars <
188                           BLE_GATT_DISC_C_TEST_MAX_CHARS);
189 
190         dst = ble_gatt_disc_c_test_chars + ble_gatt_disc_c_test_num_chars++;
191         *dst = *chr;
192         break;
193 
194     case BLE_HS_EDONE:
195         ble_gatt_disc_c_test_rx_complete = 1;
196         break;
197 
198     default:
199         TEST_ASSERT(0);
200         break;
201     }
202 
203     if (*stop_after > 0) {
204         (*stop_after)--;
205         if (*stop_after == 0) {
206             ble_gatt_disc_c_test_rx_complete = 1;
207             return 1;
208         }
209     }
210 
211     return 0;
212 }
213 
214 static void
ble_gatt_disc_c_test_misc_all(uint16_t start_handle,uint16_t end_handle,int stop_after,struct ble_gatt_disc_c_test_char * chars)215 ble_gatt_disc_c_test_misc_all(uint16_t start_handle, uint16_t end_handle,
216                               int stop_after,
217                               struct ble_gatt_disc_c_test_char *chars)
218 {
219     int num_left;
220     int rc;
221 
222     ble_gatt_disc_c_test_init();
223 
224     ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
225                                  NULL, NULL);
226 
227     num_left = stop_after;
228     rc = ble_gattc_disc_all_chrs(2, start_handle, end_handle,
229                                  ble_gatt_disc_c_test_misc_cb, &num_left);
230     TEST_ASSERT(rc == 0);
231 
232     ble_gatt_disc_c_test_misc_rx_rsp(2, end_handle, chars);
233     ble_gatt_disc_c_test_misc_verify_chars(chars, stop_after);
234 }
235 
236 static void
ble_gatt_disc_c_test_misc_uuid(uint16_t start_handle,uint16_t end_handle,int stop_after,const ble_uuid_t * uuid,struct ble_gatt_disc_c_test_char * rsp_chars,struct ble_gatt_disc_c_test_char * ret_chars)237 ble_gatt_disc_c_test_misc_uuid(uint16_t start_handle, uint16_t end_handle,
238                                int stop_after, const ble_uuid_t *uuid,
239                                struct ble_gatt_disc_c_test_char *rsp_chars,
240                                struct ble_gatt_disc_c_test_char *ret_chars)
241 {
242     int rc;
243 
244     ble_gatt_disc_c_test_init();
245 
246     ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
247                                  NULL, NULL);
248 
249     rc = ble_gattc_disc_chrs_by_uuid(2, start_handle, end_handle,
250                                      uuid,
251                                      ble_gatt_disc_c_test_misc_cb,
252                                      &stop_after);
253     TEST_ASSERT(rc == 0);
254 
255     ble_gatt_disc_c_test_misc_rx_rsp(2, end_handle, rsp_chars);
256     ble_gatt_disc_c_test_misc_verify_chars(ret_chars, 0);
257 }
258 
TEST_CASE(ble_gatt_disc_c_test_disc_all)259 TEST_CASE(ble_gatt_disc_c_test_disc_all)
260 {
261     /*** One 16-bit characteristic. */
262     ble_gatt_disc_c_test_misc_all(50, 100, 0,
263                                   (struct ble_gatt_disc_c_test_char[]) {
264         {
265             .def_handle = 55,
266             .val_handle = 56,
267             .uuid = BLE_UUID16_DECLARE(0x2010),
268         }, { 0 }
269     });
270 
271     /*** Two 16-bit characteristics. */
272     ble_gatt_disc_c_test_misc_all(50, 100, 0,
273                                   (struct ble_gatt_disc_c_test_char[]) {
274         {
275             .def_handle = 55,
276             .val_handle = 56,
277             .uuid = BLE_UUID16_DECLARE(0x2010),
278         }, {
279             .def_handle = 57,
280             .val_handle = 58,
281             .uuid = BLE_UUID16_DECLARE(0x64ba),
282         }, { 0 }
283     });
284 
285     /*** Five 16-bit characteristics. */
286     ble_gatt_disc_c_test_misc_all(50, 100, 0,
287                                   (struct ble_gatt_disc_c_test_char[]) {
288         {
289             .def_handle = 55,
290             .val_handle = 56,
291             .uuid = BLE_UUID16_DECLARE(0x2010),
292         }, {
293             .def_handle = 57,
294             .val_handle = 58,
295             .uuid = BLE_UUID16_DECLARE(0x64ba),
296         }, {
297             .def_handle = 59,
298             .val_handle = 60,
299             .uuid = BLE_UUID16_DECLARE(0x5372),
300         }, {
301             .def_handle = 61,
302             .val_handle = 62,
303             .uuid = BLE_UUID16_DECLARE(0xab93),
304         }, {
305             .def_handle = 63,
306             .val_handle = 64,
307             .uuid = BLE_UUID16_DECLARE(0x0023),
308         }, { 0 }
309     });
310 
311     /*** Interleaved 16-bit and 128-bit characteristics. */
312     ble_gatt_disc_c_test_misc_all(50, 100, 0,
313                                   (struct ble_gatt_disc_c_test_char[]) {
314         {
315             .def_handle = 83,
316             .val_handle = 84,
317             .uuid = BLE_UUID16_DECLARE(0x2010),
318         }, {
319             .def_handle = 87,
320             .val_handle = 88,
321             .uuid = BLE_UUID128_DECLARE(0, 1, 2, 3, 4, 5, 6, 7,
322                                         8, 9, 10, 11, 12, 13, 14, 15),
323         }, {
324             .def_handle = 91,
325             .val_handle = 92,
326             .uuid = BLE_UUID16_DECLARE(0x0003),
327         }, {
328             .def_handle = 93,
329             .val_handle = 94,
330             .uuid = BLE_UUID128_DECLARE(1, 0, 4, 0, 6, 9, 17, 7,
331                                         8, 43, 7, 4, 12, 43, 19, 35),
332         }, {
333             .def_handle = 98,
334             .val_handle = 99,
335             .uuid = BLE_UUID16_DECLARE(0xabfa),
336         }, { 0 }
337     });
338 
339     /*** Ends with final handle ID. */
340     ble_gatt_disc_c_test_misc_all(50, 100, 0,
341                                   (struct ble_gatt_disc_c_test_char[]) {
342         {
343             .def_handle = 55,
344             .val_handle = 56,
345             .uuid = BLE_UUID16_DECLARE(0x2010),
346         }, {
347             .def_handle = 99,
348             .val_handle = 100,
349             .uuid = BLE_UUID16_DECLARE(0x64ba),
350         }, { 0 }
351     });
352 
353     /*** Stop after two characteristics. */
354     ble_gatt_disc_c_test_misc_all(50, 100, 2,
355                                   (struct ble_gatt_disc_c_test_char[]) {
356         {
357             .def_handle = 55,
358             .val_handle = 56,
359             .uuid = BLE_UUID16_DECLARE(0x2010),
360         }, {
361             .def_handle = 57,
362             .val_handle = 58,
363             .uuid = BLE_UUID16_DECLARE(0x64ba),
364         }, {
365             .def_handle = 59,
366             .val_handle = 60,
367             .uuid = BLE_UUID16_DECLARE(0x5372),
368         }, {
369             .def_handle = 61,
370             .val_handle = 62,
371             .uuid = BLE_UUID16_DECLARE(0xab93),
372         }, {
373             .def_handle = 63,
374             .val_handle = 64,
375             .uuid = BLE_UUID16_DECLARE(0x0023),
376         }, { 0 }
377     });
378 }
379 
TEST_CASE(ble_gatt_disc_c_test_disc_uuid)380 TEST_CASE(ble_gatt_disc_c_test_disc_uuid)
381 {
382     /*** One 16-bit characteristic. */
383     ble_gatt_disc_c_test_misc_uuid(50, 100, 0, BLE_UUID16_DECLARE(0x2010),
384         (struct ble_gatt_disc_c_test_char[]) {
385         {
386             .def_handle = 55,
387             .val_handle = 56,
388             .uuid = BLE_UUID16_DECLARE(0x2010),
389         }, { 0 } },
390         (struct ble_gatt_disc_c_test_char[]) {
391         {
392             .def_handle = 55,
393             .val_handle = 56,
394             .uuid = BLE_UUID16_DECLARE(0x2010),
395         }, { 0 } }
396     );
397 
398     /*** No matching characteristics. */
399     ble_gatt_disc_c_test_misc_uuid(50, 100, 0, BLE_UUID16_DECLARE(0x2010),
400         (struct ble_gatt_disc_c_test_char[]) {
401         {
402             .def_handle = 55,
403             .val_handle = 56,
404             .uuid = BLE_UUID16_DECLARE(0x1234),
405         }, { 0 } },
406         (struct ble_gatt_disc_c_test_char[]) {
407         { 0 } }
408     );
409 
410     /*** 2/5 16-bit characteristics. */
411     ble_gatt_disc_c_test_misc_uuid(50, 100, 0, BLE_UUID16_DECLARE(0x2010),
412         (struct ble_gatt_disc_c_test_char[]) {
413         {
414             .def_handle = 55,
415             .val_handle = 56,
416             .uuid = BLE_UUID16_DECLARE(0x2010),
417         }, {
418             .def_handle = 57,
419             .val_handle = 58,
420             .uuid = BLE_UUID16_DECLARE(0x64ba),
421         }, {
422             .def_handle = 59,
423             .val_handle = 60,
424             .uuid = BLE_UUID16_DECLARE(0x5372),
425         }, {
426             .def_handle = 61,
427             .val_handle = 62,
428             .uuid = BLE_UUID16_DECLARE(0x2010),
429         }, {
430             .def_handle = 63,
431             .val_handle = 64,
432             .uuid = BLE_UUID16_DECLARE(0x0023),
433         }, { 0 } },
434         (struct ble_gatt_disc_c_test_char[]) {
435         {
436             .def_handle = 55,
437             .val_handle = 56,
438             .uuid = BLE_UUID16_DECLARE(0x2010),
439         }, {
440             .def_handle = 61,
441             .val_handle = 62,
442             .uuid = BLE_UUID16_DECLARE(0x2010),
443         }, { 0 } }
444     );
445 
446     /*** Interleaved 16-bit and 128-bit characteristics. */
447     ble_gatt_disc_c_test_misc_uuid(
448         50, 100, 0,
449         BLE_UUID128_DECLARE(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15),
450         (struct ble_gatt_disc_c_test_char[]) {
451         {
452             .def_handle = 83,
453             .val_handle = 84,
454             .uuid = BLE_UUID16_DECLARE(0x2010),
455         }, {
456             .def_handle = 87,
457             .val_handle = 88,
458             .uuid = BLE_UUID128_DECLARE(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15),
459         }, {
460             .def_handle = 91,
461             .val_handle = 92,
462             .uuid = BLE_UUID16_DECLARE(0x0003),
463         }, {
464             .def_handle = 93,
465             .val_handle = 94,
466             .uuid = BLE_UUID128_DECLARE(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15),
467         }, {
468             .def_handle = 98,
469             .val_handle = 99,
470             .uuid = BLE_UUID16_DECLARE(0xabfa),
471         }, { 0 } },
472         (struct ble_gatt_disc_c_test_char[]) {
473         {
474             .def_handle = 87,
475             .val_handle = 88,
476             .uuid = BLE_UUID128_DECLARE(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15),
477         }, {
478             .def_handle = 93,
479             .val_handle = 94,
480             .uuid = BLE_UUID128_DECLARE(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15),
481         }, { 0 } }
482     );
483 
484     /*** Ends with final handle ID. */
485     ble_gatt_disc_c_test_misc_uuid(50, 100, 0, BLE_UUID16_DECLARE(0x64ba),
486         (struct ble_gatt_disc_c_test_char[]) {
487         {
488             .def_handle = 55,
489             .val_handle = 56,
490             .uuid = BLE_UUID16_DECLARE(0x2010),
491         }, {
492             .def_handle = 99,
493             .val_handle = 100,
494             .uuid = BLE_UUID16_DECLARE(0x64ba),
495         }, { 0 } },
496         (struct ble_gatt_disc_c_test_char[]) {
497         {
498             .def_handle = 99,
499             .val_handle = 100,
500             .uuid = BLE_UUID16_DECLARE(0x64ba),
501         }, { 0 } }
502     );
503 
504     /*** Stop after first characteristic. */
505     ble_gatt_disc_c_test_misc_uuid(50, 100, 1, BLE_UUID16_DECLARE(0x2010),
506         (struct ble_gatt_disc_c_test_char[]) {
507         {
508             .def_handle = 55,
509             .val_handle = 56,
510             .uuid = BLE_UUID16_DECLARE(0x2010),
511         }, {
512             .def_handle = 57,
513             .val_handle = 58,
514             .uuid = BLE_UUID16_DECLARE(0x64ba),
515         }, {
516             .def_handle = 59,
517             .val_handle = 60,
518             .uuid = BLE_UUID16_DECLARE(0x5372),
519         }, {
520             .def_handle = 61,
521             .val_handle = 62,
522             .uuid = BLE_UUID16_DECLARE(0x2010),
523         }, {
524             .def_handle = 63,
525             .val_handle = 64,
526             .uuid = BLE_UUID16_DECLARE(0x0023),
527         }, { 0 } },
528         (struct ble_gatt_disc_c_test_char[]) {
529         {
530             .def_handle = 55,
531             .val_handle = 56,
532             .uuid = BLE_UUID16_DECLARE(0x2010),
533         }, { 0 } }
534     );
535 }
536 
TEST_CASE(ble_gatt_disc_c_test_oom_all)537 TEST_CASE(ble_gatt_disc_c_test_oom_all)
538 {
539     /* Retrieve enough characteristics to require two transactions. */
540     struct ble_gatt_disc_c_test_char chrs[] = {
541         {
542             .def_handle = 93,
543             .val_handle = 94,
544             .uuid = BLE_UUID128_DECLARE(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15),
545         },
546         {
547             .def_handle = 95,
548             .val_handle = 96,
549             .uuid = BLE_UUID128_DECLARE(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16),
550         },
551         { 0 }
552     };
553 
554     struct os_mbuf *oms;
555     int32_t ticks_until;
556     int stop_after;
557     int num_chrs;
558     int rc;
559 
560     ble_gatt_disc_c_test_init();
561 
562     ble_hs_test_util_create_conn(1, ((uint8_t[]){2,3,4,5,6,7,8,9}),
563                                  NULL, NULL);
564 
565     /* Initiate a discover all characteristics procedure. */
566     stop_after = 0;
567     rc = ble_gattc_disc_all_chrs(1, 1, 0xffff,
568                                  ble_gatt_disc_c_test_misc_cb, &stop_after);
569     TEST_ASSERT_FATAL(rc == 0);
570 
571     /* Exhaust the msys pool.  Leave one mbuf for the forthcoming response. */
572     oms = ble_hs_test_util_mbuf_alloc_all_but(1);
573     num_chrs = ble_gatt_disc_c_test_misc_rx_rsp_once(1, chrs);
574 
575     /* Make sure there are still undiscovered characteristics. */
576     TEST_ASSERT_FATAL(num_chrs < sizeof chrs / sizeof chrs[0] - 1);
577 
578     /* Ensure no follow-up request got sent.  It should not have gotten sent
579      * due to mbuf exhaustion.
580      */
581     ble_hs_test_util_prev_tx_queue_clear();
582     TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue_pullup() == NULL);
583 
584     /* Verify that we will resume the stalled GATT procedure in one second. */
585     ticks_until = ble_gattc_timer();
586     TEST_ASSERT(ticks_until == os_time_ms_to_ticks32(MYNEWT_VAL(BLE_GATT_RESUME_RATE)));
587 
588     /* Verify the procedure proceeds after mbufs become available. */
589     rc = os_mbuf_free_chain(oms);
590     TEST_ASSERT_FATAL(rc == 0);
591 
592     os_time_advance(ticks_until);
593     ble_gattc_timer();
594 
595     /* Exhaust the msys pool.  Leave one mbuf for the forthcoming response. */
596     oms = ble_hs_test_util_mbuf_alloc_all_but(1);
597     ble_gatt_disc_c_test_misc_rx_rsp_once(1, chrs + num_chrs);
598 
599     /* Ensure no follow-up request got sent.  It should not have gotten sent
600      * due to mbuf exhaustion.
601      */
602     ble_hs_test_util_prev_tx_queue_clear();
603     TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue_pullup() == NULL);
604 
605     /* Verify that we will resume the stalled GATT procedure in one second. */
606     ticks_until = ble_gattc_timer();
607     TEST_ASSERT(ticks_until == os_time_ms_to_ticks32(MYNEWT_VAL(BLE_GATT_RESUME_RATE)));
608 
609     /* Verify that procedure completes when mbufs are available. */
610     rc = os_mbuf_free_chain(oms);
611     TEST_ASSERT_FATAL(rc == 0);
612 
613     os_time_advance(ticks_until);
614     ble_gattc_timer();
615 
616     ble_hs_test_util_rx_att_err_rsp(1,
617                                     BLE_ATT_OP_READ_TYPE_REQ,
618                                     BLE_ATT_ERR_ATTR_NOT_FOUND,
619                                     1);
620     ble_gatt_disc_c_test_misc_verify_chars(chrs, 0);
621 }
622 
TEST_CASE(ble_gatt_disc_c_test_oom_uuid)623 TEST_CASE(ble_gatt_disc_c_test_oom_uuid)
624 {
625     /* Retrieve enough characteristics to require two transactions. */
626     struct ble_gatt_disc_c_test_char chrs[] = {
627         {
628             .def_handle = 93,
629             .val_handle = 94,
630             .uuid = BLE_UUID128_DECLARE(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15),
631         },
632         {
633             .def_handle = 95,
634             .val_handle = 96,
635             .uuid = BLE_UUID128_DECLARE(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15),
636         },
637         { 0 }
638     };
639 
640     struct os_mbuf *oms;
641     int32_t ticks_until;
642     int stop_after;
643     int num_chrs;
644     int rc;
645 
646     ble_gatt_disc_c_test_init();
647 
648     ble_hs_test_util_create_conn(1, ((uint8_t[]){2,3,4,5,6,7,8,9}),
649                                  NULL, NULL);
650 
651     /* Initiate a discover characteristics by UUID procedure. */
652     stop_after = 0;
653     rc = ble_gattc_disc_chrs_by_uuid(1, 1, 0xffff, chrs[0].uuid,
654                                      ble_gatt_disc_c_test_misc_cb,
655                                      &stop_after);
656     TEST_ASSERT_FATAL(rc == 0);
657 
658     /* Exhaust the msys pool.  Leave one mbuf for the forthcoming response. */
659     oms = ble_hs_test_util_mbuf_alloc_all_but(1);
660     num_chrs = ble_gatt_disc_c_test_misc_rx_rsp_once(1, chrs);
661 
662     /* Make sure there are still undiscovered characteristics. */
663     TEST_ASSERT_FATAL(num_chrs < sizeof chrs / sizeof chrs[0] - 1);
664 
665     /* Ensure no follow-up request got sent.  It should not have gotten sent
666      * due to mbuf exhaustion.
667      */
668     ble_hs_test_util_prev_tx_queue_clear();
669     TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue_pullup() == NULL);
670 
671     /* Verify that we will resume the stalled GATT procedure in one second. */
672     ticks_until = ble_gattc_timer();
673     TEST_ASSERT(ticks_until == os_time_ms_to_ticks32(MYNEWT_VAL(BLE_GATT_RESUME_RATE)));
674 
675     /* Verify the procedure proceeds after mbufs become available. */
676     rc = os_mbuf_free_chain(oms);
677     TEST_ASSERT_FATAL(rc == 0);
678     os_time_advance(ticks_until);
679     ble_gattc_timer();
680 
681     /* Exhaust the msys pool.  Leave one mbuf for the forthcoming response. */
682     oms = ble_hs_test_util_mbuf_alloc_all_but(1);
683     ble_gatt_disc_c_test_misc_rx_rsp_once(1, chrs + num_chrs);
684 
685     /* Ensure no follow-up request got sent.  It should not have gotten sent
686      * due to mbuf exhaustion.
687      */
688     ble_hs_test_util_prev_tx_queue_clear();
689     TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue_pullup() == NULL);
690 
691     /* Verify that we will resume the stalled GATT procedure in one second. */
692     ticks_until = ble_gattc_timer();
693     TEST_ASSERT(ticks_until == os_time_ms_to_ticks32(MYNEWT_VAL(BLE_GATT_RESUME_RATE)));
694 
695     /* Verify that procedure completes when mbufs are available. */
696     rc = os_mbuf_free_chain(oms);
697     TEST_ASSERT_FATAL(rc == 0);
698     os_time_advance(ticks_until);
699     ble_gattc_timer();
700 
701     ble_hs_test_util_rx_att_err_rsp(1,
702                                     BLE_ATT_OP_READ_TYPE_REQ,
703                                     BLE_ATT_ERR_ATTR_NOT_FOUND,
704                                     1);
705     ble_gatt_disc_c_test_misc_verify_chars(chrs, 0);
706 }
707 
TEST_SUITE(ble_gatt_disc_c_test_suite)708 TEST_SUITE(ble_gatt_disc_c_test_suite)
709 {
710     tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
711 
712     ble_gatt_disc_c_test_disc_all();
713     ble_gatt_disc_c_test_disc_uuid();
714     ble_gatt_disc_c_test_oom_all();
715     ble_gatt_disc_c_test_oom_uuid();
716 }
717 
718 int
ble_gatt_disc_c_test_all(void)719 ble_gatt_disc_c_test_all(void)
720 {
721     ble_gatt_disc_c_test_suite();
722     ble_gatt_disc_c_test_oom_all();
723 
724     return tu_any_failed;
725 }
726