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