Progress: Continue working on completing the remove program.
authorKevin Day <Kevin@kevux.org>
Wed, 12 Mar 2025 03:06:33 +0000 (22:06 -0500)
committerKevin Day <Kevin@kevux.org>
Wed, 12 Mar 2025 03:29:31 +0000 (22:29 -0500)
Add more runtime unit tests.

This begins adding simple directory recurse tests.
The current test written for this is incomplete and needs the `fl_directory_do()` to be unwrapped.
Then the individual parts need to be mocked as needed.

data/build/remove/settings-tests.remove
tests/unit/remove/c/mock-remove.c
tests/unit/remove/c/mock-remove.h
tests/unit/remove/c/test-remove-directory_no_args.c
tests/unit/remove/c/test-remove-directory_no_args.h
tests/unit/remove/c/test-remove-directory_recurse_simple.c [new file with mode: 0644]
tests/unit/remove/c/test-remove-directory_recurse_simple.h [new file with mode: 0644]
tests/unit/remove/c/test-remove-regular_no_args.c
tests/unit/remove/c/test-remove-regular_no_args.h
tests/unit/remove/c/test-remove.c
tests/unit/remove/c/test-remove.h

index beeb297cb7ce735f6af4c74a53a1210731d8612e..fa3ceedace2d1e460bee75817d568f8f828c0b4f 100644 (file)
@@ -32,6 +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_script no
 build_shared yes
index 0ebdeb7c1f2e20d80e3374695203dafca297eb51..6bc4c70f882d0cc17f79e1c99bc39bafd376ef16 100644 (file)
@@ -5,6 +5,8 @@ extern "C" {
 #endif
 
 int mock_unwrap = 0;
+int mock_unwrap_fl_directory_do = 0;
+
 f_status_t mock_directory_call_action = 0;
 f_status_t mock_status = 0;
 
@@ -43,6 +45,10 @@ f_status_t __wrap_f_file_stat(const f_string_static_t path, const bool dereferen
 
 void __wrap_fl_directory_do(const f_string_static_t path, f_directory_recurse_do_t * const recurse) {
 
+  if (mock_unwrap_fl_directory_do) {
+    return __real_fl_directory_do(path, recurse);
+  }
+
   if (mock_directory_call_action) {
     recurse->action(recurse, path, mock_type(uint32_t));
   }
index 213ba4637bc2a86d6b3daab2e348c86a02a5cfcd..0cd04efe6604cbbfefaadfdd42c0120fc154dc00 100644 (file)
@@ -30,9 +30,13 @@ extern "C" {
 const static int mock_errno_generic = 32767;
 
 extern int mock_unwrap;
+extern int mock_unwrap_fl_directory_do;
+
 extern f_status_t mock_directory_call_action;
 extern f_status_t mock_status;
 
+extern void __real_fl_directory_do(const f_string_static_t path, f_directory_recurse_do_t * const recurse);
+
 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);
index e4229a231df8ed256acd7b4f38345b98b5826b91..b693f518d8999ea8c4bc9cff11975464c2ceb8f9 100644 (file)
@@ -7,7 +7,7 @@
 extern "C" {
 #endif
 
-void test__kt_remove__directory_no_args__empty_exists_link(void **state) {
+void test__kt_remove__directory_no_args__one_empty_exists_link(void **state) {
 
   mock_unwrap = 0;
   mock_directory_call_action = F_true;
@@ -90,7 +90,7 @@ void test__kt_remove__directory_no_args__empty_exists_link(void **state) {
   }
 }
 
-void test__kt_remove__directory_no_args__empty_exists_link_not(void **state) {
+void test__kt_remove__directory_no_args__one_empty_exists_link_not(void **state) {
 
   mock_unwrap = 0;
   mock_directory_call_action = F_true;
@@ -173,7 +173,7 @@ void test__kt_remove__directory_no_args__empty_exists_link_not(void **state) {
   }
 }
 
-void test__kt_remove__directory_no_args__empty_exists_not(void **state) {
+void test__kt_remove__directory_no_args__one_empty_exists_not(void **state) {
 
   mock_unwrap = 0;
 
@@ -208,6 +208,572 @@ void test__kt_remove__directory_no_args__empty_exists_not(void **state) {
   }
 }
 
+void test__kt_remove__directory_no_args__one_empty_not_exists_link(void **state) {
+
+  mock_unwrap = 0;
+  mock_directory_call_action = F_true;
+
+  struct stat statistics;
+  struct stat statistics_regular;
+
+  {
+    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.
+
+    memset(&statistics_regular, 0, sizeof(struct stat));
+    statistics_regular.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);
+
+    // Directory processing.
+    will_return(__wrap_f_directory_empty, F_false); // kt_remove_flag_file_operate_empty_d is set.
+    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.
+
+    memset(&statistics_regular, 0, sizeof(struct stat));
+    statistics_regular.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);
+
+    // Directory processing.
+    will_return(__wrap_f_directory_empty, F_false); // kt_remove_flag_file_operate_empty_d is set.
+    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.
+
+    memset(&statistics_regular, 0, sizeof(struct stat));
+    statistics_regular.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);
+
+    // Directory processing.
+    will_return(__wrap_f_directory_empty, F_false); // kt_remove_flag_file_operate_empty_d is set.
+    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__one_empty_not_exists_link_not(void **state) {
+
+  mock_unwrap = 0;
+  mock_directory_call_action = F_true;
+
+  struct stat statistics;
+  struct stat statistics_regular;
+
+  {
+    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.
+
+    memset(&statistics_regular, 0, sizeof(struct stat));
+    statistics_regular.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);
+
+    // Directory processing.
+    will_return(__wrap_f_directory_empty, F_false); // kt_remove_flag_file_operate_empty_d is set.
+    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.
+
+    memset(&statistics_regular, 0, sizeof(struct stat));
+    statistics_regular.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);
+
+    // Directory processing.
+    will_return(__wrap_f_directory_empty, F_false); // kt_remove_flag_file_operate_empty_d is set.
+    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.
+
+    memset(&statistics_regular, 0, sizeof(struct stat));
+    statistics_regular.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);
+
+    // Directory processing.
+    will_return(__wrap_f_directory_empty, F_false); // kt_remove_flag_file_operate_empty_d is set.
+    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__two_empty_exists_and_not(void **state) {
+
+  mock_unwrap = 0;
+  mock_directory_call_action = F_true;
+
+  struct stat statistics;
+
+  {
+    const f_string_t argv[] = { "mocked_main", "to_remove", "also/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 1.
+    will_return(__wrap_f_file_exists, F_false);
+
+    // Pre-process file 2.
+    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", "also/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 1.
+    will_return(__wrap_f_file_exists, F_false);
+
+    // Pre-process file 2.
+    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(4, argv, 0);
+
+    assert_int_equal(result, 0);
+  }
+
+  {
+    const f_string_t argv[] = { "mocked_main", "to_remove", "also/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 1.
+    will_return(__wrap_f_file_exists, F_false);
+
+    // Pre-process file 2.
+    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(4, argv, 0);
+
+    assert_int_equal(result, 0);
+  }
+}
+
+void test__kt_remove__directory_no_args__two_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", "also/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 1.
+    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);
+
+    // Pre-process file 2.
+    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", "also/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 1.
+    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);
+
+    // Pre-process file 2.
+    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(4, argv, 0);
+
+    assert_int_equal(result, 0);
+  }
+
+  {
+    const f_string_t argv[] = { "mocked_main", "to_remove", "also/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 1.
+    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);
+
+    // Pre-process file 2.
+    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(4, argv, 0);
+
+    assert_int_equal(result, 0);
+  }
+}
+
+void test__kt_remove__directory_no_args__two_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", "also/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 1.
+    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);
+
+    // Pre-process file 2.
+    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(4, argv, 0);
+
+    assert_int_equal(result, 0);
+  }
+
+  {
+    const f_string_t argv[] = { "mocked_main", "to_remove", "also/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 1.
+    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);
+
+    // Pre-process file 2.
+    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(4, argv, 0);
+
+    assert_int_equal(result, 0);
+  }
+
+  {
+    const f_string_t argv[] = { "mocked_main", "to_remove", "also/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 1.
+    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);
+
+    // Pre-process file 2.
+    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(4, argv, 0);
+
+    assert_int_equal(result, 0);
+  }
+}
+
+void test__kt_remove__directory_no_args__two_empty_exists_not(void **state) {
+
+  mock_unwrap = 0;
+
+  {
+    const f_string_t argv[] = { "mocked_main", "to_remove", "also/remove", 0 };
+
+    will_return(__wrap_f_file_exists, F_false);
+    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", "also/remove", "+V", 0 };
+
+    will_return(__wrap_f_file_exists, F_false);
+    will_return(__wrap_f_file_exists, F_false);
+
+    const int result = kt_main_test__remove(4, argv, 0);
+
+    assert_int_equal(result, 0);
+  }
+
+  {
+    const f_string_t argv[] = { "mocked_main", "to_remove", "also/remove", "+D", 0 };
+
+    will_return(__wrap_f_file_exists, F_false);
+    will_return(__wrap_f_file_exists, F_false);
+
+    const int result = kt_main_test__remove(4, argv, 0);
+
+    assert_int_equal(result, 0);
+  }
+}
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index b2c048dba32f83807ee925a01e7a34e613a004b2..f458fd5a8250c885c206ae92016f341a4785af8a 100644 (file)
 #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.
+ * Test that the remove works for one 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);
+extern void test__kt_remove__directory_no_args__one_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.
+ * Test that the remove works for one 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);
+extern void test__kt_remove__directory_no_args__one_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.
+ * Test that the remove works for one 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);
+extern void test__kt_remove__directory_no_args__one_empty_exists_not(void **state);
+
+/**
+ * Test that the remove works for one directory file with child files and is a link without other complex arguments.
+ */
+extern void test__kt_remove__directory_no_args__one_empty_not_exists_link(void **state);
+
+/**
+ * Test that the remove works for one directory file with child files and is a not link without other complex arguments.
+ */
+extern void test__kt_remove__directory_no_args__one_empty_not_exists_link_not(void **state);
+
+/**
+ * Test that the remove works for two files that one does not exist and the other does, for directory files (that are empty) without other complex arguments.
+ */
+extern void test__kt_remove__directory_no_args__two_empty_exists_and_not(void **state);
+
+/**
+ * Test that the remove works for two files that exists and is a link, for directory files (that are empty) without other complex arguments.
+ */
+extern void test__kt_remove__directory_no_args__two_empty_exists_link(void **state);
+
+/**
+ * Test that the remove works for two files 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__two_empty_exists_link_not(void **state);
+
+/**
+ * Test that the remove works for two files that does not exist, for directory files (that are empty) without other complex arguments.
+ */
+extern void test__kt_remove__directory_no_args__two_empty_exists_not(void **state);
 
 #endif // _TEST__KT_remove__directory_no_args
diff --git a/tests/unit/remove/c/test-remove-directory_recurse_simple.c b/tests/unit/remove/c/test-remove-directory_recurse_simple.c
new file mode 100644 (file)
index 0000000..35be553
--- /dev/null
@@ -0,0 +1,56 @@
+#include "test-remove.h"
+#include "test-remove-directory_recurse_simple.h"
+
+#include <program/kevux/tools/remove/remove/main.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void test__kt_remove__directory_recurse_simple__one_child_one_exists_link(void **state) {
+
+  mock_unwrap = 0;
+  mock_directory_call_action = F_true;
+
+  struct stat stat_parent;
+  struct stat stat_regular;
+
+  //const f_string_static_t child_1 = macro_f_string_static_t_initialize_1("child_1", 0, 7); @todo use this.
+
+  {
+    const f_string_t argv[] = { "mocked_main", "to_remove", "-r", 0 };
+
+    memset(&stat_parent, 0, sizeof(struct stat));
+    stat_parent.st_mode = F_file_mode_all_d | F_file_type_directory_d; // Should result in kt_remove_flag_file_operate_remove_d.
+
+    memset(&stat_regular, 0, sizeof(struct stat));
+    stat_regular.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, &stat_parent);
+    will_return(__wrap_f_file_stat, F_false);
+
+    // Parent Directory processing, beging.
+    will_return(__wrap_f_directory_empty, F_false);
+
+    // Child file processing. @todo the __wrap_fl_directory_do mock will need to be unwrapped and then individual parts must be mocked.
+    will_return(__wrap_fl_directory_do, f_directory_recurse_do_flag_action_e | f_directory_recurse_do_flag_regular_e);
+
+    // Parent Directory processing, continue.
+    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);
+  }
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/tests/unit/remove/c/test-remove-directory_recurse_simple.h b/tests/unit/remove/c/test-remove-directory_recurse_simple.h
new file mode 100644 (file)
index 0000000..b40425c
--- /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_recurse_simple
+#define _TEST__KT_remove__directory_recurse_simple
+
+/**
+ * Test that the remove works for one file that exists and is 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(void **state);
+
+#endif // _TEST__KT_remove__directory_recurse_simple
index 2e4edecde1aee1bcca2bdc3bb783b7e0806d74db..1ab1a97178f8e6db3bcce38d635cd4a687dd21f5 100644 (file)
@@ -7,7 +7,7 @@
 extern "C" {
 #endif
 
-void test__kt_remove__regular_no_args__exists_link(void **state) {
+void test__kt_remove__regular_no_args__one_exists_link(void **state) {
 
   mock_unwrap = 0;
 
@@ -28,7 +28,7 @@ void test__kt_remove__regular_no_args__exists_link(void **state) {
     // 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);
+    const int result = kt_main_test__remove(3, argv, 0);
 
     assert_int_equal(result, 0);
   }
@@ -48,7 +48,7 @@ void test__kt_remove__regular_no_args__exists_link(void **state) {
     // 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);
+    const int result = kt_main_test__remove(4, argv, 0);
 
     assert_int_equal(result, 0);
   }
@@ -68,13 +68,13 @@ void test__kt_remove__regular_no_args__exists_link(void **state) {
     // 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);
+    const int result = kt_main_test__remove(4, argv, 0);
 
     assert_int_equal(result, 0);
   }
 }
 
-void test__kt_remove__regular_no_args__exists_link_not(void **state) {
+void test__kt_remove__regular_no_args__one_exists_link_not(void **state) {
 
   mock_unwrap = 0;
 
@@ -95,7 +95,7 @@ void test__kt_remove__regular_no_args__exists_link_not(void **state) {
     // 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);
+    const int result = kt_main_test__remove(4, argv, 0);
 
     assert_int_equal(result, 0);
   }
@@ -115,7 +115,7 @@ void test__kt_remove__regular_no_args__exists_link_not(void **state) {
     // 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);
+    const int result = kt_main_test__remove(4, argv, 0);
 
     assert_int_equal(result, 0);
   }
@@ -135,13 +135,13 @@ void test__kt_remove__regular_no_args__exists_link_not(void **state) {
     // 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);
+    const int result = kt_main_test__remove(4, argv, 0);
 
     assert_int_equal(result, 0);
   }
 }
 
-void test__kt_remove__regular_no_args__exists_not(void **state) {
+void test__kt_remove__regular_no_args__one_exists_not(void **state) {
 
   mock_unwrap = 0;
 
@@ -150,7 +150,7 @@ void test__kt_remove__regular_no_args__exists_not(void **state) {
 
     will_return(__wrap_f_file_exists, F_false);
 
-    const int result = kt_main_test__remove(2, argv, 0);
+    const int result = kt_main_test__remove(3, argv, 0);
 
     assert_int_equal(result, 0);
   }
@@ -160,7 +160,7 @@ void test__kt_remove__regular_no_args__exists_not(void **state) {
 
     will_return(__wrap_f_file_exists, F_false);
 
-    const int result = kt_main_test__remove(3, argv, 0);
+    const int result = kt_main_test__remove(4, argv, 0);
 
     assert_int_equal(result, 0);
   }
@@ -170,10 +170,312 @@ void test__kt_remove__regular_no_args__exists_not(void **state) {
 
     will_return(__wrap_f_file_exists, F_false);
 
+    const int result = kt_main_test__remove(4, argv, 0);
+
+    assert_int_equal(result, 0);
+  }
+}
+
+void test__kt_remove__regular_no_args__two_exists_and_not(void **state) {
+
+  mock_unwrap = 0;
+
+  struct stat statistics;
+
+  {
+    const f_string_t argv[] = { "mocked_main", "to_remove", "also/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 1.
+    will_return(__wrap_f_file_exists, F_false);
+
+    // Pre-process file 2.
+    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", "also/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 1.
+    will_return(__wrap_f_file_exists, F_false);
+
+    // Pre-process file 2.
+    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(4, argv, 0);
+
+    assert_int_equal(result, 0);
+  }
+
+  {
+    const f_string_t argv[] = { "mocked_main", "to_remove", "also/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 1.
+    will_return(__wrap_f_file_exists, F_false);
+
+    // Pre-process file 2.
+    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(4, argv, 0);
+
+    assert_int_equal(result, 0);
+  }
+}
+
+void test__kt_remove__regular_no_args__two_exists_link(void **state) {
+
+  mock_unwrap = 0;
+
+  struct stat statistics;
+
+  {
+    const f_string_t argv[] = { "mocked_main", "to_remove", "also/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 1.
+    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);
+
+    // Pre-process file 2.
+    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", "also/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 1.
+    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);
+
+    // Pre-process file 2.
+    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(4, argv, 0);
+
+    assert_int_equal(result, 0);
+  }
+
+  {
+    const f_string_t argv[] = { "mocked_main", "to_remove", "also/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 1.
+    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);
+
+    // Pre-process file 2.
+    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(4, argv, 0);
+
+    assert_int_equal(result, 0);
+  }
+}
+
+void test__kt_remove__regular_no_args__two_exists_link_not(void **state) {
+
+  mock_unwrap = 0;
+
+  struct stat statistics;
+
+  {
+    const f_string_t argv[] = { "mocked_main", "to_remove", "also/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 1.
+    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);
+
+    // Pre-process file 2.
+    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(4, argv, 0);
+
+    assert_int_equal(result, 0);
+  }
+
+  {
+    const f_string_t argv[] = { "mocked_main", "to_remove", "also/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 1.
+    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);
+
+    // Pre-process file 2.
+    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(4, argv, 0);
+
+    assert_int_equal(result, 0);
+  }
+
+  {
+    const f_string_t argv[] = { "mocked_main", "to_remove", "also/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 1.
+    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);
+
+    // Pre-process file 2.
+    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(4, argv, 0);
+
+    assert_int_equal(result, 0);
+  }
+}
+
+void test__kt_remove__regular_no_args__two_exists_not(void **state) {
+
+  mock_unwrap = 0;
+
+  {
+    const f_string_t argv[] = { "mocked_main", "to_remove", "also/remove", 0 };
+
+    will_return(__wrap_f_file_exists, F_false);
+    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", "also/remove", "+V", 0 };
+
+    will_return(__wrap_f_file_exists, F_false);
+    will_return(__wrap_f_file_exists, F_false);
+
+    const int result = kt_main_test__remove(4, argv, 0);
+
+    assert_int_equal(result, 0);
+  }
+
+  {
+    const f_string_t argv[] = { "mocked_main", "to_remove", "also/remove", "+D", 0 };
+
+    will_return(__wrap_f_file_exists, F_false);
+    will_return(__wrap_f_file_exists, F_false);
+
+    const int result = kt_main_test__remove(4, argv, 0);
+
+    assert_int_equal(result, 0);
+  }
 }
 
 #ifdef __cplusplus
index f1d630382b8b45511ae681591ae6fd2bbb1de1c0..1b889b4507668dc98836cffdec185063a96d4017 100644 (file)
 #define _TEST__KT_remove__regular_no_args
 
 /**
- * Test that the remove works for file that exists and is a link, for regular files without other complex arguments.
+ * Test that the remove works for one file that exists and is a link, for regular files without other complex arguments.
  */
-extern void test__kt_remove__regular_no_args__exists_link(void **state);
+extern void test__kt_remove__regular_no_args__one_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.
+ * Test that the remove works for one 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);
+extern void test__kt_remove__regular_no_args__one_exists_link_not(void **state);
 
 /**
- * Test that the remove works for file that does not exist, for regular files without other complex arguments.
+ * Test that the remove works for one file that does not exist, for regular files without other complex arguments.
  */
-extern void test__kt_remove__regular_no_args__exists_not(void **state);
+extern void test__kt_remove__regular_no_args__one_exists_not(void **state);
+
+/**
+ * Test that the remove works for two files that one does not exist and the other does, for regular files without other complex arguments.
+ */
+extern void test__kt_remove__regular_no_args__two_exists_and_not(void **state);
+
+/**
+ * Test that the remove works for two files that exists and is a link, for regular files without other complex arguments.
+ */
+extern void test__kt_remove__regular_no_args__two_exists_link(void **state);
+
+/**
+ * Test that the remove works for two files that exists and is a not link, for regular files without other complex arguments.
+ */
+extern void test__kt_remove__regular_no_args__two_exists_link_not(void **state);
+
+/**
+ * Test that the remove works for two files that does not exist, for regular files without other complex arguments.
+ */
+extern void test__kt_remove__regular_no_args__two_exists_not(void **state);
 
 #endif // _TEST__KT_remove__regular_no_args
index 1b89e12adfac297b2c36874e705138e684e9f21f..e1e5c560b663dbfbd4c3f26adc7b1b690435293a 100644 (file)
@@ -22,13 +22,27 @@ 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__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),
+    cmocka_unit_test(test__kt_remove__directory_no_args__one_empty_exists_link),
+    cmocka_unit_test(test__kt_remove__directory_no_args__one_empty_exists_link_not),
+    cmocka_unit_test(test__kt_remove__directory_no_args__one_empty_exists_not),
+    cmocka_unit_test(test__kt_remove__directory_no_args__one_empty_not_exists_link),
+    cmocka_unit_test(test__kt_remove__directory_no_args__one_empty_not_exists_link_not),
+
+    cmocka_unit_test(test__kt_remove__directory_no_args__two_empty_exists_and_not),
+    cmocka_unit_test(test__kt_remove__directory_no_args__two_empty_exists_link),
+    cmocka_unit_test(test__kt_remove__directory_no_args__two_empty_exists_link_not),
+    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__regular_no_args__one_exists_link),
+    cmocka_unit_test(test__kt_remove__regular_no_args__one_exists_link_not),
+    cmocka_unit_test(test__kt_remove__regular_no_args__one_exists_not),
+
+    cmocka_unit_test(test__kt_remove__regular_no_args__two_exists_and_not),
+    cmocka_unit_test(test__kt_remove__regular_no_args__two_exists_link),
+    cmocka_unit_test(test__kt_remove__regular_no_args__two_exists_link_not),
+    cmocka_unit_test(test__kt_remove__regular_no_args__two_exists_not),
   };
 
   return cmocka_run_group_tests(tests, setup, setdown);
index e687aafa677c83da4e7955ab97effee56f42dae8..43d61d9de217c0afc96b45b901baaa12cd191974 100644 (file)
@@ -33,6 +33,7 @@
 #include "test-remove-print_help.h"
 #include "test-remove-print_version.h"
 #include "test-remove-directory_no_args.h"
+#include "test-remove-directory_recurse_simple.h"
 #include "test-remove-regular_no_args.h"
 
 #ifdef __cplusplus