402 lines
9.7 KiB
C
402 lines
9.7 KiB
C
/*
|
|
* test-utils.c
|
|
* SPDX-FileCopyrightText: 2016-2025 BlueALSA developers
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
#if HAVE_CONFIG_H
|
|
# include <config.h>
|
|
#endif
|
|
|
|
#include <errno.h>
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
|
|
#include <bluetooth/bluetooth.h>
|
|
#include <check.h>
|
|
|
|
#include "error.h"
|
|
#include "hci.h"
|
|
#include "utils.h"
|
|
#include "shared/defs.h"
|
|
#include "shared/ffb.h"
|
|
#include "shared/hex.h"
|
|
#include "shared/nv.h"
|
|
#include "shared/rc.h"
|
|
#include "shared/rt.h"
|
|
|
|
#include "inc/check.inc"
|
|
|
|
CK_START_TEST(test_g_dbus_bluez_object_path_to_hci_dev_id) {
|
|
|
|
ck_assert_int_eq(g_dbus_bluez_object_path_to_hci_dev_id("/org/bluez"), -1);
|
|
ck_assert_int_eq(g_dbus_bluez_object_path_to_hci_dev_id("/org/bluez/hci0"), 0);
|
|
ck_assert_int_eq(g_dbus_bluez_object_path_to_hci_dev_id("/org/bluez/hci5"), 5);
|
|
|
|
} CK_END_TEST
|
|
|
|
CK_START_TEST(test_g_dbus_bluez_object_path_to_bdaddr) {
|
|
|
|
bdaddr_t addr_ok = {{ 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12 }};
|
|
bdaddr_t addr;
|
|
|
|
ck_assert_ptr_eq(g_dbus_bluez_object_path_to_bdaddr(
|
|
"/org/bluez/hci0/dev_12_34_56_78_9A_BC", &addr), &addr);
|
|
ck_assert_int_eq(bacmp(&addr, &addr_ok), 0);
|
|
|
|
ck_assert_ptr_eq(g_dbus_bluez_object_path_to_bdaddr(
|
|
"/org/bluez/dev_12_34_56_78_9A_BC/fd1", &addr), &addr);
|
|
ck_assert_int_eq(bacmp(&addr, &addr_ok), 0);
|
|
|
|
ck_assert_ptr_eq(g_dbus_bluez_object_path_to_bdaddr(
|
|
"/org/bluez/dev_12_34_56_78_9A_XX", &addr), NULL);
|
|
|
|
} CK_END_TEST
|
|
|
|
CK_START_TEST(test_g_variant_sanitize_object_path) {
|
|
|
|
char path1[] = "/some/valid_path/123";
|
|
char path2[] = "/a#$*/invalid-path";
|
|
|
|
ck_assert_str_eq(g_variant_sanitize_object_path(path1), "/some/valid_path/123");
|
|
ck_assert_str_eq(g_variant_sanitize_object_path(path2), "/a___/invalid_path");
|
|
|
|
} CK_END_TEST
|
|
|
|
#if DEBUG
|
|
CK_START_TEST(test_batostr_) {
|
|
|
|
const bdaddr_t ba = {{ 1, 2, 3, 4, 5, 6 }};
|
|
char tmp[18];
|
|
|
|
ba2str(&ba, tmp);
|
|
ck_assert_str_eq(batostr_(&ba), tmp);
|
|
|
|
} CK_END_TEST
|
|
#endif
|
|
|
|
CK_START_TEST(test_error_code_strerror) {
|
|
ck_assert_str_eq(error_code_strerror(ERROR_CODE_INVALID_SIZE), "Invalid size");
|
|
ck_assert_str_eq(error_code_strerror(0xFFFF), "Unknown error");
|
|
} CK_END_TEST
|
|
|
|
CK_START_TEST(test_nv_lookup_entry) {
|
|
|
|
const nv_entry_t entries[] = {
|
|
{ "name1", .v.i = 1 },
|
|
{ "name2", .v.i = 2 },
|
|
{ 0 }
|
|
};
|
|
|
|
ck_assert_ptr_eq(nv_lookup_entry(entries, "invalid"), NULL);
|
|
ck_assert_ptr_eq(nv_lookup_entry(entries, "name2"), &entries[1]);
|
|
|
|
} CK_END_TEST
|
|
|
|
CK_START_TEST(test_nv_name_from_int) {
|
|
|
|
const nv_entry_t entries[] = {
|
|
{ "name1", .v.i = 1 },
|
|
{ "name2", .v.i = -42 },
|
|
{ 0 }
|
|
};
|
|
|
|
ck_assert_ptr_eq(nv_name_from_int(entries, 0), NULL);
|
|
ck_assert_str_eq(nv_name_from_int(entries, -42), "name2");
|
|
|
|
} CK_END_TEST
|
|
|
|
CK_START_TEST(test_nv_name_from_uint) {
|
|
|
|
const nv_entry_t entries[] = {
|
|
{ "name1", .v.u = 1 },
|
|
{ "name2", .v.u = 0xFFEEDDCC },
|
|
{ 0 }
|
|
};
|
|
|
|
ck_assert_ptr_eq(nv_name_from_uint(entries, 0), NULL);
|
|
ck_assert_str_eq(nv_name_from_uint(entries, 0xFFEEDDCC), "name2");
|
|
|
|
} CK_END_TEST
|
|
|
|
CK_START_TEST(test_nv_join_names) {
|
|
|
|
const nv_entry_t entries_zero[] = {{ 0 }};
|
|
const nv_entry_t entries[] = {
|
|
{ "name1", .v.i = 1 },
|
|
{ "name2", .v.i = 2 },
|
|
{ 0 }
|
|
};
|
|
|
|
char *tmp;
|
|
|
|
ck_assert_str_eq(tmp = nv_join_names(entries_zero), "");
|
|
free(tmp);
|
|
|
|
ck_assert_str_eq(tmp = nv_join_names(entries), "name1, name2");
|
|
free(tmp);
|
|
|
|
} CK_END_TEST
|
|
|
|
struct test_rc {
|
|
rc_t rc;
|
|
bool freed;
|
|
};
|
|
|
|
static void test_rc_free(void * ptr) {
|
|
struct test_rc * tmp = ptr;
|
|
tmp->freed = true;
|
|
}
|
|
|
|
CK_START_TEST(test_rc_callback) {
|
|
|
|
struct test_rc rc;
|
|
|
|
rc_init(&rc.rc, test_rc_free);
|
|
ck_assert_int_eq(rc.rc.count, 1);
|
|
rc.freed = false;
|
|
|
|
ck_assert_ptr_eq(rc_ref(&rc), &rc);
|
|
ck_assert_int_eq(rc.rc.count, 2);
|
|
ck_assert_int_eq(rc.freed, false);
|
|
|
|
ck_assert_int_eq(rc_unref_with_count(&rc), 1);
|
|
ck_assert_int_eq(rc.rc.count, 1);
|
|
ck_assert_int_eq(rc.freed, false);
|
|
|
|
ck_assert_int_eq(rc_unref_with_count(&rc), 0);
|
|
ck_assert_int_eq(rc.rc.count, 0);
|
|
ck_assert_int_eq(rc.freed, true);
|
|
|
|
} CK_END_TEST
|
|
|
|
CK_START_TEST(test_difftimespec) {
|
|
|
|
struct timespec ts1, ts2, ts;
|
|
|
|
ts1.tv_sec = ts2.tv_sec = 12345;
|
|
ts1.tv_nsec = ts2.tv_nsec = 67890;
|
|
ck_assert_int_eq(difftimespec(&ts1, &ts2, &ts), 0);
|
|
ck_assert_int_eq(ts.tv_sec, 0);
|
|
ck_assert_int_eq(ts.tv_nsec, 0);
|
|
|
|
ts1.tv_sec = 10;
|
|
ts1.tv_nsec = 100000000;
|
|
ts2.tv_sec = 10;
|
|
ts2.tv_nsec = 500000000;
|
|
ck_assert_int_gt(difftimespec(&ts1, &ts2, &ts), 0);
|
|
ck_assert_int_eq(ts.tv_sec, 0);
|
|
ck_assert_int_eq(ts.tv_nsec, 400000000);
|
|
|
|
ts1.tv_sec = 10;
|
|
ts1.tv_nsec = 100000000;
|
|
ts2.tv_sec = 11;
|
|
ts2.tv_nsec = 500000000;
|
|
ck_assert_int_gt(difftimespec(&ts1, &ts2, &ts), 0);
|
|
ck_assert_int_eq(ts.tv_sec, 1);
|
|
ck_assert_int_eq(ts.tv_nsec, 400000000);
|
|
|
|
ts1.tv_sec = 10;
|
|
ts1.tv_nsec = 800000000;
|
|
ts2.tv_sec = 12;
|
|
ts2.tv_nsec = 100000000;
|
|
ck_assert_int_gt(difftimespec(&ts1, &ts2, &ts), 0);
|
|
ck_assert_int_eq(ts.tv_sec, 1);
|
|
ck_assert_int_eq(ts.tv_nsec, 300000000);
|
|
|
|
ts1.tv_sec = 10;
|
|
ts1.tv_nsec = 500000000;
|
|
ts2.tv_sec = 10;
|
|
ts2.tv_nsec = 100000000;
|
|
ck_assert_int_lt(difftimespec(&ts1, &ts2, &ts), 0);
|
|
ck_assert_int_eq(ts.tv_sec, 0);
|
|
ck_assert_int_eq(ts.tv_nsec, 400000000);
|
|
|
|
ts1.tv_sec = 12;
|
|
ts1.tv_nsec = 100000000;
|
|
ts2.tv_sec = 10;
|
|
ts2.tv_nsec = 800000000;
|
|
ck_assert_int_lt(difftimespec(&ts1, &ts2, &ts), 0);
|
|
ck_assert_int_eq(ts.tv_sec, 1);
|
|
ck_assert_int_eq(ts.tv_nsec, 300000000);
|
|
|
|
ts1.tv_sec = 12;
|
|
ts1.tv_nsec = 500000000;
|
|
ts2.tv_sec = 10;
|
|
ts2.tv_nsec = 500000000;
|
|
ck_assert_int_lt(difftimespec(&ts1, &ts2, &ts), 0);
|
|
ck_assert_int_eq(ts.tv_sec, 2);
|
|
ck_assert_int_eq(ts.tv_nsec, 0);
|
|
|
|
} CK_END_TEST
|
|
|
|
CK_START_TEST(test_ffb) {
|
|
|
|
ffb_t ffb_u8 = { 0 };
|
|
ffb_t ffb_16 = { 0 };
|
|
|
|
/* allow free before allocation */
|
|
ffb_free(&ffb_u8);
|
|
ffb_free(&ffb_16);
|
|
|
|
ck_assert_int_eq(ffb_init_uint8_t(&ffb_u8, 64), 0);
|
|
ck_assert_ptr_eq(ffb_u8.data, ffb_u8.tail);
|
|
ck_assert_int_eq(ffb_u8.nmemb, 64);
|
|
|
|
ck_assert_int_eq(ffb_init_int16_t(&ffb_16, 64), 0);
|
|
ck_assert_ptr_eq(ffb_16.data, ffb_16.tail);
|
|
ck_assert_int_eq(ffb_16.nmemb, 64);
|
|
|
|
memcpy(ffb_u8.data, "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ", 36);
|
|
ffb_seek(&ffb_u8, 36);
|
|
|
|
memcpy(ffb_16.data, "11223344556677889900AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXXYYZZ", 36 * 2);
|
|
ffb_seek(&ffb_16, 36);
|
|
|
|
ck_assert_int_eq(ffb_len_in(&ffb_u8), 64 - 36);
|
|
ck_assert_int_eq(ffb_blen_in(&ffb_u8), 64 - 36);
|
|
ck_assert_int_eq(ffb_len_out(&ffb_u8), 36);
|
|
ck_assert_int_eq(ffb_blen_out(&ffb_u8), 36);
|
|
ck_assert_int_eq(((uint8_t *)ffb_u8.tail)[-1], 'Z');
|
|
|
|
ck_assert_int_eq(ffb_len_in(&ffb_16), 64 - 36);
|
|
ck_assert_int_eq(ffb_blen_in(&ffb_16), (64 - 36) * 2);
|
|
ck_assert_int_eq(ffb_len_out(&ffb_16), 36);
|
|
ck_assert_int_eq(ffb_blen_out(&ffb_16), 36 * 2);
|
|
ck_assert_int_eq(((int16_t *)ffb_16.tail)[-1], 0x5a5a);
|
|
|
|
ck_assert_int_eq(ffb_shift(&ffb_u8, 33), 33);
|
|
ck_assert_int_eq(ffb_len_in(&ffb_u8), 64 - (36 - 33));
|
|
ck_assert_int_eq(ffb_len_out(&ffb_u8), 36 - 33);
|
|
ck_assert_mem_eq(ffb_u8.data, "XYZ", ffb_len_out(&ffb_u8));
|
|
ck_assert_int_eq(((uint8_t *)ffb_u8.tail)[-1], 'Z');
|
|
|
|
ck_assert_int_eq(ffb_shift(&ffb_u8, 100), 36 - 33);
|
|
ck_assert_ptr_eq(ffb_u8.data, ffb_u8.tail);
|
|
|
|
ffb_seek(&ffb_u8, 4);
|
|
ck_assert_ptr_ne(ffb_u8.data, ffb_u8.tail);
|
|
|
|
ffb_rewind(&ffb_u8);
|
|
ck_assert_ptr_eq(ffb_u8.data, ffb_u8.tail);
|
|
|
|
ffb_free(&ffb_u8);
|
|
ck_assert_ptr_eq(ffb_u8.data, NULL);
|
|
|
|
ffb_free(&ffb_16);
|
|
ck_assert_ptr_eq(ffb_16.data, NULL);
|
|
|
|
} CK_END_TEST
|
|
|
|
CK_START_TEST(test_ffb_static) {
|
|
|
|
ffb_t ffb = { 0 };
|
|
uint32_t buffer[64];
|
|
|
|
ffb_init_from_array(&ffb, buffer);
|
|
|
|
ck_assert_ptr_eq(ffb.data, buffer);
|
|
ck_assert_ptr_eq(ffb.tail, buffer);
|
|
ck_assert_uint_eq(ffb.nmemb, ARRAYSIZE(buffer));
|
|
ck_assert_uint_eq(ffb.size, 4);
|
|
|
|
} CK_END_TEST
|
|
|
|
CK_START_TEST(test_ffb_resize) {
|
|
|
|
const char *data = "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
const size_t data_len = strlen(data);
|
|
|
|
ffb_t ffb = { 0 };
|
|
ck_assert_int_eq(ffb_init_uint8_t(&ffb, 64), 0);
|
|
|
|
memcpy(ffb.data, data, data_len);
|
|
ffb_seek(&ffb, data_len);
|
|
|
|
ck_assert_int_eq(ffb_len_out(&ffb), data_len);
|
|
ck_assert_int_eq(ffb_len_in(&ffb), 64 - data_len);
|
|
ck_assert_mem_eq(ffb.data, data, data_len);
|
|
|
|
ck_assert_int_eq(ffb_init_uint8_t(&ffb, 128), 0);
|
|
|
|
ck_assert_int_eq(ffb_len_out(&ffb), data_len);
|
|
ck_assert_int_eq(ffb_len_in(&ffb), 128 - data_len);
|
|
ck_assert_mem_eq(ffb.data, data, data_len);
|
|
|
|
ffb_free(&ffb);
|
|
|
|
} CK_END_TEST
|
|
|
|
CK_START_TEST(test_bin2hex) {
|
|
|
|
const uint8_t bin[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0xFF };
|
|
char hex[sizeof(bin) * 2 + 1];
|
|
|
|
ck_assert_int_eq(bin2hex(bin, hex, sizeof(bin)), 12);
|
|
ck_assert_str_eq(hex, "deadbeef00ff");
|
|
|
|
} CK_END_TEST
|
|
|
|
CK_START_TEST(test_hex2bin) {
|
|
|
|
const uint8_t bin_ok[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0x00 };
|
|
const char hex[] = "DEADbeef\x00\xFF";
|
|
uint8_t bin[sizeof(bin_ok)];
|
|
|
|
ck_assert_int_eq(hex2bin(hex, bin, sizeof(hex) - 1), 5);
|
|
ck_assert_mem_eq(bin, bin_ok, sizeof(bin));
|
|
|
|
ck_assert_int_eq(hex2bin(hex, bin, 3), -1);
|
|
ck_assert_int_eq(errno, EINVAL);
|
|
|
|
} CK_END_TEST
|
|
|
|
int main(void) {
|
|
|
|
Suite *s = suite_create(__FILE__);
|
|
TCase *tc = tcase_create(__FILE__);
|
|
SRunner *sr = srunner_create(s);
|
|
|
|
suite_add_tcase(s, tc);
|
|
|
|
/* error.c */
|
|
tcase_add_test(tc, test_error_code_strerror);
|
|
|
|
/* shared/ffb.c */
|
|
tcase_add_test(tc, test_ffb);
|
|
tcase_add_test(tc, test_ffb_static);
|
|
tcase_add_test(tc, test_ffb_resize);
|
|
|
|
/* shared/hex.c */
|
|
tcase_add_test(tc, test_bin2hex);
|
|
tcase_add_test(tc, test_hex2bin);
|
|
|
|
/* shared/nv.c */
|
|
tcase_add_test(tc, test_nv_lookup_entry);
|
|
tcase_add_test(tc, test_nv_name_from_int);
|
|
tcase_add_test(tc, test_nv_name_from_uint);
|
|
tcase_add_test(tc, test_nv_join_names);
|
|
|
|
/* shared/rc.c */
|
|
tcase_add_test(tc, test_rc_callback);
|
|
|
|
/* shared/rt.c */
|
|
tcase_add_test(tc, test_difftimespec);
|
|
|
|
tcase_add_test(tc, test_g_dbus_bluez_object_path_to_hci_dev_id);
|
|
tcase_add_test(tc, test_g_dbus_bluez_object_path_to_bdaddr);
|
|
tcase_add_test(tc, test_g_variant_sanitize_object_path);
|
|
#if DEBUG
|
|
tcase_add_test(tc, test_batostr_);
|
|
#endif
|
|
|
|
srunner_run_all(sr, CK_ENV);
|
|
int nf = srunner_ntests_failed(sr);
|
|
srunner_free(sr);
|
|
|
|
return nf == 0 ? 0 : 1;
|
|
}
|