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