From bf990a10a2c24f6304bb04dc2569765abb5b2347 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Mon, 17 Mar 2025 20:20:32 -0500 Subject: [PATCH] Progress: Continue working on completing the remove program. Add more recurse simple program unit tests. Add the tree simple program unit tests. Implement the tree delete operation. Relocate the parent directory pre-process to a loop that is processed after all other files and directories are removed. --- data/build/remove/settings-tests.remove | 2 +- .../c/program/kevux/tools/remove/main/operate.c | 35 ++++ .../c/program/kevux/tools/remove/main/operate.h | 39 ++++ .../c/program/kevux/tools/remove/main/preprocess.c | 5 - sources/c/program/kevux/tools/remove/main/remove.c | 18 +- tests/unit/remove/c/mock-remove.c | 3 +- .../unit/remove/c/test-remove-directory_no_args.c | 27 +++ .../c/test-remove-directory_recurse_simple.c | 232 ++++++++++++++++++++- .../c/test-remove-directory_recurse_simple.h | 15 ++ .../remove/c/test-remove-directory_tree_simple.c | 55 +++++ .../remove/c/test-remove-directory_tree_simple.h | 18 ++ tests/unit/remove/c/test-remove.c | 5 + tests/unit/remove/c/test-remove.h | 1 + 13 files changed, 436 insertions(+), 19 deletions(-) create mode 100644 tests/unit/remove/c/test-remove-directory_tree_simple.c create mode 100644 tests/unit/remove/c/test-remove-directory_tree_simple.h diff --git a/data/build/remove/settings-tests.remove b/data/build/remove/settings-tests.remove index fa3ceed..efc5e30 100644 --- a/data/build/remove/settings-tests.remove +++ b/data/build/remove/settings-tests.remove @@ -32,7 +32,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-directory_no_args.c test-remove-regular_no_args.c -build_sources_program test-remove-directory_recurse_simple.c +build_sources_program test-remove-directory_recurse_simple.c test-remove-directory_tree_simple.c build_script no build_shared yes diff --git a/sources/c/program/kevux/tools/remove/main/operate.c b/sources/c/program/kevux/tools/remove/main/operate.c index 9964e16..acc6998 100644 --- a/sources/c/program/kevux/tools/remove/main/operate.c +++ b/sources/c/program/kevux/tools/remove/main/operate.c @@ -94,6 +94,41 @@ extern "C" { } #endif // _di_kt_remove_operate_file_directory_action_ +#ifndef _di_kt_remove_operate_file_parent_ + void kt_remove_operate_file_parent(kt_remove_main_t * const main, const f_string_static_t path) { + + if (!main) return; + + if (!path.used) { + main->setting.state.status = F_data_not; + + return; + } + + if (kt_remove_signal_check(main)) return; + + const uint16_t flag_operate = kt_remove_preprocess_file(main, path, kt_remove_flag_file_operate_parent_d); + + if (!kt_remove_operate_shall_remove(flag_operate) || (main->setting.flag & kt_remove_main_flag_simulate_d)) return; + + if (F_status_is_error_not(main->setting.state.status) && !(flag_operate & kt_remove_flag_file_operate_processed_d)) { + main->setting.state.status = kt_remove_operate_file_remove(main, path, flag_operate); + } + + if (F_status_is_error_not(main->setting.state.status)) { + kt_remove_operate_memory_save(main, path, flag_operate); + + if (F_status_is_error(main->setting.state.status)) { + kt_remove_print_error_file(&main->program.error, macro_kt_remove_f(kt_remove_operate_memory_save), path, f_file_operation_process_s, fll_error_file_type_path_e); + } + } + + if (F_status_is_error_not(main->setting.state.status)) { + main->setting.state.status = F_okay; + } + } +#endif // _di_kt_remove_operate_file_parent_ + #ifndef _di_kt_remove_operate_file_recurse_handle_ void kt_remove_operate_file_recurse_handle(f_directory_recurse_do_t * const recurse, const f_string_static_t name, const uint32_t flag) { diff --git a/sources/c/program/kevux/tools/remove/main/operate.h b/sources/c/program/kevux/tools/remove/main/operate.h index 3ed63b6..98627ed 100644 --- a/sources/c/program/kevux/tools/remove/main/operate.h +++ b/sources/c/program/kevux/tools/remove/main/operate.h @@ -106,6 +106,45 @@ extern "C" { #endif // _di_kt_remove_operate_file_directory_action_ /** + * Operate on a single parent directory (from the tree array). + * + * @param main + * The main program and settings data. + * + * Must not be NULL. + * + * This alters main.setting.state.status: + * F_yes on success and file remove. + * F_no on success and file not removed. + * F_data_not on success but path is an empty string. + * + * F_no (with error bit set) on file not removed due to failure. + * + * Errors (with error bit) from: f_string_dynamic_append(). + * + * Errors (with error bit) from: kt_remove_operate_file_directory(). + * Errors (with error bit) from: kt_remove_operate_file_remove_delete(). + * Errors (with error bit) from: kt_remove_operate_file_remove(). + * Errors (with error bit) from: kt_remove_preprocess_file(). + * @param path + * The path to the file to operate on. + * + * This should always be TRUE when calling from the top level. + * This should always be FALSE if calling from within a fl_directory_do() callback. + * This is because fl_directory_do() handles directory traversal and processing. + * + * @see f_string_dynamic_append() + * + * @see kt_remove_operate_file_directory() + * @see kt_remove_operate_file_remove_delete() + * @see kt_remove_operate_file_remove() + * @see kt_remove_preprocess_file() + */ +#ifndef _di_kt_remove_operate_file_parent_ + extern void kt_remove_operate_file_parent(kt_remove_main_t * const main, const f_string_static_t path); +#endif // _di_kt_remove_operate_file_parent_ + +/** * Handle errors while performing directory recurse for a single file operation action. * * @param recurse diff --git a/sources/c/program/kevux/tools/remove/main/preprocess.c b/sources/c/program/kevux/tools/remove/main/preprocess.c index 4f843ad..b1f91c6 100644 --- a/sources/c/program/kevux/tools/remove/main/preprocess.c +++ b/sources/c/program/kevux/tools/remove/main/preprocess.c @@ -312,11 +312,6 @@ extern "C" { } ++main->cache.tree.used; - - f_print_dynamic(f_string_eol_s, main->program.output.to); - - // Pre-process parent directories and set parent flag to prevent potential recursion. - kt_remove_preprocess_file(main, main->cache.tree.array[main->cache.tree.used - 1], kt_remove_flag_file_operate_parent_d); } } else if (F_status_is_error(main->setting.state.status)) { diff --git a/sources/c/program/kevux/tools/remove/main/remove.c b/sources/c/program/kevux/tools/remove/main/remove.c index 3bea4f9..58e376f 100644 --- a/sources/c/program/kevux/tools/remove/main/remove.c +++ b/sources/c/program/kevux/tools/remove/main/remove.c @@ -56,7 +56,9 @@ extern "C" { main->setting.state.status = F_okay; - for (f_number_unsigned_t i = 0; i < main->setting.files.used; ++i) { + f_number_unsigned_t i = 0; + + for (; i < main->setting.files.used; ++i) { kt_remove_operate_file(main, main->setting.files.array[i]); @@ -64,8 +66,20 @@ extern "C" { f_print_dynamic(f_string_eol_s, main->program.output.to); } - if (F_status_is_error(main->setting.state.status)) break; + if (F_status_is_error(main->setting.state.status)) return; } // for + + if (main->cache.tree.used) { + for (i = 0; i < main->cache.tree.used; ++i) { + + if (main->setting.flag & kt_remove_main_flag_simulate_d) { + f_print_dynamic(f_string_eol_s, main->program.output.to); + } + + kt_remove_operate_file_parent(main, main->cache.tree.array[i]); + if (F_status_is_error(main->setting.state.status)) return; + } // for + } } #endif // _di_kt_remove_process_normal_operate_ diff --git a/tests/unit/remove/c/mock-remove.c b/tests/unit/remove/c/mock-remove.c index 1c6decd..f9e509c 100644 --- a/tests/unit/remove/c/mock-remove.c +++ b/tests/unit/remove/c/mock-remove.c @@ -48,10 +48,11 @@ void __wrap_fl_directory_do(const f_string_static_t path, f_directory_recurse_do for (uint32_t i = 0; i < total; ++i) { f_string_static_t * const child_path = mock_ptr_type(f_string_static_t *); + f_string_static_t * const child_name = mock_ptr_type(f_string_static_t *); recurse->path = child_path ? *child_path : f_string_empty_s; - recurse->action(recurse, recurse->path, mock_type(uint32_t)); + recurse->action(recurse, child_name ? *child_name : f_string_empty_s, mock_type(uint32_t)); } // for } else { diff --git a/tests/unit/remove/c/test-remove-directory_no_args.c b/tests/unit/remove/c/test-remove-directory_no_args.c index ea1cdc9..7971eba 100644 --- a/tests/unit/remove/c/test-remove-directory_no_args.c +++ b/tests/unit/remove/c/test-remove-directory_no_args.c @@ -31,6 +31,7 @@ void test__kt_remove__directory_no_args__one_empty_exists_link(void **state) { will_return(__wrap_f_directory_empty, F_true); will_return(__wrap_fl_directory_do, 1); will_return(__wrap_fl_directory_do, &file); + will_return(__wrap_fl_directory_do, &file); will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_top_after_e); // This will fail if f_directory_remove() is not called, therefore success here means f_directory_remove has been called. @@ -57,6 +58,7 @@ void test__kt_remove__directory_no_args__one_empty_exists_link(void **state) { will_return(__wrap_f_directory_empty, F_true); will_return(__wrap_fl_directory_do, 1); will_return(__wrap_fl_directory_do, &file); + will_return(__wrap_fl_directory_do, &file); will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_directory_e | f_directory_recurse_do_flag_top_after_e); // This will fail if f_directory_remove() is not called, therefore success here means f_directory_remove has been called. @@ -83,6 +85,7 @@ void test__kt_remove__directory_no_args__one_empty_exists_link(void **state) { will_return(__wrap_f_directory_empty, F_true); will_return(__wrap_fl_directory_do, 1); will_return(__wrap_fl_directory_do, &file); + will_return(__wrap_fl_directory_do, &file); will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_directory_e | f_directory_recurse_do_flag_top_after_e); // This will fail if f_directory_remove() is not called, therefore success here means f_directory_remove has been called. @@ -118,6 +121,7 @@ void test__kt_remove__directory_no_args__one_empty_exists_link_not(void **state) will_return(__wrap_f_directory_empty, F_true); will_return(__wrap_fl_directory_do, 1); will_return(__wrap_fl_directory_do, &file); + will_return(__wrap_fl_directory_do, &file); will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_directory_e | f_directory_recurse_do_flag_top_after_e); // This will fail if f_directory_remove() is not called, therefore success here means f_directory_remove has been called. @@ -144,6 +148,7 @@ void test__kt_remove__directory_no_args__one_empty_exists_link_not(void **state) will_return(__wrap_f_directory_empty, F_true); will_return(__wrap_fl_directory_do, 1); will_return(__wrap_fl_directory_do, &file); + will_return(__wrap_fl_directory_do, &file); will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_directory_e | f_directory_recurse_do_flag_top_after_e); // This will fail if f_directory_remove() is not called, therefore success here means f_directory_remove has been called. @@ -170,6 +175,7 @@ void test__kt_remove__directory_no_args__one_empty_exists_link_not(void **state) will_return(__wrap_f_directory_empty, F_true); will_return(__wrap_fl_directory_do, 1); will_return(__wrap_fl_directory_do, &file); + will_return(__wrap_fl_directory_do, &file); will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_directory_e | f_directory_recurse_do_flag_top_after_e); // This will fail if f_directory_remove() is not called, therefore success here means f_directory_remove has been called. @@ -246,6 +252,7 @@ void test__kt_remove__directory_no_args__one_empty_not_exists_link(void **state) will_return(__wrap_f_directory_empty, F_false); // kt_remove_flag_file_operate_empty_d is set. will_return(__wrap_fl_directory_do, 1); will_return(__wrap_fl_directory_do, &file); + will_return(__wrap_fl_directory_do, &file); will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_directory_e | f_directory_recurse_do_flag_top_after_e); // This will fail if f_directory_remove() is not called, therefore success here means f_directory_remove has been called. @@ -275,6 +282,7 @@ void test__kt_remove__directory_no_args__one_empty_not_exists_link(void **state) will_return(__wrap_f_directory_empty, F_false); // kt_remove_flag_file_operate_empty_d is set. will_return(__wrap_fl_directory_do, 1); will_return(__wrap_fl_directory_do, &file); + will_return(__wrap_fl_directory_do, &file); will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_directory_e | f_directory_recurse_do_flag_top_after_e); // This will fail if f_directory_remove() is not called, therefore success here means f_directory_remove has been called. @@ -304,6 +312,7 @@ void test__kt_remove__directory_no_args__one_empty_not_exists_link(void **state) will_return(__wrap_f_directory_empty, F_false); // kt_remove_flag_file_operate_empty_d is set. will_return(__wrap_fl_directory_do, 1); will_return(__wrap_fl_directory_do, &file); + will_return(__wrap_fl_directory_do, &file); will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_directory_e | f_directory_recurse_do_flag_top_after_e); // This will fail if f_directory_remove() is not called, therefore success here means f_directory_remove has been called. @@ -343,6 +352,7 @@ void test__kt_remove__directory_no_args__one_empty_not_exists_link_not(void **st will_return(__wrap_f_directory_empty, F_false); // kt_remove_flag_file_operate_empty_d is set. will_return(__wrap_fl_directory_do, 1); will_return(__wrap_fl_directory_do, &file); + will_return(__wrap_fl_directory_do, &file); will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_directory_e | f_directory_recurse_do_flag_top_after_e); // This will fail if f_directory_remove() is not called, therefore success here means f_directory_remove has been called. @@ -372,6 +382,7 @@ void test__kt_remove__directory_no_args__one_empty_not_exists_link_not(void **st will_return(__wrap_f_directory_empty, F_false); // kt_remove_flag_file_operate_empty_d is set. will_return(__wrap_fl_directory_do, 1); will_return(__wrap_fl_directory_do, &file); + will_return(__wrap_fl_directory_do, &file); will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_directory_e | f_directory_recurse_do_flag_top_after_e); // This will fail if f_directory_remove() is not called, therefore success here means f_directory_remove has been called. @@ -401,6 +412,7 @@ void test__kt_remove__directory_no_args__one_empty_not_exists_link_not(void **st will_return(__wrap_f_directory_empty, F_false); // kt_remove_flag_file_operate_empty_d is set. will_return(__wrap_fl_directory_do, 1); will_return(__wrap_fl_directory_do, &file); + will_return(__wrap_fl_directory_do, &file); will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_directory_e | f_directory_recurse_do_flag_top_after_e); // This will fail if f_directory_remove() is not called, therefore success here means f_directory_remove has been called. @@ -439,6 +451,7 @@ void test__kt_remove__directory_no_args__two_empty_exists_and_not(void **state) will_return(__wrap_f_directory_empty, F_true); will_return(__wrap_fl_directory_do, 1); will_return(__wrap_fl_directory_do, &file); + will_return(__wrap_fl_directory_do, &file); will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_directory_e | f_directory_recurse_do_flag_top_after_e); // This will fail if f_directory_remove() is not called, therefore success here means f_directory_remove has been called. @@ -468,6 +481,7 @@ void test__kt_remove__directory_no_args__two_empty_exists_and_not(void **state) will_return(__wrap_f_directory_empty, F_true); will_return(__wrap_fl_directory_do, 1); will_return(__wrap_fl_directory_do, &file); + will_return(__wrap_fl_directory_do, &file); will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_directory_e | f_directory_recurse_do_flag_top_after_e); // This will fail if f_directory_remove() is not called, therefore success here means f_directory_remove has been called. @@ -497,6 +511,7 @@ void test__kt_remove__directory_no_args__two_empty_exists_and_not(void **state) will_return(__wrap_f_directory_empty, F_true); will_return(__wrap_fl_directory_do, 1); will_return(__wrap_fl_directory_do, &file); + will_return(__wrap_fl_directory_do, &file); will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_directory_e | f_directory_recurse_do_flag_top_after_e); // This will fail if f_directory_remove() is not called, therefore success here means f_directory_remove has been called. @@ -532,6 +547,7 @@ void test__kt_remove__directory_no_args__two_empty_exists_link(void **state) { will_return(__wrap_f_directory_empty, F_true); will_return(__wrap_fl_directory_do, 1); will_return(__wrap_fl_directory_do, &file); + will_return(__wrap_fl_directory_do, &file); will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_directory_e | f_directory_recurse_do_flag_top_after_e); // This will fail if f_directory_remove() is not called, therefore success here means f_directory_remove has been called. @@ -547,6 +563,7 @@ void test__kt_remove__directory_no_args__two_empty_exists_link(void **state) { will_return(__wrap_f_directory_empty, F_true); will_return(__wrap_fl_directory_do, 1); will_return(__wrap_fl_directory_do, &file); + will_return(__wrap_fl_directory_do, &file); will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_directory_e | f_directory_recurse_do_flag_top_after_e); // This will fail if f_directory_remove() is not called, therefore success here means f_directory_remove has been called. @@ -573,6 +590,7 @@ void test__kt_remove__directory_no_args__two_empty_exists_link(void **state) { will_return(__wrap_f_directory_empty, F_true); will_return(__wrap_fl_directory_do, 1); will_return(__wrap_fl_directory_do, &file); + will_return(__wrap_fl_directory_do, &file); will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_directory_e | f_directory_recurse_do_flag_top_after_e); // This will fail if f_directory_remove() is not called, therefore success here means f_directory_remove has been called. @@ -588,6 +606,7 @@ void test__kt_remove__directory_no_args__two_empty_exists_link(void **state) { will_return(__wrap_f_directory_empty, F_true); will_return(__wrap_fl_directory_do, 1); will_return(__wrap_fl_directory_do, &file); + will_return(__wrap_fl_directory_do, &file); will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_directory_e | f_directory_recurse_do_flag_top_after_e); // This will fail if f_directory_remove() is not called, therefore success here means f_directory_remove has been called. @@ -614,6 +633,7 @@ void test__kt_remove__directory_no_args__two_empty_exists_link(void **state) { will_return(__wrap_f_directory_empty, F_true); will_return(__wrap_fl_directory_do, 1); will_return(__wrap_fl_directory_do, &file); + will_return(__wrap_fl_directory_do, &file); will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_directory_e | f_directory_recurse_do_flag_top_after_e); // This will fail if f_directory_remove() is not called, therefore success here means f_directory_remove has been called. @@ -629,6 +649,7 @@ void test__kt_remove__directory_no_args__two_empty_exists_link(void **state) { will_return(__wrap_f_directory_empty, F_true); will_return(__wrap_fl_directory_do, 1); will_return(__wrap_fl_directory_do, &file); + will_return(__wrap_fl_directory_do, &file); will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_directory_e | f_directory_recurse_do_flag_top_after_e); // This will fail if f_directory_remove() is not called, therefore success here means f_directory_remove has been called. @@ -664,6 +685,7 @@ void test__kt_remove__directory_no_args__two_empty_exists_link_not(void **state) will_return(__wrap_f_directory_empty, F_true); will_return(__wrap_fl_directory_do, 1); will_return(__wrap_fl_directory_do, &file); + will_return(__wrap_fl_directory_do, &file); will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_directory_e | f_directory_recurse_do_flag_top_after_e); // This will fail if f_directory_remove() is not called, therefore success here means f_directory_remove has been called. @@ -679,6 +701,7 @@ void test__kt_remove__directory_no_args__two_empty_exists_link_not(void **state) will_return(__wrap_f_directory_empty, F_true); will_return(__wrap_fl_directory_do, 1); will_return(__wrap_fl_directory_do, &file); + will_return(__wrap_fl_directory_do, &file); will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_directory_e | f_directory_recurse_do_flag_top_after_e); // This will fail if f_directory_remove() is not called, therefore success here means f_directory_remove has been called. @@ -705,6 +728,7 @@ void test__kt_remove__directory_no_args__two_empty_exists_link_not(void **state) will_return(__wrap_f_directory_empty, F_true); will_return(__wrap_fl_directory_do, 1); will_return(__wrap_fl_directory_do, &file); + will_return(__wrap_fl_directory_do, &file); will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_directory_e | f_directory_recurse_do_flag_top_after_e); // This will fail if f_directory_remove() is not called, therefore success here means f_directory_remove has been called. @@ -720,6 +744,7 @@ void test__kt_remove__directory_no_args__two_empty_exists_link_not(void **state) will_return(__wrap_f_directory_empty, F_true); will_return(__wrap_fl_directory_do, 1); will_return(__wrap_fl_directory_do, &file); + will_return(__wrap_fl_directory_do, &file); will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_directory_e | f_directory_recurse_do_flag_top_after_e); // This will fail if f_directory_remove() is not called, therefore success here means f_directory_remove has been called. @@ -746,6 +771,7 @@ void test__kt_remove__directory_no_args__two_empty_exists_link_not(void **state) will_return(__wrap_f_directory_empty, F_true); will_return(__wrap_fl_directory_do, 1); will_return(__wrap_fl_directory_do, &file); + will_return(__wrap_fl_directory_do, &file); will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_directory_e | f_directory_recurse_do_flag_top_after_e); // This will fail if f_directory_remove() is not called, therefore success here means f_directory_remove has been called. @@ -761,6 +787,7 @@ void test__kt_remove__directory_no_args__two_empty_exists_link_not(void **state) will_return(__wrap_f_directory_empty, F_true); will_return(__wrap_fl_directory_do, 1); will_return(__wrap_fl_directory_do, &file); + will_return(__wrap_fl_directory_do, &file); will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_directory_e | f_directory_recurse_do_flag_top_after_e); // This will fail if f_directory_remove() is not called, therefore success here means f_directory_remove has been called. diff --git a/tests/unit/remove/c/test-remove-directory_recurse_simple.c b/tests/unit/remove/c/test-remove-directory_recurse_simple.c index 2ff097d..c14dccc 100644 --- a/tests/unit/remove/c/test-remove-directory_recurse_simple.c +++ b/tests/unit/remove/c/test-remove-directory_recurse_simple.c @@ -11,49 +11,261 @@ void test__kt_remove__directory_recurse_simple__one_child_one_exists_link(void * mock_unwrap = 0; - const f_string_static_t parent = macro_f_string_static_t_initialize_1("to_remove", 0, 9); + const f_string_static_t target = macro_f_string_static_t_initialize_1("to_remove", 0, 9); const f_string_static_t child_1 = macro_f_string_static_t_initialize_1("child_1", 0, 7); - struct stat stat_parent; + struct stat stat_directory; struct stat stat_regular; { - const f_string_t argv[] = { "mocked_main", parent.string, "-r", 0 }; + const f_string_t argv[] = { "mocked_main", target.string, "-r", 0 }; - memset(&stat_parent, 0, sizeof(struct stat)); + memset(&stat_directory, 0, sizeof(struct stat)); memset(&stat_regular, 0, sizeof(struct stat)); - stat_parent.st_mode = F_file_mode_all_d | F_file_type_directory_d; + stat_directory.st_mode = F_file_mode_all_d | F_file_type_directory_d; stat_regular.st_mode = F_file_mode_all_d | F_file_type_regular_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, &stat_parent); + will_return(__wrap_f_file_stat, &stat_directory); will_return(__wrap_f_file_stat, F_okay); - // Parent Directory pre-processing, begin, perform directory listing action. + // Target Directory pre-processing, begin, perform directory listing action. will_return(__wrap_f_directory_empty, F_false); will_return(__wrap_fl_directory_do, 1); // The first child pre-processing. will_return(__wrap_fl_directory_do, &child_1); + will_return(__wrap_fl_directory_do, &child_1); + will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_regular_e); + will_return(__wrap_f_file_exists, F_true); + will_return(__wrap_f_file_is, F_false); // Not a link, kt_remove_flag_file_operate_link_d is not set. + will_return(__wrap_f_file_stat, &stat_regular); + will_return(__wrap_f_file_stat, F_okay); + + // Target Directory processing, begin. + will_return(__wrap_fl_directory_do, 2); + + // The first child processing. + will_return(__wrap_fl_directory_do, &child_1); + will_return(__wrap_fl_directory_do, &child_1); + will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_regular_e); + will_return(__wrap_f_file_remove, F_okay); + + // Target Directory processing, continue. + will_return(__wrap_fl_directory_do, &target); + will_return(__wrap_fl_directory_do, &target); + will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_directory_e | f_directory_recurse_do_flag_top_after_e); + 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_recurse_simple__one_child_one_exists_link_not(void **state) { + + mock_unwrap = 0; + + const f_string_static_t target = macro_f_string_static_t_initialize_1("to_remove", 0, 9); + const f_string_static_t child_1 = macro_f_string_static_t_initialize_1("child_1", 0, 7); + + struct stat stat_directory; + struct stat stat_regular; + + { + const f_string_t argv[] = { "mocked_main", target.string, "-r", 0 }; + + memset(&stat_directory, 0, sizeof(struct stat)); + memset(&stat_regular, 0, sizeof(struct stat)); + + stat_directory.st_mode = F_file_mode_all_d | F_file_type_directory_d; + stat_regular.st_mode = F_file_mode_all_d | F_file_type_regular_d; + + // Pre-process file. + will_return(__wrap_f_file_exists, F_true); + will_return(__wrap_f_file_is, F_false); // Not a link, kt_remove_flag_file_operate_link_d is not set. + will_return(__wrap_f_file_stat, &stat_directory); + will_return(__wrap_f_file_stat, F_okay); + + // Target Directory pre-processing, begin, perform directory listing action. + will_return(__wrap_f_directory_empty, F_false); + will_return(__wrap_fl_directory_do, 1); + + // The first child pre-processing. + will_return(__wrap_fl_directory_do, &child_1); + will_return(__wrap_fl_directory_do, &child_1); will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_regular_e); will_return(__wrap_f_file_exists, F_true); will_return(__wrap_f_file_is, F_false); // Not a link, kt_remove_flag_file_operate_link_d is not set. will_return(__wrap_f_file_stat, &stat_regular); will_return(__wrap_f_file_stat, F_okay); - // Parent Directory processing, begin. + // Target Directory processing, begin. will_return(__wrap_fl_directory_do, 2); // The first child processing. will_return(__wrap_fl_directory_do, &child_1); + will_return(__wrap_fl_directory_do, &child_1); + will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_regular_e); + will_return(__wrap_f_file_remove, F_okay); + + // Target Directory processing, continue. + will_return(__wrap_fl_directory_do, &target); + will_return(__wrap_fl_directory_do, &target); + will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_directory_e | f_directory_recurse_do_flag_top_after_e); + 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_recurse_simple__one_child_two_exists_link(void **state) { + + mock_unwrap = 0; + + const f_string_static_t target = macro_f_string_static_t_initialize_1("to_remove", 0, 9); + const f_string_static_t child_1 = macro_f_string_static_t_initialize_1("child_1", 0, 7); + const f_string_static_t child_2 = macro_f_string_static_t_initialize_1("child_2", 0, 7); + + struct stat stat_directory; + struct stat stat_regular; + + { + const f_string_t argv[] = { "mocked_main", target.string, "-r", 0 }; + + memset(&stat_directory, 0, sizeof(struct stat)); + memset(&stat_regular, 0, sizeof(struct stat)); + + stat_directory.st_mode = F_file_mode_all_d | F_file_type_directory_d; + stat_regular.st_mode = F_file_mode_all_d | F_file_type_regular_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, &stat_directory); + will_return(__wrap_f_file_stat, F_okay); + + // Target Directory pre-processing, begin, perform directory listing action. + will_return(__wrap_f_directory_empty, F_false); + will_return(__wrap_fl_directory_do, 2); + + // The first child pre-processing. + will_return(__wrap_fl_directory_do, &child_1); + will_return(__wrap_fl_directory_do, &child_1); + will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_regular_e); + will_return(__wrap_f_file_exists, F_true); + will_return(__wrap_f_file_is, F_false); // Not a link, kt_remove_flag_file_operate_link_d is not set. + will_return(__wrap_f_file_stat, &stat_regular); + will_return(__wrap_f_file_stat, F_okay); + + // The second child pre-processing. + will_return(__wrap_fl_directory_do, &child_2); + will_return(__wrap_fl_directory_do, &child_2); + will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_regular_e); + 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, &stat_regular); + will_return(__wrap_f_file_stat, F_okay); + + // Target Directory processing, begin. + will_return(__wrap_fl_directory_do, 3); + + // The first child processing. + will_return(__wrap_fl_directory_do, &child_1); + will_return(__wrap_fl_directory_do, &child_1); + will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_regular_e); + will_return(__wrap_f_file_remove, F_okay); + + // The second child processing. + will_return(__wrap_fl_directory_do, &child_2); + will_return(__wrap_fl_directory_do, &child_2); + will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_regular_e); + will_return(__wrap_f_file_remove, F_okay); + + // Target Directory processing, continue. + will_return(__wrap_fl_directory_do, &target); + will_return(__wrap_fl_directory_do, &target); + will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_directory_e | f_directory_recurse_do_flag_top_after_e); + 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_recurse_simple__one_child_two_exists_link_not(void **state) { + + mock_unwrap = 0; + + const f_string_static_t target = macro_f_string_static_t_initialize_1("to_remove", 0, 9); + const f_string_static_t child_1 = macro_f_string_static_t_initialize_1("child_1", 0, 7); + const f_string_static_t child_2 = macro_f_string_static_t_initialize_1("child_2", 0, 7); + + struct stat stat_directory; + struct stat stat_regular; + + { + const f_string_t argv[] = { "mocked_main", target.string, "-r", 0 }; + + memset(&stat_directory, 0, sizeof(struct stat)); + memset(&stat_regular, 0, sizeof(struct stat)); + + stat_directory.st_mode = F_file_mode_all_d | F_file_type_directory_d; + stat_regular.st_mode = F_file_mode_all_d | F_file_type_regular_d; + + // Pre-process file. + will_return(__wrap_f_file_exists, F_true); + will_return(__wrap_f_file_is, F_false); // Not a link, kt_remove_flag_file_operate_link_d is not set. + will_return(__wrap_f_file_stat, &stat_directory); + will_return(__wrap_f_file_stat, F_okay); + + // Target Directory pre-processing, begin, perform directory listing action. + will_return(__wrap_f_directory_empty, F_false); + will_return(__wrap_fl_directory_do, 2); + + // The first child pre-processing. + will_return(__wrap_fl_directory_do, &child_1); + will_return(__wrap_fl_directory_do, &child_1); + will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_regular_e); + will_return(__wrap_f_file_exists, F_true); + will_return(__wrap_f_file_is, F_false); // Not a link, kt_remove_flag_file_operate_link_d is not set. + will_return(__wrap_f_file_stat, &stat_regular); + will_return(__wrap_f_file_stat, F_okay); + + // The second child pre-processing. + will_return(__wrap_fl_directory_do, &child_2); + will_return(__wrap_fl_directory_do, &child_2); + will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_regular_e); + 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, &stat_regular); + will_return(__wrap_f_file_stat, F_okay); + + // Target Directory processing, begin. + will_return(__wrap_fl_directory_do, 3); + + // The first child processing. + will_return(__wrap_fl_directory_do, &child_1); + will_return(__wrap_fl_directory_do, &child_1); + will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_regular_e); + will_return(__wrap_f_file_remove, F_okay); + + // The second child processing. + will_return(__wrap_fl_directory_do, &child_2); + will_return(__wrap_fl_directory_do, &child_2); will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_regular_e); will_return(__wrap_f_file_remove, F_okay); - // Parent Directory processing, continue. - will_return(__wrap_fl_directory_do, &parent); + // Target Directory processing, continue. + will_return(__wrap_fl_directory_do, &target); + will_return(__wrap_fl_directory_do, &target); will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_directory_e | f_directory_recurse_do_flag_top_after_e); will_return(__wrap_f_directory_remove, F_okay); diff --git a/tests/unit/remove/c/test-remove-directory_recurse_simple.h b/tests/unit/remove/c/test-remove-directory_recurse_simple.h index b40425c..ce8bbbb 100644 --- a/tests/unit/remove/c/test-remove-directory_recurse_simple.h +++ b/tests/unit/remove/c/test-remove-directory_recurse_simple.h @@ -15,4 +15,19 @@ */ extern void test__kt_remove__directory_recurse_simple__one_child_one_exists_link(void **state); +/** + * Test that the remove works for one file that exists and is not a link, for directory files that has one child with the recurse argument. + */ +extern void test__kt_remove__directory_recurse_simple__one_child_one_exists_link_not(void **state); + +/** + * Test that the remove works for one file that exists and is a link, for directory files that has two children with the recurse argument. + */ +extern void test__kt_remove__directory_recurse_simple__one_child_two_exists_link(void **state); + +/** + * Test that the remove works for one file that exists and is not a link, for directory files that has two children with the recurse argument. + */ +extern void test__kt_remove__directory_recurse_simple__one_child_two_exists_link_not(void **state); + #endif // _TEST__KT_remove__directory_recurse_simple diff --git a/tests/unit/remove/c/test-remove-directory_tree_simple.c b/tests/unit/remove/c/test-remove-directory_tree_simple.c new file mode 100644 index 0000000..1b31cc0 --- /dev/null +++ b/tests/unit/remove/c/test-remove-directory_tree_simple.c @@ -0,0 +1,55 @@ +#include "test-remove.h" +#include "test-remove-directory_tree_simple.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void test__kt_remove__directory_tree_simple__one_child_none_parent_one_exists_link(void **state) { + + mock_unwrap = 0; + + const f_string_static_t target_full = macro_f_string_static_t_initialize_1("parent_1/to_remove", 0, 18); + + struct stat stat_directory; + struct stat stat_regular; + + { + const f_string_t argv[] = { "mocked_main", target_full.string, "-t", 0 }; + + memset(&stat_directory, 0, sizeof(struct stat)); + memset(&stat_regular, 0, sizeof(struct stat)); + + stat_directory.st_mode = F_file_mode_all_d | F_file_type_directory_d; + stat_regular.st_mode = F_file_mode_all_d | F_file_type_regular_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, &stat_regular); + will_return(__wrap_f_file_stat, F_okay); + + // Pre-process parent directory 1. + will_return(__wrap_f_file_exists, F_true); + will_return(__wrap_f_file_is, F_false); // Not a link, kt_remove_flag_file_operate_link_d is not set. + will_return(__wrap_f_file_stat, &stat_directory); + will_return(__wrap_f_file_stat, F_okay); + will_return(__wrap_f_directory_empty, F_false); + + // Target processing. + will_return(__wrap_f_file_remove, F_okay); + + // Parent 1 processing. + will_return(__wrap_f_directory_remove, F_okay); + + 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_tree_simple.h b/tests/unit/remove/c/test-remove-directory_tree_simple.h new file mode 100644 index 0000000..86a33dc --- /dev/null +++ b/tests/unit/remove/c/test-remove-directory_tree_simple.h @@ -0,0 +1,18 @@ +/** + * Kevux Tools - Remove + * + * Project: Kevux Tools + * API Version: 0.5 + * Licenses: lgpl-2.1-or-later + * + * Test the remove. + */ +#ifndef _TEST__KT_remove__directory_tree_simple +#define _TEST__KT_remove__directory_tree_simple + +/** + * Test that the remove works for one file that exists and is a link, for directory files that has no children and one parent with the tree argument. + */ +extern void test__kt_remove__directory_tree_simple__one_child_none_parent_one_exists_link(void **state); + +#endif // _TEST__KT_remove__directory_tree_simple diff --git a/tests/unit/remove/c/test-remove.c b/tests/unit/remove/c/test-remove.c index e1e5c56..f86c513 100644 --- a/tests/unit/remove/c/test-remove.c +++ b/tests/unit/remove/c/test-remove.c @@ -34,6 +34,11 @@ int main(void) { cmocka_unit_test(test__kt_remove__directory_no_args__two_empty_exists_not), cmocka_unit_test(test__kt_remove__directory_recurse_simple__one_child_one_exists_link), + cmocka_unit_test(test__kt_remove__directory_recurse_simple__one_child_one_exists_link_not), + cmocka_unit_test(test__kt_remove__directory_recurse_simple__one_child_two_exists_link), + cmocka_unit_test(test__kt_remove__directory_recurse_simple__one_child_two_exists_link_not), + + cmocka_unit_test(test__kt_remove__directory_tree_simple__one_child_none_parent_one_exists_link), cmocka_unit_test(test__kt_remove__regular_no_args__one_exists_link), cmocka_unit_test(test__kt_remove__regular_no_args__one_exists_link_not), diff --git a/tests/unit/remove/c/test-remove.h b/tests/unit/remove/c/test-remove.h index 43d61d9..1b40857 100644 --- a/tests/unit/remove/c/test-remove.h +++ b/tests/unit/remove/c/test-remove.h @@ -34,6 +34,7 @@ #include "test-remove-print_version.h" #include "test-remove-directory_no_args.h" #include "test-remove-directory_recurse_simple.h" +#include "test-remove-directory_tree_simple.h" #include "test-remove-regular_no_args.h" #ifdef __cplusplus -- 1.8.3.1