]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-path-util.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / test / test-path-util.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright 2013 Zbigniew Jędrzejewski-Szmek
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <stdio.h>
22 #include <sys/mount.h>
23 #include <unistd.h>
24
25 #include "alloc-util.h"
26 #include "fd-util.h"
27 #include "macro.h"
28 #include "mount-util.h"
29 #include "path-util.h"
30 #include "rm-rf.h"
31 #include "stat-util.h"
32 #include "string-util.h"
33 #include "strv.h"
34 #include "util.h"
35
36 #define test_path_compare(a, b, result) { \
37 assert_se(path_compare(a, b) == result); \
38 assert_se(path_compare(b, a) == -result); \
39 assert_se(path_equal(a, b) == !result); \
40 assert_se(path_equal(b, a) == !result); \
41 }
42
43 static void test_path(void) {
44 _cleanup_close_ int fd = -1;
45
46 test_path_compare("/goo", "/goo", 0);
47 test_path_compare("/goo", "/goo", 0);
48 test_path_compare("//goo", "/goo", 0);
49 test_path_compare("//goo/////", "/goo", 0);
50 test_path_compare("goo/////", "goo", 0);
51
52 test_path_compare("/goo/boo", "/goo//boo", 0);
53 test_path_compare("//goo/boo", "/goo/boo//", 0);
54
55 test_path_compare("/", "///", 0);
56
57 test_path_compare("/x", "x/", 1);
58 test_path_compare("x/", "/", -1);
59
60 test_path_compare("/x/./y", "x/y", 1);
61 test_path_compare("x/.y", "x/y", -1);
62
63 test_path_compare("foo", "/foo", -1);
64 test_path_compare("/foo", "/foo/bar", -1);
65 test_path_compare("/foo/aaa", "/foo/b", -1);
66 test_path_compare("/foo/aaa", "/foo/b/a", -1);
67 test_path_compare("/foo/a", "/foo/aaa", -1);
68 test_path_compare("/foo/a/b", "/foo/aaa", -1);
69
70 assert_se(path_is_absolute("/"));
71 assert_se(!path_is_absolute("./"));
72
73 assert_se(is_path("/dir"));
74 assert_se(is_path("a/b"));
75 assert_se(!is_path("."));
76
77 assert_se(streq(basename("./aa/bb/../file.da."), "file.da."));
78 assert_se(streq(basename("/aa///.file"), ".file"));
79 assert_se(streq(basename("/aa///file..."), "file..."));
80 assert_se(streq(basename("file.../"), ""));
81
82 fd = open("/", O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOCTTY);
83 assert_se(fd >= 0);
84 assert_se(fd_is_mount_point(fd, "/", 0) > 0);
85
86 {
87 char p1[] = "aaa/bbb////ccc";
88 char p2[] = "//aaa/.////ccc";
89 char p3[] = "/./";
90
91 assert_se(path_equal(path_kill_slashes(p1), "aaa/bbb/ccc"));
92 assert_se(path_equal(path_kill_slashes(p2), "/aaa/./ccc"));
93 assert_se(path_equal(path_kill_slashes(p3), "/./"));
94 }
95
96 assert_se(PATH_IN_SET("/bin", "/", "/bin", "/foo"));
97 assert_se(PATH_IN_SET("/bin", "/bin"));
98 assert_se(PATH_IN_SET("/bin", "/foo/bar", "/bin"));
99 assert_se(PATH_IN_SET("/", "/", "/", "/foo/bar"));
100 assert_se(!PATH_IN_SET("/", "/abc", "/def"));
101
102 assert_se(path_equal_ptr(NULL, NULL));
103 assert_se(path_equal_ptr("/a", "/a"));
104 assert_se(!path_equal_ptr("/a", "/b"));
105 assert_se(!path_equal_ptr("/a", NULL));
106 assert_se(!path_equal_ptr(NULL, "/a"));
107 }
108
109 static void test_path_equal_root(void) {
110 /* Nail down the details of how path_equal("/", ...) works. */
111
112 assert_se(path_equal("/", "/"));
113 assert_se(path_equal("/", "//"));
114
115 assert_se(!path_equal("/", "/./"));
116 assert_se(!path_equal("/", "/../"));
117
118 assert_se(!path_equal("/", "/.../"));
119
120 /* Make sure that files_same works as expected. */
121
122 assert_se(files_same("/", "/", 0) > 0);
123 assert_se(files_same("/", "/", AT_SYMLINK_NOFOLLOW) > 0);
124 assert_se(files_same("/", "//", 0) > 0);
125 assert_se(files_same("/", "//", AT_SYMLINK_NOFOLLOW) > 0);
126
127 assert_se(files_same("/", "/./", 0) > 0);
128 assert_se(files_same("/", "/./", AT_SYMLINK_NOFOLLOW) > 0);
129 assert_se(files_same("/", "/../", 0) > 0);
130 assert_se(files_same("/", "/../", AT_SYMLINK_NOFOLLOW) > 0);
131
132 assert_se(files_same("/", "/.../", 0) == -ENOENT);
133 assert_se(files_same("/", "/.../", AT_SYMLINK_NOFOLLOW) == -ENOENT);
134
135 /* The same for path_equal_or_files_same. */
136
137 assert_se(path_equal_or_files_same("/", "/", 0));
138 assert_se(path_equal_or_files_same("/", "/", AT_SYMLINK_NOFOLLOW));
139 assert_se(path_equal_or_files_same("/", "//", 0));
140 assert_se(path_equal_or_files_same("/", "//", AT_SYMLINK_NOFOLLOW));
141
142 assert_se(path_equal_or_files_same("/", "/./", 0));
143 assert_se(path_equal_or_files_same("/", "/./", AT_SYMLINK_NOFOLLOW));
144 assert_se(path_equal_or_files_same("/", "/../", 0));
145 assert_se(path_equal_or_files_same("/", "/../", AT_SYMLINK_NOFOLLOW));
146
147 assert_se(!path_equal_or_files_same("/", "/.../", 0));
148 assert_se(!path_equal_or_files_same("/", "/.../", AT_SYMLINK_NOFOLLOW));
149 }
150
151 static void test_find_binary(const char *self) {
152 char *p;
153
154 assert_se(find_binary("/bin/sh", &p) == 0);
155 puts(p);
156 assert_se(path_equal(p, "/bin/sh"));
157 free(p);
158
159 assert_se(find_binary(self, &p) == 0);
160 puts(p);
161 /* libtool might prefix the binary name with "lt-" */
162 assert_se(endswith(p, "/lt-test-path-util") || endswith(p, "/test-path-util"));
163 assert_se(path_is_absolute(p));
164 free(p);
165
166 assert_se(find_binary("sh", &p) == 0);
167 puts(p);
168 assert_se(endswith(p, "/sh"));
169 assert_se(path_is_absolute(p));
170 free(p);
171
172 assert_se(find_binary("xxxx-xxxx", &p) == -ENOENT);
173 assert_se(find_binary("/some/dir/xxxx-xxxx", &p) == -ENOENT);
174 }
175
176 static void test_prefixes(void) {
177 static const char* values[] = { "/a/b/c/d", "/a/b/c", "/a/b", "/a", "", NULL};
178 unsigned i;
179 char s[PATH_MAX];
180 bool b;
181
182 i = 0;
183 PATH_FOREACH_PREFIX_MORE(s, "/a/b/c/d") {
184 log_error("---%s---", s);
185 assert_se(streq(s, values[i++]));
186 }
187 assert_se(values[i] == NULL);
188
189 i = 1;
190 PATH_FOREACH_PREFIX(s, "/a/b/c/d") {
191 log_error("---%s---", s);
192 assert_se(streq(s, values[i++]));
193 }
194 assert_se(values[i] == NULL);
195
196 i = 0;
197 PATH_FOREACH_PREFIX_MORE(s, "////a////b////c///d///////")
198 assert_se(streq(s, values[i++]));
199 assert_se(values[i] == NULL);
200
201 i = 1;
202 PATH_FOREACH_PREFIX(s, "////a////b////c///d///////")
203 assert_se(streq(s, values[i++]));
204 assert_se(values[i] == NULL);
205
206 PATH_FOREACH_PREFIX(s, "////")
207 assert_not_reached("Wut?");
208
209 b = false;
210 PATH_FOREACH_PREFIX_MORE(s, "////") {
211 assert_se(!b);
212 assert_se(streq(s, ""));
213 b = true;
214 }
215 assert_se(b);
216
217 PATH_FOREACH_PREFIX(s, "")
218 assert_not_reached("wut?");
219
220 b = false;
221 PATH_FOREACH_PREFIX_MORE(s, "") {
222 assert_se(!b);
223 assert_se(streq(s, ""));
224 b = true;
225 }
226 }
227
228 static void test_path_join(void) {
229
230 #define test_join(root, path, rest, expected) { \
231 _cleanup_free_ char *z = NULL; \
232 z = path_join(root, path, rest); \
233 assert_se(streq(z, expected)); \
234 }
235
236 test_join("/root", "/a/b", "/c", "/root/a/b/c");
237 test_join("/root", "a/b", "c", "/root/a/b/c");
238 test_join("/root", "/a/b", "c", "/root/a/b/c");
239 test_join("/root", "/", "c", "/root/c");
240 test_join("/root", "/", NULL, "/root/");
241
242 test_join(NULL, "/a/b", "/c", "/a/b/c");
243 test_join(NULL, "a/b", "c", "a/b/c");
244 test_join(NULL, "/a/b", "c", "/a/b/c");
245 test_join(NULL, "/", "c", "/c");
246 test_join(NULL, "/", NULL, "/");
247 }
248
249 static void test_fsck_exists(void) {
250 /* Ensure we use a sane default for PATH. */
251 unsetenv("PATH");
252
253 /* fsck.minix is provided by util-linux and will probably exist. */
254 assert_se(fsck_exists("minix") == 1);
255
256 assert_se(fsck_exists("AbCdE") == 0);
257 assert_se(fsck_exists("/../bin/") == 0);
258 }
259
260 static void test_make_relative(void) {
261 char *result;
262
263 assert_se(path_make_relative("some/relative/path", "/some/path", &result) < 0);
264 assert_se(path_make_relative("/some/path", "some/relative/path", &result) < 0);
265 assert_se(path_make_relative("/some/dotdot/../path", "/some/path", &result) < 0);
266
267 #define test(from_dir, to_path, expected) { \
268 _cleanup_free_ char *z = NULL; \
269 path_make_relative(from_dir, to_path, &z); \
270 assert_se(streq(z, expected)); \
271 }
272
273 test("/", "/", ".");
274 test("/", "/some/path", "some/path");
275 test("/some/path", "/some/path", ".");
276 test("/some/path", "/some/path/in/subdir", "in/subdir");
277 test("/some/path", "/", "../..");
278 test("/some/path", "/some/other/path", "../other/path");
279 test("/some/path/./dot", "/some/further/path", "../../further/path");
280 test("//extra/////slashes///won't////fool///anybody//", "////extra///slashes////are/just///fine///", "../../../are/just/fine");
281 }
282
283 static void test_strv_resolve(void) {
284 char tmp_dir[] = "/tmp/test-path-util-XXXXXX";
285 _cleanup_strv_free_ char **search_dirs = NULL;
286 _cleanup_strv_free_ char **absolute_dirs = NULL;
287 char **d;
288
289 assert_se(mkdtemp(tmp_dir) != NULL);
290
291 search_dirs = strv_new("/dir1", "/dir2", "/dir3", NULL);
292 assert_se(search_dirs);
293 STRV_FOREACH(d, search_dirs) {
294 char *p = strappend(tmp_dir, *d);
295 assert_se(p);
296 assert_se(strv_push(&absolute_dirs, p) == 0);
297 }
298
299 assert_se(mkdir(absolute_dirs[0], 0700) == 0);
300 assert_se(mkdir(absolute_dirs[1], 0700) == 0);
301 assert_se(symlink("dir2", absolute_dirs[2]) == 0);
302
303 path_strv_resolve(search_dirs, tmp_dir);
304 assert_se(streq(search_dirs[0], "/dir1"));
305 assert_se(streq(search_dirs[1], "/dir2"));
306 assert_se(streq(search_dirs[2], "/dir2"));
307
308 assert_se(rm_rf(tmp_dir, REMOVE_ROOT|REMOVE_PHYSICAL) == 0);
309 }
310
311 static void test_path_startswith(void) {
312 const char *p;
313
314 p = path_startswith("/foo/bar/barfoo/", "/foo");
315 assert_se(streq_ptr(p, "bar/barfoo/"));
316
317 p = path_startswith("/foo/bar/barfoo/", "/foo/");
318 assert_se(streq_ptr(p, "bar/barfoo/"));
319
320 p = path_startswith("/foo/bar/barfoo/", "/");
321 assert_se(streq_ptr(p, "foo/bar/barfoo/"));
322
323 p = path_startswith("/foo/bar/barfoo/", "////");
324 assert_se(streq_ptr(p, "foo/bar/barfoo/"));
325
326 p = path_startswith("/foo/bar/barfoo/", "/foo//bar/////barfoo///");
327 assert_se(streq_ptr(p, ""));
328
329 p = path_startswith("/foo/bar/barfoo/", "/foo/bar/barfoo////");
330 assert_se(streq_ptr(p, ""));
331
332 p = path_startswith("/foo/bar/barfoo/", "/foo/bar///barfoo/");
333 assert_se(streq_ptr(p, ""));
334
335 p = path_startswith("/foo/bar/barfoo/", "/foo////bar/barfoo/");
336 assert_se(streq_ptr(p, ""));
337
338 p = path_startswith("/foo/bar/barfoo/", "////foo/bar/barfoo/");
339 assert_se(streq_ptr(p, ""));
340
341 p = path_startswith("/foo/bar/barfoo/", "/foo/bar/barfoo");
342 assert_se(streq_ptr(p, ""));
343
344 assert_se(!path_startswith("/foo/bar/barfoo/", "/foo/bar/barfooa/"));
345 assert_se(!path_startswith("/foo/bar/barfoo/", "/foo/bar/barfooa"));
346 assert_se(!path_startswith("/foo/bar/barfoo/", ""));
347 assert_se(!path_startswith("/foo/bar/barfoo/", "/bar/foo"));
348 assert_se(!path_startswith("/foo/bar/barfoo/", "/f/b/b/"));
349 }
350
351 static void test_prefix_root_one(const char *r, const char *p, const char *expected) {
352 _cleanup_free_ char *s = NULL;
353 const char *t;
354
355 assert_se(s = prefix_root(r, p));
356 assert_se(streq_ptr(s, expected));
357
358 t = prefix_roota(r, p);
359 assert_se(t);
360 assert_se(streq_ptr(t, expected));
361 }
362
363 static void test_prefix_root(void) {
364 test_prefix_root_one("/", "/foo", "/foo");
365 test_prefix_root_one(NULL, "/foo", "/foo");
366 test_prefix_root_one("", "/foo", "/foo");
367 test_prefix_root_one("///", "/foo", "/foo");
368 test_prefix_root_one("/", "////foo", "/foo");
369 test_prefix_root_one(NULL, "////foo", "/foo");
370
371 test_prefix_root_one("/foo", "/bar", "/foo/bar");
372 test_prefix_root_one("/foo", "bar", "/foo/bar");
373 test_prefix_root_one("foo", "bar", "foo/bar");
374 test_prefix_root_one("/foo/", "/bar", "/foo/bar");
375 test_prefix_root_one("/foo/", "//bar", "/foo/bar");
376 test_prefix_root_one("/foo///", "//bar", "/foo/bar");
377 }
378
379 static void test_path_is_mount_point(void) {
380 int fd;
381 char tmp_dir[] = "/tmp/test-path-is-mount-point-XXXXXX";
382 _cleanup_free_ char *file1 = NULL, *file2 = NULL, *link1 = NULL, *link2 = NULL;
383 _cleanup_free_ char *dir1 = NULL, *dir1file = NULL, *dirlink1 = NULL, *dirlink1file = NULL;
384 _cleanup_free_ char *dir2 = NULL, *dir2file = NULL;
385
386 assert_se(path_is_mount_point("/", NULL, AT_SYMLINK_FOLLOW) > 0);
387 assert_se(path_is_mount_point("/", NULL, 0) > 0);
388
389 assert_se(path_is_mount_point("/proc", NULL, AT_SYMLINK_FOLLOW) > 0);
390 assert_se(path_is_mount_point("/proc", NULL, 0) > 0);
391
392 assert_se(path_is_mount_point("/proc/1", NULL, AT_SYMLINK_FOLLOW) == 0);
393 assert_se(path_is_mount_point("/proc/1", NULL, 0) == 0);
394
395 assert_se(path_is_mount_point("/sys", NULL, AT_SYMLINK_FOLLOW) > 0);
396 assert_se(path_is_mount_point("/sys", NULL, 0) > 0);
397
398 /* we'll create a hierarchy of different kinds of dir/file/link
399 * layouts:
400 *
401 * <tmp>/file1, <tmp>/file2
402 * <tmp>/link1 -> file1, <tmp>/link2 -> file2
403 * <tmp>/dir1/
404 * <tmp>/dir1/file
405 * <tmp>/dirlink1 -> dir1
406 * <tmp>/dirlink1file -> dirlink1/file
407 * <tmp>/dir2/
408 * <tmp>/dir2/file
409 */
410
411 /* file mountpoints */
412 assert_se(mkdtemp(tmp_dir) != NULL);
413 file1 = path_join(NULL, tmp_dir, "file1");
414 assert_se(file1);
415 file2 = path_join(NULL, tmp_dir, "file2");
416 assert_se(file2);
417 fd = open(file1, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664);
418 assert_se(fd > 0);
419 close(fd);
420 fd = open(file2, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664);
421 assert_se(fd > 0);
422 close(fd);
423 link1 = path_join(NULL, tmp_dir, "link1");
424 assert_se(link1);
425 assert_se(symlink("file1", link1) == 0);
426 link2 = path_join(NULL, tmp_dir, "link2");
427 assert_se(link1);
428 assert_se(symlink("file2", link2) == 0);
429
430 assert_se(path_is_mount_point(file1, NULL, AT_SYMLINK_FOLLOW) == 0);
431 assert_se(path_is_mount_point(file1, NULL, 0) == 0);
432 assert_se(path_is_mount_point(link1, NULL, AT_SYMLINK_FOLLOW) == 0);
433 assert_se(path_is_mount_point(link1, NULL, 0) == 0);
434
435 /* directory mountpoints */
436 dir1 = path_join(NULL, tmp_dir, "dir1");
437 assert_se(dir1);
438 assert_se(mkdir(dir1, 0755) == 0);
439 dirlink1 = path_join(NULL, tmp_dir, "dirlink1");
440 assert_se(dirlink1);
441 assert_se(symlink("dir1", dirlink1) == 0);
442 dirlink1file = path_join(NULL, tmp_dir, "dirlink1file");
443 assert_se(dirlink1file);
444 assert_se(symlink("dirlink1/file", dirlink1file) == 0);
445 dir2 = path_join(NULL, tmp_dir, "dir2");
446 assert_se(dir2);
447 assert_se(mkdir(dir2, 0755) == 0);
448
449 assert_se(path_is_mount_point(dir1, NULL, AT_SYMLINK_FOLLOW) == 0);
450 assert_se(path_is_mount_point(dir1, NULL, 0) == 0);
451 assert_se(path_is_mount_point(dirlink1, NULL, AT_SYMLINK_FOLLOW) == 0);
452 assert_se(path_is_mount_point(dirlink1, NULL, 0) == 0);
453
454 /* file in subdirectory mountpoints */
455 dir1file = path_join(NULL, dir1, "file");
456 assert_se(dir1file);
457 fd = open(dir1file, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664);
458 assert_se(fd > 0);
459 close(fd);
460
461 assert_se(path_is_mount_point(dir1file, NULL, AT_SYMLINK_FOLLOW) == 0);
462 assert_se(path_is_mount_point(dir1file, NULL, 0) == 0);
463 assert_se(path_is_mount_point(dirlink1file, NULL, AT_SYMLINK_FOLLOW) == 0);
464 assert_se(path_is_mount_point(dirlink1file, NULL, 0) == 0);
465
466 /* these tests will only work as root */
467 if (mount(file1, file2, NULL, MS_BIND, NULL) >= 0) {
468 int rt, rf, rlt, rlf, rl1t, rl1f;
469
470 /* files */
471 /* capture results in vars, to avoid dangling mounts on failure */
472 rf = path_is_mount_point(file2, NULL, 0);
473 rt = path_is_mount_point(file2, NULL, AT_SYMLINK_FOLLOW);
474 rlf = path_is_mount_point(link2, NULL, 0);
475 rlt = path_is_mount_point(link2, NULL, AT_SYMLINK_FOLLOW);
476
477 assert_se(umount(file2) == 0);
478
479 assert_se(rf == 1);
480 assert_se(rt == 1);
481 assert_se(rlf == 0);
482 assert_se(rlt == 1);
483
484 /* dirs */
485 dir2file = path_join(NULL, dir2, "file");
486 assert_se(dir2file);
487 fd = open(dir2file, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664);
488 assert_se(fd > 0);
489 close(fd);
490
491 assert_se(mount(dir2, dir1, NULL, MS_BIND, NULL) >= 0);
492
493 rf = path_is_mount_point(dir1, NULL, 0);
494 rt = path_is_mount_point(dir1, NULL, AT_SYMLINK_FOLLOW);
495 rlf = path_is_mount_point(dirlink1, NULL, 0);
496 rlt = path_is_mount_point(dirlink1, NULL, AT_SYMLINK_FOLLOW);
497 /* its parent is a mount point, but not /file itself */
498 rl1f = path_is_mount_point(dirlink1file, NULL, 0);
499 rl1t = path_is_mount_point(dirlink1file, NULL, AT_SYMLINK_FOLLOW);
500
501 assert_se(umount(dir1) == 0);
502
503 assert_se(rf == 1);
504 assert_se(rt == 1);
505 assert_se(rlf == 0);
506 assert_se(rlt == 1);
507 assert_se(rl1f == 0);
508 assert_se(rl1t == 0);
509
510 } else
511 printf("Skipping bind mount file test: %m\n");
512
513 assert_se(rm_rf(tmp_dir, REMOVE_ROOT|REMOVE_PHYSICAL) == 0);
514 }
515
516 static void test_file_in_same_dir(void) {
517 char *t;
518
519 t = file_in_same_dir("/", "a");
520 assert_se(streq(t, "/a"));
521 free(t);
522
523 t = file_in_same_dir("/", "/a");
524 assert_se(streq(t, "/a"));
525 free(t);
526
527 t = file_in_same_dir("", "a");
528 assert_se(streq(t, "a"));
529 free(t);
530
531 t = file_in_same_dir("a/", "a");
532 assert_se(streq(t, "a/a"));
533 free(t);
534
535 t = file_in_same_dir("bar/foo", "bar");
536 assert_se(streq(t, "bar/bar"));
537 free(t);
538 }
539
540 static void test_filename_is_valid(void) {
541 char foo[FILENAME_MAX+2];
542 int i;
543
544 assert_se(!filename_is_valid(""));
545 assert_se(!filename_is_valid("/bar/foo"));
546 assert_se(!filename_is_valid("/"));
547 assert_se(!filename_is_valid("."));
548 assert_se(!filename_is_valid(".."));
549
550 for (i=0; i<FILENAME_MAX+1; i++)
551 foo[i] = 'a';
552 foo[FILENAME_MAX+1] = '\0';
553
554 assert_se(!filename_is_valid(foo));
555
556 assert_se(filename_is_valid("foo_bar-333"));
557 assert_se(filename_is_valid("o.o"));
558 }
559
560 static void test_hidden_or_backup_file(void) {
561 assert_se(hidden_or_backup_file(".hidden"));
562 assert_se(hidden_or_backup_file("..hidden"));
563 assert_se(!hidden_or_backup_file("hidden."));
564
565 assert_se(hidden_or_backup_file("backup~"));
566 assert_se(hidden_or_backup_file(".backup~"));
567
568 assert_se(hidden_or_backup_file("lost+found"));
569 assert_se(hidden_or_backup_file("aquota.user"));
570 assert_se(hidden_or_backup_file("aquota.group"));
571
572 assert_se(hidden_or_backup_file("test.rpmnew"));
573 assert_se(hidden_or_backup_file("test.dpkg-old"));
574 assert_se(hidden_or_backup_file("test.dpkg-remove"));
575 assert_se(hidden_or_backup_file("test.swp"));
576
577 assert_se(!hidden_or_backup_file("test.rpmnew."));
578 assert_se(!hidden_or_backup_file("test.dpkg-old.foo"));
579 }
580
581 static void test_systemd_installation_has_version(const char *path) {
582 int r;
583 const unsigned versions[] = {0, 231, atoi(PACKAGE_VERSION), 999};
584 unsigned i;
585
586 for (i = 0; i < ELEMENTSOF(versions); i++) {
587 r = systemd_installation_has_version(path, versions[i]);
588 assert_se(r >= 0);
589 log_info("%s has systemd >= %u: %s",
590 path ?: "Current installation", versions[i], yes_no(r));
591 }
592 }
593
594 static void test_skip_dev_prefix(void) {
595
596 assert_se(streq(skip_dev_prefix("/"), "/"));
597 assert_se(streq(skip_dev_prefix("/dev"), ""));
598 assert_se(streq(skip_dev_prefix("/dev/"), ""));
599 assert_se(streq(skip_dev_prefix("/dev/foo"), "foo"));
600 assert_se(streq(skip_dev_prefix("/dev/foo/bar"), "foo/bar"));
601 assert_se(streq(skip_dev_prefix("//dev"), ""));
602 assert_se(streq(skip_dev_prefix("//dev//"), ""));
603 assert_se(streq(skip_dev_prefix("/dev///foo"), "foo"));
604 assert_se(streq(skip_dev_prefix("///dev///foo///bar"), "foo///bar"));
605 assert_se(streq(skip_dev_prefix("//foo"), "//foo"));
606 assert_se(streq(skip_dev_prefix("foo"), "foo"));
607 }
608
609 int main(int argc, char **argv) {
610 log_set_max_level(LOG_DEBUG);
611 log_parse_environment();
612 log_open();
613
614 test_path();
615 test_path_equal_root();
616 test_find_binary(argv[0]);
617 test_prefixes();
618 test_path_join();
619 test_fsck_exists();
620 test_make_relative();
621 test_strv_resolve();
622 test_path_startswith();
623 test_prefix_root();
624 test_path_is_mount_point();
625 test_file_in_same_dir();
626 test_filename_is_valid();
627 test_hidden_or_backup_file();
628 test_skip_dev_prefix();
629
630 test_systemd_installation_has_version(argv[1]); /* NULL is OK */
631
632 return 0;
633 }