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