]>
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"
40 #include "user-util.h"
43 static void test_unit_name_is_valid(void) {
44 assert_se(unit_name_is_valid("foo.service", UNIT_NAME_ANY
));
45 assert_se(unit_name_is_valid("foo.service", UNIT_NAME_PLAIN
));
46 assert_se(!unit_name_is_valid("foo.service", UNIT_NAME_INSTANCE
));
47 assert_se(!unit_name_is_valid("foo.service", UNIT_NAME_TEMPLATE
));
48 assert_se(!unit_name_is_valid("foo.service", UNIT_NAME_INSTANCE
|UNIT_NAME_TEMPLATE
));
50 assert_se(unit_name_is_valid("foo@bar.service", UNIT_NAME_ANY
));
51 assert_se(!unit_name_is_valid("foo@bar.service", UNIT_NAME_PLAIN
));
52 assert_se(unit_name_is_valid("foo@bar.service", UNIT_NAME_INSTANCE
));
53 assert_se(!unit_name_is_valid("foo@bar.service", UNIT_NAME_TEMPLATE
));
54 assert_se(unit_name_is_valid("foo@bar.service", UNIT_NAME_INSTANCE
|UNIT_NAME_TEMPLATE
));
56 assert_se(unit_name_is_valid("foo@.service", UNIT_NAME_ANY
));
57 assert_se(!unit_name_is_valid("foo@.service", UNIT_NAME_PLAIN
));
58 assert_se(!unit_name_is_valid("foo@.service", UNIT_NAME_INSTANCE
));
59 assert_se(unit_name_is_valid("foo@.service", UNIT_NAME_TEMPLATE
));
60 assert_se(unit_name_is_valid("foo@.service", UNIT_NAME_INSTANCE
|UNIT_NAME_TEMPLATE
));
62 assert_se(!unit_name_is_valid(".service", UNIT_NAME_ANY
));
63 assert_se(!unit_name_is_valid("", UNIT_NAME_ANY
));
64 assert_se(!unit_name_is_valid("foo.waldo", UNIT_NAME_ANY
));
65 assert_se(!unit_name_is_valid("@.service", UNIT_NAME_ANY
));
66 assert_se(!unit_name_is_valid("@piep.service", UNIT_NAME_ANY
));
69 static void test_u_n_r_i_one(const char *pattern
, const char *repl
, const char *expected
, int ret
) {
70 _cleanup_free_
char *t
= NULL
;
71 assert_se(unit_name_replace_instance(pattern
, repl
, &t
) == ret
);
73 assert_se(streq_ptr(t
, expected
));
76 static void test_u_n_r_i(void) {
77 puts("-------------------------------------------------");
78 test_u_n_r_i_one("foo@.service", "waldo", "foo@waldo.service", 0);
79 test_u_n_r_i_one("foo@xyz.service", "waldo", "foo@waldo.service", 0);
80 test_u_n_r_i_one("xyz", "waldo", NULL
, -EINVAL
);
81 test_u_n_r_i_one("", "waldo", NULL
, -EINVAL
);
82 test_u_n_r_i_one("foo.service", "waldo", NULL
, -EINVAL
);
83 test_u_n_r_i_one(".service", "waldo", NULL
, -EINVAL
);
84 test_u_n_r_i_one("foo@", "waldo", NULL
, -EINVAL
);
85 test_u_n_r_i_one("@bar", "waldo", NULL
, -EINVAL
);
88 static void test_u_n_f_p_one(const char *path
, const char *suffix
, const char *expected
, int ret
) {
89 _cleanup_free_
char *t
= NULL
;
91 assert_se(unit_name_from_path(path
, suffix
, &t
) == ret
);
93 assert_se(streq_ptr(t
, expected
));
96 _cleanup_free_
char *k
= NULL
;
97 assert_se(unit_name_to_path(t
, &k
) == 0);
99 assert_se(path_equal(k
, isempty(path
) ? "/" : path
));
103 static void test_u_n_f_p(void) {
104 puts("-------------------------------------------------");
105 test_u_n_f_p_one("/waldo", ".mount", "waldo.mount", 0);
106 test_u_n_f_p_one("/waldo/quuix", ".mount", "waldo-quuix.mount", 0);
107 test_u_n_f_p_one("/waldo/quuix/", ".mount", "waldo-quuix.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("///", ".mount", "-.mount", 0);
111 test_u_n_f_p_one("/foo/../bar", ".mount", NULL
, -EINVAL
);
112 test_u_n_f_p_one("/foo/./bar", ".mount", NULL
, -EINVAL
);
115 static void test_u_n_f_p_i_one(const char *pattern
, const char *path
, const char *suffix
, const char *expected
, int ret
) {
116 _cleanup_free_
char *t
= NULL
;
118 assert_se(unit_name_from_path_instance(pattern
, path
, suffix
, &t
) == ret
);
120 assert_se(streq_ptr(t
, expected
));
123 _cleanup_free_
char *k
= NULL
, *v
= NULL
;
125 assert_se(unit_name_to_instance(t
, &k
) > 0);
126 assert_se(unit_name_path_unescape(k
, &v
) == 0);
127 assert_se(path_equal(v
, isempty(path
) ? "/" : path
));
131 static void test_u_n_f_p_i(void) {
132 puts("-------------------------------------------------");
134 test_u_n_f_p_i_one("waldo", "/waldo", ".mount", "waldo@waldo.mount", 0);
135 test_u_n_f_p_i_one("waldo", "/waldo////quuix////", ".mount", "waldo@waldo-quuix.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", "waldo@-.mount", 0);
139 test_u_n_f_p_i_one("waldo", "..", ".mount", NULL
, -EINVAL
);
140 test_u_n_f_p_i_one("waldo", "/foo", ".waldi", NULL
, -EINVAL
);
141 test_u_n_f_p_i_one("wa--ldo", "/--", ".mount", "wa--ldo@\\x2d\\x2d.mount", 0);
144 static void test_u_n_t_p_one(const char *unit
, const char *path
, int ret
) {
145 _cleanup_free_
char *p
= NULL
;
147 assert_se(unit_name_to_path(unit
, &p
) == ret
);
148 assert_se(streq_ptr(path
, p
));
151 static void test_u_n_t_p(void) {
152 test_u_n_t_p_one("home.mount", "/home", 0);
153 test_u_n_t_p_one("home-lennart.mount", "/home/lennart", 0);
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("home-..-lennart.mount", NULL
, -EINVAL
);
158 test_u_n_t_p_one("", NULL
, -EINVAL
);
159 test_u_n_t_p_one("home/foo", NULL
, -EINVAL
);
162 static void test_u_n_m_one(const char *pattern
, const char *expect
, int ret
) {
163 _cleanup_free_
char *t
= NULL
;
165 assert_se(unit_name_mangle(pattern
, UNIT_NAME_NOGLOB
, &t
) == ret
);
167 assert_se(streq_ptr(t
, expect
));
170 _cleanup_free_
char *k
= NULL
;
172 assert_se(unit_name_is_valid(t
, UNIT_NAME_ANY
));
174 assert_se(unit_name_mangle(t
, UNIT_NAME_NOGLOB
, &k
) == 0);
175 assert_se(streq_ptr(t
, k
));
179 static void test_u_n_m(void) {
180 puts("-------------------------------------------------");
181 test_u_n_m_one("foo.service", "foo.service", 0);
182 test_u_n_m_one("/home", "home.mount", 1);
183 test_u_n_m_one("/dev/sda", "dev-sda.device", 1);
184 test_u_n_m_one("üxknürz.service", "\\xc3\\xbcxkn\\xc3\\xbcrz.service", 1);
185 test_u_n_m_one("foobar-meh...waldi.service", "foobar-meh...waldi.service", 0);
186 test_u_n_m_one("_____####----.....service", "_____\\x23\\x23\\x23\\x23----.....service", 1);
187 test_u_n_m_one("_____##@;;;,,,##----.....service", "_____\\x23\\x23@\\x3b\\x3b\\x3b\\x2c\\x2c\\x2c\\x23\\x23----.....service", 1);
188 test_u_n_m_one("xxx@@@@/////\\\\\\\\\\yyy.service", "xxx@@@@-----\\\\\\\\\\yyy.service", 1);
189 test_u_n_m_one("", NULL
, -EINVAL
);
192 static int test_unit_printf(void) {
197 _cleanup_free_
char *mid
= NULL
, *bid
= NULL
, *host
= NULL
, *uid
= NULL
, *user
= NULL
, *shell
= NULL
, *home
= NULL
;
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());
202 assert_se(user
= getusername_malloc());
203 assert_se(asprintf(&uid
, UID_FMT
, getuid()));
204 assert_se(get_home_dir(&home
) >= 0);
205 assert_se(get_shell(&shell
) >= 0);
207 r
= manager_new(MANAGER_USER
, true, &m
);
208 if (r
== -EPERM
|| r
== -EACCES
|| r
== -EADDRINUSE
) {
209 puts("manager_new: Permission denied. Skipping test.");
210 return EXIT_TEST_SKIP
;
214 #define expect(unit, pattern, expected) \
217 _cleanup_free_ char *t = NULL; \
218 assert_se(unit_full_printf(unit, pattern, &t) >= 0); \
219 printf("result: %s\nexpect: %s\n", t, expected); \
220 if ((e = endswith(expected, "*"))) \
221 assert_se(strncmp(t, e, e-expected)); \
223 assert_se(streq(t, expected)); \
226 assert_se(setenv("XDG_RUNTIME_DIR", "/run/user/1/", 1) == 0);
228 assert_se(u
= unit_new(m
, sizeof(Service
)));
229 assert_se(unit_add_name(u
, "blah.service") == 0);
230 assert_se(unit_add_name(u
, "blah.service") == 0);
233 expect(u
, "%%", "%");
234 expect(u
, "%%s", "%s");
235 expect(u
, "%", ""); // REALLY?
238 expect(u
, "%n", "blah.service");
239 expect(u
, "%f", "/blah");
240 expect(u
, "%N", "blah");
241 expect(u
, "%p", "blah");
242 expect(u
, "%P", "blah");
244 expect(u
, "%u", user
);
245 expect(u
, "%U", uid
);
246 expect(u
, "%h", home
);
247 expect(u
, "%m", mid
);
248 expect(u
, "%b", bid
);
249 expect(u
, "%H", host
);
250 expect(u
, "%t", "/run/user/*");
253 assert_se(u2
= unit_new(m
, sizeof(Service
)));
254 assert_se(unit_add_name(u2
, "blah@foo-foo.service") == 0);
255 assert_se(unit_add_name(u2
, "blah@foo-foo.service") == 0);
257 expect(u2
, "%n", "blah@foo-foo.service");
258 expect(u2
, "%N", "blah@foo-foo");
259 expect(u2
, "%f", "/foo/foo");
260 expect(u2
, "%p", "blah");
261 expect(u2
, "%P", "blah");
262 expect(u2
, "%i", "foo-foo");
263 expect(u2
, "%I", "foo/foo");
264 expect(u2
, "%u", user
);
265 expect(u2
, "%U", uid
);
266 expect(u2
, "%h", home
);
267 expect(u2
, "%m", mid
);
268 expect(u2
, "%b", bid
);
269 expect(u2
, "%H", host
);
270 expect(u2
, "%t", "/run/user/*");
278 static void test_unit_instance_is_valid(void) {
279 assert_se(unit_instance_is_valid("fooBar"));
280 assert_se(unit_instance_is_valid("foo-bar"));
281 assert_se(unit_instance_is_valid("foo.stUff"));
282 assert_se(unit_instance_is_valid("fOo123.stuff"));
283 assert_se(unit_instance_is_valid("@f_oo123.Stuff"));
285 assert_se(!unit_instance_is_valid("$¢£"));
286 assert_se(!unit_instance_is_valid(""));
287 assert_se(!unit_instance_is_valid("foo bar"));
288 assert_se(!unit_instance_is_valid("foo/bar"));
291 static void test_unit_prefix_is_valid(void) {
292 assert_se(unit_prefix_is_valid("fooBar"));
293 assert_se(unit_prefix_is_valid("foo-bar"));
294 assert_se(unit_prefix_is_valid("foo.stUff"));
295 assert_se(unit_prefix_is_valid("fOo123.stuff"));
296 assert_se(unit_prefix_is_valid("foo123.Stuff"));
298 assert_se(!unit_prefix_is_valid("$¢£"));
299 assert_se(!unit_prefix_is_valid(""));
300 assert_se(!unit_prefix_is_valid("foo bar"));
301 assert_se(!unit_prefix_is_valid("foo/bar"));
302 assert_se(!unit_prefix_is_valid("@foo-bar"));
305 static void test_unit_name_change_suffix(void) {
308 assert_se(unit_name_change_suffix("foo.mount", ".service", &t
) == 0);
309 assert_se(streq(t
, "foo.service"));
312 assert_se(unit_name_change_suffix("foo@stuff.service", ".socket", &t
) == 0);
313 assert_se(streq(t
, "foo@stuff.socket"));
317 static void test_unit_name_build(void) {
320 assert_se(unit_name_build("foo", "bar", ".service", &t
) == 0);
321 assert_se(streq(t
, "foo@bar.service"));
324 assert_se(unit_name_build("fo0-stUff_b", "bar", ".mount", &t
) == 0);
325 assert_se(streq(t
, "fo0-stUff_b@bar.mount"));
328 assert_se(unit_name_build("foo", NULL
, ".service", &t
) == 0);
329 assert_se(streq(t
, "foo.service"));
333 static void test_slice_name_is_valid(void) {
334 assert_se(slice_name_is_valid("-.slice"));
335 assert_se(slice_name_is_valid("foo.slice"));
336 assert_se(slice_name_is_valid("foo-bar.slice"));
337 assert_se(slice_name_is_valid("foo-bar-baz.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(".slice"));
344 assert_se(!slice_name_is_valid(""));
345 assert_se(!slice_name_is_valid("foo.service"));
348 static void test_build_subslice(void) {
352 assert_se(slice_build_subslice("-.slice", "foo", &a
) >= 0);
353 assert_se(slice_build_subslice(a
, "bar", &b
) >= 0);
355 assert_se(slice_build_subslice(b
, "barfoo", &a
) >= 0);
357 assert_se(slice_build_subslice(a
, "foobar", &b
) >= 0);
359 assert_se(streq(b
, "foo-bar-barfoo-foobar.slice"));
362 assert_se(slice_build_subslice("foo.service", "bar", &a
) < 0);
363 assert_se(slice_build_subslice("foo", "bar", &a
) < 0);
366 static void test_build_parent_slice_one(const char *name
, const char *expect
, int ret
) {
367 _cleanup_free_
char *s
= NULL
;
369 assert_se(slice_build_parent_slice(name
, &s
) == ret
);
370 assert_se(streq_ptr(s
, expect
));
373 static void test_build_parent_slice(void) {
374 test_build_parent_slice_one("-.slice", NULL
, 0);
375 test_build_parent_slice_one("foo.slice", "-.slice", 1);
376 test_build_parent_slice_one("foo-bar.slice", "foo.slice", 1);
377 test_build_parent_slice_one("foo-bar-baz.slice", "foo-bar.slice", 1);
378 test_build_parent_slice_one("foo-bar--baz.slice", NULL
, -EINVAL
);
379 test_build_parent_slice_one("-foo-bar.slice", NULL
, -EINVAL
);
380 test_build_parent_slice_one("foo-bar-.slice", NULL
, -EINVAL
);
381 test_build_parent_slice_one("foo-bar.service", NULL
, -EINVAL
);
382 test_build_parent_slice_one(".slice", NULL
, -EINVAL
);
385 static void test_unit_name_to_instance(void) {
389 r
= unit_name_to_instance("foo@bar.service", &instance
);
391 assert_se(streq(instance
, "bar"));
394 r
= unit_name_to_instance("foo@.service", &instance
);
396 assert_se(streq(instance
, ""));
399 r
= unit_name_to_instance("fo0-stUff_b@b.service", &instance
);
401 assert_se(streq(instance
, "b"));
404 r
= unit_name_to_instance("foo.service", &instance
);
406 assert_se(!instance
);
408 r
= unit_name_to_instance("fooj@unk", &instance
);
411 r
= unit_name_to_instance("foo@", &instance
);
415 static void test_unit_name_escape(void) {
416 _cleanup_free_
char *r
;
418 r
= unit_name_escape("ab+-c.a/bc@foo.service");
420 assert_se(streq(r
, "ab\\x2b\\x2dc.a-bc\\x40foo.service"));
424 static void test_u_n_t_one(const char *name
, const char *expected
, int ret
) {
425 _cleanup_free_
char *f
= NULL
;
427 assert_se(unit_name_template(name
, &f
) == ret
);
428 printf("got: %s, expected: %s\n", strna(f
), strna(expected
));
429 assert_se(streq_ptr(f
, expected
));
432 static void test_unit_name_template(void) {
433 test_u_n_t_one("foo@bar.service", "foo@.service", 0);
434 test_u_n_t_one("foo.mount", NULL
, -EINVAL
);
437 static void test_unit_name_path_unescape_one(const char *name
, const char *path
, int ret
) {
438 _cleanup_free_
char *p
= NULL
;
440 assert_se(unit_name_path_unescape(name
, &p
) == ret
);
441 assert_se(streq_ptr(path
, p
));
444 static void test_unit_name_path_unescape(void) {
446 test_unit_name_path_unescape_one("foo", "/foo", 0);
447 test_unit_name_path_unescape_one("foo-bar", "/foo/bar", 0);
448 test_unit_name_path_unescape_one("foo-.bar", "/foo/.bar", 0);
449 test_unit_name_path_unescape_one("foo-bar-baz", "/foo/bar/baz", 0);
450 test_unit_name_path_unescape_one("-", "/", 0);
451 test_unit_name_path_unescape_one("--", NULL
, -EINVAL
);
452 test_unit_name_path_unescape_one("-foo-bar", 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(".-bar", NULL
, -EINVAL
);
456 test_unit_name_path_unescape_one("foo-..", NULL
, -EINVAL
);
457 test_unit_name_path_unescape_one("", NULL
, -EINVAL
);
460 int main(int argc
, char* argv
[]) {
462 test_unit_name_is_valid();
468 TEST_REQ_RUNNING_SYSTEMD(rc
= test_unit_printf());
469 test_unit_instance_is_valid();
470 test_unit_prefix_is_valid();
471 test_unit_name_change_suffix();
472 test_unit_name_build();
473 test_slice_name_is_valid();
474 test_build_subslice();
475 test_build_parent_slice();
476 test_unit_name_to_instance();
477 test_unit_name_escape();
478 test_unit_name_template();
479 test_unit_name_path_unescape();