]> Kevux Git Server - kevux-tools/commitdiff
Progress: Continue working on completing the remove program.
authorKevin Day <Kevin@kevux.org>
Tue, 18 Mar 2025 01:20:32 +0000 (20:20 -0500)
committerKevin Day <Kevin@kevux.org>
Tue, 18 Mar 2025 02:32:44 +0000 (21:32 -0500)
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.

13 files changed:
data/build/remove/settings-tests.remove
sources/c/program/kevux/tools/remove/main/operate.c
sources/c/program/kevux/tools/remove/main/operate.h
sources/c/program/kevux/tools/remove/main/preprocess.c
sources/c/program/kevux/tools/remove/main/remove.c
tests/unit/remove/c/mock-remove.c
tests/unit/remove/c/test-remove-directory_no_args.c
tests/unit/remove/c/test-remove-directory_recurse_simple.c
tests/unit/remove/c/test-remove-directory_recurse_simple.h
tests/unit/remove/c/test-remove-directory_tree_simple.c [new file with mode: 0644]
tests/unit/remove/c/test-remove-directory_tree_simple.h [new file with mode: 0644]
tests/unit/remove/c/test-remove.c
tests/unit/remove/c/test-remove.h

index fa3ceedace2d1e460bee75817d568f8f828c0b4f..efc5e30f0101e35c8583ee07b9dba6029e007da9 100644 (file)
@@ -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
index 9964e16bdef1b9c2214fbb04e4a37ad1e8070190..acc69982c7ee82774b78f8b6e49c64636241842d 100644 (file)
@@ -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) {
 
index 3ed63b636bd7a5b0b1650bacb7b5245223594b01..98627ed3e7475c711640a0a6ceff3ca4beb50cc7 100644 (file)
@@ -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
index 4f843ad1d0deb5037c20a3c5cb6c442b515539db..b1f91c65c5656125fc793da003faa171187c7854 100644 (file)
@@ -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)) {
index 3bea4f9a71b2e2796a92a83855e6ca914a9d3ce6..58e376f046171a53876510e7d01a2324945ed13f 100644 (file)
@@ -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_
 
index 1c6decd20028527bcca67c29c270bc8a7c6025d4..f9e509c62475fe57c0c2dc9fc60b5c13f298632a 100644 (file)
@@ -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 {
index ea1cdc9e1e546ad4c86c5102ef794032a209fc31..7971eba91658873f00510a5f98aa75b7107b4154 100644 (file)
@@ -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.
index 2ff097d109693bba1254e36dc8c90301c67bef42..c14dccca8443045f30ef23700e4a893f4ec8419f 100644 (file)
@@ -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);
 
index b40425c68ed1fb9503e04898fa18c5ef906ab1db..ce8bbbb02aa784afad8f590c4f9598868f069055 100644 (file)
  */
 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 (file)
index 0000000..1b31cc0
--- /dev/null
@@ -0,0 +1,55 @@
+#include "test-remove.h"
+#include "test-remove-directory_tree_simple.h"
+
+#include <program/kevux/tools/remove/remove/main.h>
+
+#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 (file)
index 0000000..86a33dc
--- /dev/null
@@ -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
index e1e5c560b663dbfbd4c3f26adc7b1b690435293a..f86c51386d6548241c75196e3925bc55b0735778 100644 (file)
@@ -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),
index 43d61d9de217c0afc96b45b901baaa12cd191974..1b4085717861214d9a44beb08ea46166f0c887d3 100644 (file)
@@ -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