/* * Copyright (c) 2017 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ /* * @file test access to the minimal C libraries * * This module verifies that the various minimal C libraries can be used. * * IMPORTANT: The module only ensures that each supported library is present, * and that a bare minimum of its functionality is operating correctly. It does * NOT guarantee that ALL standards-defined functionality is present, nor does * it guarantee that ALL functionality provided is working correctly. */ #undef _POSIX_C_SOURCE #define _POSIX_C_SOURCE 200809L #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef CONFIG_PICOLIBC #include #endif #ifdef CONFIG_NEWLIB_LIBC #include #endif #define STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE) #define LIST_LEN 2 /* Recent GCC's are issuing a warning for the truncated strncpy() * below (the static source string is longer than the locally-defined * destination array). That's exactly the case we're testing, so turn * it off. */ #if defined(__GNUC__) && __GNUC__ >= 8 #pragma GCC diagnostic ignored "-Wstringop-truncation" #endif ZTEST_SUITE(libc_common, NULL, NULL, NULL, NULL, NULL); /* * variables used during limits library testing; must be marked as "volatile" * to prevent compiler from computing results at compile time */ volatile long long_max = LONG_MAX; volatile long long_one = 1L; /** * * @brief Test implementation-defined constants library * @defgroup libc_api * @ingroup all_tests * @{ * */ ZTEST(libc_common, test_limits) { zassert_true((long_max + long_one == LONG_MIN)); } static ssize_t foobar(void) { return -1; } ZTEST(libc_common, test_ssize_t) { zassert_true(foobar() < 0); } /** * * @brief Test boolean types and values library * */ ZTEST(libc_common, test_stdbool) { zassert_true((true == 1), "true value"); zassert_true((false == 0), "false value"); } /* * variables used during stddef library testing; must be marked as "volatile" * to prevent compiler from computing results at compile time */ volatile long long_variable; volatile size_t size_of_long_variable = sizeof(long_variable); /** * * @brief Test standard type definitions library * */ ZTEST(libc_common, test_stddef) { #ifdef CONFIG_64BIT zassert_true((size_of_long_variable == 8), "sizeof"); #else zassert_true((size_of_long_variable == 4), "sizeof"); #endif } /* * variables used during stdint library testing; must be marked as "volatile" * to prevent compiler from computing results at compile time */ volatile uint8_t unsigned_byte = 0xff; volatile uint32_t unsigned_int = 0xffffff00; /** * * @brief Test integer types library * */ ZTEST(libc_common, test_stdint) { zassert_true((unsigned_int + unsigned_byte + 1u == 0U)); #if (UINT8_C(1) == 1) \ && (INT8_C(-1) == -1) \ && (UINT16_C(2) == 2) \ && (INT16_C(-2) == -2) \ && (UINT32_C(4) == 4) \ && (INT32_C(-4) == -4) \ && (UINT64_C(8) == 8) \ && (INT64_C(-8) == -8) \ && (UINTMAX_C(11) == 11) \ && (INTMAX_C(-11) == -11) zassert_true(true); #else zassert_true(false, "const int expr values ..."); #endif } /** * * @brief Test time_t to make sure it is at least 64 bits * */ ZTEST(libc_common, test_time_t) { #ifdef CONFIG_EXTERNAL_LIBC ztest_test_skip(); #else zassert_true(sizeof(time_t) >= sizeof(uint64_t)); #endif } /* * variables used during string library testing */ #define BUFSIZE 10 char buffer[BUFSIZE]; /** * * @brief Test string memset * */ ZTEST(libc_common, test_memset) { int i, ret; const char set = 'a'; int size = 0; memset(buffer, 0, 10); for (i = 0; i < 10; i++) { memset(buffer + i, set, size); memset(buffer + i, set, 1); ret = memcmp(buffer + i, &set, 1); zassert_true((ret == 0), "memset buffer a failed"); } } /** * * @brief Test string length function * * @see strlen(), strnlen(). * */ ZTEST(libc_common, test_strlen) { (void)memset(buffer, '\0', BUFSIZE); (void)memset(buffer, 'b', 5); /* 5 is BUFSIZE / 2 */ zassert_equal(strlen(buffer), 5, "strlen failed"); zassert_equal(strnlen(buffer, 3), 3, "strnlen failed"); zassert_equal(strnlen(buffer, BUFSIZE), 5, "strnlen failed"); } /** * * @brief Test string compare function * * @see strcmp(), strncasecmp(). * */ ZTEST(libc_common, test_strcmp) { strcpy(buffer, "eeeee"); char test = 0; zassert_true((strcmp(buffer, "fffff") < 0), "strcmp less ..."); zassert_str_equal(buffer, "eeeee", "strcmp equal ..."); zassert_true((strcmp(buffer, "ddddd") > 0), "strcmp greater ..."); zassert_true((strncasecmp(buffer, "FFFFF", 3) < 0), "strncasecmp less ..."); zassert_true((strncasecmp(buffer, "DDDDD", 3) > 0), "strncasecmp equal ..."); zassert_true((strncasecmp(buffer, "EEEEE", 3) == 0), "strncasecmp greater ..."); zassert_true((strncasecmp(&test, &test, 1) == 0), "strncasecmp failed"); } /** * * @brief Test string N compare function * * @see strncmp(). */ ZTEST(libc_common, test_strncmp) { static const char pattern[] = "eeeeeeeeeeee"; /* Note we don't want to count the final \0 that sizeof will */ __ASSERT_NO_MSG(sizeof(pattern) - 1 > BUFSIZE); memcpy(buffer, pattern, BUFSIZE); zassert_true((strncmp(buffer, "fffff", 0) == 0), "strncmp 0"); zassert_true((strncmp(buffer, "eeeff", 3) == 0), "strncmp 3"); zassert_true((strncmp(buffer, "eeeff", 4) != 0), "strncmp 4"); zassert_true((strncmp(buffer, "eeeeeeeeeeeff", BUFSIZE) == 0), "strncmp 10"); /* test compare the same strings */ buffer[BUFSIZE - 1] = '\0'; zassert_true((strncmp(buffer, buffer, BUFSIZE) == 0), "strncmp 10 with \0"); } /** * * @brief Test string copy function * * @see strcpy(). */ ZTEST(libc_common, test_strcpy) { (void)memset(buffer, '\0', BUFSIZE); strcpy(buffer, "10 chars!\0"); zassert_str_equal(buffer, "10 chars!\0", "strcpy"); } /** * * @brief Test string N copy function * * @see strncpy(). */ ZTEST(libc_common, test_strncpy) { int ret; (void)memset(buffer, '\0', BUFSIZE); strncpy(buffer, "This is over 10 characters", BUFSIZE); /* Purposely different values */ ret = strncmp(buffer, "This is over 20 characters", BUFSIZE); zassert_true((ret == 0), "strncpy"); } /** * * @brief Test string scanning function * * @see strchr(). */ ZTEST(libc_common, test_strchr) { char *rs = NULL; int ret; (void)memset(buffer, '\0', BUFSIZE); strncpy(buffer, "Copy 10", BUFSIZE); rs = strchr(buffer, '1'); zassert_not_null(rs, "strchr"); ret = strncmp(rs, "10", 2); zassert_true((ret == 0), "strchr"); } /** * * @brief Test string prefix match functions * * @see strspn(),strcspn(). */ ZTEST(libc_common, test_strxspn) { const char *empty = ""; const char *cset = "abc"; zassert_true(strspn("", empty) == 0U, "strspn empty empty"); zassert_true(strcspn("", empty) == 0U, "strcspn empty empty"); zassert_true(strspn("abde", cset) == 2U, "strspn match"); zassert_true(strcspn("abde", cset) == 0U, "strcspn nomatch"); zassert_true(strspn("da", cset) == 0U, "strspn nomatch"); zassert_true(strcspn("da", cset) == 1U, "strcspn match"); zassert_true(strspn("abac", cset) == 4U, "strspn all"); zassert_true(strcspn("defg", cset) == 4U, "strcspn all"); } /** * * @brief Test memory comparison function * * @see memcmp() */ ZTEST(libc_common, test_memcmp) { int ret; unsigned char m1[] = "a\0$def"; unsigned char m2[] = "a\0$dhj"; ret = memcmp(m1, m2, 4); zassert_true((ret == 0), "memcmp four characters failed"); ret = memcmp(m1, m2, 5); zassert_true((ret != 0), "memcmp five characters failed"); ret = memcmp(m1, m2, 0); zassert_true((ret == 0), "memcmp zero character failed"); ret = memcmp(m1, m2, sizeof(m2)); zassert_true((ret != 0), "memcmp 2 block of memory failed"); } /** * * @brief Test binary search function * * @see bsearch() */ int cmp_func(const void *a, const void *b) { return (*(int *)a - *(int *)b); } ZTEST(libc_common, test_bsearch) { void *result = NULL; int arr[5] = { 2, 5, 20, 50, 60 }; size_t size = ARRAY_SIZE(arr); int key = 30; result = (int *)bsearch(&key, arr, size, sizeof(int), cmp_func); zassert_is_null(result, "bsearch -key not found"); key = 60; result = (int *)bsearch(&key, arr, size, sizeof(int), cmp_func); zassert_not_null(result, "bsearch -key found"); } /** * * @brief Test abs function * * @see abs() */ ZTEST(libc_common, test_abs) { int val = -5, value = 5; zassert_equal(abs(val), 5, "abs -5"); zassert_equal(abs(value), 5, "abs 5"); } /** * * @brief Test atoi function * * @see atoi() */ ZTEST(libc_common, test_atoi) { zassert_equal(atoi("123"), 123, "atoi error"); zassert_equal(atoi("2c5"), 2, "atoi error"); zassert_equal(atoi("acd"), 0, "atoi error"); zassert_equal(atoi(" "), 0, "atoi error"); zassert_equal(atoi(""), 0, "atoi error"); zassert_equal(atoi("3-4e"), 3, "atoi error"); zassert_equal(atoi("8+1c"), 8, "atoi error"); zassert_equal(atoi("+3"), 3, "atoi error"); zassert_equal(atoi("-1"), -1, "atoi error"); } /** * * @brief Test value type * * @details This function check the char type, * and verify the return value. * * @see isalnum(), isalpha(), isdigit(), isgraph(), * isprint(), isspace(), isupper(), isxdigit(). * */ ZTEST(libc_common, test_checktype) { static const char exp_alnum[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; static const char exp_alpha[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; static const char exp_digit[] = "0123456789"; static const char exp_graph[] = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"; static const char exp_print[] = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"; static const char exp_space[] = {"\x9\xa\xb\xc\xd\x20"}; static const char exp_upper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; static const char exp_xdigit[] = "0123456789ABCDEFabcdef"; char buf[128]; char *ptr = buf; for (int i = 0; i < 128; i++) { if (isalnum(i) != 0) { *ptr++ = i; } } *ptr = '\0'; zassert_str_equal(buf, exp_alnum, "isalnum error"); ptr = buf; for (int i = 0; i < 128; i++) { if (isalpha(i) != 0) { *ptr++ = i; } } *ptr = '\0'; zassert_str_equal(buf, exp_alpha, "isalpha error"); ptr = buf; for (int i = 0; i < 128; i++) { if (isdigit(i) != 0) { *ptr++ = i; } } *ptr = '\0'; zassert_str_equal(buf, exp_digit, "isdigit error"); ptr = buf; for (int i = 0; i < 128; i++) { if (isgraph(i) != 0) { *ptr++ = i; } } *ptr = '\0'; zassert_str_equal(buf, exp_graph, "isgraph error"); ptr = buf; for (int i = 0; i < 128; i++) { if (isprint(i) != 0) { *ptr++ = i; } } *ptr = '\0'; zassert_str_equal(buf, exp_print, "isprint error"); ptr = buf; for (int i = 0; i < 128; i++) { if (isupper(i) != 0) { *ptr++ = i; } } *ptr = '\0'; zassert_str_equal(buf, exp_upper, "isupper error"); ptr = buf; for (int i = 0; i < 128; i++) { if (isspace(i) != 0) { *ptr++ = i; } } *ptr = '\0'; zassert_str_equal(buf, exp_space, "isspace error"); ptr = buf; for (int i = 0; i < 128; i++) { if (isxdigit(i) != 0) { *ptr++ = i; } } *ptr = '\0'; zassert_str_equal(buf, exp_xdigit, "isxdigit error"); } /** * @brief Test memchr function * * @see memchr(). */ ZTEST(libc_common, test_memchr) { static const char str[] = "testfunction"; /* verify the character inside the count scope */ zassert_not_null(memchr(str, 'e', strlen(str)), "memchr serach e"); zassert_not_null(memchr(str, '\0', strlen(str)+1), "memchr serach \0"); /* verify when the count parm is zero */ zassert_is_null(memchr(str, 't', 0), "memchr count 0 error"); /* verify the wanted character outside the count scope */ zassert_is_null(memchr(str, '\0', strlen(str)), "memchr scope error"); } /** * @brief Test memcpy operation * * @see memcpy(). */ ZTEST(libc_common, test_memcpy) { /* make sure the buffer is word aligned */ uintptr_t mem_dest[4] = {0}; uintptr_t mem_src[4] = {0}; unsigned char *mem_dest_tmp = NULL; unsigned char *mem_src_tmp = NULL; unsigned char *mem_dest_byte = (unsigned char *)mem_dest; unsigned char *mem_src_byte = (unsigned char *)mem_src; /* initialize source buffer in bytes */ for (int i = 0; i < sizeof(mem_src); i++) { mem_src_byte[i] = i; } /* verify when dest in not word aligned */ mem_dest_tmp = mem_dest_byte + 1; mem_src_tmp = mem_src_byte; zassert_equal(memcpy(mem_dest_tmp, mem_src_tmp, 10), mem_dest_tmp, "memcpy error"); zassert_equal(memcmp(mem_dest_tmp, mem_src_tmp, 10), 0, "memcpy failed"); /* restore the environment */ memset(mem_dest_byte, '\0', sizeof(mem_dest)); /* verify when dest and src are all in not word aligned */ mem_dest_tmp = mem_dest_byte + sizeof(uintptr_t) - 1; mem_src_tmp = mem_src_byte + sizeof(uintptr_t) - 1; zassert_equal(memcpy(mem_dest_tmp, mem_src_tmp, 10), mem_dest_tmp, "memcpy error"); zassert_equal(memcmp(mem_dest_tmp, mem_src_tmp, 10), 0, "memcpy failed"); /* restore the environment */ memset(mem_dest_byte, '\0', sizeof(mem_dest)); /* verify when the copy count is zero, the copy will directly return */ mem_dest_tmp = mem_dest_byte + sizeof(uintptr_t) - 1; mem_src_tmp = mem_src_byte + sizeof(uintptr_t) - 1; zassert_equal(memcpy(mem_dest_tmp, mem_src_tmp, 0), mem_dest_tmp, "memcpy error"); zassert_not_equal(memcmp(mem_dest_tmp, mem_src_tmp, 10), 0, "memcpy failed"); } /** * @brief Test memmove operation * * @see memmove(). */ ZTEST(libc_common, test_memmove) { char move_buffer[6] = "12123"; char move_new[6] = {0}; static const char move_overlap[6] = "12121"; /* verify buffer overlaps with the start of the buffer */ zassert_equal(memmove(move_buffer + 2, move_buffer, 3), move_buffer + 2, "memmove error"); zassert_equal(memcmp(move_overlap, move_buffer, sizeof(move_buffer)), 0, "memmove failed"); /* verify the buffer is not overlap, then forward-copy */ zassert_equal(memmove(move_new, move_buffer, sizeof(move_buffer)), move_new, "memmove error"); zassert_equal(memcmp(move_new, move_buffer, sizeof(move_buffer)), 0, "memmove failed"); } /** * * @brief test str operate functions * * @see strcat(), strcspn(), strncat(). * */ ZTEST(libc_common, test_str_operate) { char str1[10] = "aabbcc", ncat[10] = "ddee"; char *str2 = "b"; char *str3 = "d"; int ret; char *ptr; zassert_not_null(strcat(str1, str3), "strcat false"); zassert_str_equal(str1, "aabbccd", "test strcat failed"); ret = strcspn(str1, str2); zassert_equal(ret, 2, "strcspn failed"); ret = strcspn(str1, str3); zassert_equal(ret, 6, "strcspn not found str"); zassert_true(strncat(ncat, str1, 2), "strncat failed"); zassert_not_null(strncat(str1, str3, 2), "strncat failed"); #if defined(__GNUC__) && __GNUC__ >= 7 #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wstringop-overflow" #endif zassert_not_null(strncat(str1, str3, 1), "strncat failed"); #if defined(__GNUC__) && __GNUC__ >= 7 #pragma GCC diagnostic pop #endif zassert_str_equal(ncat, "ddeeaa", "strncat failed"); zassert_is_null(strrchr(ncat, 'z'), "strrchr not found this word. failed"); ptr = strrchr(ncat, 'e'); zassert_str_equal(ptr, "eaa", "strrchr failed"); zassert_is_null(strstr(str1, "ayz"), "strstr aabbccd with ayz failed"); zassert_not_null(strstr(str1, str2), "strstr aabbccd with b succeed"); zassert_not_null(strstr(str1, "bb"), "strstr aabbccd with bb succeed"); zassert_not_null(strstr(str1, ""), "strstr aabbccd with \0 failed"); } /** * * @brief test strtol function * * @detail in 32bit system: * when base is 10, [-2147483648..2147483647] * in 64bit system: * when base is 10, * [-9,223,372,036,854,775,808..9,223,372,036,854,775,807] * * @see strtol(). * */ ZTEST(libc_common, test_strtol) { static const char buf1[] = "+10379aegi"; static const char buf2[] = " -10379aegi"; static const char buf3[] = "-010379aegi"; static const char buf4[] = "0x10379aegi"; static const char buf5[] = "0X10379aegi"; static const char buf6[] = "01037aegi"; static const char buf7[] = "1037aegi"; static const char buf8[] = "++1037aegi"; static const char buf9[] = "A1037aegi"; static const char buf10[] = "a1037aegi"; static const char str_normal[] = "-1011 This stopped it"; static const char str_abnormal[] = "ABCDEFGH"; char *stop = NULL; long ret; /* test function strtol() */ ret = strtol(buf3, NULL, 8); zassert_equal(ret, -543, "strtol base = 8 failed"); ret = strtol(buf1, NULL, 10); zassert_equal(ret, 10379, "strtol base = 10 failed"); ret = strtol(buf2, NULL, 10); zassert_equal(ret, -10379, "strtol base = 10 failed"); ret = strtol(buf4, NULL, 16); zassert_equal(ret, 17004974, "strtol base = 16 failed"); ret = strtol(buf4, NULL, 0); zassert_equal(ret, 17004974, "strtol base = 16 failed"); ret = strtol(buf5, NULL, 0); zassert_equal(ret, 17004974, "strtol base = 16 failed"); ret = strtol(buf6, NULL, 0); zassert_equal(ret, 543, "strtol base = 8 failed"); ret = strtol(buf7, NULL, 0); zassert_equal(ret, 1037, "strtol base = 10 failed"); ret = strtol(buf8, NULL, 10); zassert_not_equal(ret, 1037, "strtol base = 10 failed"); ret = strtol(buf9, NULL, 10); zassert_not_equal(ret, 1037, "strtol base = 10 failed"); ret = strtol(buf10, NULL, 10); zassert_not_equal(ret, 1037, "strtol base = 10 failed"); ret = strtol(str_normal, &stop, 10); zassert_equal(ret, -1011, "strtol base = 10 failed"); zassert_str_equal(stop, " This stopped it", "strtol get stop failed"); ret = strtol(str_abnormal, &stop, 0); zassert_equal(ret, 0, "strtol base = 0 failed"); zassert_str_equal(stop, "ABCDEFGH", "strtol get stop failed"); #if LONG_MAX > 2147483647 char border1[] = "-9223372036854775809"; char border2[] = "+9223372036854775808"; char border3[] = "+9223372036854775806"; char border4[] = "922337203685477580000000"; ret = strtol(border1, NULL, 10); zassert_equal(ret, LONG_MIN, "strtol base = 10 failed"); ret = strtol(border2, NULL, 10); zassert_equal(ret, LONG_MAX, "strtol base = 10 failed"); ret = strtol(border3, NULL, 10); zassert_equal(ret, 9223372036854775806, "strtol base = 10 failed"); ret = strtol(border4, NULL, 10); zassert_equal(ret, LONG_MAX, "strtol base = 10 failed"); #else char border1[] = "-2147483649"; char border2[] = "+2147483648"; char border3[] = "+2147483646"; char border4[] = "214748364000000"; ret = strtol(border1, NULL, 10); zassert_equal(ret, LONG_MIN, "strtol base = 10 failed"); ret = strtol(border2, NULL, 10); zassert_equal(ret, LONG_MAX, "strtol base = 10 failed"); ret = strtol(border3, NULL, 10); zassert_equal(ret, 2147483646, "strtol base = 10 failed"); ret = strtol(border4, NULL, 10); zassert_equal(ret, LONG_MAX, "strtol base = 10 failed"); #endif } /** * * @brief test strtoul function * * @see strtoul(). * */ ZTEST(libc_common, test_strtoul) { static const char buf1[] = "+10379aegi"; static const char buf2[] = " -10379aegi"; static const char buf3[] = "-010379aegi"; static const char buf4[] = "0x10379aegi"; static const char buf5[] = "0X10379aegi"; static const char buf6[] = "01037aegi"; static const char buf7[] = "1037aegi"; static const char buf8[] = "++1037aegi"; static const char buf9[] = "A1037aegi"; static const char buf10[] = "a1037aegi"; static const char str_normal[] = "-1011 This stopped it"; static const char str_abnormal[] = "ABCDEFGH"; char *stop = NULL; long ret; /* test function strtol() */ ret = strtoul(buf3, NULL, 8); zassert_equal(ret, -543, "strtol base = 8 failed"); ret = strtoul(buf1, NULL, 10); zassert_equal(ret, 10379, "strtol base = 10 failed"); ret = strtoul(buf2, NULL, 10); zassert_equal(ret, -10379, "strtol base = 10 failed"); ret = strtoul(buf4, NULL, 16); zassert_equal(ret, 17004974, "strtol base = 16 failed"); ret = strtoul(buf4, NULL, 0); zassert_equal(ret, 17004974, "strtol base = 16 failed"); ret = strtoul(buf5, NULL, 0); zassert_equal(ret, 17004974, "strtol base = 16 failed"); ret = strtoul(buf6, NULL, 0); zassert_equal(ret, 543, "strtol base = 8 failed"); ret = strtoul(buf7, NULL, 0); zassert_equal(ret, 1037, "strtol base = 10 failed"); ret = strtoul(buf8, NULL, 10); zassert_not_equal(ret, 1037, "strtol base = 10 failed"); ret = strtoul(buf9, NULL, 10); zassert_not_equal(ret, 1037, "strtol base = 10 failed"); ret = strtoul(buf10, NULL, 10); zassert_not_equal(ret, 1037, "strtol base = 10 failed"); ret = strtoul(str_normal, &stop, 10); zassert_equal(ret, -1011, "strtol base = 10 failed"); zassert_str_equal(stop, " This stopped it", "strtol get stop failed"); ret = strtoul(str_abnormal, &stop, 0); zassert_equal(ret, 0, "strtol base = 0 failed"); zassert_str_equal(stop, "ABCDEFGH", "strtol get stop failed"); #if LONG_MAX > 2147483647 char border1[] = "18446744073709551615"; char border2[] = "-18446744073709551615000"; char border3[] = "18446744073709551619"; ret = strtoul(border1, NULL, 10); zassert_equal(ret, ULONG_MAX, "strtol base = 10 failed"); ret = strtoul(border2, NULL, 10); zassert_equal(ret, ULONG_MAX, "strtol base = 10 failed"); ret = strtoul(border3, NULL, 10); zassert_equal(ret, ULONG_MAX, "strtol base = 10 failed"); #else char border1[] = "+4294967295"; char border2[] = "-4294967295000"; char border3[] = "+4294967299"; ret = strtoul(border1, NULL, 10); zassert_equal(ret, ULONG_MAX, "strtol base = 10 failed"); ret = strtoul(border2, NULL, 10); zassert_equal(ret, ULONG_MAX, "strtol base = 10 failed"); ret = strtoul(border3, NULL, 10); zassert_equal(ret, ULONG_MAX, "strtol base = 10 failed"); #endif } /** * * @brief test strtoll function * * @see strtoll(). * */ void test_strtoll(void) { static const char buf1[] = "+10379aegi"; static const char buf2[] = " -10379aegi"; static const char buf3[] = "-010379aegi"; static const char buf4[] = "0x10379aegi"; static const char buf5[] = "0X10379aegi"; static const char buf6[] = "01037aegi"; static const char buf7[] = "1037aegi"; static const char buf8[] = "++1037aegi"; static const char buf9[] = "A1037aegi"; static const char buf10[] = "a1037aegi"; static const char str_normal[] = "-1011 This stopped it"; static const char str_abnormal[] = "ABCDEFGH"; char *stop = NULL; long long ret; /* test function strtoll() */ ret = strtoll(buf3, NULL, 8); zassert_equal(ret, -543, "strtoll base = 8 failed"); ret = strtoll(buf1, NULL, 10); zassert_equal(ret, 10379, "strtoll base = 10 failed"); ret = strtoll(buf2, NULL, 10); zassert_equal(ret, -10379, "strtoll base = 10 failed"); ret = strtoll(buf4, NULL, 16); zassert_equal(ret, 17004974, "strtoll base = 16 failed"); ret = strtoll(buf4, NULL, 0); zassert_equal(ret, 17004974, "strtoll base = 16 failed"); ret = strtoll(buf5, NULL, 0); zassert_equal(ret, 17004974, "strtoll base = 16 failed"); ret = strtoll(buf6, NULL, 0); zassert_equal(ret, 543, "strtoll base = 8 failed"); ret = strtoll(buf7, NULL, 0); zassert_equal(ret, 1037, "strtoll base = 10 failed"); ret = strtoll(buf8, NULL, 10); zassert_not_equal(ret, 1037, "strtoll base = 10 failed"); ret = strtoll(buf9, NULL, 10); zassert_not_equal(ret, 1037, "strtoll base = 10 failed"); ret = strtoll(buf10, NULL, 10); zassert_not_equal(ret, 1037, "strtoll base = 10 failed"); ret = strtoll(str_normal, &stop, 10); zassert_equal(ret, -1011, "strtoll base = 10 failed"); zassert_str_equal(stop, " This stopped it", "strtoll get stop failed"); ret = strtoll(str_abnormal, &stop, 0); zassert_equal(ret, 0, "strtoll base = 0 failed"); zassert_str_equal(stop, "ABCDEFGH", "strtoll get stop failed"); char border1[] = "-9223372036854775808"; char border2[] = "+9223372036854775807"; char border3[] = "+9223372036854775806"; char border4[] = "922337203685477580000000"; char border5[] = "0x0000000000000000000000000000000000001"; char border6[] = "10000000000000000000000000000000000001"; char border7[] = "-10000000000000000000000000000000000001"; ret = strtoll(border1, NULL, 10); zassert_equal(ret, LLONG_MIN, "strtoll base = 10 failed"); ret = strtoll(border2, NULL, 10); zassert_equal(ret, LLONG_MAX, "strtoll base = 10 failed"); ret = strtoll(border3, NULL, 10); zassert_equal(ret, 9223372036854775806, "strtoll base = 10 failed"); ret = strtoll(border4, NULL, 10); zassert_equal(ret, LLONG_MAX, "strtoll base = 10 failed"); ret = strtoull(border5, NULL, 16); zassert_equal(ret, 1, "strtoull base = 16 failed, %s != 0x%x", border5, ret); ret = strtoull(border6, NULL, 10); zassert_equal(errno, ERANGE, "strtoull base = 10 failed, %s != %lld", border6, ret); ret = strtoull(border7, NULL, 10); zassert_equal(errno, ERANGE, "strtoull base = 10 failed, %s != %lld", border7, ret); } /** * * @brief test strtoull function * * @see strtoull(). * */ void test_strtoull(void) { static const char buf1[] = "+10379aegi"; static const char buf2[] = " -10379aegi"; static const char buf3[] = "-010379aegi"; static const char buf4[] = "0x10379aegi"; static const char buf5[] = "0X10379aegi"; static const char buf6[] = "01037aegi"; static const char buf7[] = "1037aegi"; static const char buf8[] = "++1037aegi"; static const char buf9[] = "A1037aegi"; static const char buf10[] = "a1037aegi"; static const char str_normal[] = "-1011 This stopped it"; static const char str_abnormal[] = "ABCDEFGH"; char *stop = NULL; unsigned long long ret; /* test function strtoull() */ ret = strtoull(buf3, NULL, 8); zassert_equal(ret, -543, "strtoull base = 8 failed"); ret = strtoull(buf1, NULL, 10); zassert_equal(ret, 10379, "strtoull base = 10 failed"); ret = strtoull(buf2, NULL, 10); zassert_equal(ret, -10379, "strtoull base = 10 failed"); ret = strtoull(buf4, NULL, 16); zassert_equal(ret, 17004974, "strtoull base = 16 failed"); ret = strtoull(buf4, NULL, 0); zassert_equal(ret, 17004974, "strtoull base = 16 failed"); ret = strtoull(buf5, NULL, 0); zassert_equal(ret, 17004974, "strtoull base = 16 failed"); ret = strtoull(buf6, NULL, 0); zassert_equal(ret, 543, "strtoull base = 8 failed"); ret = strtoull(buf7, NULL, 0); zassert_equal(ret, 1037, "strtoull base = 10 failed"); ret = strtoull(buf8, NULL, 10); zassert_not_equal(ret, 1037, "strtoull base = 10 failed"); ret = strtoull(buf9, NULL, 10); zassert_not_equal(ret, 1037, "strtoull base = 10 failed"); ret = strtoull(buf10, NULL, 10); zassert_not_equal(ret, 1037, "strtoull base = 10 failed"); ret = strtoull(str_normal, &stop, 10); zassert_equal(ret, -1011, "strtoull base = 10 failed"); zassert_str_equal(stop, " This stopped it", "strtoull get stop failed"); ret = strtoull(str_abnormal, &stop, 0); zassert_equal(ret, 0, "strtoull base = 0 failed"); zassert_str_equal(stop, "ABCDEFGH", "strtoull get stop failed"); char border1[] = "+18446744073709551615"; char border2[] = "-18446744073709551615000"; char border3[] = "+18446744073709551619"; char border4[] = "0x0000000000000000000000000000000000001"; char border5[] = "10000000000000000000000000000000000001"; char border6[] = "-10000000000000000000000000000000000001"; ret = strtoull(border1, NULL, 10); zassert_equal(ret, ULLONG_MAX, "strtoull base = 10 failed"); ret = strtoull(border2, NULL, 10); zassert_equal(ret, ULLONG_MAX, "strtoull base = 10 failed"); ret = strtoull(border3, NULL, 10); zassert_equal(ret, ULLONG_MAX, "strtoull base = 10 failed"); ret = strtoull(border4, NULL, 16); zassert_equal(ret, 1, "strtoull base = 16 failed, %s != 0x%x", border4, ret); ret = strtoull(border5, NULL, 10); zassert_equal(errno, ERANGE, "strtoull base = 10 failed, %s != %lld", border5, ret); ret = strtoull(border6, NULL, 10); zassert_equal(errno, ERANGE, "strtoull base = 10 failed, %s != %lld", border6, ret); } /** * * @brief test convert function * */ ZTEST(libc_common, test_tolower_toupper) { static const char test[] = "Az09Za{#!"; static const char toup[] = "AZ09ZA{#!"; static const char tolw[] = "az09za{#!"; char up[11]; char lw[11]; int i = 0; for (; i < strlen(test); i++) { up[i] = toupper(test[i]); lw[i] = tolower(test[i]); } lw[i] = up[i] = '\0'; zassert_str_equal(up, toup, "toupper error"); zassert_str_equal(lw, tolw, "tolower error"); } void test_strtok_r_do(char *str, char *sep, int tlen, const char * const *toks, bool expect) { int len = 0; char *state, *tok, buf[64+1] = {0}; strncpy(buf, str, 64); tok = strtok_r(buf, sep, &state); while (tok && len < tlen) { if (strcmp(tok, toks[len]) != 0) { break; } tok = strtok_r(NULL, sep, &state); len++; } if (expect) { zassert_equal(len, tlen, "strtok_r error '%s' / '%s'", str, sep); } else { zassert_not_equal(len, tlen, "strtok_r error '%s' / '%s'", str, sep); } } ZTEST(libc_common, test_strtok_r) { static const char * const tc01[] = { "1", "2", "3", "4", "5" }; test_strtok_r_do("1,2,3,4,5", ",", 5, tc01, true); test_strtok_r_do(",, 1 ,2 ,3 4,5 ", ", ", 5, tc01, true); test_strtok_r_do("1,,,2 3,,,4 5", ", ", 5, tc01, true); test_strtok_r_do("1,2 3,,,4 5 ", ", ", 5, tc01, true); test_strtok_r_do("0,1,,,2 3,,,4 5", ", ", 5, tc01, false); test_strtok_r_do("1,,,2 3,,,4 5", ",", 5, tc01, false); test_strtok_r_do("A,,,2,3,,,4 5", ",", 5, tc01, false); test_strtok_r_do("1,,,2,3,,,", ",", 5, tc01, false); test_strtok_r_do("1|2|3,4|5", "| ", 5, tc01, false); } /** * * @brief Test time function * * @see gmtime(),gmtime_r(). */ ZTEST(libc_common, test_time_gmtime) { time_t tests1 = 0; time_t tests2 = -5; time_t tests3 = (time_t) -214748364800; time_t tests4 = 951868800; struct tm tp; zassert_not_null(gmtime(&tests1), "gmtime failed"); zassert_not_null(gmtime(&tests2), "gmtime failed"); tp.tm_wday = -5; zassert_not_null(gmtime_r(&tests3, &tp), "gmtime_r failed"); zassert_not_null(gmtime_r(&tests4, &tp), "gmtime_r failed"); } /** * @brief Test time function * * @see asctime(), asctime_r(). */ ZTEST(libc_common, test_time_asctime) { char buf[26] = {0}; struct tm tp = { .tm_sec = 10, /* Seconds */ .tm_min = 30, /* Minutes */ .tm_hour = 14, /* Hour (24-hour format) */ .tm_wday = 5, /* Day of the week (0-6, 0 = Sun) */ .tm_mday = 1, /* Day of the month */ .tm_mon = 5, /* Month (0-11, January = 0) */ .tm_year = 124, /* Year (current year - 1900) */ }; zassert_not_null(asctime_r(&tp, buf)); zassert_equal(strncmp("Fri Jun 1 14:30:10 2024\n", buf, sizeof(buf)), 0); zassert_not_null(asctime(&tp)); zassert_equal(strncmp("Fri Jun 1 14:30:10 2024\n", asctime(&tp), sizeof(buf)), 0); if (IS_ENABLED(CONFIG_COMMON_LIBC_ASCTIME_R)) { tp.tm_wday = 8; zassert_is_null(asctime_r(&tp, buf)); zassert_is_null(asctime(&tp)); tp.tm_wday = 5; tp.tm_mon = 12; zassert_is_null(asctime_r(&tp, buf)); zassert_is_null(asctime(&tp)); } } /** * @brief Test time function * * @see localtime(), localtime_r(). */ ZTEST(libc_common, test_time_localtime) { time_t tests1 = 0; time_t tests2 = -5; time_t tests3 = (time_t) -214748364800; time_t tests4 = 951868800; struct tm tp; zassert_not_null(localtime(&tests1), "localtime failed"); zassert_not_null(localtime(&tests2), "localtime failed"); tp.tm_wday = -5; zassert_not_null(localtime_r(&tests3, &tp), "localtime_r failed"); zassert_not_null(localtime_r(&tests4, &tp), "localtime_r failed"); } /** * @brief Test time function * * @see ctime(), ctime_r(). */ ZTEST(libc_common, test_time_ctime) { char buf[26] = {0}; time_t test1 = 1718260000; #ifdef CONFIG_NATIVE_LIBC setenv("TZ", "UTC", 1); #endif zassert_not_null(ctime_r(&test1, buf)); zassert_equal(strncmp("Thu Jun 13 06:26:40 2024\n", buf, sizeof(buf)), 0); zassert_not_null(ctime(&test1)); zassert_equal(strncmp("Thu Jun 13 06:26:40 2024\n", ctime(&test1), sizeof(buf)), 0); } /** * * @brief Test rand function * */ ZTEST(libc_common, test_rand) { #ifdef CONFIG_MINIMAL_LIBC int a; a = rand(); /* The default seed is 1 */ zassert_equal(a, 1103527590, "rand failed"); #else ztest_test_skip(); #endif } /** * * @brief Test srand function * */ ZTEST(libc_common, test_srand) { #ifdef CONFIG_MINIMAL_LIBC int a; srand(0); a = rand(); zassert_equal(a, 12345, "srand with seed 0 failed"); srand(1); a = rand(); zassert_equal(a, 1103527590, "srand with seed 1 failed"); srand(10); a = rand(); zassert_equal(a, 297746555, "srand with seed 10 failed"); srand(UINT_MAX - 1); a = rand(); zassert_equal(a, 2087949151, "srand with seed UINT_MAX - 1 failed"); srand(UINT_MAX); a = rand(); zassert_equal(a, 1043980748, "srand with seed UINT_MAX failed"); #else ztest_test_skip(); #endif } /** * * @brief Test rand function for reproducibility * */ ZTEST(libc_common, test_rand_reproducibility) { #ifdef CONFIG_MINIMAL_LIBC int a; int b; int c; srand(0); a = rand(); zassert_equal(a, 12345, "srand with seed 0 failed"); srand(0); b = rand(); zassert_equal(b, 12345, "srand with seed 0 failed (2nd)"); srand(0); c = rand(); zassert_equal(c, 12345, "srand with seed 0 failed (3rd)"); srand(1); a = rand(); zassert_equal(a, 1103527590, "srand with seed 1 failed"); srand(1); b = rand(); zassert_equal(b, 1103527590, "srand with seed 1 failed (2nd)"); srand(1); c = rand(); zassert_equal(c, 1103527590, "srand with seed 1 failed (3rd)"); srand(10); a = rand(); zassert_equal(a, 297746555, "srand with seed 10 failed"); srand(10); b = rand(); zassert_equal(b, 297746555, "srand with seed 10 failed (2nd)"); srand(10); c = rand(); zassert_equal(c, 297746555, "srand with seed 10 failed (3rd)"); srand(UINT_MAX - 1); a = rand(); zassert_equal(a, 2087949151, "srand with seed UINT_MAX - 1 failed"); srand(UINT_MAX - 1); b = rand(); zassert_equal(b, 2087949151, "srand with seed UINT_MAX - 1 failed (2nd)"); srand(UINT_MAX - 1); c = rand(); zassert_equal(c, 2087949151, "srand with seed UINT_MAX - 1 failed (3rd)"); srand(UINT_MAX); a = rand(); zassert_equal(a, 1043980748, "srand with seed UINT_MAX failed"); srand(UINT_MAX); b = rand(); zassert_equal(b, 1043980748, "srand with seed UINT_MAX failed (2nd)"); srand(UINT_MAX); c = rand(); zassert_equal(c, 1043980748, "srand with seed UINT_MAX failed (3rd)"); #else ztest_test_skip(); #endif } /** * * @brief test abort functions * * @see abort(). */ ZTEST(libc_common, test_abort) { #ifdef CONFIG_EXTERNAL_LIBC ztest_test_skip(); #else int a = 0; ztest_set_fault_valid(true); abort(); zassert_equal(a, 0, "abort failed"); #endif } /** * * @brief test exit functions * */ #ifndef CONFIG_EXTERNAL_LIBC static void exit_program(void *p1, void *p2, void *p3) { exit(1); } static K_THREAD_STACK_DEFINE(tstack, STACK_SIZE); static struct k_thread tdata; #endif ZTEST(libc_common, test_exit) { #ifdef CONFIG_EXTERNAL_LIBC ztest_test_skip(); #else int a = 0; k_tid_t tid = k_thread_create(&tdata, tstack, STACK_SIZE, exit_program, NULL, NULL, NULL, K_PRIO_PREEMPT(0), 0, K_NO_WAIT); k_sleep(K_MSEC(10)); k_thread_abort(tid); zassert_equal(a, 0, "exit failed"); #endif }