]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/test/test-unit-file.c
tree-wide: beautify remaining copyright statements
[thirdparty/systemd.git] / src / test / test-unit-file.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
b5b46d59 2/***
96b2fb93 3 Copyright © 2013 Zbigniew Jędrzejewski-Szmek
b5b46d59
LP
4***/
5
07630cea 6#include <fcntl.h>
b5b46d59 7#include <stddef.h>
07630cea 8#include <stdio.h>
b5b46d59 9#include <string.h>
a8107a54 10#include <sys/capability.h>
b9893505 11#include <unistd.h>
b5b46d59 12
b5efdb8a 13#include "alloc-util.h"
57b7a260 14#include "all-units.h"
a103496c 15#include "capability-util.h"
4f424df7 16#include "conf-parser.h"
3ffd4af2 17#include "fd-util.h"
07630cea 18#include "fileio.h"
627d2bac 19#include "fs-util.h"
b5b46d59 20#include "hashmap.h"
07630cea
LP
21#include "hostname-util.h"
22#include "install-printf.h"
23#include "install.h"
2c5417ad 24#include "load-fragment.h"
07630cea 25#include "macro.h"
d2120590 26#include "rm-rf.h"
07630cea
LP
27#include "specifier.h"
28#include "string-util.h"
b9893505 29#include "strv.h"
143bfdaf 30#include "test-helper.h"
d2120590 31#include "tests.h"
79413b67 32#include "user-util.h"
07630cea 33#include "util.h"
b5b46d59 34
751e7576 35static int test_unit_file_get_set(void) {
b5b46d59
LP
36 int r;
37 Hashmap *h;
38 Iterator i;
39 UnitFileList *p;
40
d5099efc 41 h = hashmap_new(&string_hash_ops);
bdf7026e 42 assert_se(h);
b5b46d59 43
313fe66f 44 r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h, NULL, NULL);
552c693e 45
4c701096 46 if (IN_SET(r, -EPERM, -EACCES)) {
9eec7d12 47 log_notice_errno(r, "Skipping test: unit_file_get_list: %m");
552c693e
CR
48 return EXIT_TEST_SKIP;
49 }
50
9eec7d12
ZJS
51 log_full_errno(r == 0 ? LOG_INFO : LOG_ERR, r,
52 "unit_file_get_list: %m");
751e7576
CH
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,
503dbda6 68 const char* argv2,
2c5417ad 69 bool ignore) {
4d8629de
ZJS
70 size_t n;
71
2c5417ad 72 assert_se(c);
c8539536
ZJS
73 log_info("expect: \"%s\" [\"%s\" \"%s\" \"%s\"]",
74 path, argv0 ?: path, argv1, argv2);
4d8629de 75 n = strv_length(c->argv);
c8539536 76 log_info("actual: \"%s\" [\"%s\" \"%s\" \"%s\"]",
4d8629de 77 c->path, c->argv[0], n > 0 ? c->argv[1] : NULL, n > 1 ? c->argv[2] : NULL);
2c5417ad 78 assert_se(streq(c->path, path));
c8539536 79 assert_se(streq(c->argv[0], argv0 ?: path));
4d8629de
ZJS
80 if (n > 0)
81 assert_se(streq_ptr(c->argv[1], argv1));
82 if (n > 1)
83 assert_se(streq_ptr(c->argv[2], argv2));
3ed0cd26 84 assert_se(!!(c->flags & EXEC_COMMAND_IGNORE_FAILURE) == ignore);
2c5417ad
ZJS
85}
86
87static void test_config_parse_exec(void) {
c8539536 88 /* int config_parse_exec(
470dca63 89 const char *unit,
c8539536
ZJS
90 const char *filename,
91 unsigned line,
92 const char *section,
93 unsigned section_line,
94 const char *lvalue,
95 int ltype,
96 const char *rvalue,
97 void *data,
98 void *userdata) */
2c5417ad
ZJS
99 int r;
100
101 ExecCommand *c = NULL, *c1;
c8539536 102 const char *ccc;
c70cac54 103 _cleanup_(manager_freep) Manager *m = NULL;
dc409696 104 _cleanup_(unit_freep) Unit *u = NULL;
139891f0 105
e0a3da1f 106 r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_MINIMAL, &m);
139891f0 107 if (MANAGER_SKIP_TEST(r)) {
9eec7d12 108 log_notice_errno(r, "Skipping test: manager_new: %m");
139891f0
WC
109 return;
110 }
111
112 assert_se(r >= 0);
113 assert_se(manager_startup(m, NULL, NULL) >= 0);
114
115 assert_se(u = unit_new(m, sizeof(Service)));
2c5417ad 116
c8539536 117 log_info("/* basic test */");
71a61510 118 r = config_parse_exec(NULL, "fake", 1, "section", 1,
2c5417ad 119 "LValue", 0, "/RValue r1",
139891f0 120 &c, u);
2c5417ad 121 assert_se(r >= 0);
503dbda6 122 check_execcommand(c, "/RValue", "/RValue", "r1", NULL, false);
2c5417ad 123
71a61510 124 r = config_parse_exec(NULL, "fake", 2, "section", 1,
c8539536 125 "LValue", 0, "/RValue///slashes r1///",
139891f0 126 &c, u);
c8539536
ZJS
127
128 log_info("/* test slashes */");
2c5417ad
ZJS
129 assert_se(r >= 0);
130 c1 = c->command_next;
c8539536 131 check_execcommand(c1, "/RValue/slashes", "/RValue///slashes", "r1///", NULL, false);
2c5417ad 132
c8539536
ZJS
133 log_info("/* trailing slash */");
134 r = config_parse_exec(NULL, "fake", 4, "section", 1,
135 "LValue", 0, "/RValue/ argv0 r1",
139891f0 136 &c, u);
bb28e684 137 assert_se(r == -ENOEXEC);
c8539536
ZJS
138 assert_se(c1->command_next == NULL);
139
140 log_info("/* honour_argv0 */");
71a61510 141 r = config_parse_exec(NULL, "fake", 3, "section", 1,
c8539536 142 "LValue", 0, "@/RValue///slashes2 ///argv0 r1",
139891f0 143 &c, u);
2c5417ad
ZJS
144 assert_se(r >= 0);
145 c1 = c1->command_next;
c8539536 146 check_execcommand(c1, "/RValue/slashes2", "///argv0", "r1", NULL, false);
2c5417ad 147
e01ff428
ZJS
148 log_info("/* honour_argv0, no args */");
149 r = config_parse_exec(NULL, "fake", 3, "section", 1,
150 "LValue", 0, "@/RValue",
139891f0 151 &c, u);
bb28e684 152 assert_se(r == -ENOEXEC);
e01ff428
ZJS
153 assert_se(c1->command_next == NULL);
154
c83f1f30 155 log_info("/* no command, whitespace only, reset */");
e01ff428
ZJS
156 r = config_parse_exec(NULL, "fake", 3, "section", 1,
157 "LValue", 0, " ",
139891f0 158 &c, u);
e01ff428 159 assert_se(r == 0);
c83f1f30 160 assert_se(c == NULL);
e01ff428 161
c8539536 162 log_info("/* ignore && honour_argv0 */");
71a61510 163 r = config_parse_exec(NULL, "fake", 4, "section", 1,
c8539536 164 "LValue", 0, "-@/RValue///slashes3 argv0a r1",
139891f0 165 &c, u);
2c5417ad 166 assert_se(r >= 0);
c83f1f30 167 c1 = c;
503dbda6 168 check_execcommand(c1, "/RValue/slashes3", "argv0a", "r1", NULL, true);
2c5417ad 169
c8539536 170 log_info("/* ignore && honour_argv0 */");
71a61510 171 r = config_parse_exec(NULL, "fake", 4, "section", 1,
c8539536 172 "LValue", 0, "@-/RValue///slashes4 argv0b r1",
139891f0 173 &c, u);
0f67f1ef
ZJS
174 assert_se(r >= 0);
175 c1 = c1->command_next;
503dbda6 176 check_execcommand(c1, "/RValue/slashes4", "argv0b", "r1", NULL, true);
0f67f1ef 177
c8539536 178 log_info("/* ignore && ignore */");
71a61510 179 r = config_parse_exec(NULL, "fake", 4, "section", 1,
0f67f1ef 180 "LValue", 0, "--/RValue argv0 r1",
139891f0 181 &c, u);
0f67f1ef
ZJS
182 assert_se(r == 0);
183 assert_se(c1->command_next == NULL);
184
c8539536 185 log_info("/* ignore && ignore (2) */");
71a61510 186 r = config_parse_exec(NULL, "fake", 4, "section", 1,
0f67f1ef 187 "LValue", 0, "-@-/RValue argv0 r1",
139891f0 188 &c, u);
0f67f1ef
ZJS
189 assert_se(r == 0);
190 assert_se(c1->command_next == NULL);
191
c8539536 192 log_info("/* semicolon */");
71a61510 193 r = config_parse_exec(NULL, "fake", 5, "section", 1,
2c5417ad
ZJS
194 "LValue", 0,
195 "-@/RValue argv0 r1 ; "
196 "/goo/goo boo",
139891f0 197 &c, u);
2c5417ad
ZJS
198 assert_se(r >= 0);
199 c1 = c1->command_next;
503dbda6 200 check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
2c5417ad
ZJS
201
202 c1 = c1->command_next;
c8539536 203 check_execcommand(c1, "/goo/goo", NULL, "boo", NULL, false);
2c5417ad 204
0e9800d5
FB
205 log_info("/* two semicolons in a row */");
206 r = config_parse_exec(NULL, "fake", 5, "section", 1,
207 "LValue", 0,
208 "-@/RValue argv0 r1 ; ; "
209 "/goo/goo boo",
139891f0 210 &c, u);
bb28e684 211 assert_se(r == -ENOEXEC);
0e9800d5
FB
212 c1 = c1->command_next;
213 check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
214
215 /* second command fails because the executable name is ";" */
216 assert_se(c1->command_next == NULL);
217
c8539536 218 log_info("/* trailing semicolon */");
71a61510 219 r = config_parse_exec(NULL, "fake", 5, "section", 1,
2c5417ad
ZJS
220 "LValue", 0,
221 "-@/RValue argv0 r1 ; ",
139891f0 222 &c, u);
2c5417ad
ZJS
223 assert_se(r >= 0);
224 c1 = c1->command_next;
503dbda6 225 check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
2c5417ad
ZJS
226
227 assert_se(c1->command_next == NULL);
228
0e9800d5
FB
229 log_info("/* trailing semicolon, no whitespace */");
230 r = config_parse_exec(NULL, "fake", 5, "section", 1,
231 "LValue", 0,
232 "-@/RValue argv0 r1 ;",
139891f0 233 &c, u);
0e9800d5
FB
234 assert_se(r >= 0);
235 c1 = c1->command_next;
236 check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
237
238 assert_se(c1->command_next == NULL);
239
240 log_info("/* trailing semicolon in single quotes */");
241 r = config_parse_exec(NULL, "fake", 5, "section", 1,
242 "LValue", 0,
243 "-@/RValue argv0 r1 ';'",
139891f0 244 &c, u);
0e9800d5
FB
245 assert_se(r >= 0);
246 c1 = c1->command_next;
46a0d98a 247 check_execcommand(c1, "/RValue", "argv0", "r1", ";", true);
0e9800d5 248
c8539536 249 log_info("/* escaped semicolon */");
71a61510 250 r = config_parse_exec(NULL, "fake", 5, "section", 1,
7e1a84f5 251 "LValue", 0,
503dbda6 252 "/bin/find \\;",
139891f0 253 &c, u);
503dbda6
ZJS
254 assert_se(r >= 0);
255 c1 = c1->command_next;
c8539536 256 check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
503dbda6 257
c8539536 258 log_info("/* escaped semicolon with following arg */");
503dbda6
ZJS
259 r = config_parse_exec(NULL, "fake", 5, "section", 1,
260 "LValue", 0,
0e9800d5 261 "/sbin/find \\; /x",
139891f0 262 &c, u);
0e9800d5
FB
263 assert_se(r >= 0);
264 c1 = c1->command_next;
265 check_execcommand(c1,
266 "/sbin/find", NULL, ";", "/x", false);
267
268 log_info("/* escaped semicolon as part of an expression */");
269 r = config_parse_exec(NULL, "fake", 5, "section", 1,
270 "LValue", 0,
271 "/sbin/find \\;x",
139891f0 272 &c, u);
7e1a84f5
OS
273 assert_se(r >= 0);
274 c1 = c1->command_next;
275 check_execcommand(c1,
0e9800d5 276 "/sbin/find", NULL, "\\;x", NULL, false);
c8539536 277
80979f1c
DM
278 log_info("/* encoded semicolon */");
279 r = config_parse_exec(NULL, "fake", 5, "section", 1,
280 "LValue", 0,
281 "/bin/find \\073",
139891f0 282 &c, u);
80979f1c
DM
283 assert_se(r >= 0);
284 c1 = c1->command_next;
ce54255f 285 check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
80979f1c 286
0e9800d5
FB
287 log_info("/* quoted semicolon */");
288 r = config_parse_exec(NULL, "fake", 5, "section", 1,
289 "LValue", 0,
290 "/bin/find \";\"",
139891f0 291 &c, u);
0e9800d5
FB
292 assert_se(r >= 0);
293 c1 = c1->command_next;
46a0d98a 294 check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
0e9800d5
FB
295
296 log_info("/* quoted semicolon with following arg */");
297 r = config_parse_exec(NULL, "fake", 5, "section", 1,
298 "LValue", 0,
299 "/sbin/find \";\" /x",
139891f0 300 &c, u);
0e9800d5
FB
301 assert_se(r >= 0);
302 c1 = c1->command_next;
303 check_execcommand(c1,
46a0d98a 304 "/sbin/find", NULL, ";", "/x", false);
0e9800d5 305
c8539536
ZJS
306 log_info("/* spaces in the filename */");
307 r = config_parse_exec(NULL, "fake", 5, "section", 1,
308 "LValue", 0,
309 "\"/PATH WITH SPACES/daemon\" -1 -2",
139891f0 310 &c, u);
c8539536
ZJS
311 assert_se(r >= 0);
312 c1 = c1->command_next;
313 check_execcommand(c1,
314 "/PATH WITH SPACES/daemon", NULL, "-1", "-2", false);
315
316 log_info("/* spaces in the filename, no args */");
317 r = config_parse_exec(NULL, "fake", 5, "section", 1,
318 "LValue", 0,
319 "\"/PATH WITH SPACES/daemon -1 -2\"",
139891f0 320 &c, u);
c8539536
ZJS
321 assert_se(r >= 0);
322 c1 = c1->command_next;
323 check_execcommand(c1,
324 "/PATH WITH SPACES/daemon -1 -2", NULL, NULL, NULL, false);
325
326 log_info("/* spaces in the filename, everything quoted */");
327 r = config_parse_exec(NULL, "fake", 5, "section", 1,
328 "LValue", 0,
329 "\"/PATH WITH SPACES/daemon\" \"-1\" '-2'",
139891f0 330 &c, u);
c8539536
ZJS
331 assert_se(r >= 0);
332 c1 = c1->command_next;
333 check_execcommand(c1,
334 "/PATH WITH SPACES/daemon", NULL, "-1", "-2", false);
335
336 log_info("/* escaped spaces in the filename */");
337 r = config_parse_exec(NULL, "fake", 5, "section", 1,
338 "LValue", 0,
339 "\"/PATH\\sWITH\\sSPACES/daemon\" '-1 -2'",
139891f0 340 &c, u);
c8539536
ZJS
341 assert_se(r >= 0);
342 c1 = c1->command_next;
343 check_execcommand(c1,
344 "/PATH WITH SPACES/daemon", NULL, "-1 -2", NULL, false);
345
346 log_info("/* escaped spaces in the filename (2) */");
347 r = config_parse_exec(NULL, "fake", 5, "section", 1,
348 "LValue", 0,
349 "\"/PATH\\x20WITH\\x20SPACES/daemon\" \"-1 -2\"",
139891f0 350 &c, u);
c8539536
ZJS
351 assert_se(r >= 0);
352 c1 = c1->command_next;
353 check_execcommand(c1,
354 "/PATH WITH SPACES/daemon", NULL, "-1 -2", NULL, false);
355
356 for (ccc = "abfnrtv\\\'\"x"; *ccc; ccc++) {
357 /* \\x is an incomplete hexadecimal sequence, invalid because of the slash */
358 char path[] = "/path\\X";
359 path[sizeof(path) - 2] = *ccc;
360
361 log_info("/* invalid character: \\%c */", *ccc);
362 r = config_parse_exec(NULL, "fake", 4, "section", 1,
363 "LValue", 0, path,
139891f0 364 &c, u);
bb28e684 365 assert_se(r == -ENOEXEC);
c8539536
ZJS
366 assert_se(c1->command_next == NULL);
367 }
368
369 log_info("/* valid character: \\s */");
370 r = config_parse_exec(NULL, "fake", 4, "section", 1,
371 "LValue", 0, "/path\\s",
139891f0 372 &c, u);
c8539536
ZJS
373 assert_se(r >= 0);
374 c1 = c1->command_next;
375 check_execcommand(c1, "/path ", NULL, NULL, NULL, false);
376
80979f1c
DM
377 log_info("/* quoted backslashes */");
378 r = config_parse_exec(NULL, "fake", 5, "section", 1,
379 "LValue", 0,
380 "/bin/grep '\\w+\\K'",
139891f0 381 &c, u);
80979f1c
DM
382 assert_se(r >= 0);
383 c1 = c1->command_next;
384 check_execcommand(c1, "/bin/grep", NULL, "\\w+\\K", NULL, false);
385
c8539536
ZJS
386 log_info("/* trailing backslash: \\ */");
387 /* backslash is invalid */
388 r = config_parse_exec(NULL, "fake", 4, "section", 1,
389 "LValue", 0, "/path\\",
139891f0 390 &c, u);
bb28e684 391 assert_se(r == -ENOEXEC);
c8539536 392 assert_se(c1->command_next == NULL);
7e1a84f5 393
470dca63
MP
394 log_info("/* missing ending ' */");
395 r = config_parse_exec(NULL, "fake", 4, "section", 1,
396 "LValue", 0, "/path 'foo",
139891f0 397 &c, u);
bb28e684 398 assert_se(r == -ENOEXEC);
470dca63
MP
399 assert_se(c1->command_next == NULL);
400
401 log_info("/* missing ending ' with trailing backslash */");
402 r = config_parse_exec(NULL, "fake", 4, "section", 1,
403 "LValue", 0, "/path 'foo\\",
139891f0 404 &c, u);
bb28e684 405 assert_se(r == -ENOEXEC);
470dca63
MP
406 assert_se(c1->command_next == NULL);
407
35b1078e
MP
408 log_info("/* invalid space between modifiers */");
409 r = config_parse_exec(NULL, "fake", 4, "section", 1,
410 "LValue", 0, "- /path",
139891f0 411 &c, u);
35b1078e
MP
412 assert_se(r == 0);
413 assert_se(c1->command_next == NULL);
414
415 log_info("/* only modifiers, no path */");
416 r = config_parse_exec(NULL, "fake", 4, "section", 1,
417 "LValue", 0, "-",
139891f0 418 &c, u);
35b1078e
MP
419 assert_se(r == 0);
420 assert_se(c1->command_next == NULL);
421
422 log_info("/* empty argument, reset */");
423 r = config_parse_exec(NULL, "fake", 4, "section", 1,
424 "LValue", 0, "",
139891f0 425 &c, u);
35b1078e
MP
426 assert_se(r == 0);
427 assert_se(c == NULL);
428
2c5417ad
ZJS
429 exec_command_free_list(c);
430}
431
88bff424
ZJS
432static void test_config_parse_log_extra_fields(void) {
433 /* int config_parse_log_extra_fields(
434 const char *unit,
435 const char *filename,
436 unsigned line,
437 const char *section,
438 unsigned section_line,
439 const char *lvalue,
440 int ltype,
441 const char *rvalue,
442 void *data,
443 void *userdata) */
444
445 int r;
446
c70cac54 447 _cleanup_(manager_freep) Manager *m = NULL;
dc409696 448 _cleanup_(unit_freep) Unit *u = NULL;
88bff424
ZJS
449 ExecContext c = {};
450
451 r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_MINIMAL, &m);
452 if (MANAGER_SKIP_TEST(r)) {
453 log_notice_errno(r, "Skipping test: manager_new: %m");
454 return;
455 }
456
457 assert_se(r >= 0);
458 assert_se(manager_startup(m, NULL, NULL) >= 0);
459
460 assert_se(u = unit_new(m, sizeof(Service)));
461
462 log_info("/* %s – basic test */", __func__);
463 r = config_parse_log_extra_fields(NULL, "fake", 1, "section", 1,
464 "LValue", 0, "FOO=BAR \"QOOF=quux ' ' \"",
465 &c, u);
466 assert_se(r >= 0);
467 assert_se(c.n_log_extra_fields == 2);
468 assert_se(strneq(c.log_extra_fields[0].iov_base, "FOO=BAR", c.log_extra_fields[0].iov_len));
469 assert_se(strneq(c.log_extra_fields[1].iov_base, "QOOF=quux ' ' ", c.log_extra_fields[1].iov_len));
470
471 log_info("/* %s – add some */", __func__);
472 r = config_parse_log_extra_fields(NULL, "fake", 1, "section", 1,
473 "LValue", 0, "FOO2=BAR2 QOOF2=quux ' '",
474 &c, u);
475 assert_se(r >= 0);
476 assert_se(c.n_log_extra_fields == 4);
477 assert_se(strneq(c.log_extra_fields[0].iov_base, "FOO=BAR", c.log_extra_fields[0].iov_len));
478 assert_se(strneq(c.log_extra_fields[1].iov_base, "QOOF=quux ' ' ", c.log_extra_fields[1].iov_len));
479 assert_se(strneq(c.log_extra_fields[2].iov_base, "FOO2=BAR2", c.log_extra_fields[2].iov_len));
480 assert_se(strneq(c.log_extra_fields[3].iov_base, "QOOF2=quux", c.log_extra_fields[3].iov_len));
481
482 exec_context_dump(&c, stdout, " --> ");
483
484 log_info("/* %s – reset */", __func__);
485 r = config_parse_log_extra_fields(NULL, "fake", 1, "section", 1,
486 "LValue", 0, "",
487 &c, u);
488 assert_se(r >= 0);
489 assert_se(c.n_log_extra_fields == 0);
490
491 exec_context_free_log_extra_fields(&c);
492
88bff424
ZJS
493 log_info("/* %s – bye */", __func__);
494}
495
f73141d7
LP
496#define env_file_1 \
497 "a=a\n" \
498 "b=b\\\n" \
499 "c\n" \
500 "d=d\\\n" \
501 "e\\\n" \
502 "f\n" \
503 "g=g\\ \n" \
504 "h=h\n" \
505 "i=i\\"
506
507#define env_file_2 \
508 "a=a\\\n"
b9893505 509
a3aa7ee6
ZJS
510#define env_file_3 \
511 "#SPAMD_ARGS=\"-d --socketpath=/var/lib/bulwark/spamd \\\n" \
512 "#--nouser-config \\\n" \
513 "normal=line"
514
d3b6d0c2
ZJS
515#define env_file_4 \
516 "# Generated\n" \
517 "\n" \
518 "HWMON_MODULES=\"coretemp f71882fg\"\n" \
519 "\n" \
520 "# For compatibility reasons\n" \
521 "\n" \
522 "MODULE_0=coretemp\n" \
523 "MODULE_1=f71882fg"
524
58f10d40
ILG
525#define env_file_5 \
526 "a=\n" \
527 "b="
d3b6d0c2 528
b9893505 529static void test_load_env_file_1(void) {
7fd1b19b 530 _cleanup_strv_free_ char **data = NULL;
b9893505
ZJS
531 int r;
532
627d2bac 533 _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
2d5bdf5b
LP
534 _cleanup_close_ int fd;
535
646853bd 536 fd = mkostemp_safe(name);
bdf7026e 537 assert_se(fd >= 0);
b9893505
ZJS
538 assert_se(write(fd, env_file_1, sizeof(env_file_1)) == sizeof(env_file_1));
539
717603e3 540 r = load_env_file(NULL, name, NULL, &data);
bdf7026e
TA
541 assert_se(r == 0);
542 assert_se(streq(data[0], "a=a"));
543 assert_se(streq(data[1], "b=bc"));
544 assert_se(streq(data[2], "d=def"));
545 assert_se(streq(data[3], "g=g "));
546 assert_se(streq(data[4], "h=h"));
547 assert_se(streq(data[5], "i=i"));
548 assert_se(data[6] == NULL);
b9893505
ZJS
549}
550
551static void test_load_env_file_2(void) {
7fd1b19b 552 _cleanup_strv_free_ char **data = NULL;
b9893505
ZJS
553 int r;
554
627d2bac 555 _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
2d5bdf5b
LP
556 _cleanup_close_ int fd;
557
646853bd 558 fd = mkostemp_safe(name);
bdf7026e 559 assert_se(fd >= 0);
b9893505
ZJS
560 assert_se(write(fd, env_file_2, sizeof(env_file_2)) == sizeof(env_file_2));
561
717603e3 562 r = load_env_file(NULL, name, NULL, &data);
bdf7026e
TA
563 assert_se(r == 0);
564 assert_se(streq(data[0], "a=a"));
565 assert_se(data[1] == NULL);
b9893505
ZJS
566}
567
a3aa7ee6 568static void test_load_env_file_3(void) {
7fd1b19b 569 _cleanup_strv_free_ char **data = NULL;
a3aa7ee6
ZJS
570 int r;
571
627d2bac 572 _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
2d5bdf5b
LP
573 _cleanup_close_ int fd;
574
646853bd 575 fd = mkostemp_safe(name);
bdf7026e 576 assert_se(fd >= 0);
a3aa7ee6
ZJS
577 assert_se(write(fd, env_file_3, sizeof(env_file_3)) == sizeof(env_file_3));
578
717603e3 579 r = load_env_file(NULL, name, NULL, &data);
bdf7026e
TA
580 assert_se(r == 0);
581 assert_se(data == NULL);
a3aa7ee6
ZJS
582}
583
d3b6d0c2 584static void test_load_env_file_4(void) {
7fd1b19b 585 _cleanup_strv_free_ char **data = NULL;
627d2bac 586 _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
2d5bdf5b 587 _cleanup_close_ int fd;
d3b6d0c2
ZJS
588 int r;
589
646853bd 590 fd = mkostemp_safe(name);
bdf7026e 591 assert_se(fd >= 0);
d3b6d0c2
ZJS
592 assert_se(write(fd, env_file_4, sizeof(env_file_4)) == sizeof(env_file_4));
593
717603e3 594 r = load_env_file(NULL, name, NULL, &data);
bdf7026e
TA
595 assert_se(r == 0);
596 assert_se(streq(data[0], "HWMON_MODULES=coretemp f71882fg"));
597 assert_se(streq(data[1], "MODULE_0=coretemp"));
598 assert_se(streq(data[2], "MODULE_1=f71882fg"));
599 assert_se(data[3] == NULL);
d3b6d0c2
ZJS
600}
601
58f10d40
ILG
602static void test_load_env_file_5(void) {
603 _cleanup_strv_free_ char **data = NULL;
604 int r;
605
627d2bac 606 _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
58f10d40
ILG
607 _cleanup_close_ int fd;
608
646853bd 609 fd = mkostemp_safe(name);
58f10d40
ILG
610 assert_se(fd >= 0);
611 assert_se(write(fd, env_file_5, sizeof(env_file_5)) == sizeof(env_file_5));
612
613 r = load_env_file(NULL, name, NULL, &data);
614 assert_se(r == 0);
615 assert_se(streq(data[0], "a="));
616 assert_se(streq(data[1], "b="));
617 assert_se(data[2] == NULL);
58f10d40 618}
d3b6d0c2 619
7742f7e9
ZJS
620static void test_install_printf(void) {
621 char name[] = "name.service",
79413b67
LP
622 path[] = "/run/systemd/system/name.service";
623 UnitFileInstallInfo i = { .name = name, .path = path, };
624 UnitFileInstallInfo i2 = { .name= name, .path = path, };
7742f7e9 625 char name3[] = "name@inst.service",
ad88e758 626 path3[] = "/run/systemd/system/name.service";
79413b67
LP
627 UnitFileInstallInfo i3 = { .name = name3, .path = path3, };
628 UnitFileInstallInfo i4 = { .name = name3, .path = path3, };
7742f7e9 629
79413b67 630 _cleanup_free_ char *mid = NULL, *bid = NULL, *host = NULL, *uid = NULL, *user = NULL;
7742f7e9 631
19f6d710
LP
632 assert_se(specifier_machine_id('m', NULL, NULL, &mid) >= 0 && mid);
633 assert_se(specifier_boot_id('b', NULL, NULL, &bid) >= 0 && bid);
dcd6361e
ZJS
634 assert_se(host = gethostname_malloc());
635 assert_se(user = uid_to_name(getuid()));
79413b67 636 assert_se(asprintf(&uid, UID_FMT, getuid()) >= 0);
7742f7e9
ZJS
637
638#define expect(src, pattern, result) \
f73141d7 639 do { \
19f6d710 640 _cleanup_free_ char *t = NULL; \
7fd1b19b 641 _cleanup_free_ char \
7742f7e9 642 *d1 = strdup(i.name), \
79413b67 643 *d2 = strdup(i.path); \
19f6d710 644 assert_se(install_full_printf(&src, pattern, &t) >= 0 || !result); \
7742f7e9
ZJS
645 memzero(i.name, strlen(i.name)); \
646 memzero(i.path, strlen(i.path)); \
79413b67 647 assert_se(d1 && d2); \
7742f7e9
ZJS
648 if (result) { \
649 printf("%s\n", t); \
79413b67
LP
650 assert_se(streq(t, result)); \
651 } else assert_se(t == NULL); \
7742f7e9
ZJS
652 strcpy(i.name, d1); \
653 strcpy(i.path, d2); \
9ed794a3 654 } while (false)
7742f7e9 655
7742f7e9
ZJS
656 expect(i, "%n", "name.service");
657 expect(i, "%N", "name");
658 expect(i, "%p", "name");
659 expect(i, "%i", "");
250e9fad 660 expect(i, "%j", "name");
79413b67
LP
661 expect(i, "%u", user);
662 expect(i, "%U", uid);
8fca4e30 663
7742f7e9
ZJS
664 expect(i, "%m", mid);
665 expect(i, "%b", bid);
666 expect(i, "%H", host);
667
79413b67
LP
668 expect(i2, "%u", user);
669 expect(i2, "%U", uid);
7742f7e9
ZJS
670
671 expect(i3, "%n", "name@inst.service");
672 expect(i3, "%N", "name@inst");
673 expect(i3, "%p", "name");
79413b67
LP
674 expect(i3, "%u", user);
675 expect(i3, "%U", uid);
8fca4e30 676
7742f7e9
ZJS
677 expect(i3, "%m", mid);
678 expect(i3, "%b", bid);
679 expect(i3, "%H", host);
680
79413b67
LP
681 expect(i4, "%u", user);
682 expect(i4, "%U", uid);
7742f7e9 683}
b9893505 684
a8107a54
EV
685static uint64_t make_cap(int cap) {
686 return ((uint64_t) 1ULL << (uint64_t) cap);
687}
688
a103496c
IP
689static void test_config_parse_capability_set(void) {
690 /* int config_parse_capability_set(
a8107a54
EV
691 const char *unit,
692 const char *filename,
693 unsigned line,
694 const char *section,
695 unsigned section_line,
696 const char *lvalue,
697 int ltype,
698 const char *rvalue,
699 void *data,
700 void *userdata) */
701 int r;
a103496c 702 uint64_t capability_bounding_set = 0;
a8107a54 703
a103496c 704 r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
a8107a54 705 "CapabilityBoundingSet", 0, "CAP_NET_RAW",
a103496c 706 &capability_bounding_set, NULL);
a8107a54 707 assert_se(r >= 0);
a103496c 708 assert_se(capability_bounding_set == make_cap(CAP_NET_RAW));
a8107a54 709
a103496c 710 r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
a8107a54 711 "CapabilityBoundingSet", 0, "CAP_NET_ADMIN",
a103496c 712 &capability_bounding_set, NULL);
a8107a54 713 assert_se(r >= 0);
a103496c 714 assert_se(capability_bounding_set == (make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN)));
a8107a54 715
7dd09746
YW
716 r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
717 "CapabilityBoundingSet", 0, "~CAP_NET_ADMIN",
718 &capability_bounding_set, NULL);
719 assert_se(r >= 0);
720 assert_se(capability_bounding_set == make_cap(CAP_NET_RAW));
721
a103496c 722 r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
a8107a54 723 "CapabilityBoundingSet", 0, "",
a103496c 724 &capability_bounding_set, NULL);
a8107a54 725 assert_se(r >= 0);
a103496c 726 assert_se(capability_bounding_set == UINT64_C(0));
a8107a54 727
a103496c 728 r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
a8107a54 729 "CapabilityBoundingSet", 0, "~",
a103496c 730 &capability_bounding_set, NULL);
a8107a54 731 assert_se(r >= 0);
a103496c 732 assert_se(cap_test_all(capability_bounding_set));
4b03af4a 733
a103496c
IP
734 capability_bounding_set = 0;
735 r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
4b03af4a 736 "CapabilityBoundingSet", 0, " 'CAP_NET_RAW' WAT_CAP??? CAP_NET_ADMIN CAP'_trailing_garbage",
a103496c 737 &capability_bounding_set, NULL);
4b03af4a 738 assert_se(r >= 0);
a103496c 739 assert_se(capability_bounding_set == (make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN)));
a8107a54
EV
740}
741
a4c18002
LP
742static void test_config_parse_rlimit(void) {
743 struct rlimit * rl[_RLIMIT_MAX] = {};
744
4f424df7 745 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55", rl, NULL) >= 0);
a4c18002
LP
746 assert_se(rl[RLIMIT_NOFILE]);
747 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 55);
748 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
749
4f424df7 750 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55:66", rl, NULL) >= 0);
91518d20
KZ
751 assert_se(rl[RLIMIT_NOFILE]);
752 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 55);
753 assert_se(rl[RLIMIT_NOFILE]->rlim_max == 66);
754
4f424df7 755 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity", rl, NULL) >= 0);
a4c18002
LP
756 assert_se(rl[RLIMIT_NOFILE]);
757 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == RLIM_INFINITY);
758 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
759
4f424df7 760 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity:infinity", rl, NULL) >= 0);
91518d20
KZ
761 assert_se(rl[RLIMIT_NOFILE]);
762 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == RLIM_INFINITY);
763 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
764
d0a7c5f6
LP
765 rl[RLIMIT_NOFILE]->rlim_cur = 10;
766 rl[RLIMIT_NOFILE]->rlim_max = 20;
767
768 /* Invalid values don't change rl */
4f424df7 769 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "10:20:30", rl, NULL) >= 0);
0316f2ae
EV
770 assert_se(rl[RLIMIT_NOFILE]);
771 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
772 assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
773
4f424df7 774 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "wat:wat", rl, NULL) >= 0);
0316f2ae
EV
775 assert_se(rl[RLIMIT_NOFILE]);
776 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
777 assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
778
4f424df7 779 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "66:wat", rl, NULL) >= 0);
0316f2ae
EV
780 assert_se(rl[RLIMIT_NOFILE]);
781 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
782 assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
783
4f424df7 784 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "200:100", rl, NULL) >= 0);
0316f2ae
EV
785 assert_se(rl[RLIMIT_NOFILE]);
786 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
787 assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
788
a4c18002
LP
789 rl[RLIMIT_NOFILE] = mfree(rl[RLIMIT_NOFILE]);
790
4f424df7 791 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "56", rl, NULL) >= 0);
a4c18002
LP
792 assert_se(rl[RLIMIT_CPU]);
793 assert_se(rl[RLIMIT_CPU]->rlim_cur == 56);
794 assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
795
4f424df7 796 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "57s", rl, NULL) >= 0);
a4c18002
LP
797 assert_se(rl[RLIMIT_CPU]);
798 assert_se(rl[RLIMIT_CPU]->rlim_cur == 57);
799 assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
800
4f424df7 801 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "40s:1m", rl, NULL) >= 0);
91518d20
KZ
802 assert_se(rl[RLIMIT_CPU]);
803 assert_se(rl[RLIMIT_CPU]->rlim_cur == 40);
804 assert_se(rl[RLIMIT_CPU]->rlim_max == 60);
805
4f424df7 806 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "infinity", rl, NULL) >= 0);
a4c18002
LP
807 assert_se(rl[RLIMIT_CPU]);
808 assert_se(rl[RLIMIT_CPU]->rlim_cur == RLIM_INFINITY);
809 assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
810
4f424df7 811 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "1234ms", rl, NULL) >= 0);
a4c18002
LP
812 assert_se(rl[RLIMIT_CPU]);
813 assert_se(rl[RLIMIT_CPU]->rlim_cur == 2);
814 assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
815
816 rl[RLIMIT_CPU] = mfree(rl[RLIMIT_CPU]);
817
4f424df7 818 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58", rl, NULL) >= 0);
a4c18002
LP
819 assert_se(rl[RLIMIT_RTTIME]);
820 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 58);
821 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
822
4f424df7 823 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58:60", rl, NULL) >= 0);
91518d20
KZ
824 assert_se(rl[RLIMIT_RTTIME]);
825 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 58);
826 assert_se(rl[RLIMIT_RTTIME]->rlim_max == 60);
827
4f424df7 828 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s", rl, NULL) >= 0);
a4c18002
LP
829 assert_se(rl[RLIMIT_RTTIME]);
830 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 59 * USEC_PER_SEC);
831 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
832
4f424df7 833 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s:123s", rl, NULL) >= 0);
91518d20
KZ
834 assert_se(rl[RLIMIT_RTTIME]);
835 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 59 * USEC_PER_SEC);
836 assert_se(rl[RLIMIT_RTTIME]->rlim_max == 123 * USEC_PER_SEC);
837
4f424df7 838 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity", rl, NULL) >= 0);
a4c18002
LP
839 assert_se(rl[RLIMIT_RTTIME]);
840 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == RLIM_INFINITY);
841 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
842
4f424df7 843 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity:infinity", rl, NULL) >= 0);
91518d20
KZ
844 assert_se(rl[RLIMIT_RTTIME]);
845 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == RLIM_INFINITY);
846 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
847
4f424df7 848 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "2345ms", rl, NULL) >= 0);
a4c18002
LP
849 assert_se(rl[RLIMIT_RTTIME]);
850 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 2345 * USEC_PER_MSEC);
851 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
852
853 rl[RLIMIT_RTTIME] = mfree(rl[RLIMIT_RTTIME]);
854}
855
4ad4beec
EV
856static void test_config_parse_pass_environ(void) {
857 /* int config_parse_pass_environ(
858 const char *unit,
859 const char *filename,
860 unsigned line,
861 const char *section,
862 unsigned section_line,
863 const char *lvalue,
864 int ltype,
865 const char *rvalue,
866 void *data,
867 void *userdata) */
868 int r;
869 _cleanup_strv_free_ char **passenv = NULL;
870
871 r = config_parse_pass_environ(NULL, "fake", 1, "section", 1,
872 "PassEnvironment", 0, "A B",
873 &passenv, NULL);
874 assert_se(r >= 0);
875 assert_se(strv_length(passenv) == 2);
876 assert_se(streq(passenv[0], "A"));
877 assert_se(streq(passenv[1], "B"));
878
879 r = config_parse_pass_environ(NULL, "fake", 1, "section", 1,
880 "PassEnvironment", 0, "",
881 &passenv, NULL);
882 assert_se(r >= 0);
883 assert_se(strv_isempty(passenv));
884
885 r = config_parse_pass_environ(NULL, "fake", 1, "section", 1,
886 "PassEnvironment", 0, "'invalid name' 'normal_name' A=1 \\",
887 &passenv, NULL);
888 assert_se(r >= 0);
889 assert_se(strv_length(passenv) == 1);
890 assert_se(streq(passenv[0], "normal_name"));
891
892}
893
0c700d39
EV
894static void test_unit_dump_config_items(void) {
895 unit_dump_config_items(stdout);
896}
897
2c5417ad 898int main(int argc, char *argv[]) {
f942504e 899 _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
751e7576 900 int r;
2c5417ad 901
c1b6628d
ZJS
902 log_parse_environment();
903 log_open();
904
651d47d1
ZJS
905 r = enter_cgroup_subroot();
906 if (r == -ENOMEDIUM) {
907 log_notice_errno(r, "Skipping test: cgroupfs not available");
908 return EXIT_TEST_SKIP;
909 }
8c759b33 910
d2120590
LP
911 assert_se(runtime_dir = setup_fake_runtime_dir());
912
751e7576 913 r = test_unit_file_get_set();
2c5417ad 914 test_config_parse_exec();
88bff424 915 test_config_parse_log_extra_fields();
a103496c 916 test_config_parse_capability_set();
a4c18002 917 test_config_parse_rlimit();
4ad4beec 918 test_config_parse_pass_environ();
b9893505
ZJS
919 test_load_env_file_1();
920 test_load_env_file_2();
a3aa7ee6 921 test_load_env_file_3();
d3b6d0c2 922 test_load_env_file_4();
58f10d40 923 test_load_env_file_5();
143bfdaf 924 TEST_REQ_RUNNING_SYSTEMD(test_install_printf());
0c700d39 925 test_unit_dump_config_items();
b5b46d59 926
751e7576 927 return r;
b5b46d59 928}