1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2012 Lennart Poettering
6 Copyright 2013 Zbigniew Jędrzejewski-Szmek
13 #include <sys/capability.h>
16 #include "alloc-util.h"
17 #include "all-units.h"
18 #include "capability-util.h"
19 #include "conf-parser.h"
24 #include "hostname-util.h"
25 #include "install-printf.h"
27 #include "load-fragment.h"
30 #include "specifier.h"
31 #include "string-util.h"
33 #include "test-helper.h"
35 #include "user-util.h"
38 static int test_unit_file_get_set(void) {
44 h
= hashmap_new(&string_hash_ops
);
47 r
= unit_file_get_list(UNIT_FILE_SYSTEM
, NULL
, h
, NULL
, NULL
);
49 if (IN_SET(r
, -EPERM
, -EACCES
)) {
50 log_notice_errno(r
, "Skipping test: unit_file_get_list: %m");
51 return EXIT_TEST_SKIP
;
54 log_full_errno(r
== 0 ? LOG_INFO
: LOG_ERR
, r
,
55 "unit_file_get_list: %m");
59 HASHMAP_FOREACH(p
, h
, i
)
60 printf("%s = %s\n", p
->path
, unit_file_state_to_string(p
->state
));
62 unit_file_list_free(h
);
67 static void check_execcommand(ExecCommand
*c
,
76 log_info("expect: \"%s\" [\"%s\" \"%s\" \"%s\"]",
77 path
, argv0
?: path
, argv1
, argv2
);
78 n
= strv_length(c
->argv
);
79 log_info("actual: \"%s\" [\"%s\" \"%s\" \"%s\"]",
80 c
->path
, c
->argv
[0], n
> 0 ? c
->argv
[1] : NULL
, n
> 1 ? c
->argv
[2] : NULL
);
81 assert_se(streq(c
->path
, path
));
82 assert_se(streq(c
->argv
[0], argv0
?: path
));
84 assert_se(streq_ptr(c
->argv
[1], argv1
));
86 assert_se(streq_ptr(c
->argv
[2], argv2
));
87 assert_se(!!(c
->flags
& EXEC_COMMAND_IGNORE_FAILURE
) == ignore
);
90 static void test_config_parse_exec(void) {
91 /* int config_parse_exec(
96 unsigned section_line,
104 ExecCommand
*c
= NULL
, *c1
;
106 _cleanup_(manager_freep
) Manager
*m
= NULL
;
107 _cleanup_(unit_freep
) Unit
*u
= NULL
;
109 r
= manager_new(UNIT_FILE_USER
, MANAGER_TEST_RUN_MINIMAL
, &m
);
110 if (MANAGER_SKIP_TEST(r
)) {
111 log_notice_errno(r
, "Skipping test: manager_new: %m");
116 assert_se(manager_startup(m
, NULL
, NULL
) >= 0);
118 assert_se(u
= unit_new(m
, sizeof(Service
)));
120 log_info("/* basic test */");
121 r
= config_parse_exec(NULL
, "fake", 1, "section", 1,
122 "LValue", 0, "/RValue r1",
125 check_execcommand(c
, "/RValue", "/RValue", "r1", NULL
, false);
127 r
= config_parse_exec(NULL
, "fake", 2, "section", 1,
128 "LValue", 0, "/RValue///slashes r1///",
131 log_info("/* test slashes */");
133 c1
= c
->command_next
;
134 check_execcommand(c1
, "/RValue/slashes", "/RValue///slashes", "r1///", NULL
, false);
136 log_info("/* trailing slash */");
137 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
138 "LValue", 0, "/RValue/ argv0 r1",
140 assert_se(r
== -ENOEXEC
);
141 assert_se(c1
->command_next
== NULL
);
143 log_info("/* honour_argv0 */");
144 r
= config_parse_exec(NULL
, "fake", 3, "section", 1,
145 "LValue", 0, "@/RValue///slashes2 ///argv0 r1",
148 c1
= c1
->command_next
;
149 check_execcommand(c1
, "/RValue/slashes2", "///argv0", "r1", NULL
, false);
151 log_info("/* honour_argv0, no args */");
152 r
= config_parse_exec(NULL
, "fake", 3, "section", 1,
153 "LValue", 0, "@/RValue",
155 assert_se(r
== -ENOEXEC
);
156 assert_se(c1
->command_next
== NULL
);
158 log_info("/* no command, whitespace only, reset */");
159 r
= config_parse_exec(NULL
, "fake", 3, "section", 1,
163 assert_se(c
== NULL
);
165 log_info("/* ignore && honour_argv0 */");
166 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
167 "LValue", 0, "-@/RValue///slashes3 argv0a r1",
171 check_execcommand(c1
, "/RValue/slashes3", "argv0a", "r1", NULL
, true);
173 log_info("/* ignore && honour_argv0 */");
174 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
175 "LValue", 0, "@-/RValue///slashes4 argv0b r1",
178 c1
= c1
->command_next
;
179 check_execcommand(c1
, "/RValue/slashes4", "argv0b", "r1", NULL
, true);
181 log_info("/* ignore && ignore */");
182 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
183 "LValue", 0, "--/RValue argv0 r1",
186 assert_se(c1
->command_next
== NULL
);
188 log_info("/* ignore && ignore (2) */");
189 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
190 "LValue", 0, "-@-/RValue argv0 r1",
193 assert_se(c1
->command_next
== NULL
);
195 log_info("/* semicolon */");
196 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
198 "-@/RValue argv0 r1 ; "
202 c1
= c1
->command_next
;
203 check_execcommand(c1
, "/RValue", "argv0", "r1", NULL
, true);
205 c1
= c1
->command_next
;
206 check_execcommand(c1
, "/goo/goo", NULL
, "boo", NULL
, false);
208 log_info("/* two semicolons in a row */");
209 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
211 "-@/RValue argv0 r1 ; ; "
214 assert_se(r
== -ENOEXEC
);
215 c1
= c1
->command_next
;
216 check_execcommand(c1
, "/RValue", "argv0", "r1", NULL
, true);
218 /* second command fails because the executable name is ";" */
219 assert_se(c1
->command_next
== NULL
);
221 log_info("/* trailing semicolon */");
222 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
224 "-@/RValue argv0 r1 ; ",
227 c1
= c1
->command_next
;
228 check_execcommand(c1
, "/RValue", "argv0", "r1", NULL
, true);
230 assert_se(c1
->command_next
== NULL
);
232 log_info("/* trailing semicolon, no whitespace */");
233 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
235 "-@/RValue argv0 r1 ;",
238 c1
= c1
->command_next
;
239 check_execcommand(c1
, "/RValue", "argv0", "r1", NULL
, true);
241 assert_se(c1
->command_next
== NULL
);
243 log_info("/* trailing semicolon in single quotes */");
244 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
246 "-@/RValue argv0 r1 ';'",
249 c1
= c1
->command_next
;
250 check_execcommand(c1
, "/RValue", "argv0", "r1", ";", true);
252 log_info("/* escaped semicolon */");
253 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
258 c1
= c1
->command_next
;
259 check_execcommand(c1
, "/bin/find", NULL
, ";", NULL
, false);
261 log_info("/* escaped semicolon with following arg */");
262 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
267 c1
= c1
->command_next
;
268 check_execcommand(c1
,
269 "/sbin/find", NULL
, ";", "/x", false);
271 log_info("/* escaped semicolon as part of an expression */");
272 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
277 c1
= c1
->command_next
;
278 check_execcommand(c1
,
279 "/sbin/find", NULL
, "\\;x", NULL
, false);
281 log_info("/* encoded semicolon */");
282 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
287 c1
= c1
->command_next
;
288 check_execcommand(c1
, "/bin/find", NULL
, ";", NULL
, false);
290 log_info("/* quoted semicolon */");
291 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
296 c1
= c1
->command_next
;
297 check_execcommand(c1
, "/bin/find", NULL
, ";", NULL
, false);
299 log_info("/* quoted semicolon with following arg */");
300 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
302 "/sbin/find \";\" /x",
305 c1
= c1
->command_next
;
306 check_execcommand(c1
,
307 "/sbin/find", NULL
, ";", "/x", false);
309 log_info("/* spaces in the filename */");
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", NULL
, "-1", "-2", false);
319 log_info("/* spaces in the filename, no args */");
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 -1 -2", NULL
, NULL
, NULL
, false);
329 log_info("/* spaces in the filename, everything quoted */");
330 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
332 "\"/PATH WITH SPACES/daemon\" \"-1\" '-2'",
335 c1
= c1
->command_next
;
336 check_execcommand(c1
,
337 "/PATH WITH SPACES/daemon", NULL
, "-1", "-2", false);
339 log_info("/* escaped spaces in the filename */");
340 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
342 "\"/PATH\\sWITH\\sSPACES/daemon\" '-1 -2'",
345 c1
= c1
->command_next
;
346 check_execcommand(c1
,
347 "/PATH WITH SPACES/daemon", NULL
, "-1 -2", NULL
, false);
349 log_info("/* escaped spaces in the filename (2) */");
350 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
352 "\"/PATH\\x20WITH\\x20SPACES/daemon\" \"-1 -2\"",
355 c1
= c1
->command_next
;
356 check_execcommand(c1
,
357 "/PATH WITH SPACES/daemon", NULL
, "-1 -2", NULL
, false);
359 for (ccc
= "abfnrtv\\\'\"x"; *ccc
; ccc
++) {
360 /* \\x is an incomplete hexadecimal sequence, invalid because of the slash */
361 char path
[] = "/path\\X";
362 path
[sizeof(path
) - 2] = *ccc
;
364 log_info("/* invalid character: \\%c */", *ccc
);
365 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
368 assert_se(r
== -ENOEXEC
);
369 assert_se(c1
->command_next
== NULL
);
372 log_info("/* valid character: \\s */");
373 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
374 "LValue", 0, "/path\\s",
377 c1
= c1
->command_next
;
378 check_execcommand(c1
, "/path ", NULL
, NULL
, NULL
, false);
380 log_info("/* quoted backslashes */");
381 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
383 "/bin/grep '\\w+\\K'",
386 c1
= c1
->command_next
;
387 check_execcommand(c1
, "/bin/grep", NULL
, "\\w+\\K", NULL
, false);
389 log_info("/* trailing backslash: \\ */");
390 /* backslash is invalid */
391 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
392 "LValue", 0, "/path\\",
394 assert_se(r
== -ENOEXEC
);
395 assert_se(c1
->command_next
== NULL
);
397 log_info("/* missing ending ' */");
398 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
399 "LValue", 0, "/path 'foo",
401 assert_se(r
== -ENOEXEC
);
402 assert_se(c1
->command_next
== NULL
);
404 log_info("/* missing ending ' with trailing backslash */");
405 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
406 "LValue", 0, "/path 'foo\\",
408 assert_se(r
== -ENOEXEC
);
409 assert_se(c1
->command_next
== NULL
);
411 log_info("/* invalid space between modifiers */");
412 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
413 "LValue", 0, "- /path",
416 assert_se(c1
->command_next
== NULL
);
418 log_info("/* only modifiers, no path */");
419 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
423 assert_se(c1
->command_next
== NULL
);
425 log_info("/* empty argument, reset */");
426 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
430 assert_se(c
== NULL
);
432 exec_command_free_list(c
);
435 static void test_config_parse_log_extra_fields(void) {
436 /* int config_parse_log_extra_fields(
438 const char *filename,
441 unsigned section_line,
450 _cleanup_(manager_freep
) Manager
*m
= NULL
;
451 _cleanup_(unit_freep
) Unit
*u
= NULL
;
454 r
= manager_new(UNIT_FILE_USER
, MANAGER_TEST_RUN_MINIMAL
, &m
);
455 if (MANAGER_SKIP_TEST(r
)) {
456 log_notice_errno(r
, "Skipping test: manager_new: %m");
461 assert_se(manager_startup(m
, NULL
, NULL
) >= 0);
463 assert_se(u
= unit_new(m
, sizeof(Service
)));
465 log_info("/* %s – basic test */", __func__
);
466 r
= config_parse_log_extra_fields(NULL
, "fake", 1, "section", 1,
467 "LValue", 0, "FOO=BAR \"QOOF=quux ' ' \"",
470 assert_se(c
.n_log_extra_fields
== 2);
471 assert_se(strneq(c
.log_extra_fields
[0].iov_base
, "FOO=BAR", c
.log_extra_fields
[0].iov_len
));
472 assert_se(strneq(c
.log_extra_fields
[1].iov_base
, "QOOF=quux ' ' ", c
.log_extra_fields
[1].iov_len
));
474 log_info("/* %s – add some */", __func__
);
475 r
= config_parse_log_extra_fields(NULL
, "fake", 1, "section", 1,
476 "LValue", 0, "FOO2=BAR2 QOOF2=quux ' '",
479 assert_se(c
.n_log_extra_fields
== 4);
480 assert_se(strneq(c
.log_extra_fields
[0].iov_base
, "FOO=BAR", c
.log_extra_fields
[0].iov_len
));
481 assert_se(strneq(c
.log_extra_fields
[1].iov_base
, "QOOF=quux ' ' ", c
.log_extra_fields
[1].iov_len
));
482 assert_se(strneq(c
.log_extra_fields
[2].iov_base
, "FOO2=BAR2", c
.log_extra_fields
[2].iov_len
));
483 assert_se(strneq(c
.log_extra_fields
[3].iov_base
, "QOOF2=quux", c
.log_extra_fields
[3].iov_len
));
485 exec_context_dump(&c
, stdout
, " --> ");
487 log_info("/* %s – reset */", __func__
);
488 r
= config_parse_log_extra_fields(NULL
, "fake", 1, "section", 1,
492 assert_se(c
.n_log_extra_fields
== 0);
494 exec_context_free_log_extra_fields(&c
);
496 log_info("/* %s – bye */", __func__
);
514 "#SPAMD_ARGS=\"-d --socketpath=/var/lib/bulwark/spamd \\\n" \
515 "#--nouser-config \\\n" \
521 "HWMON_MODULES=\"coretemp f71882fg\"\n" \
523 "# For compatibility reasons\n" \
525 "MODULE_0=coretemp\n" \
532 static void test_load_env_file_1(void) {
533 _cleanup_strv_free_
char **data
= NULL
;
536 _cleanup_(unlink_tempfilep
) char name
[] = "/tmp/test-load-env-file.XXXXXX";
537 _cleanup_close_
int fd
;
539 fd
= mkostemp_safe(name
);
541 assert_se(write(fd
, env_file_1
, sizeof(env_file_1
)) == sizeof(env_file_1
));
543 r
= load_env_file(NULL
, name
, NULL
, &data
);
545 assert_se(streq(data
[0], "a=a"));
546 assert_se(streq(data
[1], "b=bc"));
547 assert_se(streq(data
[2], "d=def"));
548 assert_se(streq(data
[3], "g=g "));
549 assert_se(streq(data
[4], "h=h"));
550 assert_se(streq(data
[5], "i=i"));
551 assert_se(data
[6] == NULL
);
554 static void test_load_env_file_2(void) {
555 _cleanup_strv_free_
char **data
= NULL
;
558 _cleanup_(unlink_tempfilep
) char name
[] = "/tmp/test-load-env-file.XXXXXX";
559 _cleanup_close_
int fd
;
561 fd
= mkostemp_safe(name
);
563 assert_se(write(fd
, env_file_2
, sizeof(env_file_2
)) == sizeof(env_file_2
));
565 r
= load_env_file(NULL
, name
, NULL
, &data
);
567 assert_se(streq(data
[0], "a=a"));
568 assert_se(data
[1] == NULL
);
571 static void test_load_env_file_3(void) {
572 _cleanup_strv_free_
char **data
= NULL
;
575 _cleanup_(unlink_tempfilep
) char name
[] = "/tmp/test-load-env-file.XXXXXX";
576 _cleanup_close_
int fd
;
578 fd
= mkostemp_safe(name
);
580 assert_se(write(fd
, env_file_3
, sizeof(env_file_3
)) == sizeof(env_file_3
));
582 r
= load_env_file(NULL
, name
, NULL
, &data
);
584 assert_se(data
== NULL
);
587 static void test_load_env_file_4(void) {
588 _cleanup_strv_free_
char **data
= NULL
;
589 _cleanup_(unlink_tempfilep
) char name
[] = "/tmp/test-load-env-file.XXXXXX";
590 _cleanup_close_
int fd
;
593 fd
= mkostemp_safe(name
);
595 assert_se(write(fd
, env_file_4
, sizeof(env_file_4
)) == sizeof(env_file_4
));
597 r
= load_env_file(NULL
, name
, NULL
, &data
);
599 assert_se(streq(data
[0], "HWMON_MODULES=coretemp f71882fg"));
600 assert_se(streq(data
[1], "MODULE_0=coretemp"));
601 assert_se(streq(data
[2], "MODULE_1=f71882fg"));
602 assert_se(data
[3] == NULL
);
605 static void test_load_env_file_5(void) {
606 _cleanup_strv_free_
char **data
= NULL
;
609 _cleanup_(unlink_tempfilep
) char name
[] = "/tmp/test-load-env-file.XXXXXX";
610 _cleanup_close_
int fd
;
612 fd
= mkostemp_safe(name
);
614 assert_se(write(fd
, env_file_5
, sizeof(env_file_5
)) == sizeof(env_file_5
));
616 r
= load_env_file(NULL
, name
, NULL
, &data
);
618 assert_se(streq(data
[0], "a="));
619 assert_se(streq(data
[1], "b="));
620 assert_se(data
[2] == NULL
);
623 static void test_install_printf(void) {
624 char name
[] = "name.service",
625 path
[] = "/run/systemd/system/name.service";
626 UnitFileInstallInfo i
= { .name
= name
, .path
= path
, };
627 UnitFileInstallInfo i2
= { .name
= name
, .path
= path
, };
628 char name3
[] = "name@inst.service",
629 path3
[] = "/run/systemd/system/name.service";
630 UnitFileInstallInfo i3
= { .name
= name3
, .path
= path3
, };
631 UnitFileInstallInfo i4
= { .name
= name3
, .path
= path3
, };
633 _cleanup_free_
char *mid
= NULL
, *bid
= NULL
, *host
= NULL
, *uid
= NULL
, *user
= NULL
;
635 assert_se(specifier_machine_id('m', NULL
, NULL
, &mid
) >= 0 && mid
);
636 assert_se(specifier_boot_id('b', NULL
, NULL
, &bid
) >= 0 && bid
);
637 assert_se(host
= gethostname_malloc());
638 assert_se(user
= uid_to_name(getuid()));
639 assert_se(asprintf(&uid
, UID_FMT
, getuid()) >= 0);
641 #define expect(src, pattern, result) \
643 _cleanup_free_ char *t = NULL; \
644 _cleanup_free_ char \
645 *d1 = strdup(i.name), \
646 *d2 = strdup(i.path); \
647 assert_se(install_full_printf(&src, pattern, &t) >= 0 || !result); \
648 memzero(i.name, strlen(i.name)); \
649 memzero(i.path, strlen(i.path)); \
650 assert_se(d1 && d2); \
653 assert_se(streq(t, result)); \
654 } else assert_se(t == NULL); \
655 strcpy(i.name, d1); \
656 strcpy(i.path, d2); \
659 expect(i
, "%n", "name.service");
660 expect(i
, "%N", "name");
661 expect(i
, "%p", "name");
663 expect(i
, "%j", "name");
664 expect(i
, "%u", user
);
665 expect(i
, "%U", uid
);
667 expect(i
, "%m", mid
);
668 expect(i
, "%b", bid
);
669 expect(i
, "%H", host
);
671 expect(i2
, "%u", user
);
672 expect(i2
, "%U", uid
);
674 expect(i3
, "%n", "name@inst.service");
675 expect(i3
, "%N", "name@inst");
676 expect(i3
, "%p", "name");
677 expect(i3
, "%u", user
);
678 expect(i3
, "%U", uid
);
680 expect(i3
, "%m", mid
);
681 expect(i3
, "%b", bid
);
682 expect(i3
, "%H", host
);
684 expect(i4
, "%u", user
);
685 expect(i4
, "%U", uid
);
688 static uint64_t make_cap(int cap
) {
689 return ((uint64_t) 1ULL << (uint64_t) cap
);
692 static void test_config_parse_capability_set(void) {
693 /* int config_parse_capability_set(
695 const char *filename,
698 unsigned section_line,
705 uint64_t capability_bounding_set
= 0;
707 r
= config_parse_capability_set(NULL
, "fake", 1, "section", 1,
708 "CapabilityBoundingSet", 0, "CAP_NET_RAW",
709 &capability_bounding_set
, NULL
);
711 assert_se(capability_bounding_set
== make_cap(CAP_NET_RAW
));
713 r
= config_parse_capability_set(NULL
, "fake", 1, "section", 1,
714 "CapabilityBoundingSet", 0, "CAP_NET_ADMIN",
715 &capability_bounding_set
, NULL
);
717 assert_se(capability_bounding_set
== (make_cap(CAP_NET_RAW
) | make_cap(CAP_NET_ADMIN
)));
719 r
= config_parse_capability_set(NULL
, "fake", 1, "section", 1,
720 "CapabilityBoundingSet", 0, "~CAP_NET_ADMIN",
721 &capability_bounding_set
, NULL
);
723 assert_se(capability_bounding_set
== make_cap(CAP_NET_RAW
));
725 r
= config_parse_capability_set(NULL
, "fake", 1, "section", 1,
726 "CapabilityBoundingSet", 0, "",
727 &capability_bounding_set
, NULL
);
729 assert_se(capability_bounding_set
== UINT64_C(0));
731 r
= config_parse_capability_set(NULL
, "fake", 1, "section", 1,
732 "CapabilityBoundingSet", 0, "~",
733 &capability_bounding_set
, NULL
);
735 assert_se(cap_test_all(capability_bounding_set
));
737 capability_bounding_set
= 0;
738 r
= config_parse_capability_set(NULL
, "fake", 1, "section", 1,
739 "CapabilityBoundingSet", 0, " 'CAP_NET_RAW' WAT_CAP??? CAP_NET_ADMIN CAP'_trailing_garbage",
740 &capability_bounding_set
, NULL
);
742 assert_se(capability_bounding_set
== (make_cap(CAP_NET_RAW
) | make_cap(CAP_NET_ADMIN
)));
745 static void test_config_parse_rlimit(void) {
746 struct rlimit
* rl
[_RLIMIT_MAX
] = {};
748 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE
, "55", rl
, NULL
) >= 0);
749 assert_se(rl
[RLIMIT_NOFILE
]);
750 assert_se(rl
[RLIMIT_NOFILE
]->rlim_cur
== 55);
751 assert_se(rl
[RLIMIT_NOFILE
]->rlim_cur
== rl
[RLIMIT_NOFILE
]->rlim_max
);
753 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE
, "55:66", rl
, NULL
) >= 0);
754 assert_se(rl
[RLIMIT_NOFILE
]);
755 assert_se(rl
[RLIMIT_NOFILE
]->rlim_cur
== 55);
756 assert_se(rl
[RLIMIT_NOFILE
]->rlim_max
== 66);
758 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE
, "infinity", rl
, NULL
) >= 0);
759 assert_se(rl
[RLIMIT_NOFILE
]);
760 assert_se(rl
[RLIMIT_NOFILE
]->rlim_cur
== RLIM_INFINITY
);
761 assert_se(rl
[RLIMIT_NOFILE
]->rlim_cur
== rl
[RLIMIT_NOFILE
]->rlim_max
);
763 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE
, "infinity:infinity", rl
, NULL
) >= 0);
764 assert_se(rl
[RLIMIT_NOFILE
]);
765 assert_se(rl
[RLIMIT_NOFILE
]->rlim_cur
== RLIM_INFINITY
);
766 assert_se(rl
[RLIMIT_NOFILE
]->rlim_cur
== rl
[RLIMIT_NOFILE
]->rlim_max
);
768 rl
[RLIMIT_NOFILE
]->rlim_cur
= 10;
769 rl
[RLIMIT_NOFILE
]->rlim_max
= 20;
771 /* Invalid values don't change rl */
772 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE
, "10:20:30", rl
, NULL
) >= 0);
773 assert_se(rl
[RLIMIT_NOFILE
]);
774 assert_se(rl
[RLIMIT_NOFILE
]->rlim_cur
== 10);
775 assert_se(rl
[RLIMIT_NOFILE
]->rlim_max
== 20);
777 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE
, "wat:wat", rl
, NULL
) >= 0);
778 assert_se(rl
[RLIMIT_NOFILE
]);
779 assert_se(rl
[RLIMIT_NOFILE
]->rlim_cur
== 10);
780 assert_se(rl
[RLIMIT_NOFILE
]->rlim_max
== 20);
782 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE
, "66:wat", rl
, NULL
) >= 0);
783 assert_se(rl
[RLIMIT_NOFILE
]);
784 assert_se(rl
[RLIMIT_NOFILE
]->rlim_cur
== 10);
785 assert_se(rl
[RLIMIT_NOFILE
]->rlim_max
== 20);
787 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE
, "200:100", rl
, NULL
) >= 0);
788 assert_se(rl
[RLIMIT_NOFILE
]);
789 assert_se(rl
[RLIMIT_NOFILE
]->rlim_cur
== 10);
790 assert_se(rl
[RLIMIT_NOFILE
]->rlim_max
== 20);
792 rl
[RLIMIT_NOFILE
] = mfree(rl
[RLIMIT_NOFILE
]);
794 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU
, "56", rl
, NULL
) >= 0);
795 assert_se(rl
[RLIMIT_CPU
]);
796 assert_se(rl
[RLIMIT_CPU
]->rlim_cur
== 56);
797 assert_se(rl
[RLIMIT_CPU
]->rlim_cur
== rl
[RLIMIT_CPU
]->rlim_max
);
799 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU
, "57s", rl
, NULL
) >= 0);
800 assert_se(rl
[RLIMIT_CPU
]);
801 assert_se(rl
[RLIMIT_CPU
]->rlim_cur
== 57);
802 assert_se(rl
[RLIMIT_CPU
]->rlim_cur
== rl
[RLIMIT_CPU
]->rlim_max
);
804 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU
, "40s:1m", rl
, NULL
) >= 0);
805 assert_se(rl
[RLIMIT_CPU
]);
806 assert_se(rl
[RLIMIT_CPU
]->rlim_cur
== 40);
807 assert_se(rl
[RLIMIT_CPU
]->rlim_max
== 60);
809 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU
, "infinity", rl
, NULL
) >= 0);
810 assert_se(rl
[RLIMIT_CPU
]);
811 assert_se(rl
[RLIMIT_CPU
]->rlim_cur
== RLIM_INFINITY
);
812 assert_se(rl
[RLIMIT_CPU
]->rlim_cur
== rl
[RLIMIT_CPU
]->rlim_max
);
814 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU
, "1234ms", rl
, NULL
) >= 0);
815 assert_se(rl
[RLIMIT_CPU
]);
816 assert_se(rl
[RLIMIT_CPU
]->rlim_cur
== 2);
817 assert_se(rl
[RLIMIT_CPU
]->rlim_cur
== rl
[RLIMIT_CPU
]->rlim_max
);
819 rl
[RLIMIT_CPU
] = mfree(rl
[RLIMIT_CPU
]);
821 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME
, "58", rl
, NULL
) >= 0);
822 assert_se(rl
[RLIMIT_RTTIME
]);
823 assert_se(rl
[RLIMIT_RTTIME
]->rlim_cur
== 58);
824 assert_se(rl
[RLIMIT_RTTIME
]->rlim_cur
== rl
[RLIMIT_RTTIME
]->rlim_max
);
826 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME
, "58:60", rl
, NULL
) >= 0);
827 assert_se(rl
[RLIMIT_RTTIME
]);
828 assert_se(rl
[RLIMIT_RTTIME
]->rlim_cur
== 58);
829 assert_se(rl
[RLIMIT_RTTIME
]->rlim_max
== 60);
831 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME
, "59s", rl
, NULL
) >= 0);
832 assert_se(rl
[RLIMIT_RTTIME
]);
833 assert_se(rl
[RLIMIT_RTTIME
]->rlim_cur
== 59 * USEC_PER_SEC
);
834 assert_se(rl
[RLIMIT_RTTIME
]->rlim_cur
== rl
[RLIMIT_RTTIME
]->rlim_max
);
836 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME
, "59s:123s", rl
, NULL
) >= 0);
837 assert_se(rl
[RLIMIT_RTTIME
]);
838 assert_se(rl
[RLIMIT_RTTIME
]->rlim_cur
== 59 * USEC_PER_SEC
);
839 assert_se(rl
[RLIMIT_RTTIME
]->rlim_max
== 123 * USEC_PER_SEC
);
841 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME
, "infinity", rl
, NULL
) >= 0);
842 assert_se(rl
[RLIMIT_RTTIME
]);
843 assert_se(rl
[RLIMIT_RTTIME
]->rlim_cur
== RLIM_INFINITY
);
844 assert_se(rl
[RLIMIT_RTTIME
]->rlim_cur
== rl
[RLIMIT_RTTIME
]->rlim_max
);
846 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME
, "infinity:infinity", rl
, NULL
) >= 0);
847 assert_se(rl
[RLIMIT_RTTIME
]);
848 assert_se(rl
[RLIMIT_RTTIME
]->rlim_cur
== RLIM_INFINITY
);
849 assert_se(rl
[RLIMIT_RTTIME
]->rlim_cur
== rl
[RLIMIT_RTTIME
]->rlim_max
);
851 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME
, "2345ms", rl
, NULL
) >= 0);
852 assert_se(rl
[RLIMIT_RTTIME
]);
853 assert_se(rl
[RLIMIT_RTTIME
]->rlim_cur
== 2345 * USEC_PER_MSEC
);
854 assert_se(rl
[RLIMIT_RTTIME
]->rlim_cur
== rl
[RLIMIT_RTTIME
]->rlim_max
);
856 rl
[RLIMIT_RTTIME
] = mfree(rl
[RLIMIT_RTTIME
]);
859 static void test_config_parse_pass_environ(void) {
860 /* int config_parse_pass_environ(
862 const char *filename,
865 unsigned section_line,
872 _cleanup_strv_free_
char **passenv
= NULL
;
874 r
= config_parse_pass_environ(NULL
, "fake", 1, "section", 1,
875 "PassEnvironment", 0, "A B",
878 assert_se(strv_length(passenv
) == 2);
879 assert_se(streq(passenv
[0], "A"));
880 assert_se(streq(passenv
[1], "B"));
882 r
= config_parse_pass_environ(NULL
, "fake", 1, "section", 1,
883 "PassEnvironment", 0, "",
886 assert_se(strv_isempty(passenv
));
888 r
= config_parse_pass_environ(NULL
, "fake", 1, "section", 1,
889 "PassEnvironment", 0, "'invalid name' 'normal_name' A=1 \\",
892 assert_se(strv_length(passenv
) == 1);
893 assert_se(streq(passenv
[0], "normal_name"));
897 static void test_unit_dump_config_items(void) {
898 unit_dump_config_items(stdout
);
901 int main(int argc
, char *argv
[]) {
902 _cleanup_(rm_rf_physical_and_freep
) char *runtime_dir
= NULL
;
905 log_parse_environment();
908 r
= enter_cgroup_subroot();
909 if (r
== -ENOMEDIUM
) {
910 log_notice_errno(r
, "Skipping test: cgroupfs not available");
911 return EXIT_TEST_SKIP
;
914 assert_se(runtime_dir
= setup_fake_runtime_dir());
916 r
= test_unit_file_get_set();
917 test_config_parse_exec();
918 test_config_parse_log_extra_fields();
919 test_config_parse_capability_set();
920 test_config_parse_rlimit();
921 test_config_parse_pass_environ();
922 test_load_env_file_1();
923 test_load_env_file_2();
924 test_load_env_file_3();
925 test_load_env_file_4();
926 test_load_env_file_5();
927 TEST_REQ_RUNNING_SYSTEMD(test_install_printf());
928 test_unit_dump_config_items();