diff --git a/components/utilities/utest/TC_uassert.c b/components/utilities/utest/TC_uassert.c new file mode 100644 index 0000000000..1490c06f50 --- /dev/null +++ b/components/utilities/utest/TC_uassert.c @@ -0,0 +1,73 @@ +#include +#include "utest.h" + +static void TC_uassert_true_false(void) +{ + uassert_true(1); + uassert_false(0); +} + +static void TC_uassert_null_not_null(void) +{ + int *ptr = RT_NULL; + int value = 10; + int *ptr2 = &value; + + uassert_null(ptr); + uassert_not_null(ptr2); +} + +static void TC_uassert_int_op(void) +{ + int a = 5; + int b = 10; + + uassert_int_equal(a, a); + uassert_int_not_equal(a, b); + uassert_int_less(a, b); + uassert_int_less_equal(a, b); + uassert_int_less_equal(a, a); + uassert_int_greater(b, a); + uassert_int_greater_equal(b, a); + uassert_int_greater_equal(b, b); +} + +static void TC_uassert_ptr_op(void) +{ + int a = 5; + int b = 10; + int *ptr_a = &a; + int *ptr_b = &b; + + uassert_ptr_equal(ptr_a, ptr_a); + uassert_ptr_not_equal(ptr_a, ptr_b); +} + +static void TC_uassert_str_op(void) +{ + const char *str1 = "Hello"; + const char *str2 = "Hello"; + const char *str3 = "World"; + + uassert_str_equal(str1, str2); + uassert_str_not_equal(str1, str3); +} + +static void TC_uassert_in_range(void) +{ + int value = 5; + uassert_in_range(value, 1, 10); + uassert_not_in_range(value, 10, 20); +} + +static void utest_do_tc(void) +{ + UTEST_UNIT_RUN(TC_uassert_true_false); + UTEST_UNIT_RUN(TC_uassert_null_not_null); + UTEST_UNIT_RUN(TC_uassert_int_op); + UTEST_UNIT_RUN(TC_uassert_ptr_op); + UTEST_UNIT_RUN(TC_uassert_str_op); + UTEST_UNIT_RUN(TC_uassert_in_range); +} + +UTEST_TC_EXPORT(utest_do_tc, "utest.uassert", RT_NULL, RT_NULL, 10); diff --git a/components/utilities/utest/utest.c b/components/utilities/utest/utest.c index af51508ce5..8d9ad7eef3 100644 --- a/components/utilities/utest/utest.c +++ b/components/utilities/utest/utest.c @@ -231,7 +231,7 @@ static void utest_do_run(const char *utest_name) { if (tc_table[i].init() != RT_EOK) { - LOG_E("[ FAILED ] [ result ] testcase (%s)", tc_table[i].name); + LOG_E("[ FAILED ] [ result ] testcase init (%s)", tc_table[i].name); goto __tc_continue; } } @@ -259,7 +259,7 @@ static void utest_do_run(const char *utest_name) { if (tc_table[i].cleanup() != RT_EOK) { - LOG_E("[ FAILED ] [ result ] testcase (%s)", tc_table[i].name); + LOG_E("[ FAILED ] [ result ] testcase cleanup (%s)", tc_table[i].name); goto __tc_continue; } } @@ -382,7 +382,7 @@ utest_t utest_handle_get(void) void utest_unit_run(test_unit_func func, const char *unit_func_name) { - // LOG_I("[==========] utest unit name: (%s)", unit_func_name); + LOG_I("[==========] utest unit name: (%s)", unit_func_name); local_utest.error = UTEST_PASSED; local_utest.passed_num = 0; local_utest.failed_num = 0; diff --git a/components/utilities/utest/utest.h b/components/utilities/utest/utest.h index a7b6a0d702..db4eebdfcb 100644 --- a/components/utilities/utest/utest.h +++ b/components/utilities/utest/utest.h @@ -172,9 +172,10 @@ utest_t utest_handle_get(void); * @return None * */ -#define UTEST_UNIT_RUN(test_unit_func) \ - utest_unit_run(test_unit_func, #test_unit_func); \ - if(utest_handle_get()->failed_num != 0) return; +#define UTEST_UNIT_RUN(test_unit_func) \ + do { \ + utest_unit_run(test_unit_func, #test_unit_func); \ + } while (0) #ifdef __cplusplus } diff --git a/components/utilities/utest/utest_assert.h b/components/utilities/utest/utest_assert.h index 8edfd1b9ad..e46350b3a3 100644 --- a/components/utilities/utest/utest_assert.h +++ b/components/utilities/utest/utest_assert.h @@ -50,11 +50,17 @@ void utest_assert_buf(const char *a, const char *b, rt_size_t sz, rt_bool_t equa */ #define uassert_true(value) __utest_assert(value, "(" #value ") is false") #define uassert_false(value) __utest_assert(!(value), "(" #value ") is true") + #define uassert_null(value) __utest_assert((const char *)(value) == RT_NULL, "(" #value ") is not null") #define uassert_not_null(value) __utest_assert((const char *)(value) != RT_NULL, "(" #value ") is null") -#define uassert_int_equal(a, b) __utest_assert((a) == (b), "(" #a ") not equal to (" #b ")") -#define uassert_int_not_equal(a, b) __utest_assert((a) != (b), "(" #a ") equal to (" #b ")") +#define __uassert_int_op(a, b, op) __utest_assert((a) op (b), "(" #a ") not " #op " (" #b ")") +#define uassert_int_equal(a, b) __uassert_int_op(a, b, ==) +#define uassert_int_not_equal(a, b) __uassert_int_op(a, b, !=) +#define uassert_int_less(a, b) __uassert_int_op(a, b, <) +#define uassert_int_less_equal(a, b) __uassert_int_op(a, b, <=) +#define uassert_int_greater(a, b) __uassert_int_op(a, b, >) +#define uassert_int_greater_equal(a, b) __uassert_int_op(a, b, >=) #define uassert_ptr_equal(a, b) __utest_assert((const void*)(a) == (const void*)(b), "(" #a ") not equal to (" #b ")") #define uassert_ptr_not_equal(a, b) __utest_assert((const void*)(a) != (const void*)(b), "(" #a ") equal to (" #b ")") diff --git a/src/klibc/utest/TC_rt_memcmp.c b/src/klibc/utest/TC_rt_memcmp.c index 80839007cb..c51cf65d65 100644 --- a/src/klibc/utest/TC_rt_memcmp.c +++ b/src/klibc/utest/TC_rt_memcmp.c @@ -12,16 +12,6 @@ #include #include -static rt_err_t utest_tc_init(void) -{ - return RT_EOK; -} - -static rt_err_t utest_tc_cleanup(void) -{ - return RT_EOK; -} - static void TC_rt_memcmp_str(void) { const char* s = "abc 123"; @@ -32,20 +22,140 @@ static void TC_rt_memcmp_str(void) /* The following tests intentionally use a length > 3 */ /* To test what rt_memcmp does in such a situation */ - uassert_int_equal(!!(rt_memcmp(s, "abc", 6) > 0), 1); - uassert_int_equal(!!(rt_memcmp("abc", s, 6) < 0), 1); + uassert_int_greater(rt_memcmp(s, "abc", 6), 0); + uassert_int_less(rt_memcmp("abc", s, 6), 0); +} - /* Check RT_NULL input handling */ - uassert_int_not_equal(rt_memcmp("abc", RT_NULL, 3), 0); - uassert_int_not_equal(rt_memcmp(RT_NULL, "abc", 3), 0); +static void TC_rt_memcmp_int_array(void) +{ + int arr1[] = {1, 2, 3, 4, 5}; + int arr2[] = {1, 2, 3, 4, 5}; + int arr3[] = {1, 2, 3, 4, 6}; - /* Check that two RT_NULL strings will match */ - uassert_int_equal(rt_memcmp(RT_NULL, RT_NULL, 0), 0); + uassert_int_equal(rt_memcmp(arr1, arr2, sizeof(arr1)), 0); + uassert_int_less(rt_memcmp(arr1, arr3, sizeof(arr1)), 0); + uassert_int_greater(rt_memcmp(arr3, arr1, sizeof(arr1)), 0); +} + +static void TC_rt_memcmp_float_array(void) +{ + float arr1[] = {1.0f, 2.0f, 3.0f}; + float arr2[] = {1.0f, 2.0f, 3.0f}; + float arr3[] = {1.0f, 2.0f, 3.1f}; + + uassert_int_equal(rt_memcmp(arr1, arr2, sizeof(arr1)), 0); + uassert_int_less(rt_memcmp(arr1, arr3, sizeof(arr1)), 0); + uassert_int_greater(rt_memcmp(arr3, arr1, sizeof(arr1)), 0); +} + +typedef struct { + int id; + float value; +} Item; + +static void TC_rt_memcmp_struct_array(void) +{ + Item arr1[] = {{1, 1.0f}, {2, 2.0f}}; + Item arr2[] = {{1, 1.0f}, {2, 2.0f}}; + Item arr3[] = {{1, 1.0f}, {2, 2.1f}}; + + uassert_int_equal(rt_memcmp(arr1, arr2, sizeof(arr1)), 0); + uassert_int_less(rt_memcmp(arr1, arr3, sizeof(arr1)), 0); + uassert_int_greater(rt_memcmp(arr3, arr1, sizeof(arr1)), 0); +} + +typedef struct { + int id; + float value; + char name[10]; +} MixedItem; + +static void TC_rt_memcmp_mixed_array(void) +{ + MixedItem arr1[] = {{1, 1.0f, "item1"}, {2, 2.0f, "item2"}}; + MixedItem arr2[] = {{1, 1.0f, "item1"}, {2, 2.0f, "item2"}}; + MixedItem arr3[] = {{1, 1.0f, "item1"}, {2, 2.1f, "item2"}}; + + uassert_int_equal(rt_memcmp(arr1, arr2, sizeof(arr1)), 0); + uassert_int_less(rt_memcmp(arr1, arr3, sizeof(arr1)), 0); + uassert_int_greater(rt_memcmp(arr3, arr1, sizeof(arr1)), 0); +} + +typedef struct { + int id; + float score; +} Student; + +typedef struct { + Student students[3]; + char className[10]; +} Class; + +static void TC_rt_memcmp_nested_struct_array(void) +{ + Class class1 = { + .students = {{1, 90.5}, {2, 85.0}, {3, 92.0}}, + .className = "ClassA" + }; + + Class class2 = { + .students = {{1, 90.5}, {2, 85.0}, {3, 92.0}}, + .className = "ClassA" + }; + + Class class3 = { + .students = {{1, 90.5}, {2, 85.1}, {3, 92.0}}, + .className = "ClassA" + }; + + uassert_int_equal(rt_memcmp(&class1, &class2, sizeof(Class)), 0); + uassert_int_not_equal(rt_memcmp(&class1, &class3, sizeof(Class)), 0); +} + +static void TC_rt_memcmp_partial_match(void) +{ + char arr1[] = "abcdefghijklmnopqrstuvwxyz"; + char arr2[] = "abcdefghijklmxyznopqrstuvw"; + + uassert_int_equal(rt_memcmp(arr1, arr2, 13), 0); + uassert_int_not_equal(rt_memcmp(arr1, arr2, sizeof(arr1)), 0); +} + +#define LARGE_ARRAY_SIZE 1000 + +static void TC_rt_memcmp_large_array(void) +{ + int *arr1 = rt_calloc(LARGE_ARRAY_SIZE, sizeof(int)); + int *arr2 = rt_calloc(LARGE_ARRAY_SIZE, sizeof(int)); + + uassert_not_null(arr1); + uassert_not_null(arr2); + + for (int i = 0; i < LARGE_ARRAY_SIZE; i++) { + arr1[i] = i; + arr2[i] = i; + } + + uassert_int_equal(rt_memcmp(arr1, arr2, LARGE_ARRAY_SIZE * sizeof(int)), 0); + arr2[LARGE_ARRAY_SIZE - 1] = LARGE_ARRAY_SIZE; + + uassert_int_less(rt_memcmp(arr1, arr2, LARGE_ARRAY_SIZE * sizeof(int)), 0); + uassert_int_greater(rt_memcmp(arr2, arr1, LARGE_ARRAY_SIZE * sizeof(int)), 0); + + rt_free(arr1); + rt_free(arr2); } static void utest_do_tc(void) { UTEST_UNIT_RUN(TC_rt_memcmp_str); + UTEST_UNIT_RUN(TC_rt_memcmp_int_array); + UTEST_UNIT_RUN(TC_rt_memcmp_float_array); + UTEST_UNIT_RUN(TC_rt_memcmp_struct_array); + UTEST_UNIT_RUN(TC_rt_memcmp_mixed_array); + UTEST_UNIT_RUN(TC_rt_memcmp_nested_struct_array); + UTEST_UNIT_RUN(TC_rt_memcmp_partial_match); + UTEST_UNIT_RUN(TC_rt_memcmp_large_array); } -UTEST_TC_EXPORT(utest_do_tc, "klibc.rt_memcmp", utest_tc_init, utest_tc_cleanup, 1000); +UTEST_TC_EXPORT(utest_do_tc, "klibc.rt_memcmp", RT_NULL, RT_NULL, 1000); diff --git a/src/klibc/utest/TC_rt_memcpy.c b/src/klibc/utest/TC_rt_memcpy.c index f5cbdaa847..c02ccd5c96 100644 --- a/src/klibc/utest/TC_rt_memcpy.c +++ b/src/klibc/utest/TC_rt_memcpy.c @@ -9,32 +9,26 @@ * 2024-12-24 Meco Man port to utest */ -#include +#include #include +#define N 80 /**< Define the constant N for buffer size as 80 */ +#define TEST_BUF_SIZE 512 /**< Define the constant TEST_BUF_SIZE as 512 */ +static char *buf; /**< Define a static buffer of 512 bytes, initialized to 0 */ + static rt_err_t utest_tc_init(void) { + buf = rt_malloc(TEST_BUF_SIZE * sizeof(char)); /**< Allocate memory for the buffer */ + uassert_not_null(buf); return RT_EOK; } static rt_err_t utest_tc_cleanup(void) { + rt_free(buf); return RT_EOK; } -#define N 80 /**< Define the constant N for buffer size as 80 */ -static char buf[512] = {0}; /**< Define a static buffer of 512 bytes, initialized to 0 */ - -/** - * Align a given pointer to a 64-byte boundary. - * @param p The pointer to align. - * @return The aligned pointer. - */ -static void* aligned(void* p) -{ - return (void*)(((intptr_t)p + 63) & -64); -} - /** * Test memory copy with alignment. * @param dalign The alignment offset for the destination buffer. @@ -43,10 +37,10 @@ static void* aligned(void* p) */ static void test_align(unsigned dalign, unsigned salign, size_t len) { - char* src = aligned(buf); /**< Source buffer starting address, 64-byte aligned */ - char* dst = aligned(buf + 128); /**< Destination buffer starting address, 64-byte aligned from buf+128 */ - char* want = aligned(buf + 256); /**< Expected result buffer starting address, 64-byte aligned from buf+256 */ - char* p; /**< Pointer to receive the return value of rt_memcpy */ + char *src = (char *)RT_ALIGN((rt_ubase_t)buf, 64); /**< Source buffer starting address, 64-byte aligned */ + char *dst = (char *)RT_ALIGN(((rt_ubase_t)buf + 128), 64); /**< Destination buffer starting address, 64-byte aligned from buf+128 */ + char *want = (char *)RT_ALIGN(((rt_ubase_t)buf + 256), 64); /**< Expected result buffer starting address, 64-byte aligned from buf+256 */ + char *p; /**< Pointer to receive the return value of rt_memcpy */ unsigned i; /** Assert that the source alignment offset plus length does not exceed N */ diff --git a/src/klibc/utest/TC_rt_memmove.c b/src/klibc/utest/TC_rt_memmove.c new file mode 100644 index 0000000000..22f80214b2 --- /dev/null +++ b/src/klibc/utest/TC_rt_memmove.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2006-2024, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2024-12-25 Meco Man first version + */ + +#include +#include + +/* Basic move with no overlap */ +static void TC_rt_memmove_basic(void) +{ + char src[] = "Hello"; + char dest[10] = {0}; + rt_memmove(dest, src, rt_strlen(src) + 1); + uassert_str_equal(dest, "Hello"); +} + +/* Move with overlap (src before dest) */ +static void TC_rt_memmove_overlap_src_before(void) +{ + char buffer[] = "1234567890"; + rt_memmove(&buffer[3], buffer, 5); + uassert_str_equal(buffer, "1231234590"); +} + +/* Move with overlap (src after dest) */ +static void TC_rt_memmove_overlap_src_after(void) +{ + char buffer[] = "1234567890"; + rt_memmove(&buffer[2], &buffer[5], 5); + uassert_str_equal(buffer, "1267890890"); +} + +/* Move with zero length */ +static void TC_rt_memmove_zero_length(void) +{ + char src[] = "Hello"; + char dest[10] = "World"; + rt_memmove(dest, src, 0); + uassert_str_equal(dest, "World"); +} + +/* Move to the same location */ +static void TC_rt_memmove_same_location(void) +{ + char buffer[] = "Hello"; + rt_memmove(buffer, buffer, rt_strlen(buffer) + 1); + uassert_str_equal(buffer, "Hello"); +} + +/* Move from NULL */ +static void TC_rt_memmove_null_src(void) +{ + char dest[10]; + rt_memset(dest, 'A', sizeof(dest)); + rt_memmove(dest, RT_NULL, 0); /* Should not crash and do nothing */ + uassert_buf_equal(dest, "AAAAAAAAAA", 10); +} + +/* Move to NULL */ +static void TC_rt_memmove_null_dest(void) +{ + char src[] = "Hello"; + rt_memmove(RT_NULL, src, 0); /* Should not crash and do nothing */ +} + +/* Move more than source size */ +static void TC_rt_memmove_too_long(void) +{ + char src[] = "Short"; + char dest[10] = {0}; + rt_memmove(dest, src, sizeof(src) + 5); /* Should only copy up to src length */ + uassert_str_equal(dest, "Short"); + uassert_int_equal(dest[5], 0); /* Ensure no buffer overflow */ +} + +/* Move empty string */ +static void TC_rt_memmove_empty_string(void) +{ + char src[] = ""; + char dest[10] = "Unchanged"; + rt_memmove(dest, src, rt_strlen(src) + 1); + + /* Expect dest to only contain '\0' at the start */ + uassert_str_equal(dest, ""); /* Destination should now be an empty string */ + uassert_int_equal(dest[0], '\0'); /* First character should be '\0' */ +} + +/* Utest function to run all test cases */ +static void utest_do_tc(void) +{ + UTEST_UNIT_RUN(TC_rt_memmove_basic); + UTEST_UNIT_RUN(TC_rt_memmove_overlap_src_before); + UTEST_UNIT_RUN(TC_rt_memmove_overlap_src_after); + UTEST_UNIT_RUN(TC_rt_memmove_zero_length); + UTEST_UNIT_RUN(TC_rt_memmove_same_location); + UTEST_UNIT_RUN(TC_rt_memmove_null_src); + UTEST_UNIT_RUN(TC_rt_memmove_null_dest); + UTEST_UNIT_RUN(TC_rt_memmove_too_long); + UTEST_UNIT_RUN(TC_rt_memmove_empty_string); +} + +UTEST_TC_EXPORT(utest_do_tc, "klibc.rt_memmove", RT_NULL, RT_NULL, 1000); diff --git a/src/klibc/utest/TC_rt_memset.c b/src/klibc/utest/TC_rt_memset.c new file mode 100644 index 0000000000..afe705df4b --- /dev/null +++ b/src/klibc/utest/TC_rt_memset.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2006-2024, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-05-06 Phillip Johnston the first version + * 2024-12-24 Meco Man port to utest + */ + +#include +#include + +#define TEST_BUF_SIZE 400 + +static char *buf; +static char *buf2; + +static rt_err_t utest_tc_init(void) +{ + buf = rt_malloc(TEST_BUF_SIZE * sizeof(char)); + uassert_not_null(buf); + buf2 = rt_malloc(TEST_BUF_SIZE * sizeof(char)); + uassert_not_null(buf2); + return RT_EOK; +} + +static rt_err_t utest_tc_cleanup(void) +{ + rt_free(buf); + rt_free(buf2); + return RT_EOK; +} + +static void test_align(int align, size_t len) +{ + char *s = (char *)RT_ALIGN(((rt_ubase_t)buf + 64), 64) + align; + char *want = (char *)RT_ALIGN(((rt_ubase_t)buf2 + 64), 64) + align; + char *p; + int i; + + uassert_false(len + 64 > (size_t)(buf + TEST_BUF_SIZE - s)); + uassert_false(len + 64 > (size_t)(buf2 + TEST_BUF_SIZE - want)); + + for(i = 0; i < TEST_BUF_SIZE; i++) + { + buf[i] = buf2[i] = ' '; + } + + for(i = 0; i < (int)len; i++) + { + want[i] = '#'; + } + + p = rt_memset(s, '#', len); + + uassert_ptr_equal(p, s); + + for(i = -64; i < (int)len + 64; i++) + { + uassert_int_equal(s[i], want[i]); + } +} + +static void TC_rt_memcpy_align(void) +{ + for(int i = 0; i < 16; i++) + { + for(size_t j = 0; j < 200; j++) + { + test_align(i, j); + } + } +} + +static void test_input(char c) +{ + rt_memset(buf, c, 10); + for(int i = 0; i < 10; i++) + { + uassert_int_equal(buf[i], c); + } +} + +static void TC_rt_memcpy_input(void) +{ + test_input('c'); + test_input(0); + test_input(-1); + test_input(0xab); + test_input((char)RT_UINT32_MAX); + test_input((char)-RT_UINT32_MAX); +} + +static void utest_do_tc(void) +{ + UTEST_UNIT_RUN(TC_rt_memcpy_align); + UTEST_UNIT_RUN(TC_rt_memcpy_input); +} + +UTEST_TC_EXPORT(utest_do_tc, "klibc.rt_memset", utest_tc_init, utest_tc_cleanup, 1000); diff --git a/src/klibc/utest/TC_rt_sprintf.c b/src/klibc/utest/TC_rt_sprintf.c index 86faf3ad1f..709155c8df 100644 --- a/src/klibc/utest/TC_rt_sprintf.c +++ b/src/klibc/utest/TC_rt_sprintf.c @@ -70,16 +70,6 @@ do { \ #define SPRINTF_TEST_CASE_NAME(testname) TC_##testname #define SPRINTF_TEST_CASE(testname) static void SPRINTF_TEST_CASE_NAME(testname)(void) -static rt_err_t utest_tc_init(void) -{ - return RT_EOK; -} - -static rt_err_t utest_tc_cleanup(void) -{ - return RT_EOK; -} - SPRINTF_TEST_CASE(space_flag) { char buffer[base_buffer_size]; @@ -1072,4 +1062,4 @@ static void utest_do_tc(void) UTEST_UNIT_RUN(SPRINTF_TEST_CASE_NAME(misc)); } -UTEST_TC_EXPORT(utest_do_tc, "klibc.rt_sprintf", utest_tc_init, utest_tc_cleanup, 1000); +UTEST_TC_EXPORT(utest_do_tc, "klibc.rt_sprintf", RT_NULL, RT_NULL, 1000);