]> git.ipfire.org Git - thirdparty/systemd.git/blob - 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
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include <fcntl.h>
4 #include <stddef.h>
5 #include <stdio.h>
6 #include <unistd.h>
7
8 #include "all-units.h"
9 #include "alloc-util.h"
10 #include "capability-util.h"
11 #include "conf-parser.h"
12 #include "fd-util.h"
13 #include "format-util.h"
14 #include "fs-util.h"
15 #include "hashmap.h"
16 #include "hostname-util.h"
17 #include "install-printf.h"
18 #include "install.h"
19 #include "load-fragment.h"
20 #include "macro.h"
21 #include "memory-util.h"
22 #include "rm-rf.h"
23 #include "specifier.h"
24 #include "string-util.h"
25 #include "strv.h"
26 #include "test-helper.h"
27 #include "tests.h"
28 #include "tmpfile-util.h"
29 #include "user-util.h"
30
31 static int test_unit_file_get_set(void) {
32 int r;
33 Hashmap *h;
34 Iterator i;
35 UnitFileList *p;
36
37 h = hashmap_new(&string_hash_ops);
38 assert_se(h);
39
40 r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h, NULL, NULL);
41 if (IN_SET(r, -EPERM, -EACCES))
42 return log_tests_skipped_errno(r, "unit_file_get_list");
43
44 log_full_errno(r == 0 ? LOG_INFO : LOG_ERR, r,
45 "unit_file_get_list: %m");
46 if (r < 0)
47 return EXIT_FAILURE;
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);
53
54 return 0;
55 }
56
57 static void check_execcommand(ExecCommand *c,
58 const char* path,
59 const char* argv0,
60 const char* argv1,
61 const char* argv2,
62 bool ignore) {
63 size_t n;
64
65 assert_se(c);
66 log_info("expect: \"%s\" [\"%s\" \"%s\" \"%s\"]",
67 path, argv0 ?: path, argv1, argv2);
68 n = strv_length(c->argv);
69 log_info("actual: \"%s\" [\"%s\" \"%s\" \"%s\"]",
70 c->path, c->argv[0], n > 0 ? c->argv[1] : NULL, n > 1 ? c->argv[2] : NULL);
71 assert_se(streq(c->path, path));
72 assert_se(streq(c->argv[0], argv0 ?: path));
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));
77 assert_se(!!(c->flags & EXEC_COMMAND_IGNORE_FAILURE) == ignore);
78 }
79
80 static void test_config_parse_exec(void) {
81 /* int config_parse_exec(
82 const char *unit,
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) */
92 int r;
93
94 ExecCommand *c = NULL, *c1;
95 const char *ccc;
96 _cleanup_(manager_freep) Manager *m = NULL;
97 _cleanup_(unit_freep) Unit *u = NULL;
98
99 r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_MINIMAL, &m);
100 if (MANAGER_SKIP_TEST(r)) {
101 log_notice_errno(r, "Skipping test: manager_new: %m");
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)));
109
110 log_info("/* basic test */");
111 r = config_parse_exec(NULL, "fake", 1, "section", 1,
112 "LValue", 0, "/RValue r1",
113 &c, u);
114 assert_se(r >= 0);
115 check_execcommand(c, "/RValue", "/RValue", "r1", NULL, false);
116
117 r = config_parse_exec(NULL, "fake", 2, "section", 1,
118 "LValue", 0, "/RValue///slashes r1///",
119 &c, u);
120
121 log_info("/* test slashes */");
122 assert_se(r >= 0);
123 c1 = c->command_next;
124 check_execcommand(c1, "/RValue/slashes", "/RValue///slashes", "r1///", NULL, false);
125
126 log_info("/* trailing slash */");
127 r = config_parse_exec(NULL, "fake", 4, "section", 1,
128 "LValue", 0, "/RValue/ argv0 r1",
129 &c, u);
130 assert_se(r == -ENOEXEC);
131 assert_se(c1->command_next == NULL);
132
133 log_info("/* honour_argv0 */");
134 r = config_parse_exec(NULL, "fake", 3, "section", 1,
135 "LValue", 0, "@/RValue///slashes2 ///argv0 r1",
136 &c, u);
137 assert_se(r >= 0);
138 c1 = c1->command_next;
139 check_execcommand(c1, "/RValue/slashes2", "///argv0", "r1", NULL, false);
140
141 log_info("/* honour_argv0, no args */");
142 r = config_parse_exec(NULL, "fake", 3, "section", 1,
143 "LValue", 0, "@/RValue",
144 &c, u);
145 assert_se(r == -ENOEXEC);
146 assert_se(c1->command_next == NULL);
147
148 log_info("/* no command, whitespace only, reset */");
149 r = config_parse_exec(NULL, "fake", 3, "section", 1,
150 "LValue", 0, " ",
151 &c, u);
152 assert_se(r == 0);
153 assert_se(c == NULL);
154
155 log_info("/* ignore && honour_argv0 */");
156 r = config_parse_exec(NULL, "fake", 4, "section", 1,
157 "LValue", 0, "-@/RValue///slashes3 argv0a r1",
158 &c, u);
159 assert_se(r >= 0);
160 c1 = c;
161 check_execcommand(c1, "/RValue/slashes3", "argv0a", "r1", NULL, true);
162
163 log_info("/* ignore && honour_argv0 */");
164 r = config_parse_exec(NULL, "fake", 4, "section", 1,
165 "LValue", 0, "@-/RValue///slashes4 argv0b r1",
166 &c, u);
167 assert_se(r >= 0);
168 c1 = c1->command_next;
169 check_execcommand(c1, "/RValue/slashes4", "argv0b", "r1", NULL, true);
170
171 log_info("/* ignore && ignore */");
172 r = config_parse_exec(NULL, "fake", 4, "section", 1,
173 "LValue", 0, "--/RValue argv0 r1",
174 &c, u);
175 assert_se(r == 0);
176 assert_se(c1->command_next == NULL);
177
178 log_info("/* ignore && ignore (2) */");
179 r = config_parse_exec(NULL, "fake", 4, "section", 1,
180 "LValue", 0, "-@-/RValue argv0 r1",
181 &c, u);
182 assert_se(r == 0);
183 assert_se(c1->command_next == NULL);
184
185 log_info("/* semicolon */");
186 r = config_parse_exec(NULL, "fake", 5, "section", 1,
187 "LValue", 0,
188 "-@/RValue argv0 r1 ; "
189 "/goo/goo boo",
190 &c, u);
191 assert_se(r >= 0);
192 c1 = c1->command_next;
193 check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
194
195 c1 = c1->command_next;
196 check_execcommand(c1, "/goo/goo", NULL, "boo", NULL, false);
197
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",
203 &c, u);
204 assert_se(r == -ENOEXEC);
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
211 log_info("/* trailing semicolon */");
212 r = config_parse_exec(NULL, "fake", 5, "section", 1,
213 "LValue", 0,
214 "-@/RValue argv0 r1 ; ",
215 &c, u);
216 assert_se(r >= 0);
217 c1 = c1->command_next;
218 check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
219
220 assert_se(c1->command_next == NULL);
221
222 log_info("/* trailing semicolon, no whitespace */");
223 r = config_parse_exec(NULL, "fake", 5, "section", 1,
224 "LValue", 0,
225 "-@/RValue argv0 r1 ;",
226 &c, u);
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 ';'",
237 &c, u);
238 assert_se(r >= 0);
239 c1 = c1->command_next;
240 check_execcommand(c1, "/RValue", "argv0", "r1", ";", true);
241
242 log_info("/* escaped semicolon */");
243 r = config_parse_exec(NULL, "fake", 5, "section", 1,
244 "LValue", 0,
245 "/bin/find \\;",
246 &c, u);
247 assert_se(r >= 0);
248 c1 = c1->command_next;
249 check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
250
251 log_info("/* escaped semicolon with following arg */");
252 r = config_parse_exec(NULL, "fake", 5, "section", 1,
253 "LValue", 0,
254 "/sbin/find \\; /x",
255 &c, u);
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",
265 &c, u);
266 assert_se(r >= 0);
267 c1 = c1->command_next;
268 check_execcommand(c1,
269 "/sbin/find", NULL, "\\;x", NULL, false);
270
271 log_info("/* encoded semicolon */");
272 r = config_parse_exec(NULL, "fake", 5, "section", 1,
273 "LValue", 0,
274 "/bin/find \\073",
275 &c, u);
276 assert_se(r >= 0);
277 c1 = c1->command_next;
278 check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
279
280 log_info("/* quoted semicolon */");
281 r = config_parse_exec(NULL, "fake", 5, "section", 1,
282 "LValue", 0,
283 "/bin/find \";\"",
284 &c, u);
285 assert_se(r >= 0);
286 c1 = c1->command_next;
287 check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
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",
293 &c, u);
294 assert_se(r >= 0);
295 c1 = c1->command_next;
296 check_execcommand(c1,
297 "/sbin/find", NULL, ";", "/x", false);
298
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",
303 &c, u);
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\"",
313 &c, u);
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'",
323 &c, u);
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'",
333 &c, u);
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\"",
343 &c, u);
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,
357 &c, u);
358 assert_se(r == -ENOEXEC);
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",
365 &c, u);
366 assert_se(r >= 0);
367 c1 = c1->command_next;
368 check_execcommand(c1, "/path ", NULL, NULL, NULL, false);
369
370 log_info("/* quoted backslashes */");
371 r = config_parse_exec(NULL, "fake", 5, "section", 1,
372 "LValue", 0,
373 "/bin/grep '\\w+\\K'",
374 &c, u);
375 assert_se(r >= 0);
376 c1 = c1->command_next;
377 check_execcommand(c1, "/bin/grep", NULL, "\\w+\\K", NULL, false);
378
379 log_info("/* trailing backslash: \\ */");
380 /* backslash is invalid */
381 r = config_parse_exec(NULL, "fake", 4, "section", 1,
382 "LValue", 0, "/path\\",
383 &c, u);
384 assert_se(r == -ENOEXEC);
385 assert_se(c1->command_next == NULL);
386
387 log_info("/* missing ending ' */");
388 r = config_parse_exec(NULL, "fake", 4, "section", 1,
389 "LValue", 0, "/path 'foo",
390 &c, u);
391 assert_se(r == -ENOEXEC);
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\\",
397 &c, u);
398 assert_se(r == -ENOEXEC);
399 assert_se(c1->command_next == NULL);
400
401 log_info("/* invalid space between modifiers */");
402 r = config_parse_exec(NULL, "fake", 4, "section", 1,
403 "LValue", 0, "- /path",
404 &c, u);
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, "-",
411 &c, u);
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, "",
418 &c, u);
419 assert_se(r == 0);
420 assert_se(c == NULL);
421
422 exec_command_free_list(c);
423 }
424
425 static 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
440 _cleanup_(manager_freep) Manager *m = NULL;
441 _cleanup_(unit_freep) Unit *u = NULL;
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
486 log_info("/* %s – bye */", __func__);
487 }
488
489 static void test_install_printf(void) {
490 char name[] = "name.service",
491 path[] = "/run/systemd/system/name.service";
492 UnitFileInstallInfo i = { .name = name, .path = path, };
493 UnitFileInstallInfo i2 = { .name= name, .path = path, };
494 char name3[] = "name@inst.service",
495 path3[] = "/run/systemd/system/name.service";
496 UnitFileInstallInfo i3 = { .name = name3, .path = path3, };
497 UnitFileInstallInfo i4 = { .name = name3, .path = path3, };
498
499 _cleanup_free_ char *mid = NULL, *bid = NULL, *host = NULL, *gid = NULL, *group = NULL, *uid = NULL, *user = NULL;
500
501 assert_se(specifier_machine_id('m', NULL, NULL, &mid) >= 0 && mid);
502 assert_se(specifier_boot_id('b', NULL, NULL, &bid) >= 0 && bid);
503 assert_se(host = gethostname_malloc());
504 assert_se(group = gid_to_name(getgid()));
505 assert_se(asprintf(&gid, UID_FMT, getgid()) >= 0);
506 assert_se(user = uid_to_name(getuid()));
507 assert_se(asprintf(&uid, UID_FMT, getuid()) >= 0);
508
509 #define expect(src, pattern, result) \
510 do { \
511 _cleanup_free_ char *t = NULL; \
512 _cleanup_free_ char \
513 *d1 = strdup(i.name), \
514 *d2 = strdup(i.path); \
515 assert_se(install_full_printf(&src, pattern, &t) >= 0 || !result); \
516 memzero(i.name, strlen(i.name)); \
517 memzero(i.path, strlen(i.path)); \
518 assert_se(d1 && d2); \
519 if (result) { \
520 printf("%s\n", t); \
521 assert_se(streq(t, result)); \
522 } else assert_se(t == NULL); \
523 strcpy(i.name, d1); \
524 strcpy(i.path, d2); \
525 } while (false)
526
527 expect(i, "%n", "name.service");
528 expect(i, "%N", "name");
529 expect(i, "%p", "name");
530 expect(i, "%i", "");
531 expect(i, "%j", "name");
532 expect(i, "%g", group);
533 expect(i, "%G", gid);
534 expect(i, "%u", user);
535 expect(i, "%U", uid);
536
537 expect(i, "%m", mid);
538 expect(i, "%b", bid);
539 expect(i, "%H", host);
540
541 expect(i2, "%g", group);
542 expect(i2, "%G", gid);
543 expect(i2, "%u", user);
544 expect(i2, "%U", uid);
545
546 expect(i3, "%n", "name@inst.service");
547 expect(i3, "%N", "name@inst");
548 expect(i3, "%p", "name");
549 expect(i3, "%g", group);
550 expect(i3, "%G", gid);
551 expect(i3, "%u", user);
552 expect(i3, "%U", uid);
553
554 expect(i3, "%m", mid);
555 expect(i3, "%b", bid);
556 expect(i3, "%H", host);
557
558 expect(i4, "%g", group);
559 expect(i4, "%G", gid);
560 expect(i4, "%u", user);
561 expect(i4, "%U", uid);
562 }
563
564 static uint64_t make_cap(int cap) {
565 return ((uint64_t) 1ULL << (uint64_t) cap);
566 }
567
568 static void test_config_parse_capability_set(void) {
569 /* int config_parse_capability_set(
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;
581 uint64_t capability_bounding_set = 0;
582
583 r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
584 "CapabilityBoundingSet", 0, "CAP_NET_RAW",
585 &capability_bounding_set, NULL);
586 assert_se(r >= 0);
587 assert_se(capability_bounding_set == make_cap(CAP_NET_RAW));
588
589 r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
590 "CapabilityBoundingSet", 0, "CAP_NET_ADMIN",
591 &capability_bounding_set, NULL);
592 assert_se(r >= 0);
593 assert_se(capability_bounding_set == (make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN)));
594
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
601 r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
602 "CapabilityBoundingSet", 0, "",
603 &capability_bounding_set, NULL);
604 assert_se(r >= 0);
605 assert_se(capability_bounding_set == UINT64_C(0));
606
607 r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
608 "CapabilityBoundingSet", 0, "~",
609 &capability_bounding_set, NULL);
610 assert_se(r >= 0);
611 assert_se(cap_test_all(capability_bounding_set));
612
613 capability_bounding_set = 0;
614 r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
615 "CapabilityBoundingSet", 0, " 'CAP_NET_RAW' WAT_CAP??? CAP_NET_ADMIN CAP'_trailing_garbage",
616 &capability_bounding_set, NULL);
617 assert_se(r >= 0);
618 assert_se(capability_bounding_set == (make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN)));
619 }
620
621 static void test_config_parse_rlimit(void) {
622 struct rlimit * rl[_RLIMIT_MAX] = {};
623
624 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55", rl, NULL) >= 0);
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
629 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55:66", rl, NULL) >= 0);
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
634 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity", rl, NULL) >= 0);
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
639 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity:infinity", rl, NULL) >= 0);
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
644 rl[RLIMIT_NOFILE]->rlim_cur = 10;
645 rl[RLIMIT_NOFILE]->rlim_max = 20;
646
647 /* Invalid values don't change rl */
648 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "10:20:30", rl, NULL) >= 0);
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
653 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "wat:wat", rl, NULL) >= 0);
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
658 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "66:wat", rl, NULL) >= 0);
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
663 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "200:100", rl, NULL) >= 0);
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
668 rl[RLIMIT_NOFILE] = mfree(rl[RLIMIT_NOFILE]);
669
670 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "56", rl, NULL) >= 0);
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
675 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "57s", rl, NULL) >= 0);
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
680 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "40s:1m", rl, NULL) >= 0);
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
685 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "infinity", rl, NULL) >= 0);
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
690 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "1234ms", rl, NULL) >= 0);
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
697 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58", rl, NULL) >= 0);
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
702 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58:60", rl, NULL) >= 0);
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
707 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s", rl, NULL) >= 0);
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
712 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s:123s", rl, NULL) >= 0);
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
717 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity", rl, NULL) >= 0);
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
722 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity:infinity", rl, NULL) >= 0);
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
727 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "2345ms", rl, NULL) >= 0);
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
735 static 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
773 static void test_unit_dump_config_items(void) {
774 unit_dump_config_items(stdout);
775 }
776
777 int main(int argc, char *argv[]) {
778 _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
779 int r;
780
781 test_setup_logging(LOG_INFO);
782
783 r = enter_cgroup_subroot();
784 if (r == -ENOMEDIUM)
785 return log_tests_skipped("cgroupfs not available");
786
787 assert_se(runtime_dir = setup_fake_runtime_dir());
788
789 r = test_unit_file_get_set();
790 test_config_parse_exec();
791 test_config_parse_log_extra_fields();
792 test_config_parse_capability_set();
793 test_config_parse_rlimit();
794 test_config_parse_pass_environ();
795 TEST_REQ_RUNNING_SYSTEMD(test_install_printf());
796 test_unit_dump_config_items();
797
798 return r;
799 }