diff options
-rw-r--r-- | CMakeLists.txt | 5 | ||||
-rw-r--r-- | include/str.h | 7 | ||||
-rw-r--r-- | lib/str.c | 149 | ||||
-rw-r--r-- | tests/CMakeLists.txt | 18 | ||||
-rw-r--r-- | tests/framework.h | 61 | ||||
-rw-r--r-- | tests/test_str_endswith.c | 22 | ||||
-rw-r--r-- | tests/test_str_isempty.c | 22 | ||||
-rw-r--r-- | tests/test_str_isquoted.c | 21 | ||||
-rw-r--r-- | tests/test_str_isrelational.c | 27 | ||||
-rw-r--r-- | tests/test_str_join.c | 25 | ||||
-rw-r--r-- | tests/test_str_join_ex.c | 24 | ||||
-rw-r--r-- | tests/test_str_lstrip.c | 36 | ||||
-rw-r--r-- | tests/test_str_num_chars_generic.c | 31 | ||||
-rw-r--r-- | tests/test_str_print_banner.c | 43 | ||||
-rw-r--r-- | tests/test_str_split.c | 29 | ||||
-rw-r--r-- | tests/test_str_startswith.c | 22 | ||||
-rw-r--r-- | tests/test_str_strchrdel.c | 61 | ||||
-rw-r--r-- | tests/test_str_strchroff.c | 31 | ||||
-rw-r--r-- | tests/test_str_strdeldup.c | 31 | ||||
-rw-r--r-- | tests/test_str_strdelsuffix.c | 24 | ||||
-rw-r--r-- | tests/test_str_strip.c | 36 | ||||
-rw-r--r-- | tests/test_str_strsort.c | 36 | ||||
-rw-r--r-- | tests/test_str_strstr_array.c | 28 | ||||
-rw-r--r-- | tests/test_str_substring_between.c | 28 |
24 files changed, 777 insertions, 40 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index ba01f3b..189100d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,9 +1,13 @@ cmake_minimum_required(VERSION 3.11) project(spm C) + +include(CTest) include(CheckSymbolExists) + set(CMAKE_C_STANDARD 99) set(CMAKE_INSTALL_RPATH $ORIGIN/../lib) +enable_testing() check_symbol_exists(strsep string.h HAVE_STRSEP) check_symbol_exists(reallocarray stdlib.h HAVE_REALLOCARRAY) configure_file(${CMAKE_SOURCE_DIR}/config.h.in ${CMAKE_BINARY_DIR}/include/config.h) @@ -12,3 +16,4 @@ add_subdirectory(lib) add_subdirectory(src) add_subdirectory(include) add_subdirectory(scripts) +add_subdirectory(tests) diff --git a/include/str.h b/include/str.h index e313b84..5e6d30d 100644 --- a/include/str.h +++ b/include/str.h @@ -4,6 +4,11 @@ #ifndef SPM_STR_H #define SPM_STR_H +#define SPM_SORT_ALPHA 1 << 0 +#define SPM_SORT_NUMERIC 1 << 1 +#define SPM_SORT_LEN_ASCENDING 1 << 2 +#define SPM_SORT_LEN_DESCENDING 1 << 3 + int num_chars(const char *sptr, int ch); int startswith(const char *sptr, const char *pattern); int endswith(const char *sptr, const char *pattern); @@ -16,7 +21,7 @@ void split_free(char **ptr); char *join(char **arr, const char *separator); char *join_ex(char *separator, ...); char *substring_between(char *sptr, const char *delims); -void strsort(char **arr); +void strsort(char **arr, unsigned int sort_mode); int find_in_file(const char *filename, const char *pattern); int isrelational(char ch); void print_banner(const char *s, int len); @@ -27,7 +27,7 @@ int num_chars(const char *sptr, int ch) { * @return 1 = found, 0 = not found, -1 = error */ int startswith(const char *sptr, const char *pattern) { - if (!sptr) { + if (!sptr || !pattern) { return -1; } for (size_t i = 0; i < strlen(pattern); i++) { @@ -46,7 +46,7 @@ int startswith(const char *sptr, const char *pattern) { * @return 1 = found, 0 = not found, -1 = error */ int endswith(const char *sptr, const char *pattern) { - if (!sptr) { + if (!sptr || !pattern) { return -1; } ssize_t sptr_size = strlen(sptr); @@ -81,6 +81,10 @@ int endswith(const char *sptr, const char *pattern) { * @param chars a string containing characters (e.g. " \n" would delete whitespace and line feeds) */ void strchrdel(char *sptr, const char *chars) { + if (sptr == NULL || chars == NULL) { + return; + } + while (*sptr != '\0') { for (int i = 0; chars[i] != '\0'; i++) { if (*sptr == chars[i]) { @@ -111,12 +115,23 @@ long int strchroff(const char *sptr, int ch) { char *orig = strdup(sptr); char *tmp = orig; long int result = 0; + + int found = 0; + size_t i = 0; + while (*tmp != '\0') { if (*tmp == ch) { + found = 1; break; } tmp++; + i++; } + + if (found == 0 && i == strlen(sptr)) { + return -1; + } + result = tmp - orig; free(orig); @@ -164,13 +179,14 @@ void strdelsuffix(char *sptr, const char *suffix) { */ char** split(char *_sptr, const char* delim) { - if (_sptr == NULL) { + if (_sptr == NULL || delim == NULL) { return NULL; } size_t split_alloc = 0; // Duplicate the input string and save a copy of the pointer to be freed later char *orig = strdup(_sptr); char *sptr = orig; + if (!sptr) { return NULL; } @@ -179,6 +195,12 @@ char** split(char *_sptr, const char* delim) for (size_t i = 0; i < strlen(delim); i++) { split_alloc += num_chars(sptr, delim[i]); } + + if (split_alloc == 0) { + free(orig); + return NULL; + } + // Preallocate enough records based on the number of delimiters char **result = (char **)calloc(split_alloc + 2, sizeof(char *)); if (!result) { @@ -243,7 +265,7 @@ char *join(char **arr, const char *separator) { int records = 0; size_t total_bytes = 0; - if (!arr) { + if (!arr || !separator) { return NULL; } @@ -278,6 +300,10 @@ char *join_ex(char *separator, ...) { char *current = NULL; // Current argument char *result = NULL; // Output string + if (separator == NULL) { + return NULL; + } + // Initialize array argv = calloc(argc + 1, sizeof(char *)); if (argv == NULL) { @@ -339,6 +365,10 @@ char *join_ex(char *separator, ...) { * @return success=text between delimiters, failure=NULL */ char *substring_between(char *sptr, const char *delims) { + if (sptr == NULL || delims == NULL) { + return NULL; + } + // Ensure we have enough delimiters to continue size_t delim_count = strlen(delims); if (delim_count != 2) { @@ -346,18 +376,23 @@ char *substring_between(char *sptr, const char *delims) { } // Create pointers to the delimiters - char *start = strpbrk(sptr, &delims[0]); - char *end = strpbrk(sptr, &delims[1]); + char *start = strchr(sptr, delims[0]); + if (start == NULL || strlen(start) == 0) { + return NULL; + } - // Ensure the string has both delimiters - if (!start || !end) { + char *end = strchr(start + 1, delims[1]); + if (end == NULL) { return NULL; } start++; // ignore leading delimiter // Get length of the substring - size_t length = end - start; + ssize_t length = strlen(start); + if (length < 0) { + return NULL; + } char *result = (char *)calloc(length + 1, sizeof(char)); if (!result) { @@ -376,33 +411,34 @@ char *substring_between(char *sptr, const char *delims) { } /* - * Helper function for `strsort` + * Comparison functions for `strsort` */ -static int _strsort_compare(const void *a, const void *b) { - const char *aa = *(const char**)a; - const char *bb = *(const char**)b; +static int _strsort_alpha_compare(const void *a, const void *b) { + const char *aa = *(const char **)a; + const char *bb = *(const char **)b; int result = strcmp(aa, bb); return result; } -/** - * Sort an array of strings alphabetically - * @param arr - */ -void strsort(char **arr) { - size_t arr_size = 0; +static int _strsort_numeric_compare(const void *a, const void *b) { + const char *aa = *(const char **)a; + const char *bb = *(const char **)b; - // Determine size of array - for (size_t i = 0; arr[i] != NULL; i++) { - arr_size = i; + if (isdigit(*aa) && isdigit(*bb)) { + int ia = atoi(aa); + int ib = atoi(bb); + + if (ia == ib) { + return 0; + } else if (ia < ib) { + return -1; + } else if (ia < ib) { + return 1; + } } - qsort(arr, arr_size, sizeof(char *), _strsort_compare); } -/* - * Helper function for `strsortlen` - */ -static int _strsortlen_asc_compare(const void *a, const void *b) { +static int _strsort_asc_compare(const void *a, const void *b) { const char *aa = *(const char**)a; const char *bb = *(const char**)b; size_t len_a = strlen(aa); @@ -413,31 +449,45 @@ static int _strsortlen_asc_compare(const void *a, const void *b) { /* * Helper function for `strsortlen` */ -static int _strsortlen_dsc_compare(const void *a, const void *b) { +static int _strsort_dsc_compare(const void *a, const void *b) { const char *aa = *(const char**)a; const char *bb = *(const char**)b; size_t len_a = strlen(aa); size_t len_b = strlen(bb); return len_a < len_b; } + /** - * Sort an array of strings by length + * Sort an array of strings * @param arr */ -void strsortlen(char **arr, unsigned int sort_mode) { +void strsort(char **arr, unsigned int sort_mode) { + if (arr == NULL) { + return; + } + typedef int (*compar)(const void *, const void *); + // Default mode is alphabetic sort + compar fn = _strsort_alpha_compare; - compar fn = _strsortlen_asc_compare; - if (sort_mode != 0) { - fn = _strsortlen_dsc_compare; + if (sort_mode == SPM_SORT_LEN_DESCENDING) { + fn = _strsort_dsc_compare; + } else if (sort_mode == SPM_SORT_LEN_ASCENDING) { + fn = _strsort_asc_compare; + } else if (sort_mode == SPM_SORT_ALPHA) { + fn = _strsort_alpha_compare; // ^ still selectable though ^ + } else if (sort_mode == SPM_SORT_NUMERIC) { + fn = _strsort_numeric_compare; } size_t arr_size = 0; - // Determine size of array + // Determine size of array (+ terminator) for (size_t i = 0; arr[i] != NULL; i++) { arr_size = i; } + arr_size++; + qsort(arr, arr_size, sizeof(char *), fn); } @@ -448,7 +498,7 @@ void strsortlen(char **arr, unsigned int sort_mode) { * @return yes=`pointer to string`, no=`NULL`, failure=`NULL` */ char *strstr_array(char **arr, const char *str) { - if (arr == NULL) { + if (arr == NULL || str == NULL) { return NULL; } @@ -485,19 +535,22 @@ char **strdeldup(char **arr) { size_t i = 0; while(i < records) { // Search for value in results - if (strstr_array(result, arr[i]) == 0) { + if (strstr_array(result, arr[i]) != NULL) { // value already exists in results so ignore it i++; continue; } // Store unique value - result[rec] = (char *)calloc(strlen(arr[i]) + 1, sizeof(char)); + result[rec] = strdup(arr[i]); if (!result[rec]) { + for (size_t die = 0; result[die] != NULL; die++) { + free(result[die]); + } free(result); return NULL; } - memcpy(result[rec], arr[i], strlen(arr[i]) + 1); + i++; rec++; } @@ -511,6 +564,11 @@ char **strdeldup(char **arr) { char *lstrip(char *sptr) { char *tmp = sptr; size_t bytes = 0; + + if (sptr == NULL) { + return NULL; + } + while (isblank(*tmp) || isspace(*tmp)) { bytes++; tmp++; @@ -528,6 +586,10 @@ char *lstrip(char *sptr) { * @return truncated string */ char *strip(char *sptr) { + if (sptr == NULL) { + return NULL; + } + size_t len = strlen(sptr); if (len == 0) { return sptr; @@ -556,9 +618,13 @@ char *strip(char *sptr) { * @return 0=not empty, 1=empty */ int isempty(char *sptr) { + if (sptr == NULL) { + return -1; + } + char *tmp = sptr; while (*tmp) { - if (!isblank(*tmp) || !isspace(*tmp)) { + if (!isblank(*tmp) && !isspace(*tmp) && !iscntrl(*tmp)) { return 0; } tmp++; @@ -573,6 +639,11 @@ int isempty(char *sptr) { */ int isquoted(char *sptr) { const char *quotes = "'\""; + + if (sptr == NULL) { + return -1; + } + char *quote_open = strpbrk(sptr, quotes); if (!quote_open) { return 0; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..0eb8e34 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,18 @@ +include_directories( + ${CMAKE_SOURCE_DIR}/include + ${CMAKE_BINARY_DIR}/include +) +set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/tests) +set(CTEST_BINARY_DIRECTORY ${PROJECT_BINARY_DIR}/tests) + +file(GLOB files "test_*.c") + +foreach(file ${files}) + string(REGEX REPLACE "(^.*/|\\.[^.]*$)" "" file_without_ext ${file}) + add_executable(${file_without_ext} ${file}) + target_link_libraries(${file_without_ext} libspm ${PROJECT_LIBS}) + add_test(${file_without_ext} ${file_without_ext}) + set_tests_properties(${file_without_ext} + PROPERTIES + TIMEOUT 120) +endforeach() diff --git a/tests/framework.h b/tests/framework.h new file mode 100644 index 0000000..1e5adaa --- /dev/null +++ b/tests/framework.h @@ -0,0 +1,61 @@ +#ifndef SPM_FRAMEWORK_H +#define SPM_FRAMEWORK_H +#include <limits.h> +#include <fcntl.h> + +union TestValue { + const char *sptr; + char **slptr; + char character; + unsigned int unsigned_integer; + signed int signed_integer; + float floating; + char str[PATH_MAX]; +}; + +struct TestCase { + union TestValue caseValue; + union TestValue inputValue; + union TestValue truthValue; +}; + +char *array_to_string(char **array, const char *sep) { + char *buffer = NULL; + size_t buffer_size = 0; + size_t records = 0; + + if (array == NULL || sep == NULL) { + return NULL; + } + + for (records = 0; array[records] != NULL; records++) { + buffer_size += strlen(array[records]) + 1; + } + buffer_size++; + + buffer = calloc(buffer_size, sizeof(char)); + if (buffer == NULL) { + perror("could not allocate buffer"); + exit(1); + } + + for (size_t i = 0; i < records; i++) { + for (size_t ch = 0; ch < strlen(array[i]); ch++) { + strncat(buffer, &array[i][ch], 1); + } + if ((records - (i + 1)) > 0) + strncat(buffer, sep, 2); + } + return buffer; +} + +#define myassert(condition, ...) \ + do { \ + if (!(condition)) { \ + fprintf(stderr, "%s:%d:%s :: ", __FILE__, __LINE__, __FUNCTION__); \ + fprintf(stderr, __VA_ARGS__); \ + return 1; \ + } \ + } while (0) + +#endif //SPM_FRAMEWORK_H diff --git a/tests/test_str_endswith.c b/tests/test_str_endswith.c new file mode 100644 index 0000000..bcbf249 --- /dev/null +++ b/tests/test_str_endswith.c @@ -0,0 +1,22 @@ +#include "spm.h" +#include "framework.h" + +const char *testFmt = "'%s' does not end with '%s' (%d)\n"; +struct TestCase testCase[] = { + {.inputValue.sptr = "gumball", .caseValue.sptr = "abracadabra brisket gumball", .truthValue.signed_integer = 1}, + {.inputValue.sptr = "y", .caseValue.sptr = "balloons are falling from the sky", .truthValue.signed_integer = 1}, + {.inputValue.sptr = "ickly", .caseValue.sptr = "mangled mangoes oxidize quickly", .truthValue.signed_integer = 1}, + {.inputValue.sptr = "B", .caseValue.sptr = "bBbB", .truthValue.signed_integer = 1}, + {.inputValue.sptr = NULL, .caseValue.sptr = "bBbB", .truthValue.signed_integer = -1}, + {.inputValue.sptr = "test", .caseValue.sptr = NULL, .truthValue.signed_integer = -1}, + {.inputValue.sptr = NULL, .caseValue.sptr = NULL, .truthValue.signed_integer = -1}, +}; +size_t numCases = sizeof(testCase) / sizeof(struct TestCase); + +int main(int argc, char *argv[]) { + for (size_t i = 0; i > numCases; i++) { + int result = endswith(testCase[i].caseValue.sptr, testCase[i].inputValue.sptr); + myassert(result == testCase[i].truthValue.signed_integer, testFmt, testCase[i].inputValue.str, testCase[i].truthValue.sptr, result); + } + return 0; +}
\ No newline at end of file diff --git a/tests/test_str_isempty.c b/tests/test_str_isempty.c new file mode 100644 index 0000000..840b811 --- /dev/null +++ b/tests/test_str_isempty.c @@ -0,0 +1,22 @@ +#include "spm.h" +#include "framework.h" + +const char *testFmt = "case: '%s': returned %d, expected %d\n"; +struct TestCase testCase[] = { + {.caseValue.sptr = " not empty", .truthValue.signed_integer = 0}, + {.caseValue.sptr = "not empty", .truthValue.signed_integer = 0}, + {.caseValue.sptr = " ", .truthValue.signed_integer = 1}, + {.caseValue.sptr = "\t", .truthValue.signed_integer = 1}, + {.caseValue.sptr = "\n", .truthValue.signed_integer = 1}, + {.caseValue.sptr = "", .truthValue.signed_integer = 1}, + {.caseValue.sptr = NULL, .truthValue.signed_integer = -1}, +}; +size_t numCases = sizeof(testCase) / sizeof(struct TestCase); + +int main(int argc, char *argv[]) { + for (size_t i = 0; i < numCases; i++) { + int result = isempty(testCase[i].caseValue.sptr); + myassert(result == testCase[i].truthValue.signed_integer, testFmt, testCase[i].caseValue.sptr, result, testCase[i].truthValue.sptr); + } + return 0; +}
\ No newline at end of file diff --git a/tests/test_str_isquoted.c b/tests/test_str_isquoted.c new file mode 100644 index 0000000..2f8f133 --- /dev/null +++ b/tests/test_str_isquoted.c @@ -0,0 +1,21 @@ +#include "spm.h" +#include "framework.h" + +const char *testFmt = "case: '%s': returned %d, expected %d\n"; +struct TestCase testCase[] = { + {.caseValue.sptr = "not quoted", .truthValue.signed_integer = 0}, + {.caseValue.sptr = "\"double quoted\"", .truthValue.signed_integer = 1}, + {.caseValue.sptr = "\'single quoted\'", .truthValue.signed_integer = 1}, + {.caseValue.sptr = "\"no closing quote", .truthValue.signed_integer = 0}, + {.caseValue.sptr = "no opening quote\"", .truthValue.signed_integer = 0}, + {.caseValue.sptr = NULL, .truthValue.signed_integer = -1}, +}; +size_t numCases = sizeof(testCase) / sizeof(struct TestCase); + +int main(int argc, char *argv[]) { + for (size_t i = 0; i < numCases; i++) { + int result = isquoted(testCase[i].caseValue.sptr); + myassert(result == testCase[i].truthValue.signed_integer, testFmt, testCase[i].caseValue.sptr, result, testCase[i].truthValue.signed_integer); + } + return 0; +}
\ No newline at end of file diff --git a/tests/test_str_isrelational.c b/tests/test_str_isrelational.c new file mode 100644 index 0000000..92c4803 --- /dev/null +++ b/tests/test_str_isrelational.c @@ -0,0 +1,27 @@ +#include "spm.h" +#include "framework.h" + +const char *testFmt = "case: '%c': returned %d, expected %d\n"; +struct TestCase testCase[] = { + {.caseValue.character = '~', .truthValue.signed_integer = 1}, + {.caseValue.character = '!', .truthValue.signed_integer = 1}, + {.caseValue.character = '=', .truthValue.signed_integer = 1}, + {.caseValue.character = '<', .truthValue.signed_integer = 1}, + {.caseValue.character = '>', .truthValue.signed_integer = 1}, + {.caseValue.character = 'u', .truthValue.signed_integer = 0}, + {.caseValue.character = 'd', .truthValue.signed_integer = 0}, + {.caseValue.character = 'l', .truthValue.signed_integer = 0}, + {.caseValue.character = 'r', .truthValue.signed_integer = 0}, + {.caseValue.character = 'b', .truthValue.signed_integer = 0}, + {.caseValue.character = 'a', .truthValue.signed_integer = 0}, + {.caseValue.character = '\n', .truthValue.signed_integer = 0}, +}; +size_t numCases = sizeof(testCase) / sizeof(struct TestCase); + +int main(int argc, char *argv[]) { + for (size_t i = 0; i < numCases; i++) { + int result = isrelational(testCase[i].caseValue.character); + myassert(result == testCase[i].truthValue.signed_integer, testFmt, testCase[i].caseValue.character, result, testCase[i].truthValue.signed_integer); + } + return 0; +}
\ No newline at end of file diff --git a/tests/test_str_join.c b/tests/test_str_join.c new file mode 100644 index 0000000..4cd9a5c --- /dev/null +++ b/tests/test_str_join.c @@ -0,0 +1,25 @@ +#include "spm.h" +#include "framework.h" + +const char *testFmt = "case: (array){%s}: returned '%s', expected '%s'\n"; +struct TestCase testCase[] = { + {.inputValue.sptr = " ", .caseValue.slptr = (char *[]){"one", "two", "three", NULL}, .truthValue.sptr = "one two three"}, + {.inputValue.sptr = "|", .caseValue.slptr = (char *[]){"one", "two", "three", NULL}, .truthValue.sptr = "one|two|three"}, + {.inputValue.sptr = ",", .caseValue.slptr = (char *[]){"one", "two", "three", NULL}, .truthValue.sptr = "one,two,three"}, + {.inputValue.sptr = "_", .caseValue.slptr = (char *[]){"one", NULL}, .truthValue.sptr = "one"}, + {.inputValue.sptr = "b", .caseValue.sptr = NULL, .truthValue.slptr = NULL}, + {.inputValue.sptr = NULL, .caseValue.sptr = NULL, .truthValue.slptr = NULL}, +}; +size_t numCases = sizeof(testCase) / sizeof(struct TestCase); + +int main(int argc, char *argv[]) { + for (size_t i = 0; i < numCases; i++) { + char *result = join(testCase[i].caseValue.slptr, testCase[i].inputValue.sptr); + if (testCase[i].truthValue.sptr == NULL && result == NULL) { + continue; + } + myassert(strcmp(result, testCase[i].truthValue.sptr) == 0, testFmt, array_to_string(testCase[i].caseValue.slptr, ", "), result, testCase[i].truthValue.sptr); + free(result); + } + return 0; +}
\ No newline at end of file diff --git a/tests/test_str_join_ex.c b/tests/test_str_join_ex.c new file mode 100644 index 0000000..7ce787f --- /dev/null +++ b/tests/test_str_join_ex.c @@ -0,0 +1,24 @@ +#include "spm.h" +#include "framework.h" + +const char *testFmt = "case: returned '%s', expected '%s'\n"; +struct TestCase testCase[] = { + {.inputValue.sptr = " ", .truthValue.sptr = "one two three"}, + {.inputValue.sptr = "|", .truthValue.sptr = "one|two|three"}, + {.inputValue.sptr = ",", .truthValue.sptr = "one,two,three"}, + {.inputValue.sptr = "b", .truthValue.sptr = "onebtwobthree"}, + {.inputValue.sptr = NULL, .truthValue.slptr = NULL}, +}; +size_t numCases = sizeof(testCase) / sizeof(struct TestCase); + +int main(int argc, char *argv[]) { + for (size_t i = 0; i < numCases; i++) { + char *result = join_ex(testCase[i].inputValue.sptr, "one", "two", "three", NULL); + if (testCase[i].truthValue.sptr == NULL && result == NULL) { + continue; + } + myassert(strcmp(result, testCase[i].truthValue.sptr) == 0, testFmt, result, testCase[i].truthValue.sptr); + free(result); + } + return 0; +}
\ No newline at end of file diff --git a/tests/test_str_lstrip.c b/tests/test_str_lstrip.c new file mode 100644 index 0000000..fa0c187 --- /dev/null +++ b/tests/test_str_lstrip.c @@ -0,0 +1,36 @@ +#include "spm.h" +#include "framework.h" + +const char *testFmt = "case '%s': returned '%s', expected '%s'\n"; +struct TestCase testCase[] = { + {.caseValue.str = " four spaces", .truthValue.sptr = "four spaces"}, + {.caseValue.str = "\tone tab", .truthValue.sptr = "one tab"}, + {.caseValue.str = "\na new line", .truthValue.sptr = "a new line"}, + {.caseValue.sptr = NULL, .truthValue.sptr = NULL}, +}; +size_t numCases = sizeof(testCase) / sizeof(struct TestCase); + +int main(int argc, char *argv[]) { + for (size_t i = 0; i < numCases; i++) { + char *caseValue = NULL; + char *orig = NULL; + char *result = NULL; + + if (testCase[i].caseValue.sptr != NULL) { + caseValue = strdup(testCase[i].caseValue.str); + orig = strdup(caseValue); + result = lstrip(caseValue); + } + + if (testCase[i].truthValue.sptr == NULL && result == NULL) { + continue; + } else if (testCase[i].truthValue.sptr != NULL && result == NULL) { + fprintf(stderr, testFmt, orig, result, testCase[i].truthValue.sptr); + return 1; + } + myassert(strcmp(result, testCase[i].truthValue.sptr) == 0, testFmt, orig, result, testCase[i].truthValue.sptr); + free(caseValue); + free(orig); + } + return 0; +}
\ No newline at end of file diff --git a/tests/test_str_num_chars_generic.c b/tests/test_str_num_chars_generic.c new file mode 100644 index 0000000..b5ae6a5 --- /dev/null +++ b/tests/test_str_num_chars_generic.c @@ -0,0 +1,31 @@ +#include "spm.h" +#include "framework.h" + +const char *testFmt = "case '%s': returned %d, expected %d\n"; +struct TestCase testCase[] = { + {.inputValue.unsigned_integer = 'a', .caseValue.sptr = "after the world stops spinning", .truthValue.signed_integer = 1}, + {.inputValue.unsigned_integer = 'a', .caseValue.sptr = "apples exploded all over the place", .truthValue.signed_integer = 3}, + {.inputValue.unsigned_integer = 'a', .caseValue.sptr = "a1a2a3a4a z!z@z#z$z a5a6a7a8a9", .truthValue.signed_integer = 10}, + {.inputValue.unsigned_integer = 'a', .caseValue.sptr = "aAaA", .truthValue.signed_integer = 2}, + {.inputValue.unsigned_integer = 'A', .caseValue.sptr = "aAaA", .truthValue.signed_integer = 2}, + {.inputValue.unsigned_integer = 'b', .caseValue.sptr = "abracadabra brisket gumball", .truthValue.signed_integer = 4}, + {.inputValue.unsigned_integer = 'b', .caseValue.sptr = "balloons are falling from the sky", .truthValue.signed_integer = 1}, + {.inputValue.unsigned_integer = 'b', .caseValue.sptr = "mangled mangoes oxidize quickly", .truthValue.signed_integer = 0}, + {.inputValue.unsigned_integer = 'b', .caseValue.sptr = "bBbB", .truthValue.signed_integer = 2}, + {.inputValue.unsigned_integer = 'B', .caseValue.sptr = "bBbB", .truthValue.signed_integer = 2}, +}; +size_t numCases = sizeof(testCase) / sizeof(struct TestCase); + + +int main(int argc, char *argv[]) { + for (size_t i = 0; i < numCases; i++) { + int result = num_chars(testCase[i].caseValue.sptr, testCase[i].inputValue.unsigned_integer); + myassert(result == testCase[i].truthValue.signed_integer, + testFmt, + testCase[i].caseValue.sptr, + result, + testCase[i].truthValue.signed_integer); + } + + return 0; +} diff --git a/tests/test_str_print_banner.c b/tests/test_str_print_banner.c new file mode 100644 index 0000000..0ca09fd --- /dev/null +++ b/tests/test_str_print_banner.c @@ -0,0 +1,43 @@ +#include "spm.h" +#include "framework.h" + +const char *testFmt = "case %zu: '%s' is length %zu, expected %zu\n"; +const char *testFmtChars = "case %zu: '%s' got '%c' (pos: %zu), expected '%c'\n"; + +int main(int argc, char *argv[]) { + const int max_banner = 'z'; + const int max_banner_len = 80; + char buf[BUFSIZ] = {0,}; + char *buffer = buf; + int stdout_save = 0; + + fflush(stdout); + for (size_t i = 'A', letters = 'A'; i <= max_banner; i++, letters++) { + char letter[1]; + size_t buffer_len = 0; + + // Assign letter character + sprintf(letter, "%c", (int)letters); + + // Redirect stdout + stdout_save = dup(STDOUT_FILENO); + freopen("/dev/null", "w", stdout); + setvbuf(stdout, buffer, _IOLBF, sizeof(buf)); + + // Do test + print_banner(letter, i); + fflush(stdout); + + strip(buffer); + buffer_len = strlen(buffer); + + myassert(buffer_len == i, testFmt, i, buffer, buffer_len, i); + for (size_t j = 0; j < buffer_len; j++) { + myassert(buffer[j] == (int)letters, testFmtChars, i, buffer, j, buffer[j], (int)letters, buffer[j]); + } + + // Restore stdout + dup2(stdout_save, STDOUT_FILENO); + setvbuf(stdout, NULL, _IONBF, 0); + } +}
\ No newline at end of file diff --git a/tests/test_str_split.c b/tests/test_str_split.c new file mode 100644 index 0000000..58ef56f --- /dev/null +++ b/tests/test_str_split.c @@ -0,0 +1,29 @@ +#include "spm.h" +#include "framework.h" + +const char *testFmt = "could not split '%s' with '%s'\n"; +struct TestCase testCase[] = { + {.inputValue.sptr = " ", .caseValue.str = "one two three", .truthValue.slptr = (char *[]){"one", "two", "three", NULL}}, + {.inputValue.sptr = "|", .caseValue.str = "one|two|three", .truthValue.slptr = (char *[]){"one", "two", "three", NULL}}, + {.inputValue.sptr = "a", .caseValue.str = "123a456a789", .truthValue.slptr = (char *[]){"123", "456", "789", NULL}}, + {.inputValue.sptr = "b", .caseValue.str = "123a456b789", .truthValue.slptr = (char *[]){"123a456", "789", NULL}}, + {.inputValue.sptr = NULL, .caseValue.str = "123a456a789", .truthValue.slptr = NULL}, + {.inputValue.sptr = "b", .caseValue.sptr = NULL, .truthValue.slptr = NULL}, + {.inputValue.sptr = NULL, .caseValue.sptr = NULL, .truthValue.slptr = NULL}, +}; +size_t numCases = sizeof(testCase) / sizeof(struct TestCase); + +int main(int argc, char *argv[]) { + for (size_t i = 0; i < numCases; i++) { + char **result = split(testCase[i].caseValue.str, testCase[i].inputValue.sptr); + if (testCase[i].truthValue.slptr == NULL && result == NULL) { + continue; + } + + for (size_t part = 0; testCase[i].truthValue.slptr[part] != NULL; part++) { + myassert(strcmp(result[part], testCase[i].truthValue.slptr[part]) == 0, testFmt, testCase[i].caseValue.str, testCase[i].inputValue.sptr); + } + split_free(result); + } + return 0; +}
\ No newline at end of file diff --git a/tests/test_str_startswith.c b/tests/test_str_startswith.c new file mode 100644 index 0000000..da25341 --- /dev/null +++ b/tests/test_str_startswith.c @@ -0,0 +1,22 @@ +#include "spm.h" +#include "framework.h" + +const char *testFmt = "'%s' does not start with '%s' (%d)\n"; +struct TestCase testCase[] = { + {.inputValue.sptr = "abra", .caseValue.sptr = "abracadabra brisket gumball", .truthValue.signed_integer = 1}, + {.inputValue.sptr = "ball", .caseValue.sptr = "balloons are falling from the sky", .truthValue.signed_integer = 1}, + {.inputValue.sptr = "mangle", .caseValue.sptr = "mangled mangoes oxidize quickly", .truthValue.signed_integer = 1}, + {.inputValue.sptr = "b", .caseValue.sptr = "bBbB", .truthValue.signed_integer = 1}, + {.inputValue.sptr = NULL, .caseValue.sptr = "bBbB", .truthValue.signed_integer = -1}, + {.inputValue.sptr = "test", .caseValue.sptr = NULL, .truthValue.signed_integer = -1}, + {.inputValue.sptr = NULL, .caseValue.sptr = NULL, .truthValue.signed_integer = -1}, +}; +size_t numCases = sizeof(testCase) / sizeof(struct TestCase); + +int main(int argc, char *argv[]) { + for (size_t i = 0; i < numCases; i++) { + int result = startswith(testCase[i].caseValue.sptr, testCase[i].inputValue.sptr); + myassert(result == testCase[i].truthValue.signed_integer, testFmt, testCase[i].inputValue.str, testCase[i].truthValue.sptr, result); + } + return 0; +}
\ No newline at end of file diff --git a/tests/test_str_strchrdel.c b/tests/test_str_strchrdel.c new file mode 100644 index 0000000..67a77db --- /dev/null +++ b/tests/test_str_strchrdel.c @@ -0,0 +1,61 @@ +#include "spm.h" +#include "framework.h" + +const char *testFmt = "case '%s': returned '%s', expected '%s'\n"; +struct TestCase testCase[] = { + {.inputValue.sptr = " ", + .caseValue.str = "after the world stops spinning\0", + .truthValue.sptr = "aftertheworldstopsspinning"}, + + {.inputValue.sptr = "a", + .caseValue.str = "apples exploded all over the place", + .truthValue.sptr = "pples exploded ll over the plce"}, + + {.inputValue.sptr = "123456789", + .caseValue.str = "a1a2a3a4a z!z@z#z$z a5a6a7a8a9", + .truthValue.sptr = "aaaaa z!z@z#z$z aaaaa"}, + + {.inputValue.sptr = "a", + .caseValue.str = "aAaA", + .truthValue.sptr = "AA"}, + + {.inputValue.sptr = "A", + .caseValue.str = "aAaA", + .truthValue.sptr = "aa"}, + + {.inputValue.sptr = "brisket", + .caseValue.str = "abracadabra brisket gumball", + .truthValue.sptr = "aacadaa gumall"}, + + {.inputValue.sptr = "b", + .caseValue.str = "balloons are falling from the sky", + .truthValue.sptr = "alloons are falling from the sky"}, + + {.inputValue.sptr = "ly", + .caseValue.str = "mangled mangoes oxidize quickly", + .truthValue.sptr = "manged mangoes oxidize quick"}, + + {.inputValue.sptr = NULL, + .caseValue.str = "bBbB", + .truthValue.sptr = "bBbB"}, + + {.inputValue.sptr = "B", + .caseValue.str = "\0", + .truthValue.sptr = ""}, +}; +size_t numCases = sizeof(testCase) / sizeof(struct TestCase); + +int main(int argc, char *argv[]) { + for (size_t i = 0; i < numCases; i++) { + char *orig = strdup(testCase[i].caseValue.str); + strchrdel(testCase[i].caseValue.str, testCase[i].inputValue.sptr); + myassert(strcmp(testCase[i].caseValue.str, testCase[i].truthValue.sptr) == 0, + testFmt, + orig, + testCase[i].caseValue.str, + testCase[i].truthValue.sptr); + free(orig); + } + + return 0; +} diff --git a/tests/test_str_strchroff.c b/tests/test_str_strchroff.c new file mode 100644 index 0000000..805a96d --- /dev/null +++ b/tests/test_str_strchroff.c @@ -0,0 +1,31 @@ +#include "spm.h" +#include "framework.h" + +const char *testFmt = "case '%s': returned %d, expected %d\n"; +struct TestCase testCase[] = { + {.inputValue.unsigned_integer = 'a', .caseValue.sptr = "after the world stops spinning", .truthValue.signed_integer = 0}, + {.inputValue.unsigned_integer = 'p', .caseValue.sptr = "apples exploded all over the place", .truthValue.signed_integer = 1}, + {.inputValue.unsigned_integer = '2', .caseValue.sptr = "a1a2a3a4a z!z@z#z$z a5a6a7a8a9", .truthValue.signed_integer = 3}, + {.inputValue.unsigned_integer = 'a', .caseValue.sptr = "aAaA", .truthValue.signed_integer = 0}, + {.inputValue.unsigned_integer = 'A', .caseValue.sptr = "aAaA", .truthValue.signed_integer = 1}, + {.inputValue.unsigned_integer = 'g', .caseValue.sptr = "abracadabra brisket gumball", .truthValue.signed_integer = 20}, + {.inputValue.unsigned_integer = 'r', .caseValue.sptr = "balloons are falling from the sky", .truthValue.signed_integer = 10}, + {.inputValue.unsigned_integer = 'b', .caseValue.sptr = "mangled mangoes oxidize quickly", .truthValue.signed_integer = -1}, + {.inputValue.unsigned_integer = 'b', .caseValue.sptr = "bBbB", .truthValue.signed_integer = 0}, + {.inputValue.unsigned_integer = 'B', .caseValue.sptr = "bBbB", .truthValue.signed_integer = 1}, +}; +size_t numCases = sizeof(testCase) / sizeof(struct TestCase); + + +int main(int argc, char *argv[]) { + for (size_t i = 0; i < numCases; i++) { + int result = strchroff(testCase[i].caseValue.sptr, testCase[i].inputValue.unsigned_integer); + myassert(result == testCase[i].truthValue.signed_integer, + testFmt, + testCase[i].caseValue.sptr, + result, + testCase[i].truthValue.signed_integer); + } + + return 0; +} diff --git a/tests/test_str_strdeldup.c b/tests/test_str_strdeldup.c new file mode 100644 index 0000000..1efdeb7 --- /dev/null +++ b/tests/test_str_strdeldup.c @@ -0,0 +1,31 @@ +#include "spm.h" +#include "framework.h" + +const char *testFmt = "case: (array){%s} expected '%s', returned '%s' \n"; +struct TestCase testCase[] = { + {.caseValue.slptr = (char *[]){"a", "a", "c", "d", "e", NULL}, .truthValue.sptr = "acde"}, + {.caseValue.slptr = (char *[]){"a", "b", "b", "d", "e", NULL}, .truthValue.sptr = "abde"}, + {.caseValue.slptr = (char *[]){"a", "b", "c", "c", "e", NULL}, .truthValue.sptr = "abce"}, + {.caseValue.slptr = (char *[]){"a", "b", "c", "d", "e", NULL}, .truthValue.sptr = "abcde"}, + {.caseValue.slptr = (char *[]){"e", "d", "c", "b", "a", NULL}, .truthValue.sptr = "edcba"}, + {.caseValue.slptr = NULL, .truthValue.sptr = NULL}, +}; +size_t numCases = sizeof(testCase) / sizeof(struct TestCase); + +int main(int argc, char *argv[]) { + for (size_t i = 0; i < numCases; i++) { + char **result = strdeldup(testCase[i].caseValue.slptr); + if (testCase[i].truthValue.sptr == NULL && result == NULL) { + continue; + } else if (testCase[i].truthValue.sptr == NULL && result != NULL) { + fprintf(stderr, testFmt, array_to_string(testCase[i].caseValue.slptr, ", "), testCase[i].truthValue.sptr, array_to_string(result, "")); + return 1; + } + char *str_result = join(result, ""); + + myassert(strcmp(str_result, testCase[i].truthValue.sptr) == 0, testFmt, array_to_string(testCase[i].caseValue.slptr, ", "), testCase[i].truthValue.sptr, str_result); + + free(str_result); + } + return 0; +}
\ No newline at end of file diff --git a/tests/test_str_strdelsuffix.c b/tests/test_str_strdelsuffix.c new file mode 100644 index 0000000..0bc9c85 --- /dev/null +++ b/tests/test_str_strdelsuffix.c @@ -0,0 +1,24 @@ +#include "spm.h" +#include "framework.h" + +const char *testFmt = "could not remove '%s' from '%s', expecting '%s'\n"; +struct TestCase testCase[] = { + {.inputValue.sptr = "gumball", .caseValue.str = "abracadabra brisket gumball", .truthValue.sptr = "abracadabra brisket"}, + {.inputValue.sptr = "y", .caseValue.str = "balloons are falling from the sky", .truthValue.sptr = "balloons are falling from the sk"}, + {.inputValue.sptr = "ickly", .caseValue.str = "mangled mangoes oxidize quickly", .truthValue.sptr = "mangled mangoes oxidize qu"}, + {.inputValue.sptr = "B", .caseValue.str = "bBbB", .truthValue.sptr = "bBb"}, + {.inputValue.sptr = NULL, .caseValue.str = "bBbB", .truthValue.sptr = "bBbB"}, + {.inputValue.sptr = "test", .caseValue.str = "\0", .truthValue.sptr = ""}, + {.inputValue.sptr = NULL, .caseValue.str = "\0", .truthValue.sptr = ""}, +}; +size_t numCases = sizeof(testCase) / sizeof(struct TestCase); + +int main(int argc, char *argv[]) { + for (size_t i = 0; i < numCases; i++) { + char *orig = strdup(testCase[i].caseValue.str); + strdelsuffix(testCase[i].caseValue.str, testCase[i].inputValue.sptr); + myassert(strcmp(testCase[i].caseValue.str, testCase[i].truthValue.sptr) == 0, testFmt, testCase[i].inputValue.sptr, orig, testCase[i].truthValue.sptr); + free(orig); + } + return 0; +}
\ No newline at end of file diff --git a/tests/test_str_strip.c b/tests/test_str_strip.c new file mode 100644 index 0000000..ea334a4 --- /dev/null +++ b/tests/test_str_strip.c @@ -0,0 +1,36 @@ +#include "spm.h" +#include "framework.h" + +const char *testFmt = "case '%s': returned '%s', expected '%s'\n"; +struct TestCase testCase[] = { + {.caseValue.str = "four spaces ", .truthValue.sptr = "four spaces"}, + {.caseValue.str = "one tab\t", .truthValue.sptr = "one tab"}, + {.caseValue.str = "a new line\n", .truthValue.sptr = "a new line"}, + {.caseValue.sptr = NULL, .truthValue.sptr = NULL}, +}; +size_t numCases = sizeof(testCase) / sizeof(struct TestCase); + +int main(int argc, char *argv[]) { + for (size_t i = 0; i < numCases; i++) { + char *caseValue = NULL; + char *orig = NULL; + char *result = NULL; + + if (testCase[i].caseValue.sptr != NULL) { + caseValue = strdup(testCase[i].caseValue.str); + orig = strdup(caseValue); + result = strip(caseValue); + } + + if (testCase[i].truthValue.sptr == NULL && result == NULL) { + continue; + } else if (testCase[i].truthValue.sptr != NULL && result == NULL) { + fprintf(stderr, testFmt, orig, result, testCase[i].truthValue.sptr); + return 1; + } + myassert(strcmp(result, testCase[i].truthValue.sptr) == 0, testFmt, orig, result, testCase[i].truthValue.sptr); + free(caseValue); + free(orig); + } + return 0; +}
\ No newline at end of file diff --git a/tests/test_str_strsort.c b/tests/test_str_strsort.c new file mode 100644 index 0000000..fbec04b --- /dev/null +++ b/tests/test_str_strsort.c @@ -0,0 +1,36 @@ +#include "spm.h" +#include "framework.h" + +const char *testFmt = "case: (array){%s}: returned '%s', expected '%s'\n"; +struct TestCase testCase[] = { + {.inputValue.unsigned_integer = SPM_SORT_NUMERIC, .caseValue.slptr = (char *[]){"1", "100", "10", "10000", "1000", "0", NULL}, .truthValue.sptr = "0 1 10 100 1000 10000"}, + {.inputValue.unsigned_integer = SPM_SORT_LEN_ASCENDING, .caseValue.slptr = (char *[]){"1", "100", "10", "10000", "1000", "0", NULL}, .truthValue.sptr = "1 0 10 100 1000 10000"}, // no QA? + {.inputValue.unsigned_integer = SPM_SORT_LEN_DESCENDING, .caseValue.slptr = (char *[]){"1", "100", "10", "10000", "1000", "0", NULL}, .truthValue.sptr = "10000 1000 100 10 1 0"}, + {.inputValue.unsigned_integer = SPM_SORT_ALPHA, .caseValue.slptr = (char *[]){"c", "b", "a", NULL}, .truthValue.sptr = "a b c"}, + {.inputValue.unsigned_integer = SPM_SORT_ALPHA, .caseValue.slptr = (char *[]){"a", "b", "c", NULL}, .truthValue.sptr = "a b c"}, + {.inputValue.unsigned_integer = SPM_SORT_ALPHA, .caseValue.slptr = (char *[]){"3", "2", "1", NULL}, .truthValue.sptr = "1 2 3"}, + {.inputValue.unsigned_integer = SPM_SORT_ALPHA, .caseValue.slptr = (char *[]){"1", "2", "3", NULL}, .truthValue.sptr = "1 2 3"}, + {.inputValue.unsigned_integer = SPM_SORT_ALPHA, .caseValue.slptr = (char *[]){"package2", "package1", NULL}, .truthValue.sptr = "package1 package2"}, + {.inputValue.unsigned_integer = SPM_SORT_ALPHA, .caseValue.slptr = (char *[]){"package1", "package2", NULL}, .truthValue.sptr = "package1 package2"}, + {.inputValue.unsigned_integer = SPM_SORT_ALPHA, .caseValue.sptr = NULL, .truthValue.slptr = NULL}, +}; +size_t numCases = sizeof(testCase) / sizeof(struct TestCase); + +int main(int argc, char *argv[]) { + for (size_t i = 0; i < numCases; i++) { + char **array_orig = strdup_array(testCase[i].caseValue.slptr); + char **array_case = strdup_array(array_orig); + + strsort(array_case, testCase[i].inputValue.unsigned_integer); + char *str_result = join(array_case, " "); + + if (testCase[i].truthValue.sptr == NULL && str_result == NULL) { + continue; + } + myassert(strcmp(str_result, testCase[i].truthValue.sptr) == 0, testFmt, array_to_string(array_orig, ", "), str_result, testCase[i].truthValue.sptr); + free(str_result); + split_free(array_case); + split_free(array_orig); + } + return 0; +}
\ No newline at end of file diff --git a/tests/test_str_strstr_array.c b/tests/test_str_strstr_array.c new file mode 100644 index 0000000..d2b7288 --- /dev/null +++ b/tests/test_str_strstr_array.c @@ -0,0 +1,28 @@ +#include "spm.h" +#include "framework.h" + +const char *testFmt = "case: (array){%s} expected '%s', returned '%s' \n"; +struct TestCase testCase[] = { + {.inputValue.sptr = "abracadabra", .caseValue.slptr = (char *[]){"abracadabra", "brisket", "gumball", NULL}, .truthValue.sptr = "abracadabra"}, + {.inputValue.sptr = "brisket", .caseValue.slptr = (char *[]){"abracadabra", "brisket", "gumball", NULL}, .truthValue.sptr = "brisket"}, + {.inputValue.sptr = "gumball", .caseValue.slptr = (char *[]){"abracadabra", "brisket", "gumball", NULL}, .truthValue.sptr = "gumball"}, + {.inputValue.sptr = "abrac", .caseValue.slptr = (char *[]){"abracadabra", "brisket", "gumball", NULL}, .truthValue.sptr = "abracadabra"}, + {.inputValue.sptr = "sket", .caseValue.slptr = (char *[]){"abracadabra", "brisket", "gumball", NULL}, .truthValue.sptr = "brisket"}, + {.inputValue.sptr = "ball", .caseValue.slptr = (char *[]){"abracadabra", "brisket", "gumball", NULL}, .truthValue.sptr = "gumball"}, + {.inputValue.sptr = NULL, .caseValue.slptr = NULL, .truthValue.sptr = NULL}, +}; +size_t numCases = sizeof(testCase) / sizeof(struct TestCase); + +int main(int argc, char *argv[]) { + for (size_t i = 0; i < numCases; i++) { + char *result = strstr_array(testCase[i].caseValue.slptr, testCase[i].inputValue.sptr); + if (testCase[i].truthValue.sptr == NULL && result == NULL) { + continue; + } else if (testCase[i].truthValue.sptr == NULL && result != NULL) { + fprintf(stderr, testFmt, testCase[i].inputValue.str, testCase[i].truthValue.sptr, result); + return 1; + } + myassert(strcmp(result, testCase[i].truthValue.sptr) == 0, testFmt, array_to_string(testCase[i].caseValue.slptr, ", "), testCase[i].truthValue.sptr, result); + } + return 0; +}
\ No newline at end of file diff --git a/tests/test_str_substring_between.c b/tests/test_str_substring_between.c new file mode 100644 index 0000000..0177068 --- /dev/null +++ b/tests/test_str_substring_between.c @@ -0,0 +1,28 @@ +#include "spm.h" +#include "framework.h" + +const char *testFmt = "case '%s': returned '%s', expected '%s'\n"; +struct TestCase testCase[] = { + {.inputValue.sptr = "[]", .caseValue.str = "[one two three]", .truthValue.sptr = "one two three"}, + {.inputValue.sptr = "..", .caseValue.str = ".[one].", .truthValue.sptr = "[one]"}, + {.inputValue.sptr = "\'\'", .caseValue.str = ".['one'].", .truthValue.sptr = "one"}, + {.inputValue.sptr = "@^", .caseValue.str = "abcdef@ghijkl^mnop@qrst^uvwxyz", .truthValue.sptr = "ghijkl"}, + {.inputValue.sptr = "", .caseValue.sptr = NULL, .truthValue.sptr = NULL}, + {.inputValue.sptr = NULL, .caseValue.sptr = NULL, .truthValue.sptr = NULL}, +}; +size_t numCases = sizeof(testCase) / sizeof(struct TestCase); + +int main(int argc, char *argv[]) { + for (size_t i = 0; i < numCases; i++) { + char *result = substring_between(testCase[i].caseValue.str, testCase[i].inputValue.sptr); + if (testCase[i].truthValue.sptr == NULL && result == NULL) { + continue; + } else if (testCase[i].truthValue.sptr != NULL && result == NULL) { + fprintf(stderr, testFmt, testCase[i].caseValue.str, result, testCase[i].truthValue.sptr); + return 1; + } + myassert(strcmp(result, testCase[i].truthValue.sptr) == 0, testFmt, testCase[i].caseValue.str, result, testCase[i].truthValue.sptr); + free(result); + } + return 0; +}
\ No newline at end of file |