]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-path-util.c
util: rework rm_rf() logic
[thirdparty/systemd.git] / src / test / test-path-util.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2013 Zbigniew Jędrzejewski-Szmek
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <stdio.h>
23 #include <unistd.h>
24
25 #include "path-util.h"
26 #include "util.h"
27 #include "macro.h"
28 #include "strv.h"
29 #include "rm-rf.h"
30
31 #define test_path_compare(a, b, result) { \
32 assert_se(path_compare(a, b) == result); \
33 assert_se(path_compare(b, a) == -result); \
34 assert_se(path_equal(a, b) == !result); \
35 assert_se(path_equal(b, a) == !result); \
36 }
37
38 static void test_path(void) {
39 test_path_compare("/goo", "/goo", 0);
40 test_path_compare("/goo", "/goo", 0);
41 test_path_compare("//goo", "/goo", 0);
42 test_path_compare("//goo/////", "/goo", 0);
43 test_path_compare("goo/////", "goo", 0);
44
45 test_path_compare("/goo/boo", "/goo//boo", 0);
46 test_path_compare("//goo/boo", "/goo/boo//", 0);
47
48 test_path_compare("/", "///", 0);
49
50 test_path_compare("/x", "x/", 1);
51 test_path_compare("x/", "/", -1);
52
53 test_path_compare("/x/./y", "x/y", 1);
54 test_path_compare("x/.y", "x/y", -1);
55
56 test_path_compare("foo", "/foo", -1);
57 test_path_compare("/foo", "/foo/bar", -1);
58 test_path_compare("/foo/aaa", "/foo/b", -1);
59 test_path_compare("/foo/aaa", "/foo/b/a", -1);
60 test_path_compare("/foo/a", "/foo/aaa", -1);
61 test_path_compare("/foo/a/b", "/foo/aaa", -1);
62
63 assert_se(path_is_absolute("/"));
64 assert_se(!path_is_absolute("./"));
65
66 assert_se(is_path("/dir"));
67 assert_se(is_path("a/b"));
68 assert_se(!is_path("."));
69
70 assert_se(streq(basename("./aa/bb/../file.da."), "file.da."));
71 assert_se(streq(basename("/aa///.file"), ".file"));
72 assert_se(streq(basename("/aa///file..."), "file..."));
73 assert_se(streq(basename("file.../"), ""));
74
75 #define test_parent(x, y) { \
76 _cleanup_free_ char *z = NULL; \
77 int r = path_get_parent(x, &z); \
78 printf("expected: %s\n", y ? y : "error"); \
79 printf("actual: %s\n", r<0 ? "error" : z); \
80 assert_se((y==NULL) ^ (r==0)); \
81 assert_se(y==NULL || path_equal(z, y)); \
82 }
83
84 test_parent("./aa/bb/../file.da.", "./aa/bb/..");
85 test_parent("/aa///.file", "/aa///");
86 test_parent("/aa///file...", "/aa///");
87 test_parent("file.../", NULL);
88
89 assert_se(path_is_mount_point("/", true));
90 assert_se(path_is_mount_point("/", false));
91
92 {
93 char p1[] = "aaa/bbb////ccc";
94 char p2[] = "//aaa/.////ccc";
95 char p3[] = "/./";
96
97 assert_se(path_equal(path_kill_slashes(p1), "aaa/bbb/ccc"));
98 assert_se(path_equal(path_kill_slashes(p2), "/aaa/./ccc"));
99 assert_se(path_equal(path_kill_slashes(p3), "/./"));
100 }
101 }
102
103 static void test_find_binary(const char *self, bool local) {
104 char *p;
105
106 assert_se(find_binary("/bin/sh", local, &p) == 0);
107 puts(p);
108 assert_se(streq(p, "/bin/sh"));
109 free(p);
110
111 assert_se(find_binary(self, local, &p) == 0);
112 puts(p);
113 assert_se(endswith(p, "/test-path-util"));
114 assert_se(path_is_absolute(p));
115 free(p);
116
117 assert_se(find_binary("sh", local, &p) == 0);
118 puts(p);
119 assert_se(endswith(p, "/sh"));
120 assert_se(path_is_absolute(p));
121 free(p);
122
123 assert_se(find_binary("xxxx-xxxx", local, &p) == -ENOENT);
124
125 assert_se(find_binary("/some/dir/xxxx-xxxx", local, &p) ==
126 (local ? -ENOENT : 0));
127 if (!local)
128 free(p);
129 }
130
131 static void test_prefixes(void) {
132 static const char* values[] = { "/a/b/c/d", "/a/b/c", "/a/b", "/a", "", NULL};
133 unsigned i;
134 char s[PATH_MAX];
135 bool b;
136
137 i = 0;
138 PATH_FOREACH_PREFIX_MORE(s, "/a/b/c/d") {
139 log_error("---%s---", s);
140 assert_se(streq(s, values[i++]));
141 }
142 assert_se(values[i] == NULL);
143
144 i = 1;
145 PATH_FOREACH_PREFIX(s, "/a/b/c/d") {
146 log_error("---%s---", s);
147 assert_se(streq(s, values[i++]));
148 }
149 assert_se(values[i] == NULL);
150
151 i = 0;
152 PATH_FOREACH_PREFIX_MORE(s, "////a////b////c///d///////")
153 assert_se(streq(s, values[i++]));
154 assert_se(values[i] == NULL);
155
156 i = 1;
157 PATH_FOREACH_PREFIX(s, "////a////b////c///d///////")
158 assert_se(streq(s, values[i++]));
159 assert_se(values[i] == NULL);
160
161 PATH_FOREACH_PREFIX(s, "////")
162 assert_not_reached("Wut?");
163
164 b = false;
165 PATH_FOREACH_PREFIX_MORE(s, "////") {
166 assert_se(!b);
167 assert_se(streq(s, ""));
168 b = true;
169 }
170 assert_se(b);
171
172 PATH_FOREACH_PREFIX(s, "")
173 assert_not_reached("wut?");
174
175 b = false;
176 PATH_FOREACH_PREFIX_MORE(s, "") {
177 assert_se(!b);
178 assert_se(streq(s, ""));
179 b = true;
180 }
181 }
182
183 static void test_path_join(void) {
184
185 #define test_join(root, path, rest, expected) { \
186 _cleanup_free_ char *z = NULL; \
187 z = path_join(root, path, rest); \
188 assert_se(streq(z, expected)); \
189 }
190
191 test_join("/root", "/a/b", "/c", "/root/a/b/c");
192 test_join("/root", "a/b", "c", "/root/a/b/c");
193 test_join("/root", "/a/b", "c", "/root/a/b/c");
194 test_join("/root", "/", "c", "/root/c");
195 test_join("/root", "/", NULL, "/root/");
196
197 test_join(NULL, "/a/b", "/c", "/a/b/c");
198 test_join(NULL, "a/b", "c", "a/b/c");
199 test_join(NULL, "/a/b", "c", "/a/b/c");
200 test_join(NULL, "/", "c", "/c");
201 test_join(NULL, "/", NULL, "/");
202 }
203
204 static void test_fsck_exists(void) {
205 /* Ensure we use a sane default for PATH. */
206 unsetenv("PATH");
207
208 /* fsck.minix is provided by util-linux and will probably exist. */
209 assert_se(fsck_exists("minix") == 0);
210
211 assert_se(fsck_exists("AbCdE") == -ENOENT);
212 }
213
214 static void test_make_relative(void) {
215 char *result;
216
217 assert_se(path_make_relative("some/relative/path", "/some/path", &result) < 0);
218 assert_se(path_make_relative("/some/path", "some/relative/path", &result) < 0);
219
220 #define test(from_dir, to_path, expected) { \
221 _cleanup_free_ char *z = NULL; \
222 path_make_relative(from_dir, to_path, &z); \
223 assert_se(streq(z, expected)); \
224 }
225
226 test("/", "/", ".");
227 test("/", "/some/path", "some/path");
228 test("/some/path", "/some/path", ".");
229 test("/some/path", "/some/path/in/subdir", "in/subdir");
230 test("/some/path", "/", "../..");
231 test("/some/path", "/some/other/path", "../other/path");
232 test("//extra/////slashes///won't////fool///anybody//", "////extra///slashes////are/just///fine///", "../../../are/just/fine");
233 }
234
235 static void test_strv_resolve(void) {
236 char tmp_dir[] = "/tmp/test-path-util-XXXXXX";
237 _cleanup_strv_free_ char **search_dirs = NULL;
238 _cleanup_strv_free_ char **absolute_dirs = NULL;
239 char **d;
240
241 assert_se(mkdtemp(tmp_dir) != NULL);
242
243 search_dirs = strv_new("/dir1", "/dir2", "/dir3", NULL);
244 assert_se(search_dirs);
245 STRV_FOREACH(d, search_dirs) {
246 char *p = strappend(tmp_dir, *d);
247 assert_se(p);
248 assert_se(strv_push(&absolute_dirs, p) == 0);
249 }
250
251 assert_se(mkdir(absolute_dirs[0], 0700) == 0);
252 assert_se(mkdir(absolute_dirs[1], 0700) == 0);
253 assert_se(symlink("dir2", absolute_dirs[2]) == 0);
254
255 path_strv_resolve(search_dirs, tmp_dir);
256 assert_se(streq(search_dirs[0], "/dir1"));
257 assert_se(streq(search_dirs[1], "/dir2"));
258 assert_se(streq(search_dirs[2], "/dir2"));
259
260 assert_se(rm_rf(tmp_dir, REMOVE_ROOT|REMOVE_PHYSICAL) == 0);
261 }
262
263 static void test_path_startswith(void) {
264 assert_se(path_startswith("/foo/bar/barfoo/", "/foo"));
265 assert_se(path_startswith("/foo/bar/barfoo/", "/foo/"));
266 assert_se(path_startswith("/foo/bar/barfoo/", "/"));
267 assert_se(path_startswith("/foo/bar/barfoo/", "////"));
268 assert_se(path_startswith("/foo/bar/barfoo/", "/foo//bar/////barfoo///"));
269 assert_se(path_startswith("/foo/bar/barfoo/", "/foo/bar/barfoo////"));
270 assert_se(path_startswith("/foo/bar/barfoo/", "/foo/bar///barfoo/"));
271 assert_se(path_startswith("/foo/bar/barfoo/", "/foo////bar/barfoo/"));
272 assert_se(path_startswith("/foo/bar/barfoo/", "////foo/bar/barfoo/"));
273 assert_se(path_startswith("/foo/bar/barfoo/", "/foo/bar/barfoo"));
274
275 assert_se(!path_startswith("/foo/bar/barfoo/", "/foo/bar/barfooa/"));
276 assert_se(!path_startswith("/foo/bar/barfoo/", "/foo/bar/barfooa"));
277 assert_se(!path_startswith("/foo/bar/barfoo/", ""));
278 assert_se(!path_startswith("/foo/bar/barfoo/", "/bar/foo"));
279 assert_se(!path_startswith("/foo/bar/barfoo/", "/f/b/b/"));
280 }
281
282 int main(int argc, char **argv) {
283 test_path();
284 test_find_binary(argv[0], true);
285 test_find_binary(argv[0], false);
286 test_prefixes();
287 test_path_join();
288 test_fsck_exists();
289 test_make_relative();
290 test_strv_resolve();
291 test_path_startswith();
292
293 return 0;
294 }