http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d98ddc1c/net/nimble/host/test/src/ble_gatts_reg_test.c ---------------------------------------------------------------------- diff --git a/net/nimble/host/test/src/ble_gatts_reg_test.c b/net/nimble/host/test/src/ble_gatts_reg_test.c new file mode 100644 index 0000000..ad5f18f --- /dev/null +++ b/net/nimble/host/test/src/ble_gatts_reg_test.c @@ -0,0 +1,718 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include <string.h> +#include <errno.h> +#include "testutil/testutil.h" +#include "nimble/ble.h" +#include "host/ble_uuid.h" +#include "host/ble_hs_test.h" +#include "ble_hs_test_util.h" + +#define BLE_GATTS_REG_TEST_MAX_ENTRIES 256 + +struct ble_gatts_reg_test_entry { + uint8_t op; + uint8_t uuid128[16]; + uint16_t handle; + uint16_t val_handle; /* If a characteristic. */ + + const struct ble_gatt_svc_def *svc; + const struct ble_gatt_chr_def *chr; + const struct ble_gatt_dsc_def *dsc; +}; + +static struct ble_gatts_reg_test_entry +ble_gatts_reg_test_entries[BLE_GATTS_REG_TEST_MAX_ENTRIES]; + +static int ble_gatts_reg_test_num_entries; + +static void +ble_gatts_reg_test_init(void) +{ + ble_hs_test_util_init(); + ble_gatts_reg_test_num_entries = 0; +} + +static void +ble_gatts_reg_test_misc_reg_cb(struct ble_gatt_register_ctxt *ctxt, void *arg) +{ + struct ble_gatts_reg_test_entry *entry; + + TEST_ASSERT_FATAL(ble_gatts_reg_test_num_entries < + BLE_GATTS_REG_TEST_MAX_ENTRIES); + + entry = ble_gatts_reg_test_entries + ble_gatts_reg_test_num_entries++; + memset(entry, 0, sizeof *entry); + + entry->op = ctxt->op; + switch (ctxt->op) { + case BLE_GATT_REGISTER_OP_SVC: + memcpy(entry->uuid128, ctxt->svc.svc_def->uuid128, 16); + entry->handle = ctxt->svc.handle; + entry->svc = ctxt->svc.svc_def; + break; + + case BLE_GATT_REGISTER_OP_CHR: + memcpy(entry->uuid128, ctxt->chr.chr_def->uuid128, 16); + entry->handle = ctxt->chr.def_handle; + entry->val_handle = ctxt->chr.val_handle; + entry->svc = ctxt->chr.svc_def; + entry->chr = ctxt->chr.chr_def; + break; + + case BLE_GATT_REGISTER_OP_DSC: + memcpy(entry->uuid128, ctxt->dsc.dsc_def->uuid128, 16); + entry->handle = ctxt->dsc.handle; + entry->svc = ctxt->dsc.svc_def; + entry->chr = ctxt->dsc.chr_def; + entry->dsc = ctxt->dsc.dsc_def; + break; + + default: + TEST_ASSERT(0); + break; + } +} + +static void +ble_gatts_reg_test_misc_lookup_good(struct ble_gatts_reg_test_entry *entry) +{ + uint16_t chr_def_handle; + uint16_t chr_val_handle; + uint16_t svc_handle; + uint16_t dsc_handle; + int rc; + + switch (entry->op) { + case BLE_GATT_REGISTER_OP_SVC: + rc = ble_gatts_find_svc(entry->uuid128, &svc_handle); + TEST_ASSERT_FATAL(rc == 0); + TEST_ASSERT(svc_handle == entry->handle); + break; + + case BLE_GATT_REGISTER_OP_CHR: + rc = ble_gatts_find_chr(entry->svc->uuid128, entry->chr->uuid128, + &chr_def_handle, &chr_val_handle); + TEST_ASSERT_FATAL(rc == 0); + TEST_ASSERT(chr_def_handle == entry->handle); + TEST_ASSERT(chr_val_handle == entry->val_handle); + break; + + case BLE_GATT_REGISTER_OP_DSC: + rc = ble_gatts_find_dsc(entry->svc->uuid128, entry->chr->uuid128, + entry->dsc->uuid128, &dsc_handle); + break; + + default: + TEST_ASSERT(0); + break; + } +} + +static void +ble_gatts_reg_test_misc_lookup_bad(struct ble_gatts_reg_test_entry *entry) +{ + struct ble_gatts_reg_test_entry *cur; + uint8_t wrong_uuid[16]; + int rc; + int i; + + switch (entry->op) { + case BLE_GATT_REGISTER_OP_SVC: + /* Wrong service UUID. */ + memcpy(wrong_uuid, entry->svc->uuid128, 16); + wrong_uuid[15]++; + rc = ble_gatts_find_svc(wrong_uuid, NULL); + TEST_ASSERT(rc == BLE_HS_ENOENT); + break; + + case BLE_GATT_REGISTER_OP_CHR: + /* Correct service UUID, wrong characteristic UUID. */ + memcpy(wrong_uuid, entry->chr->uuid128, 16); + wrong_uuid[15]++; + rc = ble_gatts_find_chr(entry->svc->uuid128, wrong_uuid, NULL, NULL); + TEST_ASSERT(rc == BLE_HS_ENOENT); + + /* Incorrect service UUID, correct characteristic UUID. */ + memcpy(wrong_uuid, entry->svc->uuid128, 16); + wrong_uuid[15]++; + rc = ble_gatts_find_chr(wrong_uuid, entry->chr->uuid128, NULL, NULL); + TEST_ASSERT(rc == BLE_HS_ENOENT); + + /* Existing (but wrong) service, correct characteristic UUID. */ + for (i = 0; i < ble_gatts_reg_test_num_entries; i++) { + cur = ble_gatts_reg_test_entries + i; + switch (cur->op) { + case BLE_GATT_REGISTER_OP_SVC: + if (cur->svc != entry->svc) { + rc = ble_gatts_find_chr(cur->svc->uuid128, + entry->chr->uuid128, + NULL, NULL); + TEST_ASSERT(rc == BLE_HS_ENOENT); + } + break; + + case BLE_GATT_REGISTER_OP_CHR: + /* Characteristic that isn't in this service. */ + if (cur->svc != entry->svc) { + rc = ble_gatts_find_chr(entry->svc->uuid128, + cur->chr->uuid128, + NULL, NULL); + TEST_ASSERT(rc == BLE_HS_ENOENT); + } + break; + + case BLE_GATT_REGISTER_OP_DSC: + /* Use descriptor UUID instead of characteristic UUID. */ + rc = ble_gatts_find_chr(entry->svc->uuid128, + cur->dsc->uuid128, + NULL, NULL); + TEST_ASSERT(rc == BLE_HS_ENOENT); + break; + + default: + TEST_ASSERT(0); + break; + } + } + break; + + case BLE_GATT_REGISTER_OP_DSC: + /* Correct svc/chr UUID, wrong dsc UUID. */ + memcpy(wrong_uuid, entry->dsc->uuid128, 16); + wrong_uuid[15]++; + rc = ble_gatts_find_dsc(entry->svc->uuid128, entry->chr->uuid128, + wrong_uuid, NULL); + TEST_ASSERT(rc == BLE_HS_ENOENT); + + /* Incorrect svc UUID, correct chr/dsc UUID. */ + memcpy(wrong_uuid, entry->svc->uuid128, 16); + wrong_uuid[15]++; + rc = ble_gatts_find_dsc(wrong_uuid, entry->chr->uuid128, + entry->dsc->uuid128, NULL); + TEST_ASSERT(rc == BLE_HS_ENOENT); + + for (i = 0; i < ble_gatts_reg_test_num_entries; i++) { + cur = ble_gatts_reg_test_entries + i; + switch (cur->op) { + case BLE_GATT_REGISTER_OP_SVC: + /* Existing (but wrong) svc, correct chr/dsc UUID. */ + if (cur->svc != entry->svc) { + rc = ble_gatts_find_dsc(cur->svc->uuid128, + entry->chr->uuid128, + entry->dsc->uuid128, + NULL); + TEST_ASSERT(rc == BLE_HS_ENOENT); + } + break; + + case BLE_GATT_REGISTER_OP_CHR: + /* Existing (but wrong) svc/chr, correct dsc UUID. */ + if (cur->chr != entry->chr) { + rc = ble_gatts_find_dsc(cur->svc->uuid128, + cur->chr->uuid128, + entry->dsc->uuid128, + NULL); + TEST_ASSERT(rc == BLE_HS_ENOENT); + } + break; + + case BLE_GATT_REGISTER_OP_DSC: + /* Descriptor that isn't in this characteristic. */ + if (cur->chr != entry->chr) { + rc = ble_gatts_find_dsc(cur->svc->uuid128, + cur->chr->uuid128, + entry->dsc->uuid128, + NULL); + TEST_ASSERT(rc == BLE_HS_ENOENT); + } + break; + + default: + TEST_ASSERT(0); + break; + } + } + break; + + default: + TEST_ASSERT(0); + break; + } +} + +static void +ble_gatts_reg_test_misc_verify_entry(uint8_t op, const uint8_t *uuid128) +{ + struct ble_gatts_reg_test_entry *entry; + int i; + + for (i = 0; i < ble_gatts_reg_test_num_entries; i++) { + entry = ble_gatts_reg_test_entries + i; + if (entry->op == op && memcmp(entry->uuid128, uuid128, 16) == 0) { + break; + } + } + TEST_ASSERT_FATAL(entry != NULL); + + /* Verify that characteristic value handle was properly assigned at + * registration. + */ + if (op == BLE_GATT_REGISTER_OP_CHR) { + TEST_ASSERT(*entry->chr->val_handle == entry->val_handle); + } + + /* Verify that the entry can be looked up. */ + ble_gatts_reg_test_misc_lookup_good(entry); + + /* Verify that "barely incorrect" UUID information doesn't retrieve any + * handles. + */ + ble_gatts_reg_test_misc_lookup_bad(entry); +} + +static int +ble_gatts_reg_test_misc_dummy_access(uint16_t conn_handle, + uint16_t attr_handle, + struct ble_gatt_access_ctxt *ctxt, + void *arg) +{ + return 0; +} + +TEST_CASE(ble_gatts_reg_test_svc_return) +{ + int rc; + + /*** Missing UUID. */ + ble_gatts_reg_test_init(); + struct ble_gatt_svc_def svcs_no_uuid[] = { { + .type = BLE_GATT_SVC_TYPE_PRIMARY, + }, { + 0 + } }; + + rc = ble_gatts_register_svcs(svcs_no_uuid, NULL, NULL); + TEST_ASSERT(rc == BLE_HS_EINVAL); + + /*** Circular dependency. */ + ble_gatts_reg_test_init(); + struct ble_gatt_svc_def svcs_circ[] = { { + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid128 = BLE_UUID16(0x1234), + .includes = (const struct ble_gatt_svc_def*[]) { svcs_circ + 1, NULL }, + }, { + .type = BLE_GATT_SVC_TYPE_SECONDARY, + .uuid128 = BLE_UUID16(0x1234), + .includes = (const struct ble_gatt_svc_def*[]) { svcs_circ + 0, NULL }, + }, { + 0 + } }; + + rc = ble_gatts_register_svcs(svcs_circ, NULL, NULL); + TEST_ASSERT(rc == BLE_HS_EINVAL); + + /*** Success. */ + ble_gatts_reg_test_init(); + struct ble_gatt_svc_def svcs_good[] = { { + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid128 = BLE_UUID16(0x1234), + .includes = (const struct ble_gatt_svc_def*[]) { svcs_good + 1, NULL }, + }, { + .type = BLE_GATT_SVC_TYPE_SECONDARY, + .uuid128 = BLE_UUID16(0x1234), + }, { + 0 + } }; + + rc = ble_gatts_register_svcs(svcs_good, NULL, NULL); + TEST_ASSERT(rc == 0); +} + +TEST_CASE(ble_gatts_reg_test_chr_return) +{ + int rc; + + /*** Missing callback. */ + ble_gatts_reg_test_init(); + struct ble_gatt_svc_def svcs_no_chr_cb[] = { { + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid128 = BLE_UUID16(0x1234), + .characteristics = (struct ble_gatt_chr_def[]) { { + .uuid128 = BLE_UUID16(0x1111), + .flags = BLE_GATT_CHR_F_READ, + }, { + 0 + } }, + }, { + 0 + } }; + + rc = ble_gatts_register_svcs(svcs_no_chr_cb, NULL, NULL); + TEST_ASSERT(rc == BLE_HS_EINVAL); + + /*** Success. */ + ble_gatts_reg_test_init(); + struct ble_gatt_svc_def svcs_good[] = { { + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid128 = BLE_UUID16(0x1234), + .characteristics = (struct ble_gatt_chr_def[]) { { + .uuid128 = BLE_UUID16(0x1111), + .access_cb = ble_gatts_reg_test_misc_dummy_access, + .flags = BLE_GATT_CHR_F_READ, + }, { + 0 + } }, + }, { + 0 + } }; + + rc = ble_gatts_register_svcs(svcs_good, NULL, NULL); + TEST_ASSERT(rc == 0); +} + +TEST_CASE(ble_gatts_reg_test_dsc_return) +{ + int rc; + + /*** Missing callback. */ + ble_gatts_reg_test_init(); + struct ble_gatt_svc_def svcs_no_dsc_cb[] = { { + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid128 = BLE_UUID16(0x1234), + .characteristics = (struct ble_gatt_chr_def[]) { { + .uuid128 = BLE_UUID16(0x1111), + .access_cb = ble_gatts_reg_test_misc_dummy_access, + .flags = BLE_GATT_CHR_F_READ, + .descriptors = (struct ble_gatt_dsc_def[]) { { + .uuid128 = BLE_UUID16(0x8888), + .att_flags = 5, + }, { + 0 + } }, + }, { + 0 + } }, + }, { + 0 + } }; + + rc = ble_gatts_register_svcs(svcs_no_dsc_cb, NULL, NULL); + TEST_ASSERT(rc == BLE_HS_EINVAL); + + /*** Success. */ + ble_gatts_reg_test_init(); + struct ble_gatt_svc_def svcs_good[] = { { + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid128 = BLE_UUID16(0x1234), + .characteristics = (struct ble_gatt_chr_def[]) { { + .uuid128 = BLE_UUID16(0x1111), + .access_cb = ble_gatts_reg_test_misc_dummy_access, + .flags = BLE_GATT_CHR_F_READ, + .descriptors = (struct ble_gatt_dsc_def[]) { { + .uuid128 = BLE_UUID16(0x8888), + .access_cb = ble_gatts_reg_test_misc_dummy_access, + .att_flags = 5, + }, { + 0 + } }, + }, { + 0 + } }, + }, { + 0 + } }; + + rc = ble_gatts_register_svcs(svcs_good, NULL, NULL); + TEST_ASSERT(rc == 0); +} + +static void +ble_gatts_reg_test_misc_svcs(struct ble_gatt_svc_def *svcs) +{ + const struct ble_gatt_svc_def *svc; + const struct ble_gatt_chr_def *chr; + const struct ble_gatt_dsc_def *dsc; + int rc; + + ble_gatts_reg_test_init(); + + /* Register all the attributes. */ + rc = ble_gatts_register_svcs(svcs, ble_gatts_reg_test_misc_reg_cb, + NULL); + TEST_ASSERT_FATAL(rc == 0); + + /* Verify that the appropriate callbacks were executed. */ + for (svc = svcs; svc->type != BLE_GATT_SVC_TYPE_END; svc++) { + ble_gatts_reg_test_misc_verify_entry(BLE_GATT_REGISTER_OP_SVC, + svc->uuid128); + + if (svc->characteristics != NULL) { + for (chr = svc->characteristics; chr->uuid128 != NULL; chr++) { + ble_gatts_reg_test_misc_verify_entry(BLE_GATT_REGISTER_OP_CHR, + chr->uuid128); + + if (chr->descriptors != NULL) { + for (dsc = chr->descriptors; dsc->uuid128 != NULL; dsc++) { + ble_gatts_reg_test_misc_verify_entry( + BLE_GATT_REGISTER_OP_DSC, dsc->uuid128); + } + } + } + } + } +} + +TEST_CASE(ble_gatts_reg_test_svc_cb) +{ + /*** 1 primary. */ + ble_gatts_reg_test_misc_svcs((struct ble_gatt_svc_def[]) { { + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid128 = BLE_UUID16(0x1234), + }, { + 0 + } }); + + /*** 3 primary. */ + ble_gatts_reg_test_misc_svcs((struct ble_gatt_svc_def[]) { { + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid128 = BLE_UUID16(0x1234), + }, { + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid128 = BLE_UUID16(0x2234), + }, { + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid128 = BLE_UUID16(0x3234), + }, { + 0 + } }); + + + /*** 1 primary, 1 secondary. */ + ble_gatts_reg_test_misc_svcs((struct ble_gatt_svc_def[]) { { + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid128 = BLE_UUID16(0x1234), + }, { + .type = BLE_GATT_SVC_TYPE_SECONDARY, + .uuid128 = BLE_UUID16(0x2222), + }, { + 0 + } }); + + /*** 1 primary, 1 secondary, 1 include. */ + struct ble_gatt_svc_def svcs[] = { + [0] = { + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid128 = BLE_UUID16(0x1234), + .includes = (const struct ble_gatt_svc_def*[]) { svcs + 1, NULL, }, + }, + [1] = { + .type = BLE_GATT_SVC_TYPE_SECONDARY, + .uuid128 = BLE_UUID16(0x2222), + }, { + 0 + } + }; + ble_gatts_reg_test_misc_svcs(svcs); +} + +TEST_CASE(ble_gatts_reg_test_chr_cb) +{ + uint16_t val_handles[16]; + + /*** 1 characteristic. */ + ble_gatts_reg_test_misc_svcs((struct ble_gatt_svc_def[]) { { + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid128 = BLE_UUID16(0x1234), + .characteristics = (struct ble_gatt_chr_def[]) { { + .uuid128 = BLE_UUID16(0x1111), + .access_cb = ble_gatts_reg_test_misc_dummy_access, + .flags = BLE_GATT_CHR_F_READ, + .val_handle = val_handles + 0, + }, { + 0 + } }, + }, { + 0 + } }); + + /*** 3 characteristics. */ + ble_gatts_reg_test_misc_svcs((struct ble_gatt_svc_def[]) { { + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid128 = BLE_UUID16(0x1234), + .characteristics = (struct ble_gatt_chr_def[]) { { + .uuid128 = BLE_UUID16(0x1111), + .access_cb = ble_gatts_reg_test_misc_dummy_access, + .flags = BLE_GATT_CHR_F_READ, + .val_handle = val_handles + 0, + }, { + .uuid128 = BLE_UUID16(0x2222), + .access_cb = ble_gatts_reg_test_misc_dummy_access, + .flags = BLE_GATT_CHR_F_WRITE, + .val_handle = val_handles + 1, + }, { + 0 + } }, + }, { + .type = BLE_GATT_SVC_TYPE_SECONDARY, + .uuid128 = BLE_UUID16(0x5678), + .characteristics = (struct ble_gatt_chr_def[]) { { + .uuid128 = BLE_UUID16(0x3333), + .access_cb = ble_gatts_reg_test_misc_dummy_access, + .flags = BLE_GATT_CHR_F_READ, + .val_handle = val_handles + 2, + }, { + 0 + } }, + }, { + 0 + } }); +} + +TEST_CASE(ble_gatts_reg_test_dsc_cb) +{ + uint16_t val_handles[16]; + + /*** 1 descriptor. */ + ble_gatts_reg_test_misc_svcs((struct ble_gatt_svc_def[]) { { + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid128 = BLE_UUID16(0x1234), + .characteristics = (struct ble_gatt_chr_def[]) { { + .uuid128 = BLE_UUID16(0x1111), + .access_cb = ble_gatts_reg_test_misc_dummy_access, + .flags = BLE_GATT_CHR_F_READ, + .val_handle = val_handles + 0, + .descriptors = (struct ble_gatt_dsc_def[]) { { + .uuid128 = BLE_UUID16(0x111a), + .att_flags = 5, + .access_cb = ble_gatts_reg_test_misc_dummy_access, + }, { + 0 + } }, + }, { + 0 + } }, + }, { + 0 + } }); + + /*** 5+ descriptors. */ + ble_gatts_reg_test_misc_svcs((struct ble_gatt_svc_def[]) { { + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid128 = BLE_UUID16(0x1234), + .characteristics = (struct ble_gatt_chr_def[]) { { + .uuid128 = BLE_UUID16(0x1111), + .access_cb = ble_gatts_reg_test_misc_dummy_access, + .flags = BLE_GATT_CHR_F_READ, + .val_handle = val_handles + 0, + .descriptors = (struct ble_gatt_dsc_def[]) { { + .uuid128 = BLE_UUID16(0x111a), + .att_flags = 5, + .access_cb = ble_gatts_reg_test_misc_dummy_access, + }, { + 0 + } }, + }, { + .uuid128 = BLE_UUID16(0x2222), + .access_cb = ble_gatts_reg_test_misc_dummy_access, + .flags = BLE_GATT_CHR_F_WRITE, + .val_handle = val_handles + 1, + }, { + 0 + } }, + }, { + .type = BLE_GATT_SVC_TYPE_SECONDARY, + .uuid128 = BLE_UUID16(0x5678), + .characteristics = (struct ble_gatt_chr_def[]) { { + .uuid128 = BLE_UUID16(0x3333), + .access_cb = ble_gatts_reg_test_misc_dummy_access, + .flags = BLE_GATT_CHR_F_READ, + .val_handle = val_handles + 2, + .descriptors = (struct ble_gatt_dsc_def[]) { { + .uuid128 = BLE_UUID16(0x333a), + .att_flags = 5, + .access_cb = ble_gatts_reg_test_misc_dummy_access, + }, { + .uuid128 = BLE_UUID16(0x333b), + .att_flags = 5, + .access_cb = ble_gatts_reg_test_misc_dummy_access, + }, { + .uuid128 = BLE_UUID16(0x333c), + .att_flags = 5, + .access_cb = ble_gatts_reg_test_misc_dummy_access, + }, { + .uuid128 = BLE_UUID16(0x333e), + .att_flags = 5, + .access_cb = ble_gatts_reg_test_misc_dummy_access, + }, { + 0 + } }, + }, { + .uuid128 = BLE_UUID16(0x4444), + .access_cb = ble_gatts_reg_test_misc_dummy_access, + .flags = BLE_GATT_CHR_F_READ, + .val_handle = val_handles + 3, + .descriptors = (struct ble_gatt_dsc_def[]) { { + .uuid128 = BLE_UUID16(0x444a), + .att_flags = 5, + .access_cb = ble_gatts_reg_test_misc_dummy_access, + }, { + .uuid128 = BLE_UUID16(0x444b), + .att_flags = 5, + .access_cb = ble_gatts_reg_test_misc_dummy_access, + }, { + .uuid128 = BLE_UUID16(0x444c), + .att_flags = 5, + .access_cb = ble_gatts_reg_test_misc_dummy_access, + }, { + .uuid128 = BLE_UUID16(0x444e), + .att_flags = 5, + .access_cb = ble_gatts_reg_test_misc_dummy_access, + }, { + 0 + } }, + }, { + 0 + } }, + }, { + 0 + } }); +} + +TEST_SUITE(ble_gatts_reg_suite) +{ + tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL); + + ble_gatts_reg_test_svc_return(); + ble_gatts_reg_test_chr_return(); + ble_gatts_reg_test_dsc_return(); + + ble_gatts_reg_test_svc_cb(); + ble_gatts_reg_test_chr_cb(); + ble_gatts_reg_test_dsc_cb(); +} + +int +ble_gatts_reg_test_all(void) +{ + ble_gatts_reg_suite(); + + return tu_any_failed; +}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d98ddc1c/net/nimble/host/test/src/ble_hs_adv_test.c ---------------------------------------------------------------------- diff --git a/net/nimble/host/test/src/ble_hs_adv_test.c b/net/nimble/host/test/src/ble_hs_adv_test.c new file mode 100644 index 0000000..e99fd5b --- /dev/null +++ b/net/nimble/host/test/src/ble_hs_adv_test.c @@ -0,0 +1,1486 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include <stddef.h> +#include <errno.h> +#include <string.h> +#include "testutil/testutil.h" +#include "nimble/hci_common.h" +#include "host/ble_hs_adv.h" +#include "host/ble_hs_test.h" +#include "ble_hs_test_util.h" + +#define BLE_ADV_TEST_DATA_OFF 4 + +static void +ble_hs_adv_test_misc_verify_tx_adv_data_hdr(uint8_t *cmd, int data_len) +{ + uint16_t opcode; + + opcode = le16toh(cmd + 0); + TEST_ASSERT(BLE_HCI_OGF(opcode) == BLE_HCI_OGF_LE); + TEST_ASSERT(BLE_HCI_OCF(opcode) == BLE_HCI_OCF_LE_SET_ADV_DATA); + + TEST_ASSERT(cmd[2] == BLE_HCI_SET_ADV_DATA_LEN); + TEST_ASSERT(cmd[3] == data_len); +} + +static void +ble_hs_adv_test_misc_verify_tx_rsp_data_hdr(uint8_t *cmd, int data_len) +{ + uint16_t opcode; + + opcode = le16toh(cmd + 0); + TEST_ASSERT(BLE_HCI_OGF(opcode) == BLE_HCI_OGF_LE); + TEST_ASSERT(BLE_HCI_OCF(opcode) == BLE_HCI_OCF_LE_SET_SCAN_RSP_DATA); + + TEST_ASSERT(cmd[2] == BLE_HCI_SET_SCAN_RSP_DATA_LEN); + TEST_ASSERT(cmd[3] == data_len); +} + +static void +ble_hs_adv_test_misc_verify_tx_field(uint8_t *cmd, uint8_t type, + uint8_t val_len, void *val) +{ + TEST_ASSERT(cmd[0] == val_len + 1); + TEST_ASSERT(cmd[1] == type); + TEST_ASSERT(memcmp(cmd + 2, val, val_len) == 0); +} + +struct ble_hs_adv_test_field { + uint8_t type; /* 0 indicates end of array. */ + uint8_t *val; + uint8_t val_len; +}; + +static int +ble_hs_adv_test_misc_calc_data_len(struct ble_hs_adv_test_field *fields) +{ + struct ble_hs_adv_test_field *field; + int len; + + len = 0; + if (fields != NULL) { + for (field = fields; field->type != 0; field++) { + len += 2 + field->val_len; + } + } + + return len; +} + +static void +ble_hs_adv_test_misc_verify_tx_fields(uint8_t *cmd, + struct ble_hs_adv_test_field *fields) +{ + struct ble_hs_adv_test_field *field; + + for (field = fields; field->type != 0; field++) { + ble_hs_adv_test_misc_verify_tx_field(cmd, field->type, field->val_len, + field->val); + cmd += 2 + field->val_len; + } +} + +static void +ble_hs_adv_test_misc_verify_tx_adv_data(struct ble_hs_adv_test_field *fields) +{ + int data_len; + uint8_t *cmd; + + cmd = ble_hs_test_util_get_last_hci_tx(); + TEST_ASSERT_FATAL(cmd != NULL); + + data_len = ble_hs_adv_test_misc_calc_data_len(fields); + ble_hs_adv_test_misc_verify_tx_adv_data_hdr(cmd, data_len); + if (fields != NULL) { + ble_hs_adv_test_misc_verify_tx_fields(cmd + BLE_ADV_TEST_DATA_OFF, + fields); + } +} + +static void +ble_hs_adv_test_misc_verify_tx_rsp_data(struct ble_hs_adv_test_field *fields) +{ + int data_len; + uint8_t *cmd; + + cmd = ble_hs_test_util_get_last_hci_tx(); + TEST_ASSERT_FATAL(cmd != NULL); + + data_len = ble_hs_adv_test_misc_calc_data_len(fields); + ble_hs_adv_test_misc_verify_tx_rsp_data_hdr(cmd, data_len); + if (fields != NULL) { + ble_hs_adv_test_misc_verify_tx_fields(cmd + BLE_ADV_TEST_DATA_OFF, + fields); + } +} + +static void +ble_hs_adv_test_misc_tx_and_verify_data( + uint8_t disc_mode, + struct ble_hs_adv_fields *adv_fields, + struct ble_hs_adv_test_field *test_adv_fields, + struct ble_hs_adv_fields *rsp_fields, + struct ble_hs_adv_test_field *test_rsp_fields) +{ + struct ble_gap_adv_params adv_params; + int rc; + + ble_hs_test_util_init(); + + adv_params = ble_hs_test_util_adv_params; + adv_params.disc_mode = disc_mode; + + rc = ble_hs_test_util_adv_set_fields(adv_fields, 0); + TEST_ASSERT_FATAL(rc == 0); + + rc = ble_gap_adv_rsp_set_fields(rsp_fields); + TEST_ASSERT_FATAL(rc == 0); + + rc = ble_hs_test_util_adv_start(BLE_ADDR_TYPE_PUBLIC, 0, NULL, &adv_params, + NULL, NULL, 0, 0); + TEST_ASSERT_FATAL(rc == 0); + + /* Discard the adv-enable command. */ + ble_hs_test_util_get_last_hci_tx(); + + ble_hs_adv_test_misc_verify_tx_rsp_data(test_rsp_fields); + ble_hs_adv_test_misc_verify_tx_adv_data(test_adv_fields); + + /* Ensure the same data gets sent on repeated advertise procedures. */ + rc = ble_hs_test_util_adv_stop(0); + TEST_ASSERT_FATAL(rc == 0); + + rc = ble_hs_test_util_adv_start(BLE_ADDR_TYPE_PUBLIC, 0, NULL, &adv_params, + NULL, NULL, 0, 0); + TEST_ASSERT_FATAL(rc == 0); + + /* Discard the adv-enable command. */ + ble_hs_test_util_get_last_hci_tx(); + + ble_hs_adv_test_misc_verify_tx_rsp_data(test_rsp_fields); + ble_hs_adv_test_misc_verify_tx_adv_data(test_adv_fields); +} + +TEST_CASE(ble_hs_adv_test_case_flags) +{ + struct ble_hs_adv_fields adv_fields; + struct ble_hs_adv_fields rsp_fields; + + memset(&adv_fields, 0, sizeof adv_fields); + memset(&rsp_fields, 0, sizeof rsp_fields); + + /* Default flags. */ + adv_fields.flags_is_present = 1; + adv_fields.tx_pwr_lvl_is_present = 1; + adv_fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO; + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, + &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, &rsp_fields, NULL); + + /* Flags |= limited discoverable. */ + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_LTD, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]) { + BLE_HS_ADV_F_DISC_LTD | BLE_HS_ADV_F_BREDR_UNSUP + }, + .val_len = 1, + }, + { 0 }, + }, &rsp_fields, NULL); + + /* Flags = general discoverable. */ + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_GEN, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]) { + BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP + }, + .val_len = 1, + }, + { 0 }, + }, &rsp_fields, NULL); +} + +TEST_CASE(ble_hs_adv_test_case_user) +{ + struct ble_hs_adv_fields adv_fields; + struct ble_hs_adv_fields rsp_fields; + + memset(&rsp_fields, 0, sizeof rsp_fields); + + /*** Complete 16-bit service class UUIDs. */ + memset(&adv_fields, 0, sizeof adv_fields); + adv_fields.flags_is_present = 1; + adv_fields.tx_pwr_lvl_is_present = 1; + adv_fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO; + adv_fields.uuids16 = (uint16_t[]) { 0x0001, 0x1234, 0x54ab }; + adv_fields.num_uuids16 = 3; + adv_fields.uuids16_is_complete = 1; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_COMP_UUIDS16, + .val = (uint8_t[]) { 0x01, 0x00, 0x34, 0x12, 0xab, 0x54 }, + .val_len = 6, + }, + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, &rsp_fields, NULL); + + /*** Incomplete 16-bit service class UUIDs. */ + memset(&adv_fields, 0, sizeof adv_fields); + adv_fields.flags_is_present = 1; + adv_fields.tx_pwr_lvl_is_present = 1; + adv_fields.uuids16 = (uint16_t[]) { 0x0001, 0x1234, 0x54ab }; + adv_fields.num_uuids16 = 3; + adv_fields.uuids16_is_complete = 0; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_INCOMP_UUIDS16, + .val = (uint8_t[]) { 0x01, 0x00, 0x34, 0x12, 0xab, 0x54 }, + .val_len = 6, + }, + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, &rsp_fields, NULL); + + /*** Complete 32-bit service class UUIDs. */ + memset(&adv_fields, 0, sizeof adv_fields); + adv_fields.flags_is_present = 1; + adv_fields.tx_pwr_lvl_is_present = 1; + adv_fields.uuids32 = (uint32_t[]) { 0x12345678, 0xabacadae }; + adv_fields.num_uuids32 = 2; + adv_fields.uuids32_is_complete = 1; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_COMP_UUIDS32, + .val = (uint8_t[]) { 0x78,0x56,0x34,0x12,0xae,0xad,0xac,0xab }, + .val_len = 8, + }, + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, &rsp_fields, NULL); + + /*** Incomplete 32-bit service class UUIDs. */ + memset(&adv_fields, 0, sizeof adv_fields); + adv_fields.flags_is_present = 1; + adv_fields.tx_pwr_lvl_is_present = 1; + adv_fields.uuids32 = (uint32_t[]) { 0x12345678, 0xabacadae }; + adv_fields.num_uuids32 = 2; + adv_fields.uuids32_is_complete = 0; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_INCOMP_UUIDS32, + .val = (uint8_t[]) { 0x78,0x56,0x34,0x12,0xae,0xad,0xac,0xab }, + .val_len = 8, + }, + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, &rsp_fields, NULL); + + /*** Complete 128-bit service class UUIDs. */ + memset(&adv_fields, 0, sizeof adv_fields); + adv_fields.flags_is_present = 1; + adv_fields.tx_pwr_lvl_is_present = 1; + adv_fields.uuids128 = (uint8_t[]) { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, + }; + adv_fields.num_uuids128 = 1; + adv_fields.uuids128_is_complete = 1; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_COMP_UUIDS128, + .val = (uint8_t[]) { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, + }, + .val_len = 16, + }, + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, &rsp_fields, NULL); + + /*** Incomplete 128-bit service class UUIDs. */ + memset(&adv_fields, 0, sizeof adv_fields); + adv_fields.flags_is_present = 1; + adv_fields.tx_pwr_lvl_is_present = 1; + adv_fields.uuids128 = (uint8_t[]) { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, + }; + adv_fields.num_uuids128 = 1; + adv_fields.uuids128_is_complete = 0; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_INCOMP_UUIDS128, + .val = (uint8_t[]) { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, + }, + .val_len = 16, + }, + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, &rsp_fields, NULL); + + /*** Complete name. */ + memset(&adv_fields, 0, sizeof adv_fields); + adv_fields.flags_is_present = 1; + adv_fields.tx_pwr_lvl_is_present = 1; + adv_fields.name = (uint8_t *)"myname"; + adv_fields.name_len = 6; + adv_fields.name_is_complete = 1; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_COMP_NAME, + .val = (uint8_t*)"myname", + .val_len = 6, + }, + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, &rsp_fields, NULL); + + /*** Incomplete name. */ + memset(&adv_fields, 0, sizeof adv_fields); + adv_fields.flags_is_present = 1; + adv_fields.tx_pwr_lvl_is_present = 1; + adv_fields.name = (uint8_t *)"myname"; + adv_fields.name_len = 6; + adv_fields.name_is_complete = 0; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_INCOMP_NAME, + .val = (uint8_t*)"myname", + .val_len = 6, + }, + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, &rsp_fields, NULL); + + /*** Class of device. */ + memset(&adv_fields, 0, sizeof adv_fields); + adv_fields.flags_is_present = 1; + adv_fields.tx_pwr_lvl_is_present = 1; + adv_fields.device_class = (uint8_t[]){ 1,2,3 }; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_DEVICE_CLASS, + .val = (uint8_t[]) { 1,2,3 }, + .val_len = BLE_HS_ADV_DEVICE_CLASS_LEN, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, &rsp_fields, NULL); + + /*** Slave interval range. */ + memset(&adv_fields, 0, sizeof adv_fields); + adv_fields.flags_is_present = 1; + adv_fields.tx_pwr_lvl_is_present = 1; + adv_fields.slave_itvl_range = (uint8_t[]){ 1,2,3,4 }; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_SLAVE_ITVL_RANGE, + .val = (uint8_t[]) { 1,2,3,4 }, + .val_len = BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, &rsp_fields, NULL); + + /*** 0x16 - Service data - 16-bit UUID. */ + memset(&adv_fields, 0, sizeof adv_fields); + adv_fields.flags_is_present = 1; + adv_fields.tx_pwr_lvl_is_present = 1; + adv_fields.svc_data_uuid16 = (uint8_t[]){ 1,2,3,4 }; + adv_fields.svc_data_uuid16_len = 4; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_SVC_DATA_UUID16, + .val = (uint8_t[]) { 1,2,3,4 }, + .val_len = 4, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, &rsp_fields, NULL); + + /*** 0x17 - Public target address. */ + memset(&adv_fields, 0, sizeof adv_fields); + adv_fields.flags_is_present = 1; + adv_fields.tx_pwr_lvl_is_present = 1; + adv_fields.public_tgt_addr = (uint8_t[]){ 1,2,3,4,5,6, 6,5,4,3,2,1 }; + adv_fields.num_public_tgt_addrs = 2; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR, + .val = (uint8_t[]){ 1,2,3,4,5,6, 6,5,4,3,2,1 }, + .val_len = 2 * BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, &rsp_fields, NULL); + + /*** 0x19 - Appearance. */ + memset(&adv_fields, 0, sizeof adv_fields); + adv_fields.flags_is_present = 1; + adv_fields.tx_pwr_lvl_is_present = 1; + adv_fields.appearance = 0x1234; + adv_fields.appearance_is_present = 1; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_APPEARANCE, + .val = (uint8_t[]){ 0x34, 0x12 }, + .val_len = BLE_HS_ADV_APPEARANCE_LEN, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, &rsp_fields, NULL); + + /*** 0x1a - Advertising interval. */ + memset(&adv_fields, 0, sizeof adv_fields); + adv_fields.flags_is_present = 1; + adv_fields.tx_pwr_lvl_is_present = 1; + adv_fields.adv_itvl = 0x1234; + adv_fields.adv_itvl_is_present = 1; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_ADV_ITVL, + .val = (uint8_t[]){ 0x34, 0x12 }, + .val_len = BLE_HS_ADV_ADV_ITVL_LEN, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, &rsp_fields, NULL); + + /*** 0x1b - LE bluetooth device address. */ + memset(&adv_fields, 0, sizeof adv_fields); + adv_fields.flags_is_present = 1; + adv_fields.tx_pwr_lvl_is_present = 1; + adv_fields.le_addr = (uint8_t[]){ 1,2,3,4,5,6,7 }; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_LE_ADDR, + .val = (uint8_t[]) { 1,2,3,4,5,6,7 }, + .val_len = BLE_HS_ADV_LE_ADDR_LEN, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, &rsp_fields, NULL); + + /*** 0x1c - LE role. */ + memset(&adv_fields, 0, sizeof adv_fields); + adv_fields.flags_is_present = 1; + adv_fields.tx_pwr_lvl_is_present = 1; + adv_fields.le_role = BLE_HS_ADV_LE_ROLE_BOTH_PERIPH_PREF; + adv_fields.le_role_is_present = 1; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_LE_ROLE, + .val = (uint8_t[]) { BLE_HS_ADV_LE_ROLE_BOTH_PERIPH_PREF }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, &rsp_fields, NULL); + + /*** 0x20 - Service data - 32-bit UUID. */ + memset(&adv_fields, 0, sizeof adv_fields); + adv_fields.flags_is_present = 1; + adv_fields.tx_pwr_lvl_is_present = 1; + adv_fields.svc_data_uuid32 = (uint8_t[]){ 1,2,3,4,5 }; + adv_fields.svc_data_uuid32_len = 5; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_SVC_DATA_UUID32, + .val = (uint8_t[]) { 1,2,3,4,5 }, + .val_len = 5, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, &rsp_fields, NULL); + + /*** 0x21 - Service data - 128-bit UUID. */ + memset(&adv_fields, 0, sizeof adv_fields); + adv_fields.flags_is_present = 1; + adv_fields.tx_pwr_lvl_is_present = 1; + adv_fields.svc_data_uuid128 = + (uint8_t[]){ 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18 }; + adv_fields.svc_data_uuid128_len = 18; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_SVC_DATA_UUID128, + .val = (uint8_t[]){ 1,2,3,4,5,6,7,8,9,10, + 11,12,13,14,15,16,17,18 }, + .val_len = 18, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, &rsp_fields, NULL); + + /*** 0x24 - URI. */ + memset(&adv_fields, 0, sizeof adv_fields); + adv_fields.flags_is_present = 1; + adv_fields.tx_pwr_lvl_is_present = 1; + adv_fields.uri = (uint8_t[]){ 1,2,3,4 }; + adv_fields.uri_len = 4; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_URI, + .val = (uint8_t[]) { 1,2,3,4 }, + .val_len = 4, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, &rsp_fields, NULL); + + /*** 0xff - Manufacturer specific data. */ + memset(&adv_fields, 0, sizeof adv_fields); + adv_fields.flags_is_present = 1; + adv_fields.tx_pwr_lvl_is_present = 1; + adv_fields.mfg_data = (uint8_t[]){ 1,2,3,4 }; + adv_fields.mfg_data_len = 4; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_MFG_DATA, + .val = (uint8_t[]) { 1,2,3,4 }, + .val_len = 4, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, &rsp_fields, NULL); +} + +TEST_CASE(ble_hs_adv_test_case_user_rsp) +{ + struct ble_hs_adv_fields rsp_fields; + struct ble_hs_adv_fields adv_fields; + + memset(&adv_fields, 0, sizeof adv_fields); + adv_fields.flags_is_present = 1; + adv_fields.tx_pwr_lvl_is_present = 1; + + /*** Complete 16-bit service class UUIDs. */ + memset(&rsp_fields, 0, sizeof rsp_fields); + rsp_fields.uuids16 = (uint16_t[]) { 0x0001, 0x1234, 0x54ab }; + rsp_fields.num_uuids16 = 3; + rsp_fields.uuids16_is_complete = 1; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, + &rsp_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_COMP_UUIDS16, + .val = (uint8_t[]) { 0x01, 0x00, 0x34, 0x12, 0xab, 0x54 }, + .val_len = 6, + }, + { 0 }, + }); + + /*** Incomplete 16-bit service class UUIDs. */ + memset(&rsp_fields, 0, sizeof rsp_fields); + rsp_fields.uuids16 = (uint16_t[]) { 0x0001, 0x1234, 0x54ab }; + rsp_fields.num_uuids16 = 3; + rsp_fields.uuids16_is_complete = 0; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, + &rsp_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_INCOMP_UUIDS16, + .val = (uint8_t[]) { 0x01, 0x00, 0x34, 0x12, 0xab, 0x54 }, + .val_len = 6, + }, + { 0 }, + }); + + /*** Complete 32-bit service class UUIDs. */ + memset(&rsp_fields, 0, sizeof rsp_fields); + rsp_fields.uuids32 = (uint32_t[]) { 0x12345678, 0xabacadae }; + rsp_fields.num_uuids32 = 2; + rsp_fields.uuids32_is_complete = 1; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, + &rsp_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_COMP_UUIDS32, + .val = (uint8_t[]) { 0x78,0x56,0x34,0x12,0xae,0xad,0xac,0xab }, + .val_len = 8, + }, + { 0 }, + }); + + /*** Incomplete 32-bit service class UUIDs. */ + memset(&rsp_fields, 0, sizeof rsp_fields); + rsp_fields.uuids32 = (uint32_t[]) { 0x12345678, 0xabacadae }; + rsp_fields.num_uuids32 = 2; + rsp_fields.uuids32_is_complete = 0; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, + &rsp_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_INCOMP_UUIDS32, + .val = (uint8_t[]) { 0x78,0x56,0x34,0x12,0xae,0xad,0xac,0xab }, + .val_len = 8, + }, + { 0 }, + }); + + /*** Complete 128-bit service class UUIDs. */ + memset(&rsp_fields, 0, sizeof rsp_fields); + rsp_fields.uuids128 = (uint8_t[]) { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, + }; + rsp_fields.num_uuids128 = 1; + rsp_fields.uuids128_is_complete = 1; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, + &rsp_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_COMP_UUIDS128, + .val = (uint8_t[]) { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, + }, + .val_len = 16, + }, + { 0 }, + }); + + /*** Incomplete 128-bit service class UUIDs. */ + memset(&rsp_fields, 0, sizeof rsp_fields); + rsp_fields.uuids128 = (uint8_t[]) { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, + }; + rsp_fields.num_uuids128 = 1; + rsp_fields.uuids128_is_complete = 0; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, + &rsp_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_INCOMP_UUIDS128, + .val = (uint8_t[]) { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, + }, + .val_len = 16, + }, + { 0 }, + }); + + /*** Complete name. */ + memset(&rsp_fields, 0, sizeof rsp_fields); + rsp_fields.name = (uint8_t *)"myname"; + rsp_fields.name_len = 6; + rsp_fields.name_is_complete = 1; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, + &rsp_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_COMP_NAME, + .val = (uint8_t*)"myname", + .val_len = 6, + }, + { 0 }, + }); + + /*** Incomplete name. */ + memset(&rsp_fields, 0, sizeof rsp_fields); + rsp_fields.name = (uint8_t *)"myname"; + rsp_fields.name_len = 6; + rsp_fields.name_is_complete = 0; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, + &rsp_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_INCOMP_NAME, + .val = (uint8_t*)"myname", + .val_len = 6, + }, + { 0 }, + }); + + /*** Class of device. */ + memset(&rsp_fields, 0, sizeof rsp_fields); + rsp_fields.device_class = (uint8_t[]){ 1,2,3 }; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, + &rsp_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_DEVICE_CLASS, + .val = (uint8_t[]) { 1,2,3 }, + .val_len = BLE_HS_ADV_DEVICE_CLASS_LEN, + }, + { 0 }, + }); + + /*** Slave interval range. */ + memset(&rsp_fields, 0, sizeof rsp_fields); + rsp_fields.slave_itvl_range = (uint8_t[]){ 1,2,3,4 }; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, + &rsp_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_SLAVE_ITVL_RANGE, + .val = (uint8_t[]) { 1,2,3,4 }, + .val_len = BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN, + }, + { 0 }, + }); + + /*** 0x16 - Service data - 16-bit UUID. */ + memset(&rsp_fields, 0, sizeof rsp_fields); + rsp_fields.svc_data_uuid16 = (uint8_t[]){ 1,2,3,4 }; + rsp_fields.svc_data_uuid16_len = 4; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, + &rsp_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_SVC_DATA_UUID16, + .val = (uint8_t[]) { 1,2,3,4 }, + .val_len = 4, + }, + { 0 }, + }); + + /*** 0x17 - Public target address. */ + memset(&rsp_fields, 0, sizeof rsp_fields); + rsp_fields.public_tgt_addr = (uint8_t[]){ 1,2,3,4,5,6, 6,5,4,3,2,1 }; + rsp_fields.num_public_tgt_addrs = 2; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, + &rsp_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR, + .val = (uint8_t[]){ 1,2,3,4,5,6, 6,5,4,3,2,1 }, + .val_len = 2 * BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN, + }, + { 0 }, + }); + + /*** 0x19 - Appearance. */ + memset(&rsp_fields, 0, sizeof rsp_fields); + rsp_fields.appearance = 0x1234; + rsp_fields.appearance_is_present = 1; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, + &rsp_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_APPEARANCE, + .val = (uint8_t[]){ 0x34, 0x12 }, + .val_len = BLE_HS_ADV_APPEARANCE_LEN, + }, + { 0 }, + }); + + /*** 0x1a - Advertising interval. */ + memset(&rsp_fields, 0, sizeof rsp_fields); + rsp_fields.adv_itvl = 0x1234; + rsp_fields.adv_itvl_is_present = 1; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, + &rsp_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_ADV_ITVL, + .val = (uint8_t[]){ 0x34, 0x12 }, + .val_len = BLE_HS_ADV_ADV_ITVL_LEN, + }, + { 0 }, + }); + + /*** 0x1b - LE bluetooth device address. */ + memset(&rsp_fields, 0, sizeof rsp_fields); + rsp_fields.le_addr = (uint8_t[]){ 1,2,3,4,5,6,7 }; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, + &rsp_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_LE_ADDR, + .val = (uint8_t[]) { 1,2,3,4,5,6,7 }, + .val_len = BLE_HS_ADV_LE_ADDR_LEN, + }, + { 0 }, + }); + + /*** 0x1c - LE role. */ + memset(&rsp_fields, 0, sizeof rsp_fields); + rsp_fields.le_role = BLE_HS_ADV_LE_ROLE_BOTH_PERIPH_PREF; + rsp_fields.le_role_is_present = 1; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, + &rsp_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_LE_ROLE, + .val = (uint8_t[]) { BLE_HS_ADV_LE_ROLE_BOTH_PERIPH_PREF }, + .val_len = 1, + }, + { 0 }, + }); + + /*** 0x20 - Service data - 32-bit UUID. */ + memset(&rsp_fields, 0, sizeof rsp_fields); + rsp_fields.svc_data_uuid32 = (uint8_t[]){ 1,2,3,4,5 }; + rsp_fields.svc_data_uuid32_len = 5; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, + &rsp_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_SVC_DATA_UUID32, + .val = (uint8_t[]) { 1,2,3,4,5 }, + .val_len = 5, + }, + { 0 }, + }); + + /*** 0x21 - Service data - 128-bit UUID. */ + memset(&rsp_fields, 0, sizeof rsp_fields); + rsp_fields.svc_data_uuid128 = + (uint8_t[]){ 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18 }; + rsp_fields.svc_data_uuid128_len = 18; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, + &rsp_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_SVC_DATA_UUID128, + .val = (uint8_t[]){ 1,2,3,4,5,6,7,8,9,10, + 11,12,13,14,15,16,17,18 }, + .val_len = 18, + }, + { 0 }, + }); + + /*** 0x24 - URI. */ + memset(&rsp_fields, 0, sizeof rsp_fields); + rsp_fields.uri = (uint8_t[]){ 1,2,3,4 }; + rsp_fields.uri_len = 4; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, + &rsp_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_URI, + .val = (uint8_t[]) { 1,2,3,4 }, + .val_len = 4, + }, + { 0 }, + }); + + /*** 0xff - Manufacturer specific data. */ + memset(&rsp_fields, 0, sizeof rsp_fields); + rsp_fields.mfg_data = (uint8_t[]){ 1,2,3,4 }; + rsp_fields.mfg_data_len = 4; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_TX_PWR_LVL, + .val = (uint8_t[]){ 0 }, + .val_len = 1, + }, + { + .type = BLE_HS_ADV_TYPE_FLAGS, + .val = (uint8_t[]){ BLE_HS_ADV_F_BREDR_UNSUP }, + .val_len = 1, + }, + { 0 }, + }, + &rsp_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_MFG_DATA, + .val = (uint8_t[]) { 1,2,3,4 }, + .val_len = 4, + }, + { 0 }, + }); +} + +TEST_CASE(ble_hs_adv_test_case_user_full_payload) +{ + /* Intentionally allocate an extra byte. */ + static const uint8_t mfg_data[30] = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, + }; + + struct ble_hs_adv_fields adv_fields; + struct ble_hs_adv_fields rsp_fields; + int rc; + + ble_hs_test_util_init(); + + memset(&rsp_fields, 0, sizeof rsp_fields); + + /*** + * An advertisement should allow 31 bytes of user data. Each field has a + * two-byte header, leaving 29 bytes of payload. + */ + memset(&adv_fields, 0, sizeof adv_fields); + adv_fields.mfg_data = (void *)mfg_data; + adv_fields.mfg_data_len = 29; + + ble_hs_adv_test_misc_tx_and_verify_data(BLE_GAP_DISC_MODE_NON, &adv_fields, + (struct ble_hs_adv_test_field[]) { + { + .type = BLE_HS_ADV_TYPE_MFG_DATA, + .val = (void *)mfg_data, + .val_len = 29, + }, + { 0 }, + }, &rsp_fields, NULL); + + /*** Fail with 30 bytes. */ + rc = ble_hs_test_util_adv_stop(0); + TEST_ASSERT_FATAL(rc == 0); + + adv_fields.mfg_data_len = 30; + rc = ble_gap_adv_set_fields(&adv_fields); + TEST_ASSERT(rc == BLE_HS_EMSGSIZE); +} + +TEST_SUITE(ble_hs_adv_test_suite) +{ + tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL); + + ble_hs_adv_test_case_flags(); + ble_hs_adv_test_case_user(); + ble_hs_adv_test_case_user_rsp(); + ble_hs_adv_test_case_user_full_payload(); +} + +int +ble_hs_adv_test_all(void) +{ + ble_hs_adv_test_suite(); + + return tu_any_failed; +} + http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d98ddc1c/net/nimble/host/test/src/ble_hs_conn_test.c ---------------------------------------------------------------------- diff --git a/net/nimble/host/test/src/ble_hs_conn_test.c b/net/nimble/host/test/src/ble_hs_conn_test.c new file mode 100644 index 0000000..c957446 --- /dev/null +++ b/net/nimble/host/test/src/ble_hs_conn_test.c @@ -0,0 +1,219 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include <stddef.h> +#include <errno.h> +#include <string.h> +#include "testutil/testutil.h" +#include "nimble/hci_common.h" +#include "host/ble_hs_adv.h" +#include "host/ble_hs_test.h" +#include "ble_hs_test_util.h" + +static int +ble_hs_conn_test_util_any() +{ + struct ble_hs_conn *conn; + + ble_hs_lock(); + conn = ble_hs_conn_first(); + ble_hs_unlock(); + + return conn != NULL; +} + +TEST_CASE(ble_hs_conn_test_direct_connect_success) +{ + struct hci_le_conn_complete evt; + struct ble_l2cap_chan *chan; + struct ble_hs_conn *conn; + uint8_t addr[6] = { 1, 2, 3, 4, 5, 6 }; + int rc; + + ble_hs_test_util_init(); + + /* Ensure no current or pending connections. */ + TEST_ASSERT(!ble_gap_master_in_progress()); + TEST_ASSERT(!ble_hs_conn_test_util_any()); + + /* Initiate connection. */ + rc = ble_hs_test_util_connect(BLE_ADDR_TYPE_PUBLIC, + BLE_ADDR_TYPE_PUBLIC, + addr, 0, NULL, NULL, NULL, 0); + TEST_ASSERT(rc == 0); + + TEST_ASSERT(ble_gap_master_in_progress()); + + /* Receive successful connection complete event. */ + memset(&evt, 0, sizeof evt); + evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE; + evt.status = BLE_ERR_SUCCESS; + evt.connection_handle = 2; + evt.role = BLE_HCI_LE_CONN_COMPLETE_ROLE_MASTER; + memcpy(evt.peer_addr, addr, 6); + rc = ble_gap_rx_conn_complete(&evt); + TEST_ASSERT(rc == 0); + TEST_ASSERT(!ble_gap_master_in_progress()); + + ble_hs_lock(); + + conn = ble_hs_conn_first(); + TEST_ASSERT_FATAL(conn != NULL); + TEST_ASSERT(conn->bhc_handle == 2); + TEST_ASSERT(memcmp(conn->bhc_peer_addr, addr, 6) == 0); + + chan = ble_hs_conn_chan_find(conn, BLE_L2CAP_CID_ATT); + TEST_ASSERT_FATAL(chan != NULL); + TEST_ASSERT(chan->blc_my_mtu == BLE_ATT_MTU_PREFERRED_DFLT); + TEST_ASSERT(chan->blc_peer_mtu == 0); + TEST_ASSERT(chan->blc_default_mtu == BLE_ATT_MTU_DFLT); + + ble_hs_unlock(); +} + +TEST_CASE(ble_hs_conn_test_direct_connectable_success) +{ + struct hci_le_conn_complete evt; + struct ble_gap_adv_params adv_params; + struct ble_l2cap_chan *chan; + struct ble_hs_conn *conn; + uint8_t addr[6] = { 1, 2, 3, 4, 5, 6 }; + int rc; + + ble_hs_test_util_init(); + + /* Ensure no current or pending connections. */ + TEST_ASSERT(!ble_gap_master_in_progress()); + TEST_ASSERT(!ble_gap_adv_active()); + TEST_ASSERT(!ble_hs_conn_test_util_any()); + + /* Initiate advertising. */ + adv_params = ble_hs_test_util_adv_params; + adv_params.conn_mode = BLE_GAP_CONN_MODE_DIR; + rc = ble_hs_test_util_adv_start(BLE_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_PUBLIC, + addr, &adv_params, NULL, NULL, 0, 0); + TEST_ASSERT(rc == 0); + + TEST_ASSERT(!ble_gap_master_in_progress()); + TEST_ASSERT(ble_gap_adv_active()); + + /* Receive successful connection complete event. */ + memset(&evt, 0, sizeof evt); + evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE; + evt.status = BLE_ERR_SUCCESS; + evt.connection_handle = 2; + evt.role = BLE_HCI_LE_CONN_COMPLETE_ROLE_SLAVE; + memcpy(evt.peer_addr, addr, 6); + rc = ble_gap_rx_conn_complete(&evt); + TEST_ASSERT(rc == 0); + TEST_ASSERT(!ble_gap_master_in_progress()); + TEST_ASSERT(!ble_gap_adv_active()); + + ble_hs_lock(); + + conn = ble_hs_conn_first(); + TEST_ASSERT_FATAL(conn != NULL); + TEST_ASSERT(conn->bhc_handle == 2); + TEST_ASSERT(memcmp(conn->bhc_peer_addr, addr, 6) == 0); + + chan = ble_hs_conn_chan_find(conn, BLE_L2CAP_CID_ATT); + TEST_ASSERT_FATAL(chan != NULL); + TEST_ASSERT(chan->blc_my_mtu == BLE_ATT_MTU_PREFERRED_DFLT); + TEST_ASSERT(chan->blc_peer_mtu == 0); + TEST_ASSERT(chan->blc_default_mtu == BLE_ATT_MTU_DFLT); + + ble_hs_unlock(); +} + +TEST_CASE(ble_hs_conn_test_undirect_connectable_success) +{ + struct ble_hs_adv_fields adv_fields; + struct hci_le_conn_complete evt; + struct ble_gap_adv_params adv_params; + struct ble_l2cap_chan *chan; + struct ble_hs_conn *conn; + uint8_t addr[6] = { 1, 2, 3, 4, 5, 6 }; + int rc; + + ble_hs_test_util_init(); + + /* Ensure no current or pending connections. */ + TEST_ASSERT(!ble_gap_master_in_progress()); + TEST_ASSERT(!ble_gap_adv_active()); + TEST_ASSERT(!ble_hs_conn_test_util_any()); + + /* Initiate advertising. */ + memset(&adv_fields, 0, sizeof adv_fields); + adv_fields.tx_pwr_lvl_is_present = 1; + rc = ble_gap_adv_set_fields(&adv_fields); + TEST_ASSERT_FATAL(rc == 0); + + adv_params = ble_hs_test_util_adv_params; + adv_params.conn_mode = BLE_GAP_CONN_MODE_UND; + rc = ble_hs_test_util_adv_start(BLE_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_PUBLIC, + addr, &adv_params, NULL, NULL, 0, 0); + TEST_ASSERT(rc == 0); + + TEST_ASSERT(!ble_gap_master_in_progress()); + TEST_ASSERT(ble_gap_adv_active()); + + /* Receive successful connection complete event. */ + memset(&evt, 0, sizeof evt); + evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE; + evt.status = BLE_ERR_SUCCESS; + evt.connection_handle = 2; + evt.role = BLE_HCI_LE_CONN_COMPLETE_ROLE_SLAVE; + memcpy(evt.peer_addr, addr, 6); + rc = ble_gap_rx_conn_complete(&evt); + TEST_ASSERT(rc == 0); + TEST_ASSERT(!ble_gap_master_in_progress()); + TEST_ASSERT(!ble_gap_adv_active()); + + ble_hs_lock(); + + conn = ble_hs_conn_first(); + TEST_ASSERT_FATAL(conn != NULL); + TEST_ASSERT(conn->bhc_handle == 2); + TEST_ASSERT(memcmp(conn->bhc_peer_addr, addr, 6) == 0); + + chan = ble_hs_conn_chan_find(conn, BLE_L2CAP_CID_ATT); + TEST_ASSERT_FATAL(chan != NULL); + TEST_ASSERT(chan->blc_my_mtu == BLE_ATT_MTU_PREFERRED_DFLT); + TEST_ASSERT(chan->blc_peer_mtu == 0); + TEST_ASSERT(chan->blc_default_mtu == BLE_ATT_MTU_DFLT); + + ble_hs_unlock(); +} + +TEST_SUITE(conn_suite) +{ + tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL); + + ble_hs_conn_test_direct_connect_success(); + ble_hs_conn_test_direct_connectable_success(); + ble_hs_conn_test_undirect_connectable_success(); +} + +int +ble_hs_conn_test_all(void) +{ + conn_suite(); + + return tu_any_failed; +} http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d98ddc1c/net/nimble/host/test/src/ble_hs_hci_test.c ---------------------------------------------------------------------- diff --git a/net/nimble/host/test/src/ble_hs_hci_test.c b/net/nimble/host/test/src/ble_hs_hci_test.c new file mode 100644 index 0000000..21184b8 --- /dev/null +++ b/net/nimble/host/test/src/ble_hs_hci_test.c @@ -0,0 +1,99 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include <stddef.h> +#include <errno.h> +#include <string.h> +#include "nimble/hci_common.h" +#include "nimble/ble_hci_trans.h" +#include "host/ble_hs_test.h" +#include "testutil/testutil.h" +#include "ble_hs_test_util.h" + +TEST_CASE(ble_hs_hci_test_event_bad) +{ + uint8_t *buf; + int rc; + + /*** Invalid event code. */ + buf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); + TEST_ASSERT_FATAL(buf != NULL); + + buf[0] = 0xff; + buf[1] = 0; + rc = ble_hs_hci_evt_process(buf); + TEST_ASSERT(rc == BLE_HS_ENOTSUP); +} + +TEST_CASE(ble_hs_hci_test_rssi) +{ + uint8_t params[BLE_HCI_READ_RSSI_ACK_PARAM_LEN]; + uint16_t opcode; + int8_t rssi; + int rc; + + opcode = ble_hs_hci_util_opcode_join(BLE_HCI_OGF_STATUS_PARAMS, + BLE_HCI_OCF_RD_RSSI); + + /*** Success. */ + /* Connection handle. */ + htole16(params + 0, 1); + + /* RSSI. */ + params[2] = -8; + + ble_hs_test_util_set_ack_params(opcode, 0, params, sizeof params); + + rc = ble_hs_hci_util_read_rssi(1, &rssi); + TEST_ASSERT_FATAL(rc == 0); + TEST_ASSERT(rssi == -8); + + /*** Failure: incorrect connection handle. */ + htole16(params + 0, 99); + + ble_hs_test_util_set_ack_params(opcode, 0, params, sizeof params); + + rc = ble_hs_hci_util_read_rssi(1, &rssi); + TEST_ASSERT(rc == BLE_HS_ECONTROLLER); + + /*** Failure: params too short. */ + ble_hs_test_util_set_ack_params(opcode, 0, params, sizeof params - 1); + rc = ble_hs_hci_util_read_rssi(1, &rssi); + TEST_ASSERT(rc == BLE_HS_ECONTROLLER); + + /*** Failure: params too long. */ + ble_hs_test_util_set_ack_params(opcode, 0, params, sizeof params + 1); + rc = ble_hs_hci_util_read_rssi(1, &rssi); + TEST_ASSERT(rc == BLE_HS_ECONTROLLER); +} + +TEST_SUITE(ble_hs_hci_suite) +{ + tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL); + + ble_hs_hci_test_event_bad(); + ble_hs_hci_test_rssi(); +} + +int +ble_hs_hci_test_all(void) +{ + ble_hs_hci_suite(); + return tu_any_failed; +} http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d98ddc1c/net/nimble/host/test/src/ble_hs_test.c ---------------------------------------------------------------------- diff --git a/net/nimble/host/test/src/ble_hs_test.c b/net/nimble/host/test/src/ble_hs_test.c new file mode 100644 index 0000000..e1f4dad --- /dev/null +++ b/net/nimble/host/test/src/ble_hs_test.c @@ -0,0 +1,61 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "syscfg/syscfg.h" +#include "os/os.h" +#include "nimble/hci_common.h" +#include "host/ble_hs_test.h" +#include "testutil/testutil.h" +#include "ble_hs_test_util.h" + +#if MYNEWT_VAL(SELFTEST) + +int +main(int argc, char **argv) +{ + tu_config.tc_print_results = 1; + tu_parse_args(argc, argv); + + tu_init(); + + ble_att_clt_test_all(); + ble_att_svr_test_all(); + ble_gap_test_all(); + ble_gatt_conn_test_all(); + ble_gatt_disc_c_test_all(); + ble_gatt_disc_d_test_all(); + ble_gatt_disc_s_test_all(); + ble_gatt_find_s_test_all(); + ble_gatt_read_test_all(); + ble_gatt_write_test_all(); + ble_gatts_notify_test_all(); + ble_gatts_read_test_suite(); + ble_gatts_reg_test_all(); + ble_hs_hci_test_all(); + ble_hs_adv_test_all(); + ble_hs_conn_test_all(); + ble_l2cap_test_all(); + ble_os_test_all(); + ble_sm_test_all(); + ble_uuid_test_all(); + + return tu_any_failed; +} + +#endif