Skip to content

Commit ad54c58

Browse files
committed
nimble/host: Add UT for large value Read By Type and Find By Type Value
Verify that Read By Type and Find By Type Value correctly handle attribute values exceeding the old hardcoded buffer limits. Tests cover full value return, MTU-based truncation, large value matching, value mismatch, and length mismatch. Also raise the 16-byte limit in the Find By Type Value test helper to BLE_ATT_ATTR_MAX_LEN.
1 parent c34aa22 commit ad54c58

File tree

2 files changed

+139
-2
lines changed

2 files changed

+139
-2
lines changed

nimble/host/test/src/ble_att_svr_test.c

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2126,6 +2126,142 @@ TEST_CASE_SELF(ble_att_svr_test_unsupported_req)
21262126
ble_att_svr_test_assert_mbufs_freed();
21272127
}
21282128

2129+
/**
2130+
* Tests that Read By Type and Find By Type Value work correctly with attribute
2131+
* values larger than the old hardcoded buffer limits (19 and 16 bytes
2132+
* respectively). Verifies proper truncation per Core Spec 3.4.4.2:
2133+
* max value length = min(ATT_MTU - 4, 253).
2134+
*/
2135+
TEST_CASE_SELF(ble_att_svr_test_large_value)
2136+
{
2137+
static uint8_t large_val[128];
2138+
uint16_t conn_handle;
2139+
uint16_t mtu;
2140+
uint16_t expected_len;
2141+
int rc;
2142+
int i;
2143+
2144+
/* Fill test buffer with a recognizable pattern. */
2145+
for (i = 0; i < (int)sizeof(large_val); i++) {
2146+
large_val[i] = i;
2147+
}
2148+
2149+
/***
2150+
* Read By Type with large attribute value (MTU = 260).
2151+
* max value = min(260 - 4, 253) = 253, but our value is 128 bytes so
2152+
* the full value should be returned without truncation.
2153+
*/
2154+
mtu = 260;
2155+
conn_handle = ble_att_svr_test_misc_init(mtu);
2156+
2157+
ble_att_svr_test_attr_r_1 = large_val;
2158+
ble_att_svr_test_attr_r_1_len = sizeof(large_val);
2159+
2160+
/* Register a primary service attribute with the r_1 access callback. */
2161+
ble_att_svr_test_misc_register_uuid(
2162+
BLE_UUID16_DECLARE(BLE_ATT_UUID_PRIMARY_SERVICE),
2163+
HA_FLAG_PERM_RW, 1, ble_att_svr_test_misc_attr_fn_r_1);
2164+
2165+
/* Read by type: value is 128 bytes, fits within min(256, 253) = 253. */
2166+
rc = ble_hs_test_util_rx_att_read_type_req16(conn_handle, 1, 0xffff,
2167+
BLE_ATT_UUID_PRIMARY_SERVICE);
2168+
TEST_ASSERT(rc == 0);
2169+
ble_att_svr_test_misc_verify_tx_read_type_rsp(
2170+
((struct ble_att_svr_test_type_entry[]) { {
2171+
.handle = 1,
2172+
.value = large_val,
2173+
.value_len = sizeof(large_val),
2174+
}, {
2175+
.handle = 0,
2176+
} }));
2177+
2178+
/***
2179+
* Read By Type with value truncated by MTU.
2180+
* MTU = 64, max value = min(64 - 4, 253) = 60. Value is 128 bytes,
2181+
* so response should contain only the first 60 bytes.
2182+
*/
2183+
mtu = 64;
2184+
conn_handle = ble_att_svr_test_misc_init(mtu);
2185+
2186+
ble_att_svr_test_attr_r_1 = large_val;
2187+
ble_att_svr_test_attr_r_1_len = sizeof(large_val);
2188+
2189+
ble_att_svr_test_misc_register_uuid(
2190+
BLE_UUID16_DECLARE(BLE_ATT_UUID_PRIMARY_SERVICE),
2191+
HA_FLAG_PERM_RW, 1, ble_att_svr_test_misc_attr_fn_r_1);
2192+
2193+
expected_len = mtu - 4; /* 60 */
2194+
2195+
rc = ble_hs_test_util_rx_att_read_type_req16(conn_handle, 1, 0xffff,
2196+
BLE_ATT_UUID_PRIMARY_SERVICE);
2197+
TEST_ASSERT(rc == 0);
2198+
ble_att_svr_test_misc_verify_tx_read_type_rsp(
2199+
((struct ble_att_svr_test_type_entry[]) { {
2200+
.handle = 1,
2201+
.value = large_val,
2202+
.value_len = expected_len,
2203+
}, {
2204+
.handle = 0,
2205+
} }));
2206+
2207+
/***
2208+
* Find By Type Value with large attribute value (> 16 bytes).
2209+
* The request value must match the full attribute value for a hit.
2210+
*/
2211+
mtu = 260;
2212+
conn_handle = ble_att_svr_test_misc_init(mtu);
2213+
2214+
ble_att_svr_test_attr_r_1 = large_val;
2215+
ble_att_svr_test_attr_r_1_len = sizeof(large_val);
2216+
2217+
ble_att_svr_test_misc_register_uuid(
2218+
BLE_UUID16_DECLARE(BLE_ATT_UUID_PRIMARY_SERVICE),
2219+
HA_FLAG_PERM_RW, 1, ble_att_svr_test_misc_attr_fn_r_1);
2220+
2221+
/* Search with the correct 128-byte value: should match. */
2222+
rc = ble_hs_test_util_rx_att_find_type_value_req(
2223+
conn_handle, 1, 0xffff, BLE_ATT_UUID_PRIMARY_SERVICE,
2224+
large_val, sizeof(large_val));
2225+
TEST_ASSERT(rc == 0);
2226+
ble_att_svr_test_misc_verify_tx_find_type_value_rsp(
2227+
((struct ble_att_svr_test_type_value_entry[]) { {
2228+
.first = 1,
2229+
.last = 1,
2230+
}, {
2231+
.first = 0,
2232+
} }));
2233+
2234+
/***
2235+
* Find By Type Value with wrong large value: should not match.
2236+
*/
2237+
{
2238+
uint8_t wrong_val[128];
2239+
memcpy(wrong_val, large_val, sizeof(wrong_val));
2240+
wrong_val[64] ^= 0xff; /* Flip one byte in the middle. */
2241+
2242+
rc = ble_hs_test_util_rx_att_find_type_value_req(
2243+
conn_handle, 1, 0xffff, BLE_ATT_UUID_PRIMARY_SERVICE,
2244+
wrong_val, sizeof(wrong_val));
2245+
TEST_ASSERT(rc != 0);
2246+
ble_hs_test_util_verify_tx_err_rsp(
2247+
BLE_ATT_OP_FIND_TYPE_VALUE_REQ, 1,
2248+
BLE_ATT_ERR_ATTR_NOT_FOUND);
2249+
}
2250+
2251+
/***
2252+
* Find By Type Value with length mismatch: should not match.
2253+
*/
2254+
rc = ble_hs_test_util_rx_att_find_type_value_req(
2255+
conn_handle, 1, 0xffff, BLE_ATT_UUID_PRIMARY_SERVICE,
2256+
large_val, 64);
2257+
TEST_ASSERT(rc != 0);
2258+
ble_hs_test_util_verify_tx_err_rsp(
2259+
BLE_ATT_OP_FIND_TYPE_VALUE_REQ, 1,
2260+
BLE_ATT_ERR_ATTR_NOT_FOUND);
2261+
2262+
ble_att_svr_test_assert_mbufs_freed();
2263+
}
2264+
21292265
TEST_SUITE(ble_att_svr_suite)
21302266
{
21312267
ble_att_svr_test_mtu();
@@ -2143,4 +2279,5 @@ TEST_SUITE(ble_att_svr_suite)
21432279
ble_att_svr_test_indicate();
21442280
ble_att_svr_test_oom();
21452281
ble_att_svr_test_unsupported_req();
2282+
ble_att_svr_test_large_value();
21462283
}

nimble/host/test/src/ble_hs_test_util.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -777,10 +777,10 @@ ble_hs_test_util_rx_att_find_type_value_req(uint16_t conn_handle,
777777
uint16_t attr_len)
778778
{
779779
struct ble_att_find_type_value_req req;
780-
uint8_t buf[BLE_ATT_FIND_TYPE_VALUE_REQ_BASE_SZ + 16];
780+
uint8_t buf[BLE_ATT_FIND_TYPE_VALUE_REQ_BASE_SZ + BLE_ATT_ATTR_MAX_LEN];
781781
int rc;
782782

783-
TEST_ASSERT(attr_len <= 16);
783+
TEST_ASSERT(attr_len <= BLE_ATT_ATTR_MAX_LEN);
784784

785785
req.bavq_start_handle = start_handle;
786786
req.bavq_end_handle = end_handle;

0 commit comments

Comments
 (0)