chiark / gitweb /
tests: add tests to test-unit-name
[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(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(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(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, &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(r == 0);
134
135 #define expect(unit, pattern, expected)                                 \
136         {                                                               \
137                 char *e;                                                \
138                 _cleanup_free_ char *t;                                 \
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(strncmp(t, e, e-expected));              \
143                 else                                                    \
144                         assert(streq(t, expected));                     \
145         }
146
147         assert_se(setenv("USER", "root", 1) == 0);
148         assert_se(setenv("HOME", "/root", 1) == 0);
149
150         assert_se(u = unit_new(m, sizeof(Service)));
151         assert_se(unit_add_name(u, "blah.service") == 0);
152         assert_se(unit_add_name(u, "blah.service") == 0);
153
154         /* general tests */
155         expect(u, "%%", "%");
156         expect(u, "%%s", "%s");
157         expect(u, "%", "");    // REALLY?
158
159         /* normal unit */
160         expect(u, "%n", "blah.service");
161         expect(u, "%N", "blah");
162         expect(u, "%p", "blah");
163         expect(u, "%P", "blah");
164         expect(u, "%i", "");
165         expect(u, "%u", root->pw_name);
166         expect(u, "%U", root_uid);
167         expect(u, "%h", root->pw_dir);
168         expect(u, "%m", mid);
169         expect(u, "%b", bid);
170         expect(u, "%H", host);
171         expect(u, "%t", "/run/user/*");
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");
180         expect(u2, "%p", "blah");
181         expect(u2, "%P", "blah");
182         expect(u2, "%i", "foo-foo");
183         expect(u2, "%I", "foo/foo");
184         expect(u2, "%u", root->pw_name);
185         expect(u2, "%U", root_uid);
186         expect(u2, "%h", root->pw_dir);
187         expect(u2, "%m", mid);
188         expect(u2, "%b", bid);
189         expect(u2, "%H", host);
190         expect(u2, "%t", "/run/user/*");
191
192         manager_free(m);
193
194         return 0;
195 }
196
197 static void test_unit_instance_is_valid(void) {
198         assert_se(unit_instance_is_valid("fooBar"));
199         assert_se(unit_instance_is_valid("foo-bar"));
200         assert_se(unit_instance_is_valid("foo.stUff"));
201         assert_se(unit_instance_is_valid("fOo123.stuff"));
202         assert_se(unit_instance_is_valid("@f_oo123.Stuff"));
203
204         assert_se(!unit_instance_is_valid("$¢£"));
205         assert_se(!unit_instance_is_valid(""));
206         assert_se(!unit_instance_is_valid("foo bar"));
207         assert_se(!unit_instance_is_valid("foo/bar"));
208 }
209
210 static void test_unit_prefix_is_valid(void) {
211         assert_se(unit_prefix_is_valid("fooBar"));
212         assert_se(unit_prefix_is_valid("foo-bar"));
213         assert_se(unit_prefix_is_valid("foo.stUff"));
214         assert_se(unit_prefix_is_valid("fOo123.stuff"));
215         assert_se(unit_prefix_is_valid("foo123.Stuff"));
216
217         assert_se(!unit_prefix_is_valid("$¢£"));
218         assert_se(!unit_prefix_is_valid(""));
219         assert_se(!unit_prefix_is_valid("foo bar"));
220         assert_se(!unit_prefix_is_valid("foo/bar"));
221         assert_se(!unit_prefix_is_valid("@foo-bar"));
222 }
223
224 static void test_unit_name_change_suffix(void) {
225         char *r;
226
227         r = unit_name_change_suffix("foo.bar", ".service");
228         assert_se(r);
229         assert_se(streq(r, "foo.service"));
230         free(r);
231
232         r = unit_name_change_suffix("foo@stuff.bar", ".boo");
233         assert_se(r);
234         assert_se(streq(r, "foo@stuff.boo"));
235         free(r);
236 }
237
238 static void test_unit_name_build(void) {
239         char *r;
240
241         r = unit_name_build("foo", "bar", ".service");
242         assert_se(r);
243         assert_se(streq(r, "foo@bar.service"));
244         free(r);
245
246         r = unit_name_build("fo0-stUff_b", "bar", ".mount");
247         assert_se(r);
248         assert_se(streq(r, "fo0-stUff_b@bar.mount"));
249         free(r);
250
251         r = unit_name_build("foo", NULL, ".service");
252         assert_se(r);
253         assert_se(streq(r, "foo.service"));
254         free(r);
255 }
256
257 static void test_unit_name_is_instance(void) {
258         assert_se(unit_name_is_instance("a@b.service"));
259         assert_se(unit_name_is_instance("a-c_c01Aj@b05Dii_-oioi.service"));
260
261         assert_se(!unit_name_is_instance("a.service"));
262         assert_se(!unit_name_is_instance("junk"));
263         assert_se(!unit_name_is_instance(""));
264 }
265
266 static void test_build_subslice(void) {
267         char *a;
268         char *b;
269
270         assert_se(build_subslice("-.slice", "foo", &a) >= 0);
271         assert_se(build_subslice(a, "bar", &b) >= 0);
272         free(a);
273         assert_se(build_subslice(b, "barfoo", &a) >= 0);
274         free(b);
275         assert_se(build_subslice(a, "foobar", &b) >= 0);
276         free(a);
277         assert_se(streq(b, "foo-bar-barfoo-foobar.slice"));
278         free(b);
279
280         assert_se(build_subslice("foo.service", "bar", &a) < 0);
281         assert_se(build_subslice("foo", "bar", &a) < 0);
282 }
283
284 static void test_unit_name_to_instance(void) {
285         char *instance;
286         int r;
287
288         r = unit_name_to_instance("foo@bar.service", &instance);
289         assert_se(r >= 0);
290         assert_se(streq(instance, "bar"));
291         free(instance);
292
293         r = unit_name_to_instance("fo0-stUff_b@b.e", &instance);
294         assert_se(r >= 0);
295         assert_se(streq(instance, "b"));
296         free(instance);
297
298         r = unit_name_to_instance("foo.bar", &instance);
299         assert_se(r >= 0);
300         assert_se(!instance);
301
302         r = unit_name_to_instance("fooj@unk", &instance);
303         assert_se(r < 0);
304 }
305
306 static void test_unit_name_escape(void) {
307         _cleanup_free_ char *r;
308
309         r = unit_name_escape("ab+-c.a/bc@foo.service");
310         assert_se(r);
311         assert_se(streq(r, "ab\\x2b\\x2dc.a-bc\\x40foo.service"));
312 }
313
314 int main(int argc, char* argv[]) {
315         int rc = 0;
316         test_replacements();
317         TEST_REQ_RUNNING_SYSTEMD(rc = test_unit_printf());
318         test_unit_instance_is_valid();
319         test_unit_prefix_is_valid();
320         test_unit_name_change_suffix();
321         test_unit_name_build();
322         test_unit_name_is_instance();
323         test_build_subslice();
324         test_unit_name_to_instance();
325         test_unit_name_escape();
326
327         return rc;
328 }