2 * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 * SPDX-License-Identifier: GPL-2.0-only
8 #include <common/compat/directory-handle.hpp>
9 #include <common/compat/errno.hpp>
10 #include <common/error.hpp>
18 #include <sys/types.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 using test_func
= int(const char *);
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(struct lttng_directory_handle
*test_dir_handle
,
67 const char *test_root_name
)
70 const int file_flags
= O_WRONLY
| O_CREAT
| O_TRUNC
;
71 const mode_t file_mode
= S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
;
72 char *branch_name
= nullptr;
74 ret
= asprintf(&branch_name
, "%s/%s", test_root_name
, "a/b/c/d");
76 diag("Failed to format folder path");
79 ret
= lttng_directory_handle_create_subdirectory_recursive(
80 test_dir_handle
, branch_name
, DIR_CREATION_MODE
);
82 diag("Failed to create test folder hierarchy %s", branch_name
);
87 ret
= asprintf(&branch_name
, "%s/%s", test_root_name
, "a/b/e/f");
89 diag("Failed to format folder path");
92 ret
= lttng_directory_handle_create_subdirectory_recursive(
93 test_dir_handle
, branch_name
, DIR_CREATION_MODE
);
95 diag("Failed to create test folder hierarchy %s", branch_name
);
100 ret
= asprintf(&branch_name
, "%s/%s", test_root_name
, "a/b/e/file1");
102 diag("Failed to format file path");
105 ret
= lttng_directory_handle_open_file(test_dir_handle
, branch_name
, file_flags
, file_mode
);
107 diag("Failed to create file %s", branch_name
);
112 PERROR("Failed to close fd to newly created file %s", branch_name
);
120 /* Remove "file1" from the test folder hierarchy. */
121 static int remove_file_from_hierarchy(struct lttng_directory_handle
*test_dir_handle
,
122 const char *test_root_name
)
125 char *file_name
= nullptr;
127 ret
= asprintf(&file_name
, "%s/%s", test_root_name
, "a/b/e/file1");
129 diag("Failed to format file path");
133 ret
= lttng_directory_handle_unlink_file(test_dir_handle
, file_name
);
135 PERROR("Failed to unlink file %s", file_name
);
143 static int test_rmdir_fail_non_empty(const char *test_dir
)
145 int ret
, tests_ran
= 0;
146 struct lttng_directory_handle
*test_dir_handle
;
147 char *created_dir
= nullptr;
148 const char test_root_name
[] = "fail_non_empty";
149 char *test_dir_path
= nullptr;
151 diag("rmdir (fail if non-empty)");
153 test_dir_handle
= lttng_directory_handle_create(test_dir
);
154 ok(test_dir_handle
, "Initialized directory handle from the test directory");
156 if (!test_dir_handle
) {
161 ret
= create_non_empty_hierarchy_with_root(test_dir_handle
, test_root_name
);
163 diag("Failed to setup folder/file hierarchy to run test");
167 ret
= lttng_directory_handle_remove_subdirectory_recursive(
168 test_dir_handle
, test_root_name
, LTTNG_DIRECTORY_HANDLE_FAIL_NON_EMPTY_FLAG
);
170 "Error returned when attempting to recursively remove non-empty hierarchy with LTTNG_DIRECTORY_HANDLE_FAIL_NON_EMPTY_FLAG");
173 ret
= remove_file_from_hierarchy(test_dir_handle
, test_root_name
);
175 diag("Failed to remove file from test folder hierarchy");
179 ret
= lttng_directory_handle_remove_subdirectory_recursive(
180 test_dir_handle
, test_root_name
, LTTNG_DIRECTORY_HANDLE_FAIL_NON_EMPTY_FLAG
);
182 "No error returned when recursively removing empty hierarchy with LTTNG_DIRECTORY_HANDLE_FAIL_NON_EMPTY_FLAG");
185 ret
= asprintf(&test_dir_path
, "%s/%s", test_dir
, test_root_name
);
187 diag("Failed to format test directory path");
190 ok(!dir_exists(test_dir_path
) && errno
== ENOENT
,
191 "Folder hierarchy %s successfully removed",
196 lttng_directory_handle_put(test_dir_handle
);
199 return ret
== 0 ? tests_ran
: ret
;
202 static int test_rmdir_skip_non_empty(const char *test_dir
)
204 int ret
, tests_ran
= 0;
205 struct lttng_directory_handle
*test_dir_handle
;
206 char *created_dir
= nullptr;
207 const char test_root_name
[] = "skip_non_empty";
208 char *test_dir_path
= nullptr;
210 diag("rmdir (skip if non-empty)");
212 test_dir_handle
= lttng_directory_handle_create(test_dir
);
213 ok(test_dir_handle
, "Initialized directory handle from the test directory");
215 if (!test_dir_handle
) {
220 ret
= create_non_empty_hierarchy_with_root(test_dir_handle
, test_root_name
);
222 diag("Failed to setup folder/file hierarchy to run test");
226 ret
= lttng_directory_handle_remove_subdirectory_recursive(
227 test_dir_handle
, test_root_name
, LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG
);
229 "No error returned when attempting to recursively remove non-empty hierarchy with LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG");
232 ret
= asprintf(&test_dir_path
, "%s/%s", test_dir
, test_root_name
);
234 diag("Failed to format test directory path");
237 ok(dir_exists(test_dir_path
), "Test directory still exists after skip");
240 ret
= remove_file_from_hierarchy(test_dir_handle
, test_root_name
);
242 diag("Failed to remove file from test folder hierarchy");
246 ret
= lttng_directory_handle_remove_subdirectory_recursive(
247 test_dir_handle
, test_root_name
, LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG
);
249 "No error returned when recursively removing empty hierarchy with LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG");
252 ok(!dir_exists(test_dir_path
) && errno
== ENOENT
,
253 "Folder hierarchy %s successfully removed",
258 lttng_directory_handle_put(test_dir_handle
);
261 return ret
== 0 ? tests_ran
: ret
;
267 char test_dir
[] = "/tmp/lttng-XXXXXX";
268 int tests_left
= TEST_COUNT
;
271 plan_tests(TEST_COUNT
);
273 diag("lttng_directory_handle tests");
275 if (!mkdtemp(test_dir
)) {
276 diag("Failed to generate temporary test directory");
280 for (func_idx
= 0; func_idx
< sizeof(test_funcs
) / sizeof(*test_funcs
); func_idx
++) {
281 tests_left
-= test_funcs
[func_idx
](test_dir
);
284 diag("Skipping %d tests that could not be executed due to a prior error",
286 skip(tests_left
, "test due to an error");
289 ret
= rmdir(test_dir
);
291 diag("Failed to clean-up test directory: %s", strerror(errno
));
293 return exit_status();