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