chiark / gitweb /
test-cgroup-mask: fix masks in test and enable by default
[elogind.git] / src / test / test-unit-file.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
9   systemd is free software; you can redistribute it and/or modify it
10   under the terms of the GNU Lesser General Public License as published by
11   the Free Software Foundation; either version 2.1 of the License, or
12   (at your option) any later version.
13
14   systemd is distributed in the hope that it will be useful, but
15   WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   Lesser General Public License for more details.
18
19   You should have received a copy of the GNU Lesser General Public License
20   along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 ***/
22
23 #include <assert.h>
24 #include <stdio.h>
25 #include <stddef.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29
30 #include "install.h"
31 #include "install-printf.h"
32 #include "specifier.h"
33 #include "util.h"
34 #include "macro.h"
35 #include "hashmap.h"
36 #include "load-fragment.h"
37 #include "strv.h"
38 #include "fileio.h"
39 #include "test-helper.h"
40
41 static int test_unit_file_get_set(void) {
42         int r;
43         Hashmap *h;
44         Iterator i;
45         UnitFileList *p;
46
47         h = hashmap_new(string_hash_func, string_compare_func);
48         assert(h);
49
50         r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h);
51
52         if (r == -EPERM || r == -EACCES) {
53                 printf("Skipping test: unit_file_get_list: %s", strerror(-r));
54                 return EXIT_TEST_SKIP;
55         }
56
57         log_full(r == 0 ? LOG_INFO : LOG_ERR,
58                  "unit_file_get_list: %s", strerror(-r));
59         if (r < 0)
60                 return EXIT_FAILURE;
61
62         HASHMAP_FOREACH(p, h, i)
63                 printf("%s = %s\n", p->path, unit_file_state_to_string(p->state));
64
65         unit_file_list_free(h);
66
67         return 0;
68 }
69
70 static void check_execcommand(ExecCommand *c,
71                               const char* path,
72                               const char* argv0,
73                               const char* argv1,
74                               bool ignore) {
75         assert_se(c);
76         log_info("%s %s %s %s",
77                  c->path, c->argv[0], c->argv[1], c->argv[2]);
78         assert_se(streq(c->path, path));
79         assert_se(streq(c->argv[0], argv0));
80         assert_se(streq(c->argv[1], argv1));
81         assert_se(c->argv[2] == NULL);
82         assert_se(c->ignore == ignore);
83 }
84
85 static void test_config_parse_exec(void) {
86         /* int config_parse_exec( */
87         /*         const char *filename, */
88         /*         unsigned line, */
89         /*         const char *section, */
90         /*         unsigned section_line, */
91         /*         const char *lvalue, */
92         /*         int ltype, */
93         /*         const char *rvalue, */
94         /*         void *data, */
95         /*         void *userdata) */
96         int r;
97
98         ExecCommand *c = NULL, *c1;
99
100         /* basic test */
101         r = config_parse_exec(NULL, "fake", 1, "section", 1,
102                               "LValue", 0, "/RValue r1",
103                               &c, NULL);
104         assert_se(r >= 0);
105         check_execcommand(c, "/RValue", "/RValue", "r1", false);
106
107         r = config_parse_exec(NULL, "fake", 2, "section", 1,
108                               "LValue", 0, "/RValue///slashes/// r1",
109                               &c, NULL);
110        /* test slashes */
111         assert_se(r >= 0);
112         c1 = c->command_next;
113         check_execcommand(c1, "/RValue/slashes", "/RValue///slashes///",
114                           "r1", false);
115
116         /* honour_argv0 */
117         r = config_parse_exec(NULL, "fake", 3, "section", 1,
118                               "LValue", 0, "@/RValue///slashes2/// argv0 r1",
119                               &c, NULL);
120         assert_se(r >= 0);
121         c1 = c1->command_next;
122         check_execcommand(c1, "/RValue/slashes2", "argv0", "r1", false);
123
124         /* ignore && honour_argv0 */
125         r = config_parse_exec(NULL, "fake", 4, "section", 1,
126                               "LValue", 0, "-@/RValue///slashes3/// argv0a r1",
127                               &c, NULL);
128         assert_se(r >= 0);
129         c1 = c1->command_next;
130         check_execcommand(c1,
131                           "/RValue/slashes3", "argv0a", "r1", true);
132
133         /* ignore && honour_argv0 */
134         r = config_parse_exec(NULL, "fake", 4, "section", 1,
135                               "LValue", 0, "@-/RValue///slashes4/// argv0b r1",
136                               &c, NULL);
137         assert_se(r >= 0);
138         c1 = c1->command_next;
139         check_execcommand(c1,
140                           "/RValue/slashes4", "argv0b", "r1", true);
141
142         /* ignore && ignore */
143         r = config_parse_exec(NULL, "fake", 4, "section", 1,
144                               "LValue", 0, "--/RValue argv0 r1",
145                               &c, NULL);
146         assert_se(r == 0);
147         assert_se(c1->command_next == NULL);
148
149         /* ignore && ignore */
150         r = config_parse_exec(NULL, "fake", 4, "section", 1,
151                               "LValue", 0, "-@-/RValue argv0 r1",
152                               &c, NULL);
153         assert_se(r == 0);
154         assert_se(c1->command_next == NULL);
155
156         /* semicolon */
157         r = config_parse_exec(NULL, "fake", 5, "section", 1,
158                               "LValue", 0,
159                               "-@/RValue argv0 r1 ; "
160                               "/goo/goo boo",
161                               &c, NULL);
162         assert_se(r >= 0);
163         c1 = c1->command_next;
164         check_execcommand(c1,
165                           "/RValue", "argv0", "r1", true);
166
167         c1 = c1->command_next;
168         check_execcommand(c1,
169                           "/goo/goo", "/goo/goo", "boo", false);
170
171         /* trailing semicolon */
172         r = config_parse_exec(NULL, "fake", 5, "section", 1,
173                               "LValue", 0,
174                               "-@/RValue argv0 r1 ; ",
175                               &c, NULL);
176         assert_se(r >= 0);
177         c1 = c1->command_next;
178         check_execcommand(c1,
179                           "/RValue", "argv0", "r1", true);
180
181         assert_se(c1->command_next == NULL);
182
183         /* escaped semicolon */
184         r = config_parse_exec(NULL, "fake", 5, "section", 1,
185                               "LValue", 0,
186                               "/usr/bin/find \\;",
187                               &c, NULL);
188         assert_se(r >= 0);
189         c1 = c1->command_next;
190         check_execcommand(c1,
191                           "/usr/bin/find", "/usr/bin/find", ";", false);
192
193         exec_command_free_list(c);
194 }
195
196 #define env_file_1                              \
197         "a=a\n"                                 \
198         "b=b\\\n"                               \
199         "c\n"                                   \
200         "d=d\\\n"                               \
201         "e\\\n"                                 \
202         "f\n"                                   \
203         "g=g\\ \n"                              \
204         "h=h\n"                                 \
205         "i=i\\"
206
207 #define env_file_2                              \
208         "a=a\\\n"
209
210 #define env_file_3 \
211         "#SPAMD_ARGS=\"-d --socketpath=/var/lib/bulwark/spamd \\\n" \
212         "#--nouser-config                                     \\\n" \
213         "normal=line"
214
215 #define env_file_4 \
216        "# Generated\n" \
217        "\n" \
218        "HWMON_MODULES=\"coretemp f71882fg\"\n" \
219        "\n" \
220        "# For compatibility reasons\n" \
221        "\n" \
222        "MODULE_0=coretemp\n" \
223        "MODULE_1=f71882fg"
224
225
226 static void test_load_env_file_1(void) {
227         _cleanup_strv_free_ char **data = NULL;
228         int r;
229
230         char name[] = "/tmp/test-load-env-file.XXXXXX";
231         _cleanup_close_ int fd;
232
233         fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
234         assert(fd >= 0);
235         assert_se(write(fd, env_file_1, sizeof(env_file_1)) == sizeof(env_file_1));
236
237         r = load_env_file(NULL, name, NULL, &data);
238         assert(r == 0);
239         assert(streq(data[0], "a=a"));
240         assert(streq(data[1], "b=bc"));
241         assert(streq(data[2], "d=def"));
242         assert(streq(data[3], "g=g "));
243         assert(streq(data[4], "h=h"));
244         assert(streq(data[5], "i=i"));
245         assert(data[6] == NULL);
246         unlink(name);
247 }
248
249 static void test_load_env_file_2(void) {
250         _cleanup_strv_free_ char **data = NULL;
251         int r;
252
253         char name[] = "/tmp/test-load-env-file.XXXXXX";
254         _cleanup_close_ int fd;
255
256         fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
257         assert(fd >= 0);
258         assert_se(write(fd, env_file_2, sizeof(env_file_2)) == sizeof(env_file_2));
259
260         r = load_env_file(NULL, name, NULL, &data);
261         assert(r == 0);
262         assert(streq(data[0], "a=a"));
263         assert(data[1] == NULL);
264         unlink(name);
265 }
266
267 static void test_load_env_file_3(void) {
268         _cleanup_strv_free_ char **data = NULL;
269         int r;
270
271         char name[] = "/tmp/test-load-env-file.XXXXXX";
272         _cleanup_close_ int fd;
273
274         fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
275         assert(fd >= 0);
276         assert_se(write(fd, env_file_3, sizeof(env_file_3)) == sizeof(env_file_3));
277
278         r = load_env_file(NULL, name, NULL, &data);
279         assert(r == 0);
280         assert(data == NULL);
281         unlink(name);
282 }
283
284 static void test_load_env_file_4(void) {
285         _cleanup_strv_free_ char **data = NULL;
286         char name[] = "/tmp/test-load-env-file.XXXXXX";
287         _cleanup_close_ int fd;
288         int r;
289
290         fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
291         assert(fd >= 0);
292         assert_se(write(fd, env_file_4, sizeof(env_file_4)) == sizeof(env_file_4));
293
294         r = load_env_file(NULL, name, NULL, &data);
295         assert(r == 0);
296         assert(streq(data[0], "HWMON_MODULES=coretemp f71882fg"));
297         assert(streq(data[1], "MODULE_0=coretemp"));
298         assert(streq(data[2], "MODULE_1=f71882fg"));
299         assert(data[3] == NULL);
300         unlink(name);
301 }
302
303
304 static void test_install_printf(void) {
305         char    name[] = "name.service",
306                 path[] = "/run/systemd/system/name.service",
307                 user[] = "xxxx-no-such-user";
308         InstallInfo i = {name, path, user};
309         InstallInfo i2 = {name, path, NULL};
310         char    name3[] = "name@inst.service",
311                 path3[] = "/run/systemd/system/name.service";
312         InstallInfo i3 = {name3, path3, user};
313         InstallInfo i4 = {name3, path3, NULL};
314
315         _cleanup_free_ char *mid, *bid, *host;
316
317         assert_se(specifier_machine_id('m', NULL, NULL, &mid) >= 0 && mid);
318         assert_se(specifier_boot_id('b', NULL, NULL, &bid) >= 0 && bid);
319         assert_se((host = gethostname_malloc()));
320
321 #define expect(src, pattern, result)                                    \
322         do {                                                            \
323                 _cleanup_free_ char *t = NULL;                          \
324                 _cleanup_free_ char                                     \
325                         *d1 = strdup(i.name),                           \
326                         *d2 = strdup(i.path),                           \
327                         *d3 = strdup(i.user);                           \
328                 assert_se(install_full_printf(&src, pattern, &t) >= 0 || !result); \
329                 memzero(i.name, strlen(i.name));                        \
330                 memzero(i.path, strlen(i.path));                        \
331                 memzero(i.user, strlen(i.user));                        \
332                 assert(d1 && d2 && d3);                                 \
333                 if (result) {                                           \
334                         printf("%s\n", t);                              \
335                         assert(streq(t, result));                       \
336                 } else assert(t == NULL);                               \
337                 strcpy(i.name, d1);                                     \
338                 strcpy(i.path, d2);                                     \
339                 strcpy(i.user, d3);                                     \
340         } while(false)
341
342         assert_se(setenv("USER", "root", 1) == 0);
343
344         expect(i, "%n", "name.service");
345         expect(i, "%N", "name");
346         expect(i, "%p", "name");
347         expect(i, "%i", "");
348         expect(i, "%u", "xxxx-no-such-user");
349
350         DISABLE_WARNING_NONNULL;
351         expect(i, "%U", NULL);
352         REENABLE_WARNING;
353
354         expect(i, "%m", mid);
355         expect(i, "%b", bid);
356         expect(i, "%H", host);
357
358         expect(i2, "%u", "root");
359         expect(i2, "%U", "0");
360
361         expect(i3, "%n", "name@inst.service");
362         expect(i3, "%N", "name@inst");
363         expect(i3, "%p", "name");
364         expect(i3, "%u", "xxxx-no-such-user");
365
366         DISABLE_WARNING_NONNULL;
367         expect(i3, "%U", NULL);
368         REENABLE_WARNING;
369
370         expect(i3, "%m", mid);
371         expect(i3, "%b", bid);
372         expect(i3, "%H", host);
373
374         expect(i4, "%u", "root");
375         expect(i4, "%U", "0");
376 }
377
378 int main(int argc, char *argv[]) {
379         int r;
380
381         log_parse_environment();
382         log_open();
383
384         r = test_unit_file_get_set();
385         test_config_parse_exec();
386         test_load_env_file_1();
387         test_load_env_file_2();
388         test_load_env_file_3();
389         test_load_env_file_4();
390         TEST_REQ_RUNNING_SYSTEMD(test_install_printf());
391
392         return r;
393 }