2 * Copyright (C) 2013 Raphaƫl Beamonte <raphael.beamonte@gmail.com>
4 * SPDX-License-Identifier: GPL-2.0-only
14 #include <sys/types.h>
18 #include <common/utils.h>
19 #include <common/common.h>
22 int lttng_opt_quiet
= 1;
23 int lttng_opt_verbose
= 3;
26 struct valid_test_input
{
28 const char *relative_part
;
29 const char *absolute_part
;
37 struct symlink_test_input
{
39 const char *expected_result
;
42 /* Valid test cases */
43 static struct valid_test_input valid_tests_inputs
[] = {
44 { "/a/b/c/d/e", "", "/a/b/c/d/e" },
45 { "/a//b//c/d/e", "", "/a/b/c/d/e" },
46 { "./a/b/c/d/e", ".", "/a/b/c/d/e" },
47 { "../a/b/c/d/../e", "..", "/a/b/c/e" },
48 { ".././a/b/c/d/./e", "..", "/a/b/c/d/e" },
49 { "../../a/b/c/d/e", "../..", "/a/b/c/d/e" },
50 { "./a/b/../c/d/../e", ".", "/a/c/e" },
51 { "../a/b/../../c/./d/./e", "..", "/c/d/e" },
52 { "../../a/b/../c/d/../../e", "../..", "/a/e" },
53 { "./a/b/c/d/../../../../e", ".", "/e" },
54 { ".././a/b/c/d/./e", "..", "/a/b/c/d/e" },
57 { "../../", "../..", "/" },
58 { "../..", "../..", "" },
63 { "/../a/b/c/d/e", "", "/a/b/c/d/e" },
64 { "/a/b/c/d/../../../../../e", "", "/e" },
68 char **valid_tests_expected_results
;
69 static const int num_valid_tests
=
70 sizeof(valid_tests_inputs
) / sizeof(valid_tests_inputs
[0]);
72 /* Symlinks test cases */
73 char tree_origin
[] = "/tmp/test_utils_expand_path.XXXXXX";
75 static const char * const tree_dirs
[] = {
81 static const int num_tree_dirs
=
82 sizeof(tree_dirs
) / sizeof(tree_dirs
[0]);
84 static struct tree_symlink tree_symlinks
[] = {
90 { "a/b/c/g", "../../../" },
92 static const int num_tree_symlinks
=
93 sizeof(tree_symlinks
) / sizeof(tree_symlinks
[0]);
95 static struct symlink_test_input symlink_tests_inputs
[] = {
96 { "a/g/../l/.", "a/b/l" },
97 { "a/g/../l/./", "a/b/l/" },
98 { "a/g/../l/..", "a/b" },
99 { "a/g/../l/../", "a/b/" },
102 static const int num_symlink_tests
=
103 sizeof(symlink_tests_inputs
) / sizeof(symlink_tests_inputs
[0]);
105 /* Invalid test cases */
106 static char *invalid_tests_inputs
[] = {
109 static const int num_invalid_tests
=
110 sizeof(invalid_tests_inputs
) / sizeof(invalid_tests_inputs
[0]);
112 #define PRINT_ERR(fmt, args...) \
113 fprintf(stderr, "test_utils_expand_path: error: " fmt "\n", ## args)
115 static int prepare_valid_results(void)
118 char *relative
, *cur_path
= NULL
, *prev_path
= NULL
,
119 *pprev_path
= NULL
, *empty
= NULL
;
122 /* Prepare the relative paths */
123 cur_path
= realpath(".", NULL
);
124 prev_path
= realpath("..", NULL
);
125 pprev_path
= realpath("../..", NULL
);
127 if (!cur_path
|| !prev_path
|| !pprev_path
|| !empty
) {
128 PRINT_ERR("strdup out of memory");
133 /* allocate memory for the expected results */
134 valid_tests_expected_results
= (char **) zmalloc(sizeof(char *) * num_valid_tests
);
135 if (!valid_tests_expected_results
) {
136 PRINT_ERR("out of memory");
140 for (i
= 0; i
< num_valid_tests
; i
++) {
141 valid_tests_expected_results
[i
] = (char *) malloc(PATH_MAX
);
142 if (valid_tests_expected_results
[i
] == NULL
) {
143 PRINT_ERR("malloc expected results");
148 if (strcmp(valid_tests_inputs
[i
].relative_part
, ".") == 0) {
150 } else if (strcmp(valid_tests_inputs
[i
].relative_part
, "..") == 0) {
151 relative
= prev_path
;
152 } else if (strcmp(valid_tests_inputs
[i
].relative_part
, "../..") == 0) {
153 relative
= pprev_path
;
158 snprintf(valid_tests_expected_results
[i
], PATH_MAX
,
159 "%s%s", relative
, valid_tests_inputs
[i
].absolute_part
);
171 static int free_valid_results(void)
175 for (i
= 0; i
< num_valid_tests
; i
++) {
176 free(valid_tests_expected_results
[i
]);
179 free(valid_tests_expected_results
);
184 static int prepare_symlink_tree(void)
187 char tmppath
[PATH_MAX
] = {};
189 /* Create the temporary directory */
190 if (mkdtemp(tree_origin
) == NULL
) {
191 PRINT_ERR("failed to mkdtemp");
195 /* Create the directories of the test tree */
196 for (i
= 0; i
< num_tree_dirs
; i
++) {
197 snprintf(tmppath
, sizeof(tmppath
), "%s/%s", tree_origin
,
200 if (mkdir(tmppath
, 0755) != 0) {
201 PRINT_ERR("mkdir failed with path \"%s\"", tmppath
);
206 /* Create the symlinks of the test tree */
207 for (i
= 0; i
< num_tree_symlinks
; i
++) {
208 snprintf(tmppath
, sizeof(tmppath
), "%s/%s",
209 tree_origin
, tree_symlinks
[i
].orig
);
211 if (symlink(tree_symlinks
[i
].dest
, tmppath
) != 0) {
212 PRINT_ERR("failed to symlink \"%s\" to \"%s\"", tmppath
,
213 tree_symlinks
[i
].dest
);
224 static int free_symlink_tree(void)
227 char tmppath
[PATH_MAX
];
229 /* Remove the symlinks from the test tree */
230 for (i
= num_tree_symlinks
- 1; i
> -1; i
--) {
231 snprintf(tmppath
, PATH_MAX
, "%s/%s",
232 tree_origin
, tree_symlinks
[i
].orig
);
234 if (unlink(tmppath
) != 0) {
235 PRINT_ERR("failed to unlink \"%s\"", tmppath
);
240 /* Remove the directories from the test tree */
241 for (i
= num_tree_dirs
- 1; i
> -1; i
--) {
242 snprintf(tmppath
, PATH_MAX
, "%s/%s", tree_origin
, tree_dirs
[i
]);
244 if (rmdir(tmppath
) != 0) {
245 PRINT_ERR("failed to rmdir \"%s\"", tmppath
);
250 /* Remove the temporary directory */
251 if (rmdir(tree_origin
) != 0) {
252 PRINT_ERR("failed to rmdir \"%s\"", tree_origin
);
262 static void test_utils_expand_path(void)
265 char name
[100], tmppath
[PATH_MAX
], real_tree_origin
[PATH_MAX
];
268 /* Test valid cases */
269 for (i
= 0; i
< num_valid_tests
; i
++) {
270 sprintf(name
, "valid test case: %s", valid_tests_inputs
[i
].input
);
272 result
= utils_expand_path(valid_tests_inputs
[i
].input
);
274 strcmp(result
, valid_tests_expected_results
[i
]) == 0, "%s", name
);
280 * Get the realpath for the tree_origin since it can itself be a
283 result
= realpath(tree_origin
, real_tree_origin
);
285 fail("realpath failed.");
289 /* Test symlink tree cases */
290 treelen
= strlen(real_tree_origin
) + 1;
291 for (i
= 0; i
< num_symlink_tests
; i
++) {
294 sprintf(name
, "symlink tree test case: [tmppath/]%s",
295 symlink_tests_inputs
[i
].input
);
297 ret
= snprintf(tmppath
, PATH_MAX
, "%s/%s",
299 symlink_tests_inputs
[i
].input
);
300 if (ret
== -1 || ret
>= PATH_MAX
) {
301 PRINT_ERR("truncation occurred while concatenating paths \"%s\" and \"%s\"",
303 symlink_tests_inputs
[i
].input
);
307 result
= utils_expand_path(tmppath
);
308 ok(result
!= NULL
&& strcmp(result
+ treelen
,
309 symlink_tests_inputs
[i
].expected_result
) == 0, "%s", name
);
314 /* Test invalid cases */
315 for (i
= 0; i
< num_invalid_tests
; i
++) {
316 const char *test_input
= invalid_tests_inputs
[i
];
318 sprintf(name
, "invalid test case: %s", test_input
?
319 test_input
: "NULL");
321 result
= utils_expand_path(test_input
);
322 if (result
!= NULL
) {
325 ok(result
== NULL
, "%s", name
);
329 int main(int argc
, char **argv
)
331 if (prepare_symlink_tree() != 0) {
335 if (prepare_valid_results() != 0) {
339 plan_tests(num_valid_tests
+ num_invalid_tests
+ num_symlink_tests
);
341 diag("utils_expand_path tests");
343 test_utils_expand_path();
345 free_valid_results();
348 return exit_status();
351 free_valid_results();