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 ret
= lttng_directory_handle_init(&test_dir_handle
, test_dir
);
173 ok(ret
== 0, "Initialized directory handle from the test directory");
179 ret
= create_non_empty_hierarchy_with_root(&test_dir_handle
, test_root_name
);
181 diag("Failed to setup folder/file hierarchy to run test");
185 ret
= lttng_directory_handle_remove_subdirectory_recursive(
186 &test_dir_handle
, test_root_name
,
187 LTTNG_DIRECTORY_HANDLE_FAIL_NON_EMPTY_FLAG
);
188 ok(ret
== -1, "Error returned when attempting to recursively remove non-empty hierarchy with LTTNG_DIRECTORY_HANDLE_FAIL_NON_EMPTY_FLAG");
191 ret
= remove_file_from_hierarchy(&test_dir_handle
, test_root_name
);
193 diag("Failed to remove file from test folder hierarchy");
197 ret
= lttng_directory_handle_remove_subdirectory_recursive(
198 &test_dir_handle
, test_root_name
,
199 LTTNG_DIRECTORY_HANDLE_FAIL_NON_EMPTY_FLAG
);
200 ok(ret
== 0, "No error returned when recursively removing empty hierarchy with LTTNG_DIRECTORY_HANDLE_FAIL_NON_EMPTY_FLAG");
203 ret
= asprintf(&test_dir_path
, "%s/%s", test_dir
, test_root_name
);
205 diag("Failed to format test directory path");
208 ok(!dir_exists(test_dir_path
) && errno
== ENOENT
,
209 "Folder hierarchy %s successfully removed",
214 lttng_directory_handle_fini(&test_dir_handle
);
217 return ret
== 0 ? tests_ran
: ret
;
220 static int test_rmdir_skip_non_empty(const char *test_dir
)
222 int ret
, tests_ran
= 0;
223 struct lttng_directory_handle test_dir_handle
;
224 char *created_dir
= NULL
;
225 const char test_root_name
[] = "skip_non_empty";
226 char *test_dir_path
= NULL
;
228 diag("rmdir (skip if non-empty)");
230 ret
= lttng_directory_handle_init(&test_dir_handle
, test_dir
);
231 ok(ret
== 0, "Initialized directory handle from the test directory");
237 ret
= create_non_empty_hierarchy_with_root(&test_dir_handle
, test_root_name
);
239 diag("Failed to setup folder/file hierarchy to run test");
243 ret
= lttng_directory_handle_remove_subdirectory_recursive(
244 &test_dir_handle
, test_root_name
,
245 LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG
);
246 ok(ret
== 0, "No error returned when attempting to recursively remove non-empty hierarchy with LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG");
249 ret
= asprintf(&test_dir_path
, "%s/%s", test_dir
, test_root_name
);
251 diag("Failed to format test directory path");
254 ok(dir_exists(test_dir_path
), "Test directory still exists after skip");
257 ret
= remove_file_from_hierarchy(&test_dir_handle
, test_root_name
);
259 diag("Failed to remove file from test folder hierarchy");
263 ret
= lttng_directory_handle_remove_subdirectory_recursive(
264 &test_dir_handle
, test_root_name
,
265 LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG
);
266 ok(ret
== 0, "No error returned when recursively removing empty hierarchy with LTTNG_DIRECTORY_HANDLE_SKIP_NON_EMPTY_FLAG");
269 ok(!dir_exists(test_dir_path
) && errno
== ENOENT
,
270 "Folder hierarchy %s successfully removed",
275 lttng_directory_handle_fini(&test_dir_handle
);
278 return ret
== 0 ? tests_ran
: ret
;
281 int main(int argc
, char **argv
)
284 char test_dir
[] = "/tmp/lttng-XXXXXX";
285 int tests_left
= TEST_COUNT
;
288 plan_tests(TEST_COUNT
);
290 diag("lttng_directory_handle tests");
292 if (!mkdtemp(test_dir
)) {
293 diag("Failed to generate temporary test directory");
297 for (func_idx
= 0; func_idx
< sizeof(test_funcs
) / sizeof(*test_funcs
);
299 tests_left
-= test_funcs
[func_idx
](test_dir
);
302 diag("Skipping %d tests that could not be executed due to a prior error",
304 skip(tests_left
, "test due to an error");
307 ret
= rmdir(test_dir
);
309 diag("Failed to clean-up test directory: %s", strerror(errno
));
311 return exit_status();