chiark / gitweb /
journal: fix dangling 'else' ambiguity
[elogind.git] / src / test / test-unit-name.c
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
7   Copyright 2013 Zbigniew Jędrzejewski-Szmek
8   Copyright 2014 Ronny Chevalier
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>
27 #include <sys/types.h>
28 #include <pwd.h>
29
30 #include "manager.h"
31 #include "unit.h"
32 #include "unit-name.h"
33 #include "unit-printf.h"
34 #include "install.h"
35 #include "specifier.h"
36 #include "util.h"
37 #include "macro.h"
38 #include "test-helper.h"
39
40 static void test_replacements(void) {
41 #define expect(pattern, repl, expected)                            \
42         {                                                          \
43                 _cleanup_free_ char *t =                           \
44                         unit_name_replace_instance(pattern, repl); \
45                 puts(t);                                           \
46                 assert_se(streq(t, expected));                        \
47         }
48
49         expect("foo@.service", "waldo", "foo@waldo.service");
50         expect("foo@xyz.service", "waldo", "foo@waldo.service");
51         expect("xyz", "waldo", "xyz");
52         expect("", "waldo", "");
53         expect("foo.service", "waldo", "foo.service");
54         expect(".service", "waldo", ".service");
55         expect("foo@", "waldo", "foo@waldo");
56         expect("@bar", "waldo", "@waldo");
57
58         puts("-------------------------------------------------");
59 #undef expect
60 #define expect(path, suffix, expected)                             \
61         {                                                          \
62                 _cleanup_free_ char *k, *t =                       \
63                         unit_name_from_path(path, suffix);         \
64                 puts(t);                                           \
65                 k = unit_name_to_path(t);                          \
66                 puts(k);                                           \
67                 assert_se(streq(k, expected ? expected : path));      \
68         }
69
70         expect("/waldo", ".mount", NULL);
71         expect("/waldo/quuix", ".mount", NULL);
72         expect("/waldo/quuix/", ".mount", "/waldo/quuix");
73         expect("/", ".mount", NULL);
74         expect("///", ".mount", "/");
75
76         puts("-------------------------------------------------");
77 #undef expect
78 #define expect(pattern, path, suffix, expected)                              \
79         {                                                                    \
80                 _cleanup_free_ char *t =                                     \
81                         unit_name_from_path_instance(pattern, path, suffix); \
82                 puts(t);                                                     \
83                 assert_se(streq(t, expected));                                  \
84         }
85
86         expect("waldo", "/waldo", ".mount", "waldo@waldo.mount");
87         expect("waldo", "/waldo////quuix////", ".mount", "waldo@waldo-quuix.mount");
88         expect("waldo", "/", ".mount", "waldo@-.mount");
89         expect("wa--ldo", "/--", ".mount", "wa--ldo@\\x2d\\x2d.mount");
90
91         puts("-------------------------------------------------");
92 #undef expect
93 #define expect(pattern)                                                     \
94         {                                                                   \
95                 _cleanup_free_ char *k, *t;                                 \
96                 assert_se(t = unit_name_mangle(pattern, MANGLE_NOGLOB));    \
97                 assert_se(k = unit_name_mangle(t, MANGLE_NOGLOB));          \
98                 puts(t);                                                    \
99                 assert_se(streq(t, k));                                     \
100         }
101
102         expect("/home");
103         expect("/dev/sda");
104         expect("üxknürz.service");
105         expect("foobar-meh...waldi.service");
106         expect("_____####----.....service");
107         expect("_____##@;;;,,,##----.....service");
108         expect("xxx@@@@/////\\\\\\\\\\yyy.service");
109
110 #undef expect
111 }
112
113 static int test_unit_printf(void) {
114         Manager *m = NULL;
115         Unit *u, *u2;
116         int r;
117
118         _cleanup_free_ char *mid, *bid, *host, *root_uid;
119         struct passwd *root;
120
121         assert_se(specifier_machine_id('m', NULL, NULL, &mid) >= 0 && mid);
122         assert_se(specifier_boot_id('b', NULL, NULL, &bid) >= 0 && bid);
123         assert_se((host = gethostname_malloc()));
124
125         assert_se((root = getpwnam("root")));
126         assert_se(asprintf(&root_uid, "%d", (int) root->pw_uid) > 0);
127
128         r = manager_new(SYSTEMD_USER, true, &m);
129         if (r == -EPERM || r == -EACCES || r == -EADDRINUSE) {
130                 puts("manager_new: Permission denied. Skipping test.");
131                 return EXIT_TEST_SKIP;
132         }
133         assert_se(r == 0);
134
135 #define expect(unit, pattern, expected)                                 \
136         {                                                               \
137                 char *e;                                                \
138                 _cleanup_free_ char *t = NULL;                          \
139                 assert_se(unit_full_printf(unit, pattern, &t) >= 0);    \
140                 printf("result: %s\nexpect: %s\n", t, expected);        \
141                 if ((e = endswith(expected, "*")))                      \
142                         assert_se(strncmp(t, e, e-expected));              \
143                 else                                                    \
144                         assert_se(streq(t, expected));                     \
145         }
146
147         assert_se(setenv("USER", "root", 1) == 0);
148         assert_se(setenv("HOME", "/root", 1) == 0);
149         assert_se(setenv("XDG_RUNTIME_DIR", "/run/user/1/", 1) == 0);
150
151         assert_se(u = unit_new(m, sizeof(Service)));
152         assert_se(unit_add_name(u, "blah.service") == 0);
153         assert_se(unit_add_name(u, "blah.service") == 0);
154
155         /* general tests */
156         expect(u, "%%", "%");
157         expect(u, "%%s", "%s");
158         expect(u, "%", "");    // REALLY?
159
160         /* normal unit */
161         expect(u, "%n", "blah.service");
162         expect(u, "%f", "/blah");
163         expect(u, "%N", "blah");
164         expect(u, "%p", "blah");
165         expect(u, "%P", "blah");
166         expect(u, "%i", "");
167         expect(u, "%u", root->pw_name);
168         expect(u, "%U", root_uid);
169         expect(u, "%h", root->pw_dir);
170         expect(u, "%m", mid);
171         expect(u, "%b", bid);
172         expect(u, "%H", host);
173         expect(u, "%t", "/run/user/*");
174
175         /* templated */
176         assert_se(u2 = unit_new(m, sizeof(Service)));
177         assert_se(unit_add_name(u2, "blah@foo-foo.service") == 0);
178         assert_se(unit_add_name(u2, "blah@foo-foo.service") == 0);
179
180         expect(u2, "%n", "blah@foo-foo.service");
181         expect(u2, "%N", "blah@foo-foo");
182         expect(u2, "%f", "/foo/foo");
183         expect(u2, "%p", "blah");
184         expect(u2, "%P", "blah");
185         expect(u2, "%i", "foo-foo");
186         expect(u2, "%I", "foo/foo");
187         expect(u2, "%u", root->pw_name);
188         expect(u2, "%U", root_uid);
189         expect(u2, "%h", root->pw_dir);
190         expect(u2, "%m", mid);
191         expect(u2, "%b", bid);
192         expect(u2, "%H", host);
193         expect(u2, "%t", "/run/user/*");
194
195         manager_free(m);
196
197         return 0;
198 }
199
200 static void test_unit_instance_is_valid(void) {
201         assert_se(unit_instance_is_valid("fooBar"));
202         assert_se(unit_instance_is_valid("foo-bar"));
203         assert_se(unit_instance_is_valid("foo.stUff"));
204         assert_se(unit_instance_is_valid("fOo123.stuff"));
205         assert_se(unit_instance_is_valid("@f_oo123.Stuff"));
206
207         assert_se(!unit_instance_is_valid("$¢£"));
208         assert_se(!unit_instance_is_valid(""));
209         assert_se(!unit_instance_is_valid("foo bar"));
210         assert_se(!unit_instance_is_valid("foo/bar"));
211 }
212
213 static void test_unit_prefix_is_valid(void) {
214         assert_se(unit_prefix_is_valid("fooBar"));
215         assert_se(unit_prefix_is_valid("foo-bar"));
216         assert_se(unit_prefix_is_valid("foo.stUff"));
217         assert_se(unit_prefix_is_valid("fOo123.stuff"));
218         assert_se(unit_prefix_is_valid("foo123.Stuff"));
219
220         assert_se(!unit_prefix_is_valid("$¢£"));
221         assert_se(!unit_prefix_is_valid(""));
222         assert_se(!unit_prefix_is_valid("foo bar"));
223         assert_se(!unit_prefix_is_valid("foo/bar"));
224         assert_se(!unit_prefix_is_valid("@foo-bar"));
225 }
226
227 static void test_unit_name_change_suffix(void) {
228         char *r;
229
230         r = unit_name_change_suffix("foo.bar", ".service");
231         assert_se(r);
232         assert_se(streq(r, "foo.service"));
233         free(r);
234
235         r = unit_name_change_suffix("foo@stuff.bar", ".boo");
236         assert_se(r);
237         assert_se(streq(r, "foo@stuff.boo"));
238         free(r);
239 }
240
241 static void test_unit_name_build(void) {
242         char *r;
243
244         r = unit_name_build("foo", "bar", ".service");
245         assert_se(r);
246         assert_se(streq(r, "foo@bar.service"));
247         free(r);
248
249         r = unit_name_build("fo0-stUff_b", "bar", ".mount");
250         assert_se(r);
251         assert_se(streq(r, "fo0-stUff_b@bar.mount"));
252         free(r);
253
254         r = unit_name_build("foo", NULL, ".service");
255         assert_se(r);
256         assert_se(streq(r, "foo.service"));
257         free(r);
258 }
259
260 static void test_unit_name_is_instance(void) {
261         assert_se(unit_name_is_instance("a@b.service"));
262         assert_se(unit_name_is_instance("a-c_c01Aj@b05Dii_-oioi.service"));
263
264         assert_se(!unit_name_is_instance("a.service"));
265         assert_se(!unit_name_is_instance("junk"));
266         assert_se(!unit_name_is_instance(""));
267 }
268
269 static 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
287 static 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
296         r = unit_name_to_instance("fo0-stUff_b@b.e", &instance);
297         assert_se(r >= 0);
298         assert_se(streq(instance, "b"));
299         free(instance);
300
301         r = unit_name_to_instance("foo.bar", &instance);
302         assert_se(r >= 0);
303         assert_se(!instance);
304
305         r = unit_name_to_instance("fooj@unk", &instance);
306         assert_se(r < 0);
307 }
308
309 static void test_unit_name_escape(void) {
310         _cleanup_free_ char *r;
311
312         r = unit_name_escape("ab+-c.a/bc@foo.service");
313         assert_se(r);
314         assert_se(streq(r, "ab\\x2b\\x2dc.a-bc\\x40foo.service"));
315 }
316
317 int main(int argc, char* argv[]) {
318         int rc = 0;
319         test_replacements();
320         TEST_REQ_RUNNING_SYSTEMD(rc = test_unit_printf());
321         test_unit_instance_is_valid();
322         test_unit_prefix_is_valid();
323         test_unit_name_change_suffix();
324         test_unit_name_build();
325         test_unit_name_is_instance();
326         test_build_subslice();
327         test_unit_name_to_instance();
328         test_unit_name_escape();
329
330         return rc;
331 }