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