1 /* SPDX-License-Identifier: LGPL-2.1+ */
9 #include "alloc-util.h"
10 #include "capability-util.h"
11 #include "conf-parser.h"
13 #include "format-util.h"
16 #include "hostname-util.h"
17 #include "install-printf.h"
19 #include "load-fragment.h"
21 #include "memory-util.h"
23 #include "specifier.h"
24 #include "string-util.h"
26 #include "test-helper.h"
28 #include "tmpfile-util.h"
29 #include "user-util.h"
31 static int test_unit_file_get_set(void) {
37 h
= hashmap_new(&string_hash_ops
);
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");
44 log_full_errno(r
== 0 ? LOG_INFO
: LOG_ERR
, r
,
45 "unit_file_get_list: %m");
49 HASHMAP_FOREACH(p
, h
, i
)
50 printf("%s = %s\n", p
->path
, unit_file_state_to_string(p
->state
));
52 unit_file_list_free(h
);
57 static void check_execcommand(ExecCommand
*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
));
74 assert_se(streq_ptr(c
->argv
[1], argv1
));
76 assert_se(streq_ptr(c
->argv
[2], argv2
));
77 assert_se(!!(c
->flags
& EXEC_COMMAND_IGNORE_FAILURE
) == ignore
);
80 static void test_config_parse_exec(void) {
81 /* int config_parse_exec(
86 unsigned section_line,
94 ExecCommand
*c
= NULL
, *c1
;
96 _cleanup_(manager_freep
) Manager
*m
= NULL
;
97 _cleanup_(unit_freep
) Unit
*u
= NULL
;
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");
106 assert_se(manager_startup(m
, NULL
, NULL
) >= 0);
108 assert_se(u
= unit_new(m
, sizeof(Service
)));
110 log_info("/* basic test */");
111 r
= config_parse_exec(NULL
, "fake", 1, "section", 1,
112 "LValue", 0, "/RValue r1",
115 check_execcommand(c
, "/RValue", "/RValue", "r1", NULL
, false);
117 r
= config_parse_exec(NULL
, "fake", 2, "section", 1,
118 "LValue", 0, "/RValue///slashes r1///",
121 log_info("/* test slashes */");
123 c1
= c
->command_next
;
124 check_execcommand(c1
, "/RValue/slashes", "/RValue///slashes", "r1///", NULL
, false);
126 log_info("/* trailing slash */");
127 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
128 "LValue", 0, "/RValue/ argv0 r1",
130 assert_se(r
== -ENOEXEC
);
131 assert_se(c1
->command_next
== NULL
);
133 log_info("/* honour_argv0 */");
134 r
= config_parse_exec(NULL
, "fake", 3, "section", 1,
135 "LValue", 0, "@/RValue///slashes2 ///argv0 r1",
138 c1
= c1
->command_next
;
139 check_execcommand(c1
, "/RValue/slashes2", "///argv0", "r1", NULL
, false);
141 log_info("/* honour_argv0, no args */");
142 r
= config_parse_exec(NULL
, "fake", 3, "section", 1,
143 "LValue", 0, "@/RValue",
145 assert_se(r
== -ENOEXEC
);
146 assert_se(c1
->command_next
== NULL
);
148 log_info("/* no command, whitespace only, reset */");
149 r
= config_parse_exec(NULL
, "fake", 3, "section", 1,
153 assert_se(c
== NULL
);
155 log_info("/* ignore && honour_argv0 */");
156 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
157 "LValue", 0, "-@/RValue///slashes3 argv0a r1",
161 check_execcommand(c1
, "/RValue/slashes3", "argv0a", "r1", NULL
, true);
163 log_info("/* ignore && honour_argv0 */");
164 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
165 "LValue", 0, "@-/RValue///slashes4 argv0b r1",
168 c1
= c1
->command_next
;
169 check_execcommand(c1
, "/RValue/slashes4", "argv0b", "r1", NULL
, true);
171 log_info("/* ignore && ignore */");
172 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
173 "LValue", 0, "--/RValue argv0 r1",
176 assert_se(c1
->command_next
== NULL
);
178 log_info("/* ignore && ignore (2) */");
179 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
180 "LValue", 0, "-@-/RValue argv0 r1",
183 assert_se(c1
->command_next
== NULL
);
185 log_info("/* semicolon */");
186 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
188 "-@/RValue argv0 r1 ; "
192 c1
= c1
->command_next
;
193 check_execcommand(c1
, "/RValue", "argv0", "r1", NULL
, true);
195 c1
= c1
->command_next
;
196 check_execcommand(c1
, "/goo/goo", NULL
, "boo", NULL
, false);
198 log_info("/* two semicolons in a row */");
199 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
201 "-@/RValue argv0 r1 ; ; "
204 assert_se(r
== -ENOEXEC
);
205 c1
= c1
->command_next
;
206 check_execcommand(c1
, "/RValue", "argv0", "r1", NULL
, true);
208 /* second command fails because the executable name is ";" */
209 assert_se(c1
->command_next
== NULL
);
211 log_info("/* trailing semicolon */");
212 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
214 "-@/RValue argv0 r1 ; ",
217 c1
= c1
->command_next
;
218 check_execcommand(c1
, "/RValue", "argv0", "r1", NULL
, true);
220 assert_se(c1
->command_next
== NULL
);
222 log_info("/* trailing semicolon, no whitespace */");
223 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
225 "-@/RValue argv0 r1 ;",
228 c1
= c1
->command_next
;
229 check_execcommand(c1
, "/RValue", "argv0", "r1", NULL
, true);
231 assert_se(c1
->command_next
== NULL
);
233 log_info("/* trailing semicolon in single quotes */");
234 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
236 "-@/RValue argv0 r1 ';'",
239 c1
= c1
->command_next
;
240 check_execcommand(c1
, "/RValue", "argv0", "r1", ";", true);
242 log_info("/* escaped semicolon */");
243 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
248 c1
= c1
->command_next
;
249 check_execcommand(c1
, "/bin/find", NULL
, ";", NULL
, false);
251 log_info("/* escaped semicolon with following arg */");
252 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
257 c1
= c1
->command_next
;
258 check_execcommand(c1
,
259 "/sbin/find", NULL
, ";", "/x", false);
261 log_info("/* escaped semicolon as part of an expression */");
262 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
267 c1
= c1
->command_next
;
268 check_execcommand(c1
,
269 "/sbin/find", NULL
, "\\;x", NULL
, false);
271 log_info("/* encoded semicolon */");
272 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
277 c1
= c1
->command_next
;
278 check_execcommand(c1
, "/bin/find", NULL
, ";", NULL
, false);
280 log_info("/* quoted semicolon */");
281 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
286 c1
= c1
->command_next
;
287 check_execcommand(c1
, "/bin/find", NULL
, ";", NULL
, false);
289 log_info("/* quoted semicolon with following arg */");
290 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
292 "/sbin/find \";\" /x",
295 c1
= c1
->command_next
;
296 check_execcommand(c1
,
297 "/sbin/find", NULL
, ";", "/x", false);
299 log_info("/* spaces in the filename */");
300 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
302 "\"/PATH WITH SPACES/daemon\" -1 -2",
305 c1
= c1
->command_next
;
306 check_execcommand(c1
,
307 "/PATH WITH SPACES/daemon", NULL
, "-1", "-2", false);
309 log_info("/* spaces in the filename, no args */");
310 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
312 "\"/PATH WITH SPACES/daemon -1 -2\"",
315 c1
= c1
->command_next
;
316 check_execcommand(c1
,
317 "/PATH WITH SPACES/daemon -1 -2", NULL
, NULL
, NULL
, false);
319 log_info("/* spaces in the filename, everything quoted */");
320 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
322 "\"/PATH WITH SPACES/daemon\" \"-1\" '-2'",
325 c1
= c1
->command_next
;
326 check_execcommand(c1
,
327 "/PATH WITH SPACES/daemon", NULL
, "-1", "-2", false);
329 log_info("/* escaped spaces in the filename */");
330 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
332 "\"/PATH\\sWITH\\sSPACES/daemon\" '-1 -2'",
335 c1
= c1
->command_next
;
336 check_execcommand(c1
,
337 "/PATH WITH SPACES/daemon", NULL
, "-1 -2", NULL
, false);
339 log_info("/* escaped spaces in the filename (2) */");
340 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
342 "\"/PATH\\x20WITH\\x20SPACES/daemon\" \"-1 -2\"",
345 c1
= c1
->command_next
;
346 check_execcommand(c1
,
347 "/PATH WITH SPACES/daemon", NULL
, "-1 -2", NULL
, false);
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
;
354 log_info("/* invalid character: \\%c */", *ccc
);
355 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
358 assert_se(r
== -ENOEXEC
);
359 assert_se(c1
->command_next
== NULL
);
362 log_info("/* valid character: \\s */");
363 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
364 "LValue", 0, "/path\\s",
367 c1
= c1
->command_next
;
368 check_execcommand(c1
, "/path ", NULL
, NULL
, NULL
, false);
370 log_info("/* quoted backslashes */");
371 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
373 "/bin/grep '\\w+\\K'",
376 c1
= c1
->command_next
;
377 check_execcommand(c1
, "/bin/grep", NULL
, "\\w+\\K", NULL
, false);
379 log_info("/* trailing backslash: \\ */");
380 /* backslash is invalid */
381 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
382 "LValue", 0, "/path\\",
384 assert_se(r
== -ENOEXEC
);
385 assert_se(c1
->command_next
== NULL
);
387 log_info("/* missing ending ' */");
388 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
389 "LValue", 0, "/path 'foo",
391 assert_se(r
== -ENOEXEC
);
392 assert_se(c1
->command_next
== NULL
);
394 log_info("/* missing ending ' with trailing backslash */");
395 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
396 "LValue", 0, "/path 'foo\\",
398 assert_se(r
== -ENOEXEC
);
399 assert_se(c1
->command_next
== NULL
);
401 log_info("/* invalid space between modifiers */");
402 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
403 "LValue", 0, "- /path",
406 assert_se(c1
->command_next
== NULL
);
408 log_info("/* only modifiers, no path */");
409 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
413 assert_se(c1
->command_next
== NULL
);
415 log_info("/* empty argument, reset */");
416 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
420 assert_se(c
== NULL
);
422 exec_command_free_list(c
);
425 static void test_config_parse_log_extra_fields(void) {
426 /* int config_parse_log_extra_fields(
428 const char *filename,
431 unsigned section_line,
440 _cleanup_(manager_freep
) Manager
*m
= NULL
;
441 _cleanup_(unit_freep
) Unit
*u
= NULL
;
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");
451 assert_se(manager_startup(m
, NULL
, NULL
) >= 0);
453 assert_se(u
= unit_new(m
, sizeof(Service
)));
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 ' ' \"",
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
));
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 ' '",
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
));
475 exec_context_dump(&c
, stdout
, " --> ");
477 log_info("/* %s – reset */", __func__
);
478 r
= config_parse_log_extra_fields(NULL
, "fake", 1, "section", 1,
482 assert_se(c
.n_log_extra_fields
== 0);
484 exec_context_free_log_extra_fields(&c
);
486 log_info("/* %s – bye */", __func__
);
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
, };
499 _cleanup_free_
char *mid
= NULL
, *bid
= NULL
, *host
= NULL
, *gid
= NULL
, *group
= NULL
, *uid
= NULL
, *user
= NULL
;
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);
509 #define expect(src, pattern, result) \
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); \
521 assert_se(streq(t, result)); \
522 } else assert_se(t == NULL); \
523 strcpy(i.name, d1); \
524 strcpy(i.path, d2); \
527 expect(i
, "%n", "name.service");
528 expect(i
, "%N", "name");
529 expect(i
, "%p", "name");
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
);
537 expect(i
, "%m", mid
);
538 expect(i
, "%b", bid
);
539 expect(i
, "%H", host
);
541 expect(i2
, "%g", group
);
542 expect(i2
, "%G", gid
);
543 expect(i2
, "%u", user
);
544 expect(i2
, "%U", uid
);
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
);
554 expect(i3
, "%m", mid
);
555 expect(i3
, "%b", bid
);
556 expect(i3
, "%H", host
);
558 expect(i4
, "%g", group
);
559 expect(i4
, "%G", gid
);
560 expect(i4
, "%u", user
);
561 expect(i4
, "%U", uid
);
564 static uint64_t make_cap(int cap
) {
565 return ((uint64_t) 1ULL << (uint64_t) cap
);
568 static void test_config_parse_capability_set(void) {
569 /* int config_parse_capability_set(
571 const char *filename,
574 unsigned section_line,
581 uint64_t capability_bounding_set
= 0;
583 r
= config_parse_capability_set(NULL
, "fake", 1, "section", 1,
584 "CapabilityBoundingSet", 0, "CAP_NET_RAW",
585 &capability_bounding_set
, NULL
);
587 assert_se(capability_bounding_set
== make_cap(CAP_NET_RAW
));
589 r
= config_parse_capability_set(NULL
, "fake", 1, "section", 1,
590 "CapabilityBoundingSet", 0, "CAP_NET_ADMIN",
591 &capability_bounding_set
, NULL
);
593 assert_se(capability_bounding_set
== (make_cap(CAP_NET_RAW
) | make_cap(CAP_NET_ADMIN
)));
595 r
= config_parse_capability_set(NULL
, "fake", 1, "section", 1,
596 "CapabilityBoundingSet", 0, "~CAP_NET_ADMIN",
597 &capability_bounding_set
, NULL
);
599 assert_se(capability_bounding_set
== make_cap(CAP_NET_RAW
));
601 r
= config_parse_capability_set(NULL
, "fake", 1, "section", 1,
602 "CapabilityBoundingSet", 0, "",
603 &capability_bounding_set
, NULL
);
605 assert_se(capability_bounding_set
== UINT64_C(0));
607 r
= config_parse_capability_set(NULL
, "fake", 1, "section", 1,
608 "CapabilityBoundingSet", 0, "~",
609 &capability_bounding_set
, NULL
);
611 assert_se(cap_test_all(capability_bounding_set
));
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
);
618 assert_se(capability_bounding_set
== (make_cap(CAP_NET_RAW
) | make_cap(CAP_NET_ADMIN
)));
621 static void test_config_parse_rlimit(void) {
622 struct rlimit
* rl
[_RLIMIT_MAX
] = {};
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
);
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);
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
);
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
);
644 rl
[RLIMIT_NOFILE
]->rlim_cur
= 10;
645 rl
[RLIMIT_NOFILE
]->rlim_max
= 20;
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);
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);
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);
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);
668 rl
[RLIMIT_NOFILE
] = mfree(rl
[RLIMIT_NOFILE
]);
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
);
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
);
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);
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
);
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
);
695 rl
[RLIMIT_CPU
] = mfree(rl
[RLIMIT_CPU
]);
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
);
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);
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
);
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
);
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
);
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
);
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
);
732 rl
[RLIMIT_RTTIME
] = mfree(rl
[RLIMIT_RTTIME
]);
735 static void test_config_parse_pass_environ(void) {
736 /* int config_parse_pass_environ(
738 const char *filename,
741 unsigned section_line,
748 _cleanup_strv_free_
char **passenv
= NULL
;
750 r
= config_parse_pass_environ(NULL
, "fake", 1, "section", 1,
751 "PassEnvironment", 0, "A B",
754 assert_se(strv_length(passenv
) == 2);
755 assert_se(streq(passenv
[0], "A"));
756 assert_se(streq(passenv
[1], "B"));
758 r
= config_parse_pass_environ(NULL
, "fake", 1, "section", 1,
759 "PassEnvironment", 0, "",
762 assert_se(strv_isempty(passenv
));
764 r
= config_parse_pass_environ(NULL
, "fake", 1, "section", 1,
765 "PassEnvironment", 0, "'invalid name' 'normal_name' A=1 \\",
768 assert_se(strv_length(passenv
) == 1);
769 assert_se(streq(passenv
[0], "normal_name"));
773 static void test_unit_dump_config_items(void) {
774 unit_dump_config_items(stdout
);
777 int main(int argc
, char *argv
[]) {
778 _cleanup_(rm_rf_physical_and_freep
) char *runtime_dir
= NULL
;
781 test_setup_logging(LOG_INFO
);
783 r
= enter_cgroup_subroot();
785 return log_tests_skipped("cgroupfs not available");
787 assert_se(runtime_dir
= setup_fake_runtime_dir());
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();