]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/test/test-path-util.c
path-util: make use of "mnt_id" field exported in /proc/self/fdinfo/<fd> to test...
[thirdparty/systemd.git] / src / test / test-path-util.c
CommitLineData
76877b46
ZJS
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
a696dbef 22#include <stdio.h>
3e8a78c8 23#include <unistd.h>
a696dbef 24
76877b46
ZJS
25#include "path-util.h"
26#include "util.h"
27#include "macro.h"
3e8a78c8 28#include "strv.h"
c6878637 29#include "rm-rf.h"
76877b46 30
2230852b
MS
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 }
76877b46
ZJS
37
38static void test_path(void) {
3f72b427
LP
39 _cleanup_close_ int fd = -1;
40
2230852b
MS
41 test_path_compare("/goo", "/goo", 0);
42 test_path_compare("/goo", "/goo", 0);
43 test_path_compare("//goo", "/goo", 0);
44 test_path_compare("//goo/////", "/goo", 0);
45 test_path_compare("goo/////", "goo", 0);
76877b46 46
2230852b
MS
47 test_path_compare("/goo/boo", "/goo//boo", 0);
48 test_path_compare("//goo/boo", "/goo/boo//", 0);
76877b46 49
2230852b 50 test_path_compare("/", "///", 0);
76877b46 51
2230852b
MS
52 test_path_compare("/x", "x/", 1);
53 test_path_compare("x/", "/", -1);
76877b46 54
2230852b
MS
55 test_path_compare("/x/./y", "x/y", 1);
56 test_path_compare("x/.y", "x/y", -1);
57
58 test_path_compare("foo", "/foo", -1);
59 test_path_compare("/foo", "/foo/bar", -1);
60 test_path_compare("/foo/aaa", "/foo/b", -1);
61 test_path_compare("/foo/aaa", "/foo/b/a", -1);
62 test_path_compare("/foo/a", "/foo/aaa", -1);
63 test_path_compare("/foo/a/b", "/foo/aaa", -1);
76877b46
ZJS
64
65 assert_se(path_is_absolute("/"));
66 assert_se(!path_is_absolute("./"));
67
68 assert_se(is_path("/dir"));
69 assert_se(is_path("a/b"));
70 assert_se(!is_path("."));
71
2b6bf07d
ZJS
72 assert_se(streq(basename("./aa/bb/../file.da."), "file.da."));
73 assert_se(streq(basename("/aa///.file"), ".file"));
74 assert_se(streq(basename("/aa///file..."), "file..."));
75 assert_se(streq(basename("file.../"), ""));
76877b46 76
a696dbef 77#define test_parent(x, y) { \
c8b32e11 78 _cleanup_free_ char *z = NULL; \
a696dbef
ZJS
79 int r = path_get_parent(x, &z); \
80 printf("expected: %s\n", y ? y : "error"); \
81 printf("actual: %s\n", r<0 ? "error" : z); \
82 assert_se((y==NULL) ^ (r==0)); \
83 assert_se(y==NULL || path_equal(z, y)); \
76877b46
ZJS
84 }
85
86 test_parent("./aa/bb/../file.da.", "./aa/bb/..");
87 test_parent("/aa///.file", "/aa///");
88 test_parent("/aa///file...", "/aa///");
a696dbef 89 test_parent("file.../", NULL);
76877b46 90
da00518b
LP
91 assert_se(path_is_mount_point("/", true) > 0);
92 assert_se(path_is_mount_point("/", false) > 0);
93
3f72b427
LP
94 fd = open("/", O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOCTTY);
95 assert_se(fd >= 0);
96 assert_se(fd_is_mount_point(fd) > 0);
97
da00518b
LP
98 assert_se(path_is_mount_point("/proc", true) > 0);
99 assert_se(path_is_mount_point("/proc", false) > 0);
100
3f72b427
LP
101 assert_se(path_is_mount_point("/proc/1", true) == 0);
102 assert_se(path_is_mount_point("/proc/1", false) == 0);
103
da00518b
LP
104 assert_se(path_is_mount_point("/sys", true) > 0);
105 assert_se(path_is_mount_point("/sys", false) > 0);
76877b46
ZJS
106
107 {
108 char p1[] = "aaa/bbb////ccc";
109 char p2[] = "//aaa/.////ccc";
110 char p3[] = "/./";
111
8d95631e
FB
112 assert_se(path_equal(path_kill_slashes(p1), "aaa/bbb/ccc"));
113 assert_se(path_equal(path_kill_slashes(p2), "/aaa/./ccc"));
114 assert_se(path_equal(path_kill_slashes(p3), "/./"));
76877b46
ZJS
115 }
116}
117
b63bd109 118static void test_find_binary(const char *self, bool local) {
c9d954b2
ZJS
119 char *p;
120
b63bd109 121 assert_se(find_binary("/bin/sh", local, &p) == 0);
c9d954b2 122 puts(p);
8d95631e 123 assert_se(streq(p, "/bin/sh"));
c9d954b2
ZJS
124 free(p);
125
b63bd109 126 assert_se(find_binary(self, local, &p) == 0);
c9d954b2 127 puts(p);
8d95631e
FB
128 assert_se(endswith(p, "/test-path-util"));
129 assert_se(path_is_absolute(p));
c9d954b2
ZJS
130 free(p);
131
b63bd109 132 assert_se(find_binary("sh", local, &p) == 0);
c9d954b2 133 puts(p);
8d95631e
FB
134 assert_se(endswith(p, "/sh"));
135 assert_se(path_is_absolute(p));
c9d954b2
ZJS
136 free(p);
137
b63bd109 138 assert_se(find_binary("xxxx-xxxx", local, &p) == -ENOENT);
b972115c 139
b63bd109
ZJS
140 assert_se(find_binary("/some/dir/xxxx-xxxx", local, &p) ==
141 (local ? -ENOENT : 0));
f08c4c08
TA
142 if (!local)
143 free(p);
c9d954b2
ZJS
144}
145
fecffe5d 146static void test_prefixes(void) {
e203f7c3
LP
147 static const char* values[] = { "/a/b/c/d", "/a/b/c", "/a/b", "/a", "", NULL};
148 unsigned i;
fecffe5d 149 char s[PATH_MAX];
e203f7c3 150 bool b;
fecffe5d 151
e203f7c3
LP
152 i = 0;
153 PATH_FOREACH_PREFIX_MORE(s, "/a/b/c/d") {
fecffe5d
LP
154 log_error("---%s---", s);
155 assert_se(streq(s, values[i++]));
156 }
e203f7c3 157 assert_se(values[i] == NULL);
fecffe5d 158
e203f7c3
LP
159 i = 1;
160 PATH_FOREACH_PREFIX(s, "/a/b/c/d") {
161 log_error("---%s---", s);
162 assert_se(streq(s, values[i++]));
163 }
fecffe5d
LP
164 assert_se(values[i] == NULL);
165
166 i = 0;
e203f7c3 167 PATH_FOREACH_PREFIX_MORE(s, "////a////b////c///d///////")
fecffe5d 168 assert_se(streq(s, values[i++]));
e203f7c3 169 assert_se(values[i] == NULL);
fecffe5d 170
e203f7c3
LP
171 i = 1;
172 PATH_FOREACH_PREFIX(s, "////a////b////c///d///////")
173 assert_se(streq(s, values[i++]));
fecffe5d
LP
174 assert_se(values[i] == NULL);
175
176 PATH_FOREACH_PREFIX(s, "////")
e203f7c3
LP
177 assert_not_reached("Wut?");
178
179 b = false;
180 PATH_FOREACH_PREFIX_MORE(s, "////") {
181 assert_se(!b);
fecffe5d 182 assert_se(streq(s, ""));
e203f7c3
LP
183 b = true;
184 }
185 assert_se(b);
fecffe5d
LP
186
187 PATH_FOREACH_PREFIX(s, "")
188 assert_not_reached("wut?");
189
e203f7c3
LP
190 b = false;
191 PATH_FOREACH_PREFIX_MORE(s, "") {
8d95631e
FB
192 assert_se(!b);
193 assert_se(streq(s, ""));
e203f7c3
LP
194 b = true;
195 }
fecffe5d
LP
196}
197
0c6ea3a4 198static void test_path_join(void) {
59ae3a95
TA
199
200#define test_join(root, path, rest, expected) { \
201 _cleanup_free_ char *z = NULL; \
202 z = path_join(root, path, rest); \
203 assert_se(streq(z, expected)); \
204 }
205
206 test_join("/root", "/a/b", "/c", "/root/a/b/c");
207 test_join("/root", "a/b", "c", "/root/a/b/c");
208 test_join("/root", "/a/b", "c", "/root/a/b/c");
bc854dc7 209 test_join("/root", "/", "c", "/root/c");
59ae3a95
TA
210 test_join("/root", "/", NULL, "/root/");
211
212 test_join(NULL, "/a/b", "/c", "/a/b/c");
213 test_join(NULL, "a/b", "c", "a/b/c");
214 test_join(NULL, "/a/b", "c", "/a/b/c");
bc854dc7 215 test_join(NULL, "/", "c", "/c");
59ae3a95 216 test_join(NULL, "/", NULL, "/");
0c6ea3a4
ZJS
217}
218
eb66db55
MG
219static void test_fsck_exists(void) {
220 /* Ensure we use a sane default for PATH. */
221 unsetenv("PATH");
222
223 /* fsck.minix is provided by util-linux and will probably exist. */
224 assert_se(fsck_exists("minix") == 0);
225
226 assert_se(fsck_exists("AbCdE") == -ENOENT);
227}
228
6b56a651
TK
229static void test_make_relative(void) {
230 char *result;
231
232 assert_se(path_make_relative("some/relative/path", "/some/path", &result) < 0);
233 assert_se(path_make_relative("/some/path", "some/relative/path", &result) < 0);
234
59ae3a95
TA
235#define test(from_dir, to_path, expected) { \
236 _cleanup_free_ char *z = NULL; \
237 path_make_relative(from_dir, to_path, &z); \
238 assert_se(streq(z, expected)); \
6b56a651
TK
239 }
240
241 test("/", "/", ".");
242 test("/", "/some/path", "some/path");
243 test("/some/path", "/some/path", ".");
244 test("/some/path", "/some/path/in/subdir", "in/subdir");
245 test("/some/path", "/", "../..");
246 test("/some/path", "/some/other/path", "../other/path");
247 test("//extra/////slashes///won't////fool///anybody//", "////extra///slashes////are/just///fine///", "../../../are/just/fine");
248}
249
3e8a78c8
MM
250static void test_strv_resolve(void) {
251 char tmp_dir[] = "/tmp/test-path-util-XXXXXX";
252 _cleanup_strv_free_ char **search_dirs = NULL;
253 _cleanup_strv_free_ char **absolute_dirs = NULL;
254 char **d;
255
256 assert_se(mkdtemp(tmp_dir) != NULL);
257
258 search_dirs = strv_new("/dir1", "/dir2", "/dir3", NULL);
259 assert_se(search_dirs);
260 STRV_FOREACH(d, search_dirs) {
261 char *p = strappend(tmp_dir, *d);
262 assert_se(p);
263 assert_se(strv_push(&absolute_dirs, p) == 0);
264 }
265
266 assert_se(mkdir(absolute_dirs[0], 0700) == 0);
267 assert_se(mkdir(absolute_dirs[1], 0700) == 0);
268 assert_se(symlink("dir2", absolute_dirs[2]) == 0);
269
270 path_strv_resolve(search_dirs, tmp_dir);
271 assert_se(streq(search_dirs[0], "/dir1"));
272 assert_se(streq(search_dirs[1], "/dir2"));
273 assert_se(streq(search_dirs[2], "/dir2"));
274
c6878637 275 assert_se(rm_rf(tmp_dir, REMOVE_ROOT|REMOVE_PHYSICAL) == 0);
3e8a78c8
MM
276}
277
5895b62f
RC
278static void test_path_startswith(void) {
279 assert_se(path_startswith("/foo/bar/barfoo/", "/foo"));
280 assert_se(path_startswith("/foo/bar/barfoo/", "/foo/"));
281 assert_se(path_startswith("/foo/bar/barfoo/", "/"));
282 assert_se(path_startswith("/foo/bar/barfoo/", "////"));
283 assert_se(path_startswith("/foo/bar/barfoo/", "/foo//bar/////barfoo///"));
284 assert_se(path_startswith("/foo/bar/barfoo/", "/foo/bar/barfoo////"));
285 assert_se(path_startswith("/foo/bar/barfoo/", "/foo/bar///barfoo/"));
286 assert_se(path_startswith("/foo/bar/barfoo/", "/foo////bar/barfoo/"));
287 assert_se(path_startswith("/foo/bar/barfoo/", "////foo/bar/barfoo/"));
288 assert_se(path_startswith("/foo/bar/barfoo/", "/foo/bar/barfoo"));
289
290 assert_se(!path_startswith("/foo/bar/barfoo/", "/foo/bar/barfooa/"));
291 assert_se(!path_startswith("/foo/bar/barfoo/", "/foo/bar/barfooa"));
292 assert_se(!path_startswith("/foo/bar/barfoo/", ""));
293 assert_se(!path_startswith("/foo/bar/barfoo/", "/bar/foo"));
294 assert_se(!path_startswith("/foo/bar/barfoo/", "/f/b/b/"));
295}
296
7f076504 297int main(int argc, char **argv) {
76877b46 298 test_path();
b63bd109
ZJS
299 test_find_binary(argv[0], true);
300 test_find_binary(argv[0], false);
fecffe5d 301 test_prefixes();
0c6ea3a4 302 test_path_join();
eb66db55 303 test_fsck_exists();
6b56a651 304 test_make_relative();
3e8a78c8 305 test_strv_resolve();
5895b62f
RC
306 test_path_startswith();
307
76877b46
ZJS
308 return 0;
309}