chiark / gitweb /
core: add new ConditionArchitecture() that checks the architecture returned by uname...
[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         log_full(r == 0 ? LOG_INFO : LOG_ERR,
52                  "unit_file_get_list: %s", strerror(-r));
53         if (r < 0)
54                 return EXIT_FAILURE;
55
56         HASHMAP_FOREACH(p, h, i)
57                 printf("%s = %s\n", p->path, unit_file_state_to_string(p->state));
58
59         unit_file_list_free(h);
60
61         return 0;
62 }
63
64 static void check_execcommand(ExecCommand *c,
65                               const char* path,
66                               const char* argv0,
67                               const char* argv1,
68                               bool ignore) {
69         assert_se(c);
70         log_info("%s %s %s %s",
71                  c->path, c->argv[0], c->argv[1], c->argv[2]);
72         assert_se(streq(c->path, path));
73         assert_se(streq(c->argv[0], argv0));
74         assert_se(streq(c->argv[1], argv1));
75         assert_se(c->argv[2] == NULL);
76         assert_se(c->ignore == ignore);
77 }
78
79 static void test_config_parse_exec(void) {
80         /* int config_parse_exec( */
81         /*         const char *filename, */
82         /*         unsigned line, */
83         /*         const char *section, */
84         /*         unsigned section_line, */
85         /*         const char *lvalue, */
86         /*         int ltype, */
87         /*         const char *rvalue, */
88         /*         void *data, */
89         /*         void *userdata) */
90         int r;
91
92         ExecCommand *c = NULL, *c1;
93
94         /* basic test */
95         r = config_parse_exec(NULL, "fake", 1, "section", 1,
96                               "LValue", 0, "/RValue r1",
97                               &c, NULL);
98         assert_se(r >= 0);
99         check_execcommand(c, "/RValue", "/RValue", "r1", false);
100
101         r = config_parse_exec(NULL, "fake", 2, "section", 1,
102                               "LValue", 0, "/RValue///slashes/// r1",
103                               &c, NULL);
104        /* test slashes */
105         assert_se(r >= 0);
106         c1 = c->command_next;
107         check_execcommand(c1, "/RValue/slashes", "/RValue///slashes///",
108                           "r1", false);
109
110         /* honour_argv0 */
111         r = config_parse_exec(NULL, "fake", 3, "section", 1,
112                               "LValue", 0, "@/RValue///slashes2/// argv0 r1",
113                               &c, NULL);
114         assert_se(r >= 0);
115         c1 = c1->command_next;
116         check_execcommand(c1, "/RValue/slashes2", "argv0", "r1", false);
117
118         /* ignore && honour_argv0 */
119         r = config_parse_exec(NULL, "fake", 4, "section", 1,
120                               "LValue", 0, "-@/RValue///slashes3/// argv0a r1",
121                               &c, NULL);
122         assert_se(r >= 0);
123         c1 = c1->command_next;
124         check_execcommand(c1,
125                           "/RValue/slashes3", "argv0a", "r1", true);
126
127         /* ignore && honour_argv0 */
128         r = config_parse_exec(NULL, "fake", 4, "section", 1,
129                               "LValue", 0, "@-/RValue///slashes4/// argv0b r1",
130                               &c, NULL);
131         assert_se(r >= 0);
132         c1 = c1->command_next;
133         check_execcommand(c1,
134                           "/RValue/slashes4", "argv0b", "r1", true);
135
136         /* ignore && ignore */
137         r = config_parse_exec(NULL, "fake", 4, "section", 1,
138                               "LValue", 0, "--/RValue argv0 r1",
139                               &c, NULL);
140         assert_se(r == 0);
141         assert_se(c1->command_next == NULL);
142
143         /* ignore && ignore */
144         r = config_parse_exec(NULL, "fake", 4, "section", 1,
145                               "LValue", 0, "-@-/RValue argv0 r1",
146                               &c, NULL);
147         assert_se(r == 0);
148         assert_se(c1->command_next == NULL);
149
150         /* semicolon */
151         r = config_parse_exec(NULL, "fake", 5, "section", 1,
152                               "LValue", 0,
153                               "-@/RValue argv0 r1 ; "
154                               "/goo/goo boo",
155                               &c, NULL);
156         assert_se(r >= 0);
157         c1 = c1->command_next;
158         check_execcommand(c1,
159                           "/RValue", "argv0", "r1", true);
160
161         c1 = c1->command_next;
162         check_execcommand(c1,
163                           "/goo/goo", "/goo/goo", "boo", false);
164
165         /* trailing semicolon */
166         r = config_parse_exec(NULL, "fake", 5, "section", 1,
167                               "LValue", 0,
168                               "-@/RValue argv0 r1 ; ",
169                               &c, NULL);
170         assert_se(r >= 0);
171         c1 = c1->command_next;
172         check_execcommand(c1,
173                           "/RValue", "argv0", "r1", true);
174
175         assert_se(c1->command_next == NULL);
176
177         /* escaped semicolon */
178         r = config_parse_exec(NULL, "fake", 5, "section", 1,
179                               "LValue", 0,
180                               "/usr/bin/find \\;",
181                               &c, NULL);
182         assert_se(r >= 0);
183         c1 = c1->command_next;
184         check_execcommand(c1,
185                           "/usr/bin/find", "/usr/bin/find", ";", false);
186
187         exec_command_free_list(c);
188 }
189
190 #define env_file_1                              \
191         "a=a\n"                                 \
192         "b=b\\\n"                               \
193         "c\n"                                   \
194         "d=d\\\n"                               \
195         "e\\\n"                                 \
196         "f\n"                                   \
197         "g=g\\ \n"                              \
198         "h=h\n"                                 \
199         "i=i\\"
200
201 #define env_file_2                              \
202         "a=a\\\n"
203
204 #define env_file_3 \
205         "#SPAMD_ARGS=\"-d --socketpath=/var/lib/bulwark/spamd \\\n" \
206         "#--nouser-config                                     \\\n" \
207         "normal=line"
208
209 #define env_file_4 \
210        "# Generated\n" \
211        "\n" \
212        "HWMON_MODULES=\"coretemp f71882fg\"\n" \
213        "\n" \
214        "# For compatibility reasons\n" \
215        "\n" \
216        "MODULE_0=coretemp\n" \
217        "MODULE_1=f71882fg"
218
219
220 static void test_load_env_file_1(void) {
221         _cleanup_strv_free_ char **data = NULL;
222         int r;
223
224         char name[] = "/tmp/test-load-env-file.XXXXXX";
225         _cleanup_close_ int fd;
226
227         fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
228         assert(fd >= 0);
229         assert_se(write(fd, env_file_1, sizeof(env_file_1)) == sizeof(env_file_1));
230
231         r = load_env_file(name, NULL, &data);
232         assert(r == 0);
233         assert(streq(data[0], "a=a"));
234         assert(streq(data[1], "b=bc"));
235         assert(streq(data[2], "d=def"));
236         assert(streq(data[3], "g=g "));
237         assert(streq(data[4], "h=h"));
238         assert(streq(data[5], "i=i"));
239         assert(data[6] == NULL);
240         unlink(name);
241 }
242
243 static void test_load_env_file_2(void) {
244         _cleanup_strv_free_ char **data = NULL;
245         int r;
246
247         char name[] = "/tmp/test-load-env-file.XXXXXX";
248         _cleanup_close_ int fd;
249
250         fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
251         assert(fd >= 0);
252         assert_se(write(fd, env_file_2, sizeof(env_file_2)) == sizeof(env_file_2));
253
254         r = load_env_file(name, NULL, &data);
255         assert(r == 0);
256         assert(streq(data[0], "a=a"));
257         assert(data[1] == NULL);
258         unlink(name);
259 }
260
261 static void test_load_env_file_3(void) {
262         _cleanup_strv_free_ char **data = NULL;
263         int r;
264
265         char name[] = "/tmp/test-load-env-file.XXXXXX";
266         _cleanup_close_ int fd;
267
268         fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
269         assert(fd >= 0);
270         assert_se(write(fd, env_file_3, sizeof(env_file_3)) == sizeof(env_file_3));
271
272         r = load_env_file(name, NULL, &data);
273         assert(r == 0);
274         assert(data == NULL);
275         unlink(name);
276 }
277
278 static void test_load_env_file_4(void) {
279         _cleanup_strv_free_ char **data = NULL;
280         char name[] = "/tmp/test-load-env-file.XXXXXX";
281         _cleanup_close_ int fd;
282         int r;
283
284         fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
285         assert(fd >= 0);
286         assert_se(write(fd, env_file_4, sizeof(env_file_4)) == sizeof(env_file_4));
287
288         r = load_env_file(name, NULL, &data);
289         assert(r == 0);
290         assert(streq(data[0], "HWMON_MODULES=coretemp f71882fg"));
291         assert(streq(data[1], "MODULE_0=coretemp"));
292         assert(streq(data[2], "MODULE_1=f71882fg"));
293         assert(data[3] == NULL);
294         unlink(name);
295 }
296
297
298 static void test_install_printf(void) {
299         char    name[] = "name.service",
300                 path[] = "/run/systemd/system/name.service",
301                 user[] = "xxxx-no-such-user";
302         InstallInfo i = {name, path, user};
303         InstallInfo i2 = {name, path, NULL};
304         char    name3[] = "name@inst.service",
305                 path3[] = "/run/systemd/system/name.service";
306         InstallInfo i3 = {name3, path3, user};
307         InstallInfo i4 = {name3, path3, NULL};
308
309         _cleanup_free_ char *mid, *bid, *host;
310
311         assert_se(specifier_machine_id('m', NULL, NULL, &mid) >= 0 && mid);
312         assert_se(specifier_boot_id('b', NULL, NULL, &bid) >= 0 && bid);
313         assert_se((host = gethostname_malloc()));
314
315 #define expect(src, pattern, result)                                    \
316         do {                                                            \
317                 _cleanup_free_ char *t = NULL;                          \
318                 _cleanup_free_ char                                     \
319                         *d1 = strdup(i.name),                           \
320                         *d2 = strdup(i.path),                           \
321                         *d3 = strdup(i.user);                           \
322                 assert_se(install_full_printf(&src, pattern, &t) >= 0 || !result); \
323                 memzero(i.name, strlen(i.name));                        \
324                 memzero(i.path, strlen(i.path));                        \
325                 memzero(i.user, strlen(i.user));                        \
326                 assert(d1 && d2 && d3);                                 \
327                 if (result) {                                           \
328                         printf("%s\n", t);                              \
329                         assert(streq(t, result));                       \
330                 } else assert(t == NULL);                               \
331                 strcpy(i.name, d1);                                     \
332                 strcpy(i.path, d2);                                     \
333                 strcpy(i.user, d3);                                     \
334         } while(false)
335
336         assert_se(setenv("USER", "root", 1) == 0);
337
338         expect(i, "%n", "name.service");
339         expect(i, "%N", "name");
340         expect(i, "%p", "name");
341         expect(i, "%i", "");
342         expect(i, "%u", "xxxx-no-such-user");
343
344         DISABLE_WARNING_NONNULL;
345         expect(i, "%U", NULL);
346         REENABLE_WARNING;
347
348         expect(i, "%m", mid);
349         expect(i, "%b", bid);
350         expect(i, "%H", host);
351
352         expect(i2, "%u", "root");
353         expect(i2, "%U", "0");
354
355         expect(i3, "%n", "name@inst.service");
356         expect(i3, "%N", "name@inst");
357         expect(i3, "%p", "name");
358         expect(i3, "%u", "xxxx-no-such-user");
359
360         DISABLE_WARNING_NONNULL;
361         expect(i3, "%U", NULL);
362         REENABLE_WARNING;
363
364         expect(i3, "%m", mid);
365         expect(i3, "%b", bid);
366         expect(i3, "%H", host);
367
368         expect(i4, "%u", "root");
369         expect(i4, "%U", "0");
370 }
371
372 int main(int argc, char *argv[]) {
373         int r;
374
375         log_parse_environment();
376         log_open();
377
378         r = test_unit_file_get_set();
379         test_config_parse_exec();
380         test_load_env_file_1();
381         test_load_env_file_2();
382         test_load_env_file_3();
383         test_load_env_file_4();
384         TEST_REQ_RUNNING_SYSTEMD(test_install_printf());
385
386         return r;
387 }