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