]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-unit-name.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2012 Lennart Poettering
7 Copyright 2013 Zbigniew Jędrzejewski-Szmek
8 Copyright 2014 Ronny Chevalier
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.
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.
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/>.
29 #include "alloc-util.h"
30 #include "hostname-util.h"
33 #include "path-util.h"
34 #include "specifier.h"
35 #include "string-util.h"
36 #include "test-helper.h"
37 #include "unit-name.h"
38 #include "unit-printf.h"
42 static void test_unit_name_is_valid(void) {
43 assert_se(unit_name_is_valid("foo.service", UNIT_NAME_ANY
));
44 assert_se(unit_name_is_valid("foo.service", UNIT_NAME_PLAIN
));
45 assert_se(!unit_name_is_valid("foo.service", UNIT_NAME_INSTANCE
));
46 assert_se(!unit_name_is_valid("foo.service", UNIT_NAME_TEMPLATE
));
47 assert_se(!unit_name_is_valid("foo.service", UNIT_NAME_INSTANCE
|UNIT_NAME_TEMPLATE
));
49 assert_se(unit_name_is_valid("foo@bar.service", UNIT_NAME_ANY
));
50 assert_se(!unit_name_is_valid("foo@bar.service", UNIT_NAME_PLAIN
));
51 assert_se(unit_name_is_valid("foo@bar.service", UNIT_NAME_INSTANCE
));
52 assert_se(!unit_name_is_valid("foo@bar.service", UNIT_NAME_TEMPLATE
));
53 assert_se(unit_name_is_valid("foo@bar.service", UNIT_NAME_INSTANCE
|UNIT_NAME_TEMPLATE
));
55 assert_se(unit_name_is_valid("foo@.service", UNIT_NAME_ANY
));
56 assert_se(!unit_name_is_valid("foo@.service", UNIT_NAME_PLAIN
));
57 assert_se(!unit_name_is_valid("foo@.service", UNIT_NAME_INSTANCE
));
58 assert_se(unit_name_is_valid("foo@.service", UNIT_NAME_TEMPLATE
));
59 assert_se(unit_name_is_valid("foo@.service", UNIT_NAME_INSTANCE
|UNIT_NAME_TEMPLATE
));
61 assert_se(!unit_name_is_valid(".service", UNIT_NAME_ANY
));
62 assert_se(!unit_name_is_valid("", UNIT_NAME_ANY
));
63 assert_se(!unit_name_is_valid("foo.waldo", UNIT_NAME_ANY
));
64 assert_se(!unit_name_is_valid("@.service", UNIT_NAME_ANY
));
65 assert_se(!unit_name_is_valid("@piep.service", UNIT_NAME_ANY
));
68 static void test_u_n_r_i_one(const char *pattern
, const char *repl
, const char *expected
, int ret
) {
69 _cleanup_free_
char *t
= NULL
;
70 assert_se(unit_name_replace_instance(pattern
, repl
, &t
) == ret
);
72 assert_se(streq_ptr(t
, expected
));
75 static void test_u_n_r_i(void) {
76 puts("-------------------------------------------------");
77 test_u_n_r_i_one("foo@.service", "waldo", "foo@waldo.service", 0);
78 test_u_n_r_i_one("foo@xyz.service", "waldo", "foo@waldo.service", 0);
79 test_u_n_r_i_one("xyz", "waldo", NULL
, -EINVAL
);
80 test_u_n_r_i_one("", "waldo", NULL
, -EINVAL
);
81 test_u_n_r_i_one("foo.service", "waldo", NULL
, -EINVAL
);
82 test_u_n_r_i_one(".service", "waldo", NULL
, -EINVAL
);
83 test_u_n_r_i_one("foo@", "waldo", NULL
, -EINVAL
);
84 test_u_n_r_i_one("@bar", "waldo", NULL
, -EINVAL
);
87 static void test_u_n_f_p_one(const char *path
, const char *suffix
, const char *expected
, int ret
) {
88 _cleanup_free_
char *t
= NULL
;
90 assert_se(unit_name_from_path(path
, suffix
, &t
) == ret
);
92 assert_se(streq_ptr(t
, expected
));
95 _cleanup_free_
char *k
= NULL
;
96 assert_se(unit_name_to_path(t
, &k
) == 0);
98 assert_se(path_equal(k
, isempty(path
) ? "/" : path
));
102 static void test_u_n_f_p(void) {
103 puts("-------------------------------------------------");
104 test_u_n_f_p_one("/waldo", ".mount", "waldo.mount", 0);
105 test_u_n_f_p_one("/waldo/quuix", ".mount", "waldo-quuix.mount", 0);
106 test_u_n_f_p_one("/waldo/quuix/", ".mount", "waldo-quuix.mount", 0);
107 test_u_n_f_p_one("", ".mount", "-.mount", 0);
108 test_u_n_f_p_one("/", ".mount", "-.mount", 0);
109 test_u_n_f_p_one("///", ".mount", "-.mount", 0);
110 test_u_n_f_p_one("/foo/../bar", ".mount", NULL
, -EINVAL
);
111 test_u_n_f_p_one("/foo/./bar", ".mount", NULL
, -EINVAL
);
114 static void test_u_n_f_p_i_one(const char *pattern
, const char *path
, const char *suffix
, const char *expected
, int ret
) {
115 _cleanup_free_
char *t
= NULL
;
117 assert_se(unit_name_from_path_instance(pattern
, path
, suffix
, &t
) == ret
);
119 assert_se(streq_ptr(t
, expected
));
122 _cleanup_free_
char *k
= NULL
, *v
= NULL
;
124 assert_se(unit_name_to_instance(t
, &k
) > 0);
125 assert_se(unit_name_path_unescape(k
, &v
) == 0);
126 assert_se(path_equal(v
, isempty(path
) ? "/" : path
));
130 static void test_u_n_f_p_i(void) {
131 puts("-------------------------------------------------");
133 test_u_n_f_p_i_one("waldo", "/waldo", ".mount", "waldo@waldo.mount", 0);
134 test_u_n_f_p_i_one("waldo", "/waldo////quuix////", ".mount", "waldo@waldo-quuix.mount", 0);
135 test_u_n_f_p_i_one("waldo", "/", ".mount", "waldo@-.mount", 0);
136 test_u_n_f_p_i_one("waldo", "", ".mount", "waldo@-.mount", 0);
137 test_u_n_f_p_i_one("waldo", "///", ".mount", "waldo@-.mount", 0);
138 test_u_n_f_p_i_one("waldo", "..", ".mount", NULL
, -EINVAL
);
139 test_u_n_f_p_i_one("waldo", "/foo", ".waldi", NULL
, -EINVAL
);
140 test_u_n_f_p_i_one("wa--ldo", "/--", ".mount", "wa--ldo@\\x2d\\x2d.mount", 0);
143 static void test_u_n_t_p_one(const char *unit
, const char *path
, int ret
) {
144 _cleanup_free_
char *p
= NULL
;
146 assert_se(unit_name_to_path(unit
, &p
) == ret
);
147 assert_se(streq_ptr(path
, p
));
150 static void test_u_n_t_p(void) {
151 test_u_n_t_p_one("home.mount", "/home", 0);
152 test_u_n_t_p_one("home-lennart.mount", "/home/lennart", 0);
153 test_u_n_t_p_one("home-lennart-.mount", NULL
, -EINVAL
);
154 test_u_n_t_p_one("-home-lennart.mount", NULL
, -EINVAL
);
155 test_u_n_t_p_one("-home--lennart.mount", NULL
, -EINVAL
);
156 test_u_n_t_p_one("home-..-lennart.mount", NULL
, -EINVAL
);
157 test_u_n_t_p_one("", NULL
, -EINVAL
);
158 test_u_n_t_p_one("home/foo", NULL
, -EINVAL
);
161 static void test_u_n_m_one(const char *pattern
, const char *expect
, int ret
) {
162 _cleanup_free_
char *t
= NULL
;
164 assert_se(unit_name_mangle(pattern
, UNIT_NAME_NOGLOB
, &t
) == ret
);
166 assert_se(streq_ptr(t
, expect
));
169 _cleanup_free_
char *k
= NULL
;
171 assert_se(unit_name_is_valid(t
, UNIT_NAME_ANY
));
173 assert_se(unit_name_mangle(t
, UNIT_NAME_NOGLOB
, &k
) == 0);
174 assert_se(streq_ptr(t
, k
));
178 static void test_u_n_m(void) {
179 puts("-------------------------------------------------");
180 test_u_n_m_one("foo.service", "foo.service", 0);
181 test_u_n_m_one("/home", "home.mount", 1);
182 test_u_n_m_one("/dev/sda", "dev-sda.device", 1);
183 test_u_n_m_one("üxknürz.service", "\\xc3\\xbcxkn\\xc3\\xbcrz.service", 1);
184 test_u_n_m_one("foobar-meh...waldi.service", "foobar-meh...waldi.service", 0);
185 test_u_n_m_one("_____####----.....service", "_____\\x23\\x23\\x23\\x23----.....service", 1);
186 test_u_n_m_one("_____##@;;;,,,##----.....service", "_____\\x23\\x23@\\x3b\\x3b\\x3b\\x2c\\x2c\\x2c\\x23\\x23----.....service", 1);
187 test_u_n_m_one("xxx@@@@/////\\\\\\\\\\yyy.service", "xxx@@@@-----\\\\\\\\\\yyy.service", 1);
188 test_u_n_m_one("", NULL
, -EINVAL
);
191 static int test_unit_printf(void) {
196 _cleanup_free_
char *mid
, *bid
, *host
, *root_uid
;
199 assert_se(specifier_machine_id('m', NULL
, NULL
, &mid
) >= 0 && mid
);
200 assert_se(specifier_boot_id('b', NULL
, NULL
, &bid
) >= 0 && bid
);
201 assert_se((host
= gethostname_malloc()));
203 assert_se((root
= getpwnam("root")));
204 assert_se(asprintf(&root_uid
, "%d", (int) root
->pw_uid
) > 0);
206 r
= manager_new(MANAGER_USER
, true, &m
);
207 if (r
== -EPERM
|| r
== -EACCES
|| r
== -EADDRINUSE
) {
208 puts("manager_new: Permission denied. Skipping test.");
209 return EXIT_TEST_SKIP
;
213 #define expect(unit, pattern, expected) \
216 _cleanup_free_ char *t = NULL; \
217 assert_se(unit_full_printf(unit, pattern, &t) >= 0); \
218 printf("result: %s\nexpect: %s\n", t, expected); \
219 if ((e = endswith(expected, "*"))) \
220 assert_se(strncmp(t, e, e-expected)); \
222 assert_se(streq(t, expected)); \
225 assert_se(setenv("USER", "root", 1) == 0);
226 assert_se(setenv("HOME", "/root", 1) == 0);
227 assert_se(setenv("XDG_RUNTIME_DIR", "/run/user/1/", 1) == 0);
229 assert_se(u
= unit_new(m
, sizeof(Service
)));
230 assert_se(unit_add_name(u
, "blah.service") == 0);
231 assert_se(unit_add_name(u
, "blah.service") == 0);
234 expect(u
, "%%", "%");
235 expect(u
, "%%s", "%s");
236 expect(u
, "%", ""); // REALLY?
239 expect(u
, "%n", "blah.service");
240 expect(u
, "%f", "/blah");
241 expect(u
, "%N", "blah");
242 expect(u
, "%p", "blah");
243 expect(u
, "%P", "blah");
245 expect(u
, "%u", root
->pw_name
);
246 expect(u
, "%U", root_uid
);
247 expect(u
, "%h", root
->pw_dir
);
248 expect(u
, "%m", mid
);
249 expect(u
, "%b", bid
);
250 expect(u
, "%H", host
);
251 expect(u
, "%t", "/run/user/*");
254 assert_se(u2
= unit_new(m
, sizeof(Service
)));
255 assert_se(unit_add_name(u2
, "blah@foo-foo.service") == 0);
256 assert_se(unit_add_name(u2
, "blah@foo-foo.service") == 0);
258 expect(u2
, "%n", "blah@foo-foo.service");
259 expect(u2
, "%N", "blah@foo-foo");
260 expect(u2
, "%f", "/foo/foo");
261 expect(u2
, "%p", "blah");
262 expect(u2
, "%P", "blah");
263 expect(u2
, "%i", "foo-foo");
264 expect(u2
, "%I", "foo/foo");
265 expect(u2
, "%u", root
->pw_name
);
266 expect(u2
, "%U", root_uid
);
267 expect(u2
, "%h", root
->pw_dir
);
268 expect(u2
, "%m", mid
);
269 expect(u2
, "%b", bid
);
270 expect(u2
, "%H", host
);
271 expect(u2
, "%t", "/run/user/*");
279 static void test_unit_instance_is_valid(void) {
280 assert_se(unit_instance_is_valid("fooBar"));
281 assert_se(unit_instance_is_valid("foo-bar"));
282 assert_se(unit_instance_is_valid("foo.stUff"));
283 assert_se(unit_instance_is_valid("fOo123.stuff"));
284 assert_se(unit_instance_is_valid("@f_oo123.Stuff"));
286 assert_se(!unit_instance_is_valid("$¢£"));
287 assert_se(!unit_instance_is_valid(""));
288 assert_se(!unit_instance_is_valid("foo bar"));
289 assert_se(!unit_instance_is_valid("foo/bar"));
292 static void test_unit_prefix_is_valid(void) {
293 assert_se(unit_prefix_is_valid("fooBar"));
294 assert_se(unit_prefix_is_valid("foo-bar"));
295 assert_se(unit_prefix_is_valid("foo.stUff"));
296 assert_se(unit_prefix_is_valid("fOo123.stuff"));
297 assert_se(unit_prefix_is_valid("foo123.Stuff"));
299 assert_se(!unit_prefix_is_valid("$¢£"));
300 assert_se(!unit_prefix_is_valid(""));
301 assert_se(!unit_prefix_is_valid("foo bar"));
302 assert_se(!unit_prefix_is_valid("foo/bar"));
303 assert_se(!unit_prefix_is_valid("@foo-bar"));
306 static void test_unit_name_change_suffix(void) {
309 assert_se(unit_name_change_suffix("foo.mount", ".service", &t
) == 0);
310 assert_se(streq(t
, "foo.service"));
313 assert_se(unit_name_change_suffix("foo@stuff.service", ".socket", &t
) == 0);
314 assert_se(streq(t
, "foo@stuff.socket"));
318 static void test_unit_name_build(void) {
321 assert_se(unit_name_build("foo", "bar", ".service", &t
) == 0);
322 assert_se(streq(t
, "foo@bar.service"));
325 assert_se(unit_name_build("fo0-stUff_b", "bar", ".mount", &t
) == 0);
326 assert_se(streq(t
, "fo0-stUff_b@bar.mount"));
329 assert_se(unit_name_build("foo", NULL
, ".service", &t
) == 0);
330 assert_se(streq(t
, "foo.service"));
334 static void test_slice_name_is_valid(void) {
335 assert_se(slice_name_is_valid("-.slice"));
336 assert_se(slice_name_is_valid("foo.slice"));
337 assert_se(slice_name_is_valid("foo-bar.slice"));
338 assert_se(slice_name_is_valid("foo-bar-baz.slice"));
339 assert_se(!slice_name_is_valid("-foo-bar-baz.slice"));
340 assert_se(!slice_name_is_valid("foo-bar-baz-.slice"));
341 assert_se(!slice_name_is_valid("-foo-bar-baz-.slice"));
342 assert_se(!slice_name_is_valid("foo-bar--baz.slice"));
343 assert_se(!slice_name_is_valid("foo--bar--baz.slice"));
344 assert_se(!slice_name_is_valid(".slice"));
345 assert_se(!slice_name_is_valid(""));
346 assert_se(!slice_name_is_valid("foo.service"));
349 static void test_build_subslice(void) {
353 assert_se(slice_build_subslice("-.slice", "foo", &a
) >= 0);
354 assert_se(slice_build_subslice(a
, "bar", &b
) >= 0);
356 assert_se(slice_build_subslice(b
, "barfoo", &a
) >= 0);
358 assert_se(slice_build_subslice(a
, "foobar", &b
) >= 0);
360 assert_se(streq(b
, "foo-bar-barfoo-foobar.slice"));
363 assert_se(slice_build_subslice("foo.service", "bar", &a
) < 0);
364 assert_se(slice_build_subslice("foo", "bar", &a
) < 0);
367 static void test_build_parent_slice_one(const char *name
, const char *expect
, int ret
) {
368 _cleanup_free_
char *s
= NULL
;
370 assert_se(slice_build_parent_slice(name
, &s
) == ret
);
371 assert_se(streq_ptr(s
, expect
));
374 static void test_build_parent_slice(void) {
375 test_build_parent_slice_one("-.slice", NULL
, 0);
376 test_build_parent_slice_one("foo.slice", "-.slice", 1);
377 test_build_parent_slice_one("foo-bar.slice", "foo.slice", 1);
378 test_build_parent_slice_one("foo-bar-baz.slice", "foo-bar.slice", 1);
379 test_build_parent_slice_one("foo-bar--baz.slice", NULL
, -EINVAL
);
380 test_build_parent_slice_one("-foo-bar.slice", NULL
, -EINVAL
);
381 test_build_parent_slice_one("foo-bar-.slice", NULL
, -EINVAL
);
382 test_build_parent_slice_one("foo-bar.service", NULL
, -EINVAL
);
383 test_build_parent_slice_one(".slice", NULL
, -EINVAL
);
386 static void test_unit_name_to_instance(void) {
390 r
= unit_name_to_instance("foo@bar.service", &instance
);
392 assert_se(streq(instance
, "bar"));
395 r
= unit_name_to_instance("foo@.service", &instance
);
397 assert_se(streq(instance
, ""));
400 r
= unit_name_to_instance("fo0-stUff_b@b.service", &instance
);
402 assert_se(streq(instance
, "b"));
405 r
= unit_name_to_instance("foo.service", &instance
);
407 assert_se(!instance
);
409 r
= unit_name_to_instance("fooj@unk", &instance
);
412 r
= unit_name_to_instance("foo@", &instance
);
416 static void test_unit_name_escape(void) {
417 _cleanup_free_
char *r
;
419 r
= unit_name_escape("ab+-c.a/bc@foo.service");
421 assert_se(streq(r
, "ab\\x2b\\x2dc.a-bc\\x40foo.service"));
425 static void test_u_n_t_one(const char *name
, const char *expected
, int ret
) {
426 _cleanup_free_
char *f
= NULL
;
428 assert_se(unit_name_template(name
, &f
) == ret
);
429 printf("got: %s, expected: %s\n", strna(f
), strna(expected
));
430 assert_se(streq_ptr(f
, expected
));
433 static void test_unit_name_template(void) {
434 test_u_n_t_one("foo@bar.service", "foo@.service", 0);
435 test_u_n_t_one("foo.mount", NULL
, -EINVAL
);
438 static void test_unit_name_path_unescape_one(const char *name
, const char *path
, int ret
) {
439 _cleanup_free_
char *p
= NULL
;
441 assert_se(unit_name_path_unescape(name
, &p
) == ret
);
442 assert_se(streq_ptr(path
, p
));
445 static void test_unit_name_path_unescape(void) {
447 test_unit_name_path_unescape_one("foo", "/foo", 0);
448 test_unit_name_path_unescape_one("foo-bar", "/foo/bar", 0);
449 test_unit_name_path_unescape_one("foo-.bar", "/foo/.bar", 0);
450 test_unit_name_path_unescape_one("foo-bar-baz", "/foo/bar/baz", 0);
451 test_unit_name_path_unescape_one("-", "/", 0);
452 test_unit_name_path_unescape_one("--", NULL
, -EINVAL
);
453 test_unit_name_path_unescape_one("-foo-bar", NULL
, -EINVAL
);
454 test_unit_name_path_unescape_one("foo--bar", NULL
, -EINVAL
);
455 test_unit_name_path_unescape_one("foo-bar-", NULL
, -EINVAL
);
456 test_unit_name_path_unescape_one(".-bar", NULL
, -EINVAL
);
457 test_unit_name_path_unescape_one("foo-..", NULL
, -EINVAL
);
458 test_unit_name_path_unescape_one("", NULL
, -EINVAL
);
461 int main(int argc
, char* argv
[]) {
463 test_unit_name_is_valid();
469 TEST_REQ_RUNNING_SYSTEMD(rc
= test_unit_printf());
470 test_unit_instance_is_valid();
471 test_unit_prefix_is_valid();
472 test_unit_name_change_suffix();
473 test_unit_name_build();
474 test_slice_name_is_valid();
475 test_build_subslice();
476 test_build_parent_slice();
477 test_unit_name_to_instance();
478 test_unit_name_escape();
479 test_unit_name_template();
480 test_unit_name_path_unescape();