1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
/* Paths, as the two platforms spell them.
*
* Windows takes `/` and `\` and mixes them without being asked, and calls a
* path absolute when it starts with a drive. POSIX does neither: `\` is an
* ordinary character in a file name there, and `C:` an ordinary directory.
* So half of what follows asserts that the Windows rules are *not* applied on
* POSIX -- which is the half that would otherwise rot, because the platform
* where these functions are interesting is not the platform the suite runs on.
*/
#include "slosh.h"
#include <stdio.h>
#include <string.h>
static int fails = 0;
static void ok(const char *name, bool cond, const char *detail) {
if (!cond) fails++;
printf("%s %-52s %s\n", cond ? "ok " : "FAIL", name, cond ? "" : detail);
}
static void eq(const char *name, const char *got, const char *want) {
bool same = got && want && strcmp(got, want) == 0;
char detail[512];
snprintf(detail, sizeof detail, "got %s, wanted %s", got ? got : "(null)",
want);
ok(name, same, detail);
}
int main(void) {
char buf[512];
/* ---- absoluteness ----------------------------------------------------- */
ok("a leading slash is absolute", path_is_absolute("/etc/slosh.kdl"), "");
ok("a bare name is not", !path_is_absolute("themes/t.kdl"), "");
ok("a dotted name is not", !path_is_absolute("./themes/t.kdl"), "");
ok("an empty path is not", !path_is_absolute(""), "");
ok("NULL is not", !path_is_absolute(NULL), "");
#ifdef _WIN32
ok("a drive with a slash is absolute", path_is_absolute("C:/themes"), "");
ok("a drive with a backslash is absolute", path_is_absolute("C:\\themes"),
"");
ok("a lowercase drive counts", path_is_absolute("d:/x"), "");
ok("a drive-relative root is absolute", path_is_absolute("\\themes"), "");
ok("a UNC share is absolute", path_is_absolute("\\\\host\\share\\t.kdl"), "");
/* `C:t.kdl` is relative to the current directory *of drive C*, which is a
* real thing and not one we can resolve for anybody. */
ok("a drive without a separator is not", !path_is_absolute("C:t.kdl"), "");
#else
/* The whole reason the drive rules are #ifdef'd: these are ordinary
* relative paths here, and reading them as absolute would break the
* platform that works in order to fix the one that did not. */
ok("a drive letter is just a name on POSIX", !path_is_absolute("C:/themes"),
"");
ok("a backslash is just a character on POSIX", !path_is_absolute("\\themes"),
"");
#endif
/* ---- splitting -------------------------------------------------------- */
eq("the directory of a nested path", path_dir("/a/b/c.kdl", buf, sizeof buf),
"/a/b");
eq("the name of a nested path", path_base("/a/b/c.kdl"), "c.kdl");
eq("a bare name is in the current directory",
path_dir("c.kdl", buf, sizeof buf), ".");
eq("and is its own name", path_base("c.kdl"), "c.kdl");
eq("a path at the root", path_dir("/c.kdl", buf, sizeof buf), "/");
eq("its name", path_base("/c.kdl"), "c.kdl");
#ifdef _WIN32
eq("a backslash separates",
path_dir("C:\\Users\\you\\config.kdl", buf, sizeof buf), "C:\\Users\\you");
eq("and names", path_base("C:\\Users\\you\\config.kdl"), "config.kdl");
/* The mixture is not hypothetical: slosh joins with '/' and $HOME arrives
* with '\', so the default config path is spelled both ways at once. */
eq("the last separator wins in a mixed path",
path_dir("C:\\Users\\you/.config/slosh/config.kdl", buf, sizeof buf),
"C:\\Users\\you/.config/slosh");
eq("and the other order",
path_dir("C:/Users/you\\config.kdl", buf, sizeof buf), "C:/Users/you");
/* `C:` alone is the current directory on drive C, which is somewhere else. */
eq("a file at a drive root keeps the separator",
path_dir("C:\\config.kdl", buf, sizeof buf), "C:\\");
eq("forward-slash spelling too", path_dir("C:/config.kdl", buf, sizeof buf),
"C:/");
#else
/* A POSIX file may legitimately be called `a\b`; splitting there would
* invent a directory that does not exist. */
eq("a backslash does not split on POSIX", path_dir("a\\b", buf, sizeof buf),
".");
eq("nor name", path_base("a\\b"), "a\\b");
eq("a colon is not a drive on POSIX", path_dir("a:/b", buf, sizeof buf),
"a:");
#endif
/* ---- resolving against a base ----------------------------------------- */
eq("a relative path joins the base",
path_resolve("themes/t.kdl", "/cfg", buf, sizeof buf),
"/cfg/themes/t.kdl");
eq("an absolute path ignores the base",
path_resolve("/etc/t.kdl", "/cfg", buf, sizeof buf), "/etc/t.kdl");
eq("no base leaves it alone",
path_resolve("themes/t.kdl", NULL, buf, sizeof buf), "themes/t.kdl");
eq("`.` is the base itself", path_resolve(".", "/cfg", buf, sizeof buf),
"/cfg");
#ifdef _WIN32
/* The bug this was written for: joined instead of taken as it stood, and
* opened as C:/cfg/C:/themes/t.kdl. */
eq("a drive path ignores the base",
path_resolve("C:/themes/t.kdl", "C:/cfg", buf, sizeof buf),
"C:/themes/t.kdl");
#endif
if (fails) printf("\n%d failed\n", fails);
return fails ? 1 : 0;
}
|