From: Kevin Day Date: Fri, 13 May 2022 23:27:25 +0000 (-0500) Subject: Update: Add unit tests for f_pipe. X-Git-Tag: 0.5.10~142 X-Git-Url: https://git.kevux.org/?a=commitdiff_plain;h=69860306ebef6a321f04cf3f15a22b15aebc515f;p=fll Update: Add unit tests for f_pipe. --- diff --git a/level_0/f_pipe/data/build/dependencies-tests b/level_0/f_pipe/data/build/dependencies-tests new file mode 100644 index 0000000..dea3179 --- /dev/null +++ b/level_0/f_pipe/data/build/dependencies-tests @@ -0,0 +1,3 @@ +# fss-0001 + +cmocka 1.* diff --git a/level_0/f_pipe/data/build/settings-mocks b/level_0/f_pipe/data/build/settings-mocks new file mode 100644 index 0000000..c6e225b --- /dev/null +++ b/level_0/f_pipe/data/build/settings-mocks @@ -0,0 +1,50 @@ +# fss-0001 + +build_name f_pipe + +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 + +build_sources_library pipe.c ../../tests/unit/c/mock-pipe.c + +build_sources_headers pipe.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=fstat diff --git a/level_0/f_pipe/data/build/settings-tests b/level_0/f_pipe/data/build/settings-tests new file mode 100644 index 0000000..cae1415 --- /dev/null +++ b/level_0/f_pipe/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_pipe + +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_pipe + +build_sources_program test-pipe-debug_exists.c test-pipe-error_exists.c test-pipe-input_exists.c test-pipe-warning_exists.c +build_sources_program test-pipe.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_pipe/data/build/testfile b/level_0/f_pipe/data/build/testfile new file mode 100644 index 0000000..8737eb9 --- /dev/null +++ b/level_0/f_pipe/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_pipe + shell build/programs/shared/test-f_pipe + + if exists build/programs/static/test-f_pipe + shell build/programs/static/test-f_pipe + + if not exists build/programs/shared/test-f_pipe + and not exists build/programs/static/test-f_pipe + 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_pipe/tests/unit/c/mock-pipe.c b/level_0/f_pipe/tests/unit/c/mock-pipe.c new file mode 100644 index 0000000..3efae8f --- /dev/null +++ b/level_0/f_pipe/tests/unit/c/mock-pipe.c @@ -0,0 +1,38 @@ +#include "mock-pipe.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int __wrap_fstat(int fd, struct stat *statbuf) { + + const bool failure = mock_type(bool); + + if (failure) { + errno = mock_type(int); + + return -1; + } + + struct stat * const mocked_stat = mock_type(struct stat *); + + statbuf->st_dev = mocked_stat->st_dev; + statbuf->st_ino = mocked_stat->st_ino; + statbuf->st_mode = mocked_stat->st_mode; + statbuf->st_nlink = mocked_stat->st_nlink; + statbuf->st_uid = mocked_stat->st_uid; + statbuf->st_gid = mocked_stat->st_gid; + statbuf->st_rdev = mocked_stat->st_rdev; + statbuf->st_size = mocked_stat->st_size; + statbuf->st_blksize = mocked_stat->st_blksize; + statbuf->st_blocks = mocked_stat->st_blocks; + statbuf->st_atime = mocked_stat->st_atime; + statbuf->st_mtime = mocked_stat->st_mtime; + statbuf->st_ctime = mocked_stat->st_ctime; + + return mock_type(int); +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_pipe/tests/unit/c/mock-pipe.h b/level_0/f_pipe/tests/unit/c/mock-pipe.h new file mode 100644 index 0000000..f6b44fe --- /dev/null +++ b/level_0/f_pipe/tests/unit/c/mock-pipe.h @@ -0,0 +1,37 @@ +/** + * FLL - Level 0 + * + * Project: Path + * API Version: 0.5 + * Licenses: lgpl-2.1-or-later + * + * Test the pipe project. + */ +#ifndef _MOCK__pipe_h +#define _MOCK__pipe_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_fstat(int fd, struct stat *statbuf); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _MOCK__pipe_h diff --git a/level_0/f_pipe/tests/unit/c/test-pipe-debug_exists.c b/level_0/f_pipe/tests/unit/c/test-pipe-debug_exists.c new file mode 100644 index 0000000..fa3bb98 --- /dev/null +++ b/level_0/f_pipe/tests/unit/c/test-pipe-debug_exists.c @@ -0,0 +1,75 @@ +#include "test-pipe.h" +#include "test-pipe-debug_exists.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_pipe_debug_exists__fails(void **state) { + + int errnos[] = { + EACCES, + EBADF, + EFAULT, + EINVAL, + ELOOP, + ENAMETOOLONG, + ENOENT, + ENOMEM, + ENOTDIR, + EOVERFLOW, + mock_errno_generic, + }; + + for (int i = 0; i < 11; ++i) { + + will_return(__wrap_fstat, true); + will_return(__wrap_fstat, errnos[i]); + + const f_status_t status = f_pipe_debug_exists(); + + assert_int_equal(status, F_status_set_error(F_file_stat)); + } // for +} + +void test__f_pipe_debug_exists__returns_false(void **state) { + + struct stat statistics; + + memset(&statistics, 0, sizeof(struct stat)); + + { + statistics.st_mode = 1 | S_IFREG; + + will_return(__wrap_fstat, false); + will_return(__wrap_fstat, &statistics); + will_return(__wrap_fstat, 0); + + const f_status_t status = f_pipe_debug_exists(); + + assert_int_equal(status, F_false); + } +} + +void test__f_pipe_debug_exists__returns_true(void **state) { + + struct stat statistics; + + memset(&statistics, 0, sizeof(struct stat)); + + { + statistics.st_mode = 1 | S_IFIFO; + + will_return(__wrap_fstat, false); + will_return(__wrap_fstat, &statistics); + will_return(__wrap_fstat, 0); + + const f_status_t status = f_pipe_debug_exists(); + + assert_int_equal(status, F_true); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_pipe/tests/unit/c/test-pipe-debug_exists.h b/level_0/f_pipe/tests/unit/c/test-pipe-debug_exists.h new file mode 100644 index 0000000..573d299 --- /dev/null +++ b/level_0/f_pipe/tests/unit/c/test-pipe-debug_exists.h @@ -0,0 +1,34 @@ +/** + * FLL - Level 0 + * + * Project: Pipe + * API Version: 0.5 + * Licenses: lgpl-2.1-or-later + * + * Test the pipe project. + */ +#ifndef _TEST__F_pipe_debug_exists_h +#define _TEST__F_pipe_debug_exists_h + +/** + * Test that function fails. + * + * @see f_pipe_debug_exists() + */ +extern void test__f_pipe_debug_exists__fails(void **state); + +/** + * Test that function returns F_false. + * + * @see f_pipe_debug_exists() + */ +extern void test__f_pipe_debug_exists__returns_false(void **state); + +/** + * Test that function returns F_true. + * + * @see f_pipe_debug_exists() + */ +extern void test__f_pipe_debug_exists__returns_true(void **state); + +#endif // _TEST__F_pipe_debug_exists_h diff --git a/level_0/f_pipe/tests/unit/c/test-pipe-error_exists.c b/level_0/f_pipe/tests/unit/c/test-pipe-error_exists.c new file mode 100644 index 0000000..298c4b3 --- /dev/null +++ b/level_0/f_pipe/tests/unit/c/test-pipe-error_exists.c @@ -0,0 +1,75 @@ +#include "test-pipe.h" +#include "test-pipe-error_exists.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_pipe_error_exists__fails(void **state) { + + int errnos[] = { + EACCES, + EBADF, + EFAULT, + EINVAL, + ELOOP, + ENAMETOOLONG, + ENOENT, + ENOMEM, + ENOTDIR, + EOVERFLOW, + mock_errno_generic, + }; + + for (int i = 0; i < 11; ++i) { + + will_return(__wrap_fstat, true); + will_return(__wrap_fstat, errnos[i]); + + const f_status_t status = f_pipe_error_exists(); + + assert_int_equal(status, F_status_set_error(F_file_stat)); + } // for +} + +void test__f_pipe_error_exists__returns_false(void **state) { + + struct stat statistics; + + memset(&statistics, 0, sizeof(struct stat)); + + { + statistics.st_mode = 1 | S_IFREG; + + will_return(__wrap_fstat, false); + will_return(__wrap_fstat, &statistics); + will_return(__wrap_fstat, 0); + + const f_status_t status = f_pipe_error_exists(); + + assert_int_equal(status, F_false); + } +} + +void test__f_pipe_error_exists__returns_true(void **state) { + + struct stat statistics; + + memset(&statistics, 0, sizeof(struct stat)); + + { + statistics.st_mode = 1 | S_IFIFO; + + will_return(__wrap_fstat, false); + will_return(__wrap_fstat, &statistics); + will_return(__wrap_fstat, 0); + + const f_status_t status = f_pipe_error_exists(); + + assert_int_equal(status, F_true); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_pipe/tests/unit/c/test-pipe-error_exists.h b/level_0/f_pipe/tests/unit/c/test-pipe-error_exists.h new file mode 100644 index 0000000..2c38f54 --- /dev/null +++ b/level_0/f_pipe/tests/unit/c/test-pipe-error_exists.h @@ -0,0 +1,34 @@ +/** + * FLL - Level 0 + * + * Project: Pipe + * API Version: 0.5 + * Licenses: lgpl-2.1-or-later + * + * Test the pipe project. + */ +#ifndef _TEST__F_pipe_error_exists_h +#define _TEST__F_pipe_error_exists_h + +/** + * Test that function fails. + * + * @see f_pipe_error_exists() + */ +extern void test__f_pipe_error_exists__fails(void **state); + +/** + * Test that function returns F_false. + * + * @see f_pipe_error_exists() + */ +extern void test__f_pipe_error_exists__returns_false(void **state); + +/** + * Test that function returns F_true. + * + * @see f_pipe_error_exists() + */ +extern void test__f_pipe_error_exists__returns_true(void **state); + +#endif // _TEST__F_pipe_error_exists_h diff --git a/level_0/f_pipe/tests/unit/c/test-pipe-input_exists.c b/level_0/f_pipe/tests/unit/c/test-pipe-input_exists.c new file mode 100644 index 0000000..0911556 --- /dev/null +++ b/level_0/f_pipe/tests/unit/c/test-pipe-input_exists.c @@ -0,0 +1,75 @@ +#include "test-pipe.h" +#include "test-pipe-input_exists.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_pipe_input_exists__fails(void **state) { + + int errnos[] = { + EACCES, + EBADF, + EFAULT, + EINVAL, + ELOOP, + ENAMETOOLONG, + ENOENT, + ENOMEM, + ENOTDIR, + EOVERFLOW, + mock_errno_generic, + }; + + for (int i = 0; i < 11; ++i) { + + will_return(__wrap_fstat, true); + will_return(__wrap_fstat, errnos[i]); + + const f_status_t status = f_pipe_input_exists(); + + assert_int_equal(status, F_status_set_error(F_file_stat)); + } // for +} + +void test__f_pipe_input_exists__returns_false(void **state) { + + struct stat statistics; + + memset(&statistics, 0, sizeof(struct stat)); + + { + statistics.st_mode = 1 | S_IFREG; + + will_return(__wrap_fstat, false); + will_return(__wrap_fstat, &statistics); + will_return(__wrap_fstat, 0); + + const f_status_t status = f_pipe_input_exists(); + + assert_int_equal(status, F_false); + } +} + +void test__f_pipe_input_exists__returns_true(void **state) { + + struct stat statistics; + + memset(&statistics, 0, sizeof(struct stat)); + + { + statistics.st_mode = 1 | S_IFIFO; + + will_return(__wrap_fstat, false); + will_return(__wrap_fstat, &statistics); + will_return(__wrap_fstat, 0); + + const f_status_t status = f_pipe_input_exists(); + + assert_int_equal(status, F_true); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_pipe/tests/unit/c/test-pipe-input_exists.h b/level_0/f_pipe/tests/unit/c/test-pipe-input_exists.h new file mode 100644 index 0000000..1cda8d9 --- /dev/null +++ b/level_0/f_pipe/tests/unit/c/test-pipe-input_exists.h @@ -0,0 +1,34 @@ +/** + * FLL - Level 0 + * + * Project: Pipe + * API Version: 0.5 + * Licenses: lgpl-2.1-or-later + * + * Test the pipe project. + */ +#ifndef _TEST__F_pipe_input_exists_h +#define _TEST__F_pipe_input_exists_h + +/** + * Test that function fails. + * + * @see f_pipe_input_exists() + */ +extern void test__f_pipe_input_exists__fails(void **state); + +/** + * Test that function returns F_false. + * + * @see f_pipe_input_exists() + */ +extern void test__f_pipe_input_exists__returns_false(void **state); + +/** + * Test that function returns F_true. + * + * @see f_pipe_input_exists() + */ +extern void test__f_pipe_input_exists__returns_true(void **state); + +#endif // _TEST__F_pipe_input_exists_h diff --git a/level_0/f_pipe/tests/unit/c/test-pipe-warning_exists.c b/level_0/f_pipe/tests/unit/c/test-pipe-warning_exists.c new file mode 100644 index 0000000..f0b08ce --- /dev/null +++ b/level_0/f_pipe/tests/unit/c/test-pipe-warning_exists.c @@ -0,0 +1,75 @@ +#include "test-pipe.h" +#include "test-pipe-warning_exists.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_pipe_warning_exists__fails(void **state) { + + int errnos[] = { + EACCES, + EBADF, + EFAULT, + EINVAL, + ELOOP, + ENAMETOOLONG, + ENOENT, + ENOMEM, + ENOTDIR, + EOVERFLOW, + mock_errno_generic, + }; + + for (int i = 0; i < 11; ++i) { + + will_return(__wrap_fstat, true); + will_return(__wrap_fstat, errnos[i]); + + const f_status_t status = f_pipe_warning_exists(); + + assert_int_equal(status, F_status_set_error(F_file_stat)); + } // for +} + +void test__f_pipe_warning_exists__returns_false(void **state) { + + struct stat statistics; + + memset(&statistics, 0, sizeof(struct stat)); + + { + statistics.st_mode = 1 | S_IFREG; + + will_return(__wrap_fstat, false); + will_return(__wrap_fstat, &statistics); + will_return(__wrap_fstat, 0); + + const f_status_t status = f_pipe_warning_exists(); + + assert_int_equal(status, F_false); + } +} + +void test__f_pipe_warning_exists__returns_true(void **state) { + + struct stat statistics; + + memset(&statistics, 0, sizeof(struct stat)); + + { + statistics.st_mode = 1 | S_IFIFO; + + will_return(__wrap_fstat, false); + will_return(__wrap_fstat, &statistics); + will_return(__wrap_fstat, 0); + + const f_status_t status = f_pipe_warning_exists(); + + assert_int_equal(status, F_true); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_pipe/tests/unit/c/test-pipe-warning_exists.h b/level_0/f_pipe/tests/unit/c/test-pipe-warning_exists.h new file mode 100644 index 0000000..8854b9c --- /dev/null +++ b/level_0/f_pipe/tests/unit/c/test-pipe-warning_exists.h @@ -0,0 +1,34 @@ +/** + * FLL - Level 0 + * + * Project: Pipe + * API Version: 0.5 + * Licenses: lgpl-2.1-or-later + * + * Test the pipe project. + */ +#ifndef _TEST__F_pipe_warning_exists_h +#define _TEST__F_pipe_warning_exists_h + +/** + * Test that function fails. + * + * @see f_pipe_warning_exists() + */ +extern void test__f_pipe_warning_exists__fails(void **state); + +/** + * Test that function returns F_false. + * + * @see f_pipe_warning_exists() + */ +extern void test__f_pipe_warning_exists__returns_false(void **state); + +/** + * Test that function returns F_true. + * + * @see f_pipe_warning_exists() + */ +extern void test__f_pipe_warning_exists__returns_true(void **state); + +#endif // _TEST__F_pipe_warning_exists_h diff --git a/level_0/f_pipe/tests/unit/c/test-pipe.c b/level_0/f_pipe/tests/unit/c/test-pipe.c new file mode 100644 index 0000000..c82d7ee --- /dev/null +++ b/level_0/f_pipe/tests/unit/c/test-pipe.c @@ -0,0 +1,51 @@ +#include "test-pipe.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_pipe_debug_exists__fails), + cmocka_unit_test(test__f_pipe_debug_exists__returns_false), + cmocka_unit_test(test__f_pipe_debug_exists__returns_true), + + cmocka_unit_test(test__f_pipe_error_exists__fails), + cmocka_unit_test(test__f_pipe_error_exists__returns_false), + cmocka_unit_test(test__f_pipe_error_exists__returns_true), + + cmocka_unit_test(test__f_pipe_input_exists__fails), + cmocka_unit_test(test__f_pipe_input_exists__returns_false), + cmocka_unit_test(test__f_pipe_input_exists__returns_true), + + cmocka_unit_test(test__f_pipe_warning_exists__fails), + cmocka_unit_test(test__f_pipe_warning_exists__returns_false), + cmocka_unit_test(test__f_pipe_warning_exists__returns_true), + + #ifndef _di_level_0_parameter_checking_ + // f_pipe_debug_exists() doesn't use parameter checking. + // f_pipe_error_exists() doesn't use parameter checking. + // f_pipe_input_exists() doesn't use parameter checking. + // f_pipe_warning_exists() doesn't use 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_pipe/tests/unit/c/test-pipe.h b/level_0/f_pipe/tests/unit/c/test-pipe.h new file mode 100644 index 0000000..1d0e9d6 --- /dev/null +++ b/level_0/f_pipe/tests/unit/c/test-pipe.h @@ -0,0 +1,76 @@ +/** + * FLL - Level 0 + * + * Project: IKI + * API Version: 0.5 + * Licenses: lgpl-2.1-or-later + * + * Test the pipe project. + */ +#ifndef _TEST__F_pipe_h +#define _TEST__F_pipe_h + +// Libc includes. +#include +#include +#include +#include +#include + +// cmocka includes. +#include + +// FLL-0 includes. +#include + +// Mock includes. +#include "mock-pipe.h" + +// Test includes. +#include "test-pipe-debug_exists.h" +#include "test-pipe-error_exists.h" +#include "test-pipe-input_exists.h" +#include "test-pipe-warning_exists.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_pipe_h