http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/net/nimble/host/test/src/ble_hs_test_util.h ---------------------------------------------------------------------- diff --cc net/nimble/host/test/src/ble_hs_test_util.h index 5a821cd,0000000..c798916 mode 100644,000000..100644 --- a/net/nimble/host/test/src/ble_hs_test_util.h +++ b/net/nimble/host/test/src/ble_hs_test_util.h @@@ -1,177 -1,0 +1,197 @@@ +/** + * 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. + */ + +#ifndef H_BLE_HS_TEST_UTIL_ +#define H_BLE_HS_TEST_UTIL_ + +#include <inttypes.h> +#include "host/ble_gap.h" +#include "ble_hs_priv.h" +#include "ble_hs_test_util_store.h" +struct ble_hs_conn; +struct ble_l2cap_chan; +struct hci_disconn_complete; +struct hci_create_conn; + +extern struct os_eventq ble_hs_test_util_evq; +extern const struct ble_gap_adv_params ble_hs_test_util_adv_params; + +struct ble_hs_test_util_num_completed_pkts_entry { + uint16_t handle_id; /* 0 for terminating entry in array. */ + uint16_t num_pkts; +}; + +struct ble_hs_test_util_flat_attr { + uint16_t handle; + uint16_t offset; + uint8_t value[BLE_ATT_ATTR_MAX_LEN]; + uint16_t value_len; +}; + +struct ble_hs_test_util_mbuf_params { + unsigned prev_tx:1; + unsigned rx_queue:1; + unsigned prep_list:1; +}; + ++#define BLE_HS_TEST_UTIL_L2CAP_HCI_HDR(handle, pb, len) \ ++ ((struct hci_data_hdr) { \ ++ .hdh_handle_pb_bc = ((handle) << 0) | \ ++ ((pb) << 12), \ ++ .hdh_len = (len) \ ++ }) ++ +void ble_hs_test_util_prev_tx_enqueue(struct os_mbuf *om); +struct os_mbuf *ble_hs_test_util_prev_tx_dequeue(void); +struct os_mbuf *ble_hs_test_util_prev_tx_dequeue_pullup(void); +int ble_hs_test_util_prev_tx_queue_sz(void); +void ble_hs_test_util_prev_tx_queue_clear(void); + +void ble_hs_test_util_set_ack_params(uint16_t opcode, uint8_t status, + void *params, uint8_t params_len); +void ble_hs_test_util_set_ack(uint16_t opcode, uint8_t status); +void *ble_hs_test_util_get_first_hci_tx(void); +void *ble_hs_test_util_get_last_hci_tx(void); +void ble_hs_test_util_enqueue_hci_tx(void *cmd); +void ble_hs_test_util_prev_hci_tx_clear(void); +void ble_hs_test_util_build_cmd_complete(uint8_t *dst, int len, + uint8_t param_len, uint8_t num_pkts, + uint16_t opcode); +void ble_hs_test_util_build_cmd_status(uint8_t *dst, int len, + uint8_t status, uint8_t num_pkts, + uint16_t opcode); +void ble_hs_test_util_create_rpa_conn(uint16_t handle, uint8_t own_addr_type, + const uint8_t *our_rpa, + uint8_t peer_addr_type, + const uint8_t *peer_id_addr, + const uint8_t *peer_rpa, + ble_gap_event_fn *cb, void *cb_arg); - void ble_hs_test_util_create_conn(uint16_t handle, uint8_t *addr, ++void ble_hs_test_util_create_conn(uint16_t handle, const uint8_t *addr, + ble_gap_event_fn *cb, void *cb_arg); +int ble_hs_test_util_connect(uint8_t own_addr_type, + uint8_t peer_addr_type, + const uint8_t *peer_addr, + int32_t duration_ms, + const struct ble_gap_conn_params *params, + ble_gap_event_fn *cb, + void *cb_arg, + uint8_t ack_status); +int ble_hs_test_util_conn_cancel(uint8_t ack_status); +void ble_hs_test_util_conn_cancel_full(void); ++void ble_hs_test_util_set_ack_disconnect(uint8_t hci_status); +int ble_hs_test_util_conn_terminate(uint16_t conn_handle, uint8_t hci_status); +void ble_hs_test_util_conn_disconnect(uint16_t conn_handle); +int ble_hs_test_util_exp_hci_status(int cmd_idx, int fail_idx, + uint8_t fail_status); +int ble_hs_test_util_disc(uint8_t own_addr_type, int32_t duration_ms, + const struct ble_gap_disc_params *disc_params, + ble_gap_event_fn *cb, void *cb_arg, int fail_idx, + uint8_t fail_status); +int ble_hs_test_util_disc_cancel(uint8_t ack_status); +void ble_hs_test_util_verify_tx_create_conn(const struct hci_create_conn *exp); +int ble_hs_test_util_adv_set_fields(struct ble_hs_adv_fields *adv_fields, + uint8_t hci_status); +int ble_hs_test_util_adv_start(uint8_t own_addr_type, + uint8_t peer_addr_type, + const uint8_t *peer_addr, + const struct ble_gap_adv_params *adv_params, + ble_gap_event_fn *cb, void *cb_arg, + int fail_idx, uint8_t fail_status); +int ble_hs_test_util_adv_stop(uint8_t hci_status); +int ble_hs_test_util_wl_set(struct ble_gap_white_entry *white_list, + uint8_t white_list_count, + int fail_idx, uint8_t fail_status); +int ble_hs_test_util_conn_update(uint16_t conn_handle, + struct ble_gap_upd_params *params, + uint8_t hci_status); +int ble_hs_test_util_set_our_irk(const uint8_t *irk, int fail_idx, + uint8_t hci_status); +int ble_hs_test_util_security_initiate(uint16_t conn_handle, + uint8_t hci_status); +int ble_hs_test_util_l2cap_rx_first_frag(uint16_t conn_handle, uint16_t cid, + struct hci_data_hdr *hci_hdr, + struct os_mbuf *om); +int ble_hs_test_util_l2cap_rx(uint16_t conn_handle, + struct hci_data_hdr *hci_hdr, + struct os_mbuf *om); +int ble_hs_test_util_l2cap_rx_payload_flat(uint16_t conn_handle, uint16_t cid, + const void *data, int len); +void ble_hs_test_util_rx_hci_buf_size_ack(uint16_t buf_size); ++void ble_hs_test_util_rx_att_mtu_cmd(uint16_t conn_handle, int is_req, ++ uint16_t mtu); +void ble_hs_test_util_rx_att_err_rsp(uint16_t conn_handle, uint8_t req_op, + uint8_t error_code, uint16_t err_handle); +void ble_hs_test_util_set_startup_acks(void); +void ble_hs_test_util_rx_num_completed_pkts_event( + struct ble_hs_test_util_num_completed_pkts_entry *entries); +void ble_hs_test_util_rx_disconn_complete_event( + struct hci_disconn_complete *evt); +uint8_t *ble_hs_test_util_verify_tx_hci(uint8_t ogf, uint16_t ocf, + uint8_t *out_param_len); +void ble_hs_test_util_tx_all(void); +void ble_hs_test_util_verify_tx_prep_write(uint16_t attr_handle, + uint16_t offset, + const void *data, int data_len); +void ble_hs_test_util_verify_tx_exec_write(uint8_t expected_flags); +void ble_hs_test_util_verify_tx_read_rsp(uint8_t *attr_data, int attr_len); +void ble_hs_test_util_verify_tx_read_blob_rsp(uint8_t *attr_data, + int attr_len); ++void ble_hs_test_util_verify_tx_write_rsp(void); ++void ble_hs_test_util_verify_tx_mtu_cmd(int is_req, uint16_t mtu); ++void ble_hs_test_util_verify_tx_err_rsp(uint8_t req_op, uint16_t handle, ++ uint8_t error_code); ++uint8_t ble_hs_test_util_verify_tx_l2cap_update_req( ++ struct ble_l2cap_sig_update_params *params); ++int ble_hs_test_util_rx_l2cap_update_rsp(uint16_t conn_handle, ++ uint8_t id, uint16_t result); ++void ble_hs_test_util_verify_tx_l2cap_update_rsp(uint8_t exp_id, ++ uint16_t exp_result); +void ble_hs_test_util_set_static_rnd_addr(void); +struct os_mbuf *ble_hs_test_util_om_from_flat(const void *buf, uint16_t len); +int ble_hs_test_util_flat_attr_cmp(const struct ble_hs_test_util_flat_attr *a, + const struct ble_hs_test_util_flat_attr *b); +void ble_hs_test_util_attr_to_flat(struct ble_hs_test_util_flat_attr *flat, + const struct ble_gatt_attr *attr); +void ble_hs_test_util_attr_from_flat( + struct ble_gatt_attr *attr, const struct ble_hs_test_util_flat_attr *flat); +int ble_hs_test_util_read_local_flat(uint16_t attr_handle, uint16_t max_len, + void *buf, uint16_t *out_len); +int ble_hs_test_util_write_local_flat(uint16_t attr_handle, + const void *buf, uint16_t buf_len); +int ble_hs_test_util_gatt_write_flat(uint16_t conn_handle, + uint16_t attr_handle, + const void *data, uint16_t data_len, + ble_gatt_attr_fn *cb, void *cb_arg); +int ble_hs_test_util_gatt_write_no_rsp_flat(uint16_t conn_handle, + uint16_t attr_handle, + const void *data, + uint16_t data_len); +int ble_hs_test_util_gatt_write_long_flat(uint16_t conn_handle, + uint16_t attr_handle, + const void *data, uint16_t data_len, + ble_gatt_attr_fn *cb, void *cb_arg); +int ble_hs_test_util_mbuf_count( + const struct ble_hs_test_util_mbuf_params *params); +void ble_hs_test_util_assert_mbufs_freed( + const struct ble_hs_test_util_mbuf_params *params); +void ble_hs_test_util_post_test(void *arg); +void ble_hs_test_util_init_no_start(void); +void ble_hs_test_util_init(void); + +#endif
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/c5901fcc/net/nimble/host/test/src/ble_l2cap_test.c ---------------------------------------------------------------------- diff --cc net/nimble/host/test/src/ble_l2cap_test.c index 69db2f8,0000000..9410b3d mode 100644,000000..100644 --- a/net/nimble/host/test/src/ble_l2cap_test.c +++ b/net/nimble/host/test/src/ble_l2cap_test.c @@@ -1,690 -1,0 +1,587 @@@ +/** + * 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 "testutil/testutil.h" +#include "nimble/hci_common.h" +#include "host/ble_hs_test.h" +#include "ble_hs_test_util.h" + +#define BLE_L2CAP_TEST_CID 99 + ++static uint16_t ble_l2cap_test_update_conn_handle; +static int ble_l2cap_test_update_status; +static void *ble_l2cap_test_update_arg; + +/***************************************************************************** + * $util * + *****************************************************************************/ + - #define BLE_L2CAP_TEST_UTIL_HCI_HDR(handle, pb, len) \ - ((struct hci_data_hdr) { \ - .hdh_handle_pb_bc = ((handle) << 0) | \ - ((pb) << 12), \ - .hdh_len = (len) \ - }) - +static void +ble_l2cap_test_util_init(void) +{ + ble_hs_test_util_init(); ++ ble_l2cap_test_update_conn_handle = BLE_HS_CONN_HANDLE_NONE; + ble_l2cap_test_update_status = -1; + ble_l2cap_test_update_arg = (void *)(uintptr_t)-1; +} + +static void +ble_l2cap_test_util_rx_update_req(uint16_t conn_handle, uint8_t id, + struct ble_l2cap_sig_update_params *params) +{ + struct ble_l2cap_sig_update_req req; + struct hci_data_hdr hci_hdr; + struct os_mbuf *om; + void *v; + int rc; + - hci_hdr = BLE_L2CAP_TEST_UTIL_HCI_HDR( ++ hci_hdr = BLE_HS_TEST_UTIL_L2CAP_HCI_HDR( + 2, BLE_HCI_PB_FIRST_FLUSH, + BLE_L2CAP_HDR_SZ + BLE_L2CAP_SIG_HDR_SZ + BLE_L2CAP_SIG_UPDATE_REQ_SZ); + + rc = ble_l2cap_sig_init_cmd(BLE_L2CAP_SIG_OP_UPDATE_REQ, id, + BLE_L2CAP_SIG_UPDATE_REQ_SZ, &om, &v); + TEST_ASSERT_FATAL(rc == 0); + + req.itvl_min = params->itvl_min; + req.itvl_max = params->itvl_max; + req.slave_latency = params->slave_latency; + req.timeout_multiplier = params->timeout_multiplier; + ble_l2cap_sig_update_req_write(v, BLE_L2CAP_SIG_UPDATE_REQ_SZ, &req); + + ble_hs_test_util_set_ack( + ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE, + BLE_HCI_OCF_LE_CONN_UPDATE), 0); + rc = ble_hs_test_util_l2cap_rx_first_frag(conn_handle, BLE_L2CAP_CID_SIG, + &hci_hdr, om); + TEST_ASSERT_FATAL(rc == 0); +} + - static int - ble_l2cap_test_util_rx_update_rsp(uint16_t conn_handle, - uint8_t id, uint16_t result) - { - struct ble_l2cap_sig_update_rsp rsp; - struct hci_data_hdr hci_hdr; - struct os_mbuf *om; - void *v; - int rc; - - hci_hdr = BLE_L2CAP_TEST_UTIL_HCI_HDR( - 2, BLE_HCI_PB_FIRST_FLUSH, - BLE_L2CAP_HDR_SZ + BLE_L2CAP_SIG_HDR_SZ + BLE_L2CAP_SIG_UPDATE_RSP_SZ); - - rc = ble_l2cap_sig_init_cmd(BLE_L2CAP_SIG_OP_UPDATE_RSP, id, - BLE_L2CAP_SIG_UPDATE_RSP_SZ, &om, &v); - TEST_ASSERT_FATAL(rc == 0); - - rsp.result = result; - ble_l2cap_sig_update_rsp_write(v, BLE_L2CAP_SIG_UPDATE_RSP_SZ, &rsp); - - rc = ble_hs_test_util_l2cap_rx_first_frag(conn_handle, BLE_L2CAP_CID_SIG, - &hci_hdr, om); - return rc; - } - - - static struct os_mbuf * - ble_l2cap_test_util_verify_tx_sig_hdr(uint8_t op, uint8_t id, - uint16_t payload_len, - struct ble_l2cap_sig_hdr *out_hdr) - { - struct ble_l2cap_sig_hdr hdr; - struct os_mbuf *om; - - om = ble_hs_test_util_prev_tx_dequeue(); - TEST_ASSERT_FATAL(om != NULL); - - TEST_ASSERT(OS_MBUF_PKTLEN(om) == BLE_L2CAP_SIG_HDR_SZ + payload_len); - ble_l2cap_sig_hdr_parse(om->om_data, om->om_len, &hdr); - TEST_ASSERT(hdr.op == op); - if (id != 0) { - TEST_ASSERT(hdr.identifier == id); - } - TEST_ASSERT(hdr.length == payload_len); - - om->om_data += BLE_L2CAP_SIG_HDR_SZ; - om->om_len -= BLE_L2CAP_SIG_HDR_SZ; - - if (out_hdr != NULL) { - *out_hdr = hdr; - } - - return om; - } - - /** - * @return The L2CAP sig identifier in the request. - */ - static uint8_t - ble_l2cap_test_util_verify_tx_update_req( - struct ble_l2cap_sig_update_params *params) - { - struct ble_l2cap_sig_update_req req; - struct ble_l2cap_sig_hdr hdr; - struct os_mbuf *om; - - om = ble_l2cap_test_util_verify_tx_sig_hdr(BLE_L2CAP_SIG_OP_UPDATE_REQ, 0, - BLE_L2CAP_SIG_UPDATE_REQ_SZ, - &hdr); - - /* Verify payload. */ - ble_l2cap_sig_update_req_parse(om->om_data, om->om_len, &req); - TEST_ASSERT(req.itvl_min == params->itvl_min); - TEST_ASSERT(req.itvl_max == params->itvl_max); - TEST_ASSERT(req.slave_latency == params->slave_latency); - TEST_ASSERT(req.timeout_multiplier == params->timeout_multiplier); - - return hdr.identifier; - } - - static void - ble_l2cap_test_util_verify_tx_update_rsp(uint8_t exp_id, uint16_t exp_result) - { - struct ble_l2cap_sig_update_rsp rsp; - struct os_mbuf *om; - - om = ble_l2cap_test_util_verify_tx_sig_hdr(BLE_L2CAP_SIG_OP_UPDATE_RSP, - exp_id, - BLE_L2CAP_SIG_UPDATE_RSP_SZ, - NULL); - - ble_l2cap_sig_update_rsp_parse(om->om_data, om->om_len, &rsp); - TEST_ASSERT(rsp.result == exp_result); - } - +static void +ble_l2cap_test_util_verify_tx_update_conn( + struct ble_gap_upd_params *params) +{ + uint8_t param_len; + uint8_t *param; + + param = ble_hs_test_util_verify_tx_hci(BLE_HCI_OGF_LE, + BLE_HCI_OCF_LE_CONN_UPDATE, + ¶m_len); + TEST_ASSERT(param_len == BLE_HCI_CONN_UPDATE_LEN); + TEST_ASSERT(le16toh(param + 0) == 2); + TEST_ASSERT(le16toh(param + 2) == params->itvl_min); + TEST_ASSERT(le16toh(param + 4) == params->itvl_max); + TEST_ASSERT(le16toh(param + 6) == params->latency); + TEST_ASSERT(le16toh(param + 8) == params->supervision_timeout); + TEST_ASSERT(le16toh(param + 10) == params->min_ce_len); + TEST_ASSERT(le16toh(param + 12) == params->max_ce_len); +} + +static int +ble_l2cap_test_util_dummy_rx(uint16_t conn_handle, struct os_mbuf **om) +{ + return 0; +} + +static void +ble_l2cap_test_util_create_conn(uint16_t conn_handle, uint8_t *addr, + ble_gap_event_fn *cb, void *cb_arg) +{ + struct ble_l2cap_chan *chan; + struct ble_hs_conn *conn; + + ble_hs_test_util_create_conn(conn_handle, addr, cb, cb_arg); + + ble_hs_lock(); + + conn = ble_hs_conn_find(conn_handle); + TEST_ASSERT_FATAL(conn != NULL); + + chan = ble_l2cap_chan_alloc(); + TEST_ASSERT_FATAL(chan != NULL); + + chan->blc_cid = BLE_L2CAP_TEST_CID; + chan->blc_my_mtu = 240; + chan->blc_default_mtu = 240; + chan->blc_rx_fn = ble_l2cap_test_util_dummy_rx; + + ble_hs_conn_chan_insert(conn, chan); + + ble_hs_test_util_prev_hci_tx_clear(); + + ble_hs_unlock(); +} + +static int +ble_l2cap_test_util_rx_first_frag(uint16_t conn_handle, + uint16_t l2cap_frag_len, + uint16_t cid, uint16_t l2cap_len) +{ + struct hci_data_hdr hci_hdr; + struct os_mbuf *om; + uint16_t hci_len; + void *v; + int rc; + + om = ble_hs_mbuf_l2cap_pkt(); + TEST_ASSERT_FATAL(om != NULL); + + v = os_mbuf_extend(om, l2cap_frag_len); + TEST_ASSERT_FATAL(v != NULL); + + om = ble_l2cap_prepend_hdr(om, cid, l2cap_len); + TEST_ASSERT_FATAL(om != NULL); + + hci_len = sizeof hci_hdr + l2cap_frag_len; - hci_hdr = BLE_L2CAP_TEST_UTIL_HCI_HDR(conn_handle, ++ hci_hdr = BLE_HS_TEST_UTIL_L2CAP_HCI_HDR(conn_handle, + BLE_HCI_PB_FIRST_FLUSH, hci_len); + rc = ble_hs_test_util_l2cap_rx(conn_handle, &hci_hdr, om); + return rc; +} + +static int +ble_l2cap_test_util_rx_next_frag(uint16_t conn_handle, uint16_t hci_len) +{ + struct hci_data_hdr hci_hdr; + struct os_mbuf *om; + void *v; + int rc; + + om = ble_hs_mbuf_l2cap_pkt(); + TEST_ASSERT_FATAL(om != NULL); + + v = os_mbuf_extend(om, hci_len); + TEST_ASSERT_FATAL(v != NULL); + - hci_hdr = BLE_L2CAP_TEST_UTIL_HCI_HDR(conn_handle, ++ hci_hdr = BLE_HS_TEST_UTIL_L2CAP_HCI_HDR(conn_handle, + BLE_HCI_PB_MIDDLE, hci_len); + rc = ble_hs_test_util_l2cap_rx(conn_handle, &hci_hdr, om); + return rc; +} + +static void +ble_l2cap_test_util_verify_first_frag(uint16_t conn_handle, + uint16_t l2cap_frag_len, + uint16_t l2cap_len) +{ + struct ble_hs_conn *conn; + int rc; + + rc = ble_l2cap_test_util_rx_first_frag(conn_handle, l2cap_frag_len, + BLE_L2CAP_TEST_CID, l2cap_len); + TEST_ASSERT(rc == 0); + + ble_hs_lock(); + + conn = ble_hs_conn_find(conn_handle); + TEST_ASSERT_FATAL(conn != NULL); + TEST_ASSERT(conn->bhc_rx_chan != NULL && + conn->bhc_rx_chan->blc_cid == BLE_L2CAP_TEST_CID); + + ble_hs_unlock(); +} + +static void +ble_l2cap_test_util_verify_middle_frag(uint16_t conn_handle, + uint16_t hci_len) +{ + struct ble_hs_conn *conn; + int rc; + + rc = ble_l2cap_test_util_rx_next_frag(conn_handle, hci_len); + TEST_ASSERT(rc == 0); + + ble_hs_lock(); + + conn = ble_hs_conn_find(conn_handle); + TEST_ASSERT_FATAL(conn != NULL); + TEST_ASSERT(conn->bhc_rx_chan != NULL && + conn->bhc_rx_chan->blc_cid == BLE_L2CAP_TEST_CID); + + ble_hs_unlock(); +} + +static void +ble_l2cap_test_util_verify_last_frag(uint16_t conn_handle, + uint16_t hci_len) +{ + struct ble_hs_conn *conn; + int rc; + + rc = ble_l2cap_test_util_rx_next_frag(conn_handle, hci_len); + TEST_ASSERT(rc == 0); + + ble_hs_lock(); + + conn = ble_hs_conn_find(conn_handle); + TEST_ASSERT_FATAL(conn != NULL); + TEST_ASSERT(conn->bhc_rx_chan == NULL); + + ble_hs_unlock(); +} + +/***************************************************************************** + * $rx * + *****************************************************************************/ + +TEST_CASE(ble_l2cap_test_case_bad_header) +{ + int rc; + + ble_l2cap_test_util_init(); + + ble_l2cap_test_util_create_conn(2, ((uint8_t[]){1,2,3,4,5,6}), + NULL, NULL); + + rc = ble_l2cap_test_util_rx_first_frag(2, 14, 1234, 10); + TEST_ASSERT(rc == BLE_HS_ENOENT); +} + +/***************************************************************************** + * $fragmentation * + *****************************************************************************/ + +TEST_CASE(ble_l2cap_test_case_frag_single) +{ + struct hci_data_hdr hci_hdr; + struct os_mbuf *om; + int rc; + + ble_l2cap_test_util_init(); + + ble_l2cap_test_util_create_conn(2, ((uint8_t[]){1,2,3,4,5,6}), + NULL, NULL); + + /*** HCI header specifies middle fragment without start. */ - hci_hdr = BLE_L2CAP_TEST_UTIL_HCI_HDR(2, BLE_HCI_PB_MIDDLE, 10); ++ hci_hdr = BLE_HS_TEST_UTIL_L2CAP_HCI_HDR(2, BLE_HCI_PB_MIDDLE, 10); + + om = ble_hs_mbuf_l2cap_pkt(); + TEST_ASSERT_FATAL(om != NULL); + + om = ble_l2cap_prepend_hdr(om, 0, 5); + TEST_ASSERT_FATAL(om != NULL); + + rc = ble_hs_test_util_l2cap_rx(2, &hci_hdr, om); + TEST_ASSERT(rc == BLE_HS_EBADDATA); + + /*** Packet consisting of three fragments. */ + ble_l2cap_test_util_verify_first_frag(2, 10, 30); + ble_l2cap_test_util_verify_middle_frag(2, 10); + ble_l2cap_test_util_verify_last_frag(2, 10); + + /*** Packet consisting of five fragments. */ + ble_l2cap_test_util_verify_first_frag(2, 8, 49); + ble_l2cap_test_util_verify_middle_frag(2, 13); + ble_l2cap_test_util_verify_middle_frag(2, 2); + ble_l2cap_test_util_verify_middle_frag(2, 21); + ble_l2cap_test_util_verify_last_frag(2, 5); +} + +TEST_CASE(ble_l2cap_test_case_frag_multiple) +{ + ble_l2cap_test_util_init(); + + ble_l2cap_test_util_create_conn(2, ((uint8_t[]){1,2,3,4,5,6}), + NULL, NULL); + ble_l2cap_test_util_create_conn(3, ((uint8_t[]){2,3,4,5,6,7}), + NULL, NULL); + ble_l2cap_test_util_create_conn(4, ((uint8_t[]){3,4,5,6,7,8}), + NULL, NULL); + + ble_l2cap_test_util_verify_first_frag(2, 3, 10); + ble_l2cap_test_util_verify_first_frag(3, 2, 5); + ble_l2cap_test_util_verify_middle_frag(2, 6); + ble_l2cap_test_util_verify_first_frag(4, 1, 4); + ble_l2cap_test_util_verify_middle_frag(3, 2); + ble_l2cap_test_util_verify_last_frag(3, 1); + ble_l2cap_test_util_verify_middle_frag(4, 2); + ble_l2cap_test_util_verify_last_frag(4, 1); + ble_l2cap_test_util_verify_last_frag(2, 1); +} + +TEST_CASE(ble_l2cap_test_case_frag_channels) +{ + struct ble_hs_conn *conn; + int rc; + + ble_l2cap_test_util_init(); + + ble_l2cap_test_util_create_conn(2, ((uint8_t[]){1,2,3,4,5,6}), + NULL, NULL); + + /* Receive a starting fragment on the first channel. */ + rc = ble_l2cap_test_util_rx_first_frag(2, 14, BLE_L2CAP_TEST_CID, 30); + TEST_ASSERT(rc == 0); + + ble_hs_lock(); + conn = ble_hs_conn_find(2); + TEST_ASSERT_FATAL(conn != NULL); + TEST_ASSERT(conn->bhc_rx_chan != NULL && + conn->bhc_rx_chan->blc_cid == BLE_L2CAP_TEST_CID); + ble_hs_unlock(); + + /* Receive a starting fragment on a different channel. The first fragment + * should get discarded. + */ + rc = ble_l2cap_test_util_rx_first_frag(2, 14, BLE_L2CAP_CID_ATT, 30); + TEST_ASSERT(rc == 0); + + ble_hs_lock(); + conn = ble_hs_conn_find(2); + TEST_ASSERT_FATAL(conn != NULL); + TEST_ASSERT(conn->bhc_rx_chan != NULL && + conn->bhc_rx_chan->blc_cid == BLE_L2CAP_CID_ATT); + ble_hs_unlock(); +} + +/***************************************************************************** + * $unsolicited response * + *****************************************************************************/ + +TEST_CASE(ble_l2cap_test_case_sig_unsol_rsp) +{ + int rc; + + ble_l2cap_test_util_init(); + + ble_l2cap_test_util_create_conn(2, ((uint8_t[]){1,2,3,4,5,6}), + NULL, NULL); + + /* Receive an unsolicited response. */ - rc = ble_l2cap_test_util_rx_update_rsp(2, 100, 0); ++ rc = ble_hs_test_util_rx_l2cap_update_rsp(2, 100, 0); + TEST_ASSERT(rc == BLE_HS_ENOENT); + + /* Ensure we did not send anything in return. */ + ble_hs_test_util_tx_all(); + TEST_ASSERT_FATAL(ble_hs_test_util_prev_tx_dequeue() == NULL); +} + +/***************************************************************************** + * $update * + *****************************************************************************/ + +static int +ble_l2cap_test_util_conn_cb(struct ble_gap_event *event, void *arg) +{ + int *accept; + + switch (event->type) { + case BLE_GAP_EVENT_L2CAP_UPDATE_REQ: + accept = arg; + return !*accept; + + default: + return 0; + } +} + +static void +ble_l2cap_test_util_peer_updates(int accept) +{ + struct ble_l2cap_sig_update_params l2cap_params; + struct ble_gap_upd_params params; - ble_hs_conn_flags_t conn_flags; - int rc; + + ble_l2cap_test_util_init(); + + ble_l2cap_test_util_create_conn(2, ((uint8_t[]){1,2,3,4,5,6}), + ble_l2cap_test_util_conn_cb, + &accept); + + l2cap_params.itvl_min = 0x200; + l2cap_params.itvl_max = 0x300; + l2cap_params.slave_latency = 0; + l2cap_params.timeout_multiplier = 0x100; + ble_l2cap_test_util_rx_update_req(2, 1, &l2cap_params); + + /* Ensure an update response command got sent. */ + ble_hs_process_tx_data_queue(); - ble_l2cap_test_util_verify_tx_update_rsp(1, !accept); ++ ble_hs_test_util_verify_tx_l2cap_update_rsp(1, !accept); + + if (accept) { + params.itvl_min = 0x200; + params.itvl_max = 0x300; + params.latency = 0; + params.supervision_timeout = 0x100; + params.min_ce_len = BLE_GAP_INITIAL_CONN_MIN_CE_LEN; + params.max_ce_len = BLE_GAP_INITIAL_CONN_MAX_CE_LEN; + ble_l2cap_test_util_verify_tx_update_conn(¶ms); + } else { + /* Ensure no update got scheduled. */ - rc = ble_hs_atomic_conn_flags(2, &conn_flags); - TEST_ASSERT(rc == 0 && !(conn_flags & BLE_HS_CONN_F_UPDATE)); ++ TEST_ASSERT(!ble_gap_dbg_update_active(2)); + } +} + +static void - ble_l2cap_test_util_update_cb(int status, void *arg) ++ble_l2cap_test_util_update_cb(uint16_t conn_handle, int status, void *arg) +{ ++ ble_l2cap_test_update_conn_handle = conn_handle; + ble_l2cap_test_update_status = status; + ble_l2cap_test_update_arg = arg; +} + +static void +ble_l2cap_test_util_we_update(int peer_accepts) +{ + struct ble_l2cap_sig_update_params params; + uint8_t id; + int rc; + + ble_l2cap_test_util_init(); + + ble_l2cap_test_util_create_conn(2, ((uint8_t[]){1,2,3,4,5,6}), + ble_l2cap_test_util_conn_cb, NULL); + + /* Only the slave can initiate the L2CAP connection update procedure. */ + ble_hs_atomic_conn_set_flags(2, BLE_HS_CONN_F_MASTER, 0); + + params.itvl_min = 0x200; + params.itvl_min = 0x300; + params.slave_latency = 0; + params.timeout_multiplier = 0x100; + rc = ble_l2cap_sig_update(2, ¶ms, ble_l2cap_test_util_update_cb, NULL); + TEST_ASSERT_FATAL(rc == 0); + + ble_hs_test_util_tx_all(); + + /* Ensure an update request got sent. */ - id = ble_l2cap_test_util_verify_tx_update_req(¶ms); ++ id = ble_hs_test_util_verify_tx_l2cap_update_req(¶ms); + + /* Receive response from peer. */ - rc = ble_l2cap_test_util_rx_update_rsp(2, id, !peer_accepts); ++ rc = ble_hs_test_util_rx_l2cap_update_rsp(2, id, !peer_accepts); + TEST_ASSERT(rc == 0); + + /* Ensure callback got called. */ + if (peer_accepts) { + TEST_ASSERT(ble_l2cap_test_update_status == 0); + } else { + TEST_ASSERT(ble_l2cap_test_update_status == BLE_HS_EREJECT); + } + TEST_ASSERT(ble_l2cap_test_update_arg == NULL); +} + +TEST_CASE(ble_l2cap_test_case_sig_update_accept) +{ + ble_l2cap_test_util_peer_updates(1); +} + +TEST_CASE(ble_l2cap_test_case_sig_update_reject) +{ + ble_l2cap_test_util_peer_updates(0); +} + +TEST_CASE(ble_l2cap_test_case_sig_update_init_accept) +{ + ble_l2cap_test_util_we_update(1); +} + +TEST_CASE(ble_l2cap_test_case_sig_update_init_reject) +{ + ble_l2cap_test_util_we_update(0); +} + +TEST_CASE(ble_l2cap_test_case_sig_update_init_fail_master) +{ + struct ble_l2cap_sig_update_params params; + int rc; + + ble_l2cap_test_util_init(); + + ble_l2cap_test_util_create_conn(2, ((uint8_t[]){1,2,3,4,5,6}), + ble_l2cap_test_util_conn_cb, NULL); + + params.itvl_min = 0x200; + params.itvl_min = 0x300; + params.slave_latency = 0; + params.timeout_multiplier = 0x100; + rc = ble_l2cap_sig_update(2, ¶ms, ble_l2cap_test_util_update_cb, NULL); + TEST_ASSERT_FATAL(rc == BLE_HS_EINVAL); + + /* Ensure callback never called. */ + ble_hs_test_util_tx_all(); + TEST_ASSERT(ble_l2cap_test_update_status == -1); +} + +TEST_CASE(ble_l2cap_test_case_sig_update_init_fail_bad_id) +{ + struct ble_l2cap_sig_update_params params; + uint8_t id; + int rc; + + ble_l2cap_test_util_init(); + + ble_l2cap_test_util_create_conn(2, ((uint8_t[]){1,2,3,4,5,6}), + ble_l2cap_test_util_conn_cb, NULL); + + /* Only the slave can initiate the L2CAP connection update procedure. */ + ble_hs_atomic_conn_set_flags(2, BLE_HS_CONN_F_MASTER, 0); + + params.itvl_min = 0x200; + params.itvl_min = 0x300; + params.slave_latency = 0; + params.timeout_multiplier = 0x100; + rc = ble_l2cap_sig_update(2, ¶ms, ble_l2cap_test_util_update_cb, NULL); + TEST_ASSERT_FATAL(rc == 0); + + ble_hs_test_util_tx_all(); + + /* Ensure an update request got sent. */ - id = ble_l2cap_test_util_verify_tx_update_req(¶ms); ++ id = ble_hs_test_util_verify_tx_l2cap_update_req(¶ms); + + /* Receive response from peer with incorrect ID. */ - rc = ble_l2cap_test_util_rx_update_rsp(2, id + 1, 0); ++ rc = ble_hs_test_util_rx_l2cap_update_rsp(2, id + 1, 0); + TEST_ASSERT(rc == BLE_HS_ENOENT); + + /* Ensure callback did not get called. */ + TEST_ASSERT(ble_l2cap_test_update_status == -1); + + /* Receive response from peer with correct ID. */ - rc = ble_l2cap_test_util_rx_update_rsp(2, id, 0); ++ rc = ble_hs_test_util_rx_l2cap_update_rsp(2, id, 0); + TEST_ASSERT(rc == 0); + + /* Ensure callback got called. */ + TEST_ASSERT(ble_l2cap_test_update_status == 0); + TEST_ASSERT(ble_l2cap_test_update_arg == NULL); +} + +TEST_SUITE(ble_l2cap_test_suite) +{ + tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL); + + ble_l2cap_test_case_bad_header(); + ble_l2cap_test_case_frag_single(); + ble_l2cap_test_case_frag_multiple(); + ble_l2cap_test_case_frag_channels(); + ble_l2cap_test_case_sig_unsol_rsp(); + ble_l2cap_test_case_sig_update_accept(); + ble_l2cap_test_case_sig_update_reject(); + ble_l2cap_test_case_sig_update_init_accept(); + ble_l2cap_test_case_sig_update_init_reject(); + ble_l2cap_test_case_sig_update_init_fail_master(); + ble_l2cap_test_case_sig_update_init_fail_bad_id(); +} + +int +ble_l2cap_test_all(void) +{ + ble_l2cap_test_suite(); + + return tu_any_failed; +}