chiark / gitweb /
dc6bc55244dc65ecec4fa571ce29b69d18c60fc7
[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((mid = specifier_machine_id('m', NULL, NULL)));
306         assert_se((bid = specifier_boot_id('b', NULL, NULL)));
307         assert_se((host = gethostname_malloc()));
308
309 #define expect(src, pattern, result)                                    \
310         do {                                                            \
311                 _cleanup_free_ char *t = install_full_printf(&src, pattern); \
312                 _cleanup_free_ char                                     \
313                         *d1 = strdup(i.name),                           \
314                         *d2 = strdup(i.path),                           \
315                         *d3 = strdup(i.user);                           \
316                 memzero(i.name, strlen(i.name));                        \
317                 memzero(i.path, strlen(i.path));                        \
318                 memzero(i.user, strlen(i.user));                        \
319                 assert(d1 && d2 && d3);                                 \
320                 if (result) {                                           \
321                         printf("%s\n", t);                              \
322                         assert(streq(t, result));                       \
323                 } else assert(t == NULL);                               \
324                 strcpy(i.name, d1);                                     \
325                 strcpy(i.path, d2);                                     \
326                 strcpy(i.user, d3);                                     \
327         } while(false)
328
329         assert_se(setenv("USER", "root", 1) == 0);
330
331         expect(i, "%n", "name.service");
332         expect(i, "%N", "name");
333         expect(i, "%p", "name");
334         expect(i, "%i", "");
335         expect(i, "%u", "xxxx-no-such-user");
336         expect(i, "%U", NULL);
337         expect(i, "%m", mid);
338         expect(i, "%b", bid);
339         expect(i, "%H", host);
340
341         expect(i2, "%u", "root");
342         expect(i2, "%U", "0");
343
344         expect(i3, "%n", "name@inst.service");
345         expect(i3, "%N", "name@inst");
346         expect(i3, "%p", "name");
347         expect(i3, "%u", "xxxx-no-such-user");
348         expect(i3, "%U", NULL);
349         expect(i3, "%m", mid);
350         expect(i3, "%b", bid);
351         expect(i3, "%H", host);
352
353         expect(i4, "%u", "root");
354         expect(i4, "%U", "0");
355 }
356 #pragma GCC diagnostic pop
357
358 int main(int argc, char *argv[]) {
359         int r;
360
361         log_parse_environment();
362         log_open();
363
364         r = test_unit_file_get_set();
365         test_config_parse_exec();
366         test_load_env_file_1();
367         test_load_env_file_2();
368         test_load_env_file_3();
369         test_load_env_file_4();
370         TEST_REQ_RUNNING_SYSTEMD(test_install_printf());
371
372         return r;
373 }