From 51c79447a0bf06f4e804bd40e97187b55a84d9c8 Mon Sep 17 00:00:00 2001 From: Chris <2293611667@qq.com> Date: Mon, 3 Mar 2025 15:24:47 +0800 Subject: [PATCH] Add testcase framework --- src/{misc => string}/string.c | 2 +- test/include/ctype.h | 94 ++++++ test/include/string.h | 45 +++ test/string/string.c | 434 ++++++++++++++++++++++++++++ test/testcase/ctype/ctype_tests.c | 101 +++++++ test/testcase/ctype/ctype_tests.h | 26 ++ test/testcase/ctype/isalnum.c | 73 +++++ test/testcase/ctype/isalpha.c | 63 ++++ test/testcase/ctype/isascii.c | 48 +++ test/testcase/ctype/isblank.c | 62 ++++ test/testcase/ctype/iscntrl.c | 54 ++++ test/testcase/ctype/isdigit.c | 58 ++++ test/testcase/ctype/isgraph.c | 53 ++++ test/testcase/ctype/islower.c | 58 ++++ test/testcase/ctype/isprint.c | 55 ++++ test/testcase/ctype/ispunct.c | 84 ++++++ test/testcase/ctype/isspace.c | 66 +++++ test/testcase/ctype/isupper.c | 58 ++++ test/testcase/ctype/isxdigit.c | 78 +++++ test/testcase/ctype/toascii.c | 51 ++++ test/testcase/ctype/tolower.c | 56 ++++ test/testcase/ctype/toupper.c | 56 ++++ test/testcase/main.c | 23 ++ test/testcase/string/memcmp.c | 50 ++++ test/testcase/string/memcpy.c | 86 ++++++ test/testcase/string/memmem.c | 91 ++++++ test/testcase/string/memmove.c | 110 +++++++ test/testcase/string/memset.c | 105 +++++++ test/testcase/string/strcat.c | 40 +++ test/testcase/string/strchr.c | 35 +++ test/testcase/string/strcmp.c | 44 +++ test/testcase/string/strcpy.c | 64 ++++ test/testcase/string/strdup.c | 42 +++ test/testcase/string/string_tests.c | 44 +++ test/testcase/string/string_tests.h | 30 ++ test/testcase/string/strlen.c | 34 +++ test/testcase/string/strncat.c | 42 +++ test/testcase/string/strncmp.c | 35 +++ test/testcase/string/strncpy.c | 55 ++++ test/testcase/string/strndup.c | 60 ++++ test/testcase/string/strnlen.c | 38 +++ test/testcase/string/strnstr.c | 45 +++ test/testcase/string/strrchr.c | 35 +++ test/testcase/string/strstr.c | 82 ++++++ test/testcase/string/strtok.c | 50 ++++ test/testcase/tests.h | 8 + xscript/mlibc-config.lua | 20 ++ xscript/test-config.lua | 37 +++ 48 files changed, 2979 insertions(+), 1 deletion(-) rename src/{misc => string}/string.c (99%) create mode 100644 test/include/ctype.h create mode 100644 test/include/string.h create mode 100644 test/string/string.c create mode 100644 test/testcase/ctype/ctype_tests.c create mode 100644 test/testcase/ctype/ctype_tests.h create mode 100644 test/testcase/ctype/isalnum.c create mode 100644 test/testcase/ctype/isalpha.c create mode 100644 test/testcase/ctype/isascii.c create mode 100644 test/testcase/ctype/isblank.c create mode 100644 test/testcase/ctype/iscntrl.c create mode 100644 test/testcase/ctype/isdigit.c create mode 100644 test/testcase/ctype/isgraph.c create mode 100644 test/testcase/ctype/islower.c create mode 100644 test/testcase/ctype/isprint.c create mode 100644 test/testcase/ctype/ispunct.c create mode 100644 test/testcase/ctype/isspace.c create mode 100644 test/testcase/ctype/isupper.c create mode 100644 test/testcase/ctype/isxdigit.c create mode 100644 test/testcase/ctype/toascii.c create mode 100644 test/testcase/ctype/tolower.c create mode 100644 test/testcase/ctype/toupper.c create mode 100644 test/testcase/main.c create mode 100644 test/testcase/string/memcmp.c create mode 100644 test/testcase/string/memcpy.c create mode 100644 test/testcase/string/memmem.c create mode 100644 test/testcase/string/memmove.c create mode 100644 test/testcase/string/memset.c create mode 100644 test/testcase/string/strcat.c create mode 100644 test/testcase/string/strchr.c create mode 100644 test/testcase/string/strcmp.c create mode 100644 test/testcase/string/strcpy.c create mode 100644 test/testcase/string/strdup.c create mode 100644 test/testcase/string/string_tests.c create mode 100644 test/testcase/string/string_tests.h create mode 100644 test/testcase/string/strlen.c create mode 100644 test/testcase/string/strncat.c create mode 100644 test/testcase/string/strncmp.c create mode 100644 test/testcase/string/strncpy.c create mode 100644 test/testcase/string/strndup.c create mode 100644 test/testcase/string/strnlen.c create mode 100644 test/testcase/string/strnstr.c create mode 100644 test/testcase/string/strrchr.c create mode 100644 test/testcase/string/strstr.c create mode 100644 test/testcase/string/strtok.c create mode 100644 test/testcase/tests.h create mode 100644 xscript/test-config.lua diff --git a/src/misc/string.c b/src/string/string.c similarity index 99% rename from src/misc/string.c rename to src/string/string.c index bc15748..9395381 100644 --- a/src/misc/string.c +++ b/src/string/string.c @@ -13,7 +13,7 @@ #include #include #include - +#include void *memset(void *s, int c, size_t count) { char *xs = (char *)s; diff --git a/test/include/ctype.h b/test/include/ctype.h new file mode 100644 index 0000000..4669788 --- /dev/null +++ b/test/include/ctype.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) mlibc & plct lab + * + * SPDX-License-Identifier: MIT + * + * Change Logs: + * Date Author Notes + * 2023/06/16 bernard the first verison + */ + +#ifndef MLIBC_CTYPE_H__ +#define MLIBC_CTYPE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +static inline int isupper(int a) +{ + return (int)(((unsigned)(a)-(unsigned)'A') < 26U); +} + +static inline int isalpha(int c) +{ + return (int)((((unsigned)c|32u)-(unsigned)'a') < 26U); +} + +static inline int isspace(int c) +{ + return (int)(c == (int)' ' || ((unsigned)c-(unsigned)'\t') < 5U); +} + +static inline int isgraph(int c) +{ + return (int)((((unsigned)c) > ' ') && (((unsigned)c) <= (unsigned)'~')); +} + +static inline int isprint(int c) +{ + return (int)((((unsigned)c) >= ' ') && (((unsigned)c) <= (unsigned)'~')); +} + +static inline int isdigit(int a) +{ + return (int)(((unsigned)(a)-(unsigned)'0') < 10U); +} + +static inline int isxdigit(int a) +{ + unsigned int ua = (unsigned int)a; + + return (int)(((ua - (unsigned)'0') < 10U) || ((ua | 32U) - (unsigned)'a' < 6U)); +} + +static inline int tolower(int chr) +{ + return (chr >= (int)'A' && chr <= (int)'Z') ? (chr + 32) : (chr); +} + +static inline int islower(int c) +{ + return ((unsigned)c - 'a') < 26; +} + +static inline int toupper(int chr) +{ + return (int)((chr >= (int)'a' && chr <= (int)'z') ? (chr - 32) : (chr)); +} + +static inline int isalnum(int chr) +{ + return (int)(isalpha(chr) || isdigit(chr)); +} + +static inline int isblank(int c) +{ + return (c == ' ' || c == '\t'); +} + +static inline int iscntrl(int c) +{ + return ((unsigned)c < 0x20 || c == 0x7F); +} + +static inline int ispunct(int c) +{ + return isgraph(c) && !isalnum(c); +} + +#ifdef __cplusplus +} +#endif + +#endif /*MLIBC_CTYPE_H__*/ diff --git a/test/include/string.h b/test/include/string.h new file mode 100644 index 0000000..438128b --- /dev/null +++ b/test/include/string.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) mlibc & plct lab + * + * SPDX-License-Identifier: MIT + * + * Change Logs: + * Date Author Notes + * 2021-02-17 Bernard first version + * 2021-05-02 Meco Man implement strcpy memmove5 + */ + +#ifndef MLIBC_STRING_H__ +#define MLIBC_STRING_H__ + +#include "stdint.h" +#include + +void *memset(void *s, int c, size_t count); +void *memcpy(void *dst, const void *src, size_t count); +int memcmp(const void *cs, const void *ct, size_t count); +void *memmove(void *d, const void *s, size_t n); +void* memchr(const void* m, int c, size_t n); + +size_t strlen(const char *s); +int strcmp(const char *cs, const char *ct); +int strncmp(const char *cs, const char *ct, size_t count); +char *strcpy(char *d, const char *s); +char *strncpy(char *dst, const char *src, size_t n); +char *strcat(char * dest, const char * src); +char *strncat(char *dest, const char *src, size_t count); +char* strrchr(const char* s, int c); +char *strchr(const char* str, int c); +char *__strchrnul(const char *s, int c); +char* strstr(const char* string, const char* substring); +char *strrev(char *str); +size_t strcspn(const char* s, const char* c); +char* strtok_r(char* s, const char* delim, char** last); +char* strtok(char* s, const char* delim); +char *strpbrk(const char *s1, const char *s2); +size_t strspn(const char *s, const char *group); +size_t strxfrm(char *dest, const char *src, size_t n); +char *strdup(const char *s); +char *strndup (const char *, size_t); + +#endif /*MLIBC_STRING_H__*/ diff --git a/test/string/string.c b/test/string/string.c new file mode 100644 index 0000000..9395381 --- /dev/null +++ b/test/string/string.c @@ -0,0 +1,434 @@ +/* + * Copyright (c) mlibc & plct lab + * + * SPDX-License-Identifier: MIT + * + * Change Logs: + * Date Author Notes + */ + +#include +#include +#include +#include +#include +#include +#include +void *memset(void *s, int c, size_t count) +{ + char *xs = (char *)s; + + while (count--) + *xs++ = c; + + return s; +} + +void *memcpy(void * restrict dst, const void * restrict src, size_t count) +{ + char *tmp = (char *)dst, *s = (char *)src; + size_t len; + + if (tmp <= s || tmp > (s + count)) + { + while (count--) + *tmp ++ = *s ++; + } + else + { + for (len = count; len > 0; len --) + tmp[len - 1] = s[len - 1]; + } + + return dst; +} + +int memcmp(const void *cs, const void *ct, size_t count) +{ + const unsigned char *su1, *su2; + int res = 0; + + for (su1 = (const unsigned char *)cs, su2 = (const unsigned char *)ct; 0 < count; ++su1, ++su2, count--) + if ((res = *su1 - *su2) != 0) + break; + + return res; +} + +void *memmove(void *d, const void *s, size_t n) +{ + char *dest = d; + const char *src = s; + + if ((size_t) (dest - src) < n) + { + /* + * The buffer overlaps with the start of the buffer. + * Copy backwards to prevent the premature corruption of . + */ + + while (n > 0) + { + n--; + dest[n] = src[n]; + } + } + else + { + /* It is safe to perform a forward-copy */ + while (n > 0) + { + *dest = *src; + dest++; + src++; + n--; + } + } + + return d; +} + +void* memchr(const void* m, int c, size_t n) +{ + const unsigned char* s = m; + c = (unsigned char)c; + + while(n--) + { + if(s[n] == c) + { + return (void*)(s + n); + } + } + + return 0; +} + +size_t strlen(const char *s) +{ + const char *sc; + + for (sc = s; *sc != '\0'; ++sc) /* nothing */ + ; + + return sc - s; +} + +int strcmp(const char *cs, const char *ct) +{ + while (*cs && *cs == *ct) + { + cs++; + ct++; + } + + return (*cs - *ct); +} + +int strncmp(const char *cs, const char *ct, size_t count) +{ + register signed char __res = 0; + + while (count) + { + if ((__res = *cs - *ct++) != 0 || !*cs++) + break; + count --; + } + + return __res; +} + +char *strcpy(char *d, const char *s) +{ + char *dest = d; + + while (*s != '\0') + { + *d = *s; + d++; + s++; + } + + *d = '\0'; + + return dest; +} + +char *strncpy(char *dst, const char *src, size_t n) +{ + if (n != 0) + { + char *d = dst; + const char *s = src; + + do + { + if ((*d++ = *s++) == 0) + { + /* NUL pad the remaining n-1 bytes */ + while (--n != 0) + *d++ = 0; + break; + } + } while (--n != 0); + } + + return (dst); +} + +char *strcat(char * dest, const char * src) +{ + char *tmp = dest; + + while (*dest) + dest++; + while ((*dest++ = *src++) != '\0') + ; + + return tmp; +} + +char *strncat(char *dest, const char *src, size_t count) +{ + char *tmp = dest; + + if (count) + { + while (*dest) + dest++; + while ((*dest++ = *src++)) + { + if (--count == 0) + { + *dest = '\0'; + break; + } + } + } + + return tmp; +} + +char *strrchr(const char* s, int c) +{ + return memchr(s, c, strlen(s) + 1); +} + +char *strchr(const char* str, int c) +{ + while ((*str != 0) && (*str != c)) + { + str++; + } + return ((*str == c) ? (char *)str : NULL); +} + +#define ALIGN (sizeof(size_t)) +#define ONES ((size_t)-1/UCHAR_MAX) +#define HIGHS (ONES * (UCHAR_MAX/2+1)) +#define HASZERO(x) (((x)-ONES) & ~(x) & HIGHS) + +char *__strchrnul(const char *s, int c) +{ + c = (unsigned char)c; + if (!c) return (char *)s + strlen(s); + +#ifdef __GNUC__ + typedef size_t __attribute__((__may_alias__)) word; + const word *w; + for (; (uintptr_t)s % ALIGN; s++) + if (!*s || *(unsigned char *)s == c) return (char *)s; + size_t k = ONES * c; + for (w = (void *)s; !HASZERO(*w) && !HASZERO(*w^k); w++); + s = (void *)w; +#endif + for (; *s && *(unsigned char *)s != c; s++); + return (char *)s; +} + +char *strstr(const char* string, const char* substring) +{ + const char* a; + const char* b; + + /* First scan quickly through the two strings looking for a + * single-character match. When it's found, then compare the + * rest of the substring. + */ + + b = substring; + + if(*b == 0) + { + return (char*)(uintptr_t)string; + } + + for(; *string != 0; string += 1) + { + if(*string != *b) + { + continue; + } + + a = string; + + while(1) + { + if(*b == 0) + { + return (char*)(uintptr_t)string; + } + + if(*a++ != *b++) + { + break; + } + } + + b = substring; + } + + return NULL; +} + +char *strrev(char *str) +{ + assert(str != NULL); + + size_t len = strlen(str); + size_t halflen = len >> 1; + size_t i; + for (i = 0; i < halflen; i++) + { + char tmp = str[i]; + str[i] = str[len - i - 1]; + str[len - i - 1] = tmp; + } + return str; +} + +int strcoll(const char* l, const char* r) +{ + return strcmp(l, r); +} + +#define BITOP(a, b, op) \ + ((a)[(size_t)(b) / (8 * sizeof *(a))] op(size_t) 1 << ((size_t)(b) % (8 * sizeof *(a)))) + +size_t strcspn(const char* s, const char* c) +{ + const char* a = s; + size_t byteset[32 / sizeof(size_t)]; + + if(!c[0] || !c[1]) + { + return (uintptr_t)(__strchrnul(s, *c) - (uintptr_t)a); + } + + memset(byteset, 0, sizeof byteset); + for(; *c && BITOP(byteset, *(const unsigned char*)c, |=); c++) + { + { + ; + } + } + for(; *s && !BITOP(byteset, *(const unsigned char*)s, &); s++) + { + { + ; + } + } + return (uintptr_t)s - (uintptr_t)a; +} + +char* strtok_r(char* s, const char* delim, char** last) +{ + char* spanp; + char* tok; + int c; + int sc; + + if(s == NULL && (s = *last) == NULL) + { + return (NULL); + } + +/* + * Skip (span) leading delimiters (s += strspn(s, delim), sort of). + */ +cont: + c = *s++; + for(spanp = (char*)(uintptr_t)delim; (sc = *spanp++) != 0;) + { + if(c == sc) + { + goto cont; + } + } + + if(c == 0) + { /* no non-delimiter characters */ + *last = NULL; + return (NULL); + } + tok = s - 1; + + /* + * Scan token (scan for delimiters: s += strcspn(s, delim), sort of). + * Note that delim must have one NUL; we stop if we see that, too. + */ + for(;;) + { + c = *s++; + spanp = (char*)(uintptr_t)delim; + do + { + if((sc = *spanp++) == c) + { + if(c == 0) + { + s = NULL; + } + else + { + s[-1] = '\0'; + } + *last = s; + return (tok); + } + } while(sc != 0); + } + /* NOTREACHED */ +} + +char* strtok(char* s, const char* delim) +{ + static char* last; + + return (strtok_r(s, delim, &last)); +} + +char *strpbrk(const char *s1, const char *s2) +{ + const char *p = s1; + + while(*p && strchr(s2, *p) == NULL) + { + ++p; + } + + return *p ? (char *)p : NULL; +} + +size_t strspn(const char *s, const char *group) +{ + const char *p = s; + + while(*p && strchr(group, *p) != NULL) + { + ++p; + } + + return p - s; +} \ No newline at end of file diff --git a/test/testcase/ctype/ctype_tests.c b/test/testcase/ctype/ctype_tests.c new file mode 100644 index 0000000..892e596 --- /dev/null +++ b/test/testcase/ctype/ctype_tests.c @@ -0,0 +1,101 @@ +/* + * Copyright © 2017 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ +#include "ctype_tests.h" +#include +#include +// Cmocka needs these +// clang-format off +#include +#include +#include +#include +// clang-format on + +int ctype_tests(void) +{ + int overall_result = 0; + + if(0 != isalnum_tests()) + { + overall_result = -1; + } + + if(0 != isalpha_tests()) + { + overall_result = -1; + } + + if(0 != isascii_tests()) + { + overall_result = -1; + } + + if(0 != isblank_tests()) + { + overall_result = -1; + } + + if(0 != isdigit_tests()) + { + overall_result = -1; + } + + if(0 != isgraph_tests()) + { + overall_result = -1; + } + + if(0 != iscntrl_tests()) + { + overall_result = -1; + } + + if(0 != islower_tests()) + { + overall_result = -1; + } + + if(0 != ispunct_tests()) + { + overall_result = -1; + } + + if(0 != isspace_tests()) + { + overall_result = -1; + } + + if(0 != isupper_tests()) + { + overall_result = -1; + } + + if(0 != isxdigit_tests()) + { + overall_result = -1; + } + + if(0 != toascii_tests()) + { + overall_result = -1; + } + + if(0 != tolower_tests()) + { + overall_result = -1; + } + + if(0 != toupper_tests()) + { + overall_result = -1; + } + + if(0 != isprint_tests()) + { + overall_result = -1; + } + + return overall_result; +} diff --git a/test/testcase/ctype/ctype_tests.h b/test/testcase/ctype/ctype_tests.h new file mode 100644 index 0000000..bb87fb9 --- /dev/null +++ b/test/testcase/ctype/ctype_tests.h @@ -0,0 +1,26 @@ +/* + * Copyright © 2018 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ + +#ifndef CTYPE_TESTS_H_ +#define CTYPE_TESTS_H_ + +int isalnum_tests(void); +int isalpha_tests(void); +int isascii_tests(void); +int isblank_tests(void); +int isdigit_tests(void); +int isgraph_tests(void); +int iscntrl_tests(void); +int islower_tests(void); +int ispunct_tests(void); +int isspace_tests(void); +int isupper_tests(void); +int isxdigit_tests(void); +int toascii_tests(void); +int tolower_tests(void); +int toupper_tests(void); +int isprint_tests(void); + +#endif // CTYPE_TESTS_H_ diff --git a/test/testcase/ctype/isalnum.c b/test/testcase/ctype/isalnum.c new file mode 100644 index 0000000..52c902f --- /dev/null +++ b/test/testcase/ctype/isalnum.c @@ -0,0 +1,73 @@ +/* + * Copyright © 2017 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ + +#include "ctype_tests.h" +#include +#include + +// Cmocka needs these +// clang-format off +#include +#include +#include +#include +// clang-format on + +static void good_input(void** state) +{ + for(char c = 'a'; c <= 'z'; c++) + { + assert_int_not_equal(isalnum(c), 0); + } + for(char c = 'A'; c <= 'Z'; c++) + { + assert_int_not_equal(isalnum(c), 0); + } + for(char c = '0'; c <= '9'; c++) + { + assert_int_not_equal(isalnum(c), 0); + } +} + +static void bad_input(void** state) +{ + // 48 represents '0' + for(int i = 0; i < 48; i++) + { + assert_int_equal(isalnum(i), 0); + } + + // 65 represents 'A' + for(int i = 58; i < 65; i++) + { + assert_int_equal(isalnum(i), 0); + } + + // 97 represents 'a' + for(int i = 91; i < 97; i++) + { + assert_int_equal(isalnum(i), 0); + } + + // Remaining integers spot check + assert_int_equal(isalnum(123), 0); + assert_int_equal(isalnum(1024), 0); + assert_int_equal(isalnum(15185), 0); + assert_int_equal(isalnum(1808303), 0); + assert_int_equal(isalnum(INT_MAX), 0); + assert_int_equal(isalnum(-1), 0); + assert_int_equal(isalnum(-100), 0); + assert_int_equal(isalnum(-INT_MAX), 0); +} + +int isalnum_tests(void) +{ + const struct CMUnitTest isalnum_tests[] = { + cmocka_unit_test(good_input), + cmocka_unit_test(bad_input), + }; + + return cmocka_run_group_tests(isalnum_tests, NULL, NULL); +} diff --git a/test/testcase/ctype/isalpha.c b/test/testcase/ctype/isalpha.c new file mode 100644 index 0000000..7d6b9a6 --- /dev/null +++ b/test/testcase/ctype/isalpha.c @@ -0,0 +1,63 @@ +/* + * Copyright © 2017 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ + +#include "ctype_tests.h" +#include +#include + +// Cmocka needs these +// clang-format off +#include +#include +#include +#include +// clang-format on + +static void good_input(void** state) +{ + for(char c = 'a'; c <= 'z'; c++) + { + assert_int_not_equal(isalpha(c), 0); + } + for(char c = 'A'; c <= 'Z'; c++) + { + assert_int_not_equal(isalpha(c), 0); + } +} + +static void bad_input(void** state) +{ + // 65 represents 'A' + for(int i = 0; i < 65; i++) + { + assert_int_equal(isalpha(i), 0); + } + + // 97 represents 'a' + for(int i = 91; i < 97; i++) + { + assert_int_equal(isalpha(i), 0); + } + + // Remaining integers spot check + assert_int_equal(isalpha(123), 0); + assert_int_equal(isalpha(1024), 0); + assert_int_equal(isalpha(15185), 0); + assert_int_equal(isalpha(1808303), 0); + assert_int_equal(isalpha(INT_MAX), 0); + assert_int_equal(isalpha(-1), 0); + assert_int_equal(isalpha(-100), 0); + assert_int_equal(isalpha(-INT_MAX), 0); +} + +int isalpha_tests(void) +{ + const struct CMUnitTest isalpha_tests[] = { + cmocka_unit_test(good_input), + cmocka_unit_test(bad_input), + }; + + return cmocka_run_group_tests(isalpha_tests, NULL, NULL); +} diff --git a/test/testcase/ctype/isascii.c b/test/testcase/ctype/isascii.c new file mode 100644 index 0000000..397b20a --- /dev/null +++ b/test/testcase/ctype/isascii.c @@ -0,0 +1,48 @@ +/* + * Copyright © 2017 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ + +#include "ctype_tests.h" +#include +#include + +// Cmocka needs these +// clang-format off +#include +#include +#include +#include +// clang-format on + +static void good_input(void** state) +{ + for(int i = 0; i < 0x7F; i++) + { + assert_int_not_equal(isascii(i), 0); + } +} + +static void bad_input(void** state) +{ + // Remaining integers spot check + assert_int_equal(isascii(0x80), 0); + assert_int_equal(isascii(0x100), 0); + assert_int_equal(isascii(1024), 0); + assert_int_equal(isascii(15185), 0); + assert_int_equal(isascii(1808303), 0); + assert_int_equal(isascii(INT_MAX), 0); + assert_int_equal(isascii(-1), 0); + assert_int_equal(isascii(-100), 0); + assert_int_equal(isascii(-INT_MAX), 0); +} + +int isascii_tests(void) +{ + const struct CMUnitTest isascii_tests[] = { + cmocka_unit_test(good_input), + cmocka_unit_test(bad_input), + }; + + return cmocka_run_group_tests(isascii_tests, NULL, NULL); +} diff --git a/test/testcase/ctype/isblank.c b/test/testcase/ctype/isblank.c new file mode 100644 index 0000000..914effd --- /dev/null +++ b/test/testcase/ctype/isblank.c @@ -0,0 +1,62 @@ +/* + * Copyright © 2017 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ + +#include "ctype_tests.h" +#include +#include + +// Cmocka needs these +// clang-format off +#include +#include +#include +#include +// clang-format on + +static void good_input(void** state) +{ + assert_int_not_equal(isblank(' '), 0); + assert_int_not_equal(isblank('\t'), 0); +} + +static void bad_input(void** state) +{ + // 9 represents '\t' + for(int i = 0; i < 9; i++) + { + assert_int_equal(isblank(i), 0); + } + + // 32 represents ' ' + for(int i = 10; i < 32; i++) + { + assert_int_equal(isblank(i), 0); + } + + for(int i = 33; i < 0x80; i++) + { + assert_int_equal(isblank(i), 0); + } + + // Remaining integers spot check + assert_int_equal(isblank(129), 0); + assert_int_equal(isblank(1024), 0); + assert_int_equal(isblank(15185), 0); + assert_int_equal(isblank(1808303), 0); + assert_int_equal(isblank(INT_MAX), 0); + assert_int_equal(isblank(-1), 0); + assert_int_equal(isblank(-100), 0); + assert_int_equal(isblank(-INT_MAX), 0); +} + +int isblank_tests(void) +{ + const struct CMUnitTest isblank_tests[] = { + cmocka_unit_test(good_input), + cmocka_unit_test(bad_input), + }; + + return cmocka_run_group_tests(isblank_tests, NULL, NULL); +} diff --git a/test/testcase/ctype/iscntrl.c b/test/testcase/ctype/iscntrl.c new file mode 100644 index 0000000..abc6ed0 --- /dev/null +++ b/test/testcase/ctype/iscntrl.c @@ -0,0 +1,54 @@ +/* + * Copyright © 2017 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ + +#include "ctype_tests.h" +#include +#include + +// Cmocka needs these +// clang-format off +#include +#include +#include +#include +// clang-format on + +static void good_input(void** state) +{ + for(int i = 0; i < 0x20; i++) + { + assert_int_not_equal(iscntrl(i), 0); + } + + assert_int_not_equal(iscntrl(0x7f), 0); +} + +static void bad_input(void** state) +{ + for(int i = 0x20; i < 0x7F; i++) + { + assert_int_equal(iscntrl(i), 0); + } + + // Remaining integers spot check + assert_int_equal(iscntrl(129), 0); + assert_int_equal(iscntrl(1024), 0); + assert_int_equal(iscntrl(15185), 0); + assert_int_equal(iscntrl(1808303), 0); + assert_int_equal(iscntrl(INT_MAX), 0); + assert_int_equal(iscntrl(-1), 0); + assert_int_equal(iscntrl(-100), 0); + assert_int_equal(iscntrl(-INT_MAX), 0); +} + +int iscntrl_tests(void) +{ + const struct CMUnitTest iscntrl_tests[] = { + cmocka_unit_test(good_input), + cmocka_unit_test(bad_input), + }; + + return cmocka_run_group_tests(iscntrl_tests, NULL, NULL); +} diff --git a/test/testcase/ctype/isdigit.c b/test/testcase/ctype/isdigit.c new file mode 100644 index 0000000..634a484 --- /dev/null +++ b/test/testcase/ctype/isdigit.c @@ -0,0 +1,58 @@ +/* + * Copyright © 2017 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ + +#include "ctype_tests.h" +#include +#include + +// Cmocka needs these +// clang-format off +#include +#include +#include +#include +// clang-format on + +static void good_input(void** state) +{ + for(char c = '0'; c <= '9'; c++) + { + assert_int_not_equal(isdigit(c), 0); + } +} + +static void bad_input(void** state) +{ + // 48 represents '0' + for(int i = 0; i < 48; i++) + { + assert_int_equal(isdigit(i), 0); + } + + for(int i = 58; i < 0x80; i++) + { + assert_int_equal(isdigit(i), 0); + } + + // Remaining integers spot check + assert_int_equal(isdigit(123), 0); + assert_int_equal(isdigit(1024), 0); + assert_int_equal(isdigit(15185), 0); + assert_int_equal(isdigit(1808303), 0); + assert_int_equal(isdigit(INT_MAX), 0); + assert_int_equal(isdigit(-1), 0); + assert_int_equal(isdigit(-100), 0); + assert_int_equal(isdigit(-INT_MAX), 0); +} + +int isdigit_tests(void) +{ + const struct CMUnitTest isdigit_tests[] = { + cmocka_unit_test(good_input), + cmocka_unit_test(bad_input), + }; + + return cmocka_run_group_tests(isdigit_tests, NULL, NULL); +} diff --git a/test/testcase/ctype/isgraph.c b/test/testcase/ctype/isgraph.c new file mode 100644 index 0000000..2e3de9f --- /dev/null +++ b/test/testcase/ctype/isgraph.c @@ -0,0 +1,53 @@ +/* + * Copyright © 2017 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ + +#include "ctype_tests.h" +#include +#include + +// Cmocka needs these +// clang-format off +#include +#include +#include +#include +// clang-format on + +static void good_input(void** state) +{ + for(int c = 0x21; c < 0x7F; c++) + { + assert_int_not_equal(isgraph(c), 0); + } +} + +static void bad_input(void** state) +{ + for(int i = 0; i < 0x21; i++) + { + assert_int_equal(isgraph(i), 0); + } + + // Remaining integers spot check + assert_int_equal(isgraph(127), 0); + assert_int_equal(isgraph(129), 0); + assert_int_equal(isgraph(1024), 0); + assert_int_equal(isgraph(15185), 0); + assert_int_equal(isgraph(1808303), 0); + assert_int_equal(isgraph(INT_MAX), 0); + assert_int_equal(isgraph(-1), 0); + assert_int_equal(isgraph(-100), 0); + assert_int_equal(isgraph(-INT_MAX), 0); +} + +int isgraph_tests(void) +{ + const struct CMUnitTest isgraph_tests[] = { + cmocka_unit_test(good_input), + cmocka_unit_test(bad_input), + }; + + return cmocka_run_group_tests(isgraph_tests, NULL, NULL); +} diff --git a/test/testcase/ctype/islower.c b/test/testcase/ctype/islower.c new file mode 100644 index 0000000..e7dfb7d --- /dev/null +++ b/test/testcase/ctype/islower.c @@ -0,0 +1,58 @@ +/* + * Copyright © 2017 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ + +#include "ctype_tests.h" +#include +#include + +// Cmocka needs these +// clang-format off +#include +#include +#include +#include +// clang-format on + +static void good_input(void** state) +{ + for(char c = 'a'; c <= 'z'; c++) + { + assert_int_not_equal(islower(c), 0); + } +} + +static void bad_input(void** state) +{ + // 97 represents 'a' + for(int i = 0; i < 97; i++) + { + assert_int_equal(islower(i), 0); + } + + for(int i = 123; i < 0x80; i++) + { + assert_int_equal(islower(i), 0); + } + + // Remaining integers spot check + assert_int_equal(islower(129), 0); + assert_int_equal(islower(1024), 0); + assert_int_equal(islower(15185), 0); + assert_int_equal(islower(1808303), 0); + assert_int_equal(islower(INT_MAX), 0); + assert_int_equal(islower(-1), 0); + assert_int_equal(islower(-100), 0); + assert_int_equal(islower(-INT_MAX), 0); +} + +int islower_tests(void) +{ + const struct CMUnitTest islower_tests[] = { + cmocka_unit_test(good_input), + cmocka_unit_test(bad_input), + }; + + return cmocka_run_group_tests(islower_tests, NULL, NULL); +} diff --git a/test/testcase/ctype/isprint.c b/test/testcase/ctype/isprint.c new file mode 100644 index 0000000..cbee029 --- /dev/null +++ b/test/testcase/ctype/isprint.c @@ -0,0 +1,55 @@ +/* + * Copyright © 2017 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ + +#include "ctype_tests.h" +#include +#include + +// Cmocka needs these +// clang-format off +#include +#include +#include +#include +// clang-format on + +static void good_input(void** state) +{ + for(char c = ' '; c < 0x7F; c++) + { + assert_int_not_equal(isprint(c), 0); + } +} + +static void bad_input(void** state) +{ + // 65 represents 'A' + for(int i = 0; i < ' '; i++) + { + assert_int_equal(isprint(i), 0); + } + + // Remaining integers spot check + assert_int_equal(isprint(127), 0); + assert_int_equal(isprint(128), 0); + assert_int_equal(isprint(129), 0); + assert_int_equal(isprint(1024), 0); + assert_int_equal(isprint(15185), 0); + assert_int_equal(isprint(1808303), 0); + assert_int_equal(isprint(INT_MAX), 0); + assert_int_equal(isprint(-1), 0); + assert_int_equal(isprint(-100), 0); + assert_int_equal(isprint(-INT_MAX), 0); +} + +int isprint_tests(void) +{ + const struct CMUnitTest isprint_tests[] = { + cmocka_unit_test(good_input), + cmocka_unit_test(bad_input), + }; + + return cmocka_run_group_tests(isprint_tests, NULL, NULL); +} diff --git a/test/testcase/ctype/ispunct.c b/test/testcase/ctype/ispunct.c new file mode 100644 index 0000000..0ae8a13 --- /dev/null +++ b/test/testcase/ctype/ispunct.c @@ -0,0 +1,84 @@ +/* + * Copyright © 2017 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ + +#include "ctype_tests.h" +#include +#include + +// Cmocka needs these +// clang-format off +#include +#include +#include +#include +// clang-format on + +static void good_input(void** state) +{ + for(char c = '!'; c <= '/'; c++) + { + assert_int_not_equal(ispunct(c), 0); + } + + for(char c = ':'; c <= '@'; c++) + { + assert_int_not_equal(ispunct(c), 0); + } + + for(char c = '['; c <= '`'; c++) + { + assert_int_not_equal(ispunct(c), 0); + } + + for(char c = '{'; c <= '~'; c++) + { + assert_int_not_equal(ispunct(c), 0); + } +} + +static void bad_input(void** state) +{ + for(int i = 0; i < '!'; i++) + { + assert_int_equal(ispunct(i), 0); + } + + for(int i = '0'; i < '9'; i++) + { + assert_int_equal(ispunct(i), 0); + } + + for(int i = 'A'; i < 'Z'; i++) + { + assert_int_equal(ispunct(i), 0); + } + + for(int i = 'a'; i < 'z'; i++) + { + assert_int_equal(ispunct(i), 0); + } + + // Remaining integers spot check + assert_int_equal(ispunct(127), 0); + assert_int_equal(ispunct(128), 0); + assert_int_equal(ispunct(129), 0); + assert_int_equal(ispunct(1024), 0); + assert_int_equal(ispunct(15185), 0); + assert_int_equal(ispunct(1808303), 0); + assert_int_equal(ispunct(INT_MAX), 0); + assert_int_equal(ispunct(-1), 0); + assert_int_equal(ispunct(-100), 0); + assert_int_equal(ispunct(-INT_MAX), 0); +} + +int ispunct_tests(void) +{ + const struct CMUnitTest ispunct_tests[] = { + cmocka_unit_test(good_input), + cmocka_unit_test(bad_input), + }; + + return cmocka_run_group_tests(ispunct_tests, NULL, NULL); +} diff --git a/test/testcase/ctype/isspace.c b/test/testcase/ctype/isspace.c new file mode 100644 index 0000000..88f6a5e --- /dev/null +++ b/test/testcase/ctype/isspace.c @@ -0,0 +1,66 @@ +/* + * Copyright © 2017 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ + +#include "ctype_tests.h" +#include +#include + +// Cmocka needs these +// clang-format off +#include +#include +#include +#include +// clang-format on + +static void good_input(void** state) +{ + assert_int_not_equal(isspace(' '), 0); + assert_int_not_equal(isspace('\n'), 0); + assert_int_not_equal(isspace('\t'), 0); + assert_int_not_equal(isspace(11), 0); + assert_int_not_equal(isspace(12), 0); + assert_int_not_equal(isspace(13), 0); +} + +static void bad_input(void** state) +{ + // 9 represents '\t' + for(int i = 0; i < 9; i++) + { + assert_int_equal(isspace(i), 0); + } + + // 32 represents ' ' + for(int i = 16; i < 32; i++) + { + assert_int_equal(isspace(i), 0); + } + + for(int i = 33; i < 0x80; i++) + { + assert_int_equal(isspace(i), 0); + } + + // Remaining integers spot check + assert_int_equal(isspace(129), 0); + assert_int_equal(isspace(1024), 0); + assert_int_equal(isspace(15185), 0); + assert_int_equal(isspace(1808303), 0); + assert_int_equal(isspace(INT_MAX), 0); + assert_int_equal(isspace(-1), 0); + assert_int_equal(isspace(-100), 0); + assert_int_equal(isspace(-INT_MAX), 0); +} + +int isspace_tests(void) +{ + const struct CMUnitTest isspace_tests[] = { + cmocka_unit_test(good_input), + cmocka_unit_test(bad_input), + }; + + return cmocka_run_group_tests(isspace_tests, NULL, NULL); +} diff --git a/test/testcase/ctype/isupper.c b/test/testcase/ctype/isupper.c new file mode 100644 index 0000000..680b157 --- /dev/null +++ b/test/testcase/ctype/isupper.c @@ -0,0 +1,58 @@ +/* + * Copyright © 2017 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ + +#include "ctype_tests.h" +#include +#include + +// Cmocka needs these +// clang-format off +#include +#include +#include +#include +// clang-format on + +static void good_input(void** state) +{ + for(char c = 'A'; c <= 'Z'; c++) + { + assert_int_not_equal(isupper(c), 0); + } +} + +static void bad_input(void** state) +{ + // 65 represents 'A' + for(int i = 0; i < 65; i++) + { + assert_int_equal(isupper(i), 0); + } + + for(int i = 91; i < 0x80; i++) + { + assert_int_equal(isupper(i), 0); + } + + // Remaining integers spot check + assert_int_equal(isupper(129), 0); + assert_int_equal(isupper(1024), 0); + assert_int_equal(isupper(15185), 0); + assert_int_equal(isupper(1808303), 0); + assert_int_equal(isupper(INT_MAX), 0); + assert_int_equal(isupper(-1), 0); + assert_int_equal(isupper(-100), 0); + assert_int_equal(isupper(-INT_MAX), 0); +} + +int isupper_tests(void) +{ + const struct CMUnitTest isupper_tests[] = { + cmocka_unit_test(good_input), + cmocka_unit_test(bad_input), + }; + + return cmocka_run_group_tests(isupper_tests, NULL, NULL); +} diff --git a/test/testcase/ctype/isxdigit.c b/test/testcase/ctype/isxdigit.c new file mode 100644 index 0000000..58402df --- /dev/null +++ b/test/testcase/ctype/isxdigit.c @@ -0,0 +1,78 @@ +/* + * Copyright © 2017 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ + +#include "ctype_tests.h" +#include +#include + +// Cmocka needs these +// clang-format off +#include +#include +#include +#include +// clang-format on + +static void good_input(void** state) +{ + for(char c = 'a'; c <= 'f'; c++) + { + assert_int_not_equal(isxdigit(c), 0); + } + for(char c = 'A'; c <= 'F'; c++) + { + assert_int_not_equal(isxdigit(c), 0); + } + for(char c = '0'; c <= '9'; c++) + { + assert_int_not_equal(isxdigit(c), 0); + } +} + +static void bad_input(void** state) +{ + // 48 represents '9' + for(int i = 0; i < 48; i++) + { + assert_int_equal(isxdigit(i), 0); + } + + // 65 represents 'A' + for(int i = 58; i < 65; i++) + { + assert_int_equal(isxdigit(i), 0); + } + + // 97 represents 'a' + for(int i = 71; i < 97; i++) + { + assert_int_equal(isxdigit(i), 0); + } + + for(int i = 103; i < 0x80; i++) + { + assert_int_equal(isxdigit(i), 0); + } + + // Remaining integers spot check + assert_int_equal(isxdigit(129), 0); + assert_int_equal(isxdigit(1024), 0); + assert_int_equal(isxdigit(15185), 0); + assert_int_equal(isxdigit(1808303), 0); + assert_int_equal(isxdigit(INT_MAX), 0); + assert_int_equal(isxdigit(-1), 0); + assert_int_equal(isxdigit(-100), 0); + assert_int_equal(isxdigit(-INT_MAX), 0); +} + +int isxdigit_tests(void) +{ + const struct CMUnitTest isxdigit_tests[] = { + cmocka_unit_test(good_input), + cmocka_unit_test(bad_input), + }; + + return cmocka_run_group_tests(isxdigit_tests, NULL, NULL); +} diff --git a/test/testcase/ctype/toascii.c b/test/testcase/ctype/toascii.c new file mode 100644 index 0000000..b45ff11 --- /dev/null +++ b/test/testcase/ctype/toascii.c @@ -0,0 +1,51 @@ +/* + * Copyright © 2017 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ + +#include "ctype_tests.h" +#include +#include + +// Cmocka needs these +// clang-format off +#include +#include +#include +#include +// clang-format on + +static void good_input(void** state) +{ + for(int i = 0; i < 0x80; i++) + { + assert_int_equal(toascii(i), i); + } +} + +static void bad_input(void** state) +{ + for(int i = 0x80; i < 0xFF; i++) + { + assert_int_equal(toascii(i), (i & 0x7F)); + } + + // Remaining integers spot check + assert_int_equal(toascii(1024), (1024 & 0x7F)); + assert_int_equal(toascii(15185), (15185 & 0x7F)); + assert_int_equal(toascii(1808303), (1808303 & 0x7F)); + assert_int_equal(toascii(INT_MAX), (INT_MAX & 0x7F)); + assert_int_equal(toascii(-1), (-1 & 0x7F)); + assert_int_equal(toascii(-100), (-100 & 0x7F)); + assert_int_equal(toascii(-INT_MAX), (-INT_MAX & 0x7F)); +} + +int toascii_tests(void) +{ + const struct CMUnitTest toascii_tests[] = { + cmocka_unit_test(good_input), + cmocka_unit_test(bad_input), + }; + + return cmocka_run_group_tests(toascii_tests, NULL, NULL); +} diff --git a/test/testcase/ctype/tolower.c b/test/testcase/ctype/tolower.c new file mode 100644 index 0000000..a6f6111 --- /dev/null +++ b/test/testcase/ctype/tolower.c @@ -0,0 +1,56 @@ +/* + * Copyright © 2017 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ + +#include "ctype_tests.h" +#include +#include + +// Cmocka needs these +// clang-format off +#include +#include +#include +#include +// clang-format on + +static void good_input(void** state) +{ + for(char c = 'A'; c <= 'Z'; c++) + { + assert_int_equal(tolower(c), c + 32); + } +} + +static void bad_input(void** state) +{ + for(int i = 0; i < 'A'; i++) + { + assert_int_equal(tolower(i), i); + } + + for(int i = 91; i < 0x80; i++) + { + assert_int_equal(tolower(i), i); + } + + // Remaining integers spot check + assert_int_equal(tolower(1024), 1024); + assert_int_equal(tolower(15185), 15185); + assert_int_equal(tolower(1808303), 1808303); + assert_int_equal(tolower(INT_MAX), INT_MAX); + assert_int_equal(tolower(-1), -1); + assert_int_equal(tolower(-100), -100); + assert_int_equal(tolower(-INT_MAX), -INT_MAX); +} + +int tolower_tests(void) +{ + const struct CMUnitTest tolower_tests[] = { + cmocka_unit_test(good_input), + cmocka_unit_test(bad_input), + }; + + return cmocka_run_group_tests(tolower_tests, NULL, NULL); +} diff --git a/test/testcase/ctype/toupper.c b/test/testcase/ctype/toupper.c new file mode 100644 index 0000000..786ae98 --- /dev/null +++ b/test/testcase/ctype/toupper.c @@ -0,0 +1,56 @@ +/* + * Copyright © 2017 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ + +#include "ctype_tests.h" +#include +#include + +// Cmocka needs these +// clang-format off +#include +#include +#include +#include +// clang-format on + +static void good_input(void** state) +{ + for(char c = 'a'; c <= 'z'; c++) + { + assert_int_equal(toupper(c), c - 32); + } +} + +static void bad_input(void** state) +{ + for(int i = 0; i < 'a'; i++) + { + assert_int_equal(toupper(i), i); + } + + for(int i = 0x7B; i < 0x80; i++) + { + assert_int_equal(toupper(i), i); + } + + // Remaining integers spot check + assert_int_equal(toupper(1024), 1024); + assert_int_equal(toupper(15185), 15185); + assert_int_equal(toupper(1808303), 1808303); + assert_int_equal(toupper(INT_MAX), INT_MAX); + assert_int_equal(toupper(-1), -1); + assert_int_equal(toupper(-100), -100); + assert_int_equal(toupper(-INT_MAX), -INT_MAX); +} + +int toupper_tests(void) +{ + const struct CMUnitTest toupper_tests[] = { + cmocka_unit_test(good_input), + cmocka_unit_test(bad_input), + }; + + return cmocka_run_group_tests(toupper_tests, NULL, NULL); +} diff --git a/test/testcase/main.c b/test/testcase/main.c new file mode 100644 index 0000000..f22ea6e --- /dev/null +++ b/test/testcase/main.c @@ -0,0 +1,23 @@ +/* + * Copyright © 2017 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ + +// CMocka needs these +// clang-format off +#include +#include +#include +#include +// clang-format on + +#include + +int main(void) +{ + int overall_result = 0; + + overall_result |= ctype_tests(); + overall_result |= string_tests(); + return overall_result; +} diff --git a/test/testcase/string/memcmp.c b/test/testcase/string/memcmp.c new file mode 100644 index 0000000..8794f4a --- /dev/null +++ b/test/testcase/string/memcmp.c @@ -0,0 +1,50 @@ +/* + * Copyright © 2017 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ + +#include "string_tests.h" +#include + +// Cmocka needs these +// clang-format off +#include +#include +#include +#include +// clang-format on + +static void memcmp_test(void** state) +{ + const char* s = "abc 123"; + + assert_int_equal(memcmp("abc", "abc", 4), 0); + assert_int_equal(memcmp(s, "abc", 3), 0); + assert_int_equal(memcmp("abc", s, 3), 0); + + // The following tests intentionally use a length > 3 + // To test what memcmp does in such a situation + assert_int_equal(!!(memcmp(s, "abc", 6) > 0), 1); + assert_int_equal(!!(memcmp("abc", s, 6) < 0), 1); + + // If the compiler built-in is used, these tests will trigger a segfault +#ifndef BUILTINS_ARE_ENABLED + // Check NULL input handling + assert_int_not_equal(memcmp("abc", NULL, 3), 0); + assert_int_not_equal(memcmp(NULL, "abc", 3), 0); +#endif + + // Check that two NULL strings will match + assert_int_equal(memcmp(NULL, NULL, 0), 0); +} + +#pragma mark - Public Functions - + +int memcmp_tests(void) +{ + const struct CMUnitTest memcmp_tests[] = { + cmocka_unit_test(memcmp_test), + }; + + return cmocka_run_group_tests(memcmp_tests, NULL, NULL); +} diff --git a/test/testcase/string/memcpy.c b/test/testcase/string/memcpy.c new file mode 100644 index 0000000..e30015a --- /dev/null +++ b/test/testcase/string/memcpy.c @@ -0,0 +1,86 @@ +/* + * Copyright © 2017 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ + +#include "string_tests.h" +#include +#include + +// Cmocka needs these +// clang-format off +#include +#include +#include +#include +// clang-format on + +#pragma mark - Definitions - + +#define N 80 + +#pragma mark - Declarations - + +static char buf[512]; + +#pragma mark - Private Functions - + +static void* aligned(void* p) +{ + return (void*)(((intptr_t)p + 63) & -64); +} + +static void test_align(unsigned dalign, unsigned salign, size_t len) +{ + char* src = aligned(buf); + char* dst = aligned(buf + 128); + char* want = aligned(buf + 256); + char* p; + unsigned i; + + assert_false(salign + len > N); + assert_false(dalign + len > N); + + for(i = 0; i < N; i++) + { + src[i] = '#'; + dst[i] = want[i] = ' '; + } + + for(i = 0; i < len; i++) + { + src[salign + i] = want[dalign + i] = (char)('0' + i); + } + + p = memcpy(dst + dalign, src + salign, len); + + assert_ptr_equal(p, dst + dalign); + + for(i = 0; i < N; i++) + { + assert_int_equal(dst[i], want[i]); + } +} + +static void memcpy_aligned_test(void** state) +{ + for(unsigned i = 0; i < 16; i++) + { + for(unsigned j = 0; j < 16; j++) + { + for(size_t k = 0; k < 64; k++) + { + test_align(i, j, k); + } + } + } +} + +#pragma mark - Public Functions - + +int memcpy_tests(void) +{ + const struct CMUnitTest memcpy_tests[] = {cmocka_unit_test(memcpy_aligned_test)}; + + return cmocka_run_group_tests(memcpy_tests, NULL, NULL); +} diff --git a/test/testcase/string/memmem.c b/test/testcase/string/memmem.c new file mode 100644 index 0000000..1086940 --- /dev/null +++ b/test/testcase/string/memmem.c @@ -0,0 +1,91 @@ +/* + * Copyright © 2017 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ + +#include "string_tests.h" +#include + +// Cmocka needs these +// clang-format off +#include +#include +#include +#include +// clang-format on + +#pragma mark - Definitions - + +#define N(s, tail, sub) \ + { \ + const char* p = s tail; \ + char* q = memmem(p, strlen(s), sub, strlen(sub)); \ + assert_ptr_equal(q, NULL); \ + } + +#define T(s, sub, n) \ + { \ + const char* p = s; \ + char* q = memmem(p, strlen(p), sub, strlen(sub)); \ + assert_ptr_not_equal(q, NULL); \ + assert_ptr_equal(q - p, n); \ + } + +#define T_NULL(s, sub, n) \ + { \ + const char* p = s; \ + char* q = memmem(p, strlen(p), sub, strlen(sub)); \ + assert_ptr_equal(q, NULL); \ + } + +static void check_input(void** state) +{ + N("", "a", "a") + N("a", "a", "aa") + N("a", "b", "b") + N("aa", "b", "ab") + N("aa", "a", "aaa") + N("aba", "b", "bab") + N("abba", "b", "bab") + N("abba", "ba", "aba") + N("abc abc", "d", "abcd") + N("0-1-2-3-4-5-6-7-8-9", "", "-3-4-56-7-8-") + N("0-1-2-3-4-5-6-7-8-9", "", "-3-4-5+6-7-8-") + N("_ _ _\xff_ _ _", "\x7f_", "_\x7f_") + N("_ _ _\x7f_ _ _", "\xff_", "_\xff_") + + T_NULL("", "", 0) + T_NULL("abcd", "", 0) + + T("abcd", "a", 0) + T("abcd", "b", 1) + T("abcd", "c", 2) + T("abcd", "d", 3) + T("abcd", "ab", 0) + T("abcd", "bc", 1) + T("abcd", "cd", 2) + T("ababa", "baba", 1) + T("ababab", "babab", 1) + T("abababa", "bababa", 1) + T("abababab", "bababab", 1) + T("ababababa", "babababa", 1) + T("abbababab", "bababa", 2) + T("abbababab", "ababab", 3) + T("abacabcabcab", "abcabcab", 4) + T("nanabanabanana", "aba", 3) + T("nanabanabanana", "ban", 4) + T("nanabanabanana", "anab", 1) + T("nanabanabanana", "banana", 8) + T("_ _\xff_ _", "_\xff_", 2) +} + +#pragma mark - Public Functions - + +int memmem_tests(void) +{ + const struct CMUnitTest memmem_tests[] = { + cmocka_unit_test(check_input), + }; + + return cmocka_run_group_tests(memmem_tests, NULL, NULL); +} diff --git a/test/testcase/string/memmove.c b/test/testcase/string/memmove.c new file mode 100644 index 0000000..2ff33f3 --- /dev/null +++ b/test/testcase/string/memmove.c @@ -0,0 +1,110 @@ +/* + * Copyright © 2017 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ + +#include "string_tests.h" +#include +#include + +// Cmocka needs these +// clang-format off +#include +#include +#include +#include +// clang-format on + +struct test_memmove_data +{ + char template[64]; + char buf[64]; +}; + +static void fill_buffer(char* buf, size_t size, char start_value, char end_value) +{ + for(size_t i = 0; i < size; ++i) + { + buf[i] = (char)(((size_t)start_value + i) % (size_t)(end_value - start_value + 1)); + } +} + +static int setup_test(void** state) +{ + struct test_memmove_data* md = malloc(sizeof(struct test_memmove_data)); + if(!md) + { + return -1; + } + fill_buffer(md->template, sizeof(md->template), 'A', 'Z'); + memcpy(md->buf, md->template, sizeof(md->buf)); + *state = md; + return 0; +} + +static int teardown_test(void** state) +{ + struct test_memmove_data* md = *state; + free(md); + return 0; +} + +static void memmove_test_lower_to_higher(void** state) +{ + struct test_memmove_data* md = *state; + char* p; + size_t offset = 20; + size_t len = sizeof(md->buf) - offset; + p = memmove(md->buf + offset, md->buf, len); + assert_ptr_equal(p, md->buf + offset); + assert_memory_equal(md->buf + offset, md->template, len); + assert_memory_equal(md->buf, md->template, offset); + return; +} + +static void memmove_test_higher_to_lower(void** state) +{ + struct test_memmove_data* md = *state; + char* p; + size_t offset = 20; + size_t len = sizeof(md->buf) - offset; + p = memmove(md->buf, md->buf + offset, len); + assert_ptr_equal(p, md->buf); + assert_memory_equal(md->buf, md->template + offset, len); + assert_memory_equal(md->buf + len, md->template + len, offset); + return; +} + +static void memmove_test_zero_size(void** state) +{ + struct test_memmove_data* md = *state; + char* p; + size_t offset = 30; + p = memmove(md->buf + offset, md->buf, 0); + assert_ptr_equal(p, md->buf + offset); + assert_memory_equal(md->buf, md->template, sizeof(md->template)); + return; +} + +static void memmove_test_copy_to_itself(void** state) +{ + struct test_memmove_data* md = *state; + char* p; + p = memmove(md->buf, md->buf, sizeof(md->buf)); + assert_ptr_equal(p, md->buf); + assert_memory_equal(md->buf, md->template, sizeof(md->template)); + return; +} +#pragma mark - Public Functions - + +int memmove_tests(void) +{ + const struct CMUnitTest memmove_tests[] = { + cmocka_unit_test_setup_teardown(memmove_test_lower_to_higher, setup_test, teardown_test), + cmocka_unit_test_setup_teardown(memmove_test_higher_to_lower, setup_test, teardown_test), + cmocka_unit_test_setup_teardown(memmove_test_zero_size, setup_test, teardown_test), + cmocka_unit_test_setup_teardown(memmove_test_copy_to_itself, setup_test, teardown_test), + }; + + return cmocka_run_group_tests(memmove_tests, NULL, NULL); +} diff --git a/test/testcase/string/memset.c b/test/testcase/string/memset.c new file mode 100644 index 0000000..d9cc911 --- /dev/null +++ b/test/testcase/string/memset.c @@ -0,0 +1,105 @@ +/* + * Copyright © 2017 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ + +#include "string_tests.h" +#include +#include +#include + +// Cmocka needs these +// clang-format off +#include +#include +#include +#include +// clang-format on + +#pragma mark - Definitions - + +#define N 400 + +#pragma mark - Declarations - + +static char buf[N]; +static char buf2[N]; + +#pragma mark - Private Functions - + +static char* aligned(void* p) +{ + return (char*)(((intptr_t)p + 63) & -64); +} + +static void test_align(int align, size_t len) +{ + char* s = aligned(buf + 64) + align; + char* want = aligned(buf2 + 64) + align; + char* p; + int i; + + assert_false(len + 64 > (size_t)(buf + N - s)); + assert_false(len + 64 > (size_t)(buf2 + N - want)); + + for(i = 0; i < N; i++) + { + buf[i] = buf2[i] = ' '; + } + + for(i = 0; i < (int)len; i++) + { + want[i] = '#'; + } + + p = memset(s, '#', len); + + assert_ptr_equal(p, s); + + for(i = -64; i < (int)len + 64; i++) + { + assert_int_equal(s[i], want[i]); + } +} + +static void memset_aligned_test(void** state) +{ + for(int i = 0; i < 16; i++) + { + for(size_t j = 0; j < 200; j++) + { + test_align(i, j); + } + } +} + +static void check_input_(char c, void** state) +{ + memset(buf, c, 10); + for(int i = 0; i < 10; i++) + { + assert_int_equal(buf[i], c); + } +} + +static void check_input(void** state) +{ + check_input_('c', state); + check_input_(0, state); + check_input_(-1, state); + check_input_((char)INT_MAX, state); + check_input_((char)-INT_MAX, state); + check_input_((char)0xab, state); +} + +#pragma mark - Public Functions - + +int memset_tests(void) +{ + const struct CMUnitTest memset_tests[] = { + cmocka_unit_test(memset_aligned_test), + cmocka_unit_test(check_input), + }; + + return cmocka_run_group_tests(memset_tests, NULL, NULL); +} diff --git a/test/testcase/string/strcat.c b/test/testcase/string/strcat.c new file mode 100644 index 0000000..fd01db3 --- /dev/null +++ b/test/testcase/string/strcat.c @@ -0,0 +1,40 @@ +/* + * Copyright © 2017 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ + +#include "string_tests.h" +#include + +// Cmocka needs these +// clang-format off +#include +#include +#include +#include +// clang-format on + +static void strcat_test(void** state) +{ + char b[32]; + strcpy(b, "abc"); + assert_ptr_equal(strcat(b, "123456"), b); + + // Check if strcat failed to null-terminate + assert_int_equal(b[9], 0); + assert_int_equal(strlen(b), strlen("abc") + strlen("123456")); + + // Check if the string is correct + assert_int_equal(strcmp(b, "abc123456"), 0); +} + +#pragma mark - Public Functions - + +int strcat_tests(void) +{ + const struct CMUnitTest strcat_tests[] = { + cmocka_unit_test(strcat_test), + }; + + return cmocka_run_group_tests(strcat_tests, NULL, NULL); +} diff --git a/test/testcase/string/strchr.c b/test/testcase/string/strchr.c new file mode 100644 index 0000000..b7eee7e --- /dev/null +++ b/test/testcase/string/strchr.c @@ -0,0 +1,35 @@ +/* + * Copyright © 2017 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ + +#include "string_tests.h" +#include + +// Cmocka needs these +// clang-format off +#include +#include +#include +#include +// clang-format on + +#pragma mark - Definitions - + +static void strchr_test(void** state) +{ + char b[32]; + strcpy(b, "aaababccdd0001122223"); + assert_ptr_equal(b + 3, strchr(b, 'b')); +} + +#pragma mark - Public Functions - + +int strchr_tests(void) +{ + const struct CMUnitTest strchr_tests[] = { + cmocka_unit_test(strchr_test), + }; + + return cmocka_run_group_tests(strchr_tests, NULL, NULL); +} diff --git a/test/testcase/string/strcmp.c b/test/testcase/string/strcmp.c new file mode 100644 index 0000000..96be64f --- /dev/null +++ b/test/testcase/string/strcmp.c @@ -0,0 +1,44 @@ +/* + * Copyright © 2017 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ + +#include "string_tests.h" +#include + +// Cmocka needs these +// clang-format off +#include +#include +#include +#include +// clang-format on + +static void strcmp_test(void** state) +{ + const char* s = "abc 123"; + + assert_int_equal(strcmp("abc", "abc"), 0); + assert_int_not_equal(strcmp(s, "abc"), 0); + assert_int_not_equal(strcmp("abc", s), 0); + assert_int_not_equal(strcmp("abc", NULL), 0); + assert_int_not_equal(strcmp(NULL, "abc"), 0); + + // Check that two NULL strings will match + assert_int_equal(strcmp(NULL, NULL), 0); + + // Check directionality of return + assert_int_equal(!!(strcmp(s, "abc") > 0), 1); + assert_int_equal(!!(strcmp("abc", s) < 0), 1); +} + +#pragma mark - Public Functions - + +int strcmp_tests(void) +{ + const struct CMUnitTest strcmp_tests[] = { + cmocka_unit_test(strcmp_test), + }; + + return cmocka_run_group_tests(strcmp_tests, NULL, NULL); +} diff --git a/test/testcase/string/strcpy.c b/test/testcase/string/strcpy.c new file mode 100644 index 0000000..1fe008d --- /dev/null +++ b/test/testcase/string/strcpy.c @@ -0,0 +1,64 @@ +/* + * Copyright © 2017 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ + +#include "string_tests.h" +#include + +// Cmocka needs these +// clang-format off +#include +#include +#include +#include +// clang-format on + +static void strcpy_test(void** state) +{ + char b[32]; + char* s; + b[16] = 'a'; + b[17] = 'b'; + b[18] = 'c'; + b[19] = 0; + + s = strcpy(b, b + 16); + assert_ptr_equal(s, b); + assert_int_equal(strcmp(s, "abc"), 0); + + s = strcpy(b + 1, b + 16); + assert_ptr_equal(s, b + 1); + assert_int_equal(strcmp(s, "abc"), 0); + + s = strcpy(b + 2, b + 16); + assert_ptr_equal(s, b + 2); + assert_int_equal(strcmp(s, "abc"), 0); + + s = strcpy(b + 3, b + 16); + assert_ptr_equal(s, b + 3); + assert_int_equal(strcmp(s, "abc"), 0); + + s = strcpy(b + 1, b + 17); + assert_ptr_equal(s, b + 1); + assert_int_equal(strcmp(s, "bc"), 0); + + s = strcpy(b + 2, b + 18); + assert_ptr_equal(s, b + 2); + assert_int_equal(strcmp(s, "c"), 0); + + s = strcpy(b + 3, b + 19); + assert_ptr_equal(s, b + 3); + assert_int_equal(strcmp(s, ""), 0); +} + +#pragma mark - Public Functions - + +int strcpy_tests(void) +{ + const struct CMUnitTest strcpy_tests[] = { + cmocka_unit_test(strcpy_test), + }; + + return cmocka_run_group_tests(strcpy_tests, NULL, NULL); +} diff --git a/test/testcase/string/strdup.c b/test/testcase/string/strdup.c new file mode 100644 index 0000000..cfb064d --- /dev/null +++ b/test/testcase/string/strdup.c @@ -0,0 +1,42 @@ +/* + * Copyright © 2017 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ + +#include "string_tests.h" +#include +#include + +// Cmocka needs these +// clang-format off +#include +#include +#include +#include +// clang-format on + +static void strdup_test(void** state) +{ + const char* base = "this is a base string woo!"; + char* dup; + + dup = strdup(base); + assert_ptr_not_equal(dup, NULL); + assert_int_equal(strlen(dup), 26); + assert_int_equal(strncmp(dup, base, strlen(dup)), 0); + free(dup); + + dup = strdup(NULL); + assert_ptr_equal(dup, NULL); +} + +#pragma mark - Public Functions - + +int strdup_tests(void) +{ + const struct CMUnitTest strdup_tests[] = { + cmocka_unit_test(strdup_test), + }; + + return cmocka_run_group_tests(strdup_tests, NULL, NULL); +} diff --git a/test/testcase/string/string_tests.c b/test/testcase/string/string_tests.c new file mode 100644 index 0000000..e06ec68 --- /dev/null +++ b/test/testcase/string/string_tests.c @@ -0,0 +1,44 @@ +/* + * Copyright © 2017 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ +#include + +#include "string_tests.h" +#include + +// Cmocka needs these +// clang-format off +#include +#include +#include +#include +// clang-format on + +int string_tests(void) +{ + int overall_result = 0; + + overall_result |= memcpy_tests(); + overall_result |= memset_tests(); + overall_result |= memmem_tests(); + overall_result |= memmove_tests(); + overall_result |= memcmp_tests(); + overall_result |= strcmp_tests(); + overall_result |= strcpy_tests(); + overall_result |= strdup_tests(); + overall_result |= strlen_tests(); + overall_result |= strncmp_tests(); + overall_result |= strncpy_tests(); + overall_result |= strndup_tests(); + overall_result |= strnlen_tests(); +// overall_result |= strnstr_tests(); + overall_result |= strstr_tests(); + overall_result |= strchr_tests(); + overall_result |= strrchr_tests(); + overall_result |= strcat_tests(); + overall_result |= strncat_tests(); + overall_result |= strtok_tests(); + + return overall_result; +} diff --git a/test/testcase/string/string_tests.h b/test/testcase/string/string_tests.h new file mode 100644 index 0000000..31e4ef1 --- /dev/null +++ b/test/testcase/string/string_tests.h @@ -0,0 +1,30 @@ +/* + * Copyright © 2018 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ + +#ifndef STRING_TESTS_H_ +#define STRING_TESTS_H_ + +int memcpy_tests(void); +int memset_tests(void); +int memmem_tests(void); +int memmove_tests(void); +int memcmp_tests(void); +int strcmp_tests(void); +int strcpy_tests(void); +int strdup_tests(void); +int strlen_tests(void); +int strncmp_tests(void); +int strncpy_tests(void); +int strndup_tests(void); +int strnlen_tests(void); +//int strnstr_tests(void); +int strstr_tests(void); +int strchr_tests(void); +int strrchr_tests(void); +int strncat_tests(void); +int strcat_tests(void); +int strtok_tests(void); + +#endif // STRING_TESTS_H_ diff --git a/test/testcase/string/strlen.c b/test/testcase/string/strlen.c new file mode 100644 index 0000000..7801a4f --- /dev/null +++ b/test/testcase/string/strlen.c @@ -0,0 +1,34 @@ +/* + * Copyright © 2017 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ + +#include "string_tests.h" +#include + +// Cmocka needs these +// clang-format off +#include +#include +#include +#include +// clang-format on + +static void strlen_test(void** state) +{ + assert_int_equal(strlen(""), 0); + assert_int_equal(strlen("a"), 1); + assert_int_equal(strlen("ab"), 2); + assert_int_equal(strlen("abasildjfaskjdf;askdfuoisudfoiajsdfaf"), 37); +} + +#pragma mark - Public Functions - + +int strlen_tests(void) +{ + const struct CMUnitTest strlen_tests[] = { + cmocka_unit_test(strlen_test), + }; + + return cmocka_run_group_tests(strlen_tests, NULL, NULL); +} diff --git a/test/testcase/string/strncat.c b/test/testcase/string/strncat.c new file mode 100644 index 0000000..f7f2ad1 --- /dev/null +++ b/test/testcase/string/strncat.c @@ -0,0 +1,42 @@ +/* + * Copyright © 2017 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ + +#include "string_tests.h" +#include + +// Cmocka needs these +// clang-format off +#include +#include +#include +#include +// clang-format on + +static void strncat_test(void** state) +{ + char b[32]; + strcpy(b, "abc"); + + // The following tests intentionally use a length < strlen("123456") + // To test what strncat does in such a situation + assert_ptr_equal(strncat(b, "123456", 3), b); + + // Check if strncat failed to null-terminate + assert_int_equal(b[6], 0); + + // Check if the string is correct + assert_int_equal(strcmp(b, "abc123"), 0); +} + +#pragma mark - Public Functions - + +int strncat_tests(void) +{ + const struct CMUnitTest strncat_tests[] = { + cmocka_unit_test(strncat_test), + }; + + return cmocka_run_group_tests(strncat_tests, NULL, NULL); +} diff --git a/test/testcase/string/strncmp.c b/test/testcase/string/strncmp.c new file mode 100644 index 0000000..118e62c --- /dev/null +++ b/test/testcase/string/strncmp.c @@ -0,0 +1,35 @@ +/* + * Copyright © 2017 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ + +#include "string_tests.h" +#include + +// Cmocka needs these +// clang-format off +#include +#include +#include +#include +// clang-format on + +static void strncmp_test(void** state) +{ + // Check if strncmp compares past n + assert_int_equal(strncmp("abcd", "abce", 3), 0); + + // Check if strncmp fails to compare n-1st byte + assert_int_equal(!!strncmp("abc", "abd", 3), 1); +} + +#pragma mark - Public Functions - + +int strncmp_tests(void) +{ + const struct CMUnitTest strncmp_tests[] = { + cmocka_unit_test(strncmp_test), + }; + + return cmocka_run_group_tests(strncmp_tests, NULL, NULL); +} diff --git a/test/testcase/string/strncpy.c b/test/testcase/string/strncpy.c new file mode 100644 index 0000000..c7e8f12 --- /dev/null +++ b/test/testcase/string/strncpy.c @@ -0,0 +1,55 @@ +/* + * Copyright © 2017 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ + +#include "string_tests.h" +#include + +// Cmocka needs these +// clang-format off +#include +#include +#include +#include +// clang-format on + +static void strncpy_test(void** state) +{ + char b[32]; + b[16] = 'a'; + b[17] = 'b'; + b[18] = 'c'; + b[19] = 0; + + // Check return values + assert_ptr_equal(memset(b, 'x', sizeof b), b); + assert_ptr_equal(strncpy(b, "abc", sizeof b - 1), b); + + // Check if strncpy fails to zero-pad dest + assert_int_equal(memcmp(b, "abc\0\0\0\0", 8), 0); + + // Check if strncpy overruns buffer when n > strlen(src) + assert_int_not_equal(b[sizeof b - 1], 0); + + b[3] = 'x'; + b[4] = 0; + strncpy(b, "abc", 3); + + // Check if strncpy fails to copy last byte + assert_int_equal(b[2], 'c'); + + // Check if strncpy overruns buffer to null-terminate + assert_int_equal(b[3], 'x'); +} + +#pragma mark - Public Functions - + +int strncpy_tests(void) +{ + const struct CMUnitTest strncpy_tests[] = { + cmocka_unit_test(strncpy_test), + }; + + return cmocka_run_group_tests(strncpy_tests, NULL, NULL); +} diff --git a/test/testcase/string/strndup.c b/test/testcase/string/strndup.c new file mode 100644 index 0000000..f50db04 --- /dev/null +++ b/test/testcase/string/strndup.c @@ -0,0 +1,60 @@ +/* + * Copyright © 2017 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ + +#include "string_tests.h" +#include +#include + +// Cmocka needs these +// clang-format off +#include +#include +#include +#include +// clang-format on + +static void strndup_test(void** state) +{ + const char* base = "this is a base string woo!"; + char* dup; + + dup = strndup(base, 3); + assert_ptr_not_equal(dup, NULL); + assert_int_equal(strlen(dup), 3); + assert_int_equal(strncmp(dup, base, strlen(dup)), 0); + free(dup); + + dup = strndup(base, strlen(base)); + assert_ptr_not_equal(dup, NULL); + assert_int_equal(strlen(dup), 26); + assert_int_equal(strncmp(dup, base, strlen(base)), 0); + free(dup); + + dup = strndup(base, strlen(base) + 10); + assert_ptr_not_equal(dup, NULL); + assert_int_equal(strlen(dup), 26); + assert_int_equal(strncmp(dup, base, strlen(base)), 0); + free(dup); + + dup = strndup(NULL, 10); + assert_ptr_equal(dup, NULL); + + dup = strndup(base, SIZE_MAX); + assert_ptr_not_equal(dup, NULL); + assert_int_equal(strlen(dup), 26); + assert_int_equal(strncmp(dup, base, strlen(base)), 0); + free(dup); +} + +#pragma mark - Public Functions - + +int strndup_tests(void) +{ + const struct CMUnitTest strndup_tests[] = { + cmocka_unit_test(strndup_test), + }; + + return cmocka_run_group_tests(strndup_tests, NULL, NULL); +} diff --git a/test/testcase/string/strnlen.c b/test/testcase/string/strnlen.c new file mode 100644 index 0000000..f5cedbe --- /dev/null +++ b/test/testcase/string/strnlen.c @@ -0,0 +1,38 @@ +/* + * Copyright © 2017 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ + +#include "string_tests.h" +#include +#include + +// Cmocka needs these +// clang-format off +#include +#include +#include +#include +// clang-format on + +static void strnlen_test(void** state) +{ + assert_int_equal(strnlen("", 1), 0); + assert_int_equal(strnlen("a", 1), 1); + assert_int_equal(strnlen("a", 2), 1); + assert_int_equal(strnlen("ab", 1), 1); + assert_int_equal(strnlen("ab", SIZE_MAX), 2); + assert_int_equal(strnlen("ab", (size_t)-2), 2); + assert_int_equal(strnlen("ab", 0), 0); +} + +#pragma mark - Public Functions - + +int strnlen_tests(void) +{ + const struct CMUnitTest strnlen_tests[] = { + cmocka_unit_test(strnlen_test), + }; + + return cmocka_run_group_tests(strnlen_tests, NULL, NULL); +} diff --git a/test/testcase/string/strnstr.c b/test/testcase/string/strnstr.c new file mode 100644 index 0000000..08df6d1 --- /dev/null +++ b/test/testcase/string/strnstr.c @@ -0,0 +1,45 @@ +// /* +// * Copyright © 2017 Embedded Artistry LLC. +// * License: MIT. See LICENSE file for details. +// */ + +// #include "string_tests.h" +// #include + +// // Cmocka needs these +// // clang-format off +// #include +// #include +// #include +// #include +// // clang-format on + +// static void strnstr_test(void** state) +// { +// (void)state; +// char buf[10] = "man tees"; + +// char* r = strnstr(buf, "tees", 10); +// assert_string_equal(r, "tees"); +// } + +// static void strnstr_test_null(void** state) +// { +// (void)state; +// char buf[10] = "man tees"; + +// char* r = strnstr(buf, "te", 5); +// assert_null(r); +// } + +// #pragma mark - Public Functions - + +// int strnstr_tests(void) +// { +// const struct CMUnitTest strnstr_tests[] = { +// cmocka_unit_test(strnstr_test), +// cmocka_unit_test(strnstr_test_null), +// }; + +// return cmocka_run_group_tests(strnstr_tests, NULL, NULL); +// } diff --git a/test/testcase/string/strrchr.c b/test/testcase/string/strrchr.c new file mode 100644 index 0000000..455988f --- /dev/null +++ b/test/testcase/string/strrchr.c @@ -0,0 +1,35 @@ +/* + * Copyright © 2017 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ + +#include "string_tests.h" +#include + +// Cmocka needs these +// clang-format off +#include +#include +#include +#include +// clang-format on + +#pragma mark - Definitions - + +static void strrchr_test(void** state) +{ + char b[32]; + strcpy(b, "aaababccdd0001122223"); + assert_ptr_equal(b + 5, strrchr(b, 'b')); +} + +#pragma mark - Public Functions - + +int strrchr_tests(void) +{ + const struct CMUnitTest strrchr_tests[] = { + cmocka_unit_test(strrchr_test), + }; + + return cmocka_run_group_tests(strrchr_tests, NULL, NULL); +} diff --git a/test/testcase/string/strstr.c b/test/testcase/string/strstr.c new file mode 100644 index 0000000..a27eaf6 --- /dev/null +++ b/test/testcase/string/strstr.c @@ -0,0 +1,82 @@ +/* + * Copyright © 2017 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ + +#include "string_tests.h" +#include +#include + +// Cmocka needs these +// clang-format off +#include +#include +#include +#include +// clang-format on + +#pragma mark - Definitions - + +#define N(s, sub) \ + { \ + const char* p = s; \ + char* q = strstr(p, sub); \ + assert_ptr_equal(q, NULL); \ + } + +#define T(s, sub, n) \ + { \ + const char* p = s; \ + char* q = strstr(p, sub); \ + assert_ptr_not_equal(q, NULL); \ + assert_int_equal((intptr_t)(q - p), (intptr_t)n); \ + } + +static void strstr_test(void** state) +{ + N("", "a") + N("a", "aa") + N("a", "b") + N("aa", "ab") + N("aa", "aaa") + N("abba", "aba") + N("abc abc", "abcd") + N("0-1-2-3-4-5-6-7-8-9", "-3-4-56-7-8-") + N("0-1-2-3-4-5-6-7-8-9", "-3-4-5+6-7-8-") + N("_ _ _\xff_ _ _", "_\x7f_") + N("_ _ _\x7f_ _ _", "_\xff_") + + T("", "", 0) + T("abcd", "", 0) + T("abcd", "a", 0) + T("abcd", "b", 1) + T("abcd", "c", 2) + T("abcd", "d", 3) + T("abcd", "ab", 0) + T("abcd", "bc", 1) + T("abcd", "cd", 2) + T("ababa", "baba", 1) + T("ababab", "babab", 1) + T("abababa", "bababa", 1) + T("abababab", "bababab", 1) + T("ababababa", "babababa", 1) + T("abbababab", "bababa", 2) + T("abbababab", "ababab", 3) + T("abacabcabcab", "abcabcab", 4) + T("nanabanabanana", "aba", 3) + T("nanabanabanana", "ban", 4) + T("nanabanabanana", "anab", 1) + T("nanabanabanana", "banana", 8) + T("_ _\xff_ _", "_\xff_", 2) +} + +#pragma mark - Public Functions - + +int strstr_tests(void) +{ + const struct CMUnitTest strstr_tests[] = { + cmocka_unit_test(strstr_test), + }; + + return cmocka_run_group_tests(strstr_tests, NULL, NULL); +} diff --git a/test/testcase/string/strtok.c b/test/testcase/string/strtok.c new file mode 100644 index 0000000..2cbb148 --- /dev/null +++ b/test/testcase/string/strtok.c @@ -0,0 +1,50 @@ +/* + * Copyright © 2017 Embedded Artistry LLC. + * License: MIT. See LICENSE file for details. + */ + +#include "string_tests.h" +#include + +// Cmocka needs these +// clang-format off +#include +#include +#include +#include +// clang-format on + +static void strtok_test(void** state) +{ + char b[32]; + char* s; + + strcpy(b, "abc 123; xyz; foo"); + + s = strtok(b, " "); + assert_ptr_equal(s, b); + assert_int_equal(strcmp(s, "abc"), 0); + + s = strtok(NULL, ";"); + assert_ptr_equal(s, b + 4); + assert_int_equal(strcmp(s, " 123"), 0); + + s = strtok(NULL, " ;"); + assert_ptr_equal(s, b + 11); + assert_int_equal(strcmp(s, "xyz"), 0); + + s = strtok(NULL, " ;"); + assert_ptr_equal(s, b + 16); + assert_int_equal(strcmp(s, "foo"), 0); +} + +#pragma mark - Public Functions - + +int strtok_tests(void) +{ + const struct CMUnitTest strtok_tests[] = { + cmocka_unit_test(strtok_test), + }; + + return cmocka_run_group_tests(strtok_tests, NULL, NULL); +} diff --git a/test/testcase/tests.h b/test/testcase/tests.h new file mode 100644 index 0000000..ac6e627 --- /dev/null +++ b/test/testcase/tests.h @@ -0,0 +1,8 @@ +#ifndef TEST_H__ +#define TEST_H__ + +int ctype_tests(void); +int string_tests(void); + + +#endif // TEST_H_ diff --git a/xscript/mlibc-config.lua b/xscript/mlibc-config.lua index 878d292..9bc1c58 100644 --- a/xscript/mlibc-config.lua +++ b/xscript/mlibc-config.lua @@ -53,6 +53,7 @@ target("mlibc") add_files(path.join(project_path, "src/misc/*.c")) add_files(path.join(project_path, "src/stdio/*.c")) add_files(path.join(project_path, "src/stdlib/*.c")) + add_files(path.join(project_path, "src/string/*.c")) add_files(path.join(project_path, "src/time/*.c")) -- Add header file directory add_includedirs(path.join(project_path, "./include"), {public = true}) @@ -72,4 +73,23 @@ target("mlibc") os.cp(path.join(project_path, "include"), path.join(project_path, "mlibc")) os.cp(path.join(project_path, TARGET_DIR, config.target, "libmlibc.a"), "mlibc/lib/libc.a") end) +target_end() + +target("mlibc_hosted") + -- Set target file type as static library + set_kind("static") + -- Strip all information + set_strip("all") + -- Set as default target + set_default(true) + -- Set languages standard + set_languages("c99", "cxx11") + -- Add all source files + add_files(path.join(project_path, "test/string/*.c")) + -- Add header file directory + add_includedirs(path.join(project_path, "test/include"), {public = true}) + on_load(function (target) + target:set("targetdir", TARGET_DIR .. config.target) + end) + target_end() \ No newline at end of file diff --git a/xscript/test-config.lua b/xscript/test-config.lua new file mode 100644 index 0000000..d77ace3 --- /dev/null +++ b/xscript/test-config.lua @@ -0,0 +1,37 @@ +add_requires("cmocka") + +local project_path = os.projectdir() + +-- 定义测试范围选项 +option("test-cover") + set_default("all") + set_showmenu(true) + set_description("Select test coverage areas (comma-separated: all,ctype,stdlib,string)") + set_values("all", "ctype") +option_end() + +target("mlibc-test") + set_kind("binary") + add_packages("cmocka") + add_includedirs(path.join(project_path, "test/testcase")) + add_deps("mlibc_hosted") + + -- 根据测试覆盖范围选择源文件 + local test_cover = get_config("test-cover") or "all" + + -- 统一处理'all'特殊值 + if test_cover == "all" then + add_files(path.join(project_path, "test/testcase/**.c")) + else + add_files(path.join(path.join(project_path, "test/testcase/", test_cover , "/*.c"))) + end + + -- 生成链接器映射文件 + add_ldflags("-W",{force = true}) + + -- GCC/Clang 编译器标志 + add_cflags("-Wno-stringop-overflow", "-Wno-unused-parameter", + "-Wno-nonnull-compare", "-Wno-nonnull", + "-Wno-stringop-truncation", "-Wno-unknown-pragmas", + {force = true}) +