blob: 469d96c53e3684bec3e4d13418f46b10c576afa6 [file] [log] [blame]
/*
* Copyright (c) 2022 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include <zephyr/bluetooth/addr.h>
#include <host/keys.h>
#include "mocks/conn.h"
#include "mocks/hci_core.h"
#include "mocks/keys_help_utils.h"
#include "mocks/hci_core_expects.h"
#include "testing_common_defs.h"
/* This LUT contains different combinations of ID and Address pairs */
extern const struct id_addr_pair testing_id_addr_pair_lut[CONFIG_BT_MAX_PAIRED];
/* This list holds returned references while filling keys pool */
extern struct bt_keys *returned_keys_refs[CONFIG_BT_MAX_PAIRED];
/* Pointer to the current set of oldest testing parameter */
struct id_addr_pair const *oldest_params_vector;
static int bt_unpair_custom_fake(uint8_t id, const bt_addr_le_t *addr)
{
struct bt_keys *keys = NULL;
/* Find the key slot with matched id and address */
keys = bt_keys_find_addr(id, addr);
if (keys) {
bt_keys_clear(keys);
}
/* This check is used here because bt_unpair() is called with a local variable address */
expect_single_call_bt_unpair(oldest_params_vector->id, oldest_params_vector->addr);
return 0;
}
static int bt_unpair_unreachable_custom_fake(uint8_t id, const bt_addr_le_t *addr)
{
ARG_UNUSED(id);
ARG_UNUSED(addr);
zassert_unreachable("Unexpected call to 'bt_unpair()' occurred");
return 0;
}
static void bt_conn_foreach_key_slot_0_in_use_custom_fake(int type, bt_conn_foreach_cb func,
void *data)
{
struct bt_conn conn;
/* This will make the effect as if there is a disconnection */
conn.state = BT_CONN_DISCONNECTED;
conn.id = 0x9E;
func(&conn, data);
/* This will make the effect as if there is a connection with no key */
conn.state = BT_CONN_CONNECTED;
conn.id = 0xFF;
bt_addr_le_copy(&conn.le.dst, (const bt_addr_le_t *)BT_ADDR_LE_ANY);
bt_conn_get_dst_fake.return_val = &conn.le.dst;
func(&conn, data);
/* This will make the effect as if key at slot 0 is in use with a connection */
conn.state = BT_CONN_CONNECTED;
conn.id = testing_id_addr_pair_lut[0].id;
bt_addr_le_copy(&conn.le.dst, testing_id_addr_pair_lut[0].addr);
bt_conn_get_dst_fake.return_val = &conn.le.dst;
func(&conn, data);
}
static void bt_conn_foreach_all_keys_in_use_custom_fake(int type, bt_conn_foreach_cb func,
void *data)
{
struct bt_conn conn;
/* This will make the effect as if key at slot 'x' is in use with a connection */
for (size_t i = 0; i < ARRAY_SIZE(testing_id_addr_pair_lut); i++) {
conn.state = BT_CONN_CONNECTED;
conn.id = testing_id_addr_pair_lut[i].id;
bt_addr_le_copy(&conn.le.dst, testing_id_addr_pair_lut[i].addr);
bt_conn_get_dst_fake.return_val = &conn.le.dst;
func(&conn, data);
}
}
static void bt_conn_foreach_no_keys_in_use_custom_fake(int type, bt_conn_foreach_cb func,
void *data)
{
struct bt_conn conn;
/* This will make the effect as if key at slot 'x' is in use with a connection */
for (size_t i = 0; i < ARRAY_SIZE(testing_id_addr_pair_lut); i++) {
conn.state = BT_CONN_DISCONNECTED;
conn.id = testing_id_addr_pair_lut[i].id;
bt_addr_le_copy(&conn.le.dst, testing_id_addr_pair_lut[i].addr);
bt_conn_get_dst_fake.return_val = &conn.le.dst;
func(&conn, data);
}
}
/* Setup test variables */
static void test_case_setup(void *f)
{
Z_TEST_SKIP_IFNDEF(CONFIG_BT_KEYS_OVERWRITE_OLDEST);
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_get_addr_full_list_overwrite_oldest, NULL, NULL, test_case_setup, NULL, NULL);
/*
* Test adding extra (ID, Address) pair while the keys pool list is full while all keys are in
* use with connections so that no more (ID, Address) pairs can be added.
*
* Constraints:
* - Keys pool list is full
* - All Keys are used with a connection
* - CONFIG_BT_KEYS_OVERWRITE_OLDEST is enabled
*
* Expected behaviour:
* - NULL pointer is returned as there is no room
*/
ZTEST(bt_keys_get_addr_full_list_overwrite_oldest, test_full_list_all_keys_in_use)
{
struct bt_keys *returned_key;
uint8_t id = BT_ADDR_ID_3;
bt_addr_le_t *addr = BT_ADDR_LE_3;
bt_unpair_fake.custom_fake = bt_unpair_unreachable_custom_fake;
bt_conn_foreach_fake.custom_fake = bt_conn_foreach_all_keys_in_use_custom_fake;
returned_key = bt_keys_get_addr(id, addr);
zassert_true(returned_key == NULL, "bt_keys_get_addr() returned a non-NULL reference");
}
/*
* Test adding extra (ID, Address) pair while the keys pool list is full, but no keys are used with
* connections. New (ID, Address) pairs can be added by replacing the oldest pair.
*
* Constraints:
* - Keys pool list is full
* - All Keys are not used with a connection
* - CONFIG_BT_KEYS_OVERWRITE_OLDEST is enabled
*
* Expected behaviour:
* - A valid pointer in the keys pool is returned, matching the one previously assigned to the
* oldest key (index 0).
*/
ZTEST(bt_keys_get_addr_full_list_overwrite_oldest, test_full_list_no_keys_in_use)
{
struct bt_keys *returned_key;
uint8_t id = BT_ADDR_ID_3;
bt_addr_le_t *addr = BT_ADDR_LE_3;
uint32_t expected_oldest_params_ref_idx;
expected_oldest_params_ref_idx = 0;
oldest_params_vector = &testing_id_addr_pair_lut[expected_oldest_params_ref_idx];
bt_unpair_fake.custom_fake = bt_unpair_custom_fake;
bt_conn_foreach_fake.custom_fake = bt_conn_foreach_no_keys_in_use_custom_fake;
returned_key = bt_keys_get_addr(id, addr);
zassert_true(returned_key != NULL, "bt_keys_get_addr() returned a NULL reference");
zassert_true(returned_key == returned_keys_refs[expected_oldest_params_ref_idx],
"bt_keys_get_addr() returned reference doesn't match expected one");
}
/*
* Test adding extra (ID, Address) pair while the keys pool list is full when the oldest key slot
* is in use with a connection but others keys aren't.
* New (ID, address) pair should replace the oldest one that's not in use.
*
* Constraints:
* - Keys pool list is full
* - Oldest key at slot 0 is used with a connection
* - Next oldest key (slot 1) isn't used with a connection
* - CONFIG_BT_KEYS_OVERWRITE_OLDEST is enabled
*
* Expected behaviour:
* - A valid pointer in the keys pool is returned, matching the one previously assigned to the
* oldest key (index 1).
*/
ZTEST(bt_keys_get_addr_full_list_overwrite_oldest, test_full_list_key_0_in_use_key_1_oldest)
{
struct bt_keys *returned_key;
uint8_t id = BT_ADDR_ID_4;
bt_addr_le_t *addr = BT_ADDR_LE_4;
uint32_t expected_oldest_params_ref_idx;
expected_oldest_params_ref_idx = 1;
oldest_params_vector = &testing_id_addr_pair_lut[expected_oldest_params_ref_idx];
bt_unpair_fake.custom_fake = bt_unpair_custom_fake;
bt_conn_foreach_fake.custom_fake = bt_conn_foreach_key_slot_0_in_use_custom_fake;
returned_key = bt_keys_get_addr(id, addr);
zassert_true(returned_key != NULL, "bt_keys_get_addr() returned a NULL reference");
zassert_true(returned_key == returned_keys_refs[expected_oldest_params_ref_idx],
"bt_keys_get_addr() returned reference doesn't match expected one");
}
/*
* Test adding extra (ID, Address) pair while the keys pool list is full when the oldest key slot
* is in use with a connection but others keys aren't.
* New (ID, address) pair should replace the oldest one that's not in use.
*
* Constraints:
* - Keys pool list is full
* - Key at slot 0 is used with a connection
* - oldest key (slot 2) isn't used with a connection
* - CONFIG_BT_KEYS_OVERWRITE_OLDEST is enabled
*
* Expected behaviour:
* - A valid pointer in the keys pool is returned, matching the one previously assigned to the
* oldest key (index 2).
*/
ZTEST(bt_keys_get_addr_full_list_overwrite_oldest, test_full_list_key_0_in_use_key_2_oldest)
{
struct bt_keys *returned_key;
uint8_t id = BT_ADDR_ID_5;
bt_addr_le_t *addr = BT_ADDR_LE_5;
uint32_t expected_oldest_params_ref_idx;
#if defined(CONFIG_BT_KEYS_OVERWRITE_OLDEST)
/* Normally first items inserted in the list are the oldest.
* For this particular test, we need to override that by setting
* the 'aging_counter'
*/
returned_keys_refs[1]->aging_counter = bt_keys_get_aging_counter_val();
#endif
expected_oldest_params_ref_idx = 2;
oldest_params_vector = &testing_id_addr_pair_lut[expected_oldest_params_ref_idx];
bt_unpair_fake.custom_fake = bt_unpair_custom_fake;
bt_conn_foreach_fake.custom_fake = bt_conn_foreach_key_slot_0_in_use_custom_fake;
returned_key = bt_keys_get_addr(id, addr);
zassert_true(returned_key != NULL, "bt_keys_get_addr() returned a NULL reference");
zassert_true(returned_key == returned_keys_refs[expected_oldest_params_ref_idx],
"bt_keys_get_addr() returned reference doesn't match expected one");
}