]> git.ipfire.org Git - thirdparty/systemd.git/blame_incremental - src/test/test-unit-file.c
Merge pull request #2495 from heftig/master
[thirdparty/systemd.git] / src / test / test-unit-file.c
... / ...
CommitLineData
1/***
2 This file is part of systemd.
3
4 Copyright 2012 Lennart Poettering
5 Copyright 2013 Zbigniew Jędrzejewski-Szmek
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
20
21#include <fcntl.h>
22#include <stddef.h>
23#include <stdio.h>
24#include <string.h>
25#include <sys/capability.h>
26#include <unistd.h>
27
28#include "alloc-util.h"
29#include "capability-util.h"
30#include "fd-util.h"
31#include "fileio.h"
32#include "hashmap.h"
33#include "hostname-util.h"
34#include "install-printf.h"
35#include "install.h"
36#include "load-fragment.h"
37#include "macro.h"
38#include "specifier.h"
39#include "string-util.h"
40#include "strv.h"
41#include "test-helper.h"
42#include "user-util.h"
43#include "util.h"
44
45static 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
74static 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
97static 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 Manager *m = NULL;
114 Unit *u = NULL;
115
116 r = manager_new(MANAGER_USER, true, &m);
117 if (MANAGER_SKIP_TEST(r)) {
118 printf("Skipping test: manager_new: %s\n", strerror(-r));
119 return;
120 }
121
122 assert_se(r >= 0);
123 assert_se(manager_startup(m, NULL, NULL) >= 0);
124
125 assert_se(u = unit_new(m, sizeof(Service)));
126
127 log_info("/* basic test */");
128 r = config_parse_exec(NULL, "fake", 1, "section", 1,
129 "LValue", 0, "/RValue r1",
130 &c, u);
131 assert_se(r >= 0);
132 check_execcommand(c, "/RValue", "/RValue", "r1", NULL, false);
133
134 r = config_parse_exec(NULL, "fake", 2, "section", 1,
135 "LValue", 0, "/RValue///slashes r1///",
136 &c, u);
137
138 log_info("/* test slashes */");
139 assert_se(r >= 0);
140 c1 = c->command_next;
141 check_execcommand(c1, "/RValue/slashes", "/RValue///slashes", "r1///", NULL, false);
142
143 log_info("/* trailing slash */");
144 r = config_parse_exec(NULL, "fake", 4, "section", 1,
145 "LValue", 0, "/RValue/ argv0 r1",
146 &c, u);
147 assert_se(r == 0);
148 assert_se(c1->command_next == NULL);
149
150 log_info("/* honour_argv0 */");
151 r = config_parse_exec(NULL, "fake", 3, "section", 1,
152 "LValue", 0, "@/RValue///slashes2 ///argv0 r1",
153 &c, u);
154 assert_se(r >= 0);
155 c1 = c1->command_next;
156 check_execcommand(c1, "/RValue/slashes2", "///argv0", "r1", NULL, false);
157
158 log_info("/* honour_argv0, no args */");
159 r = config_parse_exec(NULL, "fake", 3, "section", 1,
160 "LValue", 0, "@/RValue",
161 &c, u);
162 assert_se(r == 0);
163 assert_se(c1->command_next == NULL);
164
165 log_info("/* no command, whitespace only, reset */");
166 r = config_parse_exec(NULL, "fake", 3, "section", 1,
167 "LValue", 0, " ",
168 &c, u);
169 assert_se(r == 0);
170 assert_se(c == NULL);
171
172 log_info("/* ignore && honour_argv0 */");
173 r = config_parse_exec(NULL, "fake", 4, "section", 1,
174 "LValue", 0, "-@/RValue///slashes3 argv0a r1",
175 &c, u);
176 assert_se(r >= 0);
177 c1 = c;
178 check_execcommand(c1, "/RValue/slashes3", "argv0a", "r1", NULL, true);
179
180 log_info("/* ignore && honour_argv0 */");
181 r = config_parse_exec(NULL, "fake", 4, "section", 1,
182 "LValue", 0, "@-/RValue///slashes4 argv0b r1",
183 &c, u);
184 assert_se(r >= 0);
185 c1 = c1->command_next;
186 check_execcommand(c1, "/RValue/slashes4", "argv0b", "r1", NULL, true);
187
188 log_info("/* ignore && ignore */");
189 r = config_parse_exec(NULL, "fake", 4, "section", 1,
190 "LValue", 0, "--/RValue argv0 r1",
191 &c, u);
192 assert_se(r == 0);
193 assert_se(c1->command_next == NULL);
194
195 log_info("/* ignore && ignore (2) */");
196 r = config_parse_exec(NULL, "fake", 4, "section", 1,
197 "LValue", 0, "-@-/RValue argv0 r1",
198 &c, u);
199 assert_se(r == 0);
200 assert_se(c1->command_next == NULL);
201
202 log_info("/* semicolon */");
203 r = config_parse_exec(NULL, "fake", 5, "section", 1,
204 "LValue", 0,
205 "-@/RValue argv0 r1 ; "
206 "/goo/goo boo",
207 &c, u);
208 assert_se(r >= 0);
209 c1 = c1->command_next;
210 check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
211
212 c1 = c1->command_next;
213 check_execcommand(c1, "/goo/goo", NULL, "boo", NULL, false);
214
215 log_info("/* two semicolons in a row */");
216 r = config_parse_exec(NULL, "fake", 5, "section", 1,
217 "LValue", 0,
218 "-@/RValue argv0 r1 ; ; "
219 "/goo/goo boo",
220 &c, u);
221 assert_se(r >= 0);
222 c1 = c1->command_next;
223 check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
224
225 /* second command fails because the executable name is ";" */
226 assert_se(c1->command_next == NULL);
227
228 log_info("/* trailing semicolon */");
229 r = config_parse_exec(NULL, "fake", 5, "section", 1,
230 "LValue", 0,
231 "-@/RValue argv0 r1 ; ",
232 &c, u);
233 assert_se(r >= 0);
234 c1 = c1->command_next;
235 check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
236
237 assert_se(c1->command_next == NULL);
238
239 log_info("/* trailing semicolon, no whitespace */");
240 r = config_parse_exec(NULL, "fake", 5, "section", 1,
241 "LValue", 0,
242 "-@/RValue argv0 r1 ;",
243 &c, u);
244 assert_se(r >= 0);
245 c1 = c1->command_next;
246 check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
247
248 assert_se(c1->command_next == NULL);
249
250 log_info("/* trailing semicolon in single quotes */");
251 r = config_parse_exec(NULL, "fake", 5, "section", 1,
252 "LValue", 0,
253 "-@/RValue argv0 r1 ';'",
254 &c, u);
255 assert_se(r >= 0);
256 c1 = c1->command_next;
257 check_execcommand(c1, "/RValue", "argv0", "r1", ";", true);
258
259 log_info("/* escaped semicolon */");
260 r = config_parse_exec(NULL, "fake", 5, "section", 1,
261 "LValue", 0,
262 "/bin/find \\;",
263 &c, u);
264 assert_se(r >= 0);
265 c1 = c1->command_next;
266 check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
267
268 log_info("/* escaped semicolon with following arg */");
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", false);
277
278 log_info("/* escaped semicolon as part of an expression */");
279 r = config_parse_exec(NULL, "fake", 5, "section", 1,
280 "LValue", 0,
281 "/sbin/find \\;x",
282 &c, u);
283 assert_se(r >= 0);
284 c1 = c1->command_next;
285 check_execcommand(c1,
286 "/sbin/find", NULL, "\\;x", NULL, false);
287
288 log_info("/* encoded semicolon */");
289 r = config_parse_exec(NULL, "fake", 5, "section", 1,
290 "LValue", 0,
291 "/bin/find \\073",
292 &c, u);
293 assert_se(r >= 0);
294 c1 = c1->command_next;
295 check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
296
297 log_info("/* quoted semicolon */");
298 r = config_parse_exec(NULL, "fake", 5, "section", 1,
299 "LValue", 0,
300 "/bin/find \";\"",
301 &c, u);
302 assert_se(r >= 0);
303 c1 = c1->command_next;
304 check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
305
306 log_info("/* quoted semicolon with following arg */");
307 r = config_parse_exec(NULL, "fake", 5, "section", 1,
308 "LValue", 0,
309 "/sbin/find \";\" /x",
310 &c, u);
311 assert_se(r >= 0);
312 c1 = c1->command_next;
313 check_execcommand(c1,
314 "/sbin/find", NULL, ";", "/x", false);
315
316 log_info("/* spaces in the filename */");
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", NULL, "-1", "-2", false);
325
326 log_info("/* spaces in the filename, no args */");
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 -1 -2", NULL, NULL, NULL, false);
335
336 log_info("/* spaces in the filename, everything quoted */");
337 r = config_parse_exec(NULL, "fake", 5, "section", 1,
338 "LValue", 0,
339 "\"/PATH WITH SPACES/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", false);
345
346 log_info("/* escaped spaces in the filename */");
347 r = config_parse_exec(NULL, "fake", 5, "section", 1,
348 "LValue", 0,
349 "\"/PATH\\sWITH\\sSPACES/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 log_info("/* escaped spaces in the filename (2) */");
357 r = config_parse_exec(NULL, "fake", 5, "section", 1,
358 "LValue", 0,
359 "\"/PATH\\x20WITH\\x20SPACES/daemon\" \"-1 -2\"",
360 &c, u);
361 assert_se(r >= 0);
362 c1 = c1->command_next;
363 check_execcommand(c1,
364 "/PATH WITH SPACES/daemon", NULL, "-1 -2", NULL, false);
365
366 for (ccc = "abfnrtv\\\'\"x"; *ccc; ccc++) {
367 /* \\x is an incomplete hexadecimal sequence, invalid because of the slash */
368 char path[] = "/path\\X";
369 path[sizeof(path) - 2] = *ccc;
370
371 log_info("/* invalid character: \\%c */", *ccc);
372 r = config_parse_exec(NULL, "fake", 4, "section", 1,
373 "LValue", 0, path,
374 &c, u);
375 assert_se(r == 0);
376 assert_se(c1->command_next == NULL);
377 }
378
379 log_info("/* valid character: \\s */");
380 r = config_parse_exec(NULL, "fake", 4, "section", 1,
381 "LValue", 0, "/path\\s",
382 &c, u);
383 assert_se(r >= 0);
384 c1 = c1->command_next;
385 check_execcommand(c1, "/path ", NULL, NULL, NULL, false);
386
387 log_info("/* quoted backslashes */");
388 r = config_parse_exec(NULL, "fake", 5, "section", 1,
389 "LValue", 0,
390 "/bin/grep '\\w+\\K'",
391 &c, u);
392 assert_se(r >= 0);
393 c1 = c1->command_next;
394 check_execcommand(c1, "/bin/grep", NULL, "\\w+\\K", NULL, false);
395
396
397 log_info("/* trailing backslash: \\ */");
398 /* backslash is invalid */
399 r = config_parse_exec(NULL, "fake", 4, "section", 1,
400 "LValue", 0, "/path\\",
401 &c, u);
402 assert_se(r == 0);
403 assert_se(c1->command_next == NULL);
404
405 log_info("/* missing ending ' */");
406 r = config_parse_exec(NULL, "fake", 4, "section", 1,
407 "LValue", 0, "/path 'foo",
408 &c, u);
409 assert_se(r == 0);
410 assert_se(c1->command_next == NULL);
411
412 log_info("/* missing ending ' with trailing backslash */");
413 r = config_parse_exec(NULL, "fake", 4, "section", 1,
414 "LValue", 0, "/path 'foo\\",
415 &c, u);
416 assert_se(r == 0);
417 assert_se(c1->command_next == NULL);
418
419 log_info("/* invalid space between modifiers */");
420 r = config_parse_exec(NULL, "fake", 4, "section", 1,
421 "LValue", 0, "- /path",
422 &c, u);
423 assert_se(r == 0);
424 assert_se(c1->command_next == NULL);
425
426 log_info("/* only modifiers, no path */");
427 r = config_parse_exec(NULL, "fake", 4, "section", 1,
428 "LValue", 0, "-",
429 &c, u);
430 assert_se(r == 0);
431 assert_se(c1->command_next == NULL);
432
433 log_info("/* empty argument, reset */");
434 r = config_parse_exec(NULL, "fake", 4, "section", 1,
435 "LValue", 0, "",
436 &c, u);
437 assert_se(r == 0);
438 assert_se(c == NULL);
439
440 exec_command_free_list(c);
441
442 unit_free(u);
443 manager_free(m);
444}
445
446#define env_file_1 \
447 "a=a\n" \
448 "b=b\\\n" \
449 "c\n" \
450 "d=d\\\n" \
451 "e\\\n" \
452 "f\n" \
453 "g=g\\ \n" \
454 "h=h\n" \
455 "i=i\\"
456
457#define env_file_2 \
458 "a=a\\\n"
459
460#define env_file_3 \
461 "#SPAMD_ARGS=\"-d --socketpath=/var/lib/bulwark/spamd \\\n" \
462 "#--nouser-config \\\n" \
463 "normal=line"
464
465#define env_file_4 \
466 "# Generated\n" \
467 "\n" \
468 "HWMON_MODULES=\"coretemp f71882fg\"\n" \
469 "\n" \
470 "# For compatibility reasons\n" \
471 "\n" \
472 "MODULE_0=coretemp\n" \
473 "MODULE_1=f71882fg"
474
475#define env_file_5 \
476 "a=\n" \
477 "b="
478
479static void test_load_env_file_1(void) {
480 _cleanup_strv_free_ char **data = NULL;
481 int r;
482
483 char name[] = "/tmp/test-load-env-file.XXXXXX";
484 _cleanup_close_ int fd;
485
486 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
487 assert_se(fd >= 0);
488 assert_se(write(fd, env_file_1, sizeof(env_file_1)) == sizeof(env_file_1));
489
490 r = load_env_file(NULL, name, NULL, &data);
491 assert_se(r == 0);
492 assert_se(streq(data[0], "a=a"));
493 assert_se(streq(data[1], "b=bc"));
494 assert_se(streq(data[2], "d=def"));
495 assert_se(streq(data[3], "g=g "));
496 assert_se(streq(data[4], "h=h"));
497 assert_se(streq(data[5], "i=i"));
498 assert_se(data[6] == NULL);
499 unlink(name);
500}
501
502static void test_load_env_file_2(void) {
503 _cleanup_strv_free_ char **data = NULL;
504 int r;
505
506 char name[] = "/tmp/test-load-env-file.XXXXXX";
507 _cleanup_close_ int fd;
508
509 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
510 assert_se(fd >= 0);
511 assert_se(write(fd, env_file_2, sizeof(env_file_2)) == sizeof(env_file_2));
512
513 r = load_env_file(NULL, name, NULL, &data);
514 assert_se(r == 0);
515 assert_se(streq(data[0], "a=a"));
516 assert_se(data[1] == NULL);
517 unlink(name);
518}
519
520static void test_load_env_file_3(void) {
521 _cleanup_strv_free_ char **data = NULL;
522 int r;
523
524 char name[] = "/tmp/test-load-env-file.XXXXXX";
525 _cleanup_close_ int fd;
526
527 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
528 assert_se(fd >= 0);
529 assert_se(write(fd, env_file_3, sizeof(env_file_3)) == sizeof(env_file_3));
530
531 r = load_env_file(NULL, name, NULL, &data);
532 assert_se(r == 0);
533 assert_se(data == NULL);
534 unlink(name);
535}
536
537static void test_load_env_file_4(void) {
538 _cleanup_strv_free_ char **data = NULL;
539 char name[] = "/tmp/test-load-env-file.XXXXXX";
540 _cleanup_close_ int fd;
541 int r;
542
543 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
544 assert_se(fd >= 0);
545 assert_se(write(fd, env_file_4, sizeof(env_file_4)) == sizeof(env_file_4));
546
547 r = load_env_file(NULL, name, NULL, &data);
548 assert_se(r == 0);
549 assert_se(streq(data[0], "HWMON_MODULES=coretemp f71882fg"));
550 assert_se(streq(data[1], "MODULE_0=coretemp"));
551 assert_se(streq(data[2], "MODULE_1=f71882fg"));
552 assert_se(data[3] == NULL);
553 unlink(name);
554}
555
556static void test_load_env_file_5(void) {
557 _cleanup_strv_free_ char **data = NULL;
558 int r;
559
560 char name[] = "/tmp/test-load-env-file.XXXXXX";
561 _cleanup_close_ int fd;
562
563 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
564 assert_se(fd >= 0);
565 assert_se(write(fd, env_file_5, sizeof(env_file_5)) == sizeof(env_file_5));
566
567 r = load_env_file(NULL, name, NULL, &data);
568 assert_se(r == 0);
569 assert_se(streq(data[0], "a="));
570 assert_se(streq(data[1], "b="));
571 assert_se(data[2] == NULL);
572 unlink(name);
573}
574
575static void test_install_printf(void) {
576 char name[] = "name.service",
577 path[] = "/run/systemd/system/name.service";
578 UnitFileInstallInfo i = { .name = name, .path = path, };
579 UnitFileInstallInfo i2 = { .name= name, .path = path, };
580 char name3[] = "name@inst.service",
581 path3[] = "/run/systemd/system/name.service";
582 UnitFileInstallInfo i3 = { .name = name3, .path = path3, };
583 UnitFileInstallInfo i4 = { .name = name3, .path = path3, };
584
585 _cleanup_free_ char *mid = NULL, *bid = NULL, *host = NULL, *uid = NULL, *user = NULL;
586
587 assert_se(specifier_machine_id('m', NULL, NULL, &mid) >= 0 && mid);
588 assert_se(specifier_boot_id('b', NULL, NULL, &bid) >= 0 && bid);
589 assert_se((host = gethostname_malloc()));
590 assert_se((user = getusername_malloc()));
591 assert_se(asprintf(&uid, UID_FMT, getuid()) >= 0);
592
593#define expect(src, pattern, result) \
594 do { \
595 _cleanup_free_ char *t = NULL; \
596 _cleanup_free_ char \
597 *d1 = strdup(i.name), \
598 *d2 = strdup(i.path); \
599 assert_se(install_full_printf(&src, pattern, &t) >= 0 || !result); \
600 memzero(i.name, strlen(i.name)); \
601 memzero(i.path, strlen(i.path)); \
602 assert_se(d1 && d2); \
603 if (result) { \
604 printf("%s\n", t); \
605 assert_se(streq(t, result)); \
606 } else assert_se(t == NULL); \
607 strcpy(i.name, d1); \
608 strcpy(i.path, d2); \
609 } while(false)
610
611 expect(i, "%n", "name.service");
612 expect(i, "%N", "name");
613 expect(i, "%p", "name");
614 expect(i, "%i", "");
615 expect(i, "%u", user);
616 expect(i, "%U", uid);
617
618 expect(i, "%m", mid);
619 expect(i, "%b", bid);
620 expect(i, "%H", host);
621
622 expect(i2, "%u", user);
623 expect(i2, "%U", uid);
624
625 expect(i3, "%n", "name@inst.service");
626 expect(i3, "%N", "name@inst");
627 expect(i3, "%p", "name");
628 expect(i3, "%u", user);
629 expect(i3, "%U", uid);
630
631 expect(i3, "%m", mid);
632 expect(i3, "%b", bid);
633 expect(i3, "%H", host);
634
635 expect(i4, "%u", user);
636 expect(i4, "%U", uid);
637}
638
639static uint64_t make_cap(int cap) {
640 return ((uint64_t) 1ULL << (uint64_t) cap);
641}
642
643static void test_config_parse_capability_set(void) {
644 /* int config_parse_capability_set(
645 const char *unit,
646 const char *filename,
647 unsigned line,
648 const char *section,
649 unsigned section_line,
650 const char *lvalue,
651 int ltype,
652 const char *rvalue,
653 void *data,
654 void *userdata) */
655 int r;
656 uint64_t capability_bounding_set = 0;
657
658 r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
659 "CapabilityBoundingSet", 0, "CAP_NET_RAW",
660 &capability_bounding_set, NULL);
661 assert_se(r >= 0);
662 assert_se(capability_bounding_set == make_cap(CAP_NET_RAW));
663
664 r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
665 "CapabilityBoundingSet", 0, "CAP_NET_ADMIN",
666 &capability_bounding_set, NULL);
667 assert_se(r >= 0);
668 assert_se(capability_bounding_set == (make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN)));
669
670 r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
671 "CapabilityBoundingSet", 0, "",
672 &capability_bounding_set, NULL);
673 assert_se(r >= 0);
674 assert_se(capability_bounding_set == UINT64_C(0));
675
676 r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
677 "CapabilityBoundingSet", 0, "~",
678 &capability_bounding_set, NULL);
679 assert_se(r >= 0);
680 assert_se(cap_test_all(capability_bounding_set));
681
682 capability_bounding_set = 0;
683 r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
684 "CapabilityBoundingSet", 0, " 'CAP_NET_RAW' WAT_CAP??? CAP_NET_ADMIN CAP'_trailing_garbage",
685 &capability_bounding_set, NULL);
686 assert_se(r >= 0);
687 assert_se(capability_bounding_set == (make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN)));
688}
689
690static void test_config_parse_rlimit(void) {
691 struct rlimit * rl[_RLIMIT_MAX] = {};
692
693 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55", rl, NULL) >= 0);
694 assert_se(rl[RLIMIT_NOFILE]);
695 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 55);
696 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
697
698 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55:66", rl, NULL) >= 0);
699 assert_se(rl[RLIMIT_NOFILE]);
700 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 55);
701 assert_se(rl[RLIMIT_NOFILE]->rlim_max == 66);
702
703 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity", rl, NULL) >= 0);
704 assert_se(rl[RLIMIT_NOFILE]);
705 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == RLIM_INFINITY);
706 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
707
708 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity:infinity", rl, NULL) >= 0);
709 assert_se(rl[RLIMIT_NOFILE]);
710 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == RLIM_INFINITY);
711 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
712
713 rl[RLIMIT_NOFILE]->rlim_cur = 10;
714 rl[RLIMIT_NOFILE]->rlim_max = 20;
715
716 /* Invalid values don't change rl */
717 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "10:20:30", rl, NULL) >= 0);
718 assert_se(rl[RLIMIT_NOFILE]);
719 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
720 assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
721
722 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "wat:wat", rl, NULL) >= 0);
723 assert_se(rl[RLIMIT_NOFILE]);
724 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
725 assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
726
727 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "66:wat", rl, NULL) >= 0);
728 assert_se(rl[RLIMIT_NOFILE]);
729 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
730 assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
731
732 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "200:100", rl, NULL) >= 0);
733 assert_se(rl[RLIMIT_NOFILE]);
734 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
735 assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
736
737 rl[RLIMIT_NOFILE] = mfree(rl[RLIMIT_NOFILE]);
738
739 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "56", rl, NULL) >= 0);
740 assert_se(rl[RLIMIT_CPU]);
741 assert_se(rl[RLIMIT_CPU]->rlim_cur == 56);
742 assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
743
744 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "57s", rl, NULL) >= 0);
745 assert_se(rl[RLIMIT_CPU]);
746 assert_se(rl[RLIMIT_CPU]->rlim_cur == 57);
747 assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
748
749 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "40s:1m", rl, NULL) >= 0);
750 assert_se(rl[RLIMIT_CPU]);
751 assert_se(rl[RLIMIT_CPU]->rlim_cur == 40);
752 assert_se(rl[RLIMIT_CPU]->rlim_max == 60);
753
754 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "infinity", rl, NULL) >= 0);
755 assert_se(rl[RLIMIT_CPU]);
756 assert_se(rl[RLIMIT_CPU]->rlim_cur == RLIM_INFINITY);
757 assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
758
759 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "1234ms", rl, NULL) >= 0);
760 assert_se(rl[RLIMIT_CPU]);
761 assert_se(rl[RLIMIT_CPU]->rlim_cur == 2);
762 assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
763
764 rl[RLIMIT_CPU] = mfree(rl[RLIMIT_CPU]);
765
766 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58", rl, NULL) >= 0);
767 assert_se(rl[RLIMIT_RTTIME]);
768 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 58);
769 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
770
771 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58:60", rl, NULL) >= 0);
772 assert_se(rl[RLIMIT_RTTIME]);
773 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 58);
774 assert_se(rl[RLIMIT_RTTIME]->rlim_max == 60);
775
776 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s", rl, NULL) >= 0);
777 assert_se(rl[RLIMIT_RTTIME]);
778 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 59 * USEC_PER_SEC);
779 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
780
781 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s:123s", rl, NULL) >= 0);
782 assert_se(rl[RLIMIT_RTTIME]);
783 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 59 * USEC_PER_SEC);
784 assert_se(rl[RLIMIT_RTTIME]->rlim_max == 123 * USEC_PER_SEC);
785
786 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity", rl, NULL) >= 0);
787 assert_se(rl[RLIMIT_RTTIME]);
788 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == RLIM_INFINITY);
789 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
790
791 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity:infinity", rl, NULL) >= 0);
792 assert_se(rl[RLIMIT_RTTIME]);
793 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == RLIM_INFINITY);
794 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
795
796 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "2345ms", rl, NULL) >= 0);
797 assert_se(rl[RLIMIT_RTTIME]);
798 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 2345 * USEC_PER_MSEC);
799 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
800
801 rl[RLIMIT_RTTIME] = mfree(rl[RLIMIT_RTTIME]);
802}
803
804static void test_config_parse_pass_environ(void) {
805 /* int config_parse_pass_environ(
806 const char *unit,
807 const char *filename,
808 unsigned line,
809 const char *section,
810 unsigned section_line,
811 const char *lvalue,
812 int ltype,
813 const char *rvalue,
814 void *data,
815 void *userdata) */
816 int r;
817 _cleanup_strv_free_ char **passenv = NULL;
818
819 r = config_parse_pass_environ(NULL, "fake", 1, "section", 1,
820 "PassEnvironment", 0, "A B",
821 &passenv, NULL);
822 assert_se(r >= 0);
823 assert_se(strv_length(passenv) == 2);
824 assert_se(streq(passenv[0], "A"));
825 assert_se(streq(passenv[1], "B"));
826
827 r = config_parse_pass_environ(NULL, "fake", 1, "section", 1,
828 "PassEnvironment", 0, "",
829 &passenv, NULL);
830 assert_se(r >= 0);
831 assert_se(strv_isempty(passenv));
832
833 r = config_parse_pass_environ(NULL, "fake", 1, "section", 1,
834 "PassEnvironment", 0, "'invalid name' 'normal_name' A=1 \\",
835 &passenv, NULL);
836 assert_se(r >= 0);
837 assert_se(strv_length(passenv) == 1);
838 assert_se(streq(passenv[0], "normal_name"));
839
840}
841
842int main(int argc, char *argv[]) {
843 int r;
844
845 log_parse_environment();
846 log_open();
847
848 r = test_unit_file_get_set();
849 test_config_parse_exec();
850 test_config_parse_capability_set();
851 test_config_parse_rlimit();
852 test_config_parse_pass_environ();
853 test_load_env_file_1();
854 test_load_env_file_2();
855 test_load_env_file_3();
856 test_load_env_file_4();
857 test_load_env_file_5();
858 TEST_REQ_RUNNING_SYSTEMD(test_install_printf());
859
860 return r;
861}