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