pebble/tests/fw/services/bluetooth/test_local_addr.c
2025-01-27 11:38:16 -08:00

207 lines
7.4 KiB
C

/*
* Copyright 2024 Google LLC
*
* Licensed 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 "services/common/bluetooth/bluetooth_persistent_storage.h"
#include "services/common/bluetooth/local_addr.h"
#include <bluetooth/bluetooth_types.h>
#include <stdbool.h>
#include <clar.h>
////////////////////////////////////////////////////////////////////////////////////////////////////
// Fakes / Stubs
#include "stubs_bt_lock.h"
#include "stubs_logging.h"
#include "stubs_passert.h"
static bool s_last_driver_allow_cycling;
BTDeviceAddress s_last_driver_addr;
bool s_last_driver_addr_is_null;
void bt_driver_set_local_address(bool allow_cycling,
const BTDeviceAddress *pinned_address) {
s_last_driver_allow_cycling = allow_cycling;
if (pinned_address) {
s_last_driver_addr_is_null = false;
s_last_driver_addr = *pinned_address;
} else {
s_last_driver_addr_is_null = true;
memset(&s_last_driver_addr, 0x00, sizeof(s_last_driver_addr));
}
return cl_mock_type(void);
}
BTDeviceAddress s_last_bt_persist_pinned_addr;
bool s_last_bt_persist_pinned_addr_is_null;
bool bt_persistent_storage_get_ble_pinned_address(BTDeviceAddress *address_out) {
if (s_last_bt_persist_pinned_addr_is_null) {
return false;
}
if (address_out) {
*address_out = s_last_bt_persist_pinned_addr;
}
return true;
}
bool bt_persistent_storage_set_ble_pinned_address(const BTDeviceAddress *addr) {
if (addr) {
s_last_bt_persist_pinned_addr_is_null = false;
s_last_bt_persist_pinned_addr = *addr;
} else {
s_last_bt_persist_pinned_addr_is_null = true;
memset(&s_last_bt_persist_pinned_addr, 0x00, sizeof(s_last_bt_persist_pinned_addr));
}
return cl_mock_type(bool);
}
bool bt_persistent_storage_has_pinned_ble_pairings(void) {
return cl_mock_type(bool);
}
#define TEST_PINNED_ADDR_1 ((BTDeviceAddress){ .octets = { 0x11, 0x22, 0x33, 0x33, 0x44, 0x55 } })
#define TEST_PINNED_ADDR_2 ((BTDeviceAddress){ .octets = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff } })
bool bt_driver_id_generate_private_resolvable_address(BTDeviceAddress *root_pinned_address_out) {
*root_pinned_address_out = TEST_PINNED_ADDR_1;
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// Tests
#define TEST_BONDING_ID ((BTBondingID) 1)
static void prv_init_no_pinnings_no_pinned_address(void) {
cl_will_return(bt_persistent_storage_has_pinned_ble_pairings, false);
cl_will_return(bt_persistent_storage_set_ble_pinned_address, true);
cl_will_return(bt_driver_set_local_address, 0);
s_last_bt_persist_pinned_addr_is_null = true;
bt_local_addr_init();
}
static void prv_assert_driver_addr_is_null(void) {
cl_assert_equal_b(s_last_driver_addr_is_null, true);
cl_assert_equal_m(&s_last_driver_addr, &(BTDeviceAddress){}, sizeof(s_last_driver_addr));
}
static void prv_assert_driver_addr_is_addr1(void) {
cl_assert_equal_b(s_last_driver_addr_is_null, false);
cl_assert_equal_m(&s_last_driver_addr, &TEST_PINNED_ADDR_1, sizeof(s_last_driver_addr));
}
static void prv_assert_driver_addr_is_addr2(void) {
cl_assert_equal_b(s_last_driver_addr_is_null, false);
cl_assert_equal_m(&s_last_driver_addr, &TEST_PINNED_ADDR_2, sizeof(s_last_driver_addr));
}
void test_local_addr__initialize(void) {
memset(&s_last_bt_persist_pinned_addr, 0xff, sizeof(s_last_bt_persist_pinned_addr));
memset(&s_last_driver_addr, 0xff, sizeof(s_last_driver_addr));
s_last_bt_persist_pinned_addr_is_null = false;
s_last_driver_allow_cycling = false;
s_last_driver_addr_is_null = false;
}
void test_local_addr__cleanup(void) {
}
void test_local_addr__init_generates_pinned_address_if_needed(void) {
prv_init_no_pinnings_no_pinned_address();
cl_assert_equal_b(false, s_last_bt_persist_pinned_addr_is_null);
cl_assert_equal_m(&s_last_bt_persist_pinned_addr,
&TEST_PINNED_ADDR_1, sizeof(s_last_bt_persist_pinned_addr));
cl_assert_equal_b(true, s_last_driver_allow_cycling);
}
void test_local_addr__init_loads_stored_pinned_address(void) {
cl_will_return(bt_persistent_storage_has_pinned_ble_pairings, true);
cl_will_return(bt_persistent_storage_set_ble_pinned_address, true);
cl_will_return(bt_driver_set_local_address, 0);
s_last_bt_persist_pinned_addr_is_null = false;
s_last_bt_persist_pinned_addr = TEST_PINNED_ADDR_2;
bt_local_addr_init();
cl_assert_equal_b(false, s_last_driver_allow_cycling);
prv_assert_driver_addr_is_addr2();
}
void test_local_addr__pause_resume(void) {
prv_init_no_pinnings_no_pinned_address();
// flip to make sure that bt_local_addr_pause_cycling() will set these again:
s_last_driver_allow_cycling = true;
s_last_driver_addr_is_null = false;
cl_will_return(bt_driver_set_local_address, 0);
bt_local_addr_pause_cycling();
cl_assert_equal_b(false, s_last_driver_allow_cycling);
// Check that it's using the pinned address that was generated upon initialization:
prv_assert_driver_addr_is_addr1();
bt_local_addr_pause_cycling();
// Already paused, shouldn't result in a bt_driver_set_local_address() call.
bt_local_addr_resume_cycling();
// Still paused, shouldn't result in a bt_driver_set_local_address() call.
// flip to make sure that bt_local_addr_pause_cycling() will set these again:
s_last_driver_allow_cycling = true;
s_last_driver_addr_is_null = false;
cl_will_return(bt_driver_set_local_address, 0);
bt_local_addr_resume_cycling();
cl_assert_equal_b(true, s_last_driver_allow_cycling);
prv_assert_driver_addr_is_null();
}
void test_local_addr__pin_unpin(void) {
prv_init_no_pinnings_no_pinned_address();
// Pin:
cl_will_return(bt_driver_set_local_address, 0);
cl_will_return(bt_persistent_storage_has_pinned_ble_pairings, true);
bt_local_addr_pin(&TEST_PINNED_ADDR_1);
bt_local_addr_handle_bonding_change(TEST_BONDING_ID, BtPersistBondingOpDidAdd);
cl_assert_equal_b(false, s_last_driver_allow_cycling);
prv_assert_driver_addr_is_addr1();
// Unpin (done implicitly when bonding is removed):
cl_will_return(bt_persistent_storage_has_pinned_ble_pairings, false);
cl_will_return(bt_driver_set_local_address, 0);
bt_local_addr_handle_bonding_change(TEST_BONDING_ID, BtPersistBondingOpWillDelete);
cl_assert_equal_b(true, s_last_driver_allow_cycling);
prv_assert_driver_addr_is_null();
}
void test_local_addr__pause_then_pin(void) {
prv_init_no_pinnings_no_pinned_address();
// Pause:
cl_will_return(bt_driver_set_local_address, 0);
bt_local_addr_pause_cycling();
cl_assert_equal_b(false, s_last_driver_allow_cycling);
prv_assert_driver_addr_is_addr1();
// Pin, expect pinned address to be sent to BT driver:
cl_will_return(bt_driver_set_local_address, 0);
cl_will_return(bt_persistent_storage_has_pinned_ble_pairings, true);
bt_local_addr_pin(&TEST_PINNED_ADDR_1);
bt_local_addr_handle_bonding_change(TEST_BONDING_ID, BtPersistBondingOpDidAdd);
cl_assert_equal_b(false, s_last_driver_allow_cycling);
prv_assert_driver_addr_is_addr1();
}