xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/host/test/src/ble_gatt_write_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 "testutil/testutil.h"
23 #include "nimble/ble.h"
24 #include "host/ble_hs_test.h"
25 #include "host/ble_gatt.h"
26 #include "ble_hs_test_util.h"
27 
28 #define BLE_GATT_WRITE_TEST_MAX_ATTRS   128
29 
30 static int ble_gatt_write_test_cb_called;
31 
32 static uint8_t ble_gatt_write_test_attr_value[BLE_ATT_ATTR_MAX_LEN];
33 static struct ble_gatt_error ble_gatt_write_test_error;
34 
35 static struct ble_hs_test_util_flat_attr
36 ble_gatt_write_test_attrs[BLE_GATT_WRITE_TEST_MAX_ATTRS];
37 static int ble_gatt_write_test_num_attrs;
38 
39 static void
ble_gatt_write_test_init(void)40 ble_gatt_write_test_init(void)
41 {
42     int i;
43 
44     ble_hs_test_util_init();
45     ble_gatt_write_test_cb_called = 0;
46     ble_gatt_write_test_num_attrs = 0;
47 
48     for (i = 0; i < sizeof ble_gatt_write_test_attr_value; i++) {
49         ble_gatt_write_test_attr_value[i] = i;
50     }
51 }
52 
53 static int
ble_gatt_write_test_cb_good(uint16_t conn_handle,const struct ble_gatt_error * error,struct ble_gatt_attr * attr,void * arg)54 ble_gatt_write_test_cb_good(uint16_t conn_handle,
55                             const struct ble_gatt_error *error,
56                             struct ble_gatt_attr *attr, void *arg)
57 {
58     int *attr_len;
59 
60     attr_len = arg;
61 
62     TEST_ASSERT(error != NULL);
63     TEST_ASSERT(conn_handle == 2);
64 
65     ble_gatt_write_test_error = *error;
66 
67     if (attr_len != NULL) {
68         TEST_ASSERT(error->status == 0);
69         TEST_ASSERT(attr->handle == 100);
70     }
71 
72     ble_gatt_write_test_cb_called = 1;
73 
74     return 0;
75 }
76 
77 static void
ble_gatt_write_test_rx_rsp(uint16_t conn_handle)78 ble_gatt_write_test_rx_rsp(uint16_t conn_handle)
79 {
80     uint8_t op;
81     int rc;
82 
83     op = BLE_ATT_OP_WRITE_RSP;
84     rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
85                                                 &op, 1);
86     TEST_ASSERT(rc == 0);
87 }
88 
89 static void
ble_gatt_write_test_rx_prep_rsp(uint16_t conn_handle,uint16_t attr_handle,uint16_t offset,const void * attr_data,uint16_t attr_data_len)90 ble_gatt_write_test_rx_prep_rsp(uint16_t conn_handle, uint16_t attr_handle,
91                                 uint16_t offset,
92                                 const void *attr_data, uint16_t attr_data_len)
93 {
94     struct ble_att_prep_write_cmd rsp;
95     uint8_t buf[512];
96     int rc;
97 
98     rsp.bapc_handle = attr_handle;
99     rsp.bapc_offset = offset;
100     ble_att_prep_write_rsp_write(buf, sizeof buf, &rsp);
101 
102     memcpy(buf + BLE_ATT_PREP_WRITE_CMD_BASE_SZ, attr_data, attr_data_len);
103 
104     rc = ble_hs_test_util_l2cap_rx_payload_flat(
105         conn_handle, BLE_L2CAP_CID_ATT, buf,
106         BLE_ATT_PREP_WRITE_CMD_BASE_SZ + attr_data_len);
107     TEST_ASSERT(rc == 0);
108 }
109 
110 static void
ble_gatt_write_test_rx_exec_rsp(uint16_t conn_handle)111 ble_gatt_write_test_rx_exec_rsp(uint16_t conn_handle)
112 {
113     uint8_t op;
114     int rc;
115 
116     op = BLE_ATT_OP_EXEC_WRITE_RSP;
117     rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
118                                                 &op, 1);
119     TEST_ASSERT(rc == 0);
120 }
121 
122 static void
ble_gatt_write_test_misc_long_good(int attr_len)123 ble_gatt_write_test_misc_long_good(int attr_len)
124 {
125     uint16_t mtu;
126     int off;
127     int len;
128     int rc;
129 
130     ble_gatt_write_test_init();
131 
132     ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
133                                  NULL, NULL);
134 
135     mtu = ble_att_mtu(2);
136 
137     rc = ble_hs_test_util_gatt_write_long_flat(
138         2, 100, ble_gatt_write_test_attr_value, attr_len,
139         ble_gatt_write_test_cb_good, &attr_len);
140     TEST_ASSERT(rc == 0);
141 
142     off = 0;
143     while (off < attr_len) {
144         len = mtu - BLE_ATT_PREP_WRITE_CMD_BASE_SZ;
145         if (off + len > attr_len) {
146             len = attr_len - off;
147         }
148 
149         /* Send the pending ATT Prep Write Command. */
150         ble_hs_test_util_verify_tx_prep_write(
151             100, off, ble_gatt_write_test_attr_value + off, len);
152 
153         /* Receive Prep Write response. */
154         ble_gatt_write_test_rx_prep_rsp(
155             2, 100, off, ble_gatt_write_test_attr_value + off, len);
156 
157         /* Verify callback hasn't gotten called. */
158         TEST_ASSERT(!ble_gatt_write_test_cb_called);
159 
160         off += len;
161     }
162 
163     /* Verify execute write request sent. */
164     ble_hs_test_util_verify_tx_exec_write(BLE_ATT_EXEC_WRITE_F_EXECUTE);
165 
166     /* Receive Exec Write response. */
167     ble_gatt_write_test_rx_exec_rsp(2);
168 
169     /* Verify callback got called. */
170     TEST_ASSERT(ble_gatt_write_test_cb_called);
171 }
172 
173 typedef void ble_gatt_write_test_long_fail_fn(uint16_t conn_handle,
174                                               int off, int len);
175 
176 static void
ble_gatt_write_test_misc_long_bad(int attr_len,ble_gatt_write_test_long_fail_fn * cb)177 ble_gatt_write_test_misc_long_bad(int attr_len,
178                                   ble_gatt_write_test_long_fail_fn *cb)
179 {
180     uint16_t mtu;
181     int fail_now;
182     int off;
183     int len;
184     int rc;
185 
186     ble_gatt_write_test_init();
187 
188     ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
189                                  NULL, NULL);
190     mtu = ble_att_mtu(2);
191 
192     rc = ble_hs_test_util_gatt_write_long_flat(
193         2, 100, ble_gatt_write_test_attr_value, attr_len,
194         ble_gatt_write_test_cb_good, NULL);
195     TEST_ASSERT(rc == 0);
196 
197     fail_now = 0;
198     off = 0;
199     while (off < attr_len) {
200         len = mtu - BLE_ATT_PREP_WRITE_CMD_BASE_SZ;
201         if (off + len > attr_len) {
202             len = attr_len - off;
203         }
204 
205         /* Send the pending ATT Prep Write Command. */
206         ble_hs_test_util_verify_tx_prep_write(
207             100, off, ble_gatt_write_test_attr_value + off, len);
208 
209         /* Receive Prep Write response. */
210         len = BLE_ATT_MTU_DFLT - BLE_ATT_PREP_WRITE_CMD_BASE_SZ;
211         if (off + len >= attr_len) {
212             len = attr_len - off;
213             fail_now = 1;
214         }
215         if (!fail_now) {
216             ble_gatt_write_test_rx_prep_rsp(
217                 2, 100, off, ble_gatt_write_test_attr_value + off, len);
218         } else {
219             cb(2, off, len);
220             break;
221         }
222 
223         /* Verify callback hasn't gotten called. */
224         TEST_ASSERT(!ble_gatt_write_test_cb_called);
225 
226         off += len;
227     }
228 
229     /* Verify callback was called. */
230     TEST_ASSERT(ble_gatt_write_test_cb_called);
231     TEST_ASSERT(ble_gatt_write_test_error.status == BLE_HS_EBADDATA);
232     TEST_ASSERT(ble_gatt_write_test_error.att_handle == 0);
233 }
234 
235 static void
ble_gatt_write_test_misc_long_fail_handle(uint16_t conn_handle,int off,int len)236 ble_gatt_write_test_misc_long_fail_handle(uint16_t conn_handle,
237                                           int off, int len)
238 {
239     ble_gatt_write_test_rx_prep_rsp(
240         conn_handle, 99, off, ble_gatt_write_test_attr_value + off,
241         len);
242 }
243 
244 static void
ble_gatt_write_test_misc_long_fail_offset(uint16_t conn_handle,int off,int len)245 ble_gatt_write_test_misc_long_fail_offset(uint16_t conn_handle,
246                                           int off, int len)
247 {
248     ble_gatt_write_test_rx_prep_rsp(
249         conn_handle, 100, off + 1, ble_gatt_write_test_attr_value + off,
250         len);
251 }
252 
253 static void
ble_gatt_write_test_misc_long_fail_value(uint16_t conn_handle,int off,int len)254 ble_gatt_write_test_misc_long_fail_value(uint16_t conn_handle,
255                                          int off, int len)
256 {
257     ble_gatt_write_test_rx_prep_rsp(
258         conn_handle, 100, off, ble_gatt_write_test_attr_value + off + 1,
259         len);
260 }
261 
262 static void
ble_gatt_write_test_misc_long_fail_length(uint16_t conn_handle,int off,int len)263 ble_gatt_write_test_misc_long_fail_length(uint16_t conn_handle,
264                                           int off, int len)
265 {
266     ble_gatt_write_test_rx_prep_rsp(
267         conn_handle, 100, off, ble_gatt_write_test_attr_value + off,
268         len - 1);
269 }
270 
271 static int
ble_gatt_write_test_reliable_cb_good(uint16_t conn_handle,const struct ble_gatt_error * error,struct ble_gatt_attr * attrs,uint8_t num_attrs,void * arg)272 ble_gatt_write_test_reliable_cb_good(uint16_t conn_handle,
273                                      const struct ble_gatt_error *error,
274                                      struct ble_gatt_attr *attrs,
275                                      uint8_t num_attrs, void *arg)
276 {
277     int i;
278 
279     TEST_ASSERT_FATAL(num_attrs <= BLE_GATT_WRITE_TEST_MAX_ATTRS);
280 
281     TEST_ASSERT(conn_handle == 2);
282 
283     ble_gatt_write_test_num_attrs = num_attrs;
284     for (i = 0; i < num_attrs; i++) {
285         ble_hs_test_util_attr_to_flat(ble_gatt_write_test_attrs + i,
286                                       attrs + i);
287     }
288 
289     ble_gatt_write_test_cb_called = 1;
290 
291     return 0;
292 }
293 
294 static void
ble_gatt_write_test_misc_reliable_good(struct ble_hs_test_util_flat_attr * flat_attrs)295 ble_gatt_write_test_misc_reliable_good(
296     struct ble_hs_test_util_flat_attr *flat_attrs)
297 {
298     const struct ble_hs_test_util_flat_attr *attr;
299     struct ble_gatt_attr attrs[16];
300     uint16_t mtu;
301     int num_attrs;
302     int attr_idx;
303     int len;
304     int off;
305     int rc;
306     int i;
307 
308     ble_gatt_write_test_init();
309 
310     for (num_attrs = 0; flat_attrs[num_attrs].handle != 0; num_attrs++) {
311         TEST_ASSERT_FATAL(num_attrs < sizeof attrs / sizeof attrs[0]);
312         ble_hs_test_util_attr_from_flat(attrs + num_attrs,
313                                         flat_attrs + num_attrs);
314     }
315 
316     ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
317                                  NULL, NULL);
318     mtu = ble_att_mtu(2);
319 
320     rc = ble_gattc_write_reliable(2, attrs, num_attrs,
321                                   ble_gatt_write_test_reliable_cb_good, NULL);
322     TEST_ASSERT(rc == 0);
323 
324     attr_idx = 0;
325     off = 0;
326     while (attr_idx < num_attrs) {
327         attr = flat_attrs + attr_idx;
328 
329         len = mtu - BLE_ATT_PREP_WRITE_CMD_BASE_SZ;
330         if (off + len > attr->value_len) {
331             len = attr->value_len - off;
332         }
333 
334         /* Send the pending ATT Prep Write Command. */
335         ble_hs_test_util_verify_tx_prep_write(attr->handle, off,
336                                               attr->value + off, len);
337 
338         /* Receive Prep Write response. */
339         ble_gatt_write_test_rx_prep_rsp(2, attr->handle, off,
340                                         attr->value + off, len);
341 
342         /* Verify callback hasn't gotten called. */
343         TEST_ASSERT(!ble_gatt_write_test_cb_called);
344 
345         off += len;
346         if (off >= attr->value_len) {
347             attr_idx++;
348             off = 0;
349         }
350     }
351 
352     /* Verify execute write request sent. */
353     ble_hs_test_util_verify_tx_exec_write(BLE_ATT_EXEC_WRITE_F_EXECUTE);
354 
355     /* Receive Exec Write response. */
356     ble_gatt_write_test_rx_exec_rsp(2);
357 
358     /* Verify callback got called. */
359     TEST_ASSERT(ble_gatt_write_test_cb_called);
360     TEST_ASSERT(ble_gatt_write_test_num_attrs == num_attrs);
361     for (i = 0; i < num_attrs; i++) {
362         rc = ble_hs_test_util_flat_attr_cmp(
363             ble_gatt_write_test_attrs + i, flat_attrs + i);
364         TEST_ASSERT(rc == 0);
365     }
366 }
367 
TEST_CASE(ble_gatt_write_test_no_rsp)368 TEST_CASE(ble_gatt_write_test_no_rsp)
369 {
370     int attr_len;
371     int rc;
372 
373     ble_gatt_write_test_init();
374 
375     ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
376                                  NULL, NULL);
377 
378     attr_len = 4;
379     rc = ble_hs_test_util_gatt_write_no_rsp_flat(
380         2, 100, ble_gatt_write_test_attr_value, attr_len);
381     TEST_ASSERT(rc == 0);
382 
383     /* Send the pending ATT Write Command. */
384 
385     /* No response expected; verify callback not called. */
386     TEST_ASSERT(!ble_gatt_write_test_cb_called);
387 }
388 
TEST_CASE(ble_gatt_write_test_rsp)389 TEST_CASE(ble_gatt_write_test_rsp)
390 {
391     int attr_len;
392 
393     ble_gatt_write_test_init();
394 
395     ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
396                                  NULL, NULL);
397 
398     attr_len = 4;
399     ble_hs_test_util_gatt_write_flat(2, 100, ble_gatt_write_test_attr_value,
400                                      attr_len, ble_gatt_write_test_cb_good,
401                                      &attr_len);
402 
403     /* Send the pending ATT Write Command. */
404 
405     /* Response not received yet; verify callback not called. */
406     TEST_ASSERT(!ble_gatt_write_test_cb_called);
407 
408     /* Receive write response. */
409     ble_gatt_write_test_rx_rsp(2);
410 
411     /* Verify callback got called. */
412     TEST_ASSERT(ble_gatt_write_test_cb_called);
413 }
414 
TEST_CASE(ble_gatt_write_test_long_good)415 TEST_CASE(ble_gatt_write_test_long_good)
416 {
417     /*** 1 prep write req/rsp. */
418     ble_gatt_write_test_misc_long_good(
419         BLE_ATT_MTU_DFLT - BLE_ATT_PREP_WRITE_CMD_BASE_SZ);
420 
421     /*** 2 prep write reqs/rsps. */
422     ble_gatt_write_test_misc_long_good(
423         BLE_ATT_MTU_DFLT - BLE_ATT_PREP_WRITE_CMD_BASE_SZ + 1);
424 
425     /*** Maximum reqs/rsps. */
426     ble_gatt_write_test_misc_long_good(BLE_ATT_ATTR_MAX_LEN);
427 }
428 
TEST_CASE(ble_gatt_write_test_long_bad_handle)429 TEST_CASE(ble_gatt_write_test_long_bad_handle)
430 {
431     /*** 1 prep write req/rsp. */
432     ble_gatt_write_test_misc_long_bad(
433         BLE_ATT_MTU_DFLT - BLE_ATT_PREP_WRITE_CMD_BASE_SZ,
434         ble_gatt_write_test_misc_long_fail_handle);
435 
436     /*** 2 prep write reqs/rsps. */
437     ble_gatt_write_test_misc_long_bad(
438         BLE_ATT_MTU_DFLT - BLE_ATT_PREP_WRITE_CMD_BASE_SZ + 1,
439         ble_gatt_write_test_misc_long_fail_handle);
440 
441     /*** Maximum reqs/rsps. */
442     ble_gatt_write_test_misc_long_bad(
443         BLE_ATT_ATTR_MAX_LEN,
444         ble_gatt_write_test_misc_long_fail_handle);
445 }
446 
TEST_CASE(ble_gatt_write_test_long_bad_offset)447 TEST_CASE(ble_gatt_write_test_long_bad_offset)
448 {
449     /*** 1 prep write req/rsp. */
450     ble_gatt_write_test_misc_long_bad(
451         BLE_ATT_MTU_DFLT - BLE_ATT_PREP_WRITE_CMD_BASE_SZ,
452         ble_gatt_write_test_misc_long_fail_offset);
453 
454     /*** 2 prep write reqs/rsps. */
455     ble_gatt_write_test_misc_long_bad(
456         BLE_ATT_MTU_DFLT - BLE_ATT_PREP_WRITE_CMD_BASE_SZ + 1,
457         ble_gatt_write_test_misc_long_fail_offset);
458 
459     /*** Maximum reqs/rsps. */
460     ble_gatt_write_test_misc_long_bad(
461         BLE_ATT_ATTR_MAX_LEN,
462         ble_gatt_write_test_misc_long_fail_offset);
463 }
464 
TEST_CASE(ble_gatt_write_test_long_bad_value)465 TEST_CASE(ble_gatt_write_test_long_bad_value)
466 {
467     /*** 1 prep write req/rsp. */
468     ble_gatt_write_test_misc_long_bad(
469         BLE_ATT_MTU_DFLT - BLE_ATT_PREP_WRITE_CMD_BASE_SZ,
470         ble_gatt_write_test_misc_long_fail_value);
471 
472     /*** 2 prep write reqs/rsps. */
473     ble_gatt_write_test_misc_long_bad(
474         BLE_ATT_MTU_DFLT - BLE_ATT_PREP_WRITE_CMD_BASE_SZ + 1,
475         ble_gatt_write_test_misc_long_fail_value);
476 
477     /*** Maximum reqs/rsps. */
478     ble_gatt_write_test_misc_long_bad(
479         BLE_ATT_ATTR_MAX_LEN,
480         ble_gatt_write_test_misc_long_fail_value);
481 }
482 
TEST_CASE(ble_gatt_write_test_long_bad_length)483 TEST_CASE(ble_gatt_write_test_long_bad_length)
484 {
485     /*** 1 prep write req/rsp. */
486     ble_gatt_write_test_misc_long_bad(
487         BLE_ATT_MTU_DFLT - BLE_ATT_PREP_WRITE_CMD_BASE_SZ,
488         ble_gatt_write_test_misc_long_fail_length);
489 
490     /*** 2 prep write reqs/rsps. */
491     ble_gatt_write_test_misc_long_bad(
492         BLE_ATT_MTU_DFLT - BLE_ATT_PREP_WRITE_CMD_BASE_SZ + 1,
493         ble_gatt_write_test_misc_long_fail_length);
494 
495     /*** Maximum reqs/rsps. */
496     ble_gatt_write_test_misc_long_bad(
497         BLE_ATT_ATTR_MAX_LEN,
498         ble_gatt_write_test_misc_long_fail_length);
499 }
500 
TEST_CASE(ble_gatt_write_test_reliable_good)501 TEST_CASE(ble_gatt_write_test_reliable_good)
502 {
503     /*** 1 attribute. */
504     ble_gatt_write_test_misc_reliable_good(
505         ((struct ble_hs_test_util_flat_attr[]) { {
506             .handle = 100,
507             .value_len = 2,
508             .value = { 1, 2 },
509         }, {
510             0
511         } }));
512 
513     /*** 2 attributes. */
514     ble_gatt_write_test_misc_reliable_good(
515         ((struct ble_hs_test_util_flat_attr[]) { {
516             .handle = 100,
517             .value_len = 2,
518             .value = { 1,2 },
519         }, {
520             .handle = 113,
521             .value_len = 6,
522             .value = { 5,6,7,8,9,10 },
523         }, {
524             0
525         } }));
526 
527     /*** 3 attributes. */
528     ble_gatt_write_test_misc_reliable_good(
529         ((struct ble_hs_test_util_flat_attr[]) { {
530             .handle = 100,
531             .value_len = 2,
532             .value = { 1,2 },
533         }, {
534             .handle = 113,
535             .value_len = 6,
536             .value = { 5,6,7,8,9,10 },
537         }, {
538             .handle = 144,
539             .value_len = 1,
540             .value = { 0xff },
541         }, {
542             0
543         } }));
544 
545     /*** Long attributes. */
546     ble_gatt_write_test_misc_reliable_good(
547         ((struct ble_hs_test_util_flat_attr[]) { {
548             .handle = 100,
549             .value_len = 20,
550             .value = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20 },
551         }, {
552             .handle = 144,
553             .value_len = 20,
554             .value = { 11,12,13,14,15,16,17,18,19,110,
555                        111,112,113,114,115,116,117,118,119,120 },
556         }, {
557             0
558         } }));
559 }
560 
TEST_CASE(ble_gatt_write_test_long_queue_full)561 TEST_CASE(ble_gatt_write_test_long_queue_full)
562 {
563     int off;
564     int len;
565     int rc;
566     int i;
567 
568     ble_gatt_write_test_init();
569 
570     ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
571                                  NULL, NULL);
572 
573     rc = ble_hs_test_util_gatt_write_long_flat(
574         2, 100, ble_gatt_write_test_attr_value, 128,
575         ble_gatt_write_test_cb_good, NULL);
576     TEST_ASSERT(rc == 0);
577 
578     off = 0;
579     for (i = 0; i < 2; i++) {
580         /* Verify prep write request was sent. */
581         TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue() != NULL);
582 
583         /* Receive Prep Write response. */
584         len = BLE_ATT_MTU_DFLT - BLE_ATT_PREP_WRITE_CMD_BASE_SZ;
585         ble_gatt_write_test_rx_prep_rsp(
586             2, 100, off, ble_gatt_write_test_attr_value + off, len);
587 
588         /* Verify callback hasn't gotten called. */
589         TEST_ASSERT(!ble_gatt_write_test_cb_called);
590 
591         off += len;
592     }
593 
594     /* Verify prep write request was sent. */
595     TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue() != NULL);
596 
597     /* Receive queue full error. */
598     ble_hs_test_util_rx_att_err_rsp(2, BLE_ATT_OP_PREP_WRITE_REQ,
599                                     BLE_ATT_ERR_PREPARE_QUEUE_FULL, 100);
600 
601     /* Verify callback was called. */
602     TEST_ASSERT(ble_gatt_write_test_cb_called);
603     TEST_ASSERT(ble_gatt_write_test_error.status ==
604                 BLE_HS_ATT_ERR(BLE_ATT_ERR_PREPARE_QUEUE_FULL));
605     TEST_ASSERT(ble_gatt_write_test_error.att_handle == 100);
606 
607     /* Verify clear queue command got sent. */
608     ble_hs_test_util_verify_tx_exec_write(BLE_ATT_EXEC_WRITE_F_CANCEL);
609 }
610 
TEST_CASE(ble_gatt_write_test_long_oom)611 TEST_CASE(ble_gatt_write_test_long_oom)
612 {
613     static const struct ble_hs_test_util_flat_attr attr = {
614         .handle = 34,
615         .value = {
616             1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
617             17, 18, 19, 20,
618         },
619         .value_len = 20,
620     };
621 
622     struct os_mbuf *oms;
623     int32_t ticks_until;
624     int chunk_sz;
625     int off;
626     int rc;
627 
628     ble_gatt_write_test_init();
629     ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
630                                  NULL, NULL);
631 
632     /* Initiate a write long procedure. */
633     off = 0;
634     rc = ble_hs_test_util_gatt_write_long_flat(
635         2, attr.handle, attr.value, attr.value_len,
636         ble_gatt_write_test_cb_good, NULL);
637     TEST_ASSERT_FATAL(rc == 0);
638 
639     chunk_sz = ble_att_mtu(2) - BLE_ATT_PREP_WRITE_CMD_BASE_SZ;
640 
641     ble_hs_test_util_verify_tx_prep_write(attr.handle, off,
642                                           attr.value + off, chunk_sz);
643 
644     /* Exhaust the msys pool.  Leave one mbuf for the forthcoming response. */
645     oms = ble_hs_test_util_mbuf_alloc_all_but(1);
646     ble_gatt_write_test_rx_prep_rsp(2, attr.handle, off, attr.value + off,
647                                     chunk_sz);
648     off += chunk_sz;
649 
650     /* Ensure no follow-up request got sent.  It should not have gotten sent
651      * due to mbuf exhaustion.
652      */
653     ble_hs_test_util_prev_tx_queue_clear();
654     TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue_pullup() == NULL);
655 
656     /* Verify that we will resume the stalled GATT procedure in one second. */
657     ticks_until = ble_gattc_timer();
658     TEST_ASSERT(ticks_until == os_time_ms_to_ticks32(MYNEWT_VAL(BLE_GATT_RESUME_RATE)));
659 
660     /* Verify the procedure proceeds after mbufs become available. */
661     rc = os_mbuf_free_chain(oms);
662     TEST_ASSERT_FATAL(rc == 0);
663     os_time_advance(ticks_until);
664     ble_gattc_timer();
665 
666     chunk_sz = attr.value_len - off;
667     ble_hs_test_util_verify_tx_prep_write(attr.handle, off,
668                                           attr.value + off, chunk_sz);
669 
670     /* Exhaust the msys pool.  Leave one mbuf for the forthcoming response. */
671     oms = ble_hs_test_util_mbuf_alloc_all_but(1);
672     ble_gatt_write_test_rx_prep_rsp(
673         2, attr.handle, off, attr.value + off, chunk_sz);
674     off += chunk_sz;
675 
676     /* Ensure no follow-up request got sent.  It should not have gotten sent
677      * due to mbuf exhaustion.
678      */
679     ble_hs_test_util_prev_tx_queue_clear();
680     TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue_pullup() == NULL);
681 
682     /* Verify that we will resume the stalled GATT procedure in one second. */
683     ticks_until = ble_gattc_timer();
684     TEST_ASSERT(ticks_until == os_time_ms_to_ticks32(MYNEWT_VAL(BLE_GATT_RESUME_RATE)));
685 
686     /* Verify that procedure completes when mbufs are available. */
687     rc = os_mbuf_free_chain(oms);
688     TEST_ASSERT_FATAL(rc == 0);
689     os_time_advance(ticks_until);
690     ble_gattc_timer();
691 
692     /* Verify execute write request sent. */
693     ble_hs_test_util_verify_tx_exec_write(BLE_ATT_EXEC_WRITE_F_EXECUTE);
694 
695     /* Receive Exec Write response. */
696     ble_gatt_write_test_rx_exec_rsp(2);
697 
698     /* Verify callback got called. */
699     TEST_ASSERT(ble_gatt_write_test_cb_called);
700     TEST_ASSERT(!ble_gattc_any_jobs());
701 }
702 
TEST_CASE(ble_gatt_write_test_reliable_oom)703 TEST_CASE(ble_gatt_write_test_reliable_oom)
704 {
705     static const struct ble_hs_test_util_flat_attr attr = {
706         .handle = 34,
707         .value = {
708             1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
709             17, 18, 19, 20,
710         },
711         .value_len = 20,
712     };
713 
714     struct ble_gatt_attr mattr;
715     struct os_mbuf *oms;
716     int32_t ticks_until;
717     int chunk_sz;
718     int off;
719     int rc;
720 
721     ble_gatt_write_test_init();
722     ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
723                                  NULL, NULL);
724 
725     /* Initiate a write reliable procedure. */
726     ble_hs_test_util_attr_from_flat(&mattr, &attr);
727 
728     off = 0;
729     rc = ble_gattc_write_reliable(2, &mattr, 1,
730                                   ble_gatt_write_test_reliable_cb_good, NULL);
731     TEST_ASSERT_FATAL(rc == 0);
732 
733     chunk_sz = ble_att_mtu(2) - BLE_ATT_PREP_WRITE_CMD_BASE_SZ;
734 
735     ble_hs_test_util_verify_tx_prep_write(attr.handle, off,
736                                           attr.value + off, chunk_sz);
737 
738     /* Exhaust the msys pool.  Leave one mbuf for the forthcoming response. */
739     oms = ble_hs_test_util_mbuf_alloc_all_but(1);
740     ble_gatt_write_test_rx_prep_rsp(2, attr.handle, off, attr.value + off,
741                                     chunk_sz);
742     off += chunk_sz;
743 
744     /* Ensure no follow-up request got sent.  It should not have gotten sent
745      * due to mbuf exhaustion.
746      */
747     ble_hs_test_util_prev_tx_queue_clear();
748     TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue_pullup() == NULL);
749 
750     /* Verify that we will resume the stalled GATT procedure in one second. */
751     ticks_until = ble_gattc_timer();
752     TEST_ASSERT(ticks_until == os_time_ms_to_ticks32(MYNEWT_VAL(BLE_GATT_RESUME_RATE)));
753 
754     /* Verify the procedure proceeds after mbufs become available. */
755     rc = os_mbuf_free_chain(oms);
756     TEST_ASSERT_FATAL(rc == 0);
757     os_time_advance(ticks_until);
758     ble_gattc_timer();
759 
760     chunk_sz = attr.value_len - off;
761     ble_hs_test_util_verify_tx_prep_write(attr.handle, off,
762                                           attr.value + off, chunk_sz);
763 
764     /* Exhaust the msys pool.  Leave one mbuf for the forthcoming response. */
765     oms = ble_hs_test_util_mbuf_alloc_all_but(1);
766     ble_gatt_write_test_rx_prep_rsp(
767         2, attr.handle, off, attr.value + off, chunk_sz);
768     off += chunk_sz;
769 
770     /* Ensure no follow-up request got sent.  It should not have gotten sent
771      * due to mbuf exhaustion.
772      */
773     ble_hs_test_util_prev_tx_queue_clear();
774     TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue_pullup() == NULL);
775 
776     /* Verify that we will resume the stalled GATT procedure in one second. */
777     ticks_until = ble_gattc_timer();
778     TEST_ASSERT(ticks_until == os_time_ms_to_ticks32(MYNEWT_VAL(BLE_GATT_RESUME_RATE)));
779 
780     /* Verify that procedure completes when mbufs are available. */
781     rc = os_mbuf_free_chain(oms);
782     TEST_ASSERT_FATAL(rc == 0);
783     os_time_advance(ticks_until);
784     ble_gattc_timer();
785 
786     /* Verify execute write request sent. */
787     ble_hs_test_util_verify_tx_exec_write(BLE_ATT_EXEC_WRITE_F_EXECUTE);
788 
789     /* Receive Exec Write response. */
790     ble_gatt_write_test_rx_exec_rsp(2);
791 
792     /* Verify callback got called. */
793     TEST_ASSERT(ble_gatt_write_test_cb_called);
794     TEST_ASSERT(!ble_gattc_any_jobs());
795 }
796 
TEST_SUITE(ble_gatt_write_test_suite)797 TEST_SUITE(ble_gatt_write_test_suite)
798 {
799     tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
800 
801     ble_gatt_write_test_no_rsp();
802     ble_gatt_write_test_rsp();
803     ble_gatt_write_test_long_good();
804     ble_gatt_write_test_long_bad_handle();
805     ble_gatt_write_test_long_bad_offset();
806     ble_gatt_write_test_long_bad_value();
807     ble_gatt_write_test_long_bad_length();
808     ble_gatt_write_test_long_queue_full();
809     ble_gatt_write_test_reliable_good();
810     ble_gatt_write_test_long_oom();
811     ble_gatt_write_test_reliable_oom();
812 }
813 
814 int
ble_gatt_write_test_all(void)815 ble_gatt_write_test_all(void)
816 {
817     ble_gatt_write_test_suite();
818 
819     return tu_any_failed;
820 }
821