]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/test/test-unit-name.c
util: be a bit safer in path_is_safe()
[thirdparty/systemd.git] / src / test / test-unit-name.c
CommitLineData
b0193f1c
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2012 Lennart Poettering
1682ff60 7 Copyright 2013 Zbigniew Jędrzejewski-Szmek
068ae9fb 8 Copyright 2014 Ronny Chevalier
b0193f1c
LP
9
10 systemd is free software; you can redistribute it and/or modify it
11 under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
14
15 systemd is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
19
20 You should have received a copy of the GNU Lesser General Public License
21 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22***/
23
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
1682ff60 27#include <pwd.h>
b0193f1c 28
1682ff60
ZJS
29#include "manager.h"
30#include "unit.h"
b0193f1c 31#include "unit-name.h"
1682ff60 32#include "unit-printf.h"
1682ff60 33#include "specifier.h"
b0193f1c 34#include "util.h"
1682ff60 35#include "macro.h"
143bfdaf 36#include "test-helper.h"
b0193f1c 37
1682ff60 38static void test_replacements(void) {
3251c0d2
ZJS
39#define expect(pattern, repl, expected) \
40 { \
7fd1b19b 41 _cleanup_free_ char *t = \
3251c0d2
ZJS
42 unit_name_replace_instance(pattern, repl); \
43 puts(t); \
bdf7026e 44 assert_se(streq(t, expected)); \
3251c0d2
ZJS
45 }
46
47 expect("foo@.service", "waldo", "foo@waldo.service");
48 expect("foo@xyz.service", "waldo", "foo@waldo.service");
49 expect("xyz", "waldo", "xyz");
50 expect("", "waldo", "");
51 expect("foo.service", "waldo", "foo.service");
52 expect(".service", "waldo", ".service");
53 expect("foo@", "waldo", "foo@waldo");
54 expect("@bar", "waldo", "@waldo");
55
56 puts("-------------------------------------------------");
57#undef expect
58#define expect(path, suffix, expected) \
59 { \
7fd1b19b 60 _cleanup_free_ char *k, *t = \
3251c0d2
ZJS
61 unit_name_from_path(path, suffix); \
62 puts(t); \
63 k = unit_name_to_path(t); \
64 puts(k); \
bdf7026e 65 assert_se(streq(k, expected ? expected : path)); \
3251c0d2
ZJS
66 }
67
68 expect("/waldo", ".mount", NULL);
69 expect("/waldo/quuix", ".mount", NULL);
70 expect("/waldo/quuix/", ".mount", "/waldo/quuix");
71 expect("/", ".mount", NULL);
72 expect("///", ".mount", "/");
73
74 puts("-------------------------------------------------");
75#undef expect
f78e6385
ZJS
76#define expect(pattern, path, suffix, expected) \
77 { \
78 _cleanup_free_ char *t = \
3251c0d2 79 unit_name_from_path_instance(pattern, path, suffix); \
f78e6385 80 puts(t); \
bdf7026e 81 assert_se(streq(t, expected)); \
3251c0d2
ZJS
82 }
83
84 expect("waldo", "/waldo", ".mount", "waldo@waldo.mount");
85 expect("waldo", "/waldo////quuix////", ".mount", "waldo@waldo-quuix.mount");
86 expect("waldo", "/", ".mount", "waldo@-.mount");
87 expect("wa--ldo", "/--", ".mount", "wa--ldo@\\x2d\\x2d.mount");
88
89 puts("-------------------------------------------------");
90#undef expect
f78e6385
ZJS
91#define expect(pattern) \
92 { \
93 _cleanup_free_ char *k, *t; \
94 assert_se(t = unit_name_mangle(pattern, MANGLE_NOGLOB)); \
95 assert_se(k = unit_name_mangle(t, MANGLE_NOGLOB)); \
96 puts(t); \
97 assert_se(streq(t, k)); \
3251c0d2
ZJS
98 }
99
100 expect("/home");
101 expect("/dev/sda");
102 expect("üxknürz.service");
103 expect("foobar-meh...waldi.service");
104 expect("_____####----.....service");
105 expect("_____##@;;;,,,##----.....service");
106 expect("xxx@@@@/////\\\\\\\\\\yyy.service");
b0193f1c 107
1682ff60
ZJS
108#undef expect
109}
110
49e5de64 111static int test_unit_printf(void) {
39883f62 112 Manager *m = NULL;
1682ff60 113 Unit *u, *u2;
c5e33bf8 114 int r;
1682ff60 115
7fd1b19b 116 _cleanup_free_ char *mid, *bid, *host, *root_uid;
1682ff60
ZJS
117 struct passwd *root;
118
19f6d710
LP
119 assert_se(specifier_machine_id('m', NULL, NULL, &mid) >= 0 && mid);
120 assert_se(specifier_boot_id('b', NULL, NULL, &bid) >= 0 && bid);
1682ff60
ZJS
121 assert_se((host = gethostname_malloc()));
122
123 assert_se((root = getpwnam("root")));
124 assert_se(asprintf(&root_uid, "%d", (int) root->pw_uid) > 0);
125
0d8c31ff 126 r = manager_new(SYSTEMD_USER, true, &m);
a454d241 127 if (r == -EPERM || r == -EACCES || r == -EADDRINUSE) {
c5e33bf8 128 puts("manager_new: Permission denied. Skipping test.");
49e5de64 129 return EXIT_TEST_SKIP;
c5e33bf8 130 }
bdf7026e 131 assert_se(r == 0);
1682ff60
ZJS
132
133#define expect(unit, pattern, expected) \
134 { \
fa3cd739 135 char *e; \
e1ba963f 136 _cleanup_free_ char *t = NULL; \
19f6d710 137 assert_se(unit_full_printf(unit, pattern, &t) >= 0); \
c5e33bf8 138 printf("result: %s\nexpect: %s\n", t, expected); \
fa3cd739 139 if ((e = endswith(expected, "*"))) \
bdf7026e 140 assert_se(strncmp(t, e, e-expected)); \
fa3cd739 141 else \
bdf7026e 142 assert_se(streq(t, expected)); \
1682ff60
ZJS
143 }
144
145 assert_se(setenv("USER", "root", 1) == 0);
146 assert_se(setenv("HOME", "/root", 1) == 0);
6dbfd104 147 assert_se(setenv("XDG_RUNTIME_DIR", "/run/user/1/", 1) == 0);
1682ff60
ZJS
148
149 assert_se(u = unit_new(m, sizeof(Service)));
150 assert_se(unit_add_name(u, "blah.service") == 0);
151 assert_se(unit_add_name(u, "blah.service") == 0);
152
153 /* general tests */
154 expect(u, "%%", "%");
155 expect(u, "%%s", "%s");
156 expect(u, "%", ""); // REALLY?
157
158 /* normal unit */
159 expect(u, "%n", "blah.service");
14b0295f 160 expect(u, "%f", "/blah");
1682ff60
ZJS
161 expect(u, "%N", "blah");
162 expect(u, "%p", "blah");
163 expect(u, "%P", "blah");
164 expect(u, "%i", "");
1682ff60
ZJS
165 expect(u, "%u", root->pw_name);
166 expect(u, "%U", root_uid);
167 expect(u, "%h", root->pw_dir);
1682ff60
ZJS
168 expect(u, "%m", mid);
169 expect(u, "%b", bid);
170 expect(u, "%H", host);
fa3cd739 171 expect(u, "%t", "/run/user/*");
1682ff60
ZJS
172
173 /* templated */
174 assert_se(u2 = unit_new(m, sizeof(Service)));
175 assert_se(unit_add_name(u2, "blah@foo-foo.service") == 0);
176 assert_se(unit_add_name(u2, "blah@foo-foo.service") == 0);
177
178 expect(u2, "%n", "blah@foo-foo.service");
179 expect(u2, "%N", "blah@foo-foo");
14b0295f 180 expect(u2, "%f", "/foo/foo");
1682ff60
ZJS
181 expect(u2, "%p", "blah");
182 expect(u2, "%P", "blah");
183 expect(u2, "%i", "foo-foo");
184 expect(u2, "%I", "foo/foo");
185 expect(u2, "%u", root->pw_name);
186 expect(u2, "%U", root_uid);
187 expect(u2, "%h", root->pw_dir);
1682ff60
ZJS
188 expect(u2, "%m", mid);
189 expect(u2, "%b", bid);
190 expect(u2, "%H", host);
fa3cd739 191 expect(u2, "%t", "/run/user/*");
49e5de64 192
b463b813 193 manager_free(m);
fee0a921 194#undef expect
b463b813 195
49e5de64 196 return 0;
1682ff60
ZJS
197}
198
068ae9fb
RC
199static void test_unit_instance_is_valid(void) {
200 assert_se(unit_instance_is_valid("fooBar"));
201 assert_se(unit_instance_is_valid("foo-bar"));
202 assert_se(unit_instance_is_valid("foo.stUff"));
203 assert_se(unit_instance_is_valid("fOo123.stuff"));
204 assert_se(unit_instance_is_valid("@f_oo123.Stuff"));
205
206 assert_se(!unit_instance_is_valid("$¢£"));
207 assert_se(!unit_instance_is_valid(""));
208 assert_se(!unit_instance_is_valid("foo bar"));
209 assert_se(!unit_instance_is_valid("foo/bar"));
210}
211
212static void test_unit_prefix_is_valid(void) {
213 assert_se(unit_prefix_is_valid("fooBar"));
214 assert_se(unit_prefix_is_valid("foo-bar"));
215 assert_se(unit_prefix_is_valid("foo.stUff"));
216 assert_se(unit_prefix_is_valid("fOo123.stuff"));
217 assert_se(unit_prefix_is_valid("foo123.Stuff"));
218
219 assert_se(!unit_prefix_is_valid("$¢£"));
220 assert_se(!unit_prefix_is_valid(""));
221 assert_se(!unit_prefix_is_valid("foo bar"));
222 assert_se(!unit_prefix_is_valid("foo/bar"));
223 assert_se(!unit_prefix_is_valid("@foo-bar"));
224}
225
226static void test_unit_name_change_suffix(void) {
227 char *r;
228
229 r = unit_name_change_suffix("foo.bar", ".service");
230 assert_se(r);
231 assert_se(streq(r, "foo.service"));
232 free(r);
233
234 r = unit_name_change_suffix("foo@stuff.bar", ".boo");
235 assert_se(r);
236 assert_se(streq(r, "foo@stuff.boo"));
237 free(r);
238}
239
240static void test_unit_name_build(void) {
241 char *r;
242
243 r = unit_name_build("foo", "bar", ".service");
244 assert_se(r);
245 assert_se(streq(r, "foo@bar.service"));
246 free(r);
247
248 r = unit_name_build("fo0-stUff_b", "bar", ".mount");
249 assert_se(r);
250 assert_se(streq(r, "fo0-stUff_b@bar.mount"));
251 free(r);
252
253 r = unit_name_build("foo", NULL, ".service");
254 assert_se(r);
255 assert_se(streq(r, "foo.service"));
256 free(r);
257}
258
259static void test_unit_name_is_instance(void) {
260 assert_se(unit_name_is_instance("a@b.service"));
261 assert_se(unit_name_is_instance("a-c_c01Aj@b05Dii_-oioi.service"));
262
263 assert_se(!unit_name_is_instance("a.service"));
fee0a921 264 assert_se(!unit_name_is_instance("a@.service"));
068ae9fb
RC
265 assert_se(!unit_name_is_instance("junk"));
266 assert_se(!unit_name_is_instance(""));
267}
268
269static void test_build_subslice(void) {
270 char *a;
271 char *b;
272
273 assert_se(build_subslice("-.slice", "foo", &a) >= 0);
274 assert_se(build_subslice(a, "bar", &b) >= 0);
275 free(a);
276 assert_se(build_subslice(b, "barfoo", &a) >= 0);
277 free(b);
278 assert_se(build_subslice(a, "foobar", &b) >= 0);
279 free(a);
280 assert_se(streq(b, "foo-bar-barfoo-foobar.slice"));
281 free(b);
282
283 assert_se(build_subslice("foo.service", "bar", &a) < 0);
284 assert_se(build_subslice("foo", "bar", &a) < 0);
285}
286
287static void test_unit_name_to_instance(void) {
288 char *instance;
289 int r;
290
291 r = unit_name_to_instance("foo@bar.service", &instance);
292 assert_se(r >= 0);
293 assert_se(streq(instance, "bar"));
294 free(instance);
295
fee0a921
RC
296 r = unit_name_to_instance("foo@.service", &instance);
297 assert_se(r >= 0);
298 assert_se(streq(instance, ""));
299 free(instance);
300
068ae9fb
RC
301 r = unit_name_to_instance("fo0-stUff_b@b.e", &instance);
302 assert_se(r >= 0);
303 assert_se(streq(instance, "b"));
304 free(instance);
305
306 r = unit_name_to_instance("foo.bar", &instance);
307 assert_se(r >= 0);
308 assert_se(!instance);
309
310 r = unit_name_to_instance("fooj@unk", &instance);
311 assert_se(r < 0);
fee0a921
RC
312
313 r = unit_name_to_instance("foo@", &instance);
314 assert_se(r < 0);
068ae9fb
RC
315}
316
317static void test_unit_name_escape(void) {
318 _cleanup_free_ char *r;
319
320 r = unit_name_escape("ab+-c.a/bc@foo.service");
321 assert_se(r);
322 assert_se(streq(r, "ab\\x2b\\x2dc.a-bc\\x40foo.service"));
323}
324
fee0a921
RC
325static void test_unit_name_template(void) {
326#define expect(name, expected) \
327 { \
328 _cleanup_free_ char *f = NULL; \
329 f = unit_name_template(name); \
330 assert_se(f); \
331 printf("got: %s, expected: %s\n", f, expected); \
332 assert_se(streq(f, expected)); \
333 }
334 expect("foo@bar.service", "foo@.service")
335 expect("foo.mount", "foo.mount")
336#undef expect
337}
338
339static void test_unit_name_is_template(void) {
340 assert_se(unit_name_is_template("foo@.service"));
341 assert_se(unit_name_is_template("bar@.path"));
342
343 assert_se(!unit_name_is_template("bar@i.mount"));
344 assert_se(!unit_name_is_template("bar@foobbbb.service"));
345 assert_se(!unit_name_is_template("barfoo.service"));
346}
347
1682ff60 348int main(int argc, char* argv[]) {
143bfdaf 349 int rc = 0;
1682ff60 350 test_replacements();
143bfdaf 351 TEST_REQ_RUNNING_SYSTEMD(rc = test_unit_printf());
068ae9fb
RC
352 test_unit_instance_is_valid();
353 test_unit_prefix_is_valid();
354 test_unit_name_change_suffix();
355 test_unit_name_build();
356 test_unit_name_is_instance();
357 test_build_subslice();
358 test_unit_name_to_instance();
359 test_unit_name_escape();
fee0a921
RC
360 test_unit_name_template();
361 test_unit_name_is_template();
068ae9fb 362
143bfdaf 363 return rc;
b0193f1c 364}