]>
git.proxmox.com Git - systemd.git/blob - src/test/test-unit-file.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2012 Lennart Poettering
7 Copyright 2013 Zbigniew Jędrzejewski-Szmek
9 systemd is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
14 systemd is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public License
20 along with systemd; If not, see <http://www.gnu.org/licenses/>.
31 #include "install-printf.h"
32 #include "specifier.h"
36 #include "load-fragment.h"
39 #include "test-helper.h"
41 static int test_unit_file_get_set(void) {
47 h
= hashmap_new(&string_hash_ops
);
50 r
= unit_file_get_list(UNIT_FILE_SYSTEM
, NULL
, h
);
52 if (r
== -EPERM
|| r
== -EACCES
) {
53 printf("Skipping test: unit_file_get_list: %s", strerror(-r
));
54 return EXIT_TEST_SKIP
;
57 log_full(r
== 0 ? LOG_INFO
: LOG_ERR
,
58 "unit_file_get_list: %s", strerror(-r
));
62 HASHMAP_FOREACH(p
, h
, i
)
63 printf("%s = %s\n", p
->path
, unit_file_state_to_string(p
->state
));
65 unit_file_list_free(h
);
70 static void check_execcommand(ExecCommand
*c
,
79 log_info("expect: \"%s\" [\"%s\" \"%s\" \"%s\"]",
80 path
, argv0
?: path
, argv1
, argv2
);
81 n
= strv_length(c
->argv
);
82 log_info("actual: \"%s\" [\"%s\" \"%s\" \"%s\"]",
83 c
->path
, c
->argv
[0], n
> 0 ? c
->argv
[1] : NULL
, n
> 1 ? c
->argv
[2] : NULL
);
84 assert_se(streq(c
->path
, path
));
85 assert_se(streq(c
->argv
[0], argv0
?: path
));
87 assert_se(streq_ptr(c
->argv
[1], argv1
));
89 assert_se(streq_ptr(c
->argv
[2], argv2
));
90 assert_se(c
->ignore
== ignore
);
93 static void test_config_parse_exec(void) {
94 /* int config_parse_exec(
98 unsigned section_line,
106 ExecCommand
*c
= NULL
, *c1
;
109 log_info("/* basic test */");
110 r
= config_parse_exec(NULL
, "fake", 1, "section", 1,
111 "LValue", 0, "/RValue r1",
114 check_execcommand(c
, "/RValue", "/RValue", "r1", NULL
, false);
116 r
= config_parse_exec(NULL
, "fake", 2, "section", 1,
117 "LValue", 0, "/RValue///slashes r1///",
120 log_info("/* test slashes */");
122 c1
= c
->command_next
;
123 check_execcommand(c1
, "/RValue/slashes", "/RValue///slashes", "r1///", NULL
, false);
125 log_info("/* trailing slash */");
126 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
127 "LValue", 0, "/RValue/ argv0 r1",
130 assert_se(c1
->command_next
== NULL
);
132 log_info("/* honour_argv0 */");
133 r
= config_parse_exec(NULL
, "fake", 3, "section", 1,
134 "LValue", 0, "@/RValue///slashes2 ///argv0 r1",
137 c1
= c1
->command_next
;
138 check_execcommand(c1
, "/RValue/slashes2", "///argv0", "r1", NULL
, false);
140 log_info("/* honour_argv0, no args */");
141 r
= config_parse_exec(NULL
, "fake", 3, "section", 1,
142 "LValue", 0, "@/RValue",
145 assert_se(c1
->command_next
== NULL
);
147 log_info("/* no command, check for bad memory access */");
148 r
= config_parse_exec(NULL
, "fake", 3, "section", 1,
152 assert_se(c1
->command_next
== NULL
);
154 log_info("/* ignore && honour_argv0 */");
155 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
156 "LValue", 0, "-@/RValue///slashes3 argv0a r1",
159 c1
= c1
->command_next
;
160 check_execcommand(c1
, "/RValue/slashes3", "argv0a", "r1", NULL
, true);
162 log_info("/* ignore && honour_argv0 */");
163 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
164 "LValue", 0, "@-/RValue///slashes4 argv0b r1",
167 c1
= c1
->command_next
;
168 check_execcommand(c1
, "/RValue/slashes4", "argv0b", "r1", NULL
, true);
170 log_info("/* ignore && ignore */");
171 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
172 "LValue", 0, "--/RValue argv0 r1",
175 assert_se(c1
->command_next
== NULL
);
177 log_info("/* ignore && ignore (2) */");
178 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
179 "LValue", 0, "-@-/RValue argv0 r1",
182 assert_se(c1
->command_next
== NULL
);
184 log_info("/* semicolon */");
185 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
187 "-@/RValue argv0 r1 ; "
191 c1
= c1
->command_next
;
192 check_execcommand(c1
, "/RValue", "argv0", "r1", NULL
, true);
194 c1
= c1
->command_next
;
195 check_execcommand(c1
, "/goo/goo", NULL
, "boo", NULL
, false);
197 log_info("/* trailing semicolon */");
198 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
200 "-@/RValue argv0 r1 ; ",
203 c1
= c1
->command_next
;
204 check_execcommand(c1
, "/RValue", "argv0", "r1", NULL
, true);
206 assert_se(c1
->command_next
== NULL
);
208 log_info("/* escaped semicolon */");
209 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
214 c1
= c1
->command_next
;
215 check_execcommand(c1
, "/bin/find", NULL
, ";", NULL
, false);
217 log_info("/* escaped semicolon with following arg */");
218 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
223 c1
= c1
->command_next
;
224 check_execcommand(c1
,
225 "/sbin/find", NULL
, ";", "x", false);
227 log_info("/* spaces in the filename */");
228 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
230 "\"/PATH WITH SPACES/daemon\" -1 -2",
233 c1
= c1
->command_next
;
234 check_execcommand(c1
,
235 "/PATH WITH SPACES/daemon", NULL
, "-1", "-2", false);
237 log_info("/* spaces in the filename, no args */");
238 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
240 "\"/PATH WITH SPACES/daemon -1 -2\"",
243 c1
= c1
->command_next
;
244 check_execcommand(c1
,
245 "/PATH WITH SPACES/daemon -1 -2", NULL
, NULL
, NULL
, false);
247 log_info("/* spaces in the filename, everything quoted */");
248 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
250 "\"/PATH WITH SPACES/daemon\" \"-1\" '-2'",
253 c1
= c1
->command_next
;
254 check_execcommand(c1
,
255 "/PATH WITH SPACES/daemon", NULL
, "-1", "-2", false);
257 log_info("/* escaped spaces in the filename */");
258 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
260 "\"/PATH\\sWITH\\sSPACES/daemon\" '-1 -2'",
263 c1
= c1
->command_next
;
264 check_execcommand(c1
,
265 "/PATH WITH SPACES/daemon", NULL
, "-1 -2", NULL
, false);
267 log_info("/* escaped spaces in the filename (2) */");
268 r
= config_parse_exec(NULL
, "fake", 5, "section", 1,
270 "\"/PATH\\x20WITH\\x20SPACES/daemon\" \"-1 -2\"",
273 c1
= c1
->command_next
;
274 check_execcommand(c1
,
275 "/PATH WITH SPACES/daemon", NULL
, "-1 -2", NULL
, false);
277 for (ccc
= "abfnrtv\\\'\"x"; *ccc
; ccc
++) {
278 /* \\x is an incomplete hexadecimal sequence, invalid because of the slash */
279 char path
[] = "/path\\X";
280 path
[sizeof(path
) - 2] = *ccc
;
282 log_info("/* invalid character: \\%c */", *ccc
);
283 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
287 assert_se(c1
->command_next
== NULL
);
290 log_info("/* valid character: \\s */");
291 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
292 "LValue", 0, "/path\\s",
295 c1
= c1
->command_next
;
296 check_execcommand(c1
, "/path ", NULL
, NULL
, NULL
, false);
298 log_info("/* trailing backslash: \\ */");
299 /* backslash is invalid */
300 r
= config_parse_exec(NULL
, "fake", 4, "section", 1,
301 "LValue", 0, "/path\\",
304 assert_se(c1
->command_next
== NULL
);
306 exec_command_free_list(c
);
324 "#SPAMD_ARGS=\"-d --socketpath=/var/lib/bulwark/spamd \\\n" \
325 "#--nouser-config \\\n" \
331 "HWMON_MODULES=\"coretemp f71882fg\"\n" \
333 "# For compatibility reasons\n" \
335 "MODULE_0=coretemp\n" \
342 static void test_load_env_file_1(void) {
343 _cleanup_strv_free_
char **data
= NULL
;
346 char name
[] = "/tmp/test-load-env-file.XXXXXX";
347 _cleanup_close_
int fd
;
349 fd
= mkostemp_safe(name
, O_RDWR
|O_CLOEXEC
);
351 assert_se(write(fd
, env_file_1
, sizeof(env_file_1
)) == sizeof(env_file_1
));
353 r
= load_env_file(NULL
, name
, NULL
, &data
);
355 assert_se(streq(data
[0], "a=a"));
356 assert_se(streq(data
[1], "b=bc"));
357 assert_se(streq(data
[2], "d=def"));
358 assert_se(streq(data
[3], "g=g "));
359 assert_se(streq(data
[4], "h=h"));
360 assert_se(streq(data
[5], "i=i"));
361 assert_se(data
[6] == NULL
);
365 static void test_load_env_file_2(void) {
366 _cleanup_strv_free_
char **data
= NULL
;
369 char name
[] = "/tmp/test-load-env-file.XXXXXX";
370 _cleanup_close_
int fd
;
372 fd
= mkostemp_safe(name
, O_RDWR
|O_CLOEXEC
);
374 assert_se(write(fd
, env_file_2
, sizeof(env_file_2
)) == sizeof(env_file_2
));
376 r
= load_env_file(NULL
, name
, NULL
, &data
);
378 assert_se(streq(data
[0], "a=a"));
379 assert_se(data
[1] == NULL
);
383 static void test_load_env_file_3(void) {
384 _cleanup_strv_free_
char **data
= NULL
;
387 char name
[] = "/tmp/test-load-env-file.XXXXXX";
388 _cleanup_close_
int fd
;
390 fd
= mkostemp_safe(name
, O_RDWR
|O_CLOEXEC
);
392 assert_se(write(fd
, env_file_3
, sizeof(env_file_3
)) == sizeof(env_file_3
));
394 r
= load_env_file(NULL
, name
, NULL
, &data
);
396 assert_se(data
== NULL
);
400 static void test_load_env_file_4(void) {
401 _cleanup_strv_free_
char **data
= NULL
;
402 char name
[] = "/tmp/test-load-env-file.XXXXXX";
403 _cleanup_close_
int fd
;
406 fd
= mkostemp_safe(name
, O_RDWR
|O_CLOEXEC
);
408 assert_se(write(fd
, env_file_4
, sizeof(env_file_4
)) == sizeof(env_file_4
));
410 r
= load_env_file(NULL
, name
, NULL
, &data
);
412 assert_se(streq(data
[0], "HWMON_MODULES=coretemp f71882fg"));
413 assert_se(streq(data
[1], "MODULE_0=coretemp"));
414 assert_se(streq(data
[2], "MODULE_1=f71882fg"));
415 assert_se(data
[3] == NULL
);
419 static void test_load_env_file_5(void) {
420 _cleanup_strv_free_
char **data
= NULL
;
423 char name
[] = "/tmp/test-load-env-file.XXXXXX";
424 _cleanup_close_
int fd
;
426 fd
= mkostemp_safe(name
, O_RDWR
|O_CLOEXEC
);
428 assert_se(write(fd
, env_file_5
, sizeof(env_file_5
)) == sizeof(env_file_5
));
430 r
= load_env_file(NULL
, name
, NULL
, &data
);
432 assert_se(streq(data
[0], "a="));
433 assert_se(streq(data
[1], "b="));
434 assert_se(data
[2] == NULL
);
438 static void test_install_printf(void) {
439 char name
[] = "name.service",
440 path
[] = "/run/systemd/system/name.service",
441 user
[] = "xxxx-no-such-user";
442 InstallInfo i
= {name
, path
, user
};
443 InstallInfo i2
= {name
, path
, NULL
};
444 char name3
[] = "name@inst.service",
445 path3
[] = "/run/systemd/system/name.service";
446 InstallInfo i3
= {name3
, path3
, user
};
447 InstallInfo i4
= {name3
, path3
, NULL
};
449 _cleanup_free_
char *mid
, *bid
, *host
;
451 assert_se(specifier_machine_id('m', NULL
, NULL
, &mid
) >= 0 && mid
);
452 assert_se(specifier_boot_id('b', NULL
, NULL
, &bid
) >= 0 && bid
);
453 assert_se((host
= gethostname_malloc()));
455 #define expect(src, pattern, result) \
457 _cleanup_free_ char *t = NULL; \
458 _cleanup_free_ char \
459 *d1 = strdup(i.name), \
460 *d2 = strdup(i.path), \
461 *d3 = strdup(i.user); \
462 assert_se(install_full_printf(&src, pattern, &t) >= 0 || !result); \
463 memzero(i.name, strlen(i.name)); \
464 memzero(i.path, strlen(i.path)); \
465 memzero(i.user, strlen(i.user)); \
466 assert_se(d1 && d2 && d3); \
469 assert_se(streq(t, result)); \
470 } else assert_se(t == NULL); \
471 strcpy(i.name, d1); \
472 strcpy(i.path, d2); \
473 strcpy(i.user, d3); \
476 assert_se(setenv("USER", "root", 1) == 0);
478 expect(i
, "%n", "name.service");
479 expect(i
, "%N", "name");
480 expect(i
, "%p", "name");
482 expect(i
, "%u", "xxxx-no-such-user");
484 DISABLE_WARNING_NONNULL
;
485 expect(i
, "%U", NULL
);
488 expect(i
, "%m", mid
);
489 expect(i
, "%b", bid
);
490 expect(i
, "%H", host
);
492 expect(i2
, "%u", "root");
493 expect(i2
, "%U", "0");
495 expect(i3
, "%n", "name@inst.service");
496 expect(i3
, "%N", "name@inst");
497 expect(i3
, "%p", "name");
498 expect(i3
, "%u", "xxxx-no-such-user");
500 DISABLE_WARNING_NONNULL
;
501 expect(i3
, "%U", NULL
);
504 expect(i3
, "%m", mid
);
505 expect(i3
, "%b", bid
);
506 expect(i3
, "%H", host
);
508 expect(i4
, "%u", "root");
509 expect(i4
, "%U", "0");
512 int main(int argc
, char *argv
[]) {
515 log_parse_environment();
518 r
= test_unit_file_get_set();
519 test_config_parse_exec();
520 test_load_env_file_1();
521 test_load_env_file_2();
522 test_load_env_file_3();
523 test_load_env_file_4();
524 test_load_env_file_5();
525 TEST_REQ_RUNNING_SYSTEMD(test_install_printf());