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