From 60345c1ddc11a0f5d06ba573c6ba28713abccea6 Mon Sep 17 00:00:00 2001 From: Ahmed Moheb Date: Thu, 8 Sep 2022 20:28:46 +0200 Subject: [PATCH] tests: bluetooth: host: Add UT for bt_keys_update_usage() Unit test project for bt_keys_update_usage(). This part of subsys/bluetooth/host/keys.c unit testing. Signed-off-by: Ahmed Moheb --- subsys/bluetooth/host/keys.c | 5 + .../keys/bt_keys_update_usage/CMakeLists.txt | 22 +++ .../host/keys/bt_keys_update_usage/prj.conf | 12 ++ .../host/keys/bt_keys_update_usage/src/main.c | 139 ++++++++++++++++++ .../src/test_suite_save_aging_counter.c | 82 +++++++++++ .../test_suite_update_usage_invalid_inputs.c | 30 ++++ .../keys/bt_keys_update_usage/testcase.yaml | 16 ++ .../host/keys/mocks/keys_help_utils.h | 1 + .../host/keys/mocks/settings_store_expects.c | 8 + .../host/keys/mocks/settings_store_expects.h | 8 + 10 files changed, 323 insertions(+) create mode 100644 tests/bluetooth/host/keys/bt_keys_update_usage/CMakeLists.txt create mode 100644 tests/bluetooth/host/keys/bt_keys_update_usage/prj.conf create mode 100644 tests/bluetooth/host/keys/bt_keys_update_usage/src/main.c create mode 100644 tests/bluetooth/host/keys/bt_keys_update_usage/src/test_suite_save_aging_counter.c create mode 100644 tests/bluetooth/host/keys/bt_keys_update_usage/src/test_suite_update_usage_invalid_inputs.c create mode 100644 tests/bluetooth/host/keys/bt_keys_update_usage/testcase.yaml diff --git a/subsys/bluetooth/host/keys.c b/subsys/bluetooth/host/keys.c index 5040903aa6b..632d67f3d99 100644 --- a/subsys/bluetooth/host/keys.c +++ b/subsys/bluetooth/host/keys.c @@ -542,5 +542,10 @@ uint32_t bt_keys_get_aging_counter_val(void) { return aging_counter_val; } + +struct bt_keys *bt_keys_get_last_keys_updated(void) +{ + return last_keys_updated; +} #endif /* CONFIG_BT_KEYS_OVERWRITE_OLDEST */ #endif /* ZTEST_UNITTEST */ diff --git a/tests/bluetooth/host/keys/bt_keys_update_usage/CMakeLists.txt b/tests/bluetooth/host/keys/bt_keys_update_usage/CMakeLists.txt new file mode 100644 index 00000000000..9569511d98b --- /dev/null +++ b/tests/bluetooth/host/keys/bt_keys_update_usage/CMakeLists.txt @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +project(bt_keys_update_usage) +find_package(Zephyr COMPONENTS unittest HINTS $ENV{ZEPHYR_BASE}) + +add_subdirectory(${ZEPHYR_BASE}/tests/bluetooth/host host_mocks) +add_subdirectory(${ZEPHYR_BASE}/tests/bluetooth/host/keys/mocks mocks) + +target_link_libraries(testbinary PRIVATE mocks host_mocks) + +target_sources(testbinary + PRIVATE + src/main.c + src/test_suite_save_aging_counter.c + src/test_suite_update_usage_invalid_inputs.c + + # Unit under test + $ENV{ZEPHYR_BASE}/subsys/bluetooth/host/keys.c + $ENV{ZEPHYR_BASE}/subsys/bluetooth/common/addr.c +) diff --git a/tests/bluetooth/host/keys/bt_keys_update_usage/prj.conf b/tests/bluetooth/host/keys/bt_keys_update_usage/prj.conf new file mode 100644 index 00000000000..0d8659cbf89 --- /dev/null +++ b/tests/bluetooth/host/keys/bt_keys_update_usage/prj.conf @@ -0,0 +1,12 @@ +CONFIG_ZTEST=y +CONFIG_ZTEST_NEW_API=y +CONFIG_BT=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_MAX_PAIRED=11 +CONFIG_ASSERT=y +CONFIG_ASSERT_LEVEL=2 +CONFIG_ASSERT_VERBOSE=y + +CONFIG_LOG=n +CONFIG_BT_DEBUG_LOG=n +CONFIG_TEST_LOGGING_DEFAULTS=n diff --git a/tests/bluetooth/host/keys/bt_keys_update_usage/src/main.c b/tests/bluetooth/host/keys/bt_keys_update_usage/src/main.c new file mode 100644 index 00000000000..e10d43d0ac3 --- /dev/null +++ b/tests/bluetooth/host/keys/bt_keys_update_usage/src/main.c @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "mocks/keys_help_utils.h" +#include "mocks/settings_store_expects.h" +#include "testing_common_defs.h" + +#include +#include +#include + +#include + +DEFINE_FFF_GLOBALS; + +/* This LUT contains different combinations of ID, Address and key type. + * Item in this list will be used to fill keys pool. + */ +const struct id_addr_pair testing_id_addr_pair_lut[] = { + + {BT_ADDR_ID_1, BT_ADDR_LE_1}, {BT_ADDR_ID_1, BT_RPA_ADDR_LE_1}, + {BT_ADDR_ID_1, BT_RPA_ADDR_LE_2}, {BT_ADDR_ID_1, BT_ADDR_LE_3}, + + {BT_ADDR_ID_2, BT_ADDR_LE_1}, {BT_ADDR_ID_2, BT_RPA_ADDR_LE_2}, + {BT_ADDR_ID_2, BT_RPA_ADDR_LE_3}, {BT_ADDR_ID_2, BT_ADDR_LE_2}, + + {BT_ADDR_ID_3, BT_ADDR_LE_1}, {BT_ADDR_ID_3, BT_ADDR_LE_2}, + + {BT_ADDR_ID_4, BT_ADDR_LE_1}}; + +/* This list will hold returned references while filling keys pool */ +struct bt_keys *returned_keys_refs[CONFIG_BT_MAX_PAIRED]; + +/* Holds the last key reference updated */ +static struct bt_keys *last_keys_updated; + +BUILD_ASSERT(ARRAY_SIZE(testing_id_addr_pair_lut) == CONFIG_BT_MAX_PAIRED); +BUILD_ASSERT(ARRAY_SIZE(testing_id_addr_pair_lut) == ARRAY_SIZE(returned_keys_refs)); + +static void tc_setup(void *f) +{ + clear_key_pool(); + int rv = fill_key_pool_by_id_addr(testing_id_addr_pair_lut, + ARRAY_SIZE(testing_id_addr_pair_lut), returned_keys_refs); + + zassert_true(rv == 0, "Failed to fill keys pool list, error code %d", -rv); + + last_keys_updated = returned_keys_refs[CONFIG_BT_MAX_PAIRED - 1]; +} + +ZTEST_SUITE(bt_keys_update_usage_overwrite_oldest_enabled, NULL, NULL, tc_setup, NULL, NULL); + +/* + * Request updating non-existing item in the keys pool list + * + * Constraints: + * - Keys pool list is filled with items that are different from the testing ID and address pair + * used + * + * Expected behaviour: + * - Last updated key reference isn't changed + */ +ZTEST(bt_keys_update_usage_overwrite_oldest_enabled, test_update_non_existing_key) +{ + uint8_t id = BT_ADDR_ID_5; + bt_addr_le_t *addr = BT_ADDR_LE_5; + + bt_keys_update_usage(id, addr); + + zassert_equal_ptr(bt_keys_get_last_keys_updated(), last_keys_updated, + "bt_keys_update_usage() changed last updated key reference unexpectedly"); +} + +/* + * Request updating the latest key reference + * + * Constraints: + * - Keys pool list is filled with items + * - ID and address pair used are the last added pair to the list + * + * Expected behaviour: + * - Last updated key reference isn't changed + */ +ZTEST(bt_keys_update_usage_overwrite_oldest_enabled, test_update_latest_reference) +{ + uint8_t id = testing_id_addr_pair_lut[CONFIG_BT_MAX_PAIRED - 1].id; + bt_addr_le_t *addr = testing_id_addr_pair_lut[CONFIG_BT_MAX_PAIRED - 1].addr; + + bt_keys_update_usage(id, addr); + + zassert_equal_ptr(bt_keys_get_last_keys_updated(), last_keys_updated, + "bt_keys_update_usage() changed last updated key reference unexpectedly"); +} + +/* + * Request updating existing items aging counter + * + * Constraints: + * - Keys pool list is filled with items + * - ID and address used exist in the keys pool list + * - CONFIG_BT_KEYS_SAVE_AGING_COUNTER_ON_PAIRING isn't enabled + * + * Expected behaviour: + * - Last updated key reference matches the last updated key reference + */ +ZTEST(bt_keys_update_usage_overwrite_oldest_enabled, test_update_non_latest_reference) +{ + uint8_t id; + uint32_t old_aging_counter; + bt_addr_le_t *addr; + struct bt_keys *expected_updated_keys; + struct id_addr_pair const *params_vector; + + if (IS_ENABLED(CONFIG_BT_KEYS_SAVE_AGING_COUNTER_ON_PAIRING)) { + ztest_test_skip(); + } + + for (size_t it = 0; it < ARRAY_SIZE(testing_id_addr_pair_lut); it++) { + params_vector = &testing_id_addr_pair_lut[it]; + id = params_vector->id; + addr = params_vector->addr; + expected_updated_keys = returned_keys_refs[it]; + old_aging_counter = expected_updated_keys->aging_counter; + + bt_keys_update_usage(id, addr); + + zassert_true(expected_updated_keys->aging_counter > (old_aging_counter), + "bt_keys_update_usage() set incorrect aging counter"); + + zassert_equal_ptr( + bt_keys_get_last_keys_updated(), expected_updated_keys, + "bt_keys_update_usage() changed last updated key reference unexpectedly"); + + expect_not_called_settings_save_one(); + } +} diff --git a/tests/bluetooth/host/keys/bt_keys_update_usage/src/test_suite_save_aging_counter.c b/tests/bluetooth/host/keys/bt_keys_update_usage/src/test_suite_save_aging_counter.c new file mode 100644 index 00000000000..c6402a95dcd --- /dev/null +++ b/tests/bluetooth/host/keys/bt_keys_update_usage/src/test_suite_save_aging_counter.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "mocks/keys_help_utils.h" +#include "mocks/settings_store.h" +#include "mocks/settings_store_expects.h" +#include "testing_common_defs.h" + +#include +#include + +#include + +/* This LUT contains different combinations of ID and Address pairs. + * It is defined in main.c. + */ +extern const struct id_addr_pair testing_id_addr_pair_lut[CONFIG_BT_MAX_PAIRED]; + +/* This list holds returned references while filling keys pool. + * It is defined in main.c. + */ +extern struct bt_keys *returned_keys_refs[CONFIG_BT_MAX_PAIRED]; + +static void tc_setup(void *f) +{ + Z_TEST_SKIP_IFNDEF(CONFIG_BT_KEYS_SAVE_AGING_COUNTER_ON_PAIRING); + + clear_key_pool(); + int rv = fill_key_pool_by_id_addr(testing_id_addr_pair_lut, + ARRAY_SIZE(testing_id_addr_pair_lut), returned_keys_refs); + + zassert_true(rv == 0, "Failed to fill keys pool list, error code %d", -rv); +} + +ZTEST_SUITE(bt_keys_update_usage_save_aging_counter, NULL, NULL, tc_setup, NULL, NULL); + +/* + * Request updating existing items aging counter + * + * Constraints: + * - Keys pool list is filled with items + * - ID and address used exist in the keys pool list + * - CONFIG_BT_KEYS_SAVE_AGING_COUNTER_ON_PAIRING is enabled + * + * Expected behaviour: + * - Last updated key reference matches the last updated key reference + * - bt_keys_store() is called once with the correct parameters + */ +ZTEST(bt_keys_update_usage_save_aging_counter, test_update_usage_and_save_aging_counter) +{ + uint8_t id; + uint32_t old_aging_counter; + bt_addr_le_t *addr; + struct bt_keys *expected_updated_keys; + struct id_addr_pair const *params_vector; + + for (size_t it = 0; it < ARRAY_SIZE(testing_id_addr_pair_lut); it++) { + params_vector = &testing_id_addr_pair_lut[it]; + id = params_vector->id; + addr = params_vector->addr; + expected_updated_keys = returned_keys_refs[it]; + old_aging_counter = expected_updated_keys->aging_counter; + + /* Reset fake functions call counter */ + SETTINGS_STORE_FFF_FAKES_LIST(RESET_FAKE); + + bt_keys_update_usage(id, addr); + + zassert_true(expected_updated_keys->aging_counter > (old_aging_counter), + "bt_keys_update_usage() set incorrect aging counter"); + + zassert_equal_ptr( + bt_keys_get_last_keys_updated(), expected_updated_keys, + "bt_keys_update_usage() changed last updated key reference unexpectedly"); + + /* Check if bt_keys_store() was called */ + expect_single_call_settings_save_one(expected_updated_keys->storage_start); + } +} diff --git a/tests/bluetooth/host/keys/bt_keys_update_usage/src/test_suite_update_usage_invalid_inputs.c b/tests/bluetooth/host/keys/bt_keys_update_usage/src/test_suite_update_usage_invalid_inputs.c new file mode 100644 index 00000000000..5776f83a464 --- /dev/null +++ b/tests/bluetooth/host/keys/bt_keys_update_usage/src/test_suite_update_usage_invalid_inputs.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "host_mocks/assert.h" + +#include +#include + +#include + +ZTEST_SUITE(bt_keys_update_usage_invalid_inputs, NULL, NULL, NULL, NULL, NULL); + +/* + * Test function with NULL address + * + * Constraints: + * - Any ID value can be used + * - Address is passed as NULL + * + * Expected behaviour: + * - An assertion fails and execution stops + */ +ZTEST(bt_keys_update_usage_invalid_inputs, test_null_device_address) +{ + expect_assert(); + bt_keys_update_usage(0x00, NULL); +} diff --git a/tests/bluetooth/host/keys/bt_keys_update_usage/testcase.yaml b/tests/bluetooth/host/keys/bt_keys_update_usage/testcase.yaml new file mode 100644 index 00000000000..a2e1b866a3a --- /dev/null +++ b/tests/bluetooth/host/keys/bt_keys_update_usage/testcase.yaml @@ -0,0 +1,16 @@ +common: + tags: test_framework bluetooth host +tests: + bluetooth.host.bt_keys_update_usage.default: + type: unit + extra_configs: + - CONFIG_BT_SMP=y + - CONFIG_BT_KEYS_OVERWRITE_OLDEST=y + bluetooth.host.bt_keys_update_usage.save_aging_counter: + type: unit + extra_configs: + - CONFIG_SETTINGS=y + - CONFIG_BT_SETTINGS=y + - CONFIG_BT_SMP=y + - CONFIG_BT_KEYS_OVERWRITE_OLDEST=y + - CONFIG_BT_KEYS_SAVE_AGING_COUNTER_ON_PAIRING=y diff --git a/tests/bluetooth/host/keys/mocks/keys_help_utils.h b/tests/bluetooth/host/keys/mocks/keys_help_utils.h index 2d5f62e0120..a04ba0bc89d 100644 --- a/tests/bluetooth/host/keys/mocks/keys_help_utils.h +++ b/tests/bluetooth/host/keys/mocks/keys_help_utils.h @@ -23,6 +23,7 @@ struct id_addr_type { struct bt_keys *bt_keys_get_key_pool(void); #if defined(CONFIG_BT_KEYS_OVERWRITE_OLDEST) uint32_t bt_keys_get_aging_counter_val(void); +struct bt_keys *bt_keys_get_last_keys_updated(void); #endif /* keys_help_utils.c declarations */ diff --git a/tests/bluetooth/host/keys/mocks/settings_store_expects.c b/tests/bluetooth/host/keys/mocks/settings_store_expects.c index 8a0b554edd0..11da81c21af 100644 --- a/tests/bluetooth/host/keys/mocks/settings_store_expects.c +++ b/tests/bluetooth/host/keys/mocks/settings_store_expects.c @@ -35,3 +35,11 @@ void expect_single_call_settings_save_one(const void *value) zassert_equal(settings_save_one_fake.arg2_val, BT_KEYS_STORAGE_LEN, "'%s()' was called with incorrect '%s' value", func_name, "val_len"); } + +void expect_not_called_settings_save_one(void) +{ + const char *func_name = "settings_save_one"; + + zassert_equal(settings_save_one_fake.call_count, 0, "'%s()' was called unexpectedly", + func_name); +} diff --git a/tests/bluetooth/host/keys/mocks/settings_store_expects.h b/tests/bluetooth/host/keys/mocks/settings_store_expects.h index 0c92af0a07a..2e6a99ca723 100644 --- a/tests/bluetooth/host/keys/mocks/settings_store_expects.h +++ b/tests/bluetooth/host/keys/mocks/settings_store_expects.h @@ -21,3 +21,11 @@ void expect_single_call_settings_delete(void); * - settings_save_one() to be called once with correct parameters */ void expect_single_call_settings_save_one(const void *value); + +/* + * Validate expected behaviour when settings_save_one() isn't called + * + * Expected behaviour: + * - settings_save_one() isn't called at all + */ +void expect_not_called_settings_save_one(void);