2 * Copyright (C) - 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by as
6 * published by the Free Software Foundation; only version 2 of the License.
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 51
15 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include <sys/types.h>
29 #include <common/compat/directory-handle.h>
30 #include <common/error.h>
36 int lttng_opt_quiet
= 1;
37 int lttng_opt_verbose
= 3;
40 #define DIR_CREATION_MODE (S_IRWXU | S_IRWXG)
43 * Returns the number of tests that ran (irrespective of the result) or a
44 * negative value on error (will abort all tests).
46 typedef int(test_func
)(const char *test_base_path
);
48 static test_func test_rmdir_fail_non_empty
;
49 static test_func test_rmdir_skip_non_empty
;
51 static test_func
*const test_funcs
[] = {
52 &test_rmdir_fail_non_empty
,
53 &test_rmdir_skip_non_empty
,
56 static bool dir_exists(const char *path
)
61 ret
= stat(path
, &st
);
62 return ret
== 0 && S_ISDIR(st
.st_mode
);
66 * Create a non-empty folder hierarchy from a directory handle:
77 static int create_non_empty_hierarchy_with_root(
78 struct lttng_directory_handle
*test_dir_handle
,
79 const char *test_root_name
)
82 const int file_flags
= O_WRONLY
| O_CREAT
| O_TRUNC
;
83 const mode_t file_mode
= S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
;
84 char *branch_name
= NULL
;
86 ret
= asprintf(&branch_name
, "%s/%s", test_root_name
, "a/b/c/d");
88 diag("Failed to format folder path");
91 ret
= lttng_directory_handle_create_subdirectory_recursive(
96 diag("Failed to create test folder hierarchy %s", branch_name
);
101 ret
= asprintf(&branch_name
, "%s/%s", test_root_name
, "a/b/e/f");
103 diag("Failed to format folder path");
106 ret
= lttng_directory_handle_create_subdirectory_recursive(
111 diag("Failed to create test folder hierarchy %s", branch_name
);
116 ret
= asprintf(&branch_name
, "%s/%s", test_root_name
, "a/b/e/file1");
118 diag("Failed to format file path");
121 ret
= lttng_directory_handle_open_file(
122 test_dir_handle
, branch_name
, file_flags
, file_mode
);
124 diag("Failed to create file %s", branch_name
);
129 PERROR("Failed to close fd to newly created file %s",
138 /* Remove "file1" from the test folder hierarchy. */
139 int remove_file_from_hierarchy(struct lttng_directory_handle
*test_dir_handle
,
140 const char *test_root_name
)
143 char *file_name
= NULL
;
145 ret
= asprintf(&file_name
, "%s/%s", test_root_name
, "a/b/e/file1");
147 diag("Failed to format file path");
151 ret
= lttng_directory_handle_unlink_file(test_dir_handle
,
154 PERROR("Failed to unlink file %s", file_name
);
162 static int test_rmdir_fail_non_empty(const char *test_dir
)
164 int ret
, tests_ran
= 0;
165 struct lttng_directory_handle
*test_dir_handle
;
166 char *created_dir
= NULL
;
167 const char test_root_name
[] = "fail_non_empty";
168 char *test_dir_path
= NULL
;
170 diag("rmdir (fail if non-empty)");
172 test_dir_handle
= lttng_directory_handle_create(test_dir
);
173 ok(test_dir_handle
, "Initialized directory handle from the test directory");
175 if (!test_dir_handle
) {
180 ret
= create_non_empty_hierarchy_with_root(test_dir_handle
, test_root_name
);
182 diag("Failed to setup folder/file hierarchy to run test");
186 ret
= lttng_directory_handle_remove_subdirectory_recursive(
187 test_dir_handle
, test_root_name
,
188 LTTNG_DIRECTORY_HANDLE_FAIL_NON_EMPTY_FLAG
);
189 ok(ret
== -1, "Error returned when attempting to recursively remove non-empty hierarchy with LTTNG_DIRECTORY_HANDLE_FAIL_NON_EMPTY_FLAG");
192 ret
= remove_file_from_hierarchy(test_dir_handle
, test_root_name
);
194 diag("Failed to remove file from test folder hierarchy");
198 ret
= lttng_directory_handle_remove_subdirectory_recursive(
199 test_dir_handle
, test_root_name
,
200 LTTNG_DIRECTORY_HANDLE_FAIL_NON_EMPTY_FLAG
);
201 ok(ret
== 0, "No error returned when recursively removing empty hierarchy with LTTNG_DIRECTORY_HANDLE_FAIL_NON_EMPTY_FLAG");
204 ret
= asprintf(&test_dir_path
, "%s/%s", test_dir
, test_root_name
);
206 diag("Failed to format test directory path");
209 ok(!dir_exists(test_dir_path
) && errno
== ENOENT
,
210 "Folder hierarchy %s successfully removed",
215 lttng_directory_handle_put(test_dir_handle
);
218 return ret
== 0 ? tests_ran
: ret
;
221 static int test_rmdir_skip_non_empty(const char *test_dir
)
223 int ret
, tests_ran
= 0;
224 struct lttng_directory_handle
*test_dir_handle
;
225 char *created_dir
= NULL
;
226 const char test_root_name
[] = "skip_non_empty";
227 char *test_dir_path
= NULL
;
229 diag("rmdir (skip if non-empty)");
231 test_dir_handle
= lttng_directory_handle_create(test_dir
);
232 ok(test_dir_handle
, "Initialized directory handle from the test directory");
234 if (!test_dir_handle
) {
239 ret
= create_non_empty_hierarchy_with_root(test_dir_handle
, test_root_name
);
241 diag("Failed to setup folder/file hierarchy to run test");
245 ret
= lttng_directory_handle_remove_subdirectory_recursive(
246 test_dir_handle
, test_root_name
,
247 LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG
);
248 ok(ret
== 0, "No error returned when attempting to recursively remove non-empty hierarchy with LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG");
251 ret
= asprintf(&test_dir_path
, "%s/%s", test_dir
, test_root_name
);
253 diag("Failed to format test directory path");
256 ok(dir_exists(test_dir_path
), "Test directory still exists after skip");
259 ret
= remove_file_from_hierarchy(test_dir_handle
, test_root_name
);
261 diag("Failed to remove file from test folder hierarchy");
265 ret
= lttng_directory_handle_remove_subdirectory_recursive(
266 test_dir_handle
, test_root_name
,
267 LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG
);
268 ok(ret
== 0, "No error returned when recursively removing empty hierarchy with LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG");
271 ok(!dir_exists(test_dir_path
) && errno
== ENOENT
,
272 "Folder hierarchy %s successfully removed",
277 lttng_directory_handle_put(test_dir_handle
);
280 return ret
== 0 ? tests_ran
: ret
;
283 int main(int argc
, char **argv
)
286 char test_dir
[] = "/tmp/lttng-XXXXXX";
287 int tests_left
= TEST_COUNT
;
290 plan_tests(TEST_COUNT
);
292 diag("lttng_directory_handle tests");
294 if (!mkdtemp(test_dir
)) {
295 diag("Failed to generate temporary test directory");
299 for (func_idx
= 0; func_idx
< sizeof(test_funcs
) / sizeof(*test_funcs
);
301 tests_left
-= test_funcs
[func_idx
](test_dir
);
304 diag("Skipping %d tests that could not be executed due to a prior error",
306 skip(tests_left
, "test due to an error");
309 ret
= rmdir(test_dir
);
311 diag("Failed to clean-up test directory: %s", strerror(errno
));
313 return exit_status();