1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Zbigniew Jędrzejewski-Szmek
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.
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.
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/>.
25 #include "path-util.h"
30 #define test_path_compare(a, b, result) { \
31 assert_se(path_compare(a, b) == result); \
32 assert_se(path_compare(b, a) == -result); \
33 assert_se(path_equal(a, b) == !result); \
34 assert_se(path_equal(b, a) == !result); \
37 static void test_path(void) {
38 test_path_compare("/goo", "/goo", 0);
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);
44 test_path_compare("/goo/boo", "/goo//boo", 0);
45 test_path_compare("//goo/boo", "/goo/boo//", 0);
47 test_path_compare("/", "///", 0);
49 test_path_compare("/x", "x/", 1);
50 test_path_compare("x/", "/", -1);
52 test_path_compare("/x/./y", "x/y", 1);
53 test_path_compare("x/.y", "x/y", -1);
55 test_path_compare("foo", "/foo", -1);
56 test_path_compare("/foo", "/foo/bar", -1);
57 test_path_compare("/foo/aaa", "/foo/b", -1);
58 test_path_compare("/foo/aaa", "/foo/b/a", -1);
59 test_path_compare("/foo/a", "/foo/aaa", -1);
60 test_path_compare("/foo/a/b", "/foo/aaa", -1);
62 assert_se(path_is_absolute("/"));
63 assert_se(!path_is_absolute("./"));
65 assert_se(is_path("/dir"));
66 assert_se(is_path("a/b"));
67 assert_se(!is_path("."));
69 assert_se(streq(basename("./aa/bb/../file.da."), "file.da."));
70 assert_se(streq(basename("/aa///.file"), ".file"));
71 assert_se(streq(basename("/aa///file..."), "file..."));
72 assert_se(streq(basename("file.../"), ""));
74 #define test_parent(x, y) { \
75 _cleanup_free_ char *z = NULL; \
76 int r = path_get_parent(x, &z); \
77 printf("expected: %s\n", y ? y : "error"); \
78 printf("actual: %s\n", r<0 ? "error" : z); \
79 assert_se((y==NULL) ^ (r==0)); \
80 assert_se(y==NULL || path_equal(z, y)); \
83 test_parent("./aa/bb/../file.da.", "./aa/bb/..");
84 test_parent("/aa///.file", "/aa///");
85 test_parent("/aa///file...", "/aa///");
86 test_parent("file.../", NULL);
88 assert_se(path_is_mount_point("/", true));
89 assert_se(path_is_mount_point("/", false));
92 char p1[] = "aaa/bbb////ccc";
93 char p2[] = "//aaa/.////ccc";
96 assert_se(path_equal(path_kill_slashes(p1), "aaa/bbb/ccc"));
97 assert_se(path_equal(path_kill_slashes(p2), "/aaa/./ccc"));
98 assert_se(path_equal(path_kill_slashes(p3), "/./"));
102 static void test_find_binary(const char *self, bool local) {
105 assert_se(find_binary("/bin/sh", local, &p) == 0);
107 assert_se(streq(p, "/bin/sh"));
110 assert_se(find_binary(self, local, &p) == 0);
112 assert_se(endswith(p, "/test-path-util"));
113 assert_se(path_is_absolute(p));
116 assert_se(find_binary("sh", local, &p) == 0);
118 assert_se(endswith(p, "/sh"));
119 assert_se(path_is_absolute(p));
122 assert_se(find_binary("xxxx-xxxx", local, &p) == -ENOENT);
124 assert_se(find_binary("/some/dir/xxxx-xxxx", local, &p) ==
125 (local ? -ENOENT : 0));
130 static void test_prefixes(void) {
131 static const char* values[] = { "/a/b/c/d", "/a/b/c", "/a/b", "/a", "", NULL};
137 PATH_FOREACH_PREFIX_MORE(s, "/a/b/c/d") {
138 log_error("---%s---", s);
139 assert_se(streq(s, values[i++]));
141 assert_se(values[i] == NULL);
144 PATH_FOREACH_PREFIX(s, "/a/b/c/d") {
145 log_error("---%s---", s);
146 assert_se(streq(s, values[i++]));
148 assert_se(values[i] == NULL);
151 PATH_FOREACH_PREFIX_MORE(s, "////a////b////c///d///////")
152 assert_se(streq(s, values[i++]));
153 assert_se(values[i] == NULL);
156 PATH_FOREACH_PREFIX(s, "////a////b////c///d///////")
157 assert_se(streq(s, values[i++]));
158 assert_se(values[i] == NULL);
160 PATH_FOREACH_PREFIX(s, "////")
161 assert_not_reached("Wut?");
164 PATH_FOREACH_PREFIX_MORE(s, "////") {
166 assert_se(streq(s, ""));
171 PATH_FOREACH_PREFIX(s, "")
172 assert_not_reached("wut?");
175 PATH_FOREACH_PREFIX_MORE(s, "") {
177 assert_se(streq(s, ""));
182 static void test_path_join(void) {
184 #define test_join(root, path, rest, expected) { \
185 _cleanup_free_ char *z = NULL; \
186 z = path_join(root, path, rest); \
187 assert_se(streq(z, expected)); \
190 test_join("/root", "/a/b", "/c", "/root/a/b/c");
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", "/", "c", "/root/c");
194 test_join("/root", "/", NULL, "/root/");
196 test_join(NULL, "/a/b", "/c", "/a/b/c");
197 test_join(NULL, "a/b", "c", "a/b/c");
198 test_join(NULL, "/a/b", "c", "/a/b/c");
199 test_join(NULL, "/", "c", "/c");
200 test_join(NULL, "/", NULL, "/");
203 static void test_fsck_exists(void) {
204 /* Ensure we use a sane default for PATH. */
207 /* fsck.minix is provided by util-linux and will probably exist. */
208 assert_se(fsck_exists("minix") == 0);
210 assert_se(fsck_exists("AbCdE") == -ENOENT);
213 static void test_make_relative(void) {
216 assert_se(path_make_relative("some/relative/path", "/some/path", &result) < 0);
217 assert_se(path_make_relative("/some/path", "some/relative/path", &result) < 0);
219 #define test(from_dir, to_path, expected) { \
220 _cleanup_free_ char *z = NULL; \
221 path_make_relative(from_dir, to_path, &z); \
222 assert_se(streq(z, expected)); \
226 test("/", "/some/path", "some/path");
227 test("/some/path", "/some/path", ".");
228 test("/some/path", "/some/path/in/subdir", "in/subdir");
229 test("/some/path", "/", "../..");
230 test("/some/path", "/some/other/path", "../other/path");
231 test("//extra/////slashes///won't////fool///anybody//", "////extra///slashes////are/just///fine///", "../../../are/just/fine");
234 static void test_strv_resolve(void) {
235 char tmp_dir[] = "/tmp/test-path-util-XXXXXX";
236 _cleanup_strv_free_ char **search_dirs = NULL;
237 _cleanup_strv_free_ char **absolute_dirs = NULL;
240 assert_se(mkdtemp(tmp_dir) != NULL);
242 search_dirs = strv_new("/dir1", "/dir2", "/dir3", NULL);
243 assert_se(search_dirs);
244 STRV_FOREACH(d, search_dirs) {
245 char *p = strappend(tmp_dir, *d);
247 assert_se(strv_push(&absolute_dirs, p) == 0);
250 assert_se(mkdir(absolute_dirs[0], 0700) == 0);
251 assert_se(mkdir(absolute_dirs[1], 0700) == 0);
252 assert_se(symlink("dir2", absolute_dirs[2]) == 0);
254 path_strv_resolve(search_dirs, tmp_dir);
255 assert_se(streq(search_dirs[0], "/dir1"));
256 assert_se(streq(search_dirs[1], "/dir2"));
257 assert_se(streq(search_dirs[2], "/dir2"));
259 assert_se(rm_rf_dangerous(tmp_dir, false, true, false) == 0);
262 static void test_path_startswith(void) {
263 assert_se(path_startswith("/foo/bar/barfoo/", "/foo"));
264 assert_se(path_startswith("/foo/bar/barfoo/", "/foo/"));
265 assert_se(path_startswith("/foo/bar/barfoo/", "/"));
266 assert_se(path_startswith("/foo/bar/barfoo/", "////"));
267 assert_se(path_startswith("/foo/bar/barfoo/", "/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"));
274 assert_se(!path_startswith("/foo/bar/barfoo/", "/foo/bar/barfooa/"));
275 assert_se(!path_startswith("/foo/bar/barfoo/", "/foo/bar/barfooa"));
276 assert_se(!path_startswith("/foo/bar/barfoo/", ""));
277 assert_se(!path_startswith("/foo/bar/barfoo/", "/bar/foo"));
278 assert_se(!path_startswith("/foo/bar/barfoo/", "/f/b/b/"));
281 int main(int argc, char **argv) {
283 test_find_binary(argv[0], true);
284 test_find_binary(argv[0], false);
288 test_make_relative();
290 test_path_startswith();