1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 Copyright © 2013 Zbigniew Jędrzejewski-Szmek
10 #include <sys/capability.h>
13 #include "alloc-util.h"
14 #include "all-units.h"
15 #include "capability-util.h"
16 #include "conf-parser.h"
21 #include "hostname-util.h"
22 #include "install-printf.h"
24 #include "load-fragment.h"
27 #include "specifier.h"
28 #include "string-util.h"
30 #include "test-helper.h"
32 #include "user-util.h"
35 static int test_unit_file_get_set(void) {
41 h
= hashmap_new(&string_hash_ops
);
44 r
= unit_file_get_list(UNIT_FILE_SYSTEM
, NULL
, h
, NULL
, NULL
);
46 if (IN_SET(r
, -EPERM
, -EACCES
)) {
47 log_notice_errno(r
, "Skipping test: unit_file_get_list: %m");
48 return EXIT_TEST_SKIP
;
51 log_full_errno(r
== 0 ? LOG_INFO
: LOG_ERR
, r
,
52 "unit_file_get_list: %m");
56 HASHMAP_FOREACH(p
, h
, i
)
57 printf("%s = %s\n", p
->path
, unit_file_state_to_string(p
->state
));
59 unit_file_list_free(h
);
64 static void check_execcommand(ExecCommand
*c
,
73 log_info("expect: \"%s\" [\"%s\" \"%s\" \"%s\"]",
74 path
, argv0
?: path
, argv1
, argv2
);
75 n
= strv_length(c
->argv
);
76 log_info("actual: \"%s\" [\"%s\" \"%s\" \"%s\"]",
77 c
->path
, c
->argv
[0], n
> 0 ? c
->argv
[1] : NULL
, n
> 1 ? c
->argv
[2] : NULL
);
78 assert_se(streq(c
->path
, path
));
79 assert_se(streq(c
->argv
[0], argv0
?: path
));
81 assert_se(streq_ptr(c
->argv
[1], argv1
));
83 assert_se(streq_ptr(c
->argv
[2], argv2
));
84 assert_se(!!(c
->flags
& EXEC_COMMAND_IGNORE_FAILURE
) == ignore
);
87 static void test_config_parse_exec(void) {
88 /* int config_parse_exec(
93 unsigned section_line,
101 ExecCommand
*c
= NULL
, *c1
;
103 _cleanup_(manager_freep
) Manager
*m
= NULL
;
104 _cleanup_(unit_freep
) Unit
*u
= NULL
;
106 r
= manager_new(UNIT_FILE_USER
, MANAGER_TEST_RUN_MINIMAL
, &m
);
107 if (MANAGER_SKIP_TEST(r
)) {
108 log_notice_errno(r
, "Skipping test: manager_new: %m");
113 assert_se(manager_startup(m
, NULL
, NULL
) >= 0);
115 assert_se(u
= unit_new(m
, sizeof(Service
)));
117 log_info("/* basic test */");
118 r
= config_parse_exec(NULL
, "fake", 1, "section", 1,
119 "LValue", 0, "/RValue r1",
122 check_execcommand(c
, "/RValue", "/RValue", "r1", NULL
, false);
124 r
= config_parse_exec(NULL
, "fake", 2, "section", 1,
125 "LValue", 0, "/RValue///slashes r1///",
128 log_info("/* test slashes */");
130 c1
= c
->command_next
;
131 check_execcommand(c1
, "/RValue/slashes", "/RValue///slashes", "r1///", NULL
, false);
133 log_info("/* trailing slash */");
134 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
135 "LValue", 0, "/RValue/ argv0 r1",
137 assert_se(r
== -ENOEXEC
);
138 assert_se(c1
->command_next
== NULL
);
140 log_info("/* honour_argv0 */");
141 r
= config_parse_exec(NULL
, "fake", 3, "section", 1,
142 "LValue", 0, "@/RValue///slashes2 ///argv0 r1",
145 c1
= c1
->command_next
;
146 check_execcommand(c1
, "/RValue/slashes2", "///argv0", "r1", NULL
, false);
148 log_info("/* honour_argv0, no args */");
149 r
= config_parse_exec(NULL
, "fake", 3, "section", 1,
150 "LValue", 0, "@/RValue",
152 assert_se(r
== -ENOEXEC
);
153 assert_se(c1
->command_next
== NULL
);
155 log_info("/* no command, whitespace only, reset */");
156 r
= config_parse_exec(NULL
, "fake", 3, "section", 1,
160 assert_se(c
== NULL
);
162 log_info("/* ignore && honour_argv0 */");
163 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
164 "LValue", 0, "-@/RValue///slashes3 argv0a r1",
168 check_execcommand(c1
, "/RValue/slashes3", "argv0a", "r1", NULL
, true);
170 log_info("/* ignore && honour_argv0 */");
171 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
172 "LValue", 0, "@-/RValue///slashes4 argv0b r1",
175 c1
= c1
->command_next
;
176 check_execcommand(c1
, "/RValue/slashes4", "argv0b", "r1", NULL
, true);
178 log_info("/* ignore && ignore */");
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("/* ignore && ignore (2) */");
186 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
187 "LValue", 0, "-@-/RValue argv0 r1",
190 assert_se(c1
->command_next
== NULL
);
192 log_info("/* semicolon */");
193 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
195 "-@/RValue argv0 r1 ; "
199 c1
= c1
->command_next
;
200 check_execcommand(c1
, "/RValue", "argv0", "r1", NULL
, true);
202 c1
= c1
->command_next
;
203 check_execcommand(c1
, "/goo/goo", NULL
, "boo", NULL
, false);
205 log_info("/* two semicolons in a row */");
206 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
208 "-@/RValue argv0 r1 ; ; "
211 assert_se(r
== -ENOEXEC
);
212 c1
= c1
->command_next
;
213 check_execcommand(c1
, "/RValue", "argv0", "r1", NULL
, true);
215 /* second command fails because the executable name is ";" */
216 assert_se(c1
->command_next
== NULL
);
218 log_info("/* trailing semicolon */");
219 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
221 "-@/RValue argv0 r1 ; ",
224 c1
= c1
->command_next
;
225 check_execcommand(c1
, "/RValue", "argv0", "r1", NULL
, true);
227 assert_se(c1
->command_next
== NULL
);
229 log_info("/* trailing semicolon, no whitespace */");
230 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
232 "-@/RValue argv0 r1 ;",
235 c1
= c1
->command_next
;
236 check_execcommand(c1
, "/RValue", "argv0", "r1", NULL
, true);
238 assert_se(c1
->command_next
== NULL
);
240 log_info("/* trailing semicolon in single quotes */");
241 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
243 "-@/RValue argv0 r1 ';'",
246 c1
= c1
->command_next
;
247 check_execcommand(c1
, "/RValue", "argv0", "r1", ";", true);
249 log_info("/* escaped semicolon */");
250 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
255 c1
= c1
->command_next
;
256 check_execcommand(c1
, "/bin/find", NULL
, ";", NULL
, false);
258 log_info("/* escaped semicolon with following arg */");
259 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
264 c1
= c1
->command_next
;
265 check_execcommand(c1
,
266 "/sbin/find", NULL
, ";", "/x", false);
268 log_info("/* escaped semicolon as part of an expression */");
269 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
274 c1
= c1
->command_next
;
275 check_execcommand(c1
,
276 "/sbin/find", NULL
, "\\;x", NULL
, false);
278 log_info("/* encoded semicolon */");
279 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
284 c1
= c1
->command_next
;
285 check_execcommand(c1
, "/bin/find", NULL
, ";", NULL
, false);
287 log_info("/* quoted semicolon */");
288 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
293 c1
= c1
->command_next
;
294 check_execcommand(c1
, "/bin/find", NULL
, ";", NULL
, false);
296 log_info("/* quoted semicolon with following arg */");
297 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
299 "/sbin/find \";\" /x",
302 c1
= c1
->command_next
;
303 check_execcommand(c1
,
304 "/sbin/find", NULL
, ";", "/x", false);
306 log_info("/* spaces in the filename */");
307 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
309 "\"/PATH WITH SPACES/daemon\" -1 -2",
312 c1
= c1
->command_next
;
313 check_execcommand(c1
,
314 "/PATH WITH SPACES/daemon", NULL
, "-1", "-2", false);
316 log_info("/* spaces in the filename, no args */");
317 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
319 "\"/PATH WITH SPACES/daemon -1 -2\"",
322 c1
= c1
->command_next
;
323 check_execcommand(c1
,
324 "/PATH WITH SPACES/daemon -1 -2", NULL
, NULL
, NULL
, false);
326 log_info("/* spaces in the filename, everything quoted */");
327 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
329 "\"/PATH WITH SPACES/daemon\" \"-1\" '-2'",
332 c1
= c1
->command_next
;
333 check_execcommand(c1
,
334 "/PATH WITH SPACES/daemon", NULL
, "-1", "-2", false);
336 log_info("/* escaped spaces in the filename */");
337 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
339 "\"/PATH\\sWITH\\sSPACES/daemon\" '-1 -2'",
342 c1
= c1
->command_next
;
343 check_execcommand(c1
,
344 "/PATH WITH SPACES/daemon", NULL
, "-1 -2", NULL
, false);
346 log_info("/* escaped spaces in the filename (2) */");
347 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
349 "\"/PATH\\x20WITH\\x20SPACES/daemon\" \"-1 -2\"",
352 c1
= c1
->command_next
;
353 check_execcommand(c1
,
354 "/PATH WITH SPACES/daemon", NULL
, "-1 -2", NULL
, false);
356 for (ccc
= "abfnrtv\\\'\"x"; *ccc
; ccc
++) {
357 /* \\x is an incomplete hexadecimal sequence, invalid because of the slash */
358 char path
[] = "/path\\X";
359 path
[sizeof(path
) - 2] = *ccc
;
361 log_info("/* invalid character: \\%c */", *ccc
);
362 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
365 assert_se(r
== -ENOEXEC
);
366 assert_se(c1
->command_next
== NULL
);
369 log_info("/* valid character: \\s */");
370 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
371 "LValue", 0, "/path\\s",
374 c1
= c1
->command_next
;
375 check_execcommand(c1
, "/path ", NULL
, NULL
, NULL
, false);
377 log_info("/* quoted backslashes */");
378 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
380 "/bin/grep '\\w+\\K'",
383 c1
= c1
->command_next
;
384 check_execcommand(c1
, "/bin/grep", NULL
, "\\w+\\K", NULL
, false);
386 log_info("/* trailing backslash: \\ */");
387 /* backslash is invalid */
388 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
389 "LValue", 0, "/path\\",
391 assert_se(r
== -ENOEXEC
);
392 assert_se(c1
->command_next
== NULL
);
394 log_info("/* missing ending ' */");
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("/* missing ending ' with trailing backslash */");
402 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
403 "LValue", 0, "/path 'foo\\",
405 assert_se(r
== -ENOEXEC
);
406 assert_se(c1
->command_next
== NULL
);
408 log_info("/* invalid space between modifiers */");
409 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
410 "LValue", 0, "- /path",
413 assert_se(c1
->command_next
== NULL
);
415 log_info("/* only modifiers, no path */");
416 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
420 assert_se(c1
->command_next
== NULL
);
422 log_info("/* empty argument, reset */");
423 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
427 assert_se(c
== NULL
);
429 exec_command_free_list(c
);
432 static void test_config_parse_log_extra_fields(void) {
433 /* int config_parse_log_extra_fields(
435 const char *filename,
438 unsigned section_line,
447 _cleanup_(manager_freep
) Manager
*m
= NULL
;
448 _cleanup_(unit_freep
) Unit
*u
= NULL
;
451 r
= manager_new(UNIT_FILE_USER
, MANAGER_TEST_RUN_MINIMAL
, &m
);
452 if (MANAGER_SKIP_TEST(r
)) {
453 log_notice_errno(r
, "Skipping test: manager_new: %m");
458 assert_se(manager_startup(m
, NULL
, NULL
) >= 0);
460 assert_se(u
= unit_new(m
, sizeof(Service
)));
462 log_info("/* %s – basic test */", __func__
);
463 r
= config_parse_log_extra_fields(NULL
, "fake", 1, "section", 1,
464 "LValue", 0, "FOO=BAR \"QOOF=quux ' ' \"",
467 assert_se(c
.n_log_extra_fields
== 2);
468 assert_se(strneq(c
.log_extra_fields
[0].iov_base
, "FOO=BAR", c
.log_extra_fields
[0].iov_len
));
469 assert_se(strneq(c
.log_extra_fields
[1].iov_base
, "QOOF=quux ' ' ", c
.log_extra_fields
[1].iov_len
));
471 log_info("/* %s – add some */", __func__
);
472 r
= config_parse_log_extra_fields(NULL
, "fake", 1, "section", 1,
473 "LValue", 0, "FOO2=BAR2 QOOF2=quux ' '",
476 assert_se(c
.n_log_extra_fields
== 4);
477 assert_se(strneq(c
.log_extra_fields
[0].iov_base
, "FOO=BAR", c
.log_extra_fields
[0].iov_len
));
478 assert_se(strneq(c
.log_extra_fields
[1].iov_base
, "QOOF=quux ' ' ", c
.log_extra_fields
[1].iov_len
));
479 assert_se(strneq(c
.log_extra_fields
[2].iov_base
, "FOO2=BAR2", c
.log_extra_fields
[2].iov_len
));
480 assert_se(strneq(c
.log_extra_fields
[3].iov_base
, "QOOF2=quux", c
.log_extra_fields
[3].iov_len
));
482 exec_context_dump(&c
, stdout
, " --> ");
484 log_info("/* %s – reset */", __func__
);
485 r
= config_parse_log_extra_fields(NULL
, "fake", 1, "section", 1,
489 assert_se(c
.n_log_extra_fields
== 0);
491 exec_context_free_log_extra_fields(&c
);
493 log_info("/* %s – bye */", __func__
);
511 "#SPAMD_ARGS=\"-d --socketpath=/var/lib/bulwark/spamd \\\n" \
512 "#--nouser-config \\\n" \
518 "HWMON_MODULES=\"coretemp f71882fg\"\n" \
520 "# For compatibility reasons\n" \
522 "MODULE_0=coretemp\n" \
529 static void test_load_env_file_1(void) {
530 _cleanup_strv_free_
char **data
= NULL
;
533 _cleanup_(unlink_tempfilep
) char name
[] = "/tmp/test-load-env-file.XXXXXX";
534 _cleanup_close_
int fd
;
536 fd
= mkostemp_safe(name
);
538 assert_se(write(fd
, env_file_1
, sizeof(env_file_1
)) == sizeof(env_file_1
));
540 r
= load_env_file(NULL
, name
, NULL
, &data
);
542 assert_se(streq(data
[0], "a=a"));
543 assert_se(streq(data
[1], "b=bc"));
544 assert_se(streq(data
[2], "d=def"));
545 assert_se(streq(data
[3], "g=g "));
546 assert_se(streq(data
[4], "h=h"));
547 assert_se(streq(data
[5], "i=i"));
548 assert_se(data
[6] == NULL
);
551 static void test_load_env_file_2(void) {
552 _cleanup_strv_free_
char **data
= NULL
;
555 _cleanup_(unlink_tempfilep
) char name
[] = "/tmp/test-load-env-file.XXXXXX";
556 _cleanup_close_
int fd
;
558 fd
= mkostemp_safe(name
);
560 assert_se(write(fd
, env_file_2
, sizeof(env_file_2
)) == sizeof(env_file_2
));
562 r
= load_env_file(NULL
, name
, NULL
, &data
);
564 assert_se(streq(data
[0], "a=a"));
565 assert_se(data
[1] == NULL
);
568 static void test_load_env_file_3(void) {
569 _cleanup_strv_free_
char **data
= NULL
;
572 _cleanup_(unlink_tempfilep
) char name
[] = "/tmp/test-load-env-file.XXXXXX";
573 _cleanup_close_
int fd
;
575 fd
= mkostemp_safe(name
);
577 assert_se(write(fd
, env_file_3
, sizeof(env_file_3
)) == sizeof(env_file_3
));
579 r
= load_env_file(NULL
, name
, NULL
, &data
);
581 assert_se(data
== NULL
);
584 static void test_load_env_file_4(void) {
585 _cleanup_strv_free_
char **data
= NULL
;
586 _cleanup_(unlink_tempfilep
) char name
[] = "/tmp/test-load-env-file.XXXXXX";
587 _cleanup_close_
int fd
;
590 fd
= mkostemp_safe(name
);
592 assert_se(write(fd
, env_file_4
, sizeof(env_file_4
)) == sizeof(env_file_4
));
594 r
= load_env_file(NULL
, name
, NULL
, &data
);
596 assert_se(streq(data
[0], "HWMON_MODULES=coretemp f71882fg"));
597 assert_se(streq(data
[1], "MODULE_0=coretemp"));
598 assert_se(streq(data
[2], "MODULE_1=f71882fg"));
599 assert_se(data
[3] == NULL
);
602 static void test_load_env_file_5(void) {
603 _cleanup_strv_free_
char **data
= NULL
;
606 _cleanup_(unlink_tempfilep
) char name
[] = "/tmp/test-load-env-file.XXXXXX";
607 _cleanup_close_
int fd
;
609 fd
= mkostemp_safe(name
);
611 assert_se(write(fd
, env_file_5
, sizeof(env_file_5
)) == sizeof(env_file_5
));
613 r
= load_env_file(NULL
, name
, NULL
, &data
);
615 assert_se(streq(data
[0], "a="));
616 assert_se(streq(data
[1], "b="));
617 assert_se(data
[2] == NULL
);
620 static void test_install_printf(void) {
621 char name
[] = "name.service",
622 path
[] = "/run/systemd/system/name.service";
623 UnitFileInstallInfo i
= { .name
= name
, .path
= path
, };
624 UnitFileInstallInfo i2
= { .name
= name
, .path
= path
, };
625 char name3
[] = "name@inst.service",
626 path3
[] = "/run/systemd/system/name.service";
627 UnitFileInstallInfo i3
= { .name
= name3
, .path
= path3
, };
628 UnitFileInstallInfo i4
= { .name
= name3
, .path
= path3
, };
630 _cleanup_free_
char *mid
= NULL
, *bid
= NULL
, *host
= NULL
, *uid
= NULL
, *user
= NULL
;
632 assert_se(specifier_machine_id('m', NULL
, NULL
, &mid
) >= 0 && mid
);
633 assert_se(specifier_boot_id('b', NULL
, NULL
, &bid
) >= 0 && bid
);
634 assert_se(host
= gethostname_malloc());
635 assert_se(user
= uid_to_name(getuid()));
636 assert_se(asprintf(&uid
, UID_FMT
, getuid()) >= 0);
638 #define expect(src, pattern, result) \
640 _cleanup_free_ char *t = NULL; \
641 _cleanup_free_ char \
642 *d1 = strdup(i.name), \
643 *d2 = strdup(i.path); \
644 assert_se(install_full_printf(&src, pattern, &t) >= 0 || !result); \
645 memzero(i.name, strlen(i.name)); \
646 memzero(i.path, strlen(i.path)); \
647 assert_se(d1 && d2); \
650 assert_se(streq(t, result)); \
651 } else assert_se(t == NULL); \
652 strcpy(i.name, d1); \
653 strcpy(i.path, d2); \
656 expect(i
, "%n", "name.service");
657 expect(i
, "%N", "name");
658 expect(i
, "%p", "name");
660 expect(i
, "%j", "name");
661 expect(i
, "%u", user
);
662 expect(i
, "%U", uid
);
664 expect(i
, "%m", mid
);
665 expect(i
, "%b", bid
);
666 expect(i
, "%H", host
);
668 expect(i2
, "%u", user
);
669 expect(i2
, "%U", uid
);
671 expect(i3
, "%n", "name@inst.service");
672 expect(i3
, "%N", "name@inst");
673 expect(i3
, "%p", "name");
674 expect(i3
, "%u", user
);
675 expect(i3
, "%U", uid
);
677 expect(i3
, "%m", mid
);
678 expect(i3
, "%b", bid
);
679 expect(i3
, "%H", host
);
681 expect(i4
, "%u", user
);
682 expect(i4
, "%U", uid
);
685 static uint64_t make_cap(int cap
) {
686 return ((uint64_t) 1ULL << (uint64_t) cap
);
689 static void test_config_parse_capability_set(void) {
690 /* int config_parse_capability_set(
692 const char *filename,
695 unsigned section_line,
702 uint64_t capability_bounding_set
= 0;
704 r
= config_parse_capability_set(NULL
, "fake", 1, "section", 1,
705 "CapabilityBoundingSet", 0, "CAP_NET_RAW",
706 &capability_bounding_set
, NULL
);
708 assert_se(capability_bounding_set
== make_cap(CAP_NET_RAW
));
710 r
= config_parse_capability_set(NULL
, "fake", 1, "section", 1,
711 "CapabilityBoundingSet", 0, "CAP_NET_ADMIN",
712 &capability_bounding_set
, NULL
);
714 assert_se(capability_bounding_set
== (make_cap(CAP_NET_RAW
) | make_cap(CAP_NET_ADMIN
)));
716 r
= config_parse_capability_set(NULL
, "fake", 1, "section", 1,
717 "CapabilityBoundingSet", 0, "~CAP_NET_ADMIN",
718 &capability_bounding_set
, NULL
);
720 assert_se(capability_bounding_set
== make_cap(CAP_NET_RAW
));
722 r
= config_parse_capability_set(NULL
, "fake", 1, "section", 1,
723 "CapabilityBoundingSet", 0, "",
724 &capability_bounding_set
, NULL
);
726 assert_se(capability_bounding_set
== UINT64_C(0));
728 r
= config_parse_capability_set(NULL
, "fake", 1, "section", 1,
729 "CapabilityBoundingSet", 0, "~",
730 &capability_bounding_set
, NULL
);
732 assert_se(cap_test_all(capability_bounding_set
));
734 capability_bounding_set
= 0;
735 r
= config_parse_capability_set(NULL
, "fake", 1, "section", 1,
736 "CapabilityBoundingSet", 0, " 'CAP_NET_RAW' WAT_CAP??? CAP_NET_ADMIN CAP'_trailing_garbage",
737 &capability_bounding_set
, NULL
);
739 assert_se(capability_bounding_set
== (make_cap(CAP_NET_RAW
) | make_cap(CAP_NET_ADMIN
)));
742 static void test_config_parse_rlimit(void) {
743 struct rlimit
* rl
[_RLIMIT_MAX
] = {};
745 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE
, "55", rl
, NULL
) >= 0);
746 assert_se(rl
[RLIMIT_NOFILE
]);
747 assert_se(rl
[RLIMIT_NOFILE
]->rlim_cur
== 55);
748 assert_se(rl
[RLIMIT_NOFILE
]->rlim_cur
== rl
[RLIMIT_NOFILE
]->rlim_max
);
750 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE
, "55:66", rl
, NULL
) >= 0);
751 assert_se(rl
[RLIMIT_NOFILE
]);
752 assert_se(rl
[RLIMIT_NOFILE
]->rlim_cur
== 55);
753 assert_se(rl
[RLIMIT_NOFILE
]->rlim_max
== 66);
755 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE
, "infinity", rl
, NULL
) >= 0);
756 assert_se(rl
[RLIMIT_NOFILE
]);
757 assert_se(rl
[RLIMIT_NOFILE
]->rlim_cur
== RLIM_INFINITY
);
758 assert_se(rl
[RLIMIT_NOFILE
]->rlim_cur
== rl
[RLIMIT_NOFILE
]->rlim_max
);
760 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE
, "infinity:infinity", rl
, NULL
) >= 0);
761 assert_se(rl
[RLIMIT_NOFILE
]);
762 assert_se(rl
[RLIMIT_NOFILE
]->rlim_cur
== RLIM_INFINITY
);
763 assert_se(rl
[RLIMIT_NOFILE
]->rlim_cur
== rl
[RLIMIT_NOFILE
]->rlim_max
);
765 rl
[RLIMIT_NOFILE
]->rlim_cur
= 10;
766 rl
[RLIMIT_NOFILE
]->rlim_max
= 20;
768 /* Invalid values don't change rl */
769 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE
, "10:20:30", rl
, NULL
) >= 0);
770 assert_se(rl
[RLIMIT_NOFILE
]);
771 assert_se(rl
[RLIMIT_NOFILE
]->rlim_cur
== 10);
772 assert_se(rl
[RLIMIT_NOFILE
]->rlim_max
== 20);
774 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE
, "wat:wat", rl
, NULL
) >= 0);
775 assert_se(rl
[RLIMIT_NOFILE
]);
776 assert_se(rl
[RLIMIT_NOFILE
]->rlim_cur
== 10);
777 assert_se(rl
[RLIMIT_NOFILE
]->rlim_max
== 20);
779 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE
, "66:wat", rl
, NULL
) >= 0);
780 assert_se(rl
[RLIMIT_NOFILE
]);
781 assert_se(rl
[RLIMIT_NOFILE
]->rlim_cur
== 10);
782 assert_se(rl
[RLIMIT_NOFILE
]->rlim_max
== 20);
784 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE
, "200:100", rl
, NULL
) >= 0);
785 assert_se(rl
[RLIMIT_NOFILE
]);
786 assert_se(rl
[RLIMIT_NOFILE
]->rlim_cur
== 10);
787 assert_se(rl
[RLIMIT_NOFILE
]->rlim_max
== 20);
789 rl
[RLIMIT_NOFILE
] = mfree(rl
[RLIMIT_NOFILE
]);
791 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU
, "56", rl
, NULL
) >= 0);
792 assert_se(rl
[RLIMIT_CPU
]);
793 assert_se(rl
[RLIMIT_CPU
]->rlim_cur
== 56);
794 assert_se(rl
[RLIMIT_CPU
]->rlim_cur
== rl
[RLIMIT_CPU
]->rlim_max
);
796 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU
, "57s", rl
, NULL
) >= 0);
797 assert_se(rl
[RLIMIT_CPU
]);
798 assert_se(rl
[RLIMIT_CPU
]->rlim_cur
== 57);
799 assert_se(rl
[RLIMIT_CPU
]->rlim_cur
== rl
[RLIMIT_CPU
]->rlim_max
);
801 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU
, "40s:1m", rl
, NULL
) >= 0);
802 assert_se(rl
[RLIMIT_CPU
]);
803 assert_se(rl
[RLIMIT_CPU
]->rlim_cur
== 40);
804 assert_se(rl
[RLIMIT_CPU
]->rlim_max
== 60);
806 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU
, "infinity", rl
, NULL
) >= 0);
807 assert_se(rl
[RLIMIT_CPU
]);
808 assert_se(rl
[RLIMIT_CPU
]->rlim_cur
== RLIM_INFINITY
);
809 assert_se(rl
[RLIMIT_CPU
]->rlim_cur
== rl
[RLIMIT_CPU
]->rlim_max
);
811 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU
, "1234ms", rl
, NULL
) >= 0);
812 assert_se(rl
[RLIMIT_CPU
]);
813 assert_se(rl
[RLIMIT_CPU
]->rlim_cur
== 2);
814 assert_se(rl
[RLIMIT_CPU
]->rlim_cur
== rl
[RLIMIT_CPU
]->rlim_max
);
816 rl
[RLIMIT_CPU
] = mfree(rl
[RLIMIT_CPU
]);
818 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME
, "58", rl
, NULL
) >= 0);
819 assert_se(rl
[RLIMIT_RTTIME
]);
820 assert_se(rl
[RLIMIT_RTTIME
]->rlim_cur
== 58);
821 assert_se(rl
[RLIMIT_RTTIME
]->rlim_cur
== rl
[RLIMIT_RTTIME
]->rlim_max
);
823 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME
, "58:60", rl
, NULL
) >= 0);
824 assert_se(rl
[RLIMIT_RTTIME
]);
825 assert_se(rl
[RLIMIT_RTTIME
]->rlim_cur
== 58);
826 assert_se(rl
[RLIMIT_RTTIME
]->rlim_max
== 60);
828 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME
, "59s", rl
, NULL
) >= 0);
829 assert_se(rl
[RLIMIT_RTTIME
]);
830 assert_se(rl
[RLIMIT_RTTIME
]->rlim_cur
== 59 * USEC_PER_SEC
);
831 assert_se(rl
[RLIMIT_RTTIME
]->rlim_cur
== rl
[RLIMIT_RTTIME
]->rlim_max
);
833 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME
, "59s:123s", rl
, NULL
) >= 0);
834 assert_se(rl
[RLIMIT_RTTIME
]);
835 assert_se(rl
[RLIMIT_RTTIME
]->rlim_cur
== 59 * USEC_PER_SEC
);
836 assert_se(rl
[RLIMIT_RTTIME
]->rlim_max
== 123 * USEC_PER_SEC
);
838 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME
, "infinity", rl
, NULL
) >= 0);
839 assert_se(rl
[RLIMIT_RTTIME
]);
840 assert_se(rl
[RLIMIT_RTTIME
]->rlim_cur
== RLIM_INFINITY
);
841 assert_se(rl
[RLIMIT_RTTIME
]->rlim_cur
== rl
[RLIMIT_RTTIME
]->rlim_max
);
843 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME
, "infinity:infinity", rl
, NULL
) >= 0);
844 assert_se(rl
[RLIMIT_RTTIME
]);
845 assert_se(rl
[RLIMIT_RTTIME
]->rlim_cur
== RLIM_INFINITY
);
846 assert_se(rl
[RLIMIT_RTTIME
]->rlim_cur
== rl
[RLIMIT_RTTIME
]->rlim_max
);
848 assert_se(config_parse_rlimit(NULL
, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME
, "2345ms", rl
, NULL
) >= 0);
849 assert_se(rl
[RLIMIT_RTTIME
]);
850 assert_se(rl
[RLIMIT_RTTIME
]->rlim_cur
== 2345 * USEC_PER_MSEC
);
851 assert_se(rl
[RLIMIT_RTTIME
]->rlim_cur
== rl
[RLIMIT_RTTIME
]->rlim_max
);
853 rl
[RLIMIT_RTTIME
] = mfree(rl
[RLIMIT_RTTIME
]);
856 static void test_config_parse_pass_environ(void) {
857 /* int config_parse_pass_environ(
859 const char *filename,
862 unsigned section_line,
869 _cleanup_strv_free_
char **passenv
= NULL
;
871 r
= config_parse_pass_environ(NULL
, "fake", 1, "section", 1,
872 "PassEnvironment", 0, "A B",
875 assert_se(strv_length(passenv
) == 2);
876 assert_se(streq(passenv
[0], "A"));
877 assert_se(streq(passenv
[1], "B"));
879 r
= config_parse_pass_environ(NULL
, "fake", 1, "section", 1,
880 "PassEnvironment", 0, "",
883 assert_se(strv_isempty(passenv
));
885 r
= config_parse_pass_environ(NULL
, "fake", 1, "section", 1,
886 "PassEnvironment", 0, "'invalid name' 'normal_name' A=1 \\",
889 assert_se(strv_length(passenv
) == 1);
890 assert_se(streq(passenv
[0], "normal_name"));
894 static void test_unit_dump_config_items(void) {
895 unit_dump_config_items(stdout
);
898 int main(int argc
, char *argv
[]) {
899 _cleanup_(rm_rf_physical_and_freep
) char *runtime_dir
= NULL
;
902 log_parse_environment();
905 r
= enter_cgroup_subroot();
906 if (r
== -ENOMEDIUM
) {
907 log_notice_errno(r
, "Skipping test: cgroupfs not available");
908 return EXIT_TEST_SKIP
;
911 assert_se(runtime_dir
= setup_fake_runtime_dir());
913 r
= test_unit_file_get_set();
914 test_config_parse_exec();
915 test_config_parse_log_extra_fields();
916 test_config_parse_capability_set();
917 test_config_parse_rlimit();
918 test_config_parse_pass_environ();
919 test_load_env_file_1();
920 test_load_env_file_2();
921 test_load_env_file_3();
922 test_load_env_file_4();
923 test_load_env_file_5();
924 TEST_REQ_RUNNING_SYSTEMD(test_install_printf());
925 test_unit_dump_config_items();