]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-unit-file.c
Merge pull request #1736 from ronnychevalier/rc/test_execute_more_tests2
[thirdparty/systemd.git] / src / test / test-unit-file.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2012 Lennart Poettering
7 Copyright 2013 Zbigniew Jędrzejewski-Szmek
8
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.
13
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.
18
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/>.
21 ***/
22
23 #include <fcntl.h>
24 #include <stddef.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <sys/capability.h>
28 #include <unistd.h>
29
30 #include "alloc-util.h"
31 #include "fd-util.h"
32 #include "fileio.h"
33 #include "hashmap.h"
34 #include "hostname-util.h"
35 #include "install-printf.h"
36 #include "install.h"
37 #include "load-fragment.h"
38 #include "macro.h"
39 #include "specifier.h"
40 #include "string-util.h"
41 #include "strv.h"
42 #include "test-helper.h"
43 #include "util.h"
44
45 static int test_unit_file_get_set(void) {
46 int r;
47 Hashmap *h;
48 Iterator i;
49 UnitFileList *p;
50
51 h = hashmap_new(&string_hash_ops);
52 assert_se(h);
53
54 r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h);
55
56 if (r == -EPERM || r == -EACCES) {
57 printf("Skipping test: unit_file_get_list: %s", strerror(-r));
58 return EXIT_TEST_SKIP;
59 }
60
61 log_full(r == 0 ? LOG_INFO : LOG_ERR,
62 "unit_file_get_list: %s", strerror(-r));
63 if (r < 0)
64 return EXIT_FAILURE;
65
66 HASHMAP_FOREACH(p, h, i)
67 printf("%s = %s\n", p->path, unit_file_state_to_string(p->state));
68
69 unit_file_list_free(h);
70
71 return 0;
72 }
73
74 static void check_execcommand(ExecCommand *c,
75 const char* path,
76 const char* argv0,
77 const char* argv1,
78 const char* argv2,
79 bool ignore) {
80 size_t n;
81
82 assert_se(c);
83 log_info("expect: \"%s\" [\"%s\" \"%s\" \"%s\"]",
84 path, argv0 ?: path, argv1, argv2);
85 n = strv_length(c->argv);
86 log_info("actual: \"%s\" [\"%s\" \"%s\" \"%s\"]",
87 c->path, c->argv[0], n > 0 ? c->argv[1] : NULL, n > 1 ? c->argv[2] : NULL);
88 assert_se(streq(c->path, path));
89 assert_se(streq(c->argv[0], argv0 ?: path));
90 if (n > 0)
91 assert_se(streq_ptr(c->argv[1], argv1));
92 if (n > 1)
93 assert_se(streq_ptr(c->argv[2], argv2));
94 assert_se(c->ignore == ignore);
95 }
96
97 static void test_config_parse_exec(void) {
98 /* int config_parse_exec(
99 const char *unit,
100 const char *filename,
101 unsigned line,
102 const char *section,
103 unsigned section_line,
104 const char *lvalue,
105 int ltype,
106 const char *rvalue,
107 void *data,
108 void *userdata) */
109 int r;
110
111 ExecCommand *c = NULL, *c1;
112 const char *ccc;
113
114 log_info("/* basic test */");
115 r = config_parse_exec(NULL, "fake", 1, "section", 1,
116 "LValue", 0, "/RValue r1",
117 &c, NULL);
118 assert_se(r >= 0);
119 check_execcommand(c, "/RValue", "/RValue", "r1", NULL, false);
120
121 r = config_parse_exec(NULL, "fake", 2, "section", 1,
122 "LValue", 0, "/RValue///slashes r1///",
123 &c, NULL);
124
125 log_info("/* test slashes */");
126 assert_se(r >= 0);
127 c1 = c->command_next;
128 check_execcommand(c1, "/RValue/slashes", "/RValue///slashes", "r1///", NULL, false);
129
130 log_info("/* trailing slash */");
131 r = config_parse_exec(NULL, "fake", 4, "section", 1,
132 "LValue", 0, "/RValue/ argv0 r1",
133 &c, NULL);
134 assert_se(r == 0);
135 assert_se(c1->command_next == NULL);
136
137 log_info("/* honour_argv0 */");
138 r = config_parse_exec(NULL, "fake", 3, "section", 1,
139 "LValue", 0, "@/RValue///slashes2 ///argv0 r1",
140 &c, NULL);
141 assert_se(r >= 0);
142 c1 = c1->command_next;
143 check_execcommand(c1, "/RValue/slashes2", "///argv0", "r1", NULL, false);
144
145 log_info("/* honour_argv0, no args */");
146 r = config_parse_exec(NULL, "fake", 3, "section", 1,
147 "LValue", 0, "@/RValue",
148 &c, NULL);
149 assert_se(r == 0);
150 assert_se(c1->command_next == NULL);
151
152 log_info("/* no command, whitespace only, reset */");
153 r = config_parse_exec(NULL, "fake", 3, "section", 1,
154 "LValue", 0, " ",
155 &c, NULL);
156 assert_se(r == 0);
157 assert_se(c == NULL);
158
159 log_info("/* ignore && honour_argv0 */");
160 r = config_parse_exec(NULL, "fake", 4, "section", 1,
161 "LValue", 0, "-@/RValue///slashes3 argv0a r1",
162 &c, NULL);
163 assert_se(r >= 0);
164 c1 = c;
165 check_execcommand(c1, "/RValue/slashes3", "argv0a", "r1", NULL, true);
166
167 log_info("/* ignore && honour_argv0 */");
168 r = config_parse_exec(NULL, "fake", 4, "section", 1,
169 "LValue", 0, "@-/RValue///slashes4 argv0b r1",
170 &c, NULL);
171 assert_se(r >= 0);
172 c1 = c1->command_next;
173 check_execcommand(c1, "/RValue/slashes4", "argv0b", "r1", NULL, true);
174
175 log_info("/* ignore && ignore */");
176 r = config_parse_exec(NULL, "fake", 4, "section", 1,
177 "LValue", 0, "--/RValue argv0 r1",
178 &c, NULL);
179 assert_se(r == 0);
180 assert_se(c1->command_next == NULL);
181
182 log_info("/* ignore && ignore (2) */");
183 r = config_parse_exec(NULL, "fake", 4, "section", 1,
184 "LValue", 0, "-@-/RValue argv0 r1",
185 &c, NULL);
186 assert_se(r == 0);
187 assert_se(c1->command_next == NULL);
188
189 log_info("/* semicolon */");
190 r = config_parse_exec(NULL, "fake", 5, "section", 1,
191 "LValue", 0,
192 "-@/RValue argv0 r1 ; "
193 "/goo/goo boo",
194 &c, NULL);
195 assert_se(r >= 0);
196 c1 = c1->command_next;
197 check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
198
199 c1 = c1->command_next;
200 check_execcommand(c1, "/goo/goo", NULL, "boo", NULL, false);
201
202 log_info("/* two semicolons in a row */");
203 r = config_parse_exec(NULL, "fake", 5, "section", 1,
204 "LValue", 0,
205 "-@/RValue argv0 r1 ; ; "
206 "/goo/goo boo",
207 &c, NULL);
208 assert_se(r >= 0);
209 c1 = c1->command_next;
210 check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
211
212 /* second command fails because the executable name is ";" */
213 assert_se(c1->command_next == NULL);
214
215 log_info("/* trailing semicolon */");
216 r = config_parse_exec(NULL, "fake", 5, "section", 1,
217 "LValue", 0,
218 "-@/RValue argv0 r1 ; ",
219 &c, NULL);
220 assert_se(r >= 0);
221 c1 = c1->command_next;
222 check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
223
224 assert_se(c1->command_next == NULL);
225
226 log_info("/* trailing semicolon, no whitespace */");
227 r = config_parse_exec(NULL, "fake", 5, "section", 1,
228 "LValue", 0,
229 "-@/RValue argv0 r1 ;",
230 &c, NULL);
231 assert_se(r >= 0);
232 c1 = c1->command_next;
233 check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
234
235 assert_se(c1->command_next == NULL);
236
237 log_info("/* trailing semicolon in single quotes */");
238 r = config_parse_exec(NULL, "fake", 5, "section", 1,
239 "LValue", 0,
240 "-@/RValue argv0 r1 ';'",
241 &c, NULL);
242 assert_se(r >= 0);
243 c1 = c1->command_next;
244 check_execcommand(c1, "/RValue", "argv0", "r1", ";", true);
245
246 log_info("/* escaped semicolon */");
247 r = config_parse_exec(NULL, "fake", 5, "section", 1,
248 "LValue", 0,
249 "/bin/find \\;",
250 &c, NULL);
251 assert_se(r >= 0);
252 c1 = c1->command_next;
253 check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
254
255 log_info("/* escaped semicolon with following arg */");
256 r = config_parse_exec(NULL, "fake", 5, "section", 1,
257 "LValue", 0,
258 "/sbin/find \\; /x",
259 &c, NULL);
260 assert_se(r >= 0);
261 c1 = c1->command_next;
262 check_execcommand(c1,
263 "/sbin/find", NULL, ";", "/x", false);
264
265 log_info("/* escaped semicolon as part of an expression */");
266 r = config_parse_exec(NULL, "fake", 5, "section", 1,
267 "LValue", 0,
268 "/sbin/find \\;x",
269 &c, NULL);
270 assert_se(r >= 0);
271 c1 = c1->command_next;
272 check_execcommand(c1,
273 "/sbin/find", NULL, "\\;x", NULL, false);
274
275 log_info("/* encoded semicolon */");
276 r = config_parse_exec(NULL, "fake", 5, "section", 1,
277 "LValue", 0,
278 "/bin/find \\073",
279 &c, NULL);
280 assert_se(r >= 0);
281 c1 = c1->command_next;
282 check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
283
284 log_info("/* quoted semicolon */");
285 r = config_parse_exec(NULL, "fake", 5, "section", 1,
286 "LValue", 0,
287 "/bin/find \";\"",
288 &c, NULL);
289 assert_se(r >= 0);
290 c1 = c1->command_next;
291 check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
292
293 log_info("/* quoted semicolon with following arg */");
294 r = config_parse_exec(NULL, "fake", 5, "section", 1,
295 "LValue", 0,
296 "/sbin/find \";\" /x",
297 &c, NULL);
298 assert_se(r >= 0);
299 c1 = c1->command_next;
300 check_execcommand(c1,
301 "/sbin/find", NULL, ";", "/x", false);
302
303 log_info("/* spaces in the filename */");
304 r = config_parse_exec(NULL, "fake", 5, "section", 1,
305 "LValue", 0,
306 "\"/PATH WITH SPACES/daemon\" -1 -2",
307 &c, NULL);
308 assert_se(r >= 0);
309 c1 = c1->command_next;
310 check_execcommand(c1,
311 "/PATH WITH SPACES/daemon", NULL, "-1", "-2", false);
312
313 log_info("/* spaces in the filename, no args */");
314 r = config_parse_exec(NULL, "fake", 5, "section", 1,
315 "LValue", 0,
316 "\"/PATH WITH SPACES/daemon -1 -2\"",
317 &c, NULL);
318 assert_se(r >= 0);
319 c1 = c1->command_next;
320 check_execcommand(c1,
321 "/PATH WITH SPACES/daemon -1 -2", NULL, NULL, NULL, false);
322
323 log_info("/* spaces in the filename, everything quoted */");
324 r = config_parse_exec(NULL, "fake", 5, "section", 1,
325 "LValue", 0,
326 "\"/PATH WITH SPACES/daemon\" \"-1\" '-2'",
327 &c, NULL);
328 assert_se(r >= 0);
329 c1 = c1->command_next;
330 check_execcommand(c1,
331 "/PATH WITH SPACES/daemon", NULL, "-1", "-2", false);
332
333 log_info("/* escaped spaces in the filename */");
334 r = config_parse_exec(NULL, "fake", 5, "section", 1,
335 "LValue", 0,
336 "\"/PATH\\sWITH\\sSPACES/daemon\" '-1 -2'",
337 &c, NULL);
338 assert_se(r >= 0);
339 c1 = c1->command_next;
340 check_execcommand(c1,
341 "/PATH WITH SPACES/daemon", NULL, "-1 -2", NULL, false);
342
343 log_info("/* escaped spaces in the filename (2) */");
344 r = config_parse_exec(NULL, "fake", 5, "section", 1,
345 "LValue", 0,
346 "\"/PATH\\x20WITH\\x20SPACES/daemon\" \"-1 -2\"",
347 &c, NULL);
348 assert_se(r >= 0);
349 c1 = c1->command_next;
350 check_execcommand(c1,
351 "/PATH WITH SPACES/daemon", NULL, "-1 -2", NULL, false);
352
353 for (ccc = "abfnrtv\\\'\"x"; *ccc; ccc++) {
354 /* \\x is an incomplete hexadecimal sequence, invalid because of the slash */
355 char path[] = "/path\\X";
356 path[sizeof(path) - 2] = *ccc;
357
358 log_info("/* invalid character: \\%c */", *ccc);
359 r = config_parse_exec(NULL, "fake", 4, "section", 1,
360 "LValue", 0, path,
361 &c, NULL);
362 assert_se(r == 0);
363 assert_se(c1->command_next == NULL);
364 }
365
366 log_info("/* valid character: \\s */");
367 r = config_parse_exec(NULL, "fake", 4, "section", 1,
368 "LValue", 0, "/path\\s",
369 &c, NULL);
370 assert_se(r >= 0);
371 c1 = c1->command_next;
372 check_execcommand(c1, "/path ", NULL, NULL, NULL, false);
373
374 log_info("/* quoted backslashes */");
375 r = config_parse_exec(NULL, "fake", 5, "section", 1,
376 "LValue", 0,
377 "/bin/grep '\\w+\\K'",
378 &c, NULL);
379 assert_se(r >= 0);
380 c1 = c1->command_next;
381 check_execcommand(c1, "/bin/grep", NULL, "\\w+\\K", NULL, false);
382
383
384 log_info("/* trailing backslash: \\ */");
385 /* backslash is invalid */
386 r = config_parse_exec(NULL, "fake", 4, "section", 1,
387 "LValue", 0, "/path\\",
388 &c, NULL);
389 assert_se(r == 0);
390 assert_se(c1->command_next == NULL);
391
392 log_info("/* missing ending ' */");
393 r = config_parse_exec(NULL, "fake", 4, "section", 1,
394 "LValue", 0, "/path 'foo",
395 &c, NULL);
396 assert_se(r == 0);
397 assert_se(c1->command_next == NULL);
398
399 log_info("/* missing ending ' with trailing backslash */");
400 r = config_parse_exec(NULL, "fake", 4, "section", 1,
401 "LValue", 0, "/path 'foo\\",
402 &c, NULL);
403 assert_se(r == 0);
404 assert_se(c1->command_next == NULL);
405
406 log_info("/* invalid space between modifiers */");
407 r = config_parse_exec(NULL, "fake", 4, "section", 1,
408 "LValue", 0, "- /path",
409 &c, NULL);
410 assert_se(r == 0);
411 assert_se(c1->command_next == NULL);
412
413 log_info("/* only modifiers, no path */");
414 r = config_parse_exec(NULL, "fake", 4, "section", 1,
415 "LValue", 0, "-",
416 &c, NULL);
417 assert_se(r == 0);
418 assert_se(c1->command_next == NULL);
419
420 log_info("/* empty argument, reset */");
421 r = config_parse_exec(NULL, "fake", 4, "section", 1,
422 "LValue", 0, "",
423 &c, NULL);
424 assert_se(r == 0);
425 assert_se(c == NULL);
426
427 exec_command_free_list(c);
428 }
429
430 #define env_file_1 \
431 "a=a\n" \
432 "b=b\\\n" \
433 "c\n" \
434 "d=d\\\n" \
435 "e\\\n" \
436 "f\n" \
437 "g=g\\ \n" \
438 "h=h\n" \
439 "i=i\\"
440
441 #define env_file_2 \
442 "a=a\\\n"
443
444 #define env_file_3 \
445 "#SPAMD_ARGS=\"-d --socketpath=/var/lib/bulwark/spamd \\\n" \
446 "#--nouser-config \\\n" \
447 "normal=line"
448
449 #define env_file_4 \
450 "# Generated\n" \
451 "\n" \
452 "HWMON_MODULES=\"coretemp f71882fg\"\n" \
453 "\n" \
454 "# For compatibility reasons\n" \
455 "\n" \
456 "MODULE_0=coretemp\n" \
457 "MODULE_1=f71882fg"
458
459 #define env_file_5 \
460 "a=\n" \
461 "b="
462
463 static void test_load_env_file_1(void) {
464 _cleanup_strv_free_ char **data = NULL;
465 int r;
466
467 char name[] = "/tmp/test-load-env-file.XXXXXX";
468 _cleanup_close_ int fd;
469
470 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
471 assert_se(fd >= 0);
472 assert_se(write(fd, env_file_1, sizeof(env_file_1)) == sizeof(env_file_1));
473
474 r = load_env_file(NULL, name, NULL, &data);
475 assert_se(r == 0);
476 assert_se(streq(data[0], "a=a"));
477 assert_se(streq(data[1], "b=bc"));
478 assert_se(streq(data[2], "d=def"));
479 assert_se(streq(data[3], "g=g "));
480 assert_se(streq(data[4], "h=h"));
481 assert_se(streq(data[5], "i=i"));
482 assert_se(data[6] == NULL);
483 unlink(name);
484 }
485
486 static void test_load_env_file_2(void) {
487 _cleanup_strv_free_ char **data = NULL;
488 int r;
489
490 char name[] = "/tmp/test-load-env-file.XXXXXX";
491 _cleanup_close_ int fd;
492
493 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
494 assert_se(fd >= 0);
495 assert_se(write(fd, env_file_2, sizeof(env_file_2)) == sizeof(env_file_2));
496
497 r = load_env_file(NULL, name, NULL, &data);
498 assert_se(r == 0);
499 assert_se(streq(data[0], "a=a"));
500 assert_se(data[1] == NULL);
501 unlink(name);
502 }
503
504 static void test_load_env_file_3(void) {
505 _cleanup_strv_free_ char **data = NULL;
506 int r;
507
508 char name[] = "/tmp/test-load-env-file.XXXXXX";
509 _cleanup_close_ int fd;
510
511 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
512 assert_se(fd >= 0);
513 assert_se(write(fd, env_file_3, sizeof(env_file_3)) == sizeof(env_file_3));
514
515 r = load_env_file(NULL, name, NULL, &data);
516 assert_se(r == 0);
517 assert_se(data == NULL);
518 unlink(name);
519 }
520
521 static void test_load_env_file_4(void) {
522 _cleanup_strv_free_ char **data = NULL;
523 char name[] = "/tmp/test-load-env-file.XXXXXX";
524 _cleanup_close_ int fd;
525 int r;
526
527 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
528 assert_se(fd >= 0);
529 assert_se(write(fd, env_file_4, sizeof(env_file_4)) == sizeof(env_file_4));
530
531 r = load_env_file(NULL, name, NULL, &data);
532 assert_se(r == 0);
533 assert_se(streq(data[0], "HWMON_MODULES=coretemp f71882fg"));
534 assert_se(streq(data[1], "MODULE_0=coretemp"));
535 assert_se(streq(data[2], "MODULE_1=f71882fg"));
536 assert_se(data[3] == NULL);
537 unlink(name);
538 }
539
540 static void test_load_env_file_5(void) {
541 _cleanup_strv_free_ char **data = NULL;
542 int r;
543
544 char name[] = "/tmp/test-load-env-file.XXXXXX";
545 _cleanup_close_ int fd;
546
547 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
548 assert_se(fd >= 0);
549 assert_se(write(fd, env_file_5, sizeof(env_file_5)) == sizeof(env_file_5));
550
551 r = load_env_file(NULL, name, NULL, &data);
552 assert_se(r == 0);
553 assert_se(streq(data[0], "a="));
554 assert_se(streq(data[1], "b="));
555 assert_se(data[2] == NULL);
556 unlink(name);
557 }
558
559 static void test_install_printf(void) {
560 char name[] = "name.service",
561 path[] = "/run/systemd/system/name.service",
562 user[] = "xxxx-no-such-user";
563 UnitFileInstallInfo i = {name, path, user};
564 UnitFileInstallInfo i2 = {name, path, NULL};
565 char name3[] = "name@inst.service",
566 path3[] = "/run/systemd/system/name.service";
567 UnitFileInstallInfo i3 = {name3, path3, user};
568 UnitFileInstallInfo i4 = {name3, path3, NULL};
569
570 _cleanup_free_ char *mid, *bid, *host;
571
572 assert_se(specifier_machine_id('m', NULL, NULL, &mid) >= 0 && mid);
573 assert_se(specifier_boot_id('b', NULL, NULL, &bid) >= 0 && bid);
574 assert_se((host = gethostname_malloc()));
575
576 #define expect(src, pattern, result) \
577 do { \
578 _cleanup_free_ char *t = NULL; \
579 _cleanup_free_ char \
580 *d1 = strdup(i.name), \
581 *d2 = strdup(i.path), \
582 *d3 = strdup(i.user); \
583 assert_se(install_full_printf(&src, pattern, &t) >= 0 || !result); \
584 memzero(i.name, strlen(i.name)); \
585 memzero(i.path, strlen(i.path)); \
586 memzero(i.user, strlen(i.user)); \
587 assert_se(d1 && d2 && d3); \
588 if (result) { \
589 printf("%s\n", t); \
590 assert_se(streq(t, result)); \
591 } else assert_se(t == NULL); \
592 strcpy(i.name, d1); \
593 strcpy(i.path, d2); \
594 strcpy(i.user, d3); \
595 } while(false)
596
597 assert_se(setenv("USER", "root", 1) == 0);
598
599 expect(i, "%n", "name.service");
600 expect(i, "%N", "name");
601 expect(i, "%p", "name");
602 expect(i, "%i", "");
603 expect(i, "%u", "xxxx-no-such-user");
604
605 DISABLE_WARNING_NONNULL;
606 expect(i, "%U", NULL);
607 REENABLE_WARNING;
608
609 expect(i, "%m", mid);
610 expect(i, "%b", bid);
611 expect(i, "%H", host);
612
613 expect(i2, "%u", "root");
614 expect(i2, "%U", "0");
615
616 expect(i3, "%n", "name@inst.service");
617 expect(i3, "%N", "name@inst");
618 expect(i3, "%p", "name");
619 expect(i3, "%u", "xxxx-no-such-user");
620
621 DISABLE_WARNING_NONNULL;
622 expect(i3, "%U", NULL);
623 REENABLE_WARNING;
624
625 expect(i3, "%m", mid);
626 expect(i3, "%b", bid);
627 expect(i3, "%H", host);
628
629 expect(i4, "%u", "root");
630 expect(i4, "%U", "0");
631 }
632
633 static uint64_t make_cap(int cap) {
634 return ((uint64_t) 1ULL << (uint64_t) cap);
635 }
636
637 static void test_config_parse_bounding_set(void) {
638 /* int config_parse_bounding_set(
639 const char *unit,
640 const char *filename,
641 unsigned line,
642 const char *section,
643 unsigned section_line,
644 const char *lvalue,
645 int ltype,
646 const char *rvalue,
647 void *data,
648 void *userdata) */
649 int r;
650 uint64_t capability_bounding_set_drop = 0;
651
652 r = config_parse_bounding_set(NULL, "fake", 1, "section", 1,
653 "CapabilityBoundingSet", 0, "CAP_NET_RAW",
654 &capability_bounding_set_drop, NULL);
655 assert_se(r >= 0);
656 assert_se(capability_bounding_set_drop == ~make_cap(CAP_NET_RAW));
657
658 r = config_parse_bounding_set(NULL, "fake", 1, "section", 1,
659 "CapabilityBoundingSet", 0, "CAP_NET_ADMIN",
660 &capability_bounding_set_drop, NULL);
661 assert_se(r >= 0);
662 assert_se(capability_bounding_set_drop == ~(make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN)));
663
664 r = config_parse_bounding_set(NULL, "fake", 1, "section", 1,
665 "CapabilityBoundingSet", 0, "",
666 &capability_bounding_set_drop, NULL);
667 assert_se(r >= 0);
668 assert_se(capability_bounding_set_drop == ~((uint64_t) 0ULL));
669
670 r = config_parse_bounding_set(NULL, "fake", 1, "section", 1,
671 "CapabilityBoundingSet", 0, "~",
672 &capability_bounding_set_drop, NULL);
673 assert_se(r >= 0);
674 assert_se(capability_bounding_set_drop == (uint64_t) 0ULL);
675
676 capability_bounding_set_drop = 0;
677 r = config_parse_bounding_set(NULL, "fake", 1, "section", 1,
678 "CapabilityBoundingSet", 0, " 'CAP_NET_RAW' WAT_CAP??? CAP_NET_ADMIN CAP'_trailing_garbage",
679 &capability_bounding_set_drop, NULL);
680 assert_se(r >= 0);
681 assert_se(capability_bounding_set_drop == ~(make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN)));
682 }
683
684 int main(int argc, char *argv[]) {
685 int r;
686
687 log_parse_environment();
688 log_open();
689
690 r = test_unit_file_get_set();
691 test_config_parse_exec();
692 test_config_parse_bounding_set();
693 test_load_env_file_1();
694 test_load_env_file_2();
695 test_load_env_file_3();
696 test_load_env_file_4();
697 test_load_env_file_5();
698 TEST_REQ_RUNNING_SYSTEMD(test_install_printf());
699
700 return r;
701 }