/* * 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 "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_SELF(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); } ble_hs_test_util_assert_mbufs_freed(NULL); } TEST_CASE_SELF(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); ble_hs_test_util_assert_mbufs_freed(NULL); } TEST_CASE_SELF(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); ble_hs_test_util_assert_mbufs_freed(NULL); } TEST_CASE_SELF(ble_store_test_overflow) { ble_store_test_util_overflow_sec(0); ble_store_test_util_overflow_sec(1); ble_hs_test_util_assert_mbufs_freed(NULL); } TEST_CASE_SELF(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); ble_hs_test_util_assert_mbufs_freed(NULL); } TEST_SUITE(ble_store_suite) { ble_store_test_peers(); ble_store_test_delete_peer(); ble_store_test_count(); ble_store_test_overflow(); ble_store_test_clear(); }