Build fix: missing stdio.h include in signal-helper.hpp
[lttng-tools.git] / tests / unit / test_utils_expand_path.cpp
CommitLineData
cc7f9e36 1/*
9d16b343 2 * Copyright (C) 2013 Raphaël Beamonte <raphael.beamonte@gmail.com>
cc7f9e36 3 *
9d16b343 4 * SPDX-License-Identifier: GPL-2.0-only
cc7f9e36 5 *
cc7f9e36
RB
6 */
7
cc7f9e36
RB
8#include <string.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <limits.h>
12
02bf969d
RB
13#include <sys/stat.h>
14#include <sys/types.h>
15
c9e313bc
SM
16#include <common/utils.hpp>
17#include <common/path.hpp>
18#include <common/common.hpp>
8098bf0a 19
e30c79d2
MJ
20#include <tap/tap.h>
21
ad7c9c18 22/* For error.h */
cc7f9e36
RB
23int lttng_opt_quiet = 1;
24int lttng_opt_verbose = 3;
c7e35b03 25int lttng_opt_mi;
cc7f9e36 26
f1494934 27namespace {
cc7f9e36 28struct valid_test_input {
b53d4e59
SM
29 const char *input;
30 const char *relative_part;
31 const char *absolute_part;
cc7f9e36
RB
32};
33
02bf969d 34struct tree_symlink {
b53d4e59
SM
35 const char *orig;
36 const char *dest;
02bf969d
RB
37};
38
39struct symlink_test_input {
b53d4e59
SM
40 const char *input;
41 const char *expected_result;
02bf969d
RB
42};
43
cc7f9e36 44/* Valid test cases */
f1494934 45struct valid_test_input valid_tests_inputs[] = {
cc7f9e36 46 { "/a/b/c/d/e", "", "/a/b/c/d/e" },
4b223a67 47 { "/a//b//c/d/e", "", "/a/b/c/d/e" },
cc7f9e36
RB
48 { "./a/b/c/d/e", ".", "/a/b/c/d/e" },
49 { "../a/b/c/d/../e", "..", "/a/b/c/e" },
50 { ".././a/b/c/d/./e", "..", "/a/b/c/d/e" },
51 { "../../a/b/c/d/e", "../..", "/a/b/c/d/e" },
52 { "./a/b/../c/d/../e", ".", "/a/c/e" },
53 { "../a/b/../../c/./d/./e", "..", "/c/d/e" },
54 { "../../a/b/../c/d/../../e", "../..", "/a/e" },
55 { "./a/b/c/d/../../../../e", ".", "/e" },
56 { ".././a/b/c/d/./e", "..", "/a/b/c/d/e" },
57 { "a/", ".", "/a/" },
58 { "a", ".", "/a" },
59 { "../../", "../..", "/" },
60 { "../..", "../..", "" },
61 { "../", "..", "/" },
62 { "..", "..", "" },
63 { "./", ".", "/" },
64 { ".", ".", "" },
ab5ff479
RB
65 { "/../a/b/c/d/e", "", "/a/b/c/d/e" },
66 { "/a/b/c/d/../../../../../e", "", "/e" },
9a506343
RB
67 { "/..", "", "/" },
68 { "/a/..", "", "/" },
cc7f9e36
RB
69};
70char **valid_tests_expected_results;
f1494934 71const int num_valid_tests =
cc7f9e36
RB
72 sizeof(valid_tests_inputs) / sizeof(valid_tests_inputs[0]);
73
02bf969d
RB
74/* Symlinks test cases */
75char tree_origin[] = "/tmp/test_utils_expand_path.XXXXXX";
76
f1494934 77const char * const tree_dirs[] = {
02bf969d
RB
78 "a",
79 "a/b",
80 "a/b/c",
81 "a/e",
82};
f1494934 83const int num_tree_dirs =
02bf969d
RB
84 sizeof(tree_dirs) / sizeof(tree_dirs[0]);
85
f1494934 86struct tree_symlink tree_symlinks[] = {
02bf969d
RB
87 { "a/d", "b/c/" },
88 { "a/g", "d/" },
89 { "a/b/f", "../e/" },
90 { "a/b/h", "../g/" },
91 { "a/b/k", "c/g/" },
92 { "a/b/c/g", "../../../" },
93};
f1494934 94const int num_tree_symlinks =
02bf969d
RB
95 sizeof(tree_symlinks) / sizeof(tree_symlinks[0]);
96
97static struct symlink_test_input symlink_tests_inputs[] = {
98 { "a/g/../l/.", "a/b/l" },
99 { "a/g/../l/./", "a/b/l/" },
100 { "a/g/../l/..", "a/b" },
101 { "a/g/../l/../", "a/b/" },
102 { "a/b/h/g/", "" },
103};
f1494934 104const int num_symlink_tests =
02bf969d
RB
105 sizeof(symlink_tests_inputs) / sizeof(symlink_tests_inputs[0]);
106
cc7f9e36 107/* Invalid test cases */
f1494934 108char *invalid_tests_inputs[] = {
cc7f9e36 109 NULL,
cc7f9e36 110};
f1494934 111const int num_invalid_tests =
cc7f9e36 112 sizeof(invalid_tests_inputs) / sizeof(invalid_tests_inputs[0]);
f1494934 113} /* namespace */
cc7f9e36 114
b35d936e
JG
115#define PRINT_ERR(fmt, args...) \
116 fprintf(stderr, "test_utils_expand_path: error: " fmt "\n", ## args)
02bf969d 117
8dfbc0b4 118static int prepare_valid_results(void)
cc7f9e36
RB
119{
120 int i;
8098bf0a
MD
121 char *relative, *cur_path = NULL, *prev_path = NULL,
122 *pprev_path = NULL, *empty = NULL;
123 int ret = 0;
cc7f9e36
RB
124
125 /* Prepare the relative paths */
126 cur_path = realpath(".", NULL);
127 prev_path = realpath("..", NULL);
128 pprev_path = realpath("../..", NULL);
129 empty = strdup("");
8098bf0a 130 if (!cur_path || !prev_path || !pprev_path || !empty) {
b35d936e 131 PRINT_ERR("strdup out of memory");
8098bf0a
MD
132 ret = -1;
133 goto end;
134 }
cc7f9e36
RB
135
136 /* allocate memory for the expected results */
64803277 137 valid_tests_expected_results = calloc<char *>(num_valid_tests);
8098bf0a 138 if (!valid_tests_expected_results) {
b35d936e 139 PRINT_ERR("out of memory");
8098bf0a
MD
140 ret = -1;
141 goto end;
142 }
cc7f9e36 143 for (i = 0; i < num_valid_tests; i++) {
64803277 144 valid_tests_expected_results[i] = calloc<char>(PATH_MAX);
cc7f9e36 145 if (valid_tests_expected_results[i] == NULL) {
b35d936e 146 PRINT_ERR("malloc expected results");
8098bf0a
MD
147 ret = -1;
148 goto end;
cc7f9e36
RB
149 }
150
151 if (strcmp(valid_tests_inputs[i].relative_part, ".") == 0) {
152 relative = cur_path;
153 } else if (strcmp(valid_tests_inputs[i].relative_part, "..") == 0) {
154 relative = prev_path;
155 } else if (strcmp(valid_tests_inputs[i].relative_part, "../..") == 0) {
156 relative = pprev_path;
157 } else {
158 relative = empty;
159 }
160
161 snprintf(valid_tests_expected_results[i], PATH_MAX,
162 "%s%s", relative, valid_tests_inputs[i].absolute_part);
163 }
164
8098bf0a 165end:
cc7f9e36
RB
166 free(cur_path);
167 free(prev_path);
168 free(pprev_path);
169 free(empty);
170
8098bf0a 171 return ret;
cc7f9e36
RB
172}
173
8dfbc0b4 174static int free_valid_results(void)
cc7f9e36
RB
175{
176 int i;
177
178 for (i = 0; i < num_valid_tests; i++) {
179 free(valid_tests_expected_results[i]);
180 }
181
182 free(valid_tests_expected_results);
183
184 return 0;
185}
186
8dfbc0b4 187static int prepare_symlink_tree(void)
02bf969d
RB
188{
189 int i;
b35d936e 190 char tmppath[PATH_MAX] = {};
02bf969d
RB
191
192 /* Create the temporary directory */
193 if (mkdtemp(tree_origin) == NULL) {
b35d936e 194 PRINT_ERR("failed to mkdtemp");
02bf969d
RB
195 goto error;
196 }
197
198 /* Create the directories of the test tree */
199 for (i = 0; i < num_tree_dirs; i++) {
b35d936e
JG
200 snprintf(tmppath, sizeof(tmppath), "%s/%s", tree_origin,
201 tree_dirs[i]);
02bf969d
RB
202
203 if (mkdir(tmppath, 0755) != 0) {
b35d936e 204 PRINT_ERR("mkdir failed with path \"%s\"", tmppath);
02bf969d
RB
205 goto error;
206 }
207 }
208
209 /* Create the symlinks of the test tree */
210 for (i = 0; i < num_tree_symlinks; i++) {
b35d936e 211 snprintf(tmppath, sizeof(tmppath), "%s/%s",
02bf969d
RB
212 tree_origin, tree_symlinks[i].orig);
213
214 if (symlink(tree_symlinks[i].dest, tmppath) != 0) {
b35d936e
JG
215 PRINT_ERR("failed to symlink \"%s\" to \"%s\"", tmppath,
216 tree_symlinks[i].dest);
02bf969d
RB
217 goto error;
218 }
219 }
220
221 return 0;
222
223error:
224 return 1;
225}
226
8dfbc0b4 227static int free_symlink_tree(void)
02bf969d
RB
228{
229 int i;
230 char tmppath[PATH_MAX];
231
232 /* Remove the symlinks from the test tree */
233 for (i = num_tree_symlinks - 1; i > -1; i--) {
234 snprintf(tmppath, PATH_MAX, "%s/%s",
235 tree_origin, tree_symlinks[i].orig);
236
237 if (unlink(tmppath) != 0) {
b35d936e 238 PRINT_ERR("failed to unlink \"%s\"", tmppath);
02bf969d
RB
239 goto error;
240 }
241 }
242
243 /* Remove the directories from the test tree */
244 for (i = num_tree_dirs - 1; i > -1; i--) {
245 snprintf(tmppath, PATH_MAX, "%s/%s", tree_origin, tree_dirs[i]);
246
247 if (rmdir(tmppath) != 0) {
b35d936e 248 PRINT_ERR("failed to rmdir \"%s\"", tmppath);
02bf969d
RB
249 goto error;
250 }
251 }
252
253 /* Remove the temporary directory */
254 if (rmdir(tree_origin) != 0) {
b35d936e 255 PRINT_ERR("failed to rmdir \"%s\"", tree_origin);
02bf969d
RB
256 goto error;
257 }
258
259 return 0;
260
261error:
262 return 1;
263}
264
cc7f9e36
RB
265static void test_utils_expand_path(void)
266{
267 char *result;
f66e964a
JR
268 char name[100], tmppath[PATH_MAX], real_tree_origin[PATH_MAX];
269 int i, treelen;
cc7f9e36
RB
270
271 /* Test valid cases */
272 for (i = 0; i < num_valid_tests; i++) {
cc7f9e36
RB
273 sprintf(name, "valid test case: %s", valid_tests_inputs[i].input);
274
275 result = utils_expand_path(valid_tests_inputs[i].input);
ba526563 276 ok(result != NULL &&
9f4a25d3 277 strcmp(result, valid_tests_expected_results[i]) == 0, "%s", name);
cc7f9e36
RB
278
279 free(result);
280 }
281
f66e964a
JR
282 /*
283 * Get the realpath for the tree_origin since it can itself be a
284 * symlink.
285 */
286 result = realpath(tree_origin, real_tree_origin);
287 if (!result) {
288 fail("realpath failed.");
289 return;
290 }
291
02bf969d 292 /* Test symlink tree cases */
f66e964a 293 treelen = strlen(real_tree_origin) + 1;
02bf969d 294 for (i = 0; i < num_symlink_tests; i++) {
b35d936e
JG
295 int ret;
296
02bf969d
RB
297 sprintf(name, "symlink tree test case: [tmppath/]%s",
298 symlink_tests_inputs[i].input);
299
b35d936e
JG
300 ret = snprintf(tmppath, PATH_MAX, "%s/%s",
301 real_tree_origin,
302 symlink_tests_inputs[i].input);
303 if (ret == -1 || ret >= PATH_MAX) {
304 PRINT_ERR("truncation occurred while concatenating paths \"%s\" and \"%s\"",
305 real_tree_origin,
306 symlink_tests_inputs[i].input);
9f4a25d3 307 fail("%s", name);
b35d936e
JG
308 continue;
309 }
02bf969d
RB
310 result = utils_expand_path(tmppath);
311 ok(result != NULL && strcmp(result + treelen,
9f4a25d3 312 symlink_tests_inputs[i].expected_result) == 0, "%s", name);
02bf969d
RB
313
314 free(result);
315 }
316
cc7f9e36
RB
317 /* Test invalid cases */
318 for (i = 0; i < num_invalid_tests; i++) {
8082d471 319 const char *test_input = invalid_tests_inputs[i];
cc7f9e36 320
8082d471
JG
321 sprintf(name, "invalid test case: %s", test_input ?
322 test_input : "NULL");
323
324 result = utils_expand_path(test_input);
cc7f9e36
RB
325 if (result != NULL) {
326 free(result);
327 }
9f4a25d3 328 ok(result == NULL, "%s", name);
cc7f9e36
RB
329 }
330}
331
f46376a1 332int main(void)
cc7f9e36 333{
02bf969d
RB
334 if (prepare_symlink_tree() != 0) {
335 goto error_mkdir;
336 }
337
cc7f9e36 338 if (prepare_valid_results() != 0) {
02bf969d 339 goto error_malloc;
cc7f9e36
RB
340 }
341
02bf969d 342 plan_tests(num_valid_tests + num_invalid_tests + num_symlink_tests);
cc7f9e36
RB
343
344 diag("utils_expand_path tests");
345
346 test_utils_expand_path();
347
348 free_valid_results();
02bf969d
RB
349 free_symlink_tree();
350
cc7f9e36 351 return exit_status();
02bf969d
RB
352
353error_malloc:
354 free_valid_results();
355
356error_mkdir:
357 free_symlink_tree();
358
359 return 1;
cc7f9e36 360}
This page took 0.065796 seconds and 4 git commands to generate.