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
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
26 #include <sys/capability.h>
29 #include "alloc-util.h"
30 #include "capability-util.h"
34 #include "hostname-util.h"
35 #include "install-printf.h"
37 #include "load-fragment.h"
40 #include "specifier.h"
41 #include "string-util.h"
43 #include "test-helper.h"
45 #include "user-util.h"
48 static int test_unit_file_get_set(void) {
54 h
= hashmap_new(&string_hash_ops
);
57 r
= unit_file_get_list(UNIT_FILE_SYSTEM
, NULL
, h
, NULL
, NULL
);
59 if (IN_SET(r
, -EPERM
, -EACCES
)) {
60 log_notice_errno(r
, "Skipping test: unit_file_get_list: %m");
61 return EXIT_TEST_SKIP
;
64 log_full_errno(r
== 0 ? LOG_INFO
: LOG_ERR
, r
,
65 "unit_file_get_list: %m");
69 HASHMAP_FOREACH(p
, h
, i
)
70 printf("%s = %s\n", p
->path
, unit_file_state_to_string(p
->state
));
72 unit_file_list_free(h
);
77 static void check_execcommand(ExecCommand
*c
,
86 log_info("expect: \"%s\" [\"%s\" \"%s\" \"%s\"]",
87 path
, argv0
?: path
, argv1
, argv2
);
88 n
= strv_length(c
->argv
);
89 log_info("actual: \"%s\" [\"%s\" \"%s\" \"%s\"]",
90 c
->path
, c
->argv
[0], n
> 0 ? c
->argv
[1] : NULL
, n
> 1 ? c
->argv
[2] : NULL
);
91 assert_se(streq(c
->path
, path
));
92 assert_se(streq(c
->argv
[0], argv0
?: path
));
94 assert_se(streq_ptr(c
->argv
[1], argv1
));
96 assert_se(streq_ptr(c
->argv
[2], argv2
));
97 assert_se(!!(c
->flags
& EXEC_COMMAND_IGNORE_FAILURE
) == ignore
);
100 static void test_config_parse_exec(void) {
101 /* int config_parse_exec(
103 const char *filename,
106 unsigned section_line,
114 ExecCommand
*c
= NULL
, *c1
;
119 r
= manager_new(UNIT_FILE_USER
, MANAGER_TEST_RUN_MINIMAL
, &m
);
120 if (MANAGER_SKIP_TEST(r
)) {
121 log_notice_errno(r
, "Skipping test: manager_new: %m");
126 assert_se(manager_startup(m
, NULL
, NULL
) >= 0);
128 assert_se(u
= unit_new(m
, sizeof(Service
)));
130 log_info("/* basic test */");
131 r
= config_parse_exec(NULL
, "fake", 1, "section", 1,
132 "LValue", 0, "/RValue r1",
135 check_execcommand(c
, "/RValue", "/RValue", "r1", NULL
, false);
137 r
= config_parse_exec(NULL
, "fake", 2, "section", 1,
138 "LValue", 0, "/RValue///slashes r1///",
141 log_info("/* test slashes */");
143 c1
= c
->command_next
;
144 check_execcommand(c1
, "/RValue/slashes", "/RValue///slashes", "r1///", NULL
, false);
146 log_info("/* trailing slash */");
147 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
148 "LValue", 0, "/RValue/ argv0 r1",
150 assert_se(r
== -ENOEXEC
);
151 assert_se(c1
->command_next
== NULL
);
153 log_info("/* honour_argv0 */");
154 r
= config_parse_exec(NULL
, "fake", 3, "section", 1,
155 "LValue", 0, "@/RValue///slashes2 ///argv0 r1",
158 c1
= c1
->command_next
;
159 check_execcommand(c1
, "/RValue/slashes2", "///argv0", "r1", NULL
, false);
161 log_info("/* honour_argv0, no args */");
162 r
= config_parse_exec(NULL
, "fake", 3, "section", 1,
163 "LValue", 0, "@/RValue",
165 assert_se(r
== -ENOEXEC
);
166 assert_se(c1
->command_next
== NULL
);
168 log_info("/* no command, whitespace only, reset */");
169 r
= config_parse_exec(NULL
, "fake", 3, "section", 1,
173 assert_se(c
== NULL
);
175 log_info("/* ignore && honour_argv0 */");
176 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
177 "LValue", 0, "-@/RValue///slashes3 argv0a r1",
181 check_execcommand(c1
, "/RValue/slashes3", "argv0a", "r1", NULL
, true);
183 log_info("/* ignore && honour_argv0 */");
184 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
185 "LValue", 0, "@-/RValue///slashes4 argv0b r1",
188 c1
= c1
->command_next
;
189 check_execcommand(c1
, "/RValue/slashes4", "argv0b", "r1", NULL
, true);
191 log_info("/* ignore && ignore */");
192 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
193 "LValue", 0, "--/RValue argv0 r1",
196 assert_se(c1
->command_next
== NULL
);
198 log_info("/* ignore && ignore (2) */");
199 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
200 "LValue", 0, "-@-/RValue argv0 r1",
203 assert_se(c1
->command_next
== NULL
);
205 log_info("/* semicolon */");
206 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
208 "-@/RValue argv0 r1 ; "
212 c1
= c1
->command_next
;
213 check_execcommand(c1
, "/RValue", "argv0", "r1", NULL
, true);
215 c1
= c1
->command_next
;
216 check_execcommand(c1
, "/goo/goo", NULL
, "boo", NULL
, false);
218 log_info("/* two semicolons in a row */");
219 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
221 "-@/RValue argv0 r1 ; ; "
224 assert_se(r
== -ENOEXEC
);
225 c1
= c1
->command_next
;
226 check_execcommand(c1
, "/RValue", "argv0", "r1", NULL
, true);
228 /* second command fails because the executable name is ";" */
229 assert_se(c1
->command_next
== NULL
);
231 log_info("/* trailing semicolon */");
232 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
234 "-@/RValue argv0 r1 ; ",
237 c1
= c1
->command_next
;
238 check_execcommand(c1
, "/RValue", "argv0", "r1", NULL
, true);
240 assert_se(c1
->command_next
== NULL
);
242 log_info("/* trailing semicolon, no whitespace */");
243 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
245 "-@/RValue argv0 r1 ;",
248 c1
= c1
->command_next
;
249 check_execcommand(c1
, "/RValue", "argv0", "r1", NULL
, true);
251 assert_se(c1
->command_next
== NULL
);
253 log_info("/* trailing semicolon in single quotes */");
254 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
256 "-@/RValue argv0 r1 ';'",
259 c1
= c1
->command_next
;
260 check_execcommand(c1
, "/RValue", "argv0", "r1", ";", true);
262 log_info("/* escaped semicolon */");
263 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
268 c1
= c1
->command_next
;
269 check_execcommand(c1
, "/bin/find", NULL
, ";", NULL
, false);
271 log_info("/* escaped semicolon with following arg */");
272 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
277 c1
= c1
->command_next
;
278 check_execcommand(c1
,
279 "/sbin/find", NULL
, ";", "/x", false);
281 log_info("/* escaped semicolon as part of an expression */");
282 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
287 c1
= c1
->command_next
;
288 check_execcommand(c1
,
289 "/sbin/find", NULL
, "\\;x", NULL
, false);
291 log_info("/* encoded semicolon */");
292 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
297 c1
= c1
->command_next
;
298 check_execcommand(c1
, "/bin/find", NULL
, ";", NULL
, false);
300 log_info("/* quoted semicolon */");
301 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
306 c1
= c1
->command_next
;
307 check_execcommand(c1
, "/bin/find", NULL
, ";", NULL
, false);
309 log_info("/* quoted semicolon with following arg */");
310 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
312 "/sbin/find \";\" /x",
315 c1
= c1
->command_next
;
316 check_execcommand(c1
,
317 "/sbin/find", NULL
, ";", "/x", false);
319 log_info("/* spaces in the filename */");
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("/* spaces in the filename, no args */");
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 -1 -2", NULL
, NULL
, NULL
, false);
339 log_info("/* spaces in the filename, everything quoted */");
340 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
342 "\"/PATH WITH SPACES/daemon\" \"-1\" '-2'",
345 c1
= c1
->command_next
;
346 check_execcommand(c1
,
347 "/PATH WITH SPACES/daemon", NULL
, "-1", "-2", false);
349 log_info("/* escaped spaces in the filename */");
350 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
352 "\"/PATH\\sWITH\\sSPACES/daemon\" '-1 -2'",
355 c1
= c1
->command_next
;
356 check_execcommand(c1
,
357 "/PATH WITH SPACES/daemon", NULL
, "-1 -2", NULL
, false);
359 log_info("/* escaped spaces in the filename (2) */");
360 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
362 "\"/PATH\\x20WITH\\x20SPACES/daemon\" \"-1 -2\"",
365 c1
= c1
->command_next
;
366 check_execcommand(c1
,
367 "/PATH WITH SPACES/daemon", NULL
, "-1 -2", NULL
, false);
369 for (ccc
= "abfnrtv\\\'\"x"; *ccc
; ccc
++) {
370 /* \\x is an incomplete hexadecimal sequence, invalid because of the slash */
371 char path
[] = "/path\\X";
372 path
[sizeof(path
) - 2] = *ccc
;
374 log_info("/* invalid character: \\%c */", *ccc
);
375 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
378 assert_se(r
== -ENOEXEC
);
379 assert_se(c1
->command_next
== NULL
);
382 log_info("/* valid character: \\s */");
383 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
384 "LValue", 0, "/path\\s",
387 c1
= c1
->command_next
;
388 check_execcommand(c1
, "/path ", NULL
, NULL
, NULL
, false);
390 log_info("/* quoted backslashes */");
391 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
393 "/bin/grep '\\w+\\K'",
396 c1
= c1
->command_next
;
397 check_execcommand(c1
, "/bin/grep", NULL
, "\\w+\\K", NULL
, false);
400 log_info("/* trailing backslash: \\ */");
401 /* backslash is invalid */
402 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
403 "LValue", 0, "/path\\",
405 assert_se(r
== -ENOEXEC
);
406 assert_se(c1
->command_next
== NULL
);
408 log_info("/* missing ending ' */");
409 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
410 "LValue", 0, "/path 'foo",
412 assert_se(r
== -ENOEXEC
);
413 assert_se(c1
->command_next
== NULL
);
415 log_info("/* missing ending ' with trailing backslash */");
416 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
417 "LValue", 0, "/path 'foo\\",
419 assert_se(r
== -ENOEXEC
);
420 assert_se(c1
->command_next
== NULL
);
422 log_info("/* invalid space between modifiers */");
423 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
424 "LValue", 0, "- /path",
427 assert_se(c1
->command_next
== NULL
);
429 log_info("/* only modifiers, no path */");
430 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
434 assert_se(c1
->command_next
== NULL
);
436 log_info("/* empty argument, reset */");
437 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
441 assert_se(c
== NULL
);
443 exec_command_free_list(c
);
449 static void test_config_parse_log_extra_fields(void) {
450 /* int config_parse_log_extra_fields(
452 const char *filename,
455 unsigned section_line,
468 r
= manager_new(UNIT_FILE_USER
, MANAGER_TEST_RUN_MINIMAL
, &m
);
469 if (MANAGER_SKIP_TEST(r
)) {
470 log_notice_errno(r
, "Skipping test: manager_new: %m");
475 assert_se(manager_startup(m
, NULL
, NULL
) >= 0);
477 assert_se(u
= unit_new(m
, sizeof(Service
)));
479 log_info("/* %s – basic test */", __func__
);
480 r
= config_parse_log_extra_fields(NULL
, "fake", 1, "section", 1,
481 "LValue", 0, "FOO=BAR \"QOOF=quux ' ' \"",
484 assert_se(c
.n_log_extra_fields
== 2);
485 assert_se(strneq(c
.log_extra_fields
[0].iov_base
, "FOO=BAR", c
.log_extra_fields
[0].iov_len
));
486 assert_se(strneq(c
.log_extra_fields
[1].iov_base
, "QOOF=quux ' ' ", c
.log_extra_fields
[1].iov_len
));
488 log_info("/* %s – add some */", __func__
);
489 r
= config_parse_log_extra_fields(NULL
, "fake", 1, "section", 1,
490 "LValue", 0, "FOO2=BAR2 QOOF2=quux ' '",
493 assert_se(c
.n_log_extra_fields
== 4);
494 assert_se(strneq(c
.log_extra_fields
[0].iov_base
, "FOO=BAR", c
.log_extra_fields
[0].iov_len
));
495 assert_se(strneq(c
.log_extra_fields
[1].iov_base
, "QOOF=quux ' ' ", c
.log_extra_fields
[1].iov_len
));
496 assert_se(strneq(c
.log_extra_fields
[2].iov_base
, "FOO2=BAR2", c
.log_extra_fields
[2].iov_len
));
497 assert_se(strneq(c
.log_extra_fields
[3].iov_base
, "QOOF2=quux", c
.log_extra_fields
[3].iov_len
));
499 exec_context_dump(&c
, stdout
, " --> ");
501 log_info("/* %s – reset */", __func__
);
502 r
= config_parse_log_extra_fields(NULL
, "fake", 1, "section", 1,
506 assert_se(c
.n_log_extra_fields
== 0);
508 exec_context_free_log_extra_fields(&c
);
513 log_info("/* %s – bye */", __func__
);
531 "#SPAMD_ARGS=\"-d --socketpath=/var/lib/bulwark/spamd \\\n" \
532 "#--nouser-config \\\n" \
538 "HWMON_MODULES=\"coretemp f71882fg\"\n" \
540 "# For compatibility reasons\n" \
542 "MODULE_0=coretemp\n" \
549 static void test_load_env_file_1(void) {
550 _cleanup_strv_free_
char **data
= NULL
;
553 char name
[] = "/tmp/test-load-env-file.XXXXXX";
554 _cleanup_close_
int fd
;
556 fd
= mkostemp_safe(name
);
558 assert_se(write(fd
, env_file_1
, sizeof(env_file_1
)) == sizeof(env_file_1
));
560 r
= load_env_file(NULL
, name
, NULL
, &data
);
562 assert_se(streq(data
[0], "a=a"));
563 assert_se(streq(data
[1], "b=bc"));
564 assert_se(streq(data
[2], "d=def"));
565 assert_se(streq(data
[3], "g=g "));
566 assert_se(streq(data
[4], "h=h"));
567 assert_se(streq(data
[5], "i=i"));
568 assert_se(data
[6] == NULL
);
572 static void test_load_env_file_2(void) {
573 _cleanup_strv_free_
char **data
= NULL
;
576 char name
[] = "/tmp/test-load-env-file.XXXXXX";
577 _cleanup_close_
int fd
;
579 fd
= mkostemp_safe(name
);
581 assert_se(write(fd
, env_file_2
, sizeof(env_file_2
)) == sizeof(env_file_2
));
583 r
= load_env_file(NULL
, name
, NULL
, &data
);
585 assert_se(streq(data
[0], "a=a"));
586 assert_se(data
[1] == NULL
);
590 static void test_load_env_file_3(void) {
591 _cleanup_strv_free_
char **data
= NULL
;
594 char name
[] = "/tmp/test-load-env-file.XXXXXX";
595 _cleanup_close_
int fd
;
597 fd
= mkostemp_safe(name
);
599 assert_se(write(fd
, env_file_3
, sizeof(env_file_3
)) == sizeof(env_file_3
));
601 r
= load_env_file(NULL
, name
, NULL
, &data
);
603 assert_se(data
== NULL
);
607 static void test_load_env_file_4(void) {
608 _cleanup_strv_free_
char **data
= NULL
;
609 char name
[] = "/tmp/test-load-env-file.XXXXXX";
610 _cleanup_close_
int fd
;
613 fd
= mkostemp_safe(name
);
615 assert_se(write(fd
, env_file_4
, sizeof(env_file_4
)) == sizeof(env_file_4
));
617 r
= load_env_file(NULL
, name
, NULL
, &data
);
619 assert_se(streq(data
[0], "HWMON_MODULES=coretemp f71882fg"));
620 assert_se(streq(data
[1], "MODULE_0=coretemp"));
621 assert_se(streq(data
[2], "MODULE_1=f71882fg"));
622 assert_se(data
[3] == NULL
);
626 static void test_load_env_file_5(void) {
627 _cleanup_strv_free_
char **data
= NULL
;
630 char name
[] = "/tmp/test-load-env-file.XXXXXX";
631 _cleanup_close_
int fd
;
633 fd
= mkostemp_safe(name
);
635 assert_se(write(fd
, env_file_5
, sizeof(env_file_5
)) == sizeof(env_file_5
));
637 r
= load_env_file(NULL
, name
, NULL
, &data
);
639 assert_se(streq(data
[0], "a="));
640 assert_se(streq(data
[1], "b="));
641 assert_se(data
[2] == NULL
);
645 static void test_install_printf(void) {
646 char name
[] = "name.service",
647 path
[] = "/run/systemd/system/name.service";
648 UnitFileInstallInfo i
= { .name
= name
, .path
= path
, };
649 UnitFileInstallInfo i2
= { .name
= name
, .path
= path
, };
650 char name3
[] = "name@inst.service",
651 path3
[] = "/run/systemd/system/name.service";
652 UnitFileInstallInfo i3
= { .name
= name3
, .path
= path3
, };
653 UnitFileInstallInfo i4
= { .name
= name3
, .path
= path3
, };
655 _cleanup_free_
char *mid
= NULL
, *bid
= NULL
, *host
= NULL
, *uid
= NULL
, *user
= NULL
;
657 assert_se(specifier_machine_id('m', NULL
, NULL
, &mid
) >= 0 && mid
);
658 assert_se(specifier_boot_id('b', NULL
, NULL
, &bid
) >= 0 && bid
);
659 assert_se((host
= gethostname_malloc()));
660 assert_se((user
= uid_to_name(getuid())));
661 assert_se(asprintf(&uid
, UID_FMT
, getuid()) >= 0);
663 #define expect(src, pattern, result) \
665 _cleanup_free_ char *t = NULL; \
666 _cleanup_free_ char \
667 *d1 = strdup(i.name), \
668 *d2 = strdup(i.path); \
669 assert_se(install_full_printf(&src, pattern, &t) >= 0 || !result); \
670 memzero(i.name, strlen(i.name)); \
671 memzero(i.path, strlen(i.path)); \
672 assert_se(d1 && d2); \
675 assert_se(streq(t, result)); \
676 } else assert_se(t == NULL); \
677 strcpy(i.name, d1); \
678 strcpy(i.path, d2); \
681 expect(i
, "%n", "name.service");
682 expect(i
, "%N", "name");
683 expect(i
, "%p", "name");
685 expect(i
, "%u", user
);
686 expect(i
, "%U", uid
);
688 expect(i
, "%m", mid
);
689 expect(i
, "%b", bid
);
690 expect(i
, "%H", host
);
692 expect(i2
, "%u", user
);
693 expect(i2
, "%U", uid
);
695 expect(i3
, "%n", "name@inst.service");
696 expect(i3
, "%N", "name@inst");
697 expect(i3
, "%p", "name");
698 expect(i3
, "%u", user
);
699 expect(i3
, "%U", uid
);
701 expect(i3
, "%m", mid
);
702 expect(i3
, "%b", bid
);
703 expect(i3
, "%H", host
);
705 expect(i4
, "%u", user
);
706 expect(i4
, "%U", uid
);
709 static uint64_t make_cap(int cap
) {
710 return ((uint64_t) 1ULL << (uint64_t) cap
);
713 static void test_config_parse_capability_set(void) {
714 /* int config_parse_capability_set(
716 const char *filename,
719 unsigned section_line,
726 uint64_t capability_bounding_set
= 0;
728 r
= config_parse_capability_set(NULL
, "fake", 1, "section", 1,
729 "CapabilityBoundingSet", 0, "CAP_NET_RAW",
730 &capability_bounding_set
, NULL
);
732 assert_se(capability_bounding_set
== make_cap(CAP_NET_RAW
));
734 r
= config_parse_capability_set(NULL
, "fake", 1, "section", 1,
735 "CapabilityBoundingSet", 0, "CAP_NET_ADMIN",
736 &capability_bounding_set
, NULL
);
738 assert_se(capability_bounding_set
== (make_cap(CAP_NET_RAW
) | make_cap(CAP_NET_ADMIN
)));
740 r
= config_parse_capability_set(NULL
, "fake", 1, "section", 1,
741 "CapabilityBoundingSet", 0, "~CAP_NET_ADMIN",
742 &capability_bounding_set
, NULL
);
744 assert_se(capability_bounding_set
== make_cap(CAP_NET_RAW
));
746 r
= config_parse_capability_set(NULL
, "fake", 1, "section", 1,
747 "CapabilityBoundingSet", 0, "",
748 &capability_bounding_set
, NULL
);
750 assert_se(capability_bounding_set
== UINT64_C(0));
752 r
= config_parse_capability_set(NULL
, "fake", 1, "section", 1,
753 "CapabilityBoundingSet", 0, "~",
754 &capability_bounding_set
, NULL
);
756 assert_se(cap_test_all(capability_bounding_set
));
758 capability_bounding_set
= 0;
759 r
= config_parse_capability_set(NULL
, "fake", 1, "section", 1,
760 "CapabilityBoundingSet", 0, " 'CAP_NET_RAW' WAT_CAP??? CAP_NET_ADMIN CAP'_trailing_garbage",
761 &capability_bounding_set
, NULL
);
763 assert_se(capability_bounding_set
== (make_cap(CAP_NET_RAW
) | make_cap(CAP_NET_ADMIN
)));
766 static void test_config_parse_rlimit(void) {
767 struct rlimit
* rl
[_RLIMIT_MAX
] = {};
769 assert_se(config_parse_limit(NULL
, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE
, "55", rl
, NULL
) >= 0);
770 assert_se(rl
[RLIMIT_NOFILE
]);
771 assert_se(rl
[RLIMIT_NOFILE
]->rlim_cur
== 55);
772 assert_se(rl
[RLIMIT_NOFILE
]->rlim_cur
== rl
[RLIMIT_NOFILE
]->rlim_max
);
774 assert_se(config_parse_limit(NULL
, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE
, "55:66", rl
, NULL
) >= 0);
775 assert_se(rl
[RLIMIT_NOFILE
]);
776 assert_se(rl
[RLIMIT_NOFILE
]->rlim_cur
== 55);
777 assert_se(rl
[RLIMIT_NOFILE
]->rlim_max
== 66);
779 assert_se(config_parse_limit(NULL
, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE
, "infinity", rl
, NULL
) >= 0);
780 assert_se(rl
[RLIMIT_NOFILE
]);
781 assert_se(rl
[RLIMIT_NOFILE
]->rlim_cur
== RLIM_INFINITY
);
782 assert_se(rl
[RLIMIT_NOFILE
]->rlim_cur
== rl
[RLIMIT_NOFILE
]->rlim_max
);
784 assert_se(config_parse_limit(NULL
, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE
, "infinity:infinity", rl
, NULL
) >= 0);
785 assert_se(rl
[RLIMIT_NOFILE
]);
786 assert_se(rl
[RLIMIT_NOFILE
]->rlim_cur
== RLIM_INFINITY
);
787 assert_se(rl
[RLIMIT_NOFILE
]->rlim_cur
== rl
[RLIMIT_NOFILE
]->rlim_max
);
789 rl
[RLIMIT_NOFILE
]->rlim_cur
= 10;
790 rl
[RLIMIT_NOFILE
]->rlim_max
= 20;
792 /* Invalid values don't change rl */
793 assert_se(config_parse_limit(NULL
, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE
, "10:20:30", rl
, NULL
) >= 0);
794 assert_se(rl
[RLIMIT_NOFILE
]);
795 assert_se(rl
[RLIMIT_NOFILE
]->rlim_cur
== 10);
796 assert_se(rl
[RLIMIT_NOFILE
]->rlim_max
== 20);
798 assert_se(config_parse_limit(NULL
, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE
, "wat:wat", rl
, NULL
) >= 0);
799 assert_se(rl
[RLIMIT_NOFILE
]);
800 assert_se(rl
[RLIMIT_NOFILE
]->rlim_cur
== 10);
801 assert_se(rl
[RLIMIT_NOFILE
]->rlim_max
== 20);
803 assert_se(config_parse_limit(NULL
, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE
, "66:wat", rl
, NULL
) >= 0);
804 assert_se(rl
[RLIMIT_NOFILE
]);
805 assert_se(rl
[RLIMIT_NOFILE
]->rlim_cur
== 10);
806 assert_se(rl
[RLIMIT_NOFILE
]->rlim_max
== 20);
808 assert_se(config_parse_limit(NULL
, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE
, "200:100", rl
, NULL
) >= 0);
809 assert_se(rl
[RLIMIT_NOFILE
]);
810 assert_se(rl
[RLIMIT_NOFILE
]->rlim_cur
== 10);
811 assert_se(rl
[RLIMIT_NOFILE
]->rlim_max
== 20);
813 rl
[RLIMIT_NOFILE
] = mfree(rl
[RLIMIT_NOFILE
]);
815 assert_se(config_parse_limit(NULL
, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU
, "56", rl
, NULL
) >= 0);
816 assert_se(rl
[RLIMIT_CPU
]);
817 assert_se(rl
[RLIMIT_CPU
]->rlim_cur
== 56);
818 assert_se(rl
[RLIMIT_CPU
]->rlim_cur
== rl
[RLIMIT_CPU
]->rlim_max
);
820 assert_se(config_parse_limit(NULL
, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU
, "57s", rl
, NULL
) >= 0);
821 assert_se(rl
[RLIMIT_CPU
]);
822 assert_se(rl
[RLIMIT_CPU
]->rlim_cur
== 57);
823 assert_se(rl
[RLIMIT_CPU
]->rlim_cur
== rl
[RLIMIT_CPU
]->rlim_max
);
825 assert_se(config_parse_limit(NULL
, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU
, "40s:1m", rl
, NULL
) >= 0);
826 assert_se(rl
[RLIMIT_CPU
]);
827 assert_se(rl
[RLIMIT_CPU
]->rlim_cur
== 40);
828 assert_se(rl
[RLIMIT_CPU
]->rlim_max
== 60);
830 assert_se(config_parse_limit(NULL
, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU
, "infinity", rl
, NULL
) >= 0);
831 assert_se(rl
[RLIMIT_CPU
]);
832 assert_se(rl
[RLIMIT_CPU
]->rlim_cur
== RLIM_INFINITY
);
833 assert_se(rl
[RLIMIT_CPU
]->rlim_cur
== rl
[RLIMIT_CPU
]->rlim_max
);
835 assert_se(config_parse_limit(NULL
, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU
, "1234ms", rl
, NULL
) >= 0);
836 assert_se(rl
[RLIMIT_CPU
]);
837 assert_se(rl
[RLIMIT_CPU
]->rlim_cur
== 2);
838 assert_se(rl
[RLIMIT_CPU
]->rlim_cur
== rl
[RLIMIT_CPU
]->rlim_max
);
840 rl
[RLIMIT_CPU
] = mfree(rl
[RLIMIT_CPU
]);
842 assert_se(config_parse_limit(NULL
, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME
, "58", rl
, NULL
) >= 0);
843 assert_se(rl
[RLIMIT_RTTIME
]);
844 assert_se(rl
[RLIMIT_RTTIME
]->rlim_cur
== 58);
845 assert_se(rl
[RLIMIT_RTTIME
]->rlim_cur
== rl
[RLIMIT_RTTIME
]->rlim_max
);
847 assert_se(config_parse_limit(NULL
, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME
, "58:60", rl
, NULL
) >= 0);
848 assert_se(rl
[RLIMIT_RTTIME
]);
849 assert_se(rl
[RLIMIT_RTTIME
]->rlim_cur
== 58);
850 assert_se(rl
[RLIMIT_RTTIME
]->rlim_max
== 60);
852 assert_se(config_parse_limit(NULL
, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME
, "59s", rl
, NULL
) >= 0);
853 assert_se(rl
[RLIMIT_RTTIME
]);
854 assert_se(rl
[RLIMIT_RTTIME
]->rlim_cur
== 59 * USEC_PER_SEC
);
855 assert_se(rl
[RLIMIT_RTTIME
]->rlim_cur
== rl
[RLIMIT_RTTIME
]->rlim_max
);
857 assert_se(config_parse_limit(NULL
, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME
, "59s:123s", rl
, NULL
) >= 0);
858 assert_se(rl
[RLIMIT_RTTIME
]);
859 assert_se(rl
[RLIMIT_RTTIME
]->rlim_cur
== 59 * USEC_PER_SEC
);
860 assert_se(rl
[RLIMIT_RTTIME
]->rlim_max
== 123 * USEC_PER_SEC
);
862 assert_se(config_parse_limit(NULL
, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME
, "infinity", rl
, NULL
) >= 0);
863 assert_se(rl
[RLIMIT_RTTIME
]);
864 assert_se(rl
[RLIMIT_RTTIME
]->rlim_cur
== RLIM_INFINITY
);
865 assert_se(rl
[RLIMIT_RTTIME
]->rlim_cur
== rl
[RLIMIT_RTTIME
]->rlim_max
);
867 assert_se(config_parse_limit(NULL
, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME
, "infinity:infinity", rl
, NULL
) >= 0);
868 assert_se(rl
[RLIMIT_RTTIME
]);
869 assert_se(rl
[RLIMIT_RTTIME
]->rlim_cur
== RLIM_INFINITY
);
870 assert_se(rl
[RLIMIT_RTTIME
]->rlim_cur
== rl
[RLIMIT_RTTIME
]->rlim_max
);
872 assert_se(config_parse_limit(NULL
, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME
, "2345ms", rl
, NULL
) >= 0);
873 assert_se(rl
[RLIMIT_RTTIME
]);
874 assert_se(rl
[RLIMIT_RTTIME
]->rlim_cur
== 2345 * USEC_PER_MSEC
);
875 assert_se(rl
[RLIMIT_RTTIME
]->rlim_cur
== rl
[RLIMIT_RTTIME
]->rlim_max
);
877 rl
[RLIMIT_RTTIME
] = mfree(rl
[RLIMIT_RTTIME
]);
880 static void test_config_parse_pass_environ(void) {
881 /* int config_parse_pass_environ(
883 const char *filename,
886 unsigned section_line,
893 _cleanup_strv_free_
char **passenv
= NULL
;
895 r
= config_parse_pass_environ(NULL
, "fake", 1, "section", 1,
896 "PassEnvironment", 0, "A B",
899 assert_se(strv_length(passenv
) == 2);
900 assert_se(streq(passenv
[0], "A"));
901 assert_se(streq(passenv
[1], "B"));
903 r
= config_parse_pass_environ(NULL
, "fake", 1, "section", 1,
904 "PassEnvironment", 0, "",
907 assert_se(strv_isempty(passenv
));
909 r
= config_parse_pass_environ(NULL
, "fake", 1, "section", 1,
910 "PassEnvironment", 0, "'invalid name' 'normal_name' A=1 \\",
913 assert_se(strv_length(passenv
) == 1);
914 assert_se(streq(passenv
[0], "normal_name"));
918 static void test_unit_dump_config_items(void) {
919 unit_dump_config_items(stdout
);
922 int main(int argc
, char *argv
[]) {
923 _cleanup_(rm_rf_physical_and_freep
) char *runtime_dir
= NULL
;
926 log_parse_environment();
929 r
= enter_cgroup_subroot();
930 if (r
== -ENOMEDIUM
) {
931 log_notice_errno(r
, "Skipping test: cgroupfs not available");
932 return EXIT_TEST_SKIP
;
935 assert_se(runtime_dir
= setup_fake_runtime_dir());
937 r
= test_unit_file_get_set();
938 test_config_parse_exec();
939 test_config_parse_log_extra_fields();
940 test_config_parse_capability_set();
941 test_config_parse_rlimit();
942 test_config_parse_pass_environ();
943 test_load_env_file_1();
944 test_load_env_file_2();
945 test_load_env_file_3();
946 test_load_env_file_4();
947 test_load_env_file_5();
948 TEST_REQ_RUNNING_SYSTEMD(test_install_printf());
949 test_unit_dump_config_items();