2 * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 * SPDX-License-Identifier: GPL-2.0-only
15 #include <sys/types.h>
18 #include <common/compat/directory-handle.h>
19 #include <common/compat/errno.h>
20 #include <common/error.h>
26 int lttng_opt_quiet
= 1;
27 int lttng_opt_verbose
= 3;
30 #define DIR_CREATION_MODE (S_IRWXU | S_IRWXG)
33 * Returns the number of tests that ran (irrespective of the result) or a
34 * negative value on error (will abort all tests).
36 typedef int(test_func
)(const char *test_base_path
);
38 static test_func test_rmdir_fail_non_empty
;
39 static test_func test_rmdir_skip_non_empty
;
41 static test_func
*const test_funcs
[] = {
42 &test_rmdir_fail_non_empty
,
43 &test_rmdir_skip_non_empty
,
46 static bool dir_exists(const char *path
)
51 ret
= stat(path
, &st
);
52 return ret
== 0 && S_ISDIR(st
.st_mode
);
56 * Create a non-empty folder hierarchy from a directory handle:
67 static int create_non_empty_hierarchy_with_root(
68 struct lttng_directory_handle
*test_dir_handle
,
69 const char *test_root_name
)
72 const int file_flags
= O_WRONLY
| O_CREAT
| O_TRUNC
;
73 const mode_t file_mode
= S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
;
74 char *branch_name
= NULL
;
76 ret
= asprintf(&branch_name
, "%s/%s", test_root_name
, "a/b/c/d");
78 diag("Failed to format folder path");
81 ret
= lttng_directory_handle_create_subdirectory_recursive(
86 diag("Failed to create test folder hierarchy %s", branch_name
);
91 ret
= asprintf(&branch_name
, "%s/%s", test_root_name
, "a/b/e/f");
93 diag("Failed to format folder path");
96 ret
= lttng_directory_handle_create_subdirectory_recursive(
101 diag("Failed to create test folder hierarchy %s", branch_name
);
106 ret
= asprintf(&branch_name
, "%s/%s", test_root_name
, "a/b/e/file1");
108 diag("Failed to format file path");
111 ret
= lttng_directory_handle_open_file(
112 test_dir_handle
, branch_name
, file_flags
, file_mode
);
114 diag("Failed to create file %s", branch_name
);
119 PERROR("Failed to close fd to newly created file %s",
128 /* Remove "file1" from the test folder hierarchy. */
130 int remove_file_from_hierarchy(struct lttng_directory_handle
*test_dir_handle
,
131 const char *test_root_name
)
134 char *file_name
= NULL
;
136 ret
= asprintf(&file_name
, "%s/%s", test_root_name
, "a/b/e/file1");
138 diag("Failed to format file path");
142 ret
= lttng_directory_handle_unlink_file(test_dir_handle
,
145 PERROR("Failed to unlink file %s", file_name
);
153 static int test_rmdir_fail_non_empty(const char *test_dir
)
155 int ret
, tests_ran
= 0;
156 struct lttng_directory_handle
*test_dir_handle
;
157 char *created_dir
= NULL
;
158 const char test_root_name
[] = "fail_non_empty";
159 char *test_dir_path
= NULL
;
161 diag("rmdir (fail if non-empty)");
163 test_dir_handle
= lttng_directory_handle_create(test_dir
);
164 ok(test_dir_handle
, "Initialized directory handle from the test directory");
166 if (!test_dir_handle
) {
171 ret
= create_non_empty_hierarchy_with_root(test_dir_handle
, test_root_name
);
173 diag("Failed to setup folder/file hierarchy to run test");
177 ret
= lttng_directory_handle_remove_subdirectory_recursive(
178 test_dir_handle
, test_root_name
,
179 LTTNG_DIRECTORY_HANDLE_FAIL_NON_EMPTY_FLAG
);
180 ok(ret
== -1, "Error returned when attempting to recursively remove non-empty hierarchy with LTTNG_DIRECTORY_HANDLE_FAIL_NON_EMPTY_FLAG");
183 ret
= remove_file_from_hierarchy(test_dir_handle
, test_root_name
);
185 diag("Failed to remove file from test folder hierarchy");
189 ret
= lttng_directory_handle_remove_subdirectory_recursive(
190 test_dir_handle
, test_root_name
,
191 LTTNG_DIRECTORY_HANDLE_FAIL_NON_EMPTY_FLAG
);
192 ok(ret
== 0, "No error returned when recursively removing empty hierarchy with LTTNG_DIRECTORY_HANDLE_FAIL_NON_EMPTY_FLAG");
195 ret
= asprintf(&test_dir_path
, "%s/%s", test_dir
, test_root_name
);
197 diag("Failed to format test directory path");
200 ok(!dir_exists(test_dir_path
) && errno
== ENOENT
,
201 "Folder hierarchy %s successfully removed",
206 lttng_directory_handle_put(test_dir_handle
);
209 return ret
== 0 ? tests_ran
: ret
;
212 static int test_rmdir_skip_non_empty(const char *test_dir
)
214 int ret
, tests_ran
= 0;
215 struct lttng_directory_handle
*test_dir_handle
;
216 char *created_dir
= NULL
;
217 const char test_root_name
[] = "skip_non_empty";
218 char *test_dir_path
= NULL
;
220 diag("rmdir (skip if non-empty)");
222 test_dir_handle
= lttng_directory_handle_create(test_dir
);
223 ok(test_dir_handle
, "Initialized directory handle from the test directory");
225 if (!test_dir_handle
) {
230 ret
= create_non_empty_hierarchy_with_root(test_dir_handle
, test_root_name
);
232 diag("Failed to setup folder/file hierarchy to run test");
236 ret
= lttng_directory_handle_remove_subdirectory_recursive(
237 test_dir_handle
, test_root_name
,
238 LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG
);
239 ok(ret
== 0, "No error returned when attempting to recursively remove non-empty hierarchy with LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG");
242 ret
= asprintf(&test_dir_path
, "%s/%s", test_dir
, test_root_name
);
244 diag("Failed to format test directory path");
247 ok(dir_exists(test_dir_path
), "Test directory still exists after skip");
250 ret
= remove_file_from_hierarchy(test_dir_handle
, test_root_name
);
252 diag("Failed to remove file from test folder hierarchy");
256 ret
= lttng_directory_handle_remove_subdirectory_recursive(
257 test_dir_handle
, test_root_name
,
258 LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG
);
259 ok(ret
== 0, "No error returned when recursively removing empty hierarchy with LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG");
262 ok(!dir_exists(test_dir_path
) && errno
== ENOENT
,
263 "Folder hierarchy %s successfully removed",
268 lttng_directory_handle_put(test_dir_handle
);
271 return ret
== 0 ? tests_ran
: ret
;
274 int main(int argc
, char **argv
)
277 char test_dir
[] = "/tmp/lttng-XXXXXX";
278 int tests_left
= TEST_COUNT
;
281 plan_tests(TEST_COUNT
);
283 diag("lttng_directory_handle tests");
285 if (!mkdtemp(test_dir
)) {
286 diag("Failed to generate temporary test directory");
290 for (func_idx
= 0; func_idx
< sizeof(test_funcs
) / sizeof(*test_funcs
);
292 tests_left
-= test_funcs
[func_idx
](test_dir
);
295 diag("Skipping %d tests that could not be executed due to a prior error",
297 skip(tests_left
, "test due to an error");
300 ret
= rmdir(test_dir
);
302 diag("Failed to clean-up test directory: %s", strerror(errno
));
304 return exit_status();