2 * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 * SPDX-License-Identifier: GPL-2.0-only
14 #include <sys/types.h>
17 #include <common/compat/directory-handle.h>
18 #include <common/compat/errno.h>
19 #include <common/error.h>
25 int lttng_opt_quiet
= 1;
26 int lttng_opt_verbose
= 3;
29 #define DIR_CREATION_MODE (S_IRWXU | S_IRWXG)
32 * Returns the number of tests that ran (irrespective of the result) or a
33 * negative value on error (will abort all tests).
35 typedef int(test_func
)(const char *test_base_path
);
37 static test_func test_rmdir_fail_non_empty
;
38 static test_func test_rmdir_skip_non_empty
;
40 static test_func
*const test_funcs
[] = {
41 &test_rmdir_fail_non_empty
,
42 &test_rmdir_skip_non_empty
,
45 static bool dir_exists(const char *path
)
50 ret
= stat(path
, &st
);
51 return ret
== 0 && S_ISDIR(st
.st_mode
);
55 * Create a non-empty folder hierarchy from a directory handle:
66 static int create_non_empty_hierarchy_with_root(
67 struct lttng_directory_handle
*test_dir_handle
,
68 const char *test_root_name
)
71 const int file_flags
= O_WRONLY
| O_CREAT
| O_TRUNC
;
72 const mode_t file_mode
= S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
;
73 char *branch_name
= NULL
;
75 ret
= asprintf(&branch_name
, "%s/%s", test_root_name
, "a/b/c/d");
77 diag("Failed to format folder path");
80 ret
= lttng_directory_handle_create_subdirectory_recursive(
85 diag("Failed to create test folder hierarchy %s", branch_name
);
90 ret
= asprintf(&branch_name
, "%s/%s", test_root_name
, "a/b/e/f");
92 diag("Failed to format folder path");
95 ret
= lttng_directory_handle_create_subdirectory_recursive(
100 diag("Failed to create test folder hierarchy %s", branch_name
);
105 ret
= asprintf(&branch_name
, "%s/%s", test_root_name
, "a/b/e/file1");
107 diag("Failed to format file path");
110 ret
= lttng_directory_handle_open_file(
111 test_dir_handle
, branch_name
, file_flags
, file_mode
);
113 diag("Failed to create file %s", branch_name
);
118 PERROR("Failed to close fd to newly created file %s",
127 /* Remove "file1" from the test folder hierarchy. */
129 int remove_file_from_hierarchy(struct lttng_directory_handle
*test_dir_handle
,
130 const char *test_root_name
)
133 char *file_name
= NULL
;
135 ret
= asprintf(&file_name
, "%s/%s", test_root_name
, "a/b/e/file1");
137 diag("Failed to format file path");
141 ret
= lttng_directory_handle_unlink_file(test_dir_handle
,
144 PERROR("Failed to unlink file %s", file_name
);
152 static int test_rmdir_fail_non_empty(const char *test_dir
)
154 int ret
, tests_ran
= 0;
155 struct lttng_directory_handle
*test_dir_handle
;
156 char *created_dir
= NULL
;
157 const char test_root_name
[] = "fail_non_empty";
158 char *test_dir_path
= NULL
;
160 diag("rmdir (fail if non-empty)");
162 test_dir_handle
= lttng_directory_handle_create(test_dir
);
163 ok(test_dir_handle
, "Initialized directory handle from the test directory");
165 if (!test_dir_handle
) {
170 ret
= create_non_empty_hierarchy_with_root(test_dir_handle
, test_root_name
);
172 diag("Failed to setup folder/file hierarchy to run test");
176 ret
= lttng_directory_handle_remove_subdirectory_recursive(
177 test_dir_handle
, test_root_name
,
178 LTTNG_DIRECTORY_HANDLE_FAIL_NON_EMPTY_FLAG
);
179 ok(ret
== -1, "Error returned when attempting to recursively remove non-empty hierarchy with LTTNG_DIRECTORY_HANDLE_FAIL_NON_EMPTY_FLAG");
182 ret
= remove_file_from_hierarchy(test_dir_handle
, test_root_name
);
184 diag("Failed to remove file from test folder hierarchy");
188 ret
= lttng_directory_handle_remove_subdirectory_recursive(
189 test_dir_handle
, test_root_name
,
190 LTTNG_DIRECTORY_HANDLE_FAIL_NON_EMPTY_FLAG
);
191 ok(ret
== 0, "No error returned when recursively removing empty hierarchy with LTTNG_DIRECTORY_HANDLE_FAIL_NON_EMPTY_FLAG");
194 ret
= asprintf(&test_dir_path
, "%s/%s", test_dir
, test_root_name
);
196 diag("Failed to format test directory path");
199 ok(!dir_exists(test_dir_path
) && errno
== ENOENT
,
200 "Folder hierarchy %s successfully removed",
205 lttng_directory_handle_put(test_dir_handle
);
208 return ret
== 0 ? tests_ran
: ret
;
211 static int test_rmdir_skip_non_empty(const char *test_dir
)
213 int ret
, tests_ran
= 0;
214 struct lttng_directory_handle
*test_dir_handle
;
215 char *created_dir
= NULL
;
216 const char test_root_name
[] = "skip_non_empty";
217 char *test_dir_path
= NULL
;
219 diag("rmdir (skip if non-empty)");
221 test_dir_handle
= lttng_directory_handle_create(test_dir
);
222 ok(test_dir_handle
, "Initialized directory handle from the test directory");
224 if (!test_dir_handle
) {
229 ret
= create_non_empty_hierarchy_with_root(test_dir_handle
, test_root_name
);
231 diag("Failed to setup folder/file hierarchy to run test");
235 ret
= lttng_directory_handle_remove_subdirectory_recursive(
236 test_dir_handle
, test_root_name
,
237 LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG
);
238 ok(ret
== 0, "No error returned when attempting to recursively remove non-empty hierarchy with LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG");
241 ret
= asprintf(&test_dir_path
, "%s/%s", test_dir
, test_root_name
);
243 diag("Failed to format test directory path");
246 ok(dir_exists(test_dir_path
), "Test directory still exists after skip");
249 ret
= remove_file_from_hierarchy(test_dir_handle
, test_root_name
);
251 diag("Failed to remove file from test folder hierarchy");
255 ret
= lttng_directory_handle_remove_subdirectory_recursive(
256 test_dir_handle
, test_root_name
,
257 LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG
);
258 ok(ret
== 0, "No error returned when recursively removing empty hierarchy with LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG");
261 ok(!dir_exists(test_dir_path
) && errno
== ENOENT
,
262 "Folder hierarchy %s successfully removed",
267 lttng_directory_handle_put(test_dir_handle
);
270 return ret
== 0 ? tests_ran
: ret
;
273 int main(int argc
, char **argv
)
276 char test_dir
[] = "/tmp/lttng-XXXXXX";
277 int tests_left
= TEST_COUNT
;
280 plan_tests(TEST_COUNT
);
282 diag("lttng_directory_handle tests");
284 if (!mkdtemp(test_dir
)) {
285 diag("Failed to generate temporary test directory");
289 for (func_idx
= 0; func_idx
< sizeof(test_funcs
) / sizeof(*test_funcs
);
291 tests_left
-= test_funcs
[func_idx
](test_dir
);
294 diag("Skipping %d tests that could not be executed due to a prior error",
296 skip(tests_left
, "test due to an error");
299 ret
= rmdir(test_dir
);
301 diag("Failed to clean-up test directory: %s", strerror(errno
));
303 return exit_status();