diff options
author | Joseph Hunkeler <jhunkeler@users.noreply.github.com> | 2024-06-20 15:10:56 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-20 15:10:56 -0400 |
commit | 931ee28eb9c5b5e3c2b0d3008f5f65d810dc9b0c (patch) | |
tree | 5dbcccffd509fa71a99c351ed4628ed0841e1e46 /tests/test_system.c | |
parent | 11aa1d44d95da221073e512fbec3bbccc0f1a46b (diff) | |
download | stasis-931ee28eb9c5b5e3c2b0d3008f5f65d810dc9b0c.tar.gz |
Unit tests (#6)
* Initial commit of unit tests [WIP]
* Address shortcomings and bugs flushed out by unit tests
* Enable unit testing in CI workflow
* Enable verbose ctests
* Handle lack of __FILE_NAME__ define
* Only podman support `run --arch` argument
* Skip docker build testing if CI system cannot pull an image
* Remove errant call to puts()
* Identify local repo user
* Fix missing xmllint
* NULL terminate arrays
* Fix filename assignment in is_url mode
* Break loop when expected lines are exhausted
* strcmp_array expects NULL terminated array. Iterating by size in this case passes NULL to strcmp leading to an invalid read
* Remove debug printf statements
* Disable a few warnings for tests
* Workaround for ctest junit xml truncation
* Update checkout@v4
* Prevent false-positive result
* Return zero on error
* Fix strlist_remove function
* Value argument can be constant
* Fix test to match changes to startswith and endswith
* Add test_ini.c
* Fix redaction code to accept NULL pointers in array
* And let the caller specify the length of the array of strings to redact.
* Redactions now occur directly on authentication strings rather than their command line arguments
* Fix BUILD_TESTING_DEBUG
* Adds missing -D argument
Diffstat (limited to 'tests/test_system.c')
-rw-r--r-- | tests/test_system.c | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/tests/test_system.c b/tests/test_system.c new file mode 100644 index 0000000..bf60222 --- /dev/null +++ b/tests/test_system.c @@ -0,0 +1,145 @@ +#include "testing.h" + +static int ascii_file_contains(const char *filename, const char *value) { + int result = -1; + char *contents = omc_testing_read_ascii(filename); + if (!contents) { + perror(filename); + return result; + } + result = strcmp(contents, value) == 0; + guard_free(contents); + return result; +} + +void test_shell_output_null_args() { + char *result; + int status; + result = shell_output(NULL, &status); + OMC_ASSERT(strcmp(result, "") == 0, "no output expected"); + OMC_ASSERT(status != 0, "expected a non-zero exit code due to null argument string"); +} + +void test_shell_output_non_zero_exit() { + char *result; + int status; + result = shell_output("HELLO1234 WORLD", &status); + OMC_ASSERT(strcmp(result, "") == 0, "no output expected"); + OMC_ASSERT(status != 0, "expected a non-zero exit code due to intentional error"); +} + +void test_shell_output() { + char *result; + int status; + result = shell_output("echo HELLO WORLD", &status); + OMC_ASSERT(strcmp(result, "HELLO WORLD\n") == 0, "output message was incorrect"); + OMC_ASSERT(status == 0, "expected zero exit code"); +} + +void test_shell_safe() { + struct Process proc; + memset(&proc, 0, sizeof(proc)); + shell_safe(&proc, "true"); + OMC_ASSERT(proc.returncode == 0, "expected a zero exit code"); +} + +void test_shell_safe_verify_restrictions() { + struct Process proc; + + const char *invalid_chars = OMC_SHELL_SAFE_RESTRICT; + for (size_t i = 0; i < strlen(invalid_chars); i++) { + char cmd[PATH_MAX] = {0}; + memset(&proc, 0, sizeof(proc)); + + sprintf(cmd, "true%c false", invalid_chars[i]); + shell_safe(&proc, cmd); + OMC_ASSERT(proc.returncode == -1, "expected a negative result due to intentional error"); + } +} + +void test_shell_null_proc() { + int returncode = shell(NULL, "true"); + OMC_ASSERT(returncode == 0, "expected a zero exit code"); +} + +void test_shell_null_args() { + struct Process proc; + memset(&proc, 0, sizeof(proc)); + shell(&proc, NULL); + OMC_ASSERT(proc.returncode < 0, "expected a non-zero/negative exit code"); +} + +void test_shell_exit() { + struct Process proc; + memset(&proc, 0, sizeof(proc)); + shell(&proc, "true"); + OMC_ASSERT(proc.returncode == 0, "expected a zero exit code"); +} + +void test_shell_non_zero_exit() { + struct Process proc; + memset(&proc, 0, sizeof(proc)); + shell(&proc, "false"); + OMC_ASSERT(proc.returncode != 0, "expected a non-zero exit code"); +} + +void test_shell() { + struct Process procs[] = { + {.f_stdout = "", .f_stderr = "", .redirect_stderr = 0, .returncode = 0}, + {.f_stdout = "stdout.log", .f_stderr = "", .redirect_stderr = 0, .returncode = 0}, + {.f_stdout = "", .f_stderr = "stderr.log", .redirect_stderr = 0, .returncode = 0}, + {.f_stdout = "stdouterr.log", .f_stderr = "", .redirect_stderr = 1, .returncode = 0}, + }; + for (size_t i = 0; i < sizeof(procs) / sizeof(*procs); i++) { + shell(&procs[i], "echo test_stdout; echo test_stderr >&2"); + struct Process *proc = &procs[i]; + switch (i) { + case 0: + OMC_ASSERT(proc->returncode == 0, "echo should not fail"); + break; + case 1: + OMC_ASSERT(proc->returncode == 0, "echo should not fail"); + OMC_ASSERT(access(proc->f_stdout, F_OK) == 0, "stdout.log should exist"); + OMC_ASSERT(access(proc->f_stderr, F_OK) != 0, "stderr.log should not exist"); + OMC_ASSERT(ascii_file_contains(proc->f_stdout, "test_stdout\n"), "output file did not contain test message"); + remove(proc->f_stdout); + break; + case 2: + OMC_ASSERT(proc->returncode == 0, "echo should not fail"); + OMC_ASSERT(access(proc->f_stdout, F_OK) != 0, "stdout.log should not exist"); + OMC_ASSERT(access(proc->f_stderr, F_OK) == 0, "stderr.log should exist"); + OMC_ASSERT(ascii_file_contains(proc->f_stderr, "test_stderr\n"), "output file did not contain test message"); + remove(proc->f_stderr); + break; + case 3: + OMC_ASSERT(proc->returncode == 0, "echo should not fail"); + OMC_ASSERT(access("stdouterr.log", F_OK) == 0, "stdouterr.log should exist"); + OMC_ASSERT(access("stderr.log", F_OK) != 0, "stdout.log should not exist"); + OMC_ASSERT(access("stderr.log", F_OK) != 0, "stderr.log should not exist"); + OMC_ASSERT(ascii_file_contains(proc->f_stdout, "test_stdout\ntest_stderr\n"), "output file did not contain test message"); + remove(proc->f_stdout); + remove(proc->f_stderr); + break; + default: + break; + } + } +} + +int main(int argc, char *argv[]) { + OMC_TEST_BEGIN_MAIN(); + OMC_TEST_FUNC *tests[] = { + test_shell_output_null_args, + test_shell_output_non_zero_exit, + test_shell_output, + test_shell_safe_verify_restrictions, + test_shell_safe, + test_shell_null_proc, + test_shell_null_args, + test_shell_non_zero_exit, + test_shell_exit, + test_shell, + }; + OMC_TEST_RUN(tests); + OMC_TEST_END_MAIN(); +} |