You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by cc...@apache.org on 2016/05/24 21:27:59 UTC
[5/5] incubator-mynewt-core git commit: BLE Host - unit tests for
persisted CCCDs.
BLE Host - unit tests for persisted CCCDs.
Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/f98cc567
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/f98cc567
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/f98cc567
Branch: refs/heads/develop
Commit: f98cc5679ce1b3ac803fdde36907b8cd9ee21f81
Parents: 54a4b7f
Author: Christopher Collins <cc...@apache.org>
Authored: Tue May 24 14:24:18 2016 -0700
Committer: Christopher Collins <cc...@apache.org>
Committed: Tue May 24 14:27:21 2016 -0700
----------------------------------------------------------------------
.../host/src/test/ble_gatts_notify_test.c | 337 +++++++++++++++++--
net/nimble/host/src/test/ble_hs_test_util.c | 8 +-
net/nimble/host/src/test/ble_l2cap_sm_test.c | 18 +
3 files changed, 325 insertions(+), 38 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f98cc567/net/nimble/host/src/test/ble_gatts_notify_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_gatts_notify_test.c b/net/nimble/host/src/test/ble_gatts_notify_test.c
index 29ebd92..96730f1 100644
--- a/net/nimble/host/src/test/ble_gatts_notify_test.c
+++ b/net/nimble/host/src/test/ble_gatts_notify_test.c
@@ -24,6 +24,7 @@
#include "host/ble_uuid.h"
#include "host/ble_hs_test.h"
#include "ble_hs_test_util.h"
+#include "ble_hs_test_util_store.h"
#define BLE_GATTS_NOTIFY_TEST_CHR_1_UUID 0x1111
#define BLE_GATTS_NOTIFY_TEST_CHR_2_UUID 0x2222
@@ -66,13 +67,50 @@ static uint16_t ble_gatts_notify_test_chr_2_def_handle;
static uint8_t ble_gatts_notify_test_chr_2_val[1024];
static int ble_gatts_notify_test_chr_2_len;
+typedef int ble_store_write_fn(int obj_type, union ble_store_value *val);
+
+typedef int ble_store_delete_fn(int obj_type, union ble_store_key *key);
+
+static uint16_t
+ble_gatts_notify_test_misc_read_notify(uint16_t conn_handle,
+ uint16_t chr_def_handle)
+{
+ struct ble_att_read_req req;
+ struct os_mbuf *om;
+ uint8_t buf[BLE_ATT_READ_REQ_SZ];
+ uint16_t flags;
+ int rc;
+
+ req.barq_handle = chr_def_handle + 2;
+ ble_att_read_req_write(buf, sizeof buf, &req);
+
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+ buf, sizeof buf);
+ TEST_ASSERT(rc == 0);
+
+ ble_hs_test_util_tx_all();
+
+ om = ble_hs_test_util_prev_tx_dequeue_pullup();
+ TEST_ASSERT_FATAL(om != NULL);
+ TEST_ASSERT_FATAL(om->om_len == 3);
+ TEST_ASSERT_FATAL(om->om_data[0] == BLE_ATT_OP_READ_RSP);
+
+ flags = le16toh(om->om_data + 1);
+ return flags;
+}
+
static void
ble_gatts_notify_test_misc_init(uint16_t *out_conn_handle)
{
+ uint16_t flags;
int rc;
ble_hs_test_util_init();
+ ble_hs_test_util_store_init(10, 10, 10);
+ ble_hs_cfg.store_read_cb = ble_hs_test_util_store_read;
+ ble_hs_cfg.store_write_cb = ble_hs_test_util_store_write;
+
rc = ble_gatts_register_svcs(ble_gatts_notify_test_svcs,
ble_gatts_notify_test_misc_reg_cb, NULL);
TEST_ASSERT_FATAL(rc == 0);
@@ -84,6 +122,14 @@ ble_gatts_notify_test_misc_init(uint16_t *out_conn_handle)
ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
NULL, NULL);
*out_conn_handle = 2;
+
+ /* Ensure notifications disabled on new connection. */
+ flags = ble_gatts_notify_test_misc_read_notify(
+ 2, ble_gatts_notify_test_chr_1_def_handle);
+ TEST_ASSERT(flags == 0);
+ flags = ble_gatts_notify_test_misc_read_notify(
+ 2, ble_gatts_notify_test_chr_2_def_handle);
+ TEST_ASSERT(flags == 0);
}
static void
@@ -104,34 +150,6 @@ ble_gatts_notify_test_misc_enable_notify(uint16_t conn_handle,
TEST_ASSERT(rc == 0);
}
-static uint16_t
-ble_gatts_notify_test_misc_read_notify(uint16_t conn_handle,
- uint16_t chr_def_handle)
-{
- struct ble_att_read_req req;
- struct os_mbuf *om;
- uint8_t buf[BLE_ATT_READ_REQ_SZ];
- uint16_t flags;
- int rc;
-
- req.barq_handle = chr_def_handle + 2;
- ble_att_read_req_write(buf, sizeof buf, &req);
-
- rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
- buf, sizeof buf);
- TEST_ASSERT(rc == 0);
-
- ble_hs_test_util_tx_all();
-
- om = ble_hs_test_util_prev_tx_dequeue_pullup();
- TEST_ASSERT_FATAL(om != NULL);
- TEST_ASSERT_FATAL(om->om_len == 3);
- TEST_ASSERT_FATAL(om->om_data[0] == BLE_ATT_OP_READ_RSP);
-
- flags = le16toh(om->om_data + 1);
- return flags;
-}
-
static void
ble_gatts_notify_test_misc_reg_cb(uint8_t op,
union ble_gatt_register_ctxt *ctxt,
@@ -253,9 +271,18 @@ TEST_CASE(ble_gatts_notify_test_n)
BLE_GATTS_CLT_CFG_F_NOTIFY);
/* Toss both write responses. */
- ble_hs_test_util_tx_all();
- ble_hs_test_util_prev_tx_dequeue();
- ble_hs_test_util_prev_tx_dequeue();
+ ble_hs_test_util_prev_tx_queue_clear();
+
+ /* Ensure nothing got persisted since peer is not bonded. */
+ TEST_ASSERT(ble_hs_test_util_store_num_cccds == 0);
+
+ /* Ensure notifications read back as enabled. */
+ flags = ble_gatts_notify_test_misc_read_notify(
+ conn_handle, ble_gatts_notify_test_chr_1_def_handle);
+ TEST_ASSERT(flags == BLE_GATTS_CLT_CFG_F_NOTIFY);
+ flags = ble_gatts_notify_test_misc_read_notify(
+ conn_handle, ble_gatts_notify_test_chr_2_def_handle);
+ TEST_ASSERT(flags == BLE_GATTS_CLT_CFG_F_NOTIFY);
/* Update characteristic 1's value. */
ble_gatts_notify_test_chr_1_len = 1;
@@ -325,9 +352,18 @@ TEST_CASE(ble_gatts_notify_test_i)
BLE_GATTS_CLT_CFG_F_INDICATE);
/* Toss both write responses. */
- ble_hs_test_util_tx_all();
- ble_hs_test_util_prev_tx_dequeue();
- ble_hs_test_util_prev_tx_dequeue();
+ ble_hs_test_util_prev_tx_queue_clear();
+
+ /* Ensure nothing got persisted since peer is not bonded. */
+ TEST_ASSERT(ble_hs_test_util_store_num_cccds == 0);
+
+ /* Ensure indications read back as enabled. */
+ flags = ble_gatts_notify_test_misc_read_notify(
+ conn_handle, ble_gatts_notify_test_chr_1_def_handle);
+ TEST_ASSERT(flags == BLE_GATTS_CLT_CFG_F_INDICATE);
+ flags = ble_gatts_notify_test_misc_read_notify(
+ conn_handle, ble_gatts_notify_test_chr_2_def_handle);
+ TEST_ASSERT(flags == BLE_GATTS_CLT_CFG_F_INDICATE);
/* Update characteristic 1's value. */
ble_gatts_notify_test_chr_1_len = 1;
@@ -397,10 +433,243 @@ TEST_CASE(ble_gatts_notify_test_i)
TEST_ASSERT(flags == 0);
}
+TEST_CASE(ble_gatts_notify_test_bonded_n)
+{
+ struct ble_hs_conn *conn;
+ uint16_t conn_handle;
+ uint16_t flags;
+
+ ble_gatts_notify_test_misc_init(&conn_handle);
+
+ /* Enable bonding. */
+ ble_hs_lock();
+ conn = ble_hs_conn_find(conn_handle);
+ TEST_ASSERT_FATAL(conn != NULL);
+ conn->bhc_sec_state.enc_enabled = 1;
+ conn->bhc_sec_state.authenticated = 1;
+ conn->bhc_sec_state.bonded = 1;
+ ble_hs_unlock();
+
+ /* Enable notifications on both characteristics. */
+ ble_gatts_notify_test_misc_enable_notify(
+ conn_handle, ble_gatts_notify_test_chr_1_def_handle,
+ BLE_GATTS_CLT_CFG_F_NOTIFY);
+ ble_gatts_notify_test_misc_enable_notify(
+ conn_handle, ble_gatts_notify_test_chr_2_def_handle,
+ BLE_GATTS_CLT_CFG_F_NOTIFY);
+
+ /* Toss both write responses. */
+ ble_hs_test_util_prev_tx_queue_clear();
+
+ /* Ensure both CCCDs got persisted. */
+ TEST_ASSERT(ble_hs_test_util_store_num_cccds == 2);
+
+ /* Ensure notifications read back as enabled. */
+ flags = ble_gatts_notify_test_misc_read_notify(
+ conn_handle, ble_gatts_notify_test_chr_1_def_handle);
+ TEST_ASSERT(flags == BLE_GATTS_CLT_CFG_F_NOTIFY);
+ flags = ble_gatts_notify_test_misc_read_notify(
+ conn_handle, ble_gatts_notify_test_chr_2_def_handle);
+ TEST_ASSERT(flags == BLE_GATTS_CLT_CFG_F_NOTIFY);
+
+ /* Disconnect. */
+ ble_hs_test_util_conn_disconnect(conn_handle);
+
+ /* Ensure both CCCDs still persisted. */
+ TEST_ASSERT(ble_hs_test_util_store_num_cccds == 2);
+
+ /* Update characteristic 1's value. */
+ ble_gatts_notify_test_chr_1_len = 1;
+ ble_gatts_notify_test_chr_1_val[0] = 0xdd;
+ ble_gatts_chr_updated(ble_gatts_notify_test_chr_1_def_handle + 1);
+
+ /* Update characteristic 2's value. */
+ ble_gatts_notify_test_chr_2_len = 16;
+ memcpy(ble_gatts_notify_test_chr_2_val,
+ ((uint8_t[]){1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}), 16);
+ ble_gatts_chr_updated(ble_gatts_notify_test_chr_2_def_handle + 1);
+
+ /* Reconnect; ensure notifications don't get sent while unbonded and that
+ * notifications appear disabled.
+ */
+
+ ble_hs_test_util_create_conn(conn_handle, ((uint8_t[]){2,3,4,5,6,7,8,9}),
+ NULL, NULL);
+
+ /* Ensure no notifications sent. */
+ TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue() == NULL);
+
+ /* Ensure notifications disabled. */
+ flags = ble_gatts_notify_test_misc_read_notify(
+ conn_handle, ble_gatts_notify_test_chr_1_def_handle);
+ TEST_ASSERT(flags == 0);
+ flags = ble_gatts_notify_test_misc_read_notify(
+ conn_handle, ble_gatts_notify_test_chr_2_def_handle);
+ TEST_ASSERT(flags == 0);
+
+ /* Simulate a successful encryption procedure (bonding restoration). */
+ ble_hs_lock();
+ conn = ble_hs_conn_find(conn_handle);
+ TEST_ASSERT_FATAL(conn != NULL);
+ conn->bhc_sec_state.enc_enabled = 1;
+ conn->bhc_sec_state.authenticated = 1;
+ conn->bhc_sec_state.bonded = 1;
+ ble_hs_unlock();
+
+ ble_gatts_bonding_restored(conn_handle);
+
+ /* Verify notifications sent properly. */
+ ble_gatts_notify_test_misc_verify_tx_n(ble_gatts_notify_test_chr_1_val,
+ ble_gatts_notify_test_chr_1_len);
+ ble_gatts_notify_test_misc_verify_tx_n(ble_gatts_notify_test_chr_2_val,
+ ble_gatts_notify_test_chr_2_len);
+
+ /* Ensure notifications enabled. */
+ flags = ble_gatts_notify_test_misc_read_notify(
+ conn_handle, ble_gatts_notify_test_chr_1_def_handle);
+ TEST_ASSERT(flags == BLE_GATTS_CLT_CFG_F_NOTIFY);
+ flags = ble_gatts_notify_test_misc_read_notify(
+ conn_handle, ble_gatts_notify_test_chr_2_def_handle);
+ TEST_ASSERT(flags == BLE_GATTS_CLT_CFG_F_NOTIFY);
+
+ /* Ensure both CCCDs still persisted. */
+ TEST_ASSERT(ble_hs_test_util_store_num_cccds == 2);
+}
+
+TEST_CASE(ble_gatts_notify_test_bonded_i)
+{
+ struct ble_hs_conn *conn;
+ uint16_t conn_handle;
+ uint16_t flags;
+
+ ble_gatts_notify_test_misc_init(&conn_handle);
+
+ /* Enable bonding. */
+ ble_hs_lock();
+ conn = ble_hs_conn_find(conn_handle);
+ TEST_ASSERT_FATAL(conn != NULL);
+ conn->bhc_sec_state.enc_enabled = 1;
+ conn->bhc_sec_state.authenticated = 1;
+ conn->bhc_sec_state.bonded = 1;
+ ble_hs_unlock();
+
+ /* Enable indications on both characteristics. */
+ ble_gatts_notify_test_misc_enable_notify(
+ conn_handle, ble_gatts_notify_test_chr_1_def_handle,
+ BLE_GATTS_CLT_CFG_F_INDICATE);
+ ble_gatts_notify_test_misc_enable_notify(
+ conn_handle, ble_gatts_notify_test_chr_2_def_handle,
+ BLE_GATTS_CLT_CFG_F_INDICATE);
+
+ /* Toss both write responses. */
+ ble_hs_test_util_prev_tx_queue_clear();
+
+ /* Ensure both CCCDs got persisted. */
+ TEST_ASSERT(ble_hs_test_util_store_num_cccds == 2);
+
+ /* Ensure indications read back as enabled. */
+ flags = ble_gatts_notify_test_misc_read_notify(
+ conn_handle, ble_gatts_notify_test_chr_1_def_handle);
+ TEST_ASSERT(flags == BLE_GATTS_CLT_CFG_F_INDICATE);
+ flags = ble_gatts_notify_test_misc_read_notify(
+ conn_handle, ble_gatts_notify_test_chr_2_def_handle);
+ TEST_ASSERT(flags == BLE_GATTS_CLT_CFG_F_INDICATE);
+
+ /* Disconnect. */
+ ble_hs_test_util_conn_disconnect(conn_handle);
+
+ /* Ensure both CCCDs still persisted. */
+ TEST_ASSERT(ble_hs_test_util_store_num_cccds == 2);
+
+ /* Update characteristic 1's value. */
+ ble_gatts_notify_test_chr_1_len = 1;
+ ble_gatts_notify_test_chr_1_val[0] = 0xab;
+ ble_gatts_chr_updated(ble_gatts_notify_test_chr_1_def_handle + 1);
+
+ /* Update characteristic 2's value. */
+ ble_gatts_notify_test_chr_2_len = 16;
+ memcpy(ble_gatts_notify_test_chr_2_val,
+ ((uint8_t[]){0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}), 16);
+ ble_gatts_chr_updated(ble_gatts_notify_test_chr_2_def_handle + 1);
+
+ /* Reconnect; ensure notifications don't get sent while unbonded and that
+ * notifications appear disabled.
+ */
+
+ ble_hs_test_util_create_conn(conn_handle, ((uint8_t[]){2,3,4,5,6,7,8,9}),
+ NULL, NULL);
+
+ /* Ensure no indications sent. */
+ TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue() == NULL);
+
+ /* Ensure notifications disabled. */
+ flags = ble_gatts_notify_test_misc_read_notify(
+ conn_handle, ble_gatts_notify_test_chr_1_def_handle);
+ TEST_ASSERT(flags == 0);
+ flags = ble_gatts_notify_test_misc_read_notify(
+ conn_handle, ble_gatts_notify_test_chr_2_def_handle);
+ TEST_ASSERT(flags == 0);
+
+ /* Simulate a successful encryption procedure (bonding restoration). */
+ ble_hs_lock();
+ conn = ble_hs_conn_find(conn_handle);
+ TEST_ASSERT_FATAL(conn != NULL);
+ conn->bhc_sec_state.enc_enabled = 1;
+ conn->bhc_sec_state.authenticated = 1;
+ conn->bhc_sec_state.bonded = 1;
+ ble_hs_unlock();
+
+ ble_gatts_bonding_restored(conn_handle);
+
+ /* Verify first indication sent properly. */
+ ble_gatts_notify_test_misc_verify_tx_i(ble_gatts_notify_test_chr_1_val,
+ ble_gatts_notify_test_chr_1_len);
+
+ /* Verify the second indication doesn't get sent until the first is
+ * confirmed.
+ */
+ ble_hs_test_util_tx_all();
+ TEST_ASSERT(ble_hs_test_util_prev_tx_queue_sz() == 0);
+
+ /* Receive the confirmation for the first indication. */
+ ble_gatts_notify_test_misc_rx_indicate_rsp(conn_handle);
+
+ /* Verify indication sent properly. */
+ ble_hs_test_util_tx_all();
+ ble_gatts_notify_test_misc_verify_tx_i(ble_gatts_notify_test_chr_2_val,
+ ble_gatts_notify_test_chr_2_len);
+
+ /* Receive the confirmation for the second indication. */
+ ble_gatts_notify_test_misc_rx_indicate_rsp(conn_handle);
+
+ /* Verify no pending GATT jobs. */
+ TEST_ASSERT(!ble_gattc_any_jobs());
+
+ /* Ensure notifications enabled. */
+ flags = ble_gatts_notify_test_misc_read_notify(
+ conn_handle, ble_gatts_notify_test_chr_1_def_handle);
+ TEST_ASSERT(flags == BLE_GATTS_CLT_CFG_F_INDICATE);
+ flags = ble_gatts_notify_test_misc_read_notify(
+ conn_handle, ble_gatts_notify_test_chr_2_def_handle);
+ TEST_ASSERT(flags == BLE_GATTS_CLT_CFG_F_INDICATE);
+
+ /* Ensure both CCCDs still persisted. */
+ TEST_ASSERT(ble_hs_test_util_store_num_cccds == 2);
+}
+
TEST_SUITE(ble_gatts_notify_suite)
{
ble_gatts_notify_test_n();
ble_gatts_notify_test_i();
+
+ ble_gatts_notify_test_bonded_n();
+ ble_gatts_notify_test_bonded_i();
+
+ /* XXX: Test corner cases:
+ * o Bonding after CCCD configuration.
+ * o Disconnect prior to rx of indicate ack.
+ * o Multiple characteristic updates prior to rx of indicate ack.
+ */
}
int
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f98cc567/net/nimble/host/src/test/ble_hs_test_util.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_hs_test_util.c b/net/nimble/host/src/test/ble_hs_test_util.c
index 810cc19..fb3bf3b 100644
--- a/net/nimble/host/src/test/ble_hs_test_util.c
+++ b/net/nimble/host/src/test/ble_hs_test_util.c
@@ -76,11 +76,9 @@ ble_hs_test_util_prev_tx_dequeue(void)
os_mbuf_free_chain(ble_hs_test_util_prev_tx_cur);
- omp = STAILQ_LAST(&ble_hs_test_util_prev_tx_queue, os_mbuf_pkthdr,
- omp_next);
+ omp = STAILQ_FIRST(&ble_hs_test_util_prev_tx_queue);
if (omp != NULL) {
- STAILQ_REMOVE(&ble_hs_test_util_prev_tx_queue, omp, os_mbuf_pkthdr,
- omp_next);
+ STAILQ_REMOVE_HEAD(&ble_hs_test_util_prev_tx_queue, omp_next);
ble_hs_test_util_prev_tx_cur = OS_MBUF_PKTHDR_TO_MBUF(omp);
} else {
ble_hs_test_util_prev_tx_cur = NULL;
@@ -120,6 +118,7 @@ ble_hs_test_util_prev_tx_queue_sz(void)
void
ble_hs_test_util_prev_tx_queue_clear(void)
{
+ ble_hs_test_util_tx_all();
while (!STAILQ_EMPTY(&ble_hs_test_util_prev_tx_queue)) {
ble_hs_test_util_prev_tx_dequeue();
}
@@ -759,6 +758,7 @@ ble_hs_test_util_set_public_addr(uint8_t *addr)
memcpy(ble_hs_our_dev.public_addr, addr, 6);
}
+
void
ble_hs_test_util_init(void)
{
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f98cc567/net/nimble/host/src/test/ble_l2cap_sm_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_l2cap_sm_test.c b/net/nimble/host/src/test/ble_l2cap_sm_test.c
index 1159028..c58396d 100644
--- a/net/nimble/host/src/test/ble_l2cap_sm_test.c
+++ b/net/nimble/host/src/test/ble_l2cap_sm_test.c
@@ -412,6 +412,21 @@ ble_l2cap_sm_test_util_verify_tx_enc_info(
}
static void
+ble_l2cap_sm_test_util_verify_tx_sec_req(struct ble_l2cap_sm_sec_req *exp_cmd)
+{
+ struct ble_l2cap_sm_sec_req cmd;
+ struct os_mbuf *om;
+
+ ble_hs_test_util_tx_all();
+
+ om = ble_l2cap_sm_test_util_verify_tx_hdr(BLE_L2CAP_SM_OP_SEC_REQ,
+ BLE_L2CAP_SM_SEC_REQ_SZ);
+ ble_l2cap_sm_sec_req_parse(om->om_data, om->om_len, &cmd);
+
+ TEST_ASSERT(cmd.authreq == exp_cmd->authreq);
+}
+
+static void
ble_l2cap_sm_test_util_verify_tx_pair_fail(
struct ble_l2cap_sm_pair_fail *exp_cmd)
{
@@ -914,6 +929,9 @@ ble_l2cap_sm_test_util_peer_lgcy_good(
if (params->has_sec_req) {
rc = ble_l2cap_sm_slave_initiate(2);
TEST_ASSERT(rc == 0);
+
+ /* Ensure we sent the expected security request. */
+ ble_l2cap_sm_test_util_verify_tx_sec_req(¶ms->sec_req);
}
/* Receive a pair request from the peer. */