From: Kevin Day Date: Fri, 13 May 2022 06:26:33 +0000 (-0500) Subject: Update: Add unit tests for f_path. X-Git-Tag: 0.5.10~144 X-Git-Url: https://git.kevux.org/?a=commitdiff_plain;h=99f55901959e5f9e3e8cd934f3177ce9ad1442db;p=fll Update: Add unit tests for f_path. --- diff --git a/level_0/f_path/data/build/dependencies-tests b/level_0/f_path/data/build/dependencies-tests new file mode 100644 index 0000000..dea3179 --- /dev/null +++ b/level_0/f_path/data/build/dependencies-tests @@ -0,0 +1,3 @@ +# fss-0001 + +cmocka 1.* diff --git a/level_0/f_path/data/build/settings-mocks b/level_0/f_path/data/build/settings-mocks new file mode 100644 index 0000000..a9730e0 --- /dev/null +++ b/level_0/f_path/data/build/settings-mocks @@ -0,0 +1,63 @@ +# fss-0001 +# +# Build the project with appropriate mocks linked in via the dynamic linker's "--wrap" functionality. +# +# The -Wl,--wrap does not work across shared files. +# Therefore, this file is a work-around to inject the mocks into the library for testing purposes. +# This should exactly match the "settings" file, except for the additional "-Wl,--wrap" parts and the additional mock source file. +# +# The flags -o0 must be passed to prevent the compiler from optimizing away any functions being mocked (which results in the mock not happening and a real function being called). +# Alternatively, figure out which optimization that is disabled by -o0 and have that specific optimization disabled. +# + +build_name f_path + +version_major 0 +version_minor 5 +version_micro 9 +version_file micro +version_target minor + +modes individual clang test +modes_default individual + +build_compiler gcc +build_compiler-clang clang +build_indexer ar +build_indexer_arguments rcs +build_language c + +build_libraries -lc +build_libraries-individual -lf_memory -lf_string + +build_sources_library path.c private-path.c path/common.c ../../tests/unit/c/mock-path.c + +build_sources_headers path.h path/common.h + +build_script yes +build_shared yes +build_static no + +path_headers fll/level_0 +path_library_script script +path_library_shared shared +path_library_static static + +has_path_standard yes +preserve_path_headers yes + +search_exclusive yes +search_shared yes +search_static yes + +flags -O0 -z now -g -fdiagnostics-color=always -Wno-logical-not-parentheses -Wno-parentheses +flags-clang -Wno-logical-op-parentheses +flags-test -fstack-protector + +flags_library -fPIC + +# Inject mocks. +flags -Wl,--wrap=chdir +flags -Wl,--wrap=fchdir +flags -Wl,--wrap=getcwd +flags -Wl,--wrap=realpath diff --git a/level_0/f_path/data/build/settings-tests b/level_0/f_path/data/build/settings-tests new file mode 100644 index 0000000..f9fed5a --- /dev/null +++ b/level_0/f_path/data/build/settings-tests @@ -0,0 +1,53 @@ +# fss-0001 +# +# Builds a program that is links to the generated library and is executed to perform tests. +# +# Memory leaks in the test program can be checked for by running valgrind with this executable. +# + +build_name test-f_path + +version_major 0 +version_minor 5 +version_micro 9 +version_file major +version_target major + +modes individual clang test +modes_default individual + +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_string -lf_type_array -lf_utf -lf_path + +build_sources_program test-path-change.c test-path-change_at.c test-path-current.c test-path-directory_cleanup.c test-path-is.c test-path-is_absolute.c test-path-is_relative.c test-path-is_relative_current.c test-path-real.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_program -fPIE diff --git a/level_0/f_path/data/build/testfile b/level_0/f_path/data/build/testfile new file mode 100644 index 0000000..c0f71b4 --- /dev/null +++ b/level_0/f_path/data/build/testfile @@ -0,0 +1,45 @@ +# fss-0005 iki-0002 + +settings: + load_build yes + fail exit + + environment LD_LIBRARY_PATH + +main: + build settings-mocks + build settings-tests + + operate ld_library_path + + if exists build/programs/shared/test-f_path + shell build/programs/shared/test-f_path + + if exists build/programs/static/test-f_path + shell build/programs/static/test-f_path + + if not exists build/programs/shared/test-f_path + and not exists build/programs/static/test-f_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 defined environment LD_LIBRARY_PATH + and defined parameter work + define LD_LIBRARY_PATH 'build/libraries/shared:parameter:"work:value"libraries/shared:define:"LD_LIBRARY_PATH"' + + else + if defined environment LD_LIBRARY_PATH + define LD_LIBRARY_PATH 'build/libraries/shared:parameter:define:"LD_LIBRARY_PATH"' + + else + if defined 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_0/f_path/tests/unit/c/mock-path.c b/level_0/f_path/tests/unit/c/mock-path.c new file mode 100644 index 0000000..ea7d9ff --- /dev/null +++ b/level_0/f_path/tests/unit/c/mock-path.c @@ -0,0 +1,63 @@ +#include "mock-path.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int __wrap_chdir(const char *path) { + + const bool failure = mock_type(bool); + + if (failure) { + errno = mock_type(int); + + return -1; + } + + return mock_type(int); +} + +int __wrap_fchdir(int fd) { + + const bool failure = mock_type(bool); + + if (failure) { + errno = mock_type(int); + + return -1; + } + + return mock_type(int); +} + +char *__wrap_getcwd(char *buf, size_t size) { + + const bool failure = mock_type(bool); + + if (failure) { + errno = mock_type(int); + + return 0; + } + + return mock_type(char *); +} + +char *__wrap_realpath(const char *path, char *resolved_path) { + + const bool failure = mock_type(bool); + + if (failure) { + errno = mock_type(int); + + return 0; + } + + resolved_path = mock_type(char *); + + return resolved_path; +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_path/tests/unit/c/mock-path.h b/level_0/f_path/tests/unit/c/mock-path.h new file mode 100644 index 0000000..505eea4 --- /dev/null +++ b/level_0/f_path/tests/unit/c/mock-path.h @@ -0,0 +1,40 @@ +/** + * FLL - Level 0 + * + * Project: Path + * API Version: 0.5 + * Licenses: lgpl-2.1-or-later + * + * Test the path project. + */ +#ifndef _MOCK__path_h +#define _MOCK__path_h + +// Libc includes. +#include +#include +#include +#include + +// cmocka includes. +#include + +// FLL-0 includes. +#include + +#ifdef __cplusplus +extern "C" { +#endif + +const static int mock_errno_generic = 32767; + +extern int __wrap_chdir(const char *path); +extern int __wrap_fchdir(int fd); +extern char *__wrap_getcwd(char *buf, size_t size); +extern char *__wrap_realpath(const char *path, char *resolved_path); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _MOCK__path_h diff --git a/level_0/f_path/tests/unit/c/test-path-change.c b/level_0/f_path/tests/unit/c/test-path-change.c new file mode 100644 index 0000000..ca8b704 --- /dev/null +++ b/level_0/f_path/tests/unit/c/test-path-change.c @@ -0,0 +1,63 @@ +#include "test-path.h" +#include "test-path-change.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_path_change__fails(void **state) { + + const f_string_static_t path = macro_f_string_static_t_initialize("test", 0, 4); + + int errnos[] = { + EACCES, + EFAULT, + EIO, + ELOOP, + ENAMETOOLONG, + ENOENT, + ENOMEM, + ENOTDIR, + mock_errno_generic, + }; + + f_status_t statuss[] = { + F_access_denied, + F_buffer, + F_input_output, + F_loop, + F_name, + F_file_found_not, + F_memory_not, + F_directory, + F_failure, + }; + + for (int i = 0; i < 9; ++i) { + + will_return(__wrap_chdir, true); + will_return(__wrap_chdir, errnos[i]); + + const f_status_t status = f_path_change(path); + + assert_int_equal(status, F_status_set_error(statuss[i])); + } // for +} + +void test__f_path_change__works(void **state) { + + const f_string_static_t path = macro_f_string_static_t_initialize("test", 0, 4); + + { + will_return(__wrap_chdir, F_false); + will_return(__wrap_chdir, 0); + + const f_status_t status = f_path_change(path); + + assert_int_equal(status, F_none); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_path/tests/unit/c/test-path-change.h b/level_0/f_path/tests/unit/c/test-path-change.h new file mode 100644 index 0000000..9bc56ee --- /dev/null +++ b/level_0/f_path/tests/unit/c/test-path-change.h @@ -0,0 +1,27 @@ +/** + * FLL - Level 0 + * + * Project: Path + * API Version: 0.5 + * Licenses: lgpl-2.1-or-later + * + * Test the path project. + */ +#ifndef _TEST__F_path_change_h +#define _TEST__F_path_change_h + +/** + * Test that function fails. + * + * @see f_path_change() + */ +extern void test__f_path_change__fails(void **state); + +/** + * Test that function works. + * + * @see f_path_change() + */ +extern void test__f_path_change__works(void **state); + +#endif // _TEST__F_path_change_h diff --git a/level_0/f_path/tests/unit/c/test-path-change_at.c b/level_0/f_path/tests/unit/c/test-path-change_at.c new file mode 100644 index 0000000..a13ee01 --- /dev/null +++ b/level_0/f_path/tests/unit/c/test-path-change_at.c @@ -0,0 +1,65 @@ +#include "test-path.h" +#include "test-path-change_at.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_path_change_at__fails(void **state) { + + const int id = 1; + + int errnos[] = { + EACCES, + EBADF, + EFAULT, + EIO, + ELOOP, + ENAMETOOLONG, + ENOENT, + ENOMEM, + ENOTDIR, + mock_errno_generic, + }; + + f_status_t statuss[] = { + F_access_denied, + F_directory_descriptor, + F_buffer, + F_input_output, + F_loop, + F_name, + F_file_found_not, + F_memory_not, + F_directory, + F_failure, + }; + + for (int i = 0; i < 10; ++i) { + + will_return(__wrap_fchdir, true); + will_return(__wrap_fchdir, errnos[i]); + + const f_status_t status = f_path_change_at(id); + + assert_int_equal(status, F_status_set_error(statuss[i])); + } // for +} + +void test__f_path_change_at__works(void **state) { + + const int id = 1; + + { + will_return(__wrap_fchdir, F_false); + will_return(__wrap_fchdir, 0); + + const f_status_t status = f_path_change_at(id); + + assert_int_equal(status, F_none); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_path/tests/unit/c/test-path-change_at.h b/level_0/f_path/tests/unit/c/test-path-change_at.h new file mode 100644 index 0000000..c1e79dd --- /dev/null +++ b/level_0/f_path/tests/unit/c/test-path-change_at.h @@ -0,0 +1,27 @@ +/** + * FLL - Level 0 + * + * Project: Path + * API Version: 0.5 + * Licenses: lgpl-2.1-or-later + * + * Test the path project. + */ +#ifndef _TEST__F_path_change_at_h +#define _TEST__F_path_change_at_h + +/** + * Test that function fails. + * + * @see f_path_change_at() + */ +extern void test__f_path_change_at__fails(void **state); + +/** + * Test that function works. + * + * @see f_path_change_at() + */ +extern void test__f_path_change_at__works(void **state); + +#endif // _TEST__F_path_change_at_h diff --git a/level_0/f_path/tests/unit/c/test-path-current.c b/level_0/f_path/tests/unit/c/test-path-current.c new file mode 100644 index 0000000..5627d2e --- /dev/null +++ b/level_0/f_path/tests/unit/c/test-path-current.c @@ -0,0 +1,140 @@ +#include "test-path.h" +#include "test-path-current.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_path_current__fails(void **state) { + + f_string_dynamic_t destination = f_string_dynamic_t_initialize; + + { + int errnos[] = { + EACCES, + EFAULT, + EINVAL, + ENAMETOOLONG, + ENOENT, + ENOMEM, + ERANGE, + mock_errno_generic, + }; + + f_status_t statuss[] = { + F_access_denied, + F_buffer, + F_parameter, + F_name, + F_file_found_not, + F_memory_not, + F_buffer_too_small, + F_failure, + }; + + for (int i = 0; i < 8; ++i) { + + will_return(__wrap_getcwd, true); + will_return(__wrap_getcwd, errnos[i]); + + const f_status_t status = f_path_current(F_false, &destination); + + assert_int_equal(status, F_status_set_error(statuss[i])); + } // for + } + + destination.used = 0; + + { + int errnos[] = { + EACCES, + EINVAL, + EIO, + ELOOP, + ENAMETOOLONG, + ENOENT, + ENOMEM, + ENOTDIR, + mock_errno_generic, + }; + + f_status_t statuss[] = { + F_access_denied, + F_parameter, + F_input_output, + F_loop, + F_name, + F_file_found_not, + F_memory_not, + F_directory, + F_failure, + }; + + for (int i = 0; i < 9; ++i) { + + will_return(__wrap_getcwd, false); + will_return(__wrap_getcwd, 0); + + will_return(__wrap_realpath, true); + will_return(__wrap_realpath, errnos[i]); + + const f_status_t status = f_path_current(F_true, &destination); + + assert_int_equal(status, F_status_set_error(statuss[i])); + } // for + } + + f_string_dynamic_resize(0, &destination); +} + +#ifndef _di_level_0_parameter_checking_ + void test__f_path_current__parameter_checking(void **state) { + + { + const f_status_t status = f_path_current(F_false, 0); + + assert_int_equal(F_status_set_fine(status), F_parameter); + } + } +#endif // _di_level_0_parameter_checking_ + +void test__f_path_current__works(void **state) { + + const f_string_static_t path = macro_f_string_static_t_initialize("test", 0, 4); + const f_string_static_t path_real = macro_f_string_static_t_initialize("/test", 0, 5); + + f_string_dynamic_t destination = f_string_dynamic_t_initialize; + + { + will_return(__wrap_getcwd, F_false); + will_return(__wrap_getcwd, path.string); + + const f_status_t status = f_path_current(F_false, &destination); + + assert_int_equal(status, F_none); + assert_int_equal(destination.used, path.used); + assert_string_equal(destination.string, path.string); + } + + destination.used = 0; + + { + will_return(__wrap_getcwd, F_false); + will_return(__wrap_getcwd, path.string); + + will_return(__wrap_realpath, F_false); + will_return(__wrap_realpath, path_real.string); + + const f_status_t status = f_path_current(F_true, &destination); + + assert_int_equal(status, F_none); + assert_int_equal(destination.used, path_real.used); + assert_string_equal(destination.string, path_real.string); + } + + f_string_dynamic_resize(0, &destination); +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_path/tests/unit/c/test-path-current.h b/level_0/f_path/tests/unit/c/test-path-current.h new file mode 100644 index 0000000..0f3acb8 --- /dev/null +++ b/level_0/f_path/tests/unit/c/test-path-current.h @@ -0,0 +1,22 @@ +/** + * FLL - Level 0 + * + * Project: Path + * API Version: 0.5 + * Licenses: lgpl-2.1-or-later + * + * Test the path project. + */ +#ifndef _TEST__F_path_current_h +#define _TEST__F_path_current_h + +/** + * Test that parameter checking works as expected. + * + * @see f_path_current() + */ +#ifndef _di_level_0_parameter_checking_ + extern void test__f_path_current__parameter_checking(void **state); +#endif // _di_level_0_parameter_checking_ + +#endif // _TEST__F_path_current_h diff --git a/level_0/f_path/tests/unit/c/test-path-directory_cleanup.c b/level_0/f_path/tests/unit/c/test-path-directory_cleanup.c new file mode 100644 index 0000000..744c616 --- /dev/null +++ b/level_0/f_path/tests/unit/c/test-path-directory_cleanup.c @@ -0,0 +1,83 @@ +#include "test-path.h" +#include "test-path-directory_cleanup.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_level_0_parameter_checking_ + void test__f_path_directory_cleanup__parameter_checking(void **state) { + + const f_string_static_t path = macro_f_string_static_t_initialize("test", 0, 4); + + { + const f_status_t status = f_path_directory_cleanup(path, 0); + + assert_int_equal(F_status_set_fine(status), F_parameter); + } + } +#endif // _di_level_0_parameter_checking_ + +void test__f_path_directory_cleanup__works(void **state) { + + const f_string_static_t paths[] = { + macro_f_string_static_t_initialize("path", 0, 4), + macro_f_string_static_t_initialize("also path", 0, 9), + macro_f_string_static_t_initialize("", 0, 0), + macro_f_string_static_t_initialize("/", 0, 1), + macro_f_string_static_t_initialize("///", 0, 3), + macro_f_string_static_t_initialize("///path", 0, 7), + macro_f_string_static_t_initialize("///path////", 0, 11), + macro_f_string_static_t_initialize("///also////path", 0, 15), + macro_f_string_static_t_initialize("../", 0, 3), + macro_f_string_static_t_initialize("..///", 0, 3), + macro_f_string_static_t_initialize("..///path", 0, 9), + macro_f_string_static_t_initialize("..///path////", 0, 11), + macro_f_string_static_t_initialize("..///also////path", 0, 17), + macro_f_string_static_t_initialize("also///..//path", 0, 15), + }; + + const f_string_static_t expecteds[] = { + macro_f_string_static_t_initialize("path/", 0, 5), + macro_f_string_static_t_initialize("also path/", 0, 10), + macro_f_string_static_t_initialize("", 0, 0), + macro_f_string_static_t_initialize("/", 0, 1), + macro_f_string_static_t_initialize("/", 0, 1), + macro_f_string_static_t_initialize("/path/", 0, 6), + macro_f_string_static_t_initialize("/path/", 0, 6), + macro_f_string_static_t_initialize("/also/path/", 0, 11), + macro_f_string_static_t_initialize("../", 0, 3), + macro_f_string_static_t_initialize("../", 0, 3), + macro_f_string_static_t_initialize("../path/", 0, 8), + macro_f_string_static_t_initialize("../path/", 0, 8), + macro_f_string_static_t_initialize("../also/path/", 0, 13), + macro_f_string_static_t_initialize("also/../path/", 0, 13), + }; + + f_string_dynamic_t destination = f_string_dynamic_t_initialize; + + for (f_array_length_t i = 0; i < 14; ++i, destination.used = 0) { + + const f_status_t status = f_path_directory_cleanup(paths[i], &destination); + + assert_int_equal(status, F_none); + assert_int_equal(destination.used, expecteds[i].used); + + if (destination.used) { + assert_string_equal(destination.string, expecteds[i].string); + + // Check that string is NULL terminated. + assert_true(destination.size > destination.used); + assert_int_equal(destination.string[destination.used], 0); + } + + // De-allocate each pass to ensure that the NULL termination check is accurate. + f_string_dynamic_resize(0, &destination); + } // for + + f_string_dynamic_resize(0, &destination); +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_path/tests/unit/c/test-path-directory_cleanup.h b/level_0/f_path/tests/unit/c/test-path-directory_cleanup.h new file mode 100644 index 0000000..6c64516 --- /dev/null +++ b/level_0/f_path/tests/unit/c/test-path-directory_cleanup.h @@ -0,0 +1,29 @@ +/** + * FLL - Level 0 + * + * Project: Path + * API Version: 0.5 + * Licenses: lgpl-2.1-or-later + * + * Test the path project. + */ +#ifndef _TEST__F_path_directory_cleanup_h +#define _TEST__F_path_directory_cleanup_h + +/** + * Test that parameter checking works as expected. + * + * @see f_path_directory_cleanup() + */ +#ifndef _di_level_0_parameter_checking_ + extern void test__f_path_directory_cleanup__parameter_checking(void **state); +#endif // _di_level_0_parameter_checking_ + +/** + * Test that function works. + * + * @see f_path_directory_cleanup() + */ +extern void test__f_path_directory_cleanup__works(void **state); + +#endif // _TEST__F_path_directory_cleanup_h diff --git a/level_0/f_path/tests/unit/c/test-path-is.c b/level_0/f_path/tests/unit/c/test-path-is.c new file mode 100644 index 0000000..5f1d0dd --- /dev/null +++ b/level_0/f_path/tests/unit/c/test-path-is.c @@ -0,0 +1,53 @@ +#include "test-path.h" +#include "test-path-is.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_path_is__returns_false(void **state) { + + const f_string_static_t paths[] = { + macro_f_string_static_t_initialize("'false", 0, 6), + macro_f_string_static_t_initialize("false'", 0, 6), + macro_f_string_static_t_initialize("f a l s e", 0, 9), + macro_f_string_static_t_initialize("0+-12, false", 0, 12), + }; + + for (uint8_t i = 0; i < 4; ++i) { + + const f_status_t status = f_path_is(paths[i]); + + assert_int_equal(F_status_set_fine(status), F_false); + } // for +} + +void test__f_path_is__returns_data_not(void **state) { + + { + const f_status_t status = f_path_is(f_string_empty_s); + + assert_int_equal(F_status_set_fine(status), F_data_not); + } +} + +void test__f_path_is__returns_true(void **state) { + + const f_string_static_t paths[] = { + macro_f_string_static_t_initialize("'true/", 0, 6), + macro_f_string_static_t_initialize("/true'", 0, 6), + macro_f_string_static_t_initialize("t /r u e", 0, 8), + macro_f_string_static_t_initialize("0+-12,/ true", 0, 12), + }; + + for (uint8_t i = 0; i < 4; ++i) { + + const f_status_t status = f_path_is(paths[i]); + + assert_int_equal(F_status_set_fine(status), F_true); + } // for +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_path/tests/unit/c/test-path-is.h b/level_0/f_path/tests/unit/c/test-path-is.h new file mode 100644 index 0000000..b42dab8 --- /dev/null +++ b/level_0/f_path/tests/unit/c/test-path-is.h @@ -0,0 +1,34 @@ +/** + * FLL - Level 0 + * + * Project: Path + * API Version: 0.5 + * Licenses: lgpl-2.1-or-later + * + * Test the path project. + */ +#ifndef _TEST__F_path_is_h +#define _TEST__F_path_is_h + +/** + * Test that function returns F_false. + * + * @see f_path_is() + */ +extern void test__f_path_is__returns_false(void **state); + +/** + * Test that function returns F_data_not. + * + * @see f_path_is() + */ +extern void test__f_path_is__returns_data_not(void **state); + +/** + * Test that function returns F_true. + * + * @see f_path_is() + */ +extern void test__f_path_is__returns_true(void **state); + +#endif // _TEST__F_path_is_h diff --git a/level_0/f_path/tests/unit/c/test-path-is_absolute.c b/level_0/f_path/tests/unit/c/test-path-is_absolute.c new file mode 100644 index 0000000..eab0ed6 --- /dev/null +++ b/level_0/f_path/tests/unit/c/test-path-is_absolute.c @@ -0,0 +1,53 @@ +#include "test-path.h" +#include "test-path-is_absolute.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_path_is_absolute__returns_false(void **state) { + + const f_string_static_t paths[] = { + macro_f_string_static_t_initialize("'fa/lse", 0, 7), + macro_f_string_static_t_initialize("false'/", 0, 7), + macro_f_string_static_t_initialize("f a l s e", 0, 9), + macro_f_string_static_t_initialize("0+-12,/ false", 0, 13), + }; + + for (uint8_t i = 0; i < 4; ++i) { + + const f_status_t status = f_path_is_absolute(paths[i]); + + assert_int_equal(F_status_set_fine(status), F_false); + } // for +} + +void test__f_path_is_absolute__returns_data_not(void **state) { + + { + const f_status_t status = f_path_is_absolute(f_string_empty_s); + + assert_int_equal(F_status_set_fine(status), F_data_not); + } +} + +void test__f_path_is_absolute__returns_true(void **state) { + + const f_string_static_t paths[] = { + macro_f_string_static_t_initialize("/'true/", 0, 7), + macro_f_string_static_t_initialize("/true'", 0, 6), + macro_f_string_static_t_initialize("/t /r u e", 0, 9), + macro_f_string_static_t_initialize("/0+-12,/ true", 0, 13), + }; + + for (uint8_t i = 0; i < 4; ++i) { + + const f_status_t status = f_path_is_absolute(paths[i]); + + assert_int_equal(F_status_set_fine(status), F_true); + } // for +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_path/tests/unit/c/test-path-is_absolute.h b/level_0/f_path/tests/unit/c/test-path-is_absolute.h new file mode 100644 index 0000000..c31444b --- /dev/null +++ b/level_0/f_path/tests/unit/c/test-path-is_absolute.h @@ -0,0 +1,34 @@ +/** + * FLL - Level 0 + * + * Project: Path + * API Version: 0.5 + * Licenses: lgpl-2.1-or-later + * + * Test the path project. + */ +#ifndef _TEST__F_path_is_absolute_h +#define _TEST__F_path_is_absolute_h + +/** + * Test that function returns F_false. + * + * @see f_path_is_absolute() + */ +extern void test__f_path_is_absolute__returns_false(void **state); + +/** + * Test that function returns F_data_not. + * + * @see f_path_is_absolute() + */ +extern void test__f_path_is_absolute__returns_data_not(void **state); + +/** + * Test that function returns F_true. + * + * @see f_path_is_absolute() + */ +extern void test__f_path_is_absolute__returns_true(void **state); + +#endif // _TEST__F_path_is_absolute_h diff --git a/level_0/f_path/tests/unit/c/test-path-is_relative.c b/level_0/f_path/tests/unit/c/test-path-is_relative.c new file mode 100644 index 0000000..e18b750 --- /dev/null +++ b/level_0/f_path/tests/unit/c/test-path-is_relative.c @@ -0,0 +1,53 @@ +#include "test-path.h" +#include "test-path-is_relative.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_path_is_relative__returns_false(void **state) { + + const f_string_static_t paths[] = { + macro_f_string_static_t_initialize("/'false", 0, 7), + macro_f_string_static_t_initialize("/false'", 0, 7), + macro_f_string_static_t_initialize("/f a l s e", 0, 10), + macro_f_string_static_t_initialize("/0+-12, false", 0, 13), + }; + + for (uint8_t i = 0; i < 4; ++i) { + + const f_status_t status = f_path_is_relative(paths[i]); + + assert_int_equal(F_status_set_fine(status), F_false); + } // for +} + +void test__f_path_is_relative__returns_data_not(void **state) { + + { + const f_status_t status = f_path_is_relative(f_string_empty_s); + + assert_int_equal(F_status_set_fine(status), F_data_not); + } +} + +void test__f_path_is_relative__returns_true(void **state) { + + const f_string_static_t paths[] = { + macro_f_string_static_t_initialize("'true/", 0, 6), + macro_f_string_static_t_initialize("./true'", 0, 7), + macro_f_string_static_t_initialize("t /r u e", 0, 8), + macro_f_string_static_t_initialize("0+-12,/ true", 0, 12), + }; + + for (uint8_t i = 0; i < 4; ++i) { + + const f_status_t status = f_path_is_relative(paths[i]); + + assert_int_equal(F_status_set_fine(status), F_true); + } // for +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_path/tests/unit/c/test-path-is_relative.h b/level_0/f_path/tests/unit/c/test-path-is_relative.h new file mode 100644 index 0000000..6ee94aa --- /dev/null +++ b/level_0/f_path/tests/unit/c/test-path-is_relative.h @@ -0,0 +1,34 @@ +/** + * FLL - Level 0 + * + * Project: Path + * API Version: 0.5 + * Licenses: lgpl-2.1-or-later + * + * Test the path project. + */ +#ifndef _TEST__F_path_is_relative_h +#define _TEST__F_path_is_relative_h + +/** + * Test that function returns F_false. + * + * @see f_path_is_relative() + */ +extern void test__f_path_is_relative__returns_false(void **state); + +/** + * Test that function returns F_data_not. + * + * @see f_path_is_relative() + */ +extern void test__f_path_is_relative__returns_data_not(void **state); + +/** + * Test that function returns F_true. + * + * @see f_path_is_relative() + */ +extern void test__f_path_is_relative__returns_true(void **state); + +#endif // _TEST__F_path_is_relative_h diff --git a/level_0/f_path/tests/unit/c/test-path-is_relative_current.c b/level_0/f_path/tests/unit/c/test-path-is_relative_current.c new file mode 100644 index 0000000..677a1fc --- /dev/null +++ b/level_0/f_path/tests/unit/c/test-path-is_relative_current.c @@ -0,0 +1,53 @@ +#include "test-path.h" +#include "test-path-is_relative_current.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_path_is_relative_current__returns_false(void **state) { + + const f_string_static_t paths[] = { + macro_f_string_static_t_initialize("'false", 0, 6), + macro_f_string_static_t_initialize("false'", 0, 6), + macro_f_string_static_t_initialize("f a l s e", 0, 9), + macro_f_string_static_t_initialize("0+-12, false", 0, 12), + }; + + for (uint8_t i = 0; i < 4; ++i) { + + const f_status_t status = f_path_is_relative_current(paths[i]); + + assert_int_equal(F_status_set_fine(status), F_false); + } // for +} + +void test__f_path_is_relative_current__returns_data_not(void **state) { + + { + const f_status_t status = f_path_is_relative_current(f_string_empty_s); + + assert_int_equal(F_status_set_fine(status), F_data_not); + } +} + +void test__f_path_is_relative_current__returns_true(void **state) { + + const f_string_static_t paths[] = { + macro_f_string_static_t_initialize("./'true/", 0, 8), + macro_f_string_static_t_initialize("../true'", 0, 8), + macro_f_string_static_t_initialize("./../t /r u e", 0, 13), + macro_f_string_static_t_initialize("./0+-12,/ true", 0, 14), + }; + + for (uint8_t i = 0; i < 4; ++i) { + + const f_status_t status = f_path_is_relative_current(paths[i]); + + assert_int_equal(F_status_set_fine(status), F_true); + } // for +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_path/tests/unit/c/test-path-is_relative_current.h b/level_0/f_path/tests/unit/c/test-path-is_relative_current.h new file mode 100644 index 0000000..90ca5a6 --- /dev/null +++ b/level_0/f_path/tests/unit/c/test-path-is_relative_current.h @@ -0,0 +1,34 @@ +/** + * FLL - Level 0 + * + * Project: Path + * API Version: 0.5 + * Licenses: lgpl-2.1-or-later + * + * Test the path project. + */ +#ifndef _TEST__F_path_is_relative_current_h +#define _TEST__F_path_is_relative_current_h + +/** + * Test that function returns F_false. + * + * @see f_path_is_relative_current() + */ +extern void test__f_path_is_relative_current__returns_false(void **state); + +/** + * Test that function returns F_data_not. + * + * @see f_path_is_relative_current() + */ +extern void test__f_path_is_relative_current__returns_data_not(void **state); + +/** + * Test that function returns F_true. + * + * @see f_path_is_relative_current() + */ +extern void test__f_path_is_relative_current__returns_true(void **state); + +#endif // _TEST__F_path_is_relative_current_h diff --git a/level_0/f_path/tests/unit/c/test-path-real.c b/level_0/f_path/tests/unit/c/test-path-real.c new file mode 100644 index 0000000..a3957f6 --- /dev/null +++ b/level_0/f_path/tests/unit/c/test-path-real.c @@ -0,0 +1,87 @@ +#include "test-path.h" +#include "test-path-real.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_path_real__fails(void **state) { + + const f_string_static_t path = macro_f_string_static_t_initialize("test", 0, 4); + + f_string_dynamic_t destination = f_string_dynamic_t_initialize; + + int errnos[] = { + EACCES, + EINVAL, + EIO, + ELOOP, + ENAMETOOLONG, + ENOENT, + ENOMEM, + ENOTDIR, + mock_errno_generic, + }; + + f_status_t statuss[] = { + F_access_denied, + F_parameter, + F_input_output, + F_loop, + F_name, + F_file_found_not, + F_memory_not, + F_directory, + F_failure, + }; + + for (int i = 0; i < 9; ++i, destination.used = 0) { + + will_return(__wrap_realpath, true); + will_return(__wrap_realpath, errnos[i]); + + const f_status_t status = f_path_real(path, &destination); + + assert_int_equal(status, F_status_set_error(statuss[i])); + } // for + + f_string_dynamic_resize(0, &destination); +} + +#ifndef _di_level_0_parameter_checking_ + void test__f_path_real__parameter_checking(void **state) { + + const f_string_static_t path = macro_f_string_static_t_initialize("test", 0, 4); + + { + const f_status_t status = f_path_real(path, 0); + + assert_int_equal(F_status_set_fine(status), F_parameter); + } + } +#endif // _di_level_0_parameter_checking_ + +void test__f_path_real__works(void **state) { + + const f_string_static_t path = macro_f_string_static_t_initialize("test", 0, 4); + const f_string_static_t path_real = macro_f_string_static_t_initialize("/test", 0, 5); + + f_string_dynamic_t destination = f_string_dynamic_t_initialize; + + { + will_return(__wrap_realpath, F_false); + will_return(__wrap_realpath, path_real.string); + + const f_status_t status = f_path_real(path, &destination); + + assert_int_equal(status, F_none); + assert_int_equal(destination.used, path_real.used); + assert_string_equal(destination.string, path_real.string); + } + + f_string_dynamic_resize(0, &destination); +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_path/tests/unit/c/test-path-real.h b/level_0/f_path/tests/unit/c/test-path-real.h new file mode 100644 index 0000000..c6af1ba --- /dev/null +++ b/level_0/f_path/tests/unit/c/test-path-real.h @@ -0,0 +1,36 @@ +/** + * FLL - Level 0 + * + * Project: Path + * API Version: 0.5 + * Licenses: lgpl-2.1-or-later + * + * Test the path project. + */ +#ifndef _TEST__F_path_real_h +#define _TEST__F_path_real_h + +/** + * Test that function fails. + * + * @see f_path_real() + */ +extern void test__f_path_real__fails(void **state); + +/** + * Test that parameter checking works as expected. + * + * @see f_path_real() + */ +#ifndef _di_level_0_parameter_checking_ + extern void test__f_path_real__parameter_checking(void **state); +#endif // _di_level_0_parameter_checking_ + +/** + * Test that function works. + * + * @see f_path_real() + */ +extern void test__f_path_real__works(void **state); + +#endif // _TEST__F_path_real_h diff --git a/level_0/f_path/tests/unit/c/test-path.c b/level_0/f_path/tests/unit/c/test-path.c new file mode 100644 index 0000000..d3d3540 --- /dev/null +++ b/level_0/f_path/tests/unit/c/test-path.c @@ -0,0 +1,68 @@ +#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__f_path_change__fails), + cmocka_unit_test(test__f_path_change__works), + + cmocka_unit_test(test__f_path_change_at__fails), + cmocka_unit_test(test__f_path_change_at__works), + + // test__f_path_directory_cleanup__fails test isn't needed yet as f_string_dynamic_increase_by() aren't tested at this time. + cmocka_unit_test(test__f_path_directory_cleanup__works), + + cmocka_unit_test(test__f_path_is__returns_false), + cmocka_unit_test(test__f_path_is__returns_data_not), + cmocka_unit_test(test__f_path_is__returns_true), + + cmocka_unit_test(test__f_path_is_absolute__returns_false), + cmocka_unit_test(test__f_path_is_absolute__returns_data_not), + cmocka_unit_test(test__f_path_is_absolute__returns_true), + + cmocka_unit_test(test__f_path_is_relative__returns_false), + cmocka_unit_test(test__f_path_is_relative__returns_data_not), + cmocka_unit_test(test__f_path_is_relative__returns_true), + + cmocka_unit_test(test__f_path_is_relative_current__returns_false), + cmocka_unit_test(test__f_path_is_relative_current__returns_data_not), + cmocka_unit_test(test__f_path_is_relative_current__returns_true), + + cmocka_unit_test(test__f_path_real__fails), + cmocka_unit_test(test__f_path_real__works), + + #ifndef _di_level_0_parameter_checking_ + // f_path_change() doesn't use parameter checking. + // f_path_change_at() doesn't use parameter checking. + cmocka_unit_test(test__f_path_current__parameter_checking), + cmocka_unit_test(test__f_path_directory_cleanup__parameter_checking), + // f_path_is() doesn't use parameter checking. + // f_path_is_absolute() doesn't use parameter checking. + // f_path_is_relative() doesn't use parameter checking. + // f_path_is_relative_current() doesn't use parameter checking. + cmocka_unit_test(test__f_path_real__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_0/f_path/tests/unit/c/test-path.h b/level_0/f_path/tests/unit/c/test-path.h new file mode 100644 index 0000000..a8fb827 --- /dev/null +++ b/level_0/f_path/tests/unit/c/test-path.h @@ -0,0 +1,80 @@ +/** + * FLL - Level 0 + * + * Project: Path + * API Version: 0.5 + * Licenses: lgpl-2.1-or-later + * + * Test the path project. + */ +#ifndef _TEST__F_path_h +#define _TEST__F_path_h + +// Libc includes. +#include +#include +#include +#include + +// cmocka includes. +#include + +// FLL-0 includes. +#include + +// Mock includes. +#include "mock-path.h" + +// Test includes. +#include "test-path-change.h" +#include "test-path-change_at.h" +#include "test-path-current.h" +#include "test-path-directory_cleanup.h" +#include "test-path-is.h" +#include "test-path-is_absolute.h" +#include "test-path-is_relative.h" +#include "test-path-is_relative_current.h" +#include "test-path-real.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__F_path_h