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/09/22 02:12:21 UTC

[14/59] [abbrv] incubator-mynewt-core git commit: syscfg / sysinit

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d98ddc1c/net/nimble/host/src/test/ble_sm_test_util.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_sm_test_util.h b/net/nimble/host/src/test/ble_sm_test_util.h
deleted file mode 100644
index 3323be6..0000000
--- a/net/nimble/host/src/test/ble_sm_test_util.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/**
- * 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_SM_TEST_UTIL_
-#define H_BLE_SM_TEST_UTIL_
-
-struct ble_sm_test_passkey_info {
-    struct ble_sm_io passkey;
-    uint32_t exp_numcmp;
-    unsigned io_before_rx:1;
-};
-
-struct ble_sm_test_params {
-    uint8_t init_addr_type;
-    uint8_t init_id_addr[6];
-    uint8_t init_rpa[6];
-    uint8_t resp_addr_type;
-    uint8_t resp_id_addr[6];
-    uint8_t resp_rpa[6];
-    struct ble_sm_test_passkey_info passkey_info;
-
-    struct ble_sm_sec_req sec_req;
-    struct ble_sm_pair_cmd pair_req;
-    struct ble_sm_pair_cmd pair_rsp;
-    struct ble_sm_pair_confirm confirm_req[20];
-    struct ble_sm_pair_confirm confirm_rsp[20];
-    struct ble_sm_pair_random random_req[20];
-    struct ble_sm_pair_random random_rsp[20];
-    struct ble_sm_id_info id_info_req;
-    struct ble_sm_id_info id_info_rsp;
-    struct ble_sm_id_addr_info id_addr_info_req;
-    struct ble_sm_id_addr_info id_addr_info_rsp;
-    struct ble_sm_sign_info sign_info_req;
-    struct ble_sm_sign_info sign_info_rsp;
-    struct ble_sm_pair_fail pair_fail;
-
-    int pair_alg;
-    unsigned authenticated:1;
-
-    /*** Secure connections fields. */
-    uint8_t ltk[16];
-    uint8_t our_priv_key[32];
-    struct ble_sm_public_key public_key_req;
-    struct ble_sm_public_key public_key_rsp;
-    struct ble_sm_dhkey_check dhkey_check_req;
-    struct ble_sm_dhkey_check dhkey_check_rsp;
-
-    /*** Legacy fields. */
-    uint8_t stk[16];
-    struct ble_sm_enc_info enc_info_req;
-    struct ble_sm_enc_info enc_info_rsp;
-    struct ble_sm_master_id master_id_req;
-    struct ble_sm_master_id master_id_rsp;
-};
-
-extern int ble_sm_test_gap_event;
-extern int ble_sm_test_gap_status;
-extern struct ble_gap_sec_state ble_sm_test_sec_state;
-
-extern int ble_sm_test_store_obj_type;
-extern union ble_store_key ble_sm_test_store_key;
-extern union ble_store_value ble_sm_test_store_value;
-
-void ble_sm_test_util_init(void);
-int ble_sm_test_util_conn_cb(struct ble_gap_event *ctxt, void *arg);
-void ble_sm_test_util_io_inject(struct ble_sm_test_passkey_info *passkey_info,
-                                uint8_t cur_sm_state);
-void ble_sm_test_util_io_inject_bad(uint16_t conn_handle,
-                                    uint8_t correct_io_act);
-void ble_sm_test_util_io_check_pre(
-    struct ble_sm_test_passkey_info *passkey_info,
-    uint8_t cur_sm_state);
-void ble_sm_test_util_io_check_post(
-    struct ble_sm_test_passkey_info *passkey_info,
-    uint8_t cur_sm_state);
-void ble_sm_test_util_rx_sec_req(uint16_t conn_handle,
-                                 struct ble_sm_sec_req *cmd,
-                                 int exp_status);
-void ble_sm_test_util_verify_tx_pair_fail(struct ble_sm_pair_fail *exp_cmd);
-void ble_sm_test_util_us_lgcy_good(struct ble_sm_test_params *params);
-void ble_sm_test_util_peer_fail_inval(int we_are_master,
-                                      uint8_t *init_addr,
-                                      uint8_t *resp_addr,
-                                      struct ble_sm_pair_cmd *pair_req,
-                                      struct ble_sm_pair_fail *pair_fail);
-void ble_sm_test_util_peer_lgcy_fail_confirm(
-    uint8_t *init_addr,
-    uint8_t *resp_addr,
-    struct ble_sm_pair_cmd *pair_req,
-    struct ble_sm_pair_cmd *pair_rsp,
-    struct ble_sm_pair_confirm *confirm_req,
-    struct ble_sm_pair_confirm *confirm_rsp,
-    struct ble_sm_pair_random *random_req,
-    struct ble_sm_pair_random *random_rsp,
-    struct ble_sm_pair_fail *fail_rsp);
-
-void ble_sm_test_util_peer_lgcy_good(struct ble_sm_test_params *params);
-void ble_sm_test_util_peer_bonding_bad(uint16_t ediv, uint64_t rand_num);
-void ble_sm_test_util_peer_sc_good(struct ble_sm_test_params *params);
-void ble_sm_test_util_us_sc_good(struct ble_sm_test_params *params);
-void ble_sm_test_util_us_fail_inval(struct ble_sm_test_params *params);
-
-#endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d98ddc1c/net/nimble/host/src/test/ble_uuid_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_uuid_test.c b/net/nimble/host/src/test/ble_uuid_test.c
deleted file mode 100644
index 1011303..0000000
--- a/net/nimble/host/src/test/ble_uuid_test.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/**
- * 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 <string.h>
-#include "testutil/testutil.h"
-#include "host/ble_hs_test.h"
-#include "host/ble_uuid.h"
-#include "ble_hs_test_util.h"
-
-TEST_CASE(ble_uuid_test_128_to_16)
-{
-    uint16_t uuid16;
-
-    /*** RFCOMM */
-    uuid16 = ble_uuid_128_to_16(((uint8_t[]) {
-        0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
-        0x00, 0x10, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00
-    }));
-    TEST_ASSERT(uuid16 == 0x0003);
-
-    /*** BNEP */
-    uuid16 = ble_uuid_128_to_16(((uint8_t[]) {
-        0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
-        0x00, 0x10, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00
-    }));
-    TEST_ASSERT(uuid16 == 0x000f);
-
-    /*** L2CAP */
-    uuid16 = ble_uuid_128_to_16(((uint8_t[]) {
-        0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
-        0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00
-    }));
-    TEST_ASSERT(uuid16 == 0x0100);
-
-    /*** ObEXObjectPush */
-    uuid16 = ble_uuid_128_to_16(((uint8_t[]) {
-        0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
-        0x00, 0x10, 0x00, 0x00, 0x05, 0x11, 0x00, 0x00
-    }));
-    TEST_ASSERT(uuid16 == 0x1105);
-
-    /*** Invalid base. */
-    uuid16 = ble_uuid_128_to_16(((uint8_t[]) {
-        0xfb, 0x34, 0x9c, 0x5f, 0x80, 0x00, 0x00, 0x80,
-        0x00, 0x10, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00
-    }));
-    TEST_ASSERT(uuid16 == 0);
-
-    /*** Invalid prefix. */
-    uuid16 = ble_uuid_128_to_16(((uint8_t[]) {
-        0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
-        0x00, 0x10, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01
-    }));
-    TEST_ASSERT(uuid16 == 0);
-
-    /*** 16-bit UUID of 0. */
-    uuid16 = ble_uuid_128_to_16(((uint8_t[]) {
-        0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
-        0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-    }));
-}
-
-TEST_SUITE(ble_uuid_test_suite)
-{
-    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
-
-    ble_uuid_test_128_to_16();
-}
-
-int
-ble_uuid_test_all(void)
-{
-    ble_uuid_test_suite();
-
-    return tu_any_failed;
-}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d98ddc1c/net/nimble/host/test/pkg.yml
----------------------------------------------------------------------
diff --git a/net/nimble/host/test/pkg.yml b/net/nimble/host/test/pkg.yml
new file mode 100644
index 0000000..ce5ed4e
--- /dev/null
+++ b/net/nimble/host/test/pkg.yml
@@ -0,0 +1,41 @@
+# 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.
+#
+pkg.name: net/nimble/host/test
+pkg.type: unittest
+pkg.description: "NimBLE host unit tests."
+pkg.author: "Apache Mynewt <de...@mynewt.incubator.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps:
+    - libs/testutil
+    - net/nimble/host
+
+pkg.deps.SELFTEST:
+    - libs/console/stub
+    - net/nimble/transport/ram
+
+pkg.syscfg_vals.SELFTEST:
+    BLE_HS_DEBUG: 1
+    BLE_HS_PHONY_HCI_ACKS: 1
+    BLE_HS_REQUIRE_OS: 0
+    BLE_MAX_CONNECTIONS: 8
+    BLE_GATT_MAX_PROCS: 16
+    BLE_SM: 1
+    BLE_SM_SC: 1
+    MSYS_1_BLOCK_COUNT: 100

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d98ddc1c/net/nimble/host/test/src/ble_att_clt_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/test/src/ble_att_clt_test.c b/net/nimble/host/test/src/ble_att_clt_test.c
new file mode 100644
index 0000000..ab89e9d
--- /dev/null
+++ b/net/nimble/host/test/src/ble_att_clt_test.c
@@ -0,0 +1,536 @@
+/**
+ * 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_hs_test.h"
+#include "ble_hs_test_util.h"
+
+/**
+ * @return                      The handle of the new test connection.
+ */
+static uint16_t
+ble_att_clt_test_misc_init(void)
+{
+    ble_hs_test_util_init();
+    ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}), NULL,
+                                 NULL);
+    return 2;
+}
+
+static void
+ble_att_clt_test_misc_verify_tx_write(uint16_t handle_id, void *value,
+                                      int value_len, int is_req)
+{
+    struct ble_att_write_req req;
+    struct os_mbuf *om;
+
+    om = ble_hs_test_util_prev_tx_dequeue_pullup();
+    TEST_ASSERT_FATAL(om != NULL);
+
+    if (is_req) {
+        ble_att_write_req_parse(om->om_data, om->om_len, &req);
+    } else {
+        ble_att_write_cmd_parse(om->om_data, om->om_len, &req);
+    }
+
+    TEST_ASSERT(req.bawq_handle == handle_id);
+    TEST_ASSERT(om->om_len == BLE_ATT_WRITE_REQ_BASE_SZ + value_len);
+    TEST_ASSERT(memcmp(om->om_data + BLE_ATT_WRITE_REQ_BASE_SZ, value,
+                       value_len) == 0);
+}
+
+static void
+ble_att_clt_test_tx_write_req_or_cmd(uint16_t conn_handle,
+                                     struct ble_att_write_req *req,
+                                     void *value, int value_len, int is_req)
+{
+    struct os_mbuf *om;
+    int rc;
+
+    om = ble_hs_test_util_om_from_flat(value, value_len);
+    if (is_req) {
+        rc = ble_att_clt_tx_write_req(conn_handle, req, om);
+    } else {
+        rc = ble_att_clt_tx_write_cmd(conn_handle, req, om);
+    }
+    TEST_ASSERT(rc == 0);
+}
+
+TEST_CASE(ble_att_clt_test_tx_find_info)
+{
+    struct ble_att_find_info_req req;
+    uint16_t conn_handle;
+    int rc;
+
+    conn_handle = ble_att_clt_test_misc_init();
+
+    /*** Success. */
+    req.bafq_start_handle = 1;
+    req.bafq_end_handle = 0xffff;
+    rc = ble_att_clt_tx_find_info(conn_handle, &req);
+    TEST_ASSERT(rc == 0);
+
+    /*** Error: start handle of 0. */
+    req.bafq_start_handle = 0;
+    req.bafq_end_handle = 0xffff;
+    rc = ble_att_clt_tx_find_info(conn_handle, &req);
+    TEST_ASSERT(rc == BLE_HS_EINVAL);
+
+    /*** Error: start handle greater than end handle. */
+    req.bafq_start_handle = 500;
+    req.bafq_end_handle = 499;
+    rc = ble_att_clt_tx_find_info(conn_handle, &req);
+    TEST_ASSERT(rc == BLE_HS_EINVAL);
+
+    /*** Success; start and end handles equal. */
+    req.bafq_start_handle = 500;
+    req.bafq_end_handle = 500;
+    rc = ble_att_clt_tx_find_info(conn_handle, &req);
+    TEST_ASSERT(rc == 0);
+}
+
+TEST_CASE(ble_att_clt_test_rx_find_info)
+{
+    struct ble_att_find_info_rsp rsp;
+    uint16_t conn_handle;
+    uint8_t buf[1024];
+    uint8_t uuid128_1[16] = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 };
+    int off;
+    int rc;
+
+    conn_handle = ble_att_clt_test_misc_init();
+
+    /*** One 128-bit UUID. */
+    /* Receive response with attribute mapping. */
+    off = 0;
+    rsp.bafp_format = BLE_ATT_FIND_INFO_RSP_FORMAT_128BIT;
+    ble_att_find_info_rsp_write(buf + off, sizeof buf - off, &rsp);
+    off += BLE_ATT_FIND_INFO_RSP_BASE_SZ;
+
+    htole16(buf + off, 1);
+    off += 2;
+    memcpy(buf + off, uuid128_1, 16);
+    off += 16;
+
+    rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+                                                buf, off);
+    TEST_ASSERT(rc == 0);
+
+    /*** One 16-bit UUID. */
+    /* Receive response with attribute mapping. */
+    off = 0;
+    rsp.bafp_format = BLE_ATT_FIND_INFO_RSP_FORMAT_16BIT;
+    ble_att_find_info_rsp_write(buf + off, sizeof buf - off, &rsp);
+    off += BLE_ATT_FIND_INFO_RSP_BASE_SZ;
+
+    htole16(buf + off, 2);
+    off += 2;
+    htole16(buf + off, 0x000f);
+    off += 2;
+
+    rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+                                                buf, off);
+    TEST_ASSERT(rc == 0);
+
+    /*** Two 16-bit UUIDs. */
+    /* Receive response with attribute mappings. */
+    off = 0;
+    rsp.bafp_format = BLE_ATT_FIND_INFO_RSP_FORMAT_16BIT;
+    ble_att_find_info_rsp_write(buf + off, sizeof buf - off, &rsp);
+    off += BLE_ATT_FIND_INFO_RSP_BASE_SZ;
+
+    htole16(buf + off, 3);
+    off += 2;
+    htole16(buf + off, 0x0010);
+    off += 2;
+
+    htole16(buf + off, 4);
+    off += 2;
+    htole16(buf + off, 0x0011);
+    off += 2;
+
+    rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+                                                buf, off);
+    TEST_ASSERT(rc == 0);
+}
+
+static void
+ble_att_clt_test_case_tx_write_req_or_cmd(int is_req)
+{
+    struct ble_att_write_req req;
+    uint16_t conn_handle;
+    uint8_t value300[500] = { 0 };
+    uint8_t value5[5] = { 6, 7, 54, 34, 8 };
+
+    conn_handle = ble_att_clt_test_misc_init();
+
+    /*** 5-byte write. */
+    req.bawq_handle = 0x1234;
+    ble_att_clt_test_tx_write_req_or_cmd(conn_handle, &req, value5,
+                                         sizeof value5, is_req);
+    ble_hs_test_util_tx_all();
+    ble_att_clt_test_misc_verify_tx_write(0x1234, value5, sizeof value5,
+                                          is_req);
+
+    /*** Overlong write; verify command truncated to ATT MTU. */
+    req.bawq_handle = 0xab83;
+    ble_att_clt_test_tx_write_req_or_cmd(conn_handle, &req, value300,
+                                         sizeof value300, is_req);
+    ble_hs_test_util_tx_all();
+    ble_att_clt_test_misc_verify_tx_write(0xab83, value300,
+                                          BLE_ATT_MTU_DFLT - 3, is_req);
+}
+
+static void
+ble_att_clt_test_misc_prep_good(uint16_t handle, uint16_t offset,
+                                uint8_t *attr_data, uint16_t attr_data_len)
+{
+    struct ble_att_prep_write_cmd req;
+    struct os_mbuf *om;
+    uint16_t conn_handle;
+    int rc;
+    int i;
+
+    conn_handle = ble_att_clt_test_misc_init();
+
+    req.bapc_handle = handle;
+    req.bapc_offset = offset;
+    om = ble_hs_test_util_om_from_flat(attr_data, attr_data_len);
+    rc = ble_att_clt_tx_prep_write(conn_handle, &req, om);
+    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(om->om_len == BLE_ATT_PREP_WRITE_CMD_BASE_SZ + attr_data_len);
+
+    ble_att_prep_write_req_parse(om->om_data, om->om_len, &req);
+    TEST_ASSERT(req.bapc_handle == handle);
+    TEST_ASSERT(req.bapc_offset == offset);
+    for (i = 0; i < attr_data_len; i++) {
+        TEST_ASSERT(om->om_data[BLE_ATT_PREP_WRITE_CMD_BASE_SZ + i] ==
+                    attr_data[i]);
+    }
+}
+
+static void
+ble_att_clt_test_misc_exec_good(uint8_t flags)
+{
+    struct ble_att_exec_write_req req;
+    struct os_mbuf *om;
+    uint16_t conn_handle;
+    int rc;
+
+    conn_handle = ble_att_clt_test_misc_init();
+
+    req.baeq_flags = flags;
+    rc = ble_att_clt_tx_exec_write(conn_handle, &req);
+    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(om->om_len == BLE_ATT_EXEC_WRITE_REQ_SZ);
+
+    ble_att_exec_write_req_parse(om->om_data, om->om_len, &req);
+    TEST_ASSERT(req.baeq_flags == flags);
+}
+
+static void
+ble_att_clt_test_misc_prep_bad(uint16_t handle, uint16_t offset,
+                               uint8_t *attr_data, uint16_t attr_data_len,
+                               int status)
+{
+    struct ble_att_prep_write_cmd req;
+    struct os_mbuf *om;
+    uint16_t conn_handle;
+    int rc;
+
+    conn_handle = ble_att_clt_test_misc_init();
+
+    om = ble_hs_test_util_om_from_flat(attr_data, attr_data_len);
+
+    req.bapc_handle = handle;
+    req.bapc_offset = offset;
+    rc = ble_att_clt_tx_prep_write(conn_handle, &req, om);
+    TEST_ASSERT(rc == status);
+}
+
+TEST_CASE(ble_att_clt_test_tx_write)
+{
+    ble_att_clt_test_case_tx_write_req_or_cmd(0);
+    ble_att_clt_test_case_tx_write_req_or_cmd(1);
+}
+
+TEST_CASE(ble_att_clt_test_tx_read)
+{
+    struct ble_att_read_req req;
+    uint16_t conn_handle;
+    int rc;
+
+    conn_handle = ble_att_clt_test_misc_init();
+
+    /*** Success. */
+    req.barq_handle = 1;
+    rc = ble_att_clt_tx_read(conn_handle, &req);
+    TEST_ASSERT(rc == 0);
+
+    /*** Error: handle of 0. */
+    req.barq_handle = 0;
+    rc = ble_att_clt_tx_read(conn_handle, &req);
+    TEST_ASSERT(rc == BLE_HS_EINVAL);
+}
+
+TEST_CASE(ble_att_clt_test_rx_read)
+{
+    uint16_t conn_handle;
+    uint8_t buf[1024];
+    int rc;
+
+    conn_handle = ble_att_clt_test_misc_init();
+
+    /*** Basic success. */
+    buf[0] = BLE_ATT_OP_READ_RSP;
+    buf[1] = 0;
+    rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+                                                buf, 2);
+    TEST_ASSERT(rc == 0);
+
+    /*** Larger response. */
+    rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+                                                buf, 20);
+    TEST_ASSERT(rc == 0);
+
+    /*** Zero-length response. */
+    rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+                                                buf, 1);
+    TEST_ASSERT(rc == 0);
+}
+
+TEST_CASE(ble_att_clt_test_tx_read_blob)
+{
+    struct ble_att_read_blob_req req;
+    uint16_t conn_handle;
+    int rc;
+
+    conn_handle = ble_att_clt_test_misc_init();
+
+    /*** Success. */
+    req.babq_handle = 1;
+    req.babq_offset = 0;
+    rc = ble_att_clt_tx_read_blob(conn_handle, &req);
+    TEST_ASSERT(rc == 0);
+
+    /*** Error: handle of 0. */
+    req.babq_handle = 0;
+    req.babq_offset = 0;
+    rc = ble_att_clt_tx_read_blob(conn_handle, &req);
+    TEST_ASSERT(rc == BLE_HS_EINVAL);
+}
+
+TEST_CASE(ble_att_clt_test_rx_read_blob)
+{
+    uint16_t conn_handle;
+    uint8_t buf[1024];
+    int rc;
+
+    conn_handle = ble_att_clt_test_misc_init();
+
+    /*** Basic success. */
+    buf[0] = BLE_ATT_OP_READ_BLOB_RSP;
+    buf[1] = 0;
+    rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+                                                buf, 2);
+    TEST_ASSERT(rc == 0);
+
+    /*** Larger response. */
+    rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+                                                buf, 20);
+    TEST_ASSERT(rc == 0);
+
+    /*** Zero-length response. */
+    rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+                                                buf, 1);
+    TEST_ASSERT(rc == 0);
+}
+
+TEST_CASE(ble_att_clt_test_tx_read_mult)
+{
+    struct os_mbuf *om;
+    uint16_t conn_handle;
+    int rc;
+
+    conn_handle = ble_att_clt_test_misc_init();
+
+    /*** Success. */
+    rc = ble_att_clt_tx_read_mult(conn_handle, ((uint16_t[]){ 1, 2 }), 2);
+    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(om->om_len == BLE_ATT_READ_MULT_REQ_BASE_SZ + 4);
+
+    ble_att_read_mult_req_parse(om->om_data, om->om_len);
+    TEST_ASSERT(le16toh(om->om_data + BLE_ATT_READ_MULT_REQ_BASE_SZ) == 1);
+    TEST_ASSERT(le16toh(om->om_data + BLE_ATT_READ_MULT_REQ_BASE_SZ + 2) == 2);
+
+    /*** Error: no handles. */
+    rc = ble_att_clt_tx_read_mult(conn_handle, NULL, 0);
+    TEST_ASSERT(rc == BLE_HS_EINVAL);
+}
+
+TEST_CASE(ble_att_clt_test_rx_read_mult)
+{
+    uint16_t conn_handle;
+    uint8_t buf[1024];
+    int rc;
+
+    conn_handle = ble_att_clt_test_misc_init();
+
+    /*** Basic success. */
+    ble_att_read_mult_rsp_write(buf, sizeof buf);
+    htole16(buf + BLE_ATT_READ_MULT_RSP_BASE_SZ + 0, 12);
+
+    rc = ble_hs_test_util_l2cap_rx_payload_flat(
+        conn_handle, BLE_L2CAP_CID_ATT, buf,
+        BLE_ATT_READ_MULT_RSP_BASE_SZ + 2);
+    TEST_ASSERT(rc == 0);
+
+    /*** Larger response. */
+    htole16(buf + BLE_ATT_READ_MULT_RSP_BASE_SZ + 0, 12);
+    htole16(buf + BLE_ATT_READ_MULT_RSP_BASE_SZ + 2, 43);
+    htole16(buf + BLE_ATT_READ_MULT_RSP_BASE_SZ + 4, 91);
+    rc = ble_hs_test_util_l2cap_rx_payload_flat(
+        conn_handle, BLE_L2CAP_CID_ATT, buf,
+        BLE_ATT_READ_MULT_RSP_BASE_SZ + 6);
+    TEST_ASSERT(rc == 0);
+
+    /*** Zero-length response. */
+    rc = ble_hs_test_util_l2cap_rx_payload_flat(
+        conn_handle, BLE_L2CAP_CID_ATT, buf,
+        BLE_ATT_READ_MULT_RSP_BASE_SZ + 0);
+    TEST_ASSERT(rc == 0);
+}
+
+TEST_CASE(ble_att_clt_test_tx_prep_write)
+{
+    uint8_t attr_data[512];
+    int i;
+
+    for (i = 0; i < sizeof attr_data; i++) {
+        attr_data[i] = i;
+    }
+
+    /*** Success. */
+    ble_att_clt_test_misc_prep_good(123, 0, attr_data, 16);
+    ble_att_clt_test_misc_prep_good(5432, 100, attr_data, 2);
+    ble_att_clt_test_misc_prep_good(0x1234, 400, attr_data, 0);
+    ble_att_clt_test_misc_prep_good(5432, 0, attr_data,
+                                    BLE_ATT_MTU_DFLT -
+                                        BLE_ATT_PREP_WRITE_CMD_BASE_SZ);
+    ble_att_clt_test_misc_prep_good(0x1234, 507, attr_data, 5);
+
+    /*** Error: handle of 0. */
+    ble_att_clt_test_misc_prep_bad(0, 0, attr_data, 16, BLE_HS_EINVAL);
+
+    /*** Error: offset + length greater than maximum attribute size. */
+    ble_att_clt_test_misc_prep_bad(1, 507, attr_data, 6, BLE_HS_EINVAL);
+
+    /*** Error: packet larger than MTU. */
+    ble_att_clt_test_misc_prep_bad(1, 0, attr_data,
+                                   BLE_ATT_MTU_DFLT -
+                                       BLE_ATT_PREP_WRITE_CMD_BASE_SZ + 1,
+                                   BLE_HS_EINVAL);
+}
+
+TEST_CASE(ble_att_clt_test_rx_prep_write)
+{
+    struct ble_att_prep_write_cmd rsp;
+    uint16_t conn_handle;
+    uint8_t buf[1024];
+    int rc;
+
+    conn_handle = ble_att_clt_test_misc_init();
+
+    /*** Basic success. */
+    rsp.bapc_handle = 0x1234;
+    rsp.bapc_offset = 0;
+    ble_att_prep_write_rsp_write(buf, sizeof buf, &rsp);
+    memset(buf + BLE_ATT_PREP_WRITE_CMD_BASE_SZ, 1, 5);
+    rc = ble_hs_test_util_l2cap_rx_payload_flat(
+        conn_handle, BLE_L2CAP_CID_ATT, buf,
+        BLE_ATT_PREP_WRITE_CMD_BASE_SZ + 5);
+    TEST_ASSERT(rc == 0);
+
+    /*** 0-length write. */
+    rsp.bapc_handle = 0x1234;
+    rsp.bapc_offset = 0;
+    ble_att_prep_write_rsp_write(buf, sizeof buf, &rsp);
+    rc = ble_hs_test_util_l2cap_rx_payload_flat(
+        conn_handle, BLE_L2CAP_CID_ATT, buf, BLE_ATT_PREP_WRITE_CMD_BASE_SZ);
+    TEST_ASSERT(rc == 0);
+}
+
+TEST_CASE(ble_att_clt_test_tx_exec_write)
+{
+    struct ble_att_exec_write_req req;
+    uint16_t conn_handle;
+    int rc;
+
+    conn_handle = ble_att_clt_test_misc_init();
+
+    /*** Success. */
+    ble_att_clt_test_misc_exec_good(0);
+    ble_att_clt_test_misc_exec_good(BLE_ATT_EXEC_WRITE_F_CONFIRM);
+
+    /*** Error: invalid flags value. */
+    req.baeq_flags = 0x02;
+    rc = ble_att_clt_tx_exec_write(conn_handle, &req);
+    TEST_ASSERT(rc == BLE_HS_EINVAL);
+}
+
+TEST_SUITE(ble_att_clt_suite)
+{
+    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
+    ble_att_clt_test_tx_find_info();
+    ble_att_clt_test_rx_find_info();
+    ble_att_clt_test_tx_read();
+    ble_att_clt_test_rx_read();
+    ble_att_clt_test_tx_read_blob();
+    ble_att_clt_test_rx_read_blob();
+    ble_att_clt_test_tx_read_mult();
+    ble_att_clt_test_rx_read_mult();
+    ble_att_clt_test_tx_write();
+    ble_att_clt_test_tx_prep_write();
+    ble_att_clt_test_rx_prep_write();
+    ble_att_clt_test_tx_exec_write();
+}
+
+int
+ble_att_clt_test_all(void)
+{
+    ble_att_clt_suite();
+
+    return tu_any_failed;
+}