chiark / gitweb /
load-fragment: remove wrong ifdef guard
[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_ops);
48         assert_se(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 #define env_file_5                              \
226         "a=\n"                                 \
227         "b="
228
229 static void test_load_env_file_1(void) {
230         _cleanup_strv_free_ char **data = NULL;
231         int r;
232
233         char name[] = "/tmp/test-load-env-file.XXXXXX";
234         _cleanup_close_ int fd;
235
236         fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
237         assert_se(fd >= 0);
238         assert_se(write(fd, env_file_1, sizeof(env_file_1)) == sizeof(env_file_1));
239
240         r = load_env_file(NULL, name, NULL, &data);
241         assert_se(r == 0);
242         assert_se(streq(data[0], "a=a"));
243         assert_se(streq(data[1], "b=bc"));
244         assert_se(streq(data[2], "d=def"));
245         assert_se(streq(data[3], "g=g "));
246         assert_se(streq(data[4], "h=h"));
247         assert_se(streq(data[5], "i=i"));
248         assert_se(data[6] == NULL);
249         unlink(name);
250 }
251
252 static void test_load_env_file_2(void) {
253         _cleanup_strv_free_ char **data = NULL;
254         int r;
255
256         char name[] = "/tmp/test-load-env-file.XXXXXX";
257         _cleanup_close_ int fd;
258
259         fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
260         assert_se(fd >= 0);
261         assert_se(write(fd, env_file_2, sizeof(env_file_2)) == sizeof(env_file_2));
262
263         r = load_env_file(NULL, name, NULL, &data);
264         assert_se(r == 0);
265         assert_se(streq(data[0], "a=a"));
266         assert_se(data[1] == NULL);
267         unlink(name);
268 }
269
270 static void test_load_env_file_3(void) {
271         _cleanup_strv_free_ char **data = NULL;
272         int r;
273
274         char name[] = "/tmp/test-load-env-file.XXXXXX";
275         _cleanup_close_ int fd;
276
277         fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
278         assert_se(fd >= 0);
279         assert_se(write(fd, env_file_3, sizeof(env_file_3)) == sizeof(env_file_3));
280
281         r = load_env_file(NULL, name, NULL, &data);
282         assert_se(r == 0);
283         assert_se(data == NULL);
284         unlink(name);
285 }
286
287 static void test_load_env_file_4(void) {
288         _cleanup_strv_free_ char **data = NULL;
289         char name[] = "/tmp/test-load-env-file.XXXXXX";
290         _cleanup_close_ int fd;
291         int r;
292
293         fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
294         assert_se(fd >= 0);
295         assert_se(write(fd, env_file_4, sizeof(env_file_4)) == sizeof(env_file_4));
296
297         r = load_env_file(NULL, name, NULL, &data);
298         assert_se(r == 0);
299         assert_se(streq(data[0], "HWMON_MODULES=coretemp f71882fg"));
300         assert_se(streq(data[1], "MODULE_0=coretemp"));
301         assert_se(streq(data[2], "MODULE_1=f71882fg"));
302         assert_se(data[3] == NULL);
303         unlink(name);
304 }
305
306 static void test_load_env_file_5(void) {
307         _cleanup_strv_free_ char **data = NULL;
308         int r;
309
310         char name[] = "/tmp/test-load-env-file.XXXXXX";
311         _cleanup_close_ int fd;
312
313         fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
314         assert_se(fd >= 0);
315         assert_se(write(fd, env_file_5, sizeof(env_file_5)) == sizeof(env_file_5));
316
317         r = load_env_file(NULL, name, NULL, &data);
318         assert_se(r == 0);
319         assert_se(streq(data[0], "a="));
320         assert_se(streq(data[1], "b="));
321         assert_se(data[2] == NULL);
322         unlink(name);
323 }
324
325 static void test_install_printf(void) {
326         char    name[] = "name.service",
327                 path[] = "/run/systemd/system/name.service",
328                 user[] = "xxxx-no-such-user";
329         InstallInfo i = {name, path, user};
330         InstallInfo i2 = {name, path, NULL};
331         char    name3[] = "name@inst.service",
332                 path3[] = "/run/systemd/system/name.service";
333         InstallInfo i3 = {name3, path3, user};
334         InstallInfo i4 = {name3, path3, NULL};
335
336         _cleanup_free_ char *mid, *bid, *host;
337
338         assert_se(specifier_machine_id('m', NULL, NULL, &mid) >= 0 && mid);
339         assert_se(specifier_boot_id('b', NULL, NULL, &bid) >= 0 && bid);
340         assert_se((host = gethostname_malloc()));
341
342 #define expect(src, pattern, result)                                    \
343         do {                                                            \
344                 _cleanup_free_ char *t = NULL;                          \
345                 _cleanup_free_ char                                     \
346                         *d1 = strdup(i.name),                           \
347                         *d2 = strdup(i.path),                           \
348                         *d3 = strdup(i.user);                           \
349                 assert_se(install_full_printf(&src, pattern, &t) >= 0 || !result); \
350                 memzero(i.name, strlen(i.name));                        \
351                 memzero(i.path, strlen(i.path));                        \
352                 memzero(i.user, strlen(i.user));                        \
353                 assert_se(d1 && d2 && d3);                                 \
354                 if (result) {                                           \
355                         printf("%s\n", t);                              \
356                         assert_se(streq(t, result));                       \
357                 } else assert_se(t == NULL);                               \
358                 strcpy(i.name, d1);                                     \
359                 strcpy(i.path, d2);                                     \
360                 strcpy(i.user, d3);                                     \
361         } while(false)
362
363         assert_se(setenv("USER", "root", 1) == 0);
364
365         expect(i, "%n", "name.service");
366         expect(i, "%N", "name");
367         expect(i, "%p", "name");
368         expect(i, "%i", "");
369         expect(i, "%u", "xxxx-no-such-user");
370
371         DISABLE_WARNING_NONNULL;
372         expect(i, "%U", NULL);
373         REENABLE_WARNING;
374
375         expect(i, "%m", mid);
376         expect(i, "%b", bid);
377         expect(i, "%H", host);
378
379         expect(i2, "%u", "root");
380         expect(i2, "%U", "0");
381
382         expect(i3, "%n", "name@inst.service");
383         expect(i3, "%N", "name@inst");
384         expect(i3, "%p", "name");
385         expect(i3, "%u", "xxxx-no-such-user");
386
387         DISABLE_WARNING_NONNULL;
388         expect(i3, "%U", NULL);
389         REENABLE_WARNING;
390
391         expect(i3, "%m", mid);
392         expect(i3, "%b", bid);
393         expect(i3, "%H", host);
394
395         expect(i4, "%u", "root");
396         expect(i4, "%U", "0");
397 }
398
399 int main(int argc, char *argv[]) {
400         int r;
401
402         log_parse_environment();
403         log_open();
404
405         r = test_unit_file_get_set();
406         test_config_parse_exec();
407         test_load_env_file_1();
408         test_load_env_file_2();
409         test_load_env_file_3();
410         test_load_env_file_4();
411         test_load_env_file_5();
412         TEST_REQ_RUNNING_SYSTEMD(test_install_printf());
413
414         return r;
415 }