]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
e82f30d1 | 2 | |
9f7fcf80 FS |
3 | #include "sd-id128.h" |
4 | ||
e82f30d1 LP |
5 | #include "alloc-util.h" |
6 | #include "log.h" | |
7 | #include "specifier.h" | |
607f0328 | 8 | #include "stat-util.h" |
b6c93a5a | 9 | #include "stdio-util.h" |
e82f30d1 LP |
10 | #include "string-util.h" |
11 | #include "strv.h" | |
6d7c4033 | 12 | #include "tests.h" |
172e9cc3 | 13 | #include "unit-file.h" |
e82f30d1 LP |
14 | |
15 | static void test_specifier_escape_one(const char *a, const char *b) { | |
16 | _cleanup_free_ char *x = NULL; | |
17 | ||
18 | x = specifier_escape(a); | |
19 | assert_se(streq_ptr(x, b)); | |
20 | } | |
21 | ||
4f7452a8 | 22 | TEST(specifier_escape) { |
e82f30d1 LP |
23 | test_specifier_escape_one(NULL, NULL); |
24 | test_specifier_escape_one("", ""); | |
25 | test_specifier_escape_one("%", "%%"); | |
26 | test_specifier_escape_one("foo bar", "foo bar"); | |
27 | test_specifier_escape_one("foo%bar", "foo%%bar"); | |
28 | test_specifier_escape_one("%%%%%", "%%%%%%%%%%"); | |
29 | } | |
30 | ||
31 | static void test_specifier_escape_strv_one(char **a, char **b) { | |
32 | _cleanup_strv_free_ char **x = NULL; | |
33 | ||
34 | assert_se(specifier_escape_strv(a, &x) >= 0); | |
35 | assert_se(strv_equal(x, b)); | |
36 | } | |
37 | ||
4f7452a8 | 38 | TEST(specifier_escape_strv) { |
e82f30d1 LP |
39 | test_specifier_escape_strv_one(NULL, NULL); |
40 | test_specifier_escape_strv_one(STRV_MAKE(NULL), STRV_MAKE(NULL)); | |
41 | test_specifier_escape_strv_one(STRV_MAKE(""), STRV_MAKE("")); | |
42 | test_specifier_escape_strv_one(STRV_MAKE("foo"), STRV_MAKE("foo")); | |
43 | test_specifier_escape_strv_one(STRV_MAKE("%"), STRV_MAKE("%%")); | |
b6c93a5a ZJS |
44 | test_specifier_escape_strv_one(STRV_MAKE("foo", "%", "foo%", "%foo", "foo%foo", "quux", "%%%"), |
45 | STRV_MAKE("foo", "%%", "foo%%", "%%foo", "foo%%foo", "quux", "%%%%%%")); | |
46 | } | |
47 | ||
48 | /* Any specifier functions which don't need an argument. */ | |
49 | static const Specifier specifier_table[] = { | |
2824aa07 LP |
50 | COMMON_SYSTEM_SPECIFIERS, |
51 | ||
4870133b | 52 | COMMON_CREDS_SPECIFIERS(RUNTIME_SCOPE_USER), |
b6c93a5a ZJS |
53 | { 'h', specifier_user_home, NULL }, |
54 | ||
2824aa07 | 55 | COMMON_TMP_SPECIFIERS, |
b6c93a5a ZJS |
56 | {} |
57 | }; | |
58 | ||
4f7452a8 | 59 | TEST(specifier_printf) { |
f4767dc0 YW |
60 | static const Specifier table[] = { |
61 | { 'X', specifier_string, (char*) "AAAA" }, | |
62 | { 'Y', specifier_string, (char*) "BBBB" }, | |
01c69460 | 63 | { 'e', specifier_string, NULL }, |
f4767dc0 YW |
64 | COMMON_SYSTEM_SPECIFIERS, |
65 | {} | |
66 | }; | |
67 | ||
68 | _cleanup_free_ char *w = NULL; | |
69 | int r; | |
70 | ||
01c69460 | 71 | r = specifier_printf("xxx a=%X b=%Y e=%e yyy", SIZE_MAX, table, NULL, NULL, &w); |
f4767dc0 YW |
72 | assert_se(r >= 0); |
73 | assert_se(w); | |
74 | ||
75 | puts(w); | |
01c69460 | 76 | assert_se(streq(w, "xxx a=AAAA b=BBBB e= yyy")); |
f4767dc0 YW |
77 | |
78 | free(w); | |
0011d686 | 79 | r = specifier_printf("boot=%b, host=%H, pretty=%q, version=%v, arch=%a, empty=%e", SIZE_MAX, table, NULL, NULL, &w); |
f4767dc0 YW |
80 | assert_se(r >= 0); |
81 | assert_se(w); | |
82 | puts(w); | |
83 | ||
84 | w = mfree(w); | |
01c69460 | 85 | specifier_printf("os=%o, os-version=%w, build=%B, variant=%W, empty=%e%e%e", SIZE_MAX, table, NULL, NULL, &w); |
f4767dc0 YW |
86 | if (w) |
87 | puts(w); | |
88 | } | |
89 | ||
607f0328 ZJS |
90 | TEST(specifier_real_path) { |
91 | static const Specifier table[] = { | |
92 | { 'p', specifier_string, "/dev/initctl" }, | |
93 | { 'y', specifier_real_path, "/dev/initctl" }, | |
94 | { 'Y', specifier_real_directory, "/dev/initctl" }, | |
95 | { 'w', specifier_real_path, "/dev/tty" }, | |
96 | { 'W', specifier_real_directory, "/dev/tty" }, | |
97 | {} | |
98 | }; | |
99 | ||
100 | _cleanup_free_ char *w = NULL; | |
101 | int r; | |
102 | ||
103 | r = specifier_printf("p=%p y=%y Y=%Y w=%w W=%W", SIZE_MAX, table, NULL, NULL, &w); | |
104 | assert_se(r >= 0 || r == -ENOENT); | |
105 | assert_se(w || r == -ENOENT); | |
106 | puts(strnull(w)); | |
107 | ||
108 | /* /dev/initctl should normally be a symlink to /run/initctl */ | |
563e6846 | 109 | if (inode_same("/dev/initctl", "/run/initctl", 0) > 0) |
607f0328 ZJS |
110 | assert_se(streq(w, "p=/dev/initctl y=/run/initctl Y=/run w=/dev/tty W=/dev")); |
111 | } | |
112 | ||
113 | TEST(specifier_real_path_missing_file) { | |
114 | static const Specifier table[] = { | |
115 | { 'p', specifier_string, "/dev/-no-such-file--" }, | |
116 | { 'y', specifier_real_path, "/dev/-no-such-file--" }, | |
117 | { 'Y', specifier_real_directory, "/dev/-no-such-file--" }, | |
118 | {} | |
119 | }; | |
120 | ||
121 | _cleanup_free_ char *w = NULL; | |
122 | int r; | |
123 | ||
124 | r = specifier_printf("p=%p y=%y", SIZE_MAX, table, NULL, NULL, &w); | |
125 | assert_se(r == -ENOENT); | |
126 | ||
127 | r = specifier_printf("p=%p Y=%Y", SIZE_MAX, table, NULL, NULL, &w); | |
128 | assert_se(r == -ENOENT); | |
129 | } | |
130 | ||
4f7452a8 | 131 | TEST(specifiers) { |
0011d686 LB |
132 | int r; |
133 | ||
b6c93a5a ZJS |
134 | for (const Specifier *s = specifier_table; s->specifier; s++) { |
135 | char spec[3]; | |
136 | _cleanup_free_ char *resolved = NULL; | |
137 | ||
138 | xsprintf(spec, "%%%c", s->specifier); | |
139 | ||
0011d686 | 140 | r = specifier_printf(spec, SIZE_MAX, specifier_table, NULL, NULL, &resolved); |
7429c8fe | 141 | if (s->specifier == 'm' && IN_SET(r, -EUNATCH, -ENOMEDIUM, -ENOPKG)) /* machine-id might be missing in build chroots */ |
0011d686 LB |
142 | continue; |
143 | assert_se(r >= 0); | |
b6c93a5a ZJS |
144 | |
145 | log_info("%%%c → %s", s->specifier, resolved); | |
146 | } | |
e82f30d1 LP |
147 | } |
148 | ||
9f7fcf80 FS |
149 | /* Bunch of specifiers that are not part of the common lists */ |
150 | TEST(specifiers_assorted) { | |
151 | const sd_id128_t id = SD_ID128_ALLF; | |
152 | const uint64_t llu = UINT64_MAX; | |
153 | const Specifier table[] = { | |
154 | /* Used in src/partition/repart.c */ | |
155 | { 'a', specifier_uuid, &id }, | |
156 | { 'b', specifier_uint64, &llu }, | |
157 | {} | |
158 | }; | |
159 | ||
160 | for (const Specifier *s = table; s->specifier; s++) { | |
161 | char spec[3]; | |
162 | _cleanup_free_ char *resolved = NULL; | |
163 | int r; | |
164 | ||
165 | xsprintf(spec, "%%%c", s->specifier); | |
166 | ||
167 | r = specifier_printf(spec, SIZE_MAX, table, NULL, NULL, &resolved); | |
168 | assert_se(r >= 0); | |
169 | ||
170 | log_info("%%%c → %s", s->specifier, resolved); | |
171 | } | |
172 | } | |
173 | ||
7962116f ZJS |
174 | TEST(specifiers_missing_data_ok) { |
175 | _cleanup_free_ char *resolved = NULL; | |
176 | ||
177 | assert_se(setenv("SYSTEMD_OS_RELEASE", "/dev/null", 1) == 0); | |
178 | assert_se(specifier_printf("%A-%B-%M-%o-%w-%W", SIZE_MAX, specifier_table, NULL, NULL, &resolved) >= 0); | |
179 | assert_se(streq(resolved, "-----")); | |
180 | ||
181 | assert_se(setenv("SYSTEMD_OS_RELEASE", "/nosuchfileordirectory", 1) == 0); | |
6ec4c852 | 182 | assert_se(specifier_printf("%A-%B-%M-%o-%w-%W", SIZE_MAX, specifier_table, NULL, NULL, &resolved) == -EUNATCH); |
7962116f ZJS |
183 | assert_se(streq(resolved, "-----")); |
184 | ||
185 | assert_se(unsetenv("SYSTEMD_OS_RELEASE") == 0); | |
186 | } | |
187 | ||
4f7452a8 | 188 | DEFINE_TEST_MAIN(LOG_DEBUG); |