blob: a974566c816e2917af7b01c1d472fb9bc70e1230 [file] [log] [blame]
/*
* 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 "testutil/testutil.h"
#include "host/ble_hs_test.h"
#include "ble_hs_test_util.h"
static struct ble_store_status_event ble_store_test_status_event;
static void
ble_store_test_util_verify_peer_deleted(const ble_addr_t *addr)
{
union ble_store_value value;
union ble_store_key key;
ble_addr_t addrs[64];
int num_addrs;
int rc;
int i;
memset(&key, 0, sizeof key);
key.sec.peer_addr = *addr;
rc = ble_store_read(BLE_STORE_OBJ_TYPE_OUR_SEC, &key, &value);
TEST_ASSERT(rc == BLE_HS_ENOENT);
rc = ble_store_read(BLE_STORE_OBJ_TYPE_PEER_SEC, &key, &value);
TEST_ASSERT(rc == BLE_HS_ENOENT);
memset(&key, 0, sizeof key);
key.cccd.peer_addr = *addr;
rc = ble_store_read(BLE_STORE_OBJ_TYPE_CCCD, &key, &value);
TEST_ASSERT(rc == BLE_HS_ENOENT);
rc = ble_store_util_bonded_peers(addrs, &num_addrs,
sizeof addrs / sizeof addrs[0]);
TEST_ASSERT_FATAL(rc == 0);
for (i = 0; i < num_addrs; i++) {
TEST_ASSERT(ble_addr_cmp(addr, addrs + i) != 0);
}
}
static int
ble_store_test_util_status_overflow(struct ble_store_status_event *event,
void *arg)
{
int *status;
status = arg;
ble_store_test_status_event = *event;
return *status;
}
static void
ble_store_test_util_overflow_sec(int is_our_sec)
{
union ble_store_value val;
int obj_type;
int status;
int rc;
int i;
ble_hs_test_util_init();
ble_hs_cfg.store_status_cb = ble_store_test_util_status_overflow;
ble_hs_cfg.store_status_arg = &status;
if (is_our_sec) {
obj_type = BLE_STORE_OBJ_TYPE_OUR_SEC;
} else {
obj_type = BLE_STORE_OBJ_TYPE_PEER_SEC;
}
memset(&ble_store_test_status_event, 0,
sizeof ble_store_test_status_event);
memset(&val, 0, sizeof val);
val.sec.peer_addr =
(ble_addr_t){ BLE_ADDR_PUBLIC, { 1, 2, 3, 4, 5, 6 } };
val.sec.ltk_present = 1,
status = BLE_HS_ESTORE_CAP;
for (i = 0; ; i++) {
rc = ble_store_write(obj_type, &val);
if (i < MYNEWT_VAL(BLE_STORE_MAX_BONDS)) {
TEST_ASSERT_FATAL(rc == 0);
} else {
/* This record should have caused an overflow. */
TEST_ASSERT(rc == BLE_HS_ESTORE_CAP);
TEST_ASSERT(ble_store_test_status_event.event_code ==
BLE_STORE_EVENT_OVERFLOW);
TEST_ASSERT(ble_store_test_status_event.overflow.obj_type ==
obj_type);
TEST_ASSERT(ble_store_test_status_event.overflow.value == &val);
break;
}
val.sec.peer_addr.val[0]++;
}
}
static int
ble_store_test_util_count(int obj_type)
{
int count;
int rc;
rc = ble_store_util_count(obj_type, &count);
TEST_ASSERT_FATAL(rc == 0);
return count;
}
TEST_CASE(ble_store_test_peers)
{
struct ble_store_value_sec secs[3] = {
{
.peer_addr = { BLE_ADDR_PUBLIC, { 1, 2, 3, 4, 5, 6 } },
.ltk_present = 1,
},
{
/* Address value is a duplicate of above, but type differs. */
.peer_addr = { BLE_ADDR_RANDOM, { 1, 2, 3, 4, 5, 6 } },
.ltk_present = 1,
},
{
.peer_addr = { BLE_ADDR_PUBLIC, { 2, 3, 4, 5, 6, 7 } },
.ltk_present = 1,
},
};
ble_addr_t peer_addrs[3];
int num_addrs;
int rc;
int i;
ble_hs_test_util_init();
for (i = 0; i < sizeof secs / sizeof secs[0]; i++) {
rc = ble_store_write_our_sec(secs + i);
TEST_ASSERT_FATAL(rc == 0);
rc = ble_store_write_peer_sec(secs + i);
TEST_ASSERT_FATAL(rc == 0);
}
rc = ble_store_util_bonded_peers(peer_addrs, &num_addrs,
sizeof peer_addrs / sizeof peer_addrs[0]);
TEST_ASSERT_FATAL(rc == 0);
TEST_ASSERT(num_addrs == sizeof secs / sizeof secs[0]);
for (i = 0; i < num_addrs; i++) {
TEST_ASSERT(ble_addr_cmp(&peer_addrs[i], &secs[i].peer_addr) == 0);
}
}
TEST_CASE(ble_store_test_delete_peer)
{
struct ble_store_value_sec secs[2] = {
{
.peer_addr = { BLE_ADDR_PUBLIC, { 1, 2, 3, 4, 5, 6 } },
.ltk_present = 1,
},
{
/* Address value is a duplicate of above, but type differs. */
.peer_addr = { BLE_ADDR_RANDOM, { 1, 2, 3, 4, 5, 6 } },
.ltk_present = 1,
},
};
struct ble_store_value_cccd cccds[3] = {
/* First two belong to first peer. */
{
.peer_addr = secs[0].peer_addr,
.chr_val_handle = 5,
},
{
.peer_addr = secs[0].peer_addr,
.chr_val_handle = 8,
},
/* Last belongs to second peer. */
{
.peer_addr = secs[1].peer_addr,
.chr_val_handle = 5,
},
};
union ble_store_value value;
union ble_store_key key;
int count;
int rc;
int i;
ble_hs_test_util_init();
for (i = 0; i < sizeof secs / sizeof secs[0]; i++) {
rc = ble_store_write_our_sec(secs + i);
TEST_ASSERT_FATAL(rc == 0);
rc = ble_store_write_peer_sec(secs + i);
TEST_ASSERT_FATAL(rc == 0);
}
for (i = 0; i < sizeof cccds / sizeof cccds[0]; i++) {
rc = ble_store_write_cccd(cccds + i);
TEST_ASSERT_FATAL(rc == 0);
}
/* Delete first peer. */
rc = ble_store_util_delete_peer(&secs[0].peer_addr);
TEST_ASSERT_FATAL(rc == 0);
/* Ensure all traces of first peer have been removed. */
ble_store_test_util_verify_peer_deleted(&secs[0].peer_addr);
/* Ensure second peer data is still intact. */
ble_store_key_from_value_sec(&key.sec, secs + 1);
rc = ble_store_util_count(BLE_STORE_OBJ_TYPE_OUR_SEC, &count);
TEST_ASSERT_FATAL(rc == 0);
TEST_ASSERT(count == 1);
rc = ble_store_read_our_sec(&key.sec, &value.sec);
TEST_ASSERT_FATAL(rc == 0);
TEST_ASSERT(memcmp(&value.sec, secs + 1, sizeof value.sec) == 0);
rc = ble_store_util_count(BLE_STORE_OBJ_TYPE_PEER_SEC, &count);
TEST_ASSERT_FATAL(rc == 0);
TEST_ASSERT(count == 1);
rc = ble_store_read_peer_sec(&key.sec, &value.sec);
TEST_ASSERT_FATAL(rc == 0);
TEST_ASSERT(memcmp(&value.sec, secs + 1, sizeof value.sec) == 0);
ble_store_key_from_value_cccd(&key.cccd, cccds + 2);
rc = ble_store_util_count(BLE_STORE_OBJ_TYPE_CCCD, &count);
TEST_ASSERT_FATAL(rc == 0);
TEST_ASSERT(count == 1);
rc = ble_store_read_cccd(&key.cccd, &value.cccd);
TEST_ASSERT_FATAL(rc == 0);
TEST_ASSERT(memcmp(&value.cccd, cccds + 2, sizeof value.cccd) == 0);
/* Delete second peer. */
rc = ble_store_util_delete_peer(&secs[1].peer_addr);
TEST_ASSERT_FATAL(rc == 0);
/* Ensure all traces of first peer have been removed. */
ble_store_test_util_verify_peer_deleted(&secs[1].peer_addr);
}
TEST_CASE(ble_store_test_count)
{
struct ble_store_value_sec secs[4] = {
{
.peer_addr = { BLE_ADDR_PUBLIC, { 1, 2, 3, 4, 5, 6 } },
.ltk_present = 1,
},
{
.peer_addr = { BLE_ADDR_RANDOM, { 1, 2, 3, 4, 5, 6 } },
.ltk_present = 1,
},
{
.peer_addr = { BLE_ADDR_PUBLIC, { 2, 3, 4, 5, 6, 7 } },
.ltk_present = 1,
},
{
.peer_addr = { BLE_ADDR_RANDOM, { 3, 4, 5, 6, 7, 8 } },
.ltk_present = 1,
},
};
struct ble_store_value_cccd cccds[2] = {
{
.peer_addr = secs[0].peer_addr,
.chr_val_handle = 5,
},
{
.peer_addr = secs[0].peer_addr,
.chr_val_handle = 8,
},
};
int count;
int rc;
int i;
ble_hs_test_util_init();
/*** Verify initial counts are 0. */
rc = ble_store_util_count(BLE_STORE_OBJ_TYPE_OUR_SEC, &count);
TEST_ASSERT_FATAL(rc == 0);
TEST_ASSERT(count == 0);
rc = ble_store_util_count(BLE_STORE_OBJ_TYPE_PEER_SEC, &count);
TEST_ASSERT_FATAL(rc == 0);
TEST_ASSERT(count == 0);
rc = ble_store_util_count(BLE_STORE_OBJ_TYPE_CCCD, &count);
TEST_ASSERT_FATAL(rc == 0);
TEST_ASSERT(count == 0);
/* Write some test data. */
for (i = 0; i < 3; i++) {
rc = ble_store_write_our_sec(secs + i);
TEST_ASSERT_FATAL(rc == 0);
}
for (i = 0; i < 2; i++) {
rc = ble_store_write_peer_sec(secs + i);
TEST_ASSERT_FATAL(rc == 0);
}
for (i = 0; i < 1; i++) {
rc = ble_store_write_cccd(cccds + i);
TEST_ASSERT_FATAL(rc == 0);
}
/*** Verify counts after populating store. */
rc = ble_store_util_count(BLE_STORE_OBJ_TYPE_OUR_SEC, &count);
TEST_ASSERT_FATAL(rc == 0);
TEST_ASSERT(count == 3);
rc = ble_store_util_count(BLE_STORE_OBJ_TYPE_PEER_SEC, &count);
TEST_ASSERT_FATAL(rc == 0);
TEST_ASSERT(count == 2);
rc = ble_store_util_count(BLE_STORE_OBJ_TYPE_CCCD, &count);
TEST_ASSERT_FATAL(rc == 0);
TEST_ASSERT(count == 1);
}
TEST_CASE(ble_store_test_overflow)
{
ble_store_test_util_overflow_sec(0);
ble_store_test_util_overflow_sec(1);
}
TEST_CASE(ble_store_test_clear)
{
const struct ble_store_value_sec secs[2] = {
{
.peer_addr = { BLE_ADDR_PUBLIC, { 1, 2, 3, 4, 5, 6 } },
.ltk_present = 1,
},
{
/* Address value is a duplicate of above, but type differs. */
.peer_addr = { BLE_ADDR_RANDOM, { 1, 2, 3, 4, 5, 6 } },
.ltk_present = 1,
},
};
const struct ble_store_value_cccd cccds[3] = {
/* First two belong to first peer. */
{
.peer_addr = secs[0].peer_addr,
.chr_val_handle = 5,
},
{
.peer_addr = secs[0].peer_addr,
.chr_val_handle = 8,
},
/* Last belongs to second peer. */
{
.peer_addr = secs[1].peer_addr,
.chr_val_handle = 5,
},
};
int rc;
int i;
ble_hs_test_util_init();
for (i = 0; i < sizeof secs / sizeof secs[0]; i++) {
rc = ble_store_write_our_sec(secs + i);
TEST_ASSERT_FATAL(rc == 0);
rc = ble_store_write_peer_sec(secs + i);
TEST_ASSERT_FATAL(rc == 0);
}
for (i = 0; i < sizeof cccds / sizeof cccds[0]; i++) {
rc = ble_store_write_cccd(cccds + i);
TEST_ASSERT_FATAL(rc == 0);
}
/* Sanity check. */
TEST_ASSERT_FATAL(
ble_store_test_util_count(BLE_STORE_OBJ_TYPE_OUR_SEC) == 2);
TEST_ASSERT_FATAL(
ble_store_test_util_count(BLE_STORE_OBJ_TYPE_PEER_SEC) == 2);
TEST_ASSERT_FATAL(
ble_store_test_util_count(BLE_STORE_OBJ_TYPE_CCCD) == 3);
/* Ensure store is empty after clear gets called. */
rc = ble_store_clear();
TEST_ASSERT_FATAL(rc == 0);
TEST_ASSERT(ble_store_test_util_count(BLE_STORE_OBJ_TYPE_OUR_SEC) == 0);
TEST_ASSERT(ble_store_test_util_count(BLE_STORE_OBJ_TYPE_PEER_SEC) == 0);
TEST_ASSERT(ble_store_test_util_count(BLE_STORE_OBJ_TYPE_CCCD) == 0);
/* Ensure second clear succeeds with no effect. */
rc = ble_store_clear();
TEST_ASSERT_FATAL(rc == 0);
TEST_ASSERT(ble_store_test_util_count(BLE_STORE_OBJ_TYPE_OUR_SEC) == 0);
TEST_ASSERT(ble_store_test_util_count(BLE_STORE_OBJ_TYPE_PEER_SEC) == 0);
TEST_ASSERT(ble_store_test_util_count(BLE_STORE_OBJ_TYPE_CCCD) == 0);
}
TEST_SUITE(ble_store_suite)
{
tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
ble_store_test_peers();
ble_store_test_delete_peer();
ble_store_test_count();
ble_store_test_overflow();
ble_store_test_clear();
}
int
ble_store_test_all(void)
{
ble_store_suite();
return tu_any_failed;
}