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"
31 static void test_path(void) {
32 assert_se(path_equal("/goo", "/goo"));
33 assert_se(path_equal("//goo", "/goo"));
34 assert_se(path_equal("//goo/////", "/goo"));
35 assert_se(path_equal("goo/////", "goo"));
37 assert_se(path_equal("/goo/boo", "/goo//boo"));
38 assert_se(path_equal("//goo/boo", "/goo/boo//"));
40 assert_se(path_equal("/", "///"));
42 assert_se(!path_equal("/x", "x/"));
43 assert_se(!path_equal("x/", "/"));
45 assert_se(!path_equal("/x/./y", "x/y"));
46 assert_se(!path_equal("x/.y", "x/y"));
48 assert_se(path_is_absolute("/"));
49 assert_se(!path_is_absolute("./"));
51 assert_se(is_path("/dir"));
52 assert_se(is_path("a/b"));
53 assert_se(!is_path("."));
55 assert_se(streq(basename("./aa/bb/../file.da."), "file.da."));
56 assert_se(streq(basename("/aa///.file"), ".file"));
57 assert_se(streq(basename("/aa///file..."), "file..."));
58 assert_se(streq(basename("file.../"), ""));
60 #define test_parent(x, y) { \
61 _cleanup_free_ char *z = NULL; \
62 int r = path_get_parent(x, &z); \
63 printf("expected: %s\n", y ? y : "error"); \
64 printf("actual: %s\n", r<0 ? "error" : z); \
65 assert_se((y==NULL) ^ (r==0)); \
66 assert_se(y==NULL || path_equal(z, y)); \
69 test_parent("./aa/bb/../file.da.", "./aa/bb/..");
70 test_parent("/aa///.file", "/aa///");
71 test_parent("/aa///file...", "/aa///");
72 test_parent("file.../", NULL);
74 assert_se(path_is_mount_point("/", true));
75 assert_se(path_is_mount_point("/", false));
78 char p1[] = "aaa/bbb////ccc";
79 char p2[] = "//aaa/.////ccc";
82 assert_se(path_equal(path_kill_slashes(p1), "aaa/bbb/ccc"));
83 assert_se(path_equal(path_kill_slashes(p2), "/aaa/./ccc"));
84 assert_se(path_equal(path_kill_slashes(p3), "/./"));
88 static void test_find_binary(const char *self, bool local) {
91 assert_se(find_binary("/bin/sh", local, &p) == 0);
93 assert_se(streq(p, "/bin/sh"));
96 assert_se(find_binary(self, local, &p) == 0);
98 assert_se(endswith(p, "/test-path-util"));
99 assert_se(path_is_absolute(p));
102 assert_se(find_binary("sh", local, &p) == 0);
104 assert_se(endswith(p, "/sh"));
105 assert_se(path_is_absolute(p));
108 assert_se(find_binary("xxxx-xxxx", local, &p) == -ENOENT);
110 assert_se(find_binary("/some/dir/xxxx-xxxx", local, &p) ==
111 (local ? -ENOENT : 0));
114 static void test_prefixes(void) {
115 static const char* values[] = { "/a/b/c/d", "/a/b/c", "/a/b", "/a", "", NULL};
121 PATH_FOREACH_PREFIX_MORE(s, "/a/b/c/d") {
122 log_error("---%s---", s);
123 assert_se(streq(s, values[i++]));
125 assert_se(values[i] == NULL);
128 PATH_FOREACH_PREFIX(s, "/a/b/c/d") {
129 log_error("---%s---", s);
130 assert_se(streq(s, values[i++]));
132 assert_se(values[i] == NULL);
135 PATH_FOREACH_PREFIX_MORE(s, "////a////b////c///d///////")
136 assert_se(streq(s, values[i++]));
137 assert_se(values[i] == NULL);
140 PATH_FOREACH_PREFIX(s, "////a////b////c///d///////")
141 assert_se(streq(s, values[i++]));
142 assert_se(values[i] == NULL);
144 PATH_FOREACH_PREFIX(s, "////")
145 assert_not_reached("Wut?");
148 PATH_FOREACH_PREFIX_MORE(s, "////") {
150 assert_se(streq(s, ""));
155 PATH_FOREACH_PREFIX(s, "")
156 assert_not_reached("wut?");
159 PATH_FOREACH_PREFIX_MORE(s, "") {
161 assert_se(streq(s, ""));
166 static void test_path_join(void) {
168 #define test_join(root, path, rest, expected) { \
169 _cleanup_free_ char *z = NULL; \
170 z = path_join(root, path, rest); \
171 assert_se(streq(z, expected)); \
174 test_join("/root", "/a/b", "/c", "/root/a/b/c");
175 test_join("/root", "a/b", "c", "/root/a/b/c");
176 test_join("/root", "/a/b", "c", "/root/a/b/c");
177 test_join("/root", "/", "c", "/root//c");
178 test_join("/root", "/", NULL, "/root/");
180 test_join(NULL, "/a/b", "/c", "/a/b/c");
181 test_join(NULL, "a/b", "c", "a/b/c");
182 test_join(NULL, "/a/b", "c", "/a/b/c");
183 test_join(NULL, "/", "c", "//c");
184 test_join(NULL, "/", NULL, "/");
187 static void test_fsck_exists(void) {
188 /* Ensure we use a sane default for PATH. */
191 /* fsck.minix is provided by util-linux and will probably exist. */
192 assert_se(fsck_exists("minix") == 0);
194 assert_se(fsck_exists("AbCdE") == -ENOENT);
197 static void test_make_relative(void) {
200 assert_se(path_make_relative("some/relative/path", "/some/path", &result) < 0);
201 assert_se(path_make_relative("/some/path", "some/relative/path", &result) < 0);
203 #define test(from_dir, to_path, expected) { \
204 _cleanup_free_ char *z = NULL; \
205 path_make_relative(from_dir, to_path, &z); \
206 assert_se(streq(z, expected)); \
210 test("/", "/some/path", "some/path");
211 test("/some/path", "/some/path", ".");
212 test("/some/path", "/some/path/in/subdir", "in/subdir");
213 test("/some/path", "/", "../..");
214 test("/some/path", "/some/other/path", "../other/path");
215 test("//extra/////slashes///won't////fool///anybody//", "////extra///slashes////are/just///fine///", "../../../are/just/fine");
218 static void test_strv_resolve(void) {
219 char tmp_dir[] = "/tmp/test-path-util-XXXXXX";
220 _cleanup_strv_free_ char **search_dirs = NULL;
221 _cleanup_strv_free_ char **absolute_dirs = NULL;
224 assert_se(mkdtemp(tmp_dir) != NULL);
226 search_dirs = strv_new("/dir1", "/dir2", "/dir3", NULL);
227 assert_se(search_dirs);
228 STRV_FOREACH(d, search_dirs) {
229 char *p = strappend(tmp_dir, *d);
231 assert_se(strv_push(&absolute_dirs, p) == 0);
234 assert_se(mkdir(absolute_dirs[0], 0700) == 0);
235 assert_se(mkdir(absolute_dirs[1], 0700) == 0);
236 assert_se(symlink("dir2", absolute_dirs[2]) == 0);
238 path_strv_resolve(search_dirs, tmp_dir);
239 assert_se(streq(search_dirs[0], "/dir1"));
240 assert_se(streq(search_dirs[1], "/dir2"));
241 assert_se(streq(search_dirs[2], "/dir2"));
243 assert_se(rm_rf_dangerous(tmp_dir, false, true, false) == 0);
246 static void test_path_startswith(void) {
247 assert_se(path_startswith("/foo/bar/barfoo/", "/foo"));
248 assert_se(path_startswith("/foo/bar/barfoo/", "/foo/"));
249 assert_se(path_startswith("/foo/bar/barfoo/", "/"));
250 assert_se(path_startswith("/foo/bar/barfoo/", "////"));
251 assert_se(path_startswith("/foo/bar/barfoo/", "/foo//bar/////barfoo///"));
252 assert_se(path_startswith("/foo/bar/barfoo/", "/foo/bar/barfoo////"));
253 assert_se(path_startswith("/foo/bar/barfoo/", "/foo/bar///barfoo/"));
254 assert_se(path_startswith("/foo/bar/barfoo/", "/foo////bar/barfoo/"));
255 assert_se(path_startswith("/foo/bar/barfoo/", "////foo/bar/barfoo/"));
256 assert_se(path_startswith("/foo/bar/barfoo/", "/foo/bar/barfoo"));
258 assert_se(!path_startswith("/foo/bar/barfoo/", "/foo/bar/barfooa/"));
259 assert_se(!path_startswith("/foo/bar/barfoo/", "/foo/bar/barfooa"));
260 assert_se(!path_startswith("/foo/bar/barfoo/", ""));
261 assert_se(!path_startswith("/foo/bar/barfoo/", "/bar/foo"));
262 assert_se(!path_startswith("/foo/bar/barfoo/", "/f/b/b/"));
265 int main(int argc, char **argv) {
267 test_find_binary(argv[0], true);
268 test_find_binary(argv[0], false);
272 test_make_relative();
274 test_path_startswith();