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