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