]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/test/test-unit-file.c
Merge pull request #12390 from poettering/string-file-mkdir
[thirdparty/systemd.git] / src / test / test-unit-file.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
b5b46d59 2
07630cea 3#include <fcntl.h>
b5b46d59 4#include <stddef.h>
07630cea 5#include <stdio.h>
b5b46d59 6#include <string.h>
a8107a54 7#include <sys/capability.h>
b9893505 8#include <unistd.h>
b5b46d59 9
57b7a260 10#include "all-units.h"
e4de7287 11#include "alloc-util.h"
a103496c 12#include "capability-util.h"
4f424df7 13#include "conf-parser.h"
686d13b9 14#include "env-file.h"
3ffd4af2 15#include "fd-util.h"
ca78ad1d 16#include "format-util.h"
627d2bac 17#include "fs-util.h"
b5b46d59 18#include "hashmap.h"
07630cea
LP
19#include "hostname-util.h"
20#include "install-printf.h"
21#include "install.h"
2c5417ad 22#include "load-fragment.h"
07630cea 23#include "macro.h"
0a970718 24#include "memory-util.h"
d2120590 25#include "rm-rf.h"
07630cea
LP
26#include "specifier.h"
27#include "string-util.h"
b9893505 28#include "strv.h"
143bfdaf 29#include "test-helper.h"
d2120590 30#include "tests.h"
e4de7287 31#include "tmpfile-util.h"
79413b67 32#include "user-util.h"
b5b46d59 33
751e7576 34static int test_unit_file_get_set(void) {
b5b46d59
LP
35 int r;
36 Hashmap *h;
37 Iterator i;
38 UnitFileList *p;
39
d5099efc 40 h = hashmap_new(&string_hash_ops);
bdf7026e 41 assert_se(h);
b5b46d59 42
313fe66f 43 r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h, NULL, NULL);
730d989a
ZJS
44 if (IN_SET(r, -EPERM, -EACCES))
45 return log_tests_skipped_errno(r, "unit_file_get_list");
552c693e 46
9eec7d12
ZJS
47 log_full_errno(r == 0 ? LOG_INFO : LOG_ERR, r,
48 "unit_file_get_list: %m");
751e7576
CH
49 if (r < 0)
50 return EXIT_FAILURE;
b5b46d59
LP
51
52 HASHMAP_FOREACH(p, h, i)
53 printf("%s = %s\n", p->path, unit_file_state_to_string(p->state));
54
55 unit_file_list_free(h);
751e7576
CH
56
57 return 0;
2c5417ad
ZJS
58}
59
60static void check_execcommand(ExecCommand *c,
61 const char* path,
62 const char* argv0,
63 const char* argv1,
503dbda6 64 const char* argv2,
2c5417ad 65 bool ignore) {
4d8629de
ZJS
66 size_t n;
67
2c5417ad 68 assert_se(c);
c8539536
ZJS
69 log_info("expect: \"%s\" [\"%s\" \"%s\" \"%s\"]",
70 path, argv0 ?: path, argv1, argv2);
4d8629de 71 n = strv_length(c->argv);
c8539536 72 log_info("actual: \"%s\" [\"%s\" \"%s\" \"%s\"]",
4d8629de 73 c->path, c->argv[0], n > 0 ? c->argv[1] : NULL, n > 1 ? c->argv[2] : NULL);
2c5417ad 74 assert_se(streq(c->path, path));
c8539536 75 assert_se(streq(c->argv[0], argv0 ?: path));
4d8629de
ZJS
76 if (n > 0)
77 assert_se(streq_ptr(c->argv[1], argv1));
78 if (n > 1)
79 assert_se(streq_ptr(c->argv[2], argv2));
3ed0cd26 80 assert_se(!!(c->flags & EXEC_COMMAND_IGNORE_FAILURE) == ignore);
2c5417ad
ZJS
81}
82
83static void test_config_parse_exec(void) {
c8539536 84 /* int config_parse_exec(
470dca63 85 const char *unit,
c8539536
ZJS
86 const char *filename,
87 unsigned line,
88 const char *section,
89 unsigned section_line,
90 const char *lvalue,
91 int ltype,
92 const char *rvalue,
93 void *data,
94 void *userdata) */
2c5417ad
ZJS
95 int r;
96
97 ExecCommand *c = NULL, *c1;
c8539536 98 const char *ccc;
c70cac54 99 _cleanup_(manager_freep) Manager *m = NULL;
dc409696 100 _cleanup_(unit_freep) Unit *u = NULL;
139891f0 101
e0a3da1f 102 r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_MINIMAL, &m);
139891f0 103 if (MANAGER_SKIP_TEST(r)) {
9eec7d12 104 log_notice_errno(r, "Skipping test: manager_new: %m");
139891f0
WC
105 return;
106 }
107
108 assert_se(r >= 0);
109 assert_se(manager_startup(m, NULL, NULL) >= 0);
110
111 assert_se(u = unit_new(m, sizeof(Service)));
2c5417ad 112
c8539536 113 log_info("/* basic test */");
71a61510 114 r = config_parse_exec(NULL, "fake", 1, "section", 1,
2c5417ad 115 "LValue", 0, "/RValue r1",
139891f0 116 &c, u);
2c5417ad 117 assert_se(r >= 0);
503dbda6 118 check_execcommand(c, "/RValue", "/RValue", "r1", NULL, false);
2c5417ad 119
71a61510 120 r = config_parse_exec(NULL, "fake", 2, "section", 1,
c8539536 121 "LValue", 0, "/RValue///slashes r1///",
139891f0 122 &c, u);
c8539536
ZJS
123
124 log_info("/* test slashes */");
2c5417ad
ZJS
125 assert_se(r >= 0);
126 c1 = c->command_next;
c8539536 127 check_execcommand(c1, "/RValue/slashes", "/RValue///slashes", "r1///", NULL, false);
2c5417ad 128
c8539536
ZJS
129 log_info("/* trailing slash */");
130 r = config_parse_exec(NULL, "fake", 4, "section", 1,
131 "LValue", 0, "/RValue/ argv0 r1",
139891f0 132 &c, u);
bb28e684 133 assert_se(r == -ENOEXEC);
c8539536
ZJS
134 assert_se(c1->command_next == NULL);
135
136 log_info("/* honour_argv0 */");
71a61510 137 r = config_parse_exec(NULL, "fake", 3, "section", 1,
c8539536 138 "LValue", 0, "@/RValue///slashes2 ///argv0 r1",
139891f0 139 &c, u);
2c5417ad
ZJS
140 assert_se(r >= 0);
141 c1 = c1->command_next;
c8539536 142 check_execcommand(c1, "/RValue/slashes2", "///argv0", "r1", NULL, false);
2c5417ad 143
e01ff428
ZJS
144 log_info("/* honour_argv0, no args */");
145 r = config_parse_exec(NULL, "fake", 3, "section", 1,
146 "LValue", 0, "@/RValue",
139891f0 147 &c, u);
bb28e684 148 assert_se(r == -ENOEXEC);
e01ff428
ZJS
149 assert_se(c1->command_next == NULL);
150
c83f1f30 151 log_info("/* no command, whitespace only, reset */");
e01ff428
ZJS
152 r = config_parse_exec(NULL, "fake", 3, "section", 1,
153 "LValue", 0, " ",
139891f0 154 &c, u);
e01ff428 155 assert_se(r == 0);
c83f1f30 156 assert_se(c == NULL);
e01ff428 157
c8539536 158 log_info("/* ignore && honour_argv0 */");
71a61510 159 r = config_parse_exec(NULL, "fake", 4, "section", 1,
c8539536 160 "LValue", 0, "-@/RValue///slashes3 argv0a r1",
139891f0 161 &c, u);
2c5417ad 162 assert_se(r >= 0);
c83f1f30 163 c1 = c;
503dbda6 164 check_execcommand(c1, "/RValue/slashes3", "argv0a", "r1", NULL, true);
2c5417ad 165
c8539536 166 log_info("/* ignore && honour_argv0 */");
71a61510 167 r = config_parse_exec(NULL, "fake", 4, "section", 1,
c8539536 168 "LValue", 0, "@-/RValue///slashes4 argv0b r1",
139891f0 169 &c, u);
0f67f1ef
ZJS
170 assert_se(r >= 0);
171 c1 = c1->command_next;
503dbda6 172 check_execcommand(c1, "/RValue/slashes4", "argv0b", "r1", NULL, true);
0f67f1ef 173
c8539536 174 log_info("/* ignore && ignore */");
71a61510 175 r = config_parse_exec(NULL, "fake", 4, "section", 1,
0f67f1ef 176 "LValue", 0, "--/RValue argv0 r1",
139891f0 177 &c, u);
0f67f1ef
ZJS
178 assert_se(r == 0);
179 assert_se(c1->command_next == NULL);
180
c8539536 181 log_info("/* ignore && ignore (2) */");
71a61510 182 r = config_parse_exec(NULL, "fake", 4, "section", 1,
0f67f1ef 183 "LValue", 0, "-@-/RValue argv0 r1",
139891f0 184 &c, u);
0f67f1ef
ZJS
185 assert_se(r == 0);
186 assert_se(c1->command_next == NULL);
187
c8539536 188 log_info("/* semicolon */");
71a61510 189 r = config_parse_exec(NULL, "fake", 5, "section", 1,
2c5417ad
ZJS
190 "LValue", 0,
191 "-@/RValue argv0 r1 ; "
192 "/goo/goo boo",
139891f0 193 &c, u);
2c5417ad
ZJS
194 assert_se(r >= 0);
195 c1 = c1->command_next;
503dbda6 196 check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
2c5417ad
ZJS
197
198 c1 = c1->command_next;
c8539536 199 check_execcommand(c1, "/goo/goo", NULL, "boo", NULL, false);
2c5417ad 200
0e9800d5
FB
201 log_info("/* two semicolons in a row */");
202 r = config_parse_exec(NULL, "fake", 5, "section", 1,
203 "LValue", 0,
204 "-@/RValue argv0 r1 ; ; "
205 "/goo/goo boo",
139891f0 206 &c, u);
bb28e684 207 assert_se(r == -ENOEXEC);
0e9800d5
FB
208 c1 = c1->command_next;
209 check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
210
211 /* second command fails because the executable name is ";" */
212 assert_se(c1->command_next == NULL);
213
c8539536 214 log_info("/* trailing semicolon */");
71a61510 215 r = config_parse_exec(NULL, "fake", 5, "section", 1,
2c5417ad
ZJS
216 "LValue", 0,
217 "-@/RValue argv0 r1 ; ",
139891f0 218 &c, u);
2c5417ad
ZJS
219 assert_se(r >= 0);
220 c1 = c1->command_next;
503dbda6 221 check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
2c5417ad
ZJS
222
223 assert_se(c1->command_next == NULL);
224
0e9800d5
FB
225 log_info("/* trailing semicolon, no whitespace */");
226 r = config_parse_exec(NULL, "fake", 5, "section", 1,
227 "LValue", 0,
228 "-@/RValue argv0 r1 ;",
139891f0 229 &c, u);
0e9800d5
FB
230 assert_se(r >= 0);
231 c1 = c1->command_next;
232 check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
233
234 assert_se(c1->command_next == NULL);
235
236 log_info("/* trailing semicolon in single quotes */");
237 r = config_parse_exec(NULL, "fake", 5, "section", 1,
238 "LValue", 0,
239 "-@/RValue argv0 r1 ';'",
139891f0 240 &c, u);
0e9800d5
FB
241 assert_se(r >= 0);
242 c1 = c1->command_next;
46a0d98a 243 check_execcommand(c1, "/RValue", "argv0", "r1", ";", true);
0e9800d5 244
c8539536 245 log_info("/* escaped semicolon */");
71a61510 246 r = config_parse_exec(NULL, "fake", 5, "section", 1,
7e1a84f5 247 "LValue", 0,
503dbda6 248 "/bin/find \\;",
139891f0 249 &c, u);
503dbda6
ZJS
250 assert_se(r >= 0);
251 c1 = c1->command_next;
c8539536 252 check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
503dbda6 253
c8539536 254 log_info("/* escaped semicolon with following arg */");
503dbda6
ZJS
255 r = config_parse_exec(NULL, "fake", 5, "section", 1,
256 "LValue", 0,
0e9800d5 257 "/sbin/find \\; /x",
139891f0 258 &c, u);
0e9800d5
FB
259 assert_se(r >= 0);
260 c1 = c1->command_next;
261 check_execcommand(c1,
262 "/sbin/find", NULL, ";", "/x", false);
263
264 log_info("/* escaped semicolon as part of an expression */");
265 r = config_parse_exec(NULL, "fake", 5, "section", 1,
266 "LValue", 0,
267 "/sbin/find \\;x",
139891f0 268 &c, u);
7e1a84f5
OS
269 assert_se(r >= 0);
270 c1 = c1->command_next;
271 check_execcommand(c1,
0e9800d5 272 "/sbin/find", NULL, "\\;x", NULL, false);
c8539536 273
80979f1c
DM
274 log_info("/* encoded semicolon */");
275 r = config_parse_exec(NULL, "fake", 5, "section", 1,
276 "LValue", 0,
277 "/bin/find \\073",
139891f0 278 &c, u);
80979f1c
DM
279 assert_se(r >= 0);
280 c1 = c1->command_next;
ce54255f 281 check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
80979f1c 282
0e9800d5
FB
283 log_info("/* quoted semicolon */");
284 r = config_parse_exec(NULL, "fake", 5, "section", 1,
285 "LValue", 0,
286 "/bin/find \";\"",
139891f0 287 &c, u);
0e9800d5
FB
288 assert_se(r >= 0);
289 c1 = c1->command_next;
46a0d98a 290 check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
0e9800d5
FB
291
292 log_info("/* quoted semicolon with following arg */");
293 r = config_parse_exec(NULL, "fake", 5, "section", 1,
294 "LValue", 0,
295 "/sbin/find \";\" /x",
139891f0 296 &c, u);
0e9800d5
FB
297 assert_se(r >= 0);
298 c1 = c1->command_next;
299 check_execcommand(c1,
46a0d98a 300 "/sbin/find", NULL, ";", "/x", false);
0e9800d5 301
c8539536
ZJS
302 log_info("/* spaces in the filename */");
303 r = config_parse_exec(NULL, "fake", 5, "section", 1,
304 "LValue", 0,
305 "\"/PATH WITH SPACES/daemon\" -1 -2",
139891f0 306 &c, u);
c8539536
ZJS
307 assert_se(r >= 0);
308 c1 = c1->command_next;
309 check_execcommand(c1,
310 "/PATH WITH SPACES/daemon", NULL, "-1", "-2", false);
311
312 log_info("/* spaces in the filename, no args */");
313 r = config_parse_exec(NULL, "fake", 5, "section", 1,
314 "LValue", 0,
315 "\"/PATH WITH SPACES/daemon -1 -2\"",
139891f0 316 &c, u);
c8539536
ZJS
317 assert_se(r >= 0);
318 c1 = c1->command_next;
319 check_execcommand(c1,
320 "/PATH WITH SPACES/daemon -1 -2", NULL, NULL, NULL, false);
321
322 log_info("/* spaces in the filename, everything quoted */");
323 r = config_parse_exec(NULL, "fake", 5, "section", 1,
324 "LValue", 0,
325 "\"/PATH WITH SPACES/daemon\" \"-1\" '-2'",
139891f0 326 &c, u);
c8539536
ZJS
327 assert_se(r >= 0);
328 c1 = c1->command_next;
329 check_execcommand(c1,
330 "/PATH WITH SPACES/daemon", NULL, "-1", "-2", false);
331
332 log_info("/* escaped spaces in the filename */");
333 r = config_parse_exec(NULL, "fake", 5, "section", 1,
334 "LValue", 0,
335 "\"/PATH\\sWITH\\sSPACES/daemon\" '-1 -2'",
139891f0 336 &c, u);
c8539536
ZJS
337 assert_se(r >= 0);
338 c1 = c1->command_next;
339 check_execcommand(c1,
340 "/PATH WITH SPACES/daemon", NULL, "-1 -2", NULL, false);
341
342 log_info("/* escaped spaces in the filename (2) */");
343 r = config_parse_exec(NULL, "fake", 5, "section", 1,
344 "LValue", 0,
345 "\"/PATH\\x20WITH\\x20SPACES/daemon\" \"-1 -2\"",
139891f0 346 &c, u);
c8539536
ZJS
347 assert_se(r >= 0);
348 c1 = c1->command_next;
349 check_execcommand(c1,
350 "/PATH WITH SPACES/daemon", NULL, "-1 -2", NULL, false);
351
352 for (ccc = "abfnrtv\\\'\"x"; *ccc; ccc++) {
353 /* \\x is an incomplete hexadecimal sequence, invalid because of the slash */
354 char path[] = "/path\\X";
355 path[sizeof(path) - 2] = *ccc;
356
357 log_info("/* invalid character: \\%c */", *ccc);
358 r = config_parse_exec(NULL, "fake", 4, "section", 1,
359 "LValue", 0, path,
139891f0 360 &c, u);
bb28e684 361 assert_se(r == -ENOEXEC);
c8539536
ZJS
362 assert_se(c1->command_next == NULL);
363 }
364
365 log_info("/* valid character: \\s */");
366 r = config_parse_exec(NULL, "fake", 4, "section", 1,
367 "LValue", 0, "/path\\s",
139891f0 368 &c, u);
c8539536
ZJS
369 assert_se(r >= 0);
370 c1 = c1->command_next;
371 check_execcommand(c1, "/path ", NULL, NULL, NULL, false);
372
80979f1c
DM
373 log_info("/* quoted backslashes */");
374 r = config_parse_exec(NULL, "fake", 5, "section", 1,
375 "LValue", 0,
376 "/bin/grep '\\w+\\K'",
139891f0 377 &c, u);
80979f1c
DM
378 assert_se(r >= 0);
379 c1 = c1->command_next;
380 check_execcommand(c1, "/bin/grep", NULL, "\\w+\\K", NULL, false);
381
c8539536
ZJS
382 log_info("/* trailing backslash: \\ */");
383 /* backslash is invalid */
384 r = config_parse_exec(NULL, "fake", 4, "section", 1,
385 "LValue", 0, "/path\\",
139891f0 386 &c, u);
bb28e684 387 assert_se(r == -ENOEXEC);
c8539536 388 assert_se(c1->command_next == NULL);
7e1a84f5 389
470dca63
MP
390 log_info("/* missing ending ' */");
391 r = config_parse_exec(NULL, "fake", 4, "section", 1,
392 "LValue", 0, "/path 'foo",
139891f0 393 &c, u);
bb28e684 394 assert_se(r == -ENOEXEC);
470dca63
MP
395 assert_se(c1->command_next == NULL);
396
397 log_info("/* missing ending ' with trailing backslash */");
398 r = config_parse_exec(NULL, "fake", 4, "section", 1,
399 "LValue", 0, "/path 'foo\\",
139891f0 400 &c, u);
bb28e684 401 assert_se(r == -ENOEXEC);
470dca63
MP
402 assert_se(c1->command_next == NULL);
403
35b1078e
MP
404 log_info("/* invalid space between modifiers */");
405 r = config_parse_exec(NULL, "fake", 4, "section", 1,
406 "LValue", 0, "- /path",
139891f0 407 &c, u);
35b1078e
MP
408 assert_se(r == 0);
409 assert_se(c1->command_next == NULL);
410
411 log_info("/* only modifiers, no path */");
412 r = config_parse_exec(NULL, "fake", 4, "section", 1,
413 "LValue", 0, "-",
139891f0 414 &c, u);
35b1078e
MP
415 assert_se(r == 0);
416 assert_se(c1->command_next == NULL);
417
418 log_info("/* empty argument, reset */");
419 r = config_parse_exec(NULL, "fake", 4, "section", 1,
420 "LValue", 0, "",
139891f0 421 &c, u);
35b1078e
MP
422 assert_se(r == 0);
423 assert_se(c == NULL);
424
2c5417ad
ZJS
425 exec_command_free_list(c);
426}
427
88bff424
ZJS
428static void test_config_parse_log_extra_fields(void) {
429 /* int config_parse_log_extra_fields(
430 const char *unit,
431 const char *filename,
432 unsigned line,
433 const char *section,
434 unsigned section_line,
435 const char *lvalue,
436 int ltype,
437 const char *rvalue,
438 void *data,
439 void *userdata) */
440
441 int r;
442
c70cac54 443 _cleanup_(manager_freep) Manager *m = NULL;
dc409696 444 _cleanup_(unit_freep) Unit *u = NULL;
88bff424
ZJS
445 ExecContext c = {};
446
447 r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_MINIMAL, &m);
448 if (MANAGER_SKIP_TEST(r)) {
449 log_notice_errno(r, "Skipping test: manager_new: %m");
450 return;
451 }
452
453 assert_se(r >= 0);
454 assert_se(manager_startup(m, NULL, NULL) >= 0);
455
456 assert_se(u = unit_new(m, sizeof(Service)));
457
458 log_info("/* %s – basic test */", __func__);
459 r = config_parse_log_extra_fields(NULL, "fake", 1, "section", 1,
460 "LValue", 0, "FOO=BAR \"QOOF=quux ' ' \"",
461 &c, u);
462 assert_se(r >= 0);
463 assert_se(c.n_log_extra_fields == 2);
464 assert_se(strneq(c.log_extra_fields[0].iov_base, "FOO=BAR", c.log_extra_fields[0].iov_len));
465 assert_se(strneq(c.log_extra_fields[1].iov_base, "QOOF=quux ' ' ", c.log_extra_fields[1].iov_len));
466
467 log_info("/* %s – add some */", __func__);
468 r = config_parse_log_extra_fields(NULL, "fake", 1, "section", 1,
469 "LValue", 0, "FOO2=BAR2 QOOF2=quux ' '",
470 &c, u);
471 assert_se(r >= 0);
472 assert_se(c.n_log_extra_fields == 4);
473 assert_se(strneq(c.log_extra_fields[0].iov_base, "FOO=BAR", c.log_extra_fields[0].iov_len));
474 assert_se(strneq(c.log_extra_fields[1].iov_base, "QOOF=quux ' ' ", c.log_extra_fields[1].iov_len));
475 assert_se(strneq(c.log_extra_fields[2].iov_base, "FOO2=BAR2", c.log_extra_fields[2].iov_len));
476 assert_se(strneq(c.log_extra_fields[3].iov_base, "QOOF2=quux", c.log_extra_fields[3].iov_len));
477
478 exec_context_dump(&c, stdout, " --> ");
479
480 log_info("/* %s – reset */", __func__);
481 r = config_parse_log_extra_fields(NULL, "fake", 1, "section", 1,
482 "LValue", 0, "",
483 &c, u);
484 assert_se(r >= 0);
485 assert_se(c.n_log_extra_fields == 0);
486
487 exec_context_free_log_extra_fields(&c);
488
88bff424
ZJS
489 log_info("/* %s – bye */", __func__);
490}
491
f73141d7
LP
492#define env_file_1 \
493 "a=a\n" \
494 "b=b\\\n" \
495 "c\n" \
496 "d=d\\\n" \
497 "e\\\n" \
498 "f\n" \
499 "g=g\\ \n" \
500 "h=h\n" \
501 "i=i\\"
502
503#define env_file_2 \
504 "a=a\\\n"
b9893505 505
a3aa7ee6
ZJS
506#define env_file_3 \
507 "#SPAMD_ARGS=\"-d --socketpath=/var/lib/bulwark/spamd \\\n" \
508 "#--nouser-config \\\n" \
509 "normal=line"
510
d3b6d0c2
ZJS
511#define env_file_4 \
512 "# Generated\n" \
513 "\n" \
514 "HWMON_MODULES=\"coretemp f71882fg\"\n" \
515 "\n" \
516 "# For compatibility reasons\n" \
517 "\n" \
518 "MODULE_0=coretemp\n" \
519 "MODULE_1=f71882fg"
520
58f10d40
ILG
521#define env_file_5 \
522 "a=\n" \
523 "b="
d3b6d0c2 524
b9893505 525static void test_load_env_file_1(void) {
7fd1b19b 526 _cleanup_strv_free_ char **data = NULL;
b9893505
ZJS
527 int r;
528
627d2bac 529 _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
2d5bdf5b
LP
530 _cleanup_close_ int fd;
531
646853bd 532 fd = mkostemp_safe(name);
bdf7026e 533 assert_se(fd >= 0);
2d78717b 534 assert_se(write(fd, env_file_1, strlen(env_file_1)) == strlen(env_file_1));
b9893505 535
aa8fbc74 536 r = load_env_file(NULL, name, &data);
bdf7026e
TA
537 assert_se(r == 0);
538 assert_se(streq(data[0], "a=a"));
539 assert_se(streq(data[1], "b=bc"));
540 assert_se(streq(data[2], "d=def"));
541 assert_se(streq(data[3], "g=g "));
542 assert_se(streq(data[4], "h=h"));
543 assert_se(streq(data[5], "i=i"));
544 assert_se(data[6] == NULL);
b9893505
ZJS
545}
546
547static void test_load_env_file_2(void) {
7fd1b19b 548 _cleanup_strv_free_ char **data = NULL;
b9893505
ZJS
549 int r;
550
627d2bac 551 _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
2d5bdf5b
LP
552 _cleanup_close_ int fd;
553
646853bd 554 fd = mkostemp_safe(name);
bdf7026e 555 assert_se(fd >= 0);
2d78717b 556 assert_se(write(fd, env_file_2, strlen(env_file_2)) == strlen(env_file_2));
b9893505 557
aa8fbc74 558 r = load_env_file(NULL, name, &data);
bdf7026e
TA
559 assert_se(r == 0);
560 assert_se(streq(data[0], "a=a"));
561 assert_se(data[1] == NULL);
b9893505
ZJS
562}
563
a3aa7ee6 564static void test_load_env_file_3(void) {
7fd1b19b 565 _cleanup_strv_free_ char **data = NULL;
a3aa7ee6
ZJS
566 int r;
567
627d2bac 568 _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
2d5bdf5b
LP
569 _cleanup_close_ int fd;
570
646853bd 571 fd = mkostemp_safe(name);
bdf7026e 572 assert_se(fd >= 0);
2d78717b 573 assert_se(write(fd, env_file_3, strlen(env_file_3)) == strlen(env_file_3));
a3aa7ee6 574
aa8fbc74 575 r = load_env_file(NULL, name, &data);
bdf7026e
TA
576 assert_se(r == 0);
577 assert_se(data == NULL);
a3aa7ee6
ZJS
578}
579
d3b6d0c2 580static void test_load_env_file_4(void) {
7fd1b19b 581 _cleanup_strv_free_ char **data = NULL;
627d2bac 582 _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
2d5bdf5b 583 _cleanup_close_ int fd;
d3b6d0c2
ZJS
584 int r;
585
646853bd 586 fd = mkostemp_safe(name);
bdf7026e 587 assert_se(fd >= 0);
2d78717b 588 assert_se(write(fd, env_file_4, strlen(env_file_4)) == strlen(env_file_4));
d3b6d0c2 589
aa8fbc74 590 r = load_env_file(NULL, name, &data);
bdf7026e
TA
591 assert_se(r == 0);
592 assert_se(streq(data[0], "HWMON_MODULES=coretemp f71882fg"));
593 assert_se(streq(data[1], "MODULE_0=coretemp"));
594 assert_se(streq(data[2], "MODULE_1=f71882fg"));
595 assert_se(data[3] == NULL);
d3b6d0c2
ZJS
596}
597
58f10d40
ILG
598static void test_load_env_file_5(void) {
599 _cleanup_strv_free_ char **data = NULL;
600 int r;
601
627d2bac 602 _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
58f10d40
ILG
603 _cleanup_close_ int fd;
604
646853bd 605 fd = mkostemp_safe(name);
58f10d40 606 assert_se(fd >= 0);
2d78717b 607 assert_se(write(fd, env_file_5, strlen(env_file_5)) == strlen(env_file_5));
58f10d40 608
aa8fbc74 609 r = load_env_file(NULL, name, &data);
58f10d40
ILG
610 assert_se(r == 0);
611 assert_se(streq(data[0], "a="));
612 assert_se(streq(data[1], "b="));
613 assert_se(data[2] == NULL);
58f10d40 614}
d3b6d0c2 615
7742f7e9
ZJS
616static void test_install_printf(void) {
617 char name[] = "name.service",
79413b67
LP
618 path[] = "/run/systemd/system/name.service";
619 UnitFileInstallInfo i = { .name = name, .path = path, };
620 UnitFileInstallInfo i2 = { .name= name, .path = path, };
7742f7e9 621 char name3[] = "name@inst.service",
ad88e758 622 path3[] = "/run/systemd/system/name.service";
79413b67
LP
623 UnitFileInstallInfo i3 = { .name = name3, .path = path3, };
624 UnitFileInstallInfo i4 = { .name = name3, .path = path3, };
7742f7e9 625
b75f0c69 626 _cleanup_free_ char *mid = NULL, *bid = NULL, *host = NULL, *gid = NULL, *group = NULL, *uid = NULL, *user = NULL;
7742f7e9 627
19f6d710
LP
628 assert_se(specifier_machine_id('m', NULL, NULL, &mid) >= 0 && mid);
629 assert_se(specifier_boot_id('b', NULL, NULL, &bid) >= 0 && bid);
dcd6361e 630 assert_se(host = gethostname_malloc());
b75f0c69
DC
631 assert_se(group = gid_to_name(getgid()));
632 assert_se(asprintf(&gid, UID_FMT, getgid()) >= 0);
dcd6361e 633 assert_se(user = uid_to_name(getuid()));
79413b67 634 assert_se(asprintf(&uid, UID_FMT, getuid()) >= 0);
7742f7e9
ZJS
635
636#define expect(src, pattern, result) \
f73141d7 637 do { \
19f6d710 638 _cleanup_free_ char *t = NULL; \
7fd1b19b 639 _cleanup_free_ char \
7742f7e9 640 *d1 = strdup(i.name), \
79413b67 641 *d2 = strdup(i.path); \
19f6d710 642 assert_se(install_full_printf(&src, pattern, &t) >= 0 || !result); \
7742f7e9
ZJS
643 memzero(i.name, strlen(i.name)); \
644 memzero(i.path, strlen(i.path)); \
79413b67 645 assert_se(d1 && d2); \
7742f7e9
ZJS
646 if (result) { \
647 printf("%s\n", t); \
79413b67
LP
648 assert_se(streq(t, result)); \
649 } else assert_se(t == NULL); \
7742f7e9
ZJS
650 strcpy(i.name, d1); \
651 strcpy(i.path, d2); \
9ed794a3 652 } while (false)
7742f7e9 653
7742f7e9
ZJS
654 expect(i, "%n", "name.service");
655 expect(i, "%N", "name");
656 expect(i, "%p", "name");
657 expect(i, "%i", "");
250e9fad 658 expect(i, "%j", "name");
b75f0c69
DC
659 expect(i, "%g", group);
660 expect(i, "%G", gid);
79413b67
LP
661 expect(i, "%u", user);
662 expect(i, "%U", uid);
8fca4e30 663
7742f7e9
ZJS
664 expect(i, "%m", mid);
665 expect(i, "%b", bid);
666 expect(i, "%H", host);
667
b75f0c69
DC
668 expect(i2, "%g", group);
669 expect(i2, "%G", gid);
79413b67
LP
670 expect(i2, "%u", user);
671 expect(i2, "%U", uid);
7742f7e9
ZJS
672
673 expect(i3, "%n", "name@inst.service");
674 expect(i3, "%N", "name@inst");
675 expect(i3, "%p", "name");
b75f0c69
DC
676 expect(i3, "%g", group);
677 expect(i3, "%G", gid);
79413b67
LP
678 expect(i3, "%u", user);
679 expect(i3, "%U", uid);
8fca4e30 680
7742f7e9
ZJS
681 expect(i3, "%m", mid);
682 expect(i3, "%b", bid);
683 expect(i3, "%H", host);
684
b75f0c69
DC
685 expect(i4, "%g", group);
686 expect(i4, "%G", gid);
79413b67
LP
687 expect(i4, "%u", user);
688 expect(i4, "%U", uid);
7742f7e9 689}
b9893505 690
a8107a54
EV
691static uint64_t make_cap(int cap) {
692 return ((uint64_t) 1ULL << (uint64_t) cap);
693}
694
a103496c
IP
695static void test_config_parse_capability_set(void) {
696 /* int config_parse_capability_set(
a8107a54
EV
697 const char *unit,
698 const char *filename,
699 unsigned line,
700 const char *section,
701 unsigned section_line,
702 const char *lvalue,
703 int ltype,
704 const char *rvalue,
705 void *data,
706 void *userdata) */
707 int r;
a103496c 708 uint64_t capability_bounding_set = 0;
a8107a54 709
a103496c 710 r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
a8107a54 711 "CapabilityBoundingSet", 0, "CAP_NET_RAW",
a103496c 712 &capability_bounding_set, NULL);
a8107a54 713 assert_se(r >= 0);
a103496c 714 assert_se(capability_bounding_set == make_cap(CAP_NET_RAW));
a8107a54 715
a103496c 716 r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
a8107a54 717 "CapabilityBoundingSet", 0, "CAP_NET_ADMIN",
a103496c 718 &capability_bounding_set, NULL);
a8107a54 719 assert_se(r >= 0);
a103496c 720 assert_se(capability_bounding_set == (make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN)));
a8107a54 721
7dd09746
YW
722 r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
723 "CapabilityBoundingSet", 0, "~CAP_NET_ADMIN",
724 &capability_bounding_set, NULL);
725 assert_se(r >= 0);
726 assert_se(capability_bounding_set == make_cap(CAP_NET_RAW));
727
a103496c 728 r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
a8107a54 729 "CapabilityBoundingSet", 0, "",
a103496c 730 &capability_bounding_set, NULL);
a8107a54 731 assert_se(r >= 0);
a103496c 732 assert_se(capability_bounding_set == UINT64_C(0));
a8107a54 733
a103496c 734 r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
a8107a54 735 "CapabilityBoundingSet", 0, "~",
a103496c 736 &capability_bounding_set, NULL);
a8107a54 737 assert_se(r >= 0);
a103496c 738 assert_se(cap_test_all(capability_bounding_set));
4b03af4a 739
a103496c
IP
740 capability_bounding_set = 0;
741 r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
4b03af4a 742 "CapabilityBoundingSet", 0, " 'CAP_NET_RAW' WAT_CAP??? CAP_NET_ADMIN CAP'_trailing_garbage",
a103496c 743 &capability_bounding_set, NULL);
4b03af4a 744 assert_se(r >= 0);
a103496c 745 assert_se(capability_bounding_set == (make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN)));
a8107a54
EV
746}
747
a4c18002
LP
748static void test_config_parse_rlimit(void) {
749 struct rlimit * rl[_RLIMIT_MAX] = {};
750
4f424df7 751 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55", rl, NULL) >= 0);
a4c18002
LP
752 assert_se(rl[RLIMIT_NOFILE]);
753 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 55);
754 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
755
4f424df7 756 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55:66", rl, NULL) >= 0);
91518d20
KZ
757 assert_se(rl[RLIMIT_NOFILE]);
758 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 55);
759 assert_se(rl[RLIMIT_NOFILE]->rlim_max == 66);
760
4f424df7 761 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity", rl, NULL) >= 0);
a4c18002
LP
762 assert_se(rl[RLIMIT_NOFILE]);
763 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == RLIM_INFINITY);
764 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
765
4f424df7 766 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity:infinity", rl, NULL) >= 0);
91518d20
KZ
767 assert_se(rl[RLIMIT_NOFILE]);
768 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == RLIM_INFINITY);
769 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
770
d0a7c5f6
LP
771 rl[RLIMIT_NOFILE]->rlim_cur = 10;
772 rl[RLIMIT_NOFILE]->rlim_max = 20;
773
774 /* Invalid values don't change rl */
4f424df7 775 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "10:20:30", rl, NULL) >= 0);
0316f2ae
EV
776 assert_se(rl[RLIMIT_NOFILE]);
777 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
778 assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
779
4f424df7 780 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "wat:wat", rl, NULL) >= 0);
0316f2ae
EV
781 assert_se(rl[RLIMIT_NOFILE]);
782 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
783 assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
784
4f424df7 785 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "66:wat", rl, NULL) >= 0);
0316f2ae
EV
786 assert_se(rl[RLIMIT_NOFILE]);
787 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
788 assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
789
4f424df7 790 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "200:100", rl, NULL) >= 0);
0316f2ae
EV
791 assert_se(rl[RLIMIT_NOFILE]);
792 assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
793 assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
794
a4c18002
LP
795 rl[RLIMIT_NOFILE] = mfree(rl[RLIMIT_NOFILE]);
796
4f424df7 797 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "56", rl, NULL) >= 0);
a4c18002
LP
798 assert_se(rl[RLIMIT_CPU]);
799 assert_se(rl[RLIMIT_CPU]->rlim_cur == 56);
800 assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
801
4f424df7 802 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "57s", rl, NULL) >= 0);
a4c18002
LP
803 assert_se(rl[RLIMIT_CPU]);
804 assert_se(rl[RLIMIT_CPU]->rlim_cur == 57);
805 assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
806
4f424df7 807 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "40s:1m", rl, NULL) >= 0);
91518d20
KZ
808 assert_se(rl[RLIMIT_CPU]);
809 assert_se(rl[RLIMIT_CPU]->rlim_cur == 40);
810 assert_se(rl[RLIMIT_CPU]->rlim_max == 60);
811
4f424df7 812 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "infinity", rl, NULL) >= 0);
a4c18002
LP
813 assert_se(rl[RLIMIT_CPU]);
814 assert_se(rl[RLIMIT_CPU]->rlim_cur == RLIM_INFINITY);
815 assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
816
4f424df7 817 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "1234ms", rl, NULL) >= 0);
a4c18002
LP
818 assert_se(rl[RLIMIT_CPU]);
819 assert_se(rl[RLIMIT_CPU]->rlim_cur == 2);
820 assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
821
822 rl[RLIMIT_CPU] = mfree(rl[RLIMIT_CPU]);
823
4f424df7 824 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58", rl, NULL) >= 0);
a4c18002
LP
825 assert_se(rl[RLIMIT_RTTIME]);
826 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 58);
827 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
828
4f424df7 829 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58:60", rl, NULL) >= 0);
91518d20
KZ
830 assert_se(rl[RLIMIT_RTTIME]);
831 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 58);
832 assert_se(rl[RLIMIT_RTTIME]->rlim_max == 60);
833
4f424df7 834 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s", rl, NULL) >= 0);
a4c18002
LP
835 assert_se(rl[RLIMIT_RTTIME]);
836 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 59 * USEC_PER_SEC);
837 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
838
4f424df7 839 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s:123s", rl, NULL) >= 0);
91518d20
KZ
840 assert_se(rl[RLIMIT_RTTIME]);
841 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 59 * USEC_PER_SEC);
842 assert_se(rl[RLIMIT_RTTIME]->rlim_max == 123 * USEC_PER_SEC);
843
4f424df7 844 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity", rl, NULL) >= 0);
a4c18002
LP
845 assert_se(rl[RLIMIT_RTTIME]);
846 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == RLIM_INFINITY);
847 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
848
4f424df7 849 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity:infinity", rl, NULL) >= 0);
91518d20
KZ
850 assert_se(rl[RLIMIT_RTTIME]);
851 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == RLIM_INFINITY);
852 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
853
4f424df7 854 assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "2345ms", rl, NULL) >= 0);
a4c18002
LP
855 assert_se(rl[RLIMIT_RTTIME]);
856 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 2345 * USEC_PER_MSEC);
857 assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
858
859 rl[RLIMIT_RTTIME] = mfree(rl[RLIMIT_RTTIME]);
860}
861
4ad4beec
EV
862static void test_config_parse_pass_environ(void) {
863 /* int config_parse_pass_environ(
864 const char *unit,
865 const char *filename,
866 unsigned line,
867 const char *section,
868 unsigned section_line,
869 const char *lvalue,
870 int ltype,
871 const char *rvalue,
872 void *data,
873 void *userdata) */
874 int r;
875 _cleanup_strv_free_ char **passenv = NULL;
876
877 r = config_parse_pass_environ(NULL, "fake", 1, "section", 1,
878 "PassEnvironment", 0, "A B",
879 &passenv, NULL);
880 assert_se(r >= 0);
881 assert_se(strv_length(passenv) == 2);
882 assert_se(streq(passenv[0], "A"));
883 assert_se(streq(passenv[1], "B"));
884
885 r = config_parse_pass_environ(NULL, "fake", 1, "section", 1,
886 "PassEnvironment", 0, "",
887 &passenv, NULL);
888 assert_se(r >= 0);
889 assert_se(strv_isempty(passenv));
890
891 r = config_parse_pass_environ(NULL, "fake", 1, "section", 1,
892 "PassEnvironment", 0, "'invalid name' 'normal_name' A=1 \\",
893 &passenv, NULL);
894 assert_se(r >= 0);
895 assert_se(strv_length(passenv) == 1);
896 assert_se(streq(passenv[0], "normal_name"));
897
898}
899
0c700d39
EV
900static void test_unit_dump_config_items(void) {
901 unit_dump_config_items(stdout);
902}
903
2c5417ad 904int main(int argc, char *argv[]) {
f942504e 905 _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
751e7576 906 int r;
2c5417ad 907
6d7c4033 908 test_setup_logging(LOG_INFO);
c1b6628d 909
651d47d1 910 r = enter_cgroup_subroot();
317bb217
ZJS
911 if (r == -ENOMEDIUM)
912 return log_tests_skipped("cgroupfs not available");
8c759b33 913
d2120590
LP
914 assert_se(runtime_dir = setup_fake_runtime_dir());
915
751e7576 916 r = test_unit_file_get_set();
2c5417ad 917 test_config_parse_exec();
88bff424 918 test_config_parse_log_extra_fields();
a103496c 919 test_config_parse_capability_set();
a4c18002 920 test_config_parse_rlimit();
4ad4beec 921 test_config_parse_pass_environ();
b9893505
ZJS
922 test_load_env_file_1();
923 test_load_env_file_2();
a3aa7ee6 924 test_load_env_file_3();
d3b6d0c2 925 test_load_env_file_4();
58f10d40 926 test_load_env_file_5();
143bfdaf 927 TEST_REQ_RUNNING_SYSTEMD(test_install_printf());
0c700d39 928 test_unit_dump_config_items();
b5b46d59 929
751e7576 930 return r;
b5b46d59 931}