xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/host/test/src/ble_att_clt_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 "ble_hs_test_util.h"
26 
27 /**
28  * @return                      The handle of the new test connection.
29  */
30 static uint16_t
ble_att_clt_test_misc_init(void)31 ble_att_clt_test_misc_init(void)
32 {
33     ble_hs_test_util_init();
34     ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}), NULL,
35                                  NULL);
36     return 2;
37 }
38 
39 static void
ble_att_clt_test_misc_verify_tx_write(uint16_t handle_id,void * value,int value_len,int is_req)40 ble_att_clt_test_misc_verify_tx_write(uint16_t handle_id, void *value,
41                                       int value_len, int is_req)
42 {
43     struct ble_att_write_req req;
44     struct os_mbuf *om;
45 
46     om = ble_hs_test_util_prev_tx_dequeue_pullup();
47     TEST_ASSERT_FATAL(om != NULL);
48 
49     if (is_req) {
50         ble_att_write_req_parse(om->om_data, om->om_len, &req);
51     } else {
52         ble_att_write_cmd_parse(om->om_data, om->om_len, &req);
53     }
54 
55     TEST_ASSERT(req.bawq_handle == handle_id);
56     TEST_ASSERT(om->om_len == BLE_ATT_WRITE_REQ_BASE_SZ + value_len);
57     TEST_ASSERT(memcmp(om->om_data + BLE_ATT_WRITE_REQ_BASE_SZ, value,
58                        value_len) == 0);
59 }
60 
61 static void
ble_att_clt_test_tx_write_req_or_cmd(uint16_t conn_handle,uint16_t handle,void * value,int value_len,int is_req)62 ble_att_clt_test_tx_write_req_or_cmd(uint16_t conn_handle, uint16_t handle,
63                                      void *value, int value_len, int is_req)
64 {
65     struct os_mbuf *om;
66     int rc;
67 
68     om = ble_hs_test_util_om_from_flat(value, value_len);
69     if (is_req) {
70         rc = ble_att_clt_tx_write_req(conn_handle, handle, om);
71     } else {
72         rc = ble_att_clt_tx_write_cmd(conn_handle, handle, om);
73     }
74     TEST_ASSERT(rc == 0);
75 }
76 
TEST_CASE(ble_att_clt_test_tx_find_info)77 TEST_CASE(ble_att_clt_test_tx_find_info)
78 {
79     uint16_t conn_handle;
80     int rc;
81 
82     conn_handle = ble_att_clt_test_misc_init();
83 
84     /*** Success. */
85     rc = ble_att_clt_tx_find_info(conn_handle, 1, 0xffff);
86     TEST_ASSERT(rc == 0);
87 
88     /*** Error: start handle of 0. */
89     rc = ble_att_clt_tx_find_info(conn_handle, 0, 0xffff);
90     TEST_ASSERT(rc == BLE_HS_EINVAL);
91 
92     /*** Error: start handle greater than end handle. */
93     rc = ble_att_clt_tx_find_info(conn_handle, 500, 499);
94     TEST_ASSERT(rc == BLE_HS_EINVAL);
95 
96     /*** Success; start and end handles equal. */
97     rc = ble_att_clt_tx_find_info(conn_handle, 500, 500);
98     TEST_ASSERT(rc == 0);
99 }
100 
TEST_CASE(ble_att_clt_test_rx_find_info)101 TEST_CASE(ble_att_clt_test_rx_find_info)
102 {
103     struct ble_att_find_info_rsp rsp;
104     uint16_t conn_handle;
105     uint8_t buf[1024];
106     uint8_t uuid128_1[16] = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 };
107     int off;
108     int rc;
109 
110     conn_handle = ble_att_clt_test_misc_init();
111 
112     /*** One 128-bit UUID. */
113     /* Receive response with attribute mapping. */
114     off = 0;
115     rsp.bafp_format = BLE_ATT_FIND_INFO_RSP_FORMAT_128BIT;
116     ble_att_find_info_rsp_write(buf + off, sizeof buf - off, &rsp);
117     off += BLE_ATT_FIND_INFO_RSP_BASE_SZ;
118 
119     put_le16(buf + off, 1);
120     off += 2;
121     memcpy(buf + off, uuid128_1, 16);
122     off += 16;
123 
124     rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
125                                                 buf, off);
126     TEST_ASSERT(rc == 0);
127 
128     /*** One 16-bit UUID. */
129     /* Receive response with attribute mapping. */
130     off = 0;
131     rsp.bafp_format = BLE_ATT_FIND_INFO_RSP_FORMAT_16BIT;
132     ble_att_find_info_rsp_write(buf + off, sizeof buf - off, &rsp);
133     off += BLE_ATT_FIND_INFO_RSP_BASE_SZ;
134 
135     put_le16(buf + off, 2);
136     off += 2;
137     put_le16(buf + off, 0x000f);
138     off += 2;
139 
140     rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
141                                                 buf, off);
142     TEST_ASSERT(rc == 0);
143 
144     /*** Two 16-bit UUIDs. */
145     /* Receive response with attribute mappings. */
146     off = 0;
147     rsp.bafp_format = BLE_ATT_FIND_INFO_RSP_FORMAT_16BIT;
148     ble_att_find_info_rsp_write(buf + off, sizeof buf - off, &rsp);
149     off += BLE_ATT_FIND_INFO_RSP_BASE_SZ;
150 
151     put_le16(buf + off, 3);
152     off += 2;
153     put_le16(buf + off, 0x0010);
154     off += 2;
155 
156     put_le16(buf + off, 4);
157     off += 2;
158     put_le16(buf + off, 0x0011);
159     off += 2;
160 
161     rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
162                                                 buf, off);
163     TEST_ASSERT(rc == 0);
164 }
165 
166 static void
ble_att_clt_test_case_tx_write_req_or_cmd(int is_req)167 ble_att_clt_test_case_tx_write_req_or_cmd(int is_req)
168 {
169     uint16_t conn_handle;
170     uint8_t value300[500] = { 0 };
171     uint8_t value5[5] = { 6, 7, 54, 34, 8 };
172 
173     conn_handle = ble_att_clt_test_misc_init();
174 
175     /*** 5-byte write. */
176     ble_att_clt_test_tx_write_req_or_cmd(conn_handle, 0x1234, value5,
177                                          sizeof value5, is_req);
178     ble_att_clt_test_misc_verify_tx_write(0x1234, value5, sizeof value5,
179                                           is_req);
180 
181     /*** Overlong write; verify command truncated to ATT MTU. */
182     ble_att_clt_test_tx_write_req_or_cmd(conn_handle, 0xab83, value300,
183                                          sizeof value300, is_req);
184     ble_att_clt_test_misc_verify_tx_write(0xab83, value300,
185                                           BLE_ATT_MTU_DFLT - 3, is_req);
186 }
187 
188 static void
ble_att_clt_test_misc_prep_good(uint16_t handle,uint16_t offset,uint8_t * attr_data,uint16_t attr_data_len)189 ble_att_clt_test_misc_prep_good(uint16_t handle, uint16_t offset,
190                                 uint8_t *attr_data, uint16_t attr_data_len)
191 {
192     struct ble_att_prep_write_cmd req;
193     struct os_mbuf *om;
194     uint16_t conn_handle;
195     int rc;
196     int i;
197 
198     conn_handle = ble_att_clt_test_misc_init();
199 
200     om = ble_hs_test_util_om_from_flat(attr_data, attr_data_len);
201     rc = ble_att_clt_tx_prep_write(conn_handle, handle, offset, om);
202     TEST_ASSERT(rc == 0);
203 
204     om = ble_hs_test_util_prev_tx_dequeue_pullup();
205     TEST_ASSERT_FATAL(om != NULL);
206     TEST_ASSERT(om->om_len == BLE_ATT_PREP_WRITE_CMD_BASE_SZ + attr_data_len);
207 
208     ble_att_prep_write_req_parse(om->om_data, om->om_len, &req);
209     TEST_ASSERT(req.bapc_handle == handle);
210     TEST_ASSERT(req.bapc_offset == offset);
211     for (i = 0; i < attr_data_len; i++) {
212         TEST_ASSERT(om->om_data[BLE_ATT_PREP_WRITE_CMD_BASE_SZ + i] ==
213                     attr_data[i]);
214     }
215 }
216 
217 static void
ble_att_clt_test_misc_exec_good(uint8_t flags)218 ble_att_clt_test_misc_exec_good(uint8_t flags)
219 {
220     struct ble_att_exec_write_req req;
221     struct os_mbuf *om;
222     uint16_t conn_handle;
223     int rc;
224 
225     conn_handle = ble_att_clt_test_misc_init();
226 
227     rc = ble_att_clt_tx_exec_write(conn_handle, flags);
228     TEST_ASSERT(rc == 0);
229 
230     om = ble_hs_test_util_prev_tx_dequeue_pullup();
231     TEST_ASSERT_FATAL(om != NULL);
232     TEST_ASSERT(om->om_len == BLE_ATT_EXEC_WRITE_REQ_SZ);
233 
234     ble_att_exec_write_req_parse(om->om_data, om->om_len, &req);
235     TEST_ASSERT(req.baeq_flags == flags);
236 }
237 
238 static void
ble_att_clt_test_misc_prep_bad(uint16_t handle,uint16_t offset,uint8_t * attr_data,uint16_t attr_data_len,int status)239 ble_att_clt_test_misc_prep_bad(uint16_t handle, uint16_t offset,
240                                uint8_t *attr_data, uint16_t attr_data_len,
241                                int status)
242 {
243     struct os_mbuf *om;
244     uint16_t conn_handle;
245     int rc;
246 
247     conn_handle = ble_att_clt_test_misc_init();
248 
249     om = ble_hs_test_util_om_from_flat(attr_data, attr_data_len);
250 
251     rc = ble_att_clt_tx_prep_write(conn_handle, handle, offset, om);
252     TEST_ASSERT(rc == status);
253 }
254 
255 static void
ble_att_clt_test_misc_tx_mtu(uint16_t conn_handle,uint16_t mtu,int status)256 ble_att_clt_test_misc_tx_mtu(uint16_t conn_handle, uint16_t mtu, int status)
257 {
258     int rc;
259 
260     rc = ble_att_clt_tx_mtu(conn_handle, mtu);
261     TEST_ASSERT(rc == status);
262 
263     if (rc == 0) {
264         ble_hs_test_util_verify_tx_mtu_cmd(1, mtu);
265     }
266 }
267 
TEST_CASE(ble_att_clt_test_tx_write)268 TEST_CASE(ble_att_clt_test_tx_write)
269 {
270     ble_att_clt_test_case_tx_write_req_or_cmd(0);
271     ble_att_clt_test_case_tx_write_req_or_cmd(1);
272 }
273 
TEST_CASE(ble_att_clt_test_tx_read)274 TEST_CASE(ble_att_clt_test_tx_read)
275 {
276     uint16_t conn_handle;
277     int rc;
278 
279     conn_handle = ble_att_clt_test_misc_init();
280 
281     /*** Success. */
282     rc = ble_att_clt_tx_read(conn_handle, 1);
283     TEST_ASSERT(rc == 0);
284 
285     /*** Error: handle of 0. */
286     rc = ble_att_clt_tx_read(conn_handle, 0);
287     TEST_ASSERT(rc == BLE_HS_EINVAL);
288 }
289 
TEST_CASE(ble_att_clt_test_rx_read)290 TEST_CASE(ble_att_clt_test_rx_read)
291 {
292     uint16_t conn_handle;
293     uint8_t buf[1024];
294     int rc;
295 
296     conn_handle = ble_att_clt_test_misc_init();
297 
298     /*** Basic success. */
299     buf[0] = BLE_ATT_OP_READ_RSP;
300     buf[1] = 0;
301     rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
302                                                 buf, 2);
303     TEST_ASSERT(rc == 0);
304 
305     /*** Larger response. */
306     rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
307                                                 buf, 20);
308     TEST_ASSERT(rc == 0);
309 
310     /*** Zero-length response. */
311     rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
312                                                 buf, 1);
313     TEST_ASSERT(rc == 0);
314 }
315 
TEST_CASE(ble_att_clt_test_tx_read_blob)316 TEST_CASE(ble_att_clt_test_tx_read_blob)
317 {
318     uint16_t conn_handle;
319     int rc;
320 
321     conn_handle = ble_att_clt_test_misc_init();
322 
323     /*** Success. */
324     rc = ble_att_clt_tx_read_blob(conn_handle, 1, 0);
325     TEST_ASSERT(rc == 0);
326 
327     /*** Error: handle of 0. */
328     rc = ble_att_clt_tx_read_blob(conn_handle, 0, 0);
329     TEST_ASSERT(rc == BLE_HS_EINVAL);
330 }
331 
TEST_CASE(ble_att_clt_test_rx_read_blob)332 TEST_CASE(ble_att_clt_test_rx_read_blob)
333 {
334     uint16_t conn_handle;
335     uint8_t buf[1024];
336     int rc;
337 
338     conn_handle = ble_att_clt_test_misc_init();
339 
340     /*** Basic success. */
341     buf[0] = BLE_ATT_OP_READ_BLOB_RSP;
342     buf[1] = 0;
343     rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
344                                                 buf, 2);
345     TEST_ASSERT(rc == 0);
346 
347     /*** Larger response. */
348     rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
349                                                 buf, 20);
350     TEST_ASSERT(rc == 0);
351 
352     /*** Zero-length response. */
353     rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
354                                                 buf, 1);
355     TEST_ASSERT(rc == 0);
356 }
357 
TEST_CASE(ble_att_clt_test_tx_read_mult)358 TEST_CASE(ble_att_clt_test_tx_read_mult)
359 {
360     struct os_mbuf *om;
361     uint16_t conn_handle;
362     int rc;
363 
364     conn_handle = ble_att_clt_test_misc_init();
365 
366     /*** Success. */
367     rc = ble_att_clt_tx_read_mult(conn_handle, ((uint16_t[]){ 1, 2 }), 2);
368     TEST_ASSERT(rc == 0);
369 
370     om = ble_hs_test_util_prev_tx_dequeue_pullup();
371     TEST_ASSERT_FATAL(om != NULL);
372     TEST_ASSERT(om->om_len == BLE_ATT_READ_MULT_REQ_BASE_SZ + 4);
373 
374     ble_att_read_mult_req_parse(om->om_data, om->om_len);
375     TEST_ASSERT(get_le16(om->om_data + BLE_ATT_READ_MULT_REQ_BASE_SZ) == 1);
376     TEST_ASSERT(get_le16(om->om_data + BLE_ATT_READ_MULT_REQ_BASE_SZ + 2) == 2);
377 
378     /*** Error: no handles. */
379     rc = ble_att_clt_tx_read_mult(conn_handle, NULL, 0);
380     TEST_ASSERT(rc == BLE_HS_EINVAL);
381 }
382 
TEST_CASE(ble_att_clt_test_rx_read_mult)383 TEST_CASE(ble_att_clt_test_rx_read_mult)
384 {
385     uint16_t conn_handle;
386     uint8_t buf[1024];
387     int rc;
388 
389     conn_handle = ble_att_clt_test_misc_init();
390 
391     /*** Basic success. */
392     ble_att_read_mult_rsp_write(buf, sizeof buf);
393     put_le16(buf + BLE_ATT_READ_MULT_RSP_BASE_SZ + 0, 12);
394 
395     rc = ble_hs_test_util_l2cap_rx_payload_flat(
396         conn_handle, BLE_L2CAP_CID_ATT, buf,
397         BLE_ATT_READ_MULT_RSP_BASE_SZ + 2);
398     TEST_ASSERT(rc == 0);
399 
400     /*** Larger response. */
401     put_le16(buf + BLE_ATT_READ_MULT_RSP_BASE_SZ + 0, 12);
402     put_le16(buf + BLE_ATT_READ_MULT_RSP_BASE_SZ + 2, 43);
403     put_le16(buf + BLE_ATT_READ_MULT_RSP_BASE_SZ + 4, 91);
404     rc = ble_hs_test_util_l2cap_rx_payload_flat(
405         conn_handle, BLE_L2CAP_CID_ATT, buf,
406         BLE_ATT_READ_MULT_RSP_BASE_SZ + 6);
407     TEST_ASSERT(rc == 0);
408 
409     /*** Zero-length response. */
410     rc = ble_hs_test_util_l2cap_rx_payload_flat(
411         conn_handle, BLE_L2CAP_CID_ATT, buf,
412         BLE_ATT_READ_MULT_RSP_BASE_SZ + 0);
413     TEST_ASSERT(rc == 0);
414 }
415 
TEST_CASE(ble_att_clt_test_tx_prep_write)416 TEST_CASE(ble_att_clt_test_tx_prep_write)
417 {
418     uint8_t attr_data[512];
419     int i;
420 
421     for (i = 0; i < sizeof attr_data; i++) {
422         attr_data[i] = i;
423     }
424 
425     /*** Success. */
426     ble_att_clt_test_misc_prep_good(123, 0, attr_data, 16);
427     ble_att_clt_test_misc_prep_good(5432, 100, attr_data, 2);
428     ble_att_clt_test_misc_prep_good(0x1234, 400, attr_data, 0);
429     ble_att_clt_test_misc_prep_good(5432, 0, attr_data,
430                                     BLE_ATT_MTU_DFLT -
431                                         BLE_ATT_PREP_WRITE_CMD_BASE_SZ);
432     ble_att_clt_test_misc_prep_good(0x1234, 507, attr_data, 5);
433 
434     /*** Error: handle of 0. */
435     ble_att_clt_test_misc_prep_bad(0, 0, attr_data, 16, BLE_HS_EINVAL);
436 
437     /*** Error: offset + length greater than maximum attribute size. */
438     ble_att_clt_test_misc_prep_bad(1, 507, attr_data, 6, BLE_HS_EINVAL);
439 
440     /*** Error: packet larger than MTU. */
441     ble_att_clt_test_misc_prep_bad(1, 0, attr_data,
442                                    BLE_ATT_MTU_DFLT -
443                                        BLE_ATT_PREP_WRITE_CMD_BASE_SZ + 1,
444                                    BLE_HS_EINVAL);
445 }
446 
TEST_CASE(ble_att_clt_test_rx_prep_write)447 TEST_CASE(ble_att_clt_test_rx_prep_write)
448 {
449     struct ble_att_prep_write_cmd rsp;
450     uint16_t conn_handle;
451     uint8_t buf[1024];
452     int rc;
453 
454     conn_handle = ble_att_clt_test_misc_init();
455 
456     /*** Basic success. */
457     rsp.bapc_handle = 0x1234;
458     rsp.bapc_offset = 0;
459     ble_att_prep_write_rsp_write(buf, sizeof buf, &rsp);
460     memset(buf + BLE_ATT_PREP_WRITE_CMD_BASE_SZ, 1, 5);
461     rc = ble_hs_test_util_l2cap_rx_payload_flat(
462         conn_handle, BLE_L2CAP_CID_ATT, buf,
463         BLE_ATT_PREP_WRITE_CMD_BASE_SZ + 5);
464     TEST_ASSERT(rc == 0);
465 
466     /*** 0-length write. */
467     rsp.bapc_handle = 0x1234;
468     rsp.bapc_offset = 0;
469     ble_att_prep_write_rsp_write(buf, sizeof buf, &rsp);
470     rc = ble_hs_test_util_l2cap_rx_payload_flat(
471         conn_handle, BLE_L2CAP_CID_ATT, buf, BLE_ATT_PREP_WRITE_CMD_BASE_SZ);
472     TEST_ASSERT(rc == 0);
473 }
474 
TEST_CASE(ble_att_clt_test_tx_exec_write)475 TEST_CASE(ble_att_clt_test_tx_exec_write)
476 {
477     uint16_t conn_handle;
478     int rc;
479 
480     conn_handle = ble_att_clt_test_misc_init();
481 
482     /*** Success. */
483     ble_att_clt_test_misc_exec_good(BLE_ATT_EXEC_WRITE_F_CANCEL);
484     ble_att_clt_test_misc_exec_good(BLE_ATT_EXEC_WRITE_F_EXECUTE);
485 
486     /*** Success: nonzero == execute. */
487     rc = ble_att_clt_tx_exec_write(conn_handle, 0x02);
488     TEST_ASSERT(rc == 0);
489 }
490 
TEST_CASE(ble_att_clt_test_tx_mtu)491 TEST_CASE(ble_att_clt_test_tx_mtu)
492 {
493     uint16_t conn_handle;
494 
495     conn_handle = ble_att_clt_test_misc_init();
496 
497     /*** Success. */
498     ble_att_clt_test_misc_tx_mtu(conn_handle, 50, 0);
499 
500     /*** Error: repeated sends. */
501     ble_att_clt_test_misc_tx_mtu(conn_handle, 50, BLE_HS_EALREADY);
502     ble_att_clt_test_misc_tx_mtu(conn_handle, 60, BLE_HS_EALREADY);
503 }
504 
TEST_SUITE(ble_att_clt_suite)505 TEST_SUITE(ble_att_clt_suite)
506 {
507     tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
508 
509     ble_att_clt_test_tx_find_info();
510     ble_att_clt_test_rx_find_info();
511     ble_att_clt_test_tx_read();
512     ble_att_clt_test_rx_read();
513     ble_att_clt_test_tx_read_blob();
514     ble_att_clt_test_rx_read_blob();
515     ble_att_clt_test_tx_read_mult();
516     ble_att_clt_test_rx_read_mult();
517     ble_att_clt_test_tx_write();
518     ble_att_clt_test_tx_prep_write();
519     ble_att_clt_test_rx_prep_write();
520     ble_att_clt_test_tx_exec_write();
521     ble_att_clt_test_tx_mtu();
522 }
523 
524 int
ble_att_clt_test_all(void)525 ble_att_clt_test_all(void)
526 {
527     ble_att_clt_suite();
528 
529     return tu_any_failed;
530 }
531