diff options
author | Joseph Hunkeler <jhunkeler@gmail.com> | 2021-05-05 19:57:39 -0400 |
---|---|---|
committer | Joseph Hunkeler <jhunkeler@gmail.com> | 2021-05-05 19:57:39 -0400 |
commit | a92b4038179c3706bd176097be1caabd88824755 (patch) | |
tree | 3ca109b34e24e5940e2d12acca39091c83963fd3 | |
parent | ea6e2613aca23c84373e686d739498969062f79e (diff) | |
download | cleanpath-a92b4038179c3706bd176097be1caabd88824755.tar.gz |
Add tests
-rw-r--r-- | CMakeLists.txt | 6 | ||||
-rw-r--r-- | tests/CMakeLists.txt | 22 | ||||
-rw-r--r-- | tests/framework.h | 19 | ||||
-rw-r--r-- | tests/test_errors.c | 11 | ||||
-rw-r--r-- | tests/test_modes_filter_all.c | 89 | ||||
-rw-r--r-- | tests/test_modes_filter_general.c | 86 |
6 files changed, 232 insertions, 1 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 096a49e..71de6df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,10 @@ set(LIB_SOURCES lib/cleanpath.c) set(MAIN_SOURCES src/main.c) set(INCLUDES include/cleanpath.h) +include (CTest) +enable_testing() +add_subdirectory(tests) + add_library(cleanpath_static STATIC ${LIB_SOURCES}) set_target_properties(cleanpath_static PROPERTIES PUBLIC_HEADER ${INCLUDES}) set_target_properties(cleanpath_static PROPERTIES OUTPUT_NAME cleanpath) @@ -30,4 +34,4 @@ install(TARGETS cleanpath RUNTIME DESTINATION bin) install(FILES ${CMAKE_SOURCE_DIR}/docs/man/cleanpath.1 - DESTINATION share/man/man1 COMPONENT doc)
\ No newline at end of file + DESTINATION share/man/man1 COMPONENT doc) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..4f23ecf --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,22 @@ +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) +set(PROJECT_LIBS cleanpath_static) + +file(GLOB files "test_*.c") + +foreach(file ${files}) + string(REGEX REPLACE "(^.*/|\\.[^.]*$)" "" file_without_ext ${file}) + add_executable(${file_without_ext} ${file}) + if(NOT(MSVC)) + target_compile_options(${file_without_ext} PRIVATE -Wno-unused-parameter) + endif() + target_link_libraries(${file_without_ext} ${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..96ae3de --- /dev/null +++ b/tests/framework.h @@ -0,0 +1,19 @@ +#ifndef CLEAN_PATH_FRAMEWORK_H +#define CLEAN_PATH_FRAMEWORK_H + +#include <stdio.h> + +#define TEST_SEP ":" +#define TEST_PATH "/opt/local/bin:/opt/local/sbin:/usr/local/bin:" \ + "/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/Library/Apple/usr/bin" + +#define myassert(condition, ...) \ + do { \ + if (!(condition)) { \ + fprintf(stderr, "%s:%d:%s :: ", __FILE__, __LINE__, __FUNCTION__); \ + fprintf(stderr, __VA_ARGS__); \ + return 1; \ + } \ + } while (0) + +#endif //CLEAN_PATH_FRAMEWORK_H diff --git a/tests/test_errors.c b/tests/test_errors.c new file mode 100644 index 0000000..f9d641f --- /dev/null +++ b/tests/test_errors.c @@ -0,0 +1,11 @@ +#include "cleanpath.h" +#include "framework.h" + +int main() { + struct CleanPath *path; + path = NULL; + + //intentionally bad + myassert(cleanpath_init("good", NULL) == NULL, "cleanpath_init() returned non-NULL on NULL sep\n"); + myassert(cleanpath_init(NULL, "good") == NULL, "cleanpath_init() returned non-NULL on NULL path\n"); +}
\ No newline at end of file diff --git a/tests/test_modes_filter_all.c b/tests/test_modes_filter_all.c new file mode 100644 index 0000000..4f41dce --- /dev/null +++ b/tests/test_modes_filter_all.c @@ -0,0 +1,89 @@ +#include <stdio.h> +#include "cleanpath.h" +#include "framework.h" + +#define MAX_MODE 3 +#define MAX_PART CLEANPATH_PART_MAX +#define MAX_RECORD 255 + +unsigned modes[MAX_MODE] = { + CLEANPATH_FILTER_EXACT, + CLEANPATH_FILTER_LOOSE, + CLEANPATH_FILTER_REGEX, +}; + +char *modes_str[MAX_MODE] = { + "exact", + "loose", + "regex", +}; + +const char *inputs[MAX_MODE][MAX_PART][MAX_RECORD] = { + { // Filter exact + "/opt/local/bin", + "/opt/local/sbin", + "/usr/local/bin", + "/usr/bin", + "/bin", + "/usr/sbin", + "/sbin", + "/opt/X11/bin", + "/Library/Apple/usr/bin", + NULL + }, + { // Filter loose + "bin", + NULL + }, + { // Filter regex + ".*", + NULL + }, +}; + +struct TestResult { + size_t status; + size_t mode; + char *output; + char input[1024]; + char sep[25]; +}; + +int main() { + int status; + struct TestResult tr[MAX_MODE]; + + status = 0; + for (size_t mode = 0; mode < MAX_MODE; mode++) { + struct CleanPath *path; + strcpy(tr[mode].sep, TEST_SEP); + strcpy(tr[mode].input, TEST_PATH); + tr[mode].mode = mode; + tr[mode].status = 0; + tr[mode].output = NULL; + + path = cleanpath_init(tr[mode].input, tr[mode].sep); + for (size_t part = 0; part < MAX_PART && inputs[mode][part] != NULL; part++) { + for (size_t record = 0; inputs[mode][part][record] != NULL; record++) { + cleanpath_filter(path, mode, inputs[mode][part][record]); + } + } + tr[mode].output = cleanpath_read(path); + tr[mode].status = strlen(tr[mode].output) == 0; + cleanpath_free(path); + } + + for (size_t i = 0; i < MAX_MODE; i++) { + if (tr[i].status != 0) { + free(tr[i].output); + continue; + } + status++; + fprintf(stderr, "'%s' mode failed to filter elements from:\n'%s'\nRemainder:\n'%s'\n", + modes_str[tr[i].mode], tr[i].input, tr[i].output); + free(tr[i].output); + } + + myassert(status == 0, "%d mode(s) failed", status); + return 0; +}
\ No newline at end of file diff --git a/tests/test_modes_filter_general.c b/tests/test_modes_filter_general.c new file mode 100644 index 0000000..e3a9cda --- /dev/null +++ b/tests/test_modes_filter_general.c @@ -0,0 +1,86 @@ +#include "cleanpath.h" +#include "framework.h" + +#define MAX_MODE 3 +#define MAX_PART CLEANPATH_PART_MAX +#define MAX_RECORD 255 + +unsigned modes[MAX_MODE] = { + CLEANPATH_FILTER_EXACT, + CLEANPATH_FILTER_LOOSE, + CLEANPATH_FILTER_REGEX, +}; + +char *modes_str[MAX_MODE] = { + "exact", + "loose", + "regex", +}; + +const char *inputs[MAX_MODE][MAX_PART][MAX_RECORD] = { + { // Filter exact + "/opt/local/bin", + "/opt/local/sbin", + "intentionally bad", // test non-existent pattern in string + NULL + }, + { // Filter loose + "/opt/local", + "intentionally bad", // test non-existent pattern in string + NULL + }, + { // Filter regex + "^/opt/local/.*", + "intentionally bad", // test non-existent pattern in string + "intentionally worse (", // cause total regex failure with unmatched parenthesis + NULL + }, +}; +const char *expected = "/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/Library/Apple/usr/bin"; + +struct TestResult { + size_t status; + size_t mode; + char *output; + char input[1024]; + char sep[25]; +}; + +int main() { + int status; + struct TestResult tr[MAX_MODE]; + + status = 0; + for (size_t mode = 0; mode < MAX_MODE; mode++) { + struct CleanPath *path; + strcpy(tr[mode].sep, TEST_SEP); + strcpy(tr[mode].input, TEST_PATH); + tr[mode].mode = mode; + tr[mode].status = 0; + tr[mode].output = NULL; + + path = cleanpath_init(tr[mode].input, tr[mode].sep); + for (size_t part = 0; part < MAX_PART && inputs[mode][part] != NULL; part++) { + for (size_t record = 0; inputs[mode][part][record] != NULL; record++) { + cleanpath_filter(path, mode, inputs[mode][part][record]); + } + } + tr[mode].output = cleanpath_read(path); + tr[mode].status = strcmp(tr[mode].output, expected); + cleanpath_free(path); + } + + for (size_t i = 0; i < MAX_MODE; i++) { + if (tr[i].status == 0) { + free(tr[i].output); + continue; + } + status++; + fprintf(stderr, "'%s' mode failed to filter elements from:\n'%s'\nExpected:\n'%s'\nRemainder:\n'%s'\n\n", + modes_str[tr[i].mode], tr[i].input, expected, tr[i].output); + free(tr[i].output); + } + + myassert(status == 0, "%d mode(s) failed", status); + return 0; +}
\ No newline at end of file |