From: Kevin Day Date: Tue, 11 Mar 2025 04:47:08 +0000 (-0500) Subject: Progress: Continue working on completing the remove program. X-Git-Url: https://git.kevux.org/?a=commitdiff_plain;h=e486448494c9bed623eaa7c1ee44bba553170939;p=kevux-tools Progress: Continue working on completing the remove program. Fix a bug exposed by the directory unit tests where the `recurse.path_top` is not being defined and must be. Add additional safety checks to fall back to a NULL string if `recurse.path_top` is NULL. Add basic file and directory tests. There are still a lot more tests to write. This should be an acceptable start. Refresh the stand alone build settings and config.h files. --- diff --git a/data/build/remove/settings-mocks.remove b/data/build/remove/settings-mocks.remove index 1b41928..44e30b6 100644 --- a/data/build/remove/settings-mocks.remove +++ b/data/build/remove/settings-mocks.remove @@ -85,8 +85,13 @@ flags_library -fPIC flags_program-android -fPIE -Wl,-z,relro # Inject mocks. +flags -Wl,--wrap=f_directory_empty +flags -Wl,--wrap=f_directory_is flags -Wl,--wrap=f_directory_remove flags -Wl,--wrap=f_file_exists +flags -Wl,--wrap=f_file_is flags -Wl,--wrap=f_file_remove +flags -Wl,--wrap=f_file_stat +flags -Wl,--wrap=fl_directory_do flags -Wl,--wrap=fll_program_print_version flags -Wl,--wrap=kt_remove_print_message_help diff --git a/data/build/remove/settings-tests.remove b/data/build/remove/settings-tests.remove index 5df8f23..beeb297 100644 --- a/data/build/remove/settings-tests.remove +++ b/data/build/remove/settings-tests.remove @@ -31,7 +31,7 @@ build_libraries-individual_thread -lf_thread build_sources_program test-remove.c build_sources_program test-remove-print_help.c test-remove-print_version.c -build_sources_program test-remove-regular_no_args.c +build_sources_program test-remove-directory_no_args.c test-remove-regular_no_args.c build_script no build_shared yes diff --git a/data/build/stand_alone/configs/remove-config.h b/data/build/stand_alone/configs/remove-config.h index faf74ae..b8425b8 100644 --- a/data/build/stand_alone/configs/remove-config.h +++ b/data/build/stand_alone/configs/remove-config.h @@ -240,7 +240,7 @@ //#define _di_f_directory_exists_ #define _di_f_directory_exists_at_ //#define _di_f_directory_flag_d_ -#define _di_f_directory_is_ +//#define _di_f_directory_is_ #define _di_f_directory_is_at_ #define _di_f_directory_list_ #define _di_f_directory_listing_delete_ @@ -1071,7 +1071,7 @@ #define _di_f_string_mash_nulless_ #define _di_f_string_mish_ #define _di_f_string_mish_nulless_ -#define _di_f_string_null_s_ +//#define _di_f_string_null_s_ #define _di_f_string_placeholder_s_ #define _di_f_string_prepend_ #define _di_f_string_prepend_assure_ diff --git a/data/build/stand_alone/settings/settings.remove b/data/build/stand_alone/settings/settings.remove index e977fca..d505fdc 100644 --- a/data/build/stand_alone/settings/settings.remove +++ b/data/build/stand_alone/settings/settings.remove @@ -71,7 +71,7 @@ build_sources_program fll/level_2/error.c fll/level_2/private-error.c fll/level_ build_sources_program fll/level_2/print.c build_sources_program fll/level_2/program.c fll/level_2/program/common.c fll/level_2/program/print.c fll/level_2/private-program.c -build_sources_program program/kevux/tools/remove/main/common.c program/kevux/tools/remove/main/common/define.c program/kevux/tools/remove/main/common/enumeration.c program/kevux/tools/remove/main/common/print.c program/kevux/tools/remove/main/common/string.c program/kevux/tools/remove/main/common/type.c program/kevux/tools/remove/main/convert.c program/kevux/tools/remove/main/operate.c program/kevux/tools/remove/main/preprocess.c program/kevux/tools/remove/main/print/error.c program/kevux/tools/remove/main/print/message.c program/kevux/tools/remove/main/print/simulate.c program/kevux/tools/remove/main/print/verbose.c program/kevux/tools/remove/main/print/warning.c program/kevux/tools/remove/main/remove.c program/kevux/tools/remove/main/signal.c program/kevux/tools/remove/main/thread.c +build_sources_program program/kevux/tools/remove/main/common.c program/kevux/tools/remove/main/common/define.c program/kevux/tools/remove/main/common/enumeration.c program/kevux/tools/remove/main/common/print.c program/kevux/tools/remove/main/common/string.c program/kevux/tools/remove/main/common/type.c program/kevux/tools/remove/main/convert.c program/kevux/tools/remove/main/operate.c program/kevux/tools/remove/main/preprocess.c program/kevux/tools/remove/main/print/debug.c program/kevux/tools/remove/main/print/error.c program/kevux/tools/remove/main/print/message.c program/kevux/tools/remove/main/print/simulate.c program/kevux/tools/remove/main/print/verbose.c program/kevux/tools/remove/main/print/warning.c program/kevux/tools/remove/main/remove.c program/kevux/tools/remove/main/signal.c program/kevux/tools/remove/main/thread.c build_sources_program program/kevux/tools/remove/remove/config.c program/kevux/tools/remove/remove/remove.c program/kevux/tools/remove/remove/main.c program/kevux/tools/remove/remove/string.c diff --git a/sources/c/program/kevux/tools/remove/main/operate.c b/sources/c/program/kevux/tools/remove/main/operate.c index b02d2b6..1e6056a 100644 --- a/sources/c/program/kevux/tools/remove/main/operate.c +++ b/sources/c/program/kevux/tools/remove/main/operate.c @@ -50,8 +50,9 @@ extern "C" { recurse.state.code = flag_operate; recurse.state.interrupt = &kt_remove_signal_check_recurse; - recurse.flag = f_directory_recurse_do_flag_list_e | f_directory_recurse_do_flag_top_after_e; recurse.depth_max = main->setting.flag & kt_remove_main_flag_recurse_d ? kt_remove_depth_max_d : 0; + recurse.flag = f_directory_recurse_do_flag_list_e | f_directory_recurse_do_flag_top_after_e; + recurse.path_top = &path; recurse.action = &kt_remove_operate_file_directory_action; recurse.handle = &kt_remove_operate_file_recurse_handle; @@ -59,10 +60,12 @@ extern "C" { fl_directory_do(path, &recurse); const f_status_t status = f_directory_recurse_do_delete(&recurse); - if (F_status_is_error(recurse.state.status)) return recurse.state.status; - if (F_status_is_error(status)) return status; - return F_yes; + return F_status_is_error(recurse.state.status) + ? recurse.state.status + : F_status_is_error(status) + ? status + : F_yes; } #endif // _di_kt_remove_operate_file_directory_ @@ -72,7 +75,11 @@ extern "C" { if (!recurse || !recurse->state.custom || F_status_set_fine(recurse->state.status) == F_interrupt) return; if (!kt_remove_operate_shall_remove(recurse->state.code) || !(flag & f_directory_recurse_do_flag_action_e)) return; - const f_string_static_t path = flag & f_directory_recurse_do_flag_top_after_e ? *recurse->path_top : recurse->path; + const f_string_static_t path = flag & f_directory_recurse_do_flag_top_after_e + ? recurse->path_top + ? *recurse->path_top + : f_string_null_s + : recurse->path; recurse->state.status = kt_remove_operate_file_remove( (kt_remove_main_t *) recurse->state.custom, diff --git a/sources/c/program/kevux/tools/remove/main/preprocess.c b/sources/c/program/kevux/tools/remove/main/preprocess.c index 1e1bc4b..c23eaf1 100644 --- a/sources/c/program/kevux/tools/remove/main/preprocess.c +++ b/sources/c/program/kevux/tools/remove/main/preprocess.c @@ -349,8 +349,9 @@ extern "C" { recurse.state.code = flag_operate; recurse.state.interrupt = &kt_remove_signal_check_recurse; - recurse.flag = f_directory_recurse_do_flag_list_e | f_directory_recurse_do_flag_top_after_e; recurse.depth_max = main->setting.flag & kt_remove_main_flag_recurse_d ? kt_remove_depth_max_d : 0; + recurse.flag = f_directory_recurse_do_flag_list_e | f_directory_recurse_do_flag_top_after_e; + recurse.path_top = &path; recurse.action = &kt_remove_preprocess_file_recurse_action; recurse.handle = &kt_remove_operate_file_recurse_handle; diff --git a/tests/unit/remove/c/mock-remove.c b/tests/unit/remove/c/mock-remove.c index 3153283..0ebdeb7 100644 --- a/tests/unit/remove/c/mock-remove.c +++ b/tests/unit/remove/c/mock-remove.c @@ -5,35 +5,52 @@ extern "C" { #endif int mock_unwrap = 0; +f_status_t mock_directory_call_action = 0; f_status_t mock_status = 0; -f_status_t __wrap_f_directory_remove(const f_string_static_t path, const int depth_max, const bool preserve) { - - const bool failure = mock_type(bool); +f_status_t __wrap_f_directory_empty(const f_string_static_t path) { + return mock_type(f_status_t); +} - if (failure) return mock_type(f_status_t); +f_status_t __wrap_f_directory_is(const f_string_static_t path) { + return mock_type(f_status_t); +} +f_status_t __wrap_f_directory_remove(const f_string_static_t path, const int depth_max, const bool preserve) { return mock_type(f_status_t); } f_status_t __wrap_f_file_exists(const f_string_static_t path, const bool dereference) { + return mock_type(f_status_t); +} - const bool failure = mock_type(bool); - - if (failure) return mock_type(f_status_t); - +f_status_t __wrap_f_file_is(const f_string_static_t path, const int type, const bool dereference) { return mock_type(f_status_t); } f_status_t __wrap_f_file_remove(const f_string_static_t path) { + return mock_type(f_status_t); +} - const bool failure = mock_type(bool); +f_status_t __wrap_f_file_stat(const f_string_static_t path, const bool dereference, struct stat * const stat_file) { - if (failure) return mock_type(f_status_t); + struct stat * const mocked_stat = mock_ptr_type(struct stat *); + + memmove(stat_file, mocked_stat, sizeof(struct stat)); return mock_type(f_status_t); } +void __wrap_fl_directory_do(const f_string_static_t path, f_directory_recurse_do_t * const recurse) { + + if (mock_directory_call_action) { + recurse->action(recurse, path, mock_type(uint32_t)); + } + else { + recurse->state.status = mock_type(f_status_t); + } +} + f_status_t __wrap_fll_program_print_version(fl_print_t * const print, const f_string_static_t version) { mock_status = mock_type(f_status_t); diff --git a/tests/unit/remove/c/mock-remove.h b/tests/unit/remove/c/mock-remove.h index 7693110..213ba46 100644 --- a/tests/unit/remove/c/mock-remove.h +++ b/tests/unit/remove/c/mock-remove.h @@ -30,12 +30,19 @@ extern "C" { const static int mock_errno_generic = 32767; extern int mock_unwrap; +extern f_status_t mock_directory_call_action; extern f_status_t mock_status; +extern f_status_t __wrap_f_directory_empty(const f_string_static_t path); +extern f_status_t __wrap_f_directory_is(const f_string_static_t path); extern f_status_t __wrap_f_directory_remove(const f_string_static_t path, const int depth_max, const bool preserve); extern f_status_t __wrap_f_file_exists(const f_string_static_t path, const bool dereference); +extern f_status_t __wrap_f_file_is(const f_string_static_t path, const int type, const bool dereference); extern f_status_t __wrap_f_file_remove(const f_string_static_t path); +extern f_status_t __wrap_f_file_stat(const f_string_static_t path, const bool dereference, struct stat * const stat_file); + +extern void __wrap_fl_directory_do(const f_string_static_t path, f_directory_recurse_do_t * const recurse); extern f_status_t __wrap_fll_program_print_version(fl_print_t * const print, const f_string_static_t version); diff --git a/tests/unit/remove/c/test-remove-directory_no_args.c b/tests/unit/remove/c/test-remove-directory_no_args.c new file mode 100644 index 0000000..e4229a2 --- /dev/null +++ b/tests/unit/remove/c/test-remove-directory_no_args.c @@ -0,0 +1,213 @@ +#include "test-remove.h" +#include "test-remove-directory_no_args.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void test__kt_remove__directory_no_args__empty_exists_link(void **state) { + + mock_unwrap = 0; + mock_directory_call_action = F_true; + + struct stat statistics; + + { + const f_string_t argv[] = { "mocked_main", "to_remove", 0 }; + + memset(&statistics, 0, sizeof(struct stat)); + statistics.st_mode = F_file_mode_all_d | F_file_type_directory_d; // Should result in kt_remove_flag_file_operate_remove_d. + + // Pre-process file. + will_return(__wrap_f_file_exists, F_true); + will_return(__wrap_f_file_is, F_true); // A link, kt_remove_flag_file_operate_link_d is set. + will_return(__wrap_f_file_stat, &statistics); + will_return(__wrap_f_file_stat, F_false); + + // Directory processing. + will_return(__wrap_f_directory_empty, F_true); + will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_top_after_e); + will_return(__wrap_f_directory_is, F_true); + + // This will fail if f_directory_remove() is not called, therefore success here means f_directory_remove has been called. + will_return(__wrap_f_directory_remove, F_okay); + + const int result = kt_main_test__remove(2, argv, 0); + + assert_int_equal(result, 0); + } + + { + const f_string_t argv[] = { "mocked_main", "to_remove", "+V", 0 }; + + memset(&statistics, 0, sizeof(struct stat)); + statistics.st_mode = F_file_mode_all_d | F_file_type_directory_d; // Should result in kt_remove_flag_file_operate_remove_d. + + // Pre-process file. + will_return(__wrap_f_file_exists, F_true); + will_return(__wrap_f_file_is, F_true); // A link, kt_remove_flag_file_operate_link_d is set. + will_return(__wrap_f_file_stat, &statistics); + will_return(__wrap_f_file_stat, F_false); + + // Directory processing. + will_return(__wrap_f_directory_empty, F_true); + will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_top_after_e); + will_return(__wrap_f_directory_is, F_true); + + // This will fail if f_directory_remove() is not called, therefore success here means f_directory_remove has been called. + will_return(__wrap_f_directory_remove, F_okay); + + const int result = kt_main_test__remove(3, argv, 0); + + assert_int_equal(result, 0); + } + + { + const f_string_t argv[] = { "mocked_main", "to_remove", "+D", 0 }; + + memset(&statistics, 0, sizeof(struct stat)); + statistics.st_mode = F_file_mode_all_d | F_file_type_directory_d; // Should result in kt_remove_flag_file_operate_remove_d. + + // Pre-process file. + will_return(__wrap_f_file_exists, F_true); + will_return(__wrap_f_file_is, F_true); // A link, kt_remove_flag_file_operate_link_d is set. + will_return(__wrap_f_file_stat, &statistics); + will_return(__wrap_f_file_stat, F_false); + + // Directory processing. + will_return(__wrap_f_directory_empty, F_true); + will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_top_after_e); + will_return(__wrap_f_directory_is, F_true); + + // This will fail if f_directory_remove() is not called, therefore success here means f_directory_remove has been called. + will_return(__wrap_f_directory_remove, F_okay); + + const int result = kt_main_test__remove(3, argv, 0); + + assert_int_equal(result, 0); + } +} + +void test__kt_remove__directory_no_args__empty_exists_link_not(void **state) { + + mock_unwrap = 0; + mock_directory_call_action = F_true; + + struct stat statistics; + + { + const f_string_t argv[] = { "mocked_main", "to_remove", 0 }; + + memset(&statistics, 0, sizeof(struct stat)); + statistics.st_mode = F_file_mode_all_d | F_file_type_directory_d; // Should result in kt_remove_flag_file_operate_remove_d. + + // Pre-process file. + will_return(__wrap_f_file_exists, F_true); + will_return(__wrap_f_file_is, F_false); // A link, kt_remove_flag_file_operate_link_d is not set. + will_return(__wrap_f_file_stat, &statistics); + will_return(__wrap_f_file_stat, F_false); + + // Directory processing. + will_return(__wrap_f_directory_empty, F_true); + will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_top_after_e); + will_return(__wrap_f_directory_is, F_true); + + // This will fail if f_directory_remove() is not called, therefore success here means f_directory_remove has been called. + will_return(__wrap_f_directory_remove, F_okay); + + const int result = kt_main_test__remove(3, argv, 0); + + assert_int_equal(result, 0); + } + + { + const f_string_t argv[] = { "mocked_main", "to_remove", "+V", 0 }; + + memset(&statistics, 0, sizeof(struct stat)); + statistics.st_mode = F_file_mode_all_d | F_file_type_directory_d; // Should result in kt_remove_flag_file_operate_remove_d. + + // Pre-process file. + will_return(__wrap_f_file_exists, F_true); + will_return(__wrap_f_file_is, F_false); // A link, kt_remove_flag_file_operate_link_d is not set. + will_return(__wrap_f_file_stat, &statistics); + will_return(__wrap_f_file_stat, F_false); + + // Directory processing. + will_return(__wrap_f_directory_empty, F_true); + will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_top_after_e); + will_return(__wrap_f_directory_is, F_true); + + // This will fail if f_directory_remove() is not called, therefore success here means f_directory_remove has been called. + will_return(__wrap_f_directory_remove, F_okay); + + const int result = kt_main_test__remove(3, argv, 0); + + assert_int_equal(result, 0); + } + + { + const f_string_t argv[] = { "mocked_main", "to_remove", "+D", 0 }; + + memset(&statistics, 0, sizeof(struct stat)); + statistics.st_mode = F_file_mode_all_d | F_file_type_directory_d; // Should result in kt_remove_flag_file_operate_remove_d. + + // Pre-process file. + will_return(__wrap_f_file_exists, F_true); + will_return(__wrap_f_file_is, F_false); // A link, kt_remove_flag_file_operate_link_d is not set. + will_return(__wrap_f_file_stat, &statistics); + will_return(__wrap_f_file_stat, F_false); + + // Directory processing. + will_return(__wrap_f_directory_empty, F_true); + will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_top_after_e); + will_return(__wrap_f_directory_is, F_true); + + // This will fail if f_directory_remove() is not called, therefore success here means f_directory_remove has been called. + will_return(__wrap_f_directory_remove, F_okay); + + const int result = kt_main_test__remove(3, argv, 0); + + assert_int_equal(result, 0); + } +} + +void test__kt_remove__directory_no_args__empty_exists_not(void **state) { + + mock_unwrap = 0; + + { + const f_string_t argv[] = { "mocked_main", "to_remove", 0 }; + + will_return(__wrap_f_file_exists, F_false); + + const int result = kt_main_test__remove(2, argv, 0); + + assert_int_equal(result, 0); + } + + { + const f_string_t argv[] = { "mocked_main", "to_remove", "+V", 0 }; + + will_return(__wrap_f_file_exists, F_false); + + const int result = kt_main_test__remove(3, argv, 0); + + assert_int_equal(result, 0); + } + + { + const f_string_t argv[] = { "mocked_main", "to_remove", "+D", 0 }; + + will_return(__wrap_f_file_exists, F_false); + + const int result = kt_main_test__remove(3, argv, 0); + + assert_int_equal(result, 0); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/tests/unit/remove/c/test-remove-directory_no_args.h b/tests/unit/remove/c/test-remove-directory_no_args.h new file mode 100644 index 0000000..b2c048d --- /dev/null +++ b/tests/unit/remove/c/test-remove-directory_no_args.h @@ -0,0 +1,28 @@ +/** + * Kevux Tools - Remove + * + * Project: Kevux Tools + * API Version: 0.5 + * Licenses: lgpl-2.1-or-later + * + * Test the remove. + */ +#ifndef _TEST__KT_remove__directory_no_args +#define _TEST__KT_remove__directory_no_args + +/** + * Test that the remove works for file that exists and is a link, for directory files (that are empty) without other complex arguments. + */ +extern void test__kt_remove__directory_no_args__empty_exists_link(void **state); + +/** + * Test that the remove works for file that exists and is a not link, for directory files (that are empty) without other complex arguments. + */ +extern void test__kt_remove__directory_no_args__empty_exists_link_not(void **state); + +/** + * Test that the remove works for file that does not exist, for directory files (that are empty) without other complex arguments. + */ +extern void test__kt_remove__directory_no_args__empty_exists_not(void **state); + +#endif // _TEST__KT_remove__directory_no_args diff --git a/tests/unit/remove/c/test-remove-regular_no_args.c b/tests/unit/remove/c/test-remove-regular_no_args.c index bceed4f..2e4edec 100644 --- a/tests/unit/remove/c/test-remove-regular_no_args.c +++ b/tests/unit/remove/c/test-remove-regular_no_args.c @@ -7,25 +7,172 @@ extern "C" { #endif -void test__kt_remove__regular_no_args__works(void **state) { +void test__kt_remove__regular_no_args__exists_link(void **state) { mock_unwrap = 0; + struct stat statistics; + { const f_string_t argv[] = { "mocked_main", "to_remove", 0 }; - mock_status = F_okay; + memset(&statistics, 0, sizeof(struct stat)); + statistics.st_mode = F_file_mode_all_d | F_file_type_regular_d; // Should result in kt_remove_flag_file_operate_remove_d. + + // Pre-process file. + will_return(__wrap_f_file_exists, F_true); + will_return(__wrap_f_file_is, F_true); // A link, kt_remove_flag_file_operate_link_d is set. + will_return(__wrap_f_file_stat, &statistics); + will_return(__wrap_f_file_stat, F_false); + + // This will fail if f_file_remove() is not called, therefore success here means f_file_remove has been called. + will_return(__wrap_f_file_remove, F_okay); + + const int result = kt_main_test__remove(2, argv, 0); + + assert_int_equal(result, 0); + } + + { + const f_string_t argv[] = { "mocked_main", "to_remove", "+V", 0 }; + + memset(&statistics, 0, sizeof(struct stat)); + statistics.st_mode = F_file_mode_all_d | F_file_type_regular_d; // Should result in kt_remove_flag_file_operate_remove_d. + + // Pre-process file. + will_return(__wrap_f_file_exists, F_true); + will_return(__wrap_f_file_is, F_true); // A link, kt_remove_flag_file_operate_link_d is set. + will_return(__wrap_f_file_stat, &statistics); + will_return(__wrap_f_file_stat, F_false); + + // This will fail if f_file_remove() is not called, therefore success here means f_file_remove has been called. + will_return(__wrap_f_file_remove, F_okay); + + const int result = kt_main_test__remove(3, argv, 0); + + assert_int_equal(result, 0); + } + + { + const f_string_t argv[] = { "mocked_main", "to_remove", "+D", 0 }; + + memset(&statistics, 0, sizeof(struct stat)); + statistics.st_mode = F_file_mode_all_d | F_file_type_regular_d; // Should result in kt_remove_flag_file_operate_remove_d. + + // Pre-process file. + will_return(__wrap_f_file_exists, F_true); + will_return(__wrap_f_file_is, F_true); // A link, kt_remove_flag_file_operate_link_d is set. + will_return(__wrap_f_file_stat, &statistics); + will_return(__wrap_f_file_stat, F_false); + + // This will fail if f_file_remove() is not called, therefore success here means f_file_remove has been called. + will_return(__wrap_f_file_remove, F_okay); + + const int result = kt_main_test__remove(3, argv, 0); + + assert_int_equal(result, 0); + } +} + +void test__kt_remove__regular_no_args__exists_link_not(void **state) { + + mock_unwrap = 0; + + struct stat statistics; + + { + const f_string_t argv[] = { "mocked_main", "to_remove", 0 }; + + memset(&statistics, 0, sizeof(struct stat)); + statistics.st_mode = F_file_mode_all_d | F_file_type_regular_d; // Should result in kt_remove_flag_file_operate_remove_d. + + // Pre-process file. + will_return(__wrap_f_file_exists, F_true); + will_return(__wrap_f_file_is, F_false); // A link, kt_remove_flag_file_operate_link_d is not set. + will_return(__wrap_f_file_stat, &statistics); + will_return(__wrap_f_file_stat, F_false); + + // This will fail if f_file_remove() is not called, therefore success here means f_file_remove has been called. + will_return(__wrap_f_file_remove, F_okay); + + const int result = kt_main_test__remove(3, argv, 0); + + assert_int_equal(result, 0); + } + + { + const f_string_t argv[] = { "mocked_main", "to_remove", "+V", 0 }; + + memset(&statistics, 0, sizeof(struct stat)); + statistics.st_mode = F_file_mode_all_d | F_file_type_regular_d; // Should result in kt_remove_flag_file_operate_remove_d. + + // Pre-process file. + will_return(__wrap_f_file_exists, F_true); + will_return(__wrap_f_file_is, F_false); // A link, kt_remove_flag_file_operate_link_d is not set. + will_return(__wrap_f_file_stat, &statistics); + will_return(__wrap_f_file_stat, F_false); + + // This will fail if f_file_remove() is not called, therefore success here means f_file_remove has been called. + will_return(__wrap_f_file_remove, F_okay); + + const int result = kt_main_test__remove(3, argv, 0); + + assert_int_equal(result, 0); + } + + { + const f_string_t argv[] = { "mocked_main", "to_remove", "+D", 0 }; + + memset(&statistics, 0, sizeof(struct stat)); + statistics.st_mode = F_file_mode_all_d | F_file_type_regular_d; // Should result in kt_remove_flag_file_operate_remove_d. + + // Pre-process file. + will_return(__wrap_f_file_exists, F_true); + will_return(__wrap_f_file_is, F_false); // A link, kt_remove_flag_file_operate_link_d is not set. + will_return(__wrap_f_file_stat, &statistics); + will_return(__wrap_f_file_stat, F_false); + + // This will fail if f_file_remove() is not called, therefore success here means f_file_remove has been called. + will_return(__wrap_f_file_remove, F_okay); + + const int result = kt_main_test__remove(3, argv, 0); + + assert_int_equal(result, 0); + } +} + +void test__kt_remove__regular_no_args__exists_not(void **state) { + + mock_unwrap = 0; + + { + const f_string_t argv[] = { "mocked_main", "to_remove", 0 }; will_return(__wrap_f_file_exists, F_false); + + const int result = kt_main_test__remove(2, argv, 0); + + assert_int_equal(result, 0); + } + + { + const f_string_t argv[] = { "mocked_main", "to_remove", "+V", 0 }; + will_return(__wrap_f_file_exists, F_false); - // @todo this is incomplete. - //will_return(__wrap_f_file_remove, F_test); + const int result = kt_main_test__remove(3, argv, 0); - const int result = kt_main_test__remove(2, argv, 0); + assert_int_equal(result, 0); + } + + { + const f_string_t argv[] = { "mocked_main", "to_remove", "+D", 0 }; + + will_return(__wrap_f_file_exists, F_false); + + const int result = kt_main_test__remove(3, argv, 0); assert_int_equal(result, 0); - assert_int_equal(mock_status, F_okay); } } diff --git a/tests/unit/remove/c/test-remove-regular_no_args.h b/tests/unit/remove/c/test-remove-regular_no_args.h index 4f39503..f1d6303 100644 --- a/tests/unit/remove/c/test-remove-regular_no_args.h +++ b/tests/unit/remove/c/test-remove-regular_no_args.h @@ -11,8 +11,18 @@ #define _TEST__KT_remove__regular_no_args /** - * Test that the remove works, for regular files without other arguments. + * Test that the remove works for file that exists and is a link, for regular files without other complex arguments. */ -extern void test__kt_remove__regular_no_args__works(void **state); +extern void test__kt_remove__regular_no_args__exists_link(void **state); + +/** + * Test that the remove works for file that exists and is a not link, for regular files without other complex arguments. + */ +extern void test__kt_remove__regular_no_args__exists_link_not(void **state); + +/** + * Test that the remove works for file that does not exist, for regular files without other complex arguments. + */ +extern void test__kt_remove__regular_no_args__exists_not(void **state); #endif // _TEST__KT_remove__regular_no_args diff --git a/tests/unit/remove/c/test-remove.c b/tests/unit/remove/c/test-remove.c index f948bdd..1b89e12 100644 --- a/tests/unit/remove/c/test-remove.c +++ b/tests/unit/remove/c/test-remove.c @@ -22,7 +22,13 @@ int main(void) { cmocka_unit_test(test__kt_remove__print_help__works), cmocka_unit_test(test__kt_remove__print_version__works), - cmocka_unit_test(test__kt_remove__regular_no_args__works), + cmocka_unit_test(test__kt_remove__directory_no_args__empty_exists_link), + cmocka_unit_test(test__kt_remove__directory_no_args__empty_exists_link_not), + cmocka_unit_test(test__kt_remove__directory_no_args__empty_exists_not), + + cmocka_unit_test(test__kt_remove__regular_no_args__exists_link), + cmocka_unit_test(test__kt_remove__regular_no_args__exists_link_not), + cmocka_unit_test(test__kt_remove__regular_no_args__exists_not), }; return cmocka_run_group_tests(tests, setup, setdown); diff --git a/tests/unit/remove/c/test-remove.h b/tests/unit/remove/c/test-remove.h index 6bfd56e..e687aaf 100644 --- a/tests/unit/remove/c/test-remove.h +++ b/tests/unit/remove/c/test-remove.h @@ -32,6 +32,7 @@ // Test includes. #include "test-remove-print_help.h" #include "test-remove-print_version.h" +#include "test-remove-directory_no_args.h" #include "test-remove-regular_no_args.h" #ifdef __cplusplus