From: Kevin Day Date: Thu, 16 Mar 2023 23:17:26 +0000 (-0500) Subject: Update: Add unit tests for fll_path. X-Git-Url: https://git.kevux.org/?a=commitdiff_plain;h=32fa5d2af0d85e8900067822f5dd490d0871b311;p=fll Update: Add unit tests for fll_path. I noticed that the '~' path is not expanded. I checked to see if this is intentional or not. It is intentionally not supported yet. I need another function. This check encouraged me to write some unit tests for the current behavior. It seems that I had forgotten just how few unit tests I have. Now there are at least more. --- diff --git a/level_2/fll_path/c/path.c b/level_2/fll_path/c/path.c index f218c9a..30cf64a 100644 --- a/level_2/fll_path/c/path.c +++ b/level_2/fll_path/c/path.c @@ -36,9 +36,7 @@ extern "C" { status = f_path_current(F_true, canonical); if (F_status_is_error(status)) return status; - if (!path.string[0] || path.used == 1) { - return F_none; - } + if (!path.string[0]) return F_none; at = 0; } diff --git a/level_2/fll_path/c/path.h b/level_2/fll_path/c/path.h index 49da446..4ffa250 100644 --- a/level_2/fll_path/c/path.h +++ b/level_2/fll_path/c/path.h @@ -31,6 +31,7 @@ extern "C" { * This processes the relative parts: './', '../', and extra '/'. * This does not process symbolic links. * This has a max size of F_string_t_size_d. + * This removes trailing slashes, but leaves the leading slash ('/' remains as-is, but '/a/' becomes '/a'). * * An empty path (first character is NULL or path.used is 0) appends only the current path to canonical. * diff --git a/level_2/fll_path/data/build/dependencies-tests b/level_2/fll_path/data/build/dependencies-tests new file mode 100644 index 0000000..dea3179 --- /dev/null +++ b/level_2/fll_path/data/build/dependencies-tests @@ -0,0 +1,3 @@ +# fss-0001 + +cmocka 1.* diff --git a/level_2/fll_path/data/build/settings-tests b/level_2/fll_path/data/build/settings-tests new file mode 100644 index 0000000..bf78c7e --- /dev/null +++ b/level_2/fll_path/data/build/settings-tests @@ -0,0 +1,50 @@ +# fss-0001 + +build_name test-fll_path + +version_major 0 +version_minor 6 +version_micro 4 +version_file micro +version_target minor + +modes individual clang test coverage +modes_default individual test + +build_compiler gcc +build_compiler-clang clang +build_indexer ar +build_indexer_arguments rcs +build_language c + +build_libraries -lc -lcmocka +build_libraries-individual -lf_memory -lf_path -lf_string -lfll_path + +build_sources_program test-path-canonical.c + +build_sources_program test-path.c + +build_script no +build_shared yes +build_static no + +path_headers tests/unit/c +path_sources tests/unit/c + +has_path_standard no +preserve_path_headers yes + +search_exclusive yes +search_shared yes +search_static yes + +defines -Ibuild/includes +defines_static -Lbuild/libraries/static +defines_shared -Lbuild/libraries/shared + +flags -O2 -z now -g -fdiagnostics-color=always -Wno-logical-not-parentheses -Wno-parentheses +flags-clang -Wno-logical-op-parentheses +flags-test -fstack-protector -Wall +flags-coverage -O0 --coverage -fprofile-abs-path -fprofile-dir=build/coverage/ + +flags_program -fPIE diff --git a/level_2/fll_path/data/build/testfile b/level_2/fll_path/data/build/testfile new file mode 100644 index 0000000..1e73743 --- /dev/null +++ b/level_2/fll_path/data/build/testfile @@ -0,0 +1,55 @@ +# fss-0005 iki-0002 + +settings: + load_build yes + fail exit + + environment PATH LD_LIBRARY_PATH + environment CMOCKA_XML_FILE CMOCKA_MESSAGE_OUTPUT CMOCKA_TEST_ABORT + + # Cmcka is not fully thread-safe, set this to "1" to have cmocka call abort() on a test failure. + #CMOCKA_TEST_ABORT 1 + + # One of: STDOUT, SUBUNIT, TAP, or XML. + #define CMOCKA_MESSAGE_OUTPUT STDOUT + + # When in "XML" output mode, output to this file rather than stdout. + #define CMOCKA_XML_FILE ./out.xml + +main: + build settings individual test + build settings-tests individual test + + operate ld_library_path + + if exist build/programs/shared/test-fll_path + shell build/programs/shared/test-fll_path + + if exist build/programs/static/test-fll_path + shell build/programs/static/test-fll_path + + if not exist build/programs/shared/test-fll_path + and not exist build/programs/static/test-fll_path + operate not_created + +not_created: + print + print 'context:"error"Failed to test due to being unable to find either a shared or static test binary to perform tests. context:"reset"' + + exit failure + +ld_library_path: + if define LD_LIBRARY_PATH + and parameter work + define LD_LIBRARY_PATH 'build/libraries/shared:parameter:"work:value"libraries/shared:define:"LD_LIBRARY_PATH"' + + else + if define LD_LIBRARY_PATH + define LD_LIBRARY_PATH 'build/libraries/shared:define:"LD_LIBRARY_PATH"' + + else + if parameter work + define LD_LIBRARY_PATH 'build/libraries/shared:parameter:"work:value"libraries/shared' + + else + define LD_LIBRARY_PATH build/libraries/shared diff --git a/level_2/fll_path/tests/unit/c/test-path-canonical.c b/level_2/fll_path/tests/unit/c/test-path-canonical.c new file mode 100644 index 0000000..03ab0de --- /dev/null +++ b/level_2/fll_path/tests/unit/c/test-path-canonical.c @@ -0,0 +1,483 @@ +#include "test-path.h" +#include "test-path-canonical.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__fll_path_canonical__back_paths(void **state) { + + // Paths that don't begin with '/' or '../' will expand to the full PWD. + f_char_t pwd[PATH_MAX + 1]; + + memset(pwd, 0, PATH_MAX + 1); + + getcwd(pwd, PATH_MAX); + + const unsigned int pwd_length = strnlen(pwd, PATH_MAX); + + const f_string_static_t contents[] = { + macro_f_string_static_t_initialize("a/../", 0, 5), + macro_f_string_static_t_initialize("a/../b", 0, 6), + macro_f_string_static_t_initialize("a/../b/", 0, 7), + macro_f_string_static_t_initialize("a/../b/c", 0, 8), + macro_f_string_static_t_initialize("a/../b/c/", 0, 9), + macro_f_string_static_t_initialize("a/../b/c//", 0, 10), + macro_f_string_static_t_initialize("a/.././", 0, 7), + macro_f_string_static_t_initialize("a/.././b", 0, 8), + macro_f_string_static_t_initialize("a/.././b/", 0, 9), + macro_f_string_static_t_initialize("a/.././b/c", 0, 10), + macro_f_string_static_t_initialize("a/.././b/c/", 0, 11), + macro_f_string_static_t_initialize("a/.././b/c//", 0, 12), + macro_f_string_static_t_initialize("a/.././/", 0, 8), + macro_f_string_static_t_initialize("a/.././/b", 0, 9), + macro_f_string_static_t_initialize("a/.././/b/", 0, 10), + macro_f_string_static_t_initialize("a/.././/b/c", 0, 11), + macro_f_string_static_t_initialize("a/.././/b/c/", 0, 12), + macro_f_string_static_t_initialize("a/.././/b/c//", 0, 13), + macro_f_string_static_t_initialize("/z/../", 0, 6), + macro_f_string_static_t_initialize("/z/../b", 0, 7), + macro_f_string_static_t_initialize("/z/../b/", 0, 8), + macro_f_string_static_t_initialize("/z/../b/c", 0, 9), + macro_f_string_static_t_initialize("/z/../b/c/", 0, 10), + macro_f_string_static_t_initialize("/z/../b/c//", 0, 11), + }; + + const f_string_static_t expected[] = { + macro_f_string_static_t_initialize("", 0, 0), + macro_f_string_static_t_initialize("b", 0, 1), + macro_f_string_static_t_initialize("b", 0, 1), + macro_f_string_static_t_initialize("b/c", 0, 3), + macro_f_string_static_t_initialize("b/c", 0, 3), + macro_f_string_static_t_initialize("b/c", 0, 3), + macro_f_string_static_t_initialize("", 0, 0), + macro_f_string_static_t_initialize("b", 0, 1), + macro_f_string_static_t_initialize("b", 0, 1), + macro_f_string_static_t_initialize("b/c", 0, 3), + macro_f_string_static_t_initialize("b/c", 0, 3), + macro_f_string_static_t_initialize("b/c", 0, 3), + macro_f_string_static_t_initialize("", 0, 0), + macro_f_string_static_t_initialize("b", 0, 1), + macro_f_string_static_t_initialize("b", 0, 1), + macro_f_string_static_t_initialize("b/c", 0, 3), + macro_f_string_static_t_initialize("b/c", 0, 3), + macro_f_string_static_t_initialize("b/c", 0, 3), + macro_f_string_static_t_initialize("/", 0, 1), + macro_f_string_static_t_initialize("/b", 0, 2), + macro_f_string_static_t_initialize("/b", 0, 2), + macro_f_string_static_t_initialize("/b/c", 0, 4), + macro_f_string_static_t_initialize("/b/c", 0, 4), + macro_f_string_static_t_initialize("/b/c", 0, 4), + }; + + const uint8_t prepend[] = { + F_true, + F_true, + F_true, + F_true, + F_true, + F_true, + F_true, + F_true, + F_true, + F_true, + F_true, + F_true, + F_true, + F_true, + F_true, + F_true, + F_true, + F_true, + F_false, + F_false, + F_false, + F_false, + F_false, + F_false, + }; + + f_string_dynamic_t path = f_string_dynamic_t_initialize; + + for (uint8_t i = 0; i < 24; ++i) { + + const f_status_t status = fll_path_canonical(contents[i], &path); + + assert_int_equal(status, F_none); + + // Assert_string_equal() is NULL terminated, so ensure NULL termination at end of path.used. + path.string[path.used] = 0; + + if (prepend[i]) { + f_char_t prepended_string[pwd_length + expected[i].used + 2]; + f_string_static_t prepended = macro_f_string_static_t_initialize(prepended_string, 0, pwd_length + expected[i].used); + + prepended_string[prepended.used] = 0; + prepended_string[prepended.used + 1] = 0; + + if (pwd_length) { + memcpy(prepended_string, pwd, pwd_length); + } + + if (expected[i].used) { + if (pwd_length && prepended_string[pwd_length] != f_path_separator_s.string[0]) { + prepended_string[pwd_length] = f_path_separator_s.string[0]; + memcpy(prepended_string + pwd_length + 1, expected[i].string, expected[i].used); + ++prepended.used; + } + else { + memcpy(prepended_string + pwd_length, expected[i].string, expected[i].used); + } + } + + // The last slash is always removed. + if (prepended.used && prepended_string[prepended.used - 1] == f_path_separator_s.string[0]) { + prepended_string[prepended.used--] = 0; + } + + assert_int_equal(prepended.used, path.used); + assert_string_equal(prepended.string, path.string); + } + else { + assert_int_equal(expected[i].used, path.used); + assert_string_equal(expected[i].string, path.string); + } + } // for + + f_string_dynamic_resize(0, &path); +} + +void test__fll_path_canonical__empty_becomes_pwd(void **state) { + + f_char_t pwd[PATH_MAX + 1]; + + memset(pwd, 0, PATH_MAX + 1); + + getcwd(pwd, PATH_MAX); + + const unsigned int pwd_length = strnlen(pwd, PATH_MAX); + + f_string_dynamic_t path = f_string_dynamic_t_initialize; + + { + const f_status_t status = fll_path_canonical(f_string_empty_s, &path); + + assert_int_equal(status, F_none); + assert_int_equal(pwd_length, path.used); + assert_string_equal(pwd, path.string); + } // for + + f_string_dynamic_resize(0, &path); +} + +void test__fll_path_canonical__present_paths(void **state) { + + // Paths that don't begin with '/' or '../' will expand to the full PWD. + f_char_t pwd[PATH_MAX + 1]; + + memset(pwd, 0, PATH_MAX + 1); + + getcwd(pwd, PATH_MAX); + + const unsigned int pwd_length = strnlen(pwd, PATH_MAX); + + const f_string_static_t contents[] = { + macro_f_string_static_t_initialize("", 0, 1), + macro_f_string_static_t_initialize("a", 0, 2), + macro_f_string_static_t_initialize("a/", 0, 3), + macro_f_string_static_t_initialize("a/b", 0, 4), + macro_f_string_static_t_initialize("a/b/", 0, 5), + macro_f_string_static_t_initialize("a/b//", 0, 6), + macro_f_string_static_t_initialize("./", 0, 2), + macro_f_string_static_t_initialize("./a", 0, 3), + macro_f_string_static_t_initialize("./a/", 0, 4), + macro_f_string_static_t_initialize("./a/b", 0, 5), + macro_f_string_static_t_initialize("./a/b/", 0, 6), + macro_f_string_static_t_initialize("./a/b//", 0, 7), + macro_f_string_static_t_initialize(".//", 0, 3), + macro_f_string_static_t_initialize(".//a", 0, 4), + macro_f_string_static_t_initialize(".//a/", 0, 5), + macro_f_string_static_t_initialize(".//a/b", 0, 6), + macro_f_string_static_t_initialize(".//a/b/", 0, 7), + macro_f_string_static_t_initialize(".//a/b//", 0, 8), + }; + + const f_string_static_t expected[] = { + macro_f_string_static_t_initialize("", 0, 0), + macro_f_string_static_t_initialize("a", 0, 1), + macro_f_string_static_t_initialize("a", 0, 1), + macro_f_string_static_t_initialize("a/b", 0, 3), + macro_f_string_static_t_initialize("a/b", 0, 3), + macro_f_string_static_t_initialize("a/b", 0, 3), + macro_f_string_static_t_initialize("", 0, 0), + macro_f_string_static_t_initialize("a", 0, 1), + macro_f_string_static_t_initialize("a", 0, 1), + macro_f_string_static_t_initialize("a/b", 0, 3), + macro_f_string_static_t_initialize("a/b", 0, 3), + macro_f_string_static_t_initialize("a/b", 0, 3), + macro_f_string_static_t_initialize("", 0, 0), + macro_f_string_static_t_initialize("a", 0, 1), + macro_f_string_static_t_initialize("a", 0, 1), + macro_f_string_static_t_initialize("a/b", 0, 3), + macro_f_string_static_t_initialize("a/b", 0, 3), + macro_f_string_static_t_initialize("a/b", 0, 3), + }; + + f_string_dynamic_t path = f_string_dynamic_t_initialize; + + for (uint8_t i = 0; i < 18; ++i) { + + const f_status_t status = fll_path_canonical(contents[i], &path); + + assert_int_equal(status, F_none); + + // Assert_string_equal() is NULL terminated, so ensure NULL termination at end of path.used. + path.string[path.used] = 0; + + f_char_t prepended_string[pwd_length + expected[i].used + 2]; + f_string_static_t prepended = macro_f_string_static_t_initialize(prepended_string, 0, pwd_length + expected[i].used); + + prepended_string[prepended.used] = 0; + prepended_string[prepended.used + 1] = 0; + + if (pwd_length) { + memcpy(prepended_string, pwd, pwd_length); + } + + if (expected[i].used) { + if (pwd_length && prepended_string[pwd_length] != f_path_separator_s.string[0]) { + prepended_string[pwd_length] = f_path_separator_s.string[0]; + memcpy(prepended_string + pwd_length + 1, expected[i].string, expected[i].used); + ++prepended.used; + } + else { + memcpy(prepended_string + pwd_length, expected[i].string, expected[i].used); + } + } + + // The last slash is always removed. + if (prepended.used && prepended_string[prepended.used - 1] == f_path_separator_s.string[0]) { + prepended_string[prepended.used--] = 0; + } + + assert_int_equal(prepended.used, path.used); + assert_string_equal(prepended.string, path.string); + } // for + + f_string_dynamic_resize(0, &path); +} + +void test__fll_path_canonical__root_paths(void **state) { + + const f_string_static_t contents[] = { + macro_f_string_static_t_initialize("/", 0, 1), + macro_f_string_static_t_initialize("//", 0, 2), + macro_f_string_static_t_initialize("///", 0, 3), + macro_f_string_static_t_initialize("/a", 0, 2), + macro_f_string_static_t_initialize("//a", 0, 3), + macro_f_string_static_t_initialize("///a", 0, 4), + macro_f_string_static_t_initialize("/a/", 0, 3), + macro_f_string_static_t_initialize("//a/", 0, 4), + macro_f_string_static_t_initialize("///a/", 0, 5), + macro_f_string_static_t_initialize("/a/b", 0, 4), + macro_f_string_static_t_initialize("//a/b", 0, 5), + macro_f_string_static_t_initialize("///a/b", 0, 6), + macro_f_string_static_t_initialize("/a/b/", 0, 5), + macro_f_string_static_t_initialize("//a/b/", 0, 6), + macro_f_string_static_t_initialize("///a/b/", 0, 7), + macro_f_string_static_t_initialize("/a/b//", 0, 6), + macro_f_string_static_t_initialize("//a/b//", 0, 7), + macro_f_string_static_t_initialize("///a/b//", 0, 8), + }; + + const f_string_static_t expected[] = { + macro_f_string_static_t_initialize("/", 0, 1), + macro_f_string_static_t_initialize("/", 0, 1), + macro_f_string_static_t_initialize("/", 0, 1), + macro_f_string_static_t_initialize("/a", 0, 2), + macro_f_string_static_t_initialize("/a", 0, 2), + macro_f_string_static_t_initialize("/a", 0, 2), + macro_f_string_static_t_initialize("/a", 0, 2), + macro_f_string_static_t_initialize("/a", 0, 2), + macro_f_string_static_t_initialize("/a", 0, 2), + macro_f_string_static_t_initialize("/a/b", 0, 4), + macro_f_string_static_t_initialize("/a/b", 0, 4), + macro_f_string_static_t_initialize("/a/b", 0, 4), + macro_f_string_static_t_initialize("/a/b", 0, 4), + macro_f_string_static_t_initialize("/a/b", 0, 4), + macro_f_string_static_t_initialize("/a/b", 0, 4), + macro_f_string_static_t_initialize("/a/b", 0, 4), + macro_f_string_static_t_initialize("/a/b", 0, 4), + macro_f_string_static_t_initialize("/a/b", 0, 4), + }; + + f_string_dynamic_t path = f_string_dynamic_t_initialize; + + for (uint8_t i = 0; i < 18; ++i) { + + const f_status_t status = fll_path_canonical(contents[i], &path); + + // Assert_string_equal() is NULL terminated, so ensure NULL termination at end of path.used. + if (status == F_none) { + path.string[path.used] = 0; + } + + assert_int_equal(status, F_none); + assert_int_equal(expected[i].used, path.used); + assert_string_equal(expected[i].string, path.string); + } // for + + f_string_dynamic_resize(0, &path); +} + +void test__fll_path_canonical__tilde_remains(void **state) { + + // Paths that don't begin with '/' or '../' will expand to the full PWD. + f_char_t pwd[PATH_MAX + 1]; + + memset(pwd, 0, PATH_MAX + 1); + + getcwd(pwd, PATH_MAX); + + const unsigned int pwd_length = strnlen(pwd, PATH_MAX); + + const f_string_static_t contents[] = { + macro_f_string_static_t_initialize("~", 0, 1), + macro_f_string_static_t_initialize("~/", 0, 2), + macro_f_string_static_t_initialize("~//", 0, 3), + macro_f_string_static_t_initialize("~a", 0, 2), + macro_f_string_static_t_initialize("a~", 0, 2), + macro_f_string_static_t_initialize("a~b", 0, 3), + macro_f_string_static_t_initialize("/~", 0, 2), + macro_f_string_static_t_initialize("//~", 0, 3), + macro_f_string_static_t_initialize("~ ", 0, 2), + macro_f_string_static_t_initialize("~ /", 0, 3), + macro_f_string_static_t_initialize("./~", 0, 3), + macro_f_string_static_t_initialize("./~a", 0, 4), + macro_f_string_static_t_initialize("./a~", 0, 4), + macro_f_string_static_t_initialize("./a~b", 0, 5), + macro_f_string_static_t_initialize("a/~/b", 0, 5), + macro_f_string_static_t_initialize("a/~b", 0, 4), + macro_f_string_static_t_initialize("a/~b/c", 0, 6), + macro_f_string_static_t_initialize("/a/~/b", 0, 6), + macro_f_string_static_t_initialize("/a/~b", 0, 5), + macro_f_string_static_t_initialize("/a/~b/c", 0, 7), + macro_f_string_static_t_initialize("//a/~/b", 0, 7), + macro_f_string_static_t_initialize("//a/~b", 0, 6), + macro_f_string_static_t_initialize("//a/~b/c", 0, 8), + }; + + const f_string_static_t expected[] = { + macro_f_string_static_t_initialize("~", 0, 1), + macro_f_string_static_t_initialize("~", 0, 1), + macro_f_string_static_t_initialize("~", 0, 1), + macro_f_string_static_t_initialize("~a", 0, 2), + macro_f_string_static_t_initialize("a~", 0, 2), + macro_f_string_static_t_initialize("a~b", 0, 3), + macro_f_string_static_t_initialize("/~", 0, 2), + macro_f_string_static_t_initialize("/~", 0, 2), + macro_f_string_static_t_initialize("~ ", 0, 2), + macro_f_string_static_t_initialize("~ ", 0, 2), + macro_f_string_static_t_initialize("~", 0, 1), + macro_f_string_static_t_initialize("~a", 0, 2), + macro_f_string_static_t_initialize("a~", 0, 2), + macro_f_string_static_t_initialize("a~b", 0, 3), + macro_f_string_static_t_initialize("a/~/b", 0, 5), + macro_f_string_static_t_initialize("a/~b", 0, 4), + macro_f_string_static_t_initialize("a/~b/c", 0, 6), + macro_f_string_static_t_initialize("/a/~/b", 0, 6), + macro_f_string_static_t_initialize("/a/~b", 0, 5), + macro_f_string_static_t_initialize("/a/~b/c", 0, 7), + macro_f_string_static_t_initialize("/a/~/b", 0, 6), + macro_f_string_static_t_initialize("/a/~b", 0, 5), + macro_f_string_static_t_initialize("/a/~b/c", 0, 7), + }; + + const uint8_t prepend[] = { + F_true, + F_true, + F_true, + F_true, + F_true, + F_true, + F_false, + F_false, + F_true, + F_true, + F_true, + F_true, + F_true, + F_true, + F_true, + F_true, + F_true, + F_false, + F_false, + F_false, + F_false, + F_false, + F_false, + }; + + f_string_dynamic_t path = f_string_dynamic_t_initialize; + + for (uint8_t i = 0; i < 23; ++i) { + + const f_status_t status = fll_path_canonical(contents[i], &path); + + assert_int_equal(status, F_none); + + // Assert_string_equal() is NULL terminated, so ensure NULL termination at end of path.used. + path.string[path.used] = 0; + + if (prepend[i]) { + f_char_t prepended_string[pwd_length + expected[i].used + 2]; + f_string_static_t prepended = macro_f_string_static_t_initialize(prepended_string, 0, pwd_length + expected[i].used); + + prepended_string[prepended.used] = 0; + prepended_string[prepended.used + 1] = 0; + + if (pwd_length) { + memcpy(prepended_string, pwd, pwd_length); + } + + if (expected[i].used) { + if (pwd_length && prepended_string[pwd_length] != f_path_separator_s.string[0]) { + prepended_string[pwd_length] = f_path_separator_s.string[0]; + memcpy(prepended_string + pwd_length + 1, expected[i].string, expected[i].used); + ++prepended.used; + } + else { + memcpy(prepended_string + pwd_length, expected[i].string, expected[i].used); + } + } + + // The last slash is always removed. + if (prepended.used && prepended_string[prepended.used - 1] == f_path_separator_s.string[0]) { + prepended_string[prepended.used--] = 0; + } + + assert_int_equal(prepended.used, path.used); + assert_string_equal(prepended.string, path.string); + } + else { + assert_int_equal(expected[i].used, path.used); + assert_string_equal(expected[i].string, path.string); + } + } // for + + f_string_dynamic_resize(0, &path); +} + +void test__fll_path_canonical__parameter_checking(void **state) { + + { + const f_status_t status = fll_path_canonical(f_string_empty_s, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_2/fll_path/tests/unit/c/test-path-canonical.h b/level_2/fll_path/tests/unit/c/test-path-canonical.h new file mode 100644 index 0000000..6114e90 --- /dev/null +++ b/level_2/fll_path/tests/unit/c/test-path-canonical.h @@ -0,0 +1,55 @@ +/** + * FLL - Level 2 + * + * Project: IKI + * API Version: 0.6 + * Licenses: lgpl-2.1-or-later + * + * Test the fll_path project. + */ +#ifndef _TEST__FLL_path_canonical_h +#define _TEST__FLL_path_canonical_h + +/** + * Test that function works with back paths (such as '../'). + * + * @see fll_path_canonical() + */ +extern void test__fll_path_canonical__back_paths(void **state); + +/** + * Test that function returns the present working directory when path is an empty string. + * + * @see fll_path_canonical() + */ +extern void test__fll_path_canonical__empty_becomes_pwd(void **state); + +/** + * Test that function works with present directory paths. + * + * @see fll_path_canonical() + */ +extern void test__fll_path_canonical__present_paths(void **state); + +/** + * Test that function works with root paths. + * + * @see fll_path_canonical() + */ +extern void test__fll_path_canonical__root_paths(void **state); + +/** + * Test that function returns the string without expanding the tilde. + * + * @see fll_path_canonical() + */ +extern void test__fll_path_canonical__tilde_remains(void **state); + +/** + * Test that parameter checking works as expected. + * + * @see fll_path_canonical() + */ +extern void test__fll_path_canonical__parameter_checking(void **state); + +#endif // _TEST__FLL_path_canonical_h diff --git a/level_2/fll_path/tests/unit/c/test-path.c b/level_2/fll_path/tests/unit/c/test-path.c new file mode 100644 index 0000000..8b362bb --- /dev/null +++ b/level_2/fll_path/tests/unit/c/test-path.c @@ -0,0 +1,38 @@ +#include "test-path.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int setup(void **state) { + + return 0; +} + +int setdown(void **state) { + + errno = 0; + + return 0; +} + +int main(void) { + + const struct CMUnitTest tests[] = { + cmocka_unit_test(test__fll_path_canonical__back_paths), + cmocka_unit_test(test__fll_path_canonical__empty_becomes_pwd), + cmocka_unit_test(test__fll_path_canonical__present_paths), + cmocka_unit_test(test__fll_path_canonical__root_paths), + cmocka_unit_test(test__fll_path_canonical__tilde_remains), + + #ifndef _di_level_0_parameter_checking_ + cmocka_unit_test(test__fll_path_canonical__parameter_checking), + #endif // _di_level_0_parameter_checking_ + }; + + return cmocka_run_group_tests(tests, setup, setdown); +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_2/fll_path/tests/unit/c/test-path.h b/level_2/fll_path/tests/unit/c/test-path.h new file mode 100644 index 0000000..9e13f2e --- /dev/null +++ b/level_2/fll_path/tests/unit/c/test-path.h @@ -0,0 +1,74 @@ +/** + * FLL - Level 2 + * + * Project: IKI + * API Version: 0.6 + * Licenses: lgpl-2.1-or-later + * + * Test the fll_path project. + */ +#ifndef _TEST__FLL_path_h +#define _TEST__FLL_path_h + +// Libc includes. +#include +#include +#include +#include +#include +#include + +// cmocka includes. +#include + +// FLL-2 includes. +#include + +// Mock includes. +//#include "mock-path.h" + +// Test includes. +#include "test-path-canonical.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Perform any setup operations. + * + * @param state + * The test state. + * + * @return + * The status of this function, where 0 means success. + */ +extern int setup(void **state); + +/** + * Peform any setdown operations. + * + * @param state + * The test state. + * + * @return + * The status of this function, where 0 means success. + */ +extern int setdown(void **state); + +/** + * Run all tests. + * + * @return + * The final result of the tests. + * + * @see cmocka_run_group_tests() + * @see cmocka_unit_test() + */ +extern int main(void); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _TEST__FLL_path_h