]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-unit-file.c
tree-wide: beautify remaining copyright statements
[thirdparty/systemd.git] / src / test / test-unit-file.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 Copyright © 2013 Zbigniew Jędrzejewski-Szmek
4 ***/
5
6 #include <fcntl.h>
7 #include <stddef.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <sys/capability.h>
11 #include <unistd.h>
12
13 #include "alloc-util.h"
14 #include "all-units.h"
15 #include "capability-util.h"
16 #include "conf-parser.h"
17 #include "fd-util.h"
18 #include "fileio.h"
19 #include "fs-util.h"
20 #include "hashmap.h"
21 #include "hostname-util.h"
22 #include "install-printf.h"
23 #include "install.h"
24 #include "load-fragment.h"
25 #include "macro.h"
26 #include "rm-rf.h"
27 #include "specifier.h"
28 #include "string-util.h"
29 #include "strv.h"
30 #include "test-helper.h"
31 #include "tests.h"
32 #include "user-util.h"
33 #include "util.h"
34
35 static int test_unit_file_get_set(void) {
36 int r;
37 Hashmap *h;
38 Iterator i;
39 UnitFileList *p;
40
41 h = hashmap_new(&string_hash_ops);
42 assert_se(h);
43
44 r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h, NULL, NULL);
45
46 if (IN_SET(r, -EPERM, -EACCES)) {
47 log_notice_errno(r, "Skipping test: unit_file_get_list: %m");
48 return EXIT_TEST_SKIP;
49 }
50
51 log_full_errno(r == 0 ? LOG_INFO : LOG_ERR, r,
52 "unit_file_get_list: %m");
53 if (r < 0)
54 return EXIT_FAILURE;
55
56 HASHMAP_FOREACH(p, h, i)
57 printf("%s = %s\n", p->path, unit_file_state_to_string(p->state));
58
59 unit_file_list_free(h);
60
61 return 0;
62 }
63
64 static void check_execcommand(ExecCommand *c,
65 const char* path,
66 const char* argv0,
67 const char* argv1,
68 const char* argv2,
69 bool ignore) {
70 size_t n;
71
72 assert_se(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));
80 if (n > 0)
81 assert_se(streq_ptr(c->argv[1], argv1));
82 if (n > 1)
83 assert_se(streq_ptr(c->argv[2], argv2));
84 assert_se(!!(c->flags & EXEC_COMMAND_IGNORE_FAILURE) == ignore);
85 }
86
87 static void test_config_parse_exec(void) {
88 /* int config_parse_exec(
89 const char *unit,
90 const char *filename,
91 unsigned line,
92 const char *section,
93 unsigned section_line,
94 const char *lvalue,
95 int ltype,
96 const char *rvalue,
97 void *data,
98 void *userdata) */
99 int r;
100
101 ExecCommand *c = NULL, *c1;
102 const char *ccc;
103 _cleanup_(manager_freep) Manager *m = NULL;
104 _cleanup_(unit_freep) Unit *u = NULL;
105
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");
109 return;
110 }
111
112 assert_se(r >= 0);
113 assert_se(manager_startup(m, NULL, NULL) >= 0);
114
115 assert_se(u = unit_new(m, sizeof(Service)));
116
117 log_info("/* basic test */");
118 r = config_parse_exec(NULL, "fake", 1, "section", 1,
119 "LValue", 0, "/RValue r1",
120 &c, u);
121 assert_se(r >= 0);
122 check_execcommand(c, "/RValue", "/RValue", "r1", NULL, false);
123
124 r = config_parse_exec(NULL, "fake", 2, "section", 1,
125 "LValue", 0, "/RValue///slashes r1///",
126 &c, u);
127
128 log_info("/* test slashes */");
129 assert_se(r >= 0);
130 c1 = c->command_next;
131 check_execcommand(c1, "/RValue/slashes", "/RValue///slashes", "r1///", NULL, false);
132
133 log_info("/* trailing slash */");
134 r = config_parse_exec(NULL, "fake", 4, "section", 1,
135 "LValue", 0, "/RValue/ argv0 r1",
136 &c, u);
137 assert_se(r == -ENOEXEC);
138 assert_se(c1->command_next == NULL);
139
140 log_info("/* honour_argv0 */");
141 r = config_parse_exec(NULL, "fake", 3, "section", 1,
142 "LValue", 0, "@/RValue///slashes2 ///argv0 r1",
143 &c, u);
144 assert_se(r >= 0);
145 c1 = c1->command_next;
146 check_execcommand(c1, "/RValue/slashes2", "///argv0", "r1", NULL, false);
147
148 log_info("/* honour_argv0, no args */");
149 r = config_parse_exec(NULL, "fake", 3, "section", 1,
150 "LValue", 0, "@/RValue",
151 &c, u);
152 assert_se(r == -ENOEXEC);
153 assert_se(c1->command_next == NULL);
154
155 log_info("/* no command, whitespace only, reset */");
156 r = config_parse_exec(NULL, "fake", 3, "section", 1,
157 "LValue", 0, " ",
158 &c, u);
159 assert_se(r == 0);
160 assert_se(c == NULL);
161
162 log_info("/* ignore && honour_argv0 */");
163 r = config_parse_exec(NULL, "fake", 4, "section", 1,
164 "LValue", 0, "-@/RValue///slashes3 argv0a r1",
165 &c, u);
166 assert_se(r >= 0);
167 c1 = c;
168 check_execcommand(c1, "/RValue/slashes3", "argv0a", "r1", NULL, true);
169
170 log_info("/* ignore && honour_argv0 */");
171 r = config_parse_exec(NULL, "fake", 4, "section", 1,
172 "LValue", 0, "@-/RValue///slashes4 argv0b r1",
173 &c, u);
174 assert_se(r >= 0);
175 c1 = c1->command_next;
176 check_execcommand(c1, "/RValue/slashes4", "argv0b", "r1", NULL, true);
177
178 log_info("/* ignore && ignore */");
179 r = config_parse_exec(NULL, "fake", 4, "section", 1,
180 "LValue", 0, "--/RValue argv0 r1",
181 &c, u);
182 assert_se(r == 0);
183 assert_se(c1->command_next == NULL);
184
185 log_info("/* ignore && ignore (2) */");
186 r = config_parse_exec(NULL, "fake", 4, "section", 1,
187 "LValue", 0, "-@-/RValue argv0 r1",
188 &c, u);
189 assert_se(r == 0);
190 assert_se(c1->command_next == NULL);
191
192 log_info("/* semicolon */");
193 r = config_parse_exec(NULL, "fake", 5, "section", 1,
194 "LValue", 0,
195 "-@/RValue argv0 r1 ; "
196 "/goo/goo boo",
197 &c, u);
198 assert_se(r >= 0);
199 c1 = c1->command_next;
200 check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
201
202 c1 = c1->command_next;
203 check_execcommand(c1, "/goo/goo", NULL, "boo", NULL, false);
204
205 log_info("/* two semicolons in a row */");
206 r = config_parse_exec(NULL, "fake", 5, "section", 1,
207 "LValue", 0,
208 "-@/RValue argv0 r1 ; ; "
209 "/goo/goo boo",
210 &c, u);
211 assert_se(r == -ENOEXEC);
212 c1 = c1->command_next;
213 check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
214
215 /* second command fails because the executable name is ";" */
216 assert_se(c1->command_next == NULL);
217
218 log_info("/* trailing semicolon */");
219 r = config_parse_exec(NULL, "fake", 5, "section", 1,
220 "LValue", 0,
221 "-@/RValue argv0 r1 ; ",
222 &c, u);
223 assert_se(r >= 0);
224 c1 = c1->command_next;
225 check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
226
227 assert_se(c1->command_next == NULL);
228
229 log_info("/* trailing semicolon, no whitespace */");
230 r = config_parse_exec(NULL, "fake", 5, "section", 1,
231 "LValue", 0,
232 "-@/RValue argv0 r1 ;",
233 &c, u);
234 assert_se(r >= 0);
235 c1 = c1->command_next;
236 check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
237
238 assert_se(c1->command_next == NULL);
239
240 log_info("/* trailing semicolon in single quotes */");
241 r = config_parse_exec(NULL, "fake", 5, "section", 1,
242 "LValue", 0,
243 "-@/RValue argv0 r1 ';'",
244 &c, u);
245 assert_se(r >= 0);
246 c1 = c1->command_next;
247 check_execcommand(c1, "/RValue", "argv0", "r1", ";", true);
248
249 log_info("/* escaped semicolon */");
250 r = config_parse_exec(NULL, "fake", 5, "section", 1,
251 "LValue", 0,
252 "/bin/find \\;",
253 &c, u);
254 assert_se(r >= 0);
255 c1 = c1->command_next;
256 check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
257
258 log_info("/* escaped semicolon with following arg */");
259 r = config_parse_exec(NULL, "fake", 5, "section", 1,
260 "LValue", 0,
261 "/sbin/find \\; /x",
262 &c, u);
263 assert_se(r >= 0);
264 c1 = c1->command_next;
265 check_execcommand(c1,
266 "/sbin/find", NULL, ";", "/x", false);
267
268 log_info("/* escaped semicolon as part of an expression */");
269 r = config_parse_exec(NULL, "fake", 5, "section", 1,
270 "LValue", 0,
271 "/sbin/find \\;x",
272 &c, u);
273 assert_se(r >= 0);
274 c1 = c1->command_next;
275 check_execcommand(c1,
276 "/sbin/find", NULL, "\\;x", NULL, false);
277
278 log_info("/* encoded semicolon */");
279 r = config_parse_exec(NULL, "fake", 5, "section", 1,
280 "LValue", 0,
281 "/bin/find \\073",
282 &c, u);
283 assert_se(r >= 0);
284 c1 = c1->command_next;
285 check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
286
287 log_info("/* quoted semicolon */");
288 r = config_parse_exec(NULL, "fake", 5, "section", 1,
289 "LValue", 0,
290 "/bin/find \";\"",
291 &c, u);
292 assert_se(r >= 0);
293 c1 = c1->command_next;
294 check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
295
296 log_info("/* quoted semicolon with following arg */");
297 r = config_parse_exec(NULL, "fake", 5, "section", 1,
298 "LValue", 0,
299 "/sbin/find \";\" /x",
300 &c, u);
301 assert_se(r >= 0);
302 c1 = c1->command_next;
303 check_execcommand(c1,
304 "/sbin/find", NULL, ";", "/x", false);
305
306 log_info("/* spaces in the filename */");
307 r = config_parse_exec(NULL, "fake", 5, "section", 1,
308 "LValue", 0,
309 "\"/PATH WITH SPACES/daemon\" -1 -2",
310 &c, u);
311 assert_se(r >= 0);
312 c1 = c1->command_next;
313 check_execcommand(c1,
314 "/PATH WITH SPACES/daemon", NULL, "-1", "-2", false);
315
316 log_info("/* spaces in the filename, no args */");
317 r = config_parse_exec(NULL, "fake", 5, "section", 1,
318 "LValue", 0,
319 "\"/PATH WITH SPACES/daemon -1 -2\"",
320 &c, u);
321 assert_se(r >= 0);
322 c1 = c1->command_next;
323 check_execcommand(c1,
324 "/PATH WITH SPACES/daemon -1 -2", NULL, NULL, NULL, false);
325
326 log_info("/* spaces in the filename, everything quoted */");
327 r = config_parse_exec(NULL, "fake", 5, "section", 1,
328 "LValue", 0,
329 "\"/PATH WITH SPACES/daemon\" \"-1\" '-2'",
330 &c, u);
331 assert_se(r >= 0);
332 c1 = c1->command_next;
333 check_execcommand(c1,
334 "/PATH WITH SPACES/daemon", NULL, "-1", "-2", false);
335
336 log_info("/* escaped spaces in the filename */");
337 r = config_parse_exec(NULL, "fake", 5, "section", 1,
338 "LValue", 0,
339 "\"/PATH\\sWITH\\sSPACES/daemon\" '-1 -2'",
340 &c, u);
341 assert_se(r >= 0);
342 c1 = c1->command_next;
343 check_execcommand(c1,
344 "/PATH WITH SPACES/daemon", NULL, "-1 -2", NULL, false);
345
346 log_info("/* escaped spaces in the filename (2) */");
347 r = config_parse_exec(NULL, "fake", 5, "section", 1,
348 "LValue", 0,
349 "\"/PATH\\x20WITH\\x20SPACES/daemon\" \"-1 -2\"",
350 &c, u);
351 assert_se(r >= 0);
352 c1 = c1->command_next;
353 check_execcommand(c1,
354 "/PATH WITH SPACES/daemon", NULL, "-1 -2", NULL, false);
355
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;
360
361 log_info("/* invalid character: \\%c */", *ccc);
362 r = config_parse_exec(NULL, "fake", 4, "section", 1,
363 "LValue", 0, path,
364 &c, u);
365 assert_se(r == -ENOEXEC);
366 assert_se(c1->command_next == NULL);
367 }
368
369 log_info("/* valid character: \\s */");
370 r = config_parse_exec(NULL, "fake", 4, "section", 1,
371 "LValue", 0, "/path\\s",
372 &c, u);
373 assert_se(r >= 0);
374 c1 = c1->command_next;
375 check_execcommand(c1, "/path ", NULL, NULL, NULL, false);
376
377 log_info("/* quoted backslashes */");
378 r = config_parse_exec(NULL, "fake", 5, "section", 1,
379 "LValue", 0,
380 "/bin/grep '\\w+\\K'",
381 &c, u);
382 assert_se(r >= 0);
383 c1 = c1->command_next;
384 check_execcommand(c1, "/bin/grep", NULL, "\\w+\\K", NULL, false);
385
386 log_info("/* trailing backslash: \\ */");
387 /* backslash is invalid */
388 r = config_parse_exec(NULL, "fake", 4, "section", 1,
389 "LValue", 0, "/path\\",
390 &c, u);
391 assert_se(r == -ENOEXEC);
392 assert_se(c1->command_next == NULL);
393
394 log_info("/* missing ending ' */");
395 r = config_parse_exec(NULL, "fake", 4, "section", 1,
396 "LValue", 0, "/path 'foo",
397 &c, u);
398 assert_se(r == -ENOEXEC);
399 assert_se(c1->command_next == NULL);
400
401 log_info("/* missing ending ' with trailing backslash */");
402 r = config_parse_exec(NULL, "fake", 4, "section", 1,
403 "LValue", 0, "/path 'foo\\",
404 &c, u);
405 assert_se(r == -ENOEXEC);
406 assert_se(c1->command_next == NULL);
407
408 log_info("/* invalid space between modifiers */");
409 r = config_parse_exec(NULL, "fake", 4, "section", 1,
410 "LValue", 0, "- /path",
411 &c, u);
412 assert_se(r == 0);
413 assert_se(c1->command_next == NULL);
414
415 log_info("/* only modifiers, no path */");
416 r = config_parse_exec(NULL, "fake", 4, "section", 1,
417 "LValue", 0, "-",
418 &c, u);
419 assert_se(r == 0);
420 assert_se(c1->command_next == NULL);
421
422 log_info("/* empty argument, reset */");
423 r = config_parse_exec(NULL, "fake", 4, "section", 1,
424 "LValue", 0, "",
425 &c, u);
426 assert_se(r == 0);
427 assert_se(c == NULL);
428
429 exec_command_free_list(c);
430 }
431
432 static void test_config_parse_log_extra_fields(void) {
433 /* int config_parse_log_extra_fields(
434 const char *unit,
435 const char *filename,
436 unsigned line,
437 const char *section,
438 unsigned section_line,
439 const char *lvalue,
440 int ltype,
441 const char *rvalue,
442 void *data,
443 void *userdata) */
444
445 int r;
446
447 _cleanup_(manager_freep) Manager *m = NULL;
448 _cleanup_(unit_freep) Unit *u = NULL;
449 ExecContext c = {};
450
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");
454 return;
455 }
456
457 assert_se(r >= 0);
458 assert_se(manager_startup(m, NULL, NULL) >= 0);
459
460 assert_se(u = unit_new(m, sizeof(Service)));
461
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 ' ' \"",
465 &c, u);
466 assert_se(r >= 0);
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));
470
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 ' '",
474 &c, u);
475 assert_se(r >= 0);
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));
481
482 exec_context_dump(&c, stdout, " --> ");
483
484 log_info("/* %s – reset */", __func__);
485 r = config_parse_log_extra_fields(NULL, "fake", 1, "section", 1,
486 "LValue", 0, "",
487 &c, u);
488 assert_se(r >= 0);
489 assert_se(c.n_log_extra_fields == 0);
490
491 exec_context_free_log_extra_fields(&c);
492
493 log_info("/* %s – bye */", __func__);
494 }
495
496 #define env_file_1 \
497 "a=a\n" \
498 "b=b\\\n" \
499 "c\n" \
500 "d=d\\\n" \
501 "e\\\n" \
502 "f\n" \
503 "g=g\\ \n" \
504 "h=h\n" \
505 "i=i\\"
506
507 #define env_file_2 \
508 "a=a\\\n"
509
510 #define env_file_3 \
511 "#SPAMD_ARGS=\"-d --socketpath=/var/lib/bulwark/spamd \\\n" \
512 "#--nouser-config \\\n" \
513 "normal=line"
514
515 #define env_file_4 \
516 "# Generated\n" \
517 "\n" \
518 "HWMON_MODULES=\"coretemp f71882fg\"\n" \
519 "\n" \
520 "# For compatibility reasons\n" \
521 "\n" \
522 "MODULE_0=coretemp\n" \
523 "MODULE_1=f71882fg"
524
525 #define env_file_5 \
526 "a=\n" \
527 "b="
528
529 static void test_load_env_file_1(void) {
530 _cleanup_strv_free_ char **data = NULL;
531 int r;
532
533 _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
534 _cleanup_close_ int fd;
535
536 fd = mkostemp_safe(name);
537 assert_se(fd >= 0);
538 assert_se(write(fd, env_file_1, sizeof(env_file_1)) == sizeof(env_file_1));
539
540 r = load_env_file(NULL, name, NULL, &data);
541 assert_se(r == 0);
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);
549 }
550
551 static void test_load_env_file_2(void) {
552 _cleanup_strv_free_ char **data = NULL;
553 int r;
554
555 _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
556 _cleanup_close_ int fd;
557
558 fd = mkostemp_safe(name);
559 assert_se(fd >= 0);
560 assert_se(write(fd, env_file_2, sizeof(env_file_2)) == sizeof(env_file_2));
561
562 r = load_env_file(NULL, name, NULL, &data);
563 assert_se(r == 0);
564 assert_se(streq(data[0], "a=a"));
565 assert_se(data[1] == NULL);
566 }
567
568 static void test_load_env_file_3(void) {
569 _cleanup_strv_free_ char **data = NULL;
570 int r;
571
572 _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
573 _cleanup_close_ int fd;
574
575 fd = mkostemp_safe(name);
576 assert_se(fd >= 0);
577 assert_se(write(fd, env_file_3, sizeof(env_file_3)) == sizeof(env_file_3));
578
579 r = load_env_file(NULL, name, NULL, &data);
580 assert_se(r == 0);
581 assert_se(data == NULL);
582 }
583
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;
588 int r;
589
590 fd = mkostemp_safe(name);
591 assert_se(fd >= 0);
592 assert_se(write(fd, env_file_4, sizeof(env_file_4)) == sizeof(env_file_4));
593
594 r = load_env_file(NULL, name, NULL, &data);
595 assert_se(r == 0);
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);
600 }
601
602 static void test_load_env_file_5(void) {
603 _cleanup_strv_free_ char **data = NULL;
604 int r;
605
606 _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
607 _cleanup_close_ int fd;
608
609 fd = mkostemp_safe(name);
610 assert_se(fd >= 0);
611 assert_se(write(fd, env_file_5, sizeof(env_file_5)) == sizeof(env_file_5));
612
613 r = load_env_file(NULL, name, NULL, &data);
614 assert_se(r == 0);
615 assert_se(streq(data[0], "a="));
616 assert_se(streq(data[1], "b="));
617 assert_se(data[2] == NULL);
618 }
619
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, };
629
630 _cleanup_free_ char *mid = NULL, *bid = NULL, *host = NULL, *uid = NULL, *user = NULL;
631
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);
637
638 #define expect(src, pattern, result) \
639 do { \
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); \
648 if (result) { \
649 printf("%s\n", t); \
650 assert_se(streq(t, result)); \
651 } else assert_se(t == NULL); \
652 strcpy(i.name, d1); \
653 strcpy(i.path, d2); \
654 } while (false)
655
656 expect(i, "%n", "name.service");
657 expect(i, "%N", "name");
658 expect(i, "%p", "name");
659 expect(i, "%i", "");
660 expect(i, "%j", "name");
661 expect(i, "%u", user);
662 expect(i, "%U", uid);
663
664 expect(i, "%m", mid);
665 expect(i, "%b", bid);
666 expect(i, "%H", host);
667
668 expect(i2, "%u", user);
669 expect(i2, "%U", uid);
670
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);
676
677 expect(i3, "%m", mid);
678 expect(i3, "%b", bid);
679 expect(i3, "%H", host);
680
681 expect(i4, "%u", user);
682 expect(i4, "%U", uid);
683 }
684
685 static uint64_t make_cap(int cap) {
686 return ((uint64_t) 1ULL << (uint64_t) cap);
687 }
688
689 static void test_config_parse_capability_set(void) {
690 /* int config_parse_capability_set(
691 const char *unit,
692 const char *filename,
693 unsigned line,
694 const char *section,
695 unsigned section_line,
696 const char *lvalue,
697 int ltype,
698 const char *rvalue,
699 void *data,
700 void *userdata) */
701 int r;
702 uint64_t capability_bounding_set = 0;
703
704 r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
705 "CapabilityBoundingSet", 0, "CAP_NET_RAW",
706 &capability_bounding_set, NULL);
707 assert_se(r >= 0);
708 assert_se(capability_bounding_set == make_cap(CAP_NET_RAW));
709
710 r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
711 "CapabilityBoundingSet", 0, "CAP_NET_ADMIN",
712 &capability_bounding_set, NULL);
713 assert_se(r >= 0);
714 assert_se(capability_bounding_set == (make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN)));
715
716 r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
717 "CapabilityBoundingSet", 0, "~CAP_NET_ADMIN",
718 &capability_bounding_set, NULL);
719 assert_se(r >= 0);
720 assert_se(capability_bounding_set == make_cap(CAP_NET_RAW));
721
722 r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
723 "CapabilityBoundingSet", 0, "",
724 &capability_bounding_set, NULL);
725 assert_se(r >= 0);
726 assert_se(capability_bounding_set == UINT64_C(0));
727
728 r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
729 "CapabilityBoundingSet", 0, "~",
730 &capability_bounding_set, NULL);
731 assert_se(r >= 0);
732 assert_se(cap_test_all(capability_bounding_set));
733
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);
738 assert_se(r >= 0);
739 assert_se(capability_bounding_set == (make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN)));
740 }
741
742 static void test_config_parse_rlimit(void) {
743 struct rlimit * rl[_RLIMIT_MAX] = {};
744
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);
749
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);
754
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);
759
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);
764
765 rl[RLIMIT_NOFILE]->rlim_cur = 10;
766 rl[RLIMIT_NOFILE]->rlim_max = 20;
767
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);
773
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);
778
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);
783
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);
788
789 rl[RLIMIT_NOFILE] = mfree(rl[RLIMIT_NOFILE]);
790
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);
795
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);
800
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);
805
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);
810
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);
815
816 rl[RLIMIT_CPU] = mfree(rl[RLIMIT_CPU]);
817
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);
822
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);
827
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);
832
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);
837
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);
842
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);
847
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);
852
853 rl[RLIMIT_RTTIME] = mfree(rl[RLIMIT_RTTIME]);
854 }
855
856 static void test_config_parse_pass_environ(void) {
857 /* int config_parse_pass_environ(
858 const char *unit,
859 const char *filename,
860 unsigned line,
861 const char *section,
862 unsigned section_line,
863 const char *lvalue,
864 int ltype,
865 const char *rvalue,
866 void *data,
867 void *userdata) */
868 int r;
869 _cleanup_strv_free_ char **passenv = NULL;
870
871 r = config_parse_pass_environ(NULL, "fake", 1, "section", 1,
872 "PassEnvironment", 0, "A B",
873 &passenv, NULL);
874 assert_se(r >= 0);
875 assert_se(strv_length(passenv) == 2);
876 assert_se(streq(passenv[0], "A"));
877 assert_se(streq(passenv[1], "B"));
878
879 r = config_parse_pass_environ(NULL, "fake", 1, "section", 1,
880 "PassEnvironment", 0, "",
881 &passenv, NULL);
882 assert_se(r >= 0);
883 assert_se(strv_isempty(passenv));
884
885 r = config_parse_pass_environ(NULL, "fake", 1, "section", 1,
886 "PassEnvironment", 0, "'invalid name' 'normal_name' A=1 \\",
887 &passenv, NULL);
888 assert_se(r >= 0);
889 assert_se(strv_length(passenv) == 1);
890 assert_se(streq(passenv[0], "normal_name"));
891
892 }
893
894 static void test_unit_dump_config_items(void) {
895 unit_dump_config_items(stdout);
896 }
897
898 int main(int argc, char *argv[]) {
899 _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
900 int r;
901
902 log_parse_environment();
903 log_open();
904
905 r = enter_cgroup_subroot();
906 if (r == -ENOMEDIUM) {
907 log_notice_errno(r, "Skipping test: cgroupfs not available");
908 return EXIT_TEST_SKIP;
909 }
910
911 assert_se(runtime_dir = setup_fake_runtime_dir());
912
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();
926
927 return r;
928 }