diff options
author | Joseph Hunkeler <jhunkeler@users.noreply.github.com> | 2024-11-06 08:55:52 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-11-06 08:55:52 -0500 |
commit | 52e6d0f495023c0aa939bf6b2170ca5ea853202b (patch) | |
tree | 897a87316c280b6824892368662afcb848de1cf6 /tests | |
parent | 6db1b15b5c62d6fb52825c1d833ac8dfa9a49fbb (diff) | |
parent | 46ae10e55603b8852612ebe12c7636c2b358bdd6 (diff) | |
download | stasis-52e6d0f495023c0aa939bf6b2170ca5ea853202b.tar.gz |
Merge pull request #67 from jhunkeler/safety-and-convenience
Safety and convenience
Diffstat (limited to 'tests')
-rw-r--r-- | tests/data/generic_based_on.ini | 2 | ||||
-rw-r--r-- | tests/setup.sh | 22 | ||||
-rw-r--r-- | tests/test_conda.c | 6 | ||||
-rw-r--r-- | tests/test_junitxml.c | 9 | ||||
-rw-r--r-- | tests/test_str.c | 8 | ||||
-rw-r--r-- | tests/testing.h | 94 |
6 files changed, 123 insertions, 18 deletions
diff --git a/tests/data/generic_based_on.ini b/tests/data/generic_based_on.ini index 1c993ea..1287933 100644 --- a/tests/data/generic_based_on.ini +++ b/tests/data/generic_based_on.ini @@ -1,6 +1,6 @@ [meta] mission = generic -name = GENERIC +name = GENERIC_BASED_ON version = 1.2.3 rc = 1 final = false diff --git a/tests/setup.sh b/tests/setup.sh index 0875cac..50209ae 100644 --- a/tests/setup.sh +++ b/tests/setup.sh @@ -24,7 +24,15 @@ setup_script_dir="$(dirname ${BASH_SOURCE[0]})" export TOPDIR=$(pwd) export TEST_DATA="$TOPDIR"/data -WS_DEFAULT=rt_workspace_ +pushd() { + command pushd "$@" 1>/dev/null +} + +popd() { + command popd 1>/dev/null +} + +WS_DEFAULT="workspaces/rt_workspace_" setup_workspace() { if [ -z "$1" ]; then echo "setup_workspace requires a name argument" >&2 @@ -253,8 +261,18 @@ assert_file_contains() { fi } +clean_up_docker() { + CONTAINERS_DIR="$WORKSPACE/.local/share/containers" + # HOME points to the WORKSPACE. The only reason we'd have this directory is if docker/podman was executed + # Fair to assume if the directory exists, docker/podman is functional. + if [ -d "$CONTAINERS_DIR" ]; then + docker run --rm -it -v $CONTAINERS_DIR:/data alpine sh -c '/bin/rm -r -f /data/*' + fi +} + clean_up() { - if [ -z "$RT_KEEP_WORKSPACE" ] && [ -d "$WORKSPACE" ]; then + if ([ -z "$RT_KEEP_WORKSPACE" ] || [ -z "$KEEP_WORKSPACE" ]) && [ -d "$WORKSPACE" ]; then + clean_up_docker rm -rf "$WORKSPACE" fi diff --git a/tests/test_conda.c b/tests/test_conda.c index 84f98bc..63a2781 100644 --- a/tests/test_conda.c +++ b/tests/test_conda.c @@ -202,7 +202,11 @@ int main(int argc, char *argv[]) { test_delivery_gather_tool_versions, }; - const char *ws = "workspace"; + char ws[] = "workspace_XXXXXX"; + if (!mkdtemp(ws)) { + perror("mkdtemp"); + exit(1); + } getcwd(cwd_start, sizeof(cwd_start) - 1); mkdir(ws, 0755); chdir(ws); diff --git a/tests/test_junitxml.c b/tests/test_junitxml.c index e222b56..362cb32 100644 --- a/tests/test_junitxml.c +++ b/tests/test_junitxml.c @@ -3,7 +3,10 @@ void test_junitxml_testsuite_read() { struct JUNIT_Testsuite *testsuite; - STASIS_ASSERT_FATAL((testsuite = junitxml_testsuite_read("data/result.xml")) != NULL, "failed to load testsuite data"); + char datafile[PATH_MAX] = {0}; + snprintf(datafile, sizeof(datafile) - 1, "%s/result.xml", TEST_DATA_DIR); + + STASIS_ASSERT_FATAL((testsuite = junitxml_testsuite_read(datafile)) != NULL, "failed to load testsuite data"); STASIS_ASSERT(testsuite->name != NULL, "Test suite must be named"); STASIS_ASSERT(testsuite->skipped > 0, "missed skipped tests"); STASIS_ASSERT(testsuite->failures > 0, "missed failed tests"); @@ -44,7 +47,9 @@ void test_junitxml_testsuite_read() { void test_junitxml_testsuite_read_error() { struct JUNIT_Testsuite *testsuite; - STASIS_ASSERT_FATAL((testsuite = junitxml_testsuite_read("data/result_error.xml")) != NULL, "failed to load testsuite data"); + char datafile[PATH_MAX] = {0}; + snprintf(datafile, sizeof(datafile) - 1, "%s/result_error.xml", TEST_DATA_DIR); + STASIS_ASSERT_FATAL((testsuite = junitxml_testsuite_read(datafile)) != NULL, "failed to load testsuite data"); STASIS_ASSERT(testsuite->name != NULL, "test suite must be named"); STASIS_ASSERT(testsuite->skipped == 0, "should not have any skipped tests"); diff --git a/tests/test_str.c b/tests/test_str.c index 4991c1c..3aea50b 100644 --- a/tests/test_str.c +++ b/tests/test_str.c @@ -204,8 +204,7 @@ void test_split() { {.data = NULL, .delim = NULL, NULL}, }; for (size_t i = 0; i < sizeof(tc) / sizeof(*tc); i++) { - char **result; - result = split(tc[i].data, tc[i].delim, tc[i].max_split); + char **result = split((char *) tc[i].data, tc[i].delim, tc[i].max_split); STASIS_ASSERT(strcmp_array((const char **) result, tc[i].expected) == 0, "Split failed"); GENERIC_ARRAY_FREE(result); } @@ -243,8 +242,7 @@ void test_join_ex() { {.delim = "\n\n", .expected = "a\n\nb\n\nc\n\nd\n\ne"}, }; for (size_t i = 0; i < sizeof(tc) / sizeof(*tc); i++) { - char *result; - result = join_ex((char *) tc[i].delim, "a", "b", "c", "d", "e", NULL); + char *result = join_ex((char *) tc[i].delim, "a", "b", "c", "d", "e", NULL); STASIS_ASSERT(strcmp(result ? result : "", tc[i].expected) == 0, "failed to join array"); guard_free(result); } @@ -270,7 +268,7 @@ void test_substring_between() { {.data = "nothing () here", .delim = "()", .expected = ""}, // nothing exists between delimiters }; for (size_t i = 0; i < sizeof(tc) / sizeof(*tc); i++) { - char *result = substring_between(tc[i].data, tc[i].delim); + char *result = substring_between((char *) tc[i].data, tc[i].delim); STASIS_ASSERT(strcmp(result ? result : "", tc[i].expected) == 0, "unable to extract substring"); guard_free(result); } diff --git a/tests/testing.h b/tests/testing.h index 15bd208..4c97bf2 100644 --- a/tests/testing.h +++ b/tests/testing.h @@ -21,14 +21,21 @@ struct stasis_test_result_t { } stasis_test_results[STASIS_TEST_RUN_MAX]; size_t stasis_test_results_i = 0; -void stasis_testing_record_result(struct stasis_test_result_t result); - -void stasis_testing_record_result(struct stasis_test_result_t result) { +extern inline void stasis_testing_setup_workspace(); +extern inline void stasis_testing_clean_up_docker(); +extern inline void stasis_testing_teardown_workspace(); +extern inline void stasis_testing_record_result(struct stasis_test_result_t result); +extern inline int stasis_testing_has_failed(); +extern inline void stasis_testing_record_result_summary(); +extern inline char *stasis_testing_read_ascii(const char *filename); +extern inline int stasis_testing_write_ascii(const char *filename, const char *data); + +inline void stasis_testing_record_result(struct stasis_test_result_t result) { memcpy(&stasis_test_results[stasis_test_results_i], &result, sizeof(result)); stasis_test_results_i++; } -int stasis_testing_has_failed() { +inline int stasis_testing_has_failed() { for (size_t i = 0; i < stasis_test_results_i; i++) { if (stasis_test_results[i].status == false) { return 1; @@ -36,7 +43,8 @@ int stasis_testing_has_failed() { } return 0; } -void stasis_testing_record_result_summary() { + +inline void stasis_testing_record_result_summary() { size_t failed = 0; size_t skipped = 0; size_t passed = 0; @@ -70,7 +78,7 @@ void stasis_testing_record_result_summary() { fprintf(stdout, "\n[UNIT] %zu tests passed, %zu tests failed, %zu tests skipped out of %zu\n", passed, failed, skipped, stasis_test_results_i); } -char *stasis_testing_read_ascii(const char *filename) { +inline char *stasis_testing_read_ascii(const char *filename) { struct stat st; if (stat(filename, &st)) { perror(filename); @@ -96,7 +104,7 @@ char *stasis_testing_read_ascii(const char *filename) { return result; } -int stasis_testing_write_ascii(const char *filename, const char *data) { +inline int stasis_testing_write_ascii(const char *filename, const char *data) { FILE *fp; fp = fopen(filename, "w+"); if (!fp) { @@ -114,13 +122,85 @@ int stasis_testing_write_ascii(const char *filename, const char *data) { return 0; } +char TEST_DATA_DIR[PATH_MAX] = {0}; +char TEST_START_DIR[PATH_MAX] = {0}; +char TEST_WORKSPACE_DIR[PATH_MAX] = {0}; +inline void stasis_testing_setup_workspace() { + if (!realpath("data", TEST_DATA_DIR)) { + SYSERROR("%s", "Data directory is missing"); + exit(1); + } + + if (mkdir("workspaces", 0755) < 0) { + if (errno != EEXIST) { + SYSERROR("%s", "Unable to create workspaces directory"); + exit(1); + } + } + char ws[] = "workspaces/workspace_XXXXXX"; + if (mkdtemp(ws) == NULL) { + SYSERROR("Unable to create testing workspace: %s", ws); + exit(1); + } + if (!realpath(ws, TEST_WORKSPACE_DIR)) { + SYSERROR("%s", "Unable to determine absolute path to temporary workspace"); + exit(1); + } + if (chdir(TEST_WORKSPACE_DIR) < 0) { + SYSERROR("Unable to enter workspace directory: '%s'", TEST_WORKSPACE_DIR); + exit(1); + } + if (setenv("HOME", TEST_WORKSPACE_DIR, 1) < 0) { + SYSERROR("Unable to reset HOME to '%s'", TEST_WORKSPACE_DIR); + } +} + +inline void stasis_testing_clean_up_docker() { + char containers_dir[PATH_MAX] = {0}; + snprintf(containers_dir, sizeof(containers_dir) - 1, "%s/.local/share/containers", TEST_WORKSPACE_DIR); + + if (access(containers_dir, F_OK) == 0) { + char cmd[PATH_MAX] = {0}; + snprintf(cmd, sizeof(cmd) - 1, "docker run --rm -it -v %s:/data alpine sh -c '/bin/rm -r -f /data/*' &>/dev/null", containers_dir); + // This command will "fail" due to podman's internal protection(s). However, this gets us close enough. + system(cmd); + + // Podman seems to defer the rollback operation on-error for a short period. + // This buys time, so we can delete it. + sleep(1); + sync(); + if (rmtree(containers_dir)) { + SYSERROR("WARNING: Unable to fully remove container directory: '%s'", containers_dir); + } + } +} + +inline void stasis_testing_teardown_workspace() { + if (chdir(TEST_START_DIR) < 0) { + SYSERROR("Unable to re-enter test start directory from workspace directory: %s", TEST_START_DIR); + exit(1); + } + if (!getenv("KEEP_WORKSPACE")) { + if (strlen(TEST_WORKSPACE_DIR) > 1) { + stasis_testing_clean_up_docker(); + rmtree(TEST_WORKSPACE_DIR); + } + } +} + #define STASIS_TEST_BEGIN_MAIN() do { \ setenv("PYTHONUNBUFFERED", "1", 1); \ fflush(stdout); \ fflush(stderr); \ setvbuf(stdout, NULL, _IONBF, 0); \ setvbuf(stderr, NULL, _IONBF, 0); \ + if (!getcwd(TEST_START_DIR, sizeof(TEST_START_DIR) - 1)) { \ + SYSERROR("%s", "Unable to determine current working directory"); \ + exit(1); \ + } \ atexit(stasis_testing_record_result_summary); \ + atexit(stasis_testing_teardown_workspace); \ + stasis_testing_setup_workspace(); \ } while (0) #define STASIS_TEST_END_MAIN() do { return stasis_testing_has_failed(); } while (0) |