]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/test/test-unit-file.c
Merge pull request #2495 from heftig/master
[thirdparty/systemd.git] / src / test / test-unit-file.c
CommitLineData
b5b46d59
LP
1/***
2 This file is part of systemd.
3
4 Copyright 2012 Lennart Poettering
b9893505 5 Copyright 2013 Zbigniew Jędrzejewski-Szmek
b5b46d59
LP
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
07630cea 21#include <fcntl.h>
b5b46d59 22#include <stddef.h>
07630cea 23#include <stdio.h>
b5b46d59 24#include <string.h>
a8107a54 25#include <sys/capability.h>
b9893505 26#include <unistd.h>
b5b46d59 27
b5efdb8a 28#include "alloc-util.h"
a103496c 29#include "capability-util.h"
3ffd4af2 30#include "fd-util.h"
07630cea 31#include "fileio.h"
b5b46d59 32#include "hashmap.h"
07630cea
LP
33#include "hostname-util.h"
34#include "install-printf.h"
35#include "install.h"
2c5417ad 36#include "load-fragment.h"
07630cea
LP
37#include "macro.h"
38#include "specifier.h"
39#include "string-util.h"
b9893505 40#include "strv.h"
143bfdaf 41#include "test-helper.h"
79413b67 42#include "user-util.h"
07630cea 43#include "util.h"
b5b46d59 44
751e7576 45static int test_unit_file_get_set(void) {
b5b46d59
LP
46 int r;
47 Hashmap *h;
48 Iterator i;
49 UnitFileList *p;
50
d5099efc 51 h = hashmap_new(&string_hash_ops);
bdf7026e 52 assert_se(h);
b5b46d59
LP
53
54 r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h);
552c693e
CR
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
751e7576
CH
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;
b5b46d59
LP
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);
751e7576
CH
70
71 return 0;
2c5417ad
ZJS
72}
73
74static void check_execcommand(ExecCommand *c,
75 const char* path,
76 const char* argv0,
77 const char* argv1,
503dbda6 78 const char* argv2,
2c5417ad 79 bool ignore) {
4d8629de
ZJS
80 size_t n;
81
2c5417ad 82 assert_se(c);
c8539536
ZJS
83 log_info("expect: \"%s\" [\"%s\" \"%s\" \"%s\"]",
84 path, argv0 ?: path, argv1, argv2);
4d8629de 85 n = strv_length(c->argv);
c8539536 86 log_info("actual: \"%s\" [\"%s\" \"%s\" \"%s\"]",
4d8629de 87 c->path, c->argv[0], n > 0 ? c->argv[1] : NULL, n > 1 ? c->argv[2] : NULL);
2c5417ad 88 assert_se(streq(c->path, path));
c8539536 89 assert_se(streq(c->argv[0], argv0 ?: path));
4d8629de
ZJS
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));
2c5417ad
ZJS
94 assert_se(c->ignore == ignore);
95}
96
97static void test_config_parse_exec(void) {
c8539536 98 /* int config_parse_exec(
470dca63 99 const char *unit,
c8539536
ZJS
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) */
2c5417ad
ZJS
109 int r;
110
111 ExecCommand *c = NULL, *c1;
c8539536 112 const char *ccc;
139891f0
WC
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)));
2c5417ad 126
c8539536 127 log_info("/* basic test */");
71a61510 128 r = config_parse_exec(NULL, "fake", 1, "section", 1,
2c5417ad 129 "LValue", 0, "/RValue r1",
139891f0 130 &c, u);
2c5417ad 131 assert_se(r >= 0);
503dbda6 132 check_execcommand(c, "/RValue", "/RValue", "r1", NULL, false);
2c5417ad 133
71a61510 134 r = config_parse_exec(NULL, "fake", 2, "section", 1,
c8539536 135 "LValue", 0, "/RValue///slashes r1///",
139891f0 136 &c, u);
c8539536
ZJS
137
138 log_info("/* test slashes */");
2c5417ad
ZJS
139 assert_se(r >= 0);
140 c1 = c->command_next;
c8539536 141 check_execcommand(c1, "/RValue/slashes", "/RValue///slashes", "r1///", NULL, false);
2c5417ad 142
c8539536
ZJS
143 log_info("/* trailing slash */");
144 r = config_parse_exec(NULL, "fake", 4, "section", 1,
145 "LValue", 0, "/RValue/ argv0 r1",
139891f0 146 &c, u);
c8539536
ZJS
147 assert_se(r == 0);
148 assert_se(c1->command_next == NULL);
149
150 log_info("/* honour_argv0 */");
71a61510 151 r = config_parse_exec(NULL, "fake", 3, "section", 1,
c8539536 152 "LValue", 0, "@/RValue///slashes2 ///argv0 r1",
139891f0 153 &c, u);
2c5417ad
ZJS
154 assert_se(r >= 0);
155 c1 = c1->command_next;
c8539536 156 check_execcommand(c1, "/RValue/slashes2", "///argv0", "r1", NULL, false);
2c5417ad 157
e01ff428
ZJS
158 log_info("/* honour_argv0, no args */");
159 r = config_parse_exec(NULL, "fake", 3, "section", 1,
160 "LValue", 0, "@/RValue",
139891f0 161 &c, u);
e01ff428
ZJS
162 assert_se(r == 0);
163 assert_se(c1->command_next == NULL);
164
c83f1f30 165 log_info("/* no command, whitespace only, reset */");
e01ff428
ZJS
166 r = config_parse_exec(NULL, "fake", 3, "section", 1,
167 "LValue", 0, " ",
139891f0 168 &c, u);
e01ff428 169 assert_se(r == 0);
c83f1f30 170 assert_se(c == NULL);
e01ff428 171
c8539536 172 log_info("/* ignore && honour_argv0 */");
71a61510 173 r = config_parse_exec(NULL, "fake", 4, "section", 1,
c8539536 174 "LValue", 0, "-@/RValue///slashes3 argv0a r1",
139891f0 175 &c, u);
2c5417ad 176 assert_se(r >= 0);
c83f1f30 177 c1 = c;
503dbda6 178 check_execcommand(c1, "/RValue/slashes3", "argv0a", "r1", NULL, true);
2c5417ad 179
c8539536 180 log_info("/* ignore && honour_argv0 */");
71a61510 181 r = config_parse_exec(NULL, "fake", 4, "section", 1,
c8539536 182 "LValue", 0, "@-/RValue///slashes4 argv0b r1",
139891f0 183 &c, u);
0f67f1ef
ZJS
184 assert_se(r >= 0);
185 c1 = c1->command_next;
503dbda6 186 check_execcommand(c1, "/RValue/slashes4", "argv0b", "r1", NULL, true);
0f67f1ef 187
c8539536 188 log_info("/* ignore && ignore */");
71a61510 189 r = config_parse_exec(NULL, "fake", 4, "section", 1,
0f67f1ef 190 "LValue", 0, "--/RValue argv0 r1",
139891f0 191 &c, u);
0f67f1ef
ZJS
192 assert_se(r == 0);
193 assert_se(c1->command_next == NULL);
194
c8539536 195 log_info("/* ignore && ignore (2) */");
71a61510 196 r = config_parse_exec(NULL, "fake", 4, "section", 1,
0f67f1ef 197 "LValue", 0, "-@-/RValue argv0 r1",
139891f0 198 &c, u);
0f67f1ef
ZJS
199 assert_se(r == 0);
200 assert_se(c1->command_next == NULL);
201
c8539536 202 log_info("/* semicolon */");
71a61510 203 r = config_parse_exec(NULL, "fake", 5, "section", 1,
2c5417ad
ZJS
204 "LValue", 0,
205 "-@/RValue argv0 r1 ; "
206 "/goo/goo boo",
139891f0 207 &c, u);
2c5417ad
ZJS
208 assert_se(r >= 0);
209 c1 = c1->command_next;
503dbda6 210 check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
2c5417ad
ZJS
211
212 c1 = c1->command_next;
c8539536 213 check_execcommand(c1, "/goo/goo", NULL, "boo", NULL, false);
2c5417ad 214
0e9800d5
FB
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",
139891f0 220 &c, u);
0e9800d5
FB
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
c8539536 228 log_info("/* trailing semicolon */");
71a61510 229 r = config_parse_exec(NULL, "fake", 5, "section", 1,
2c5417ad
ZJS
230 "LValue", 0,
231 "-@/RValue argv0 r1 ; ",
139891f0 232 &c, u);
2c5417ad
ZJS
233 assert_se(r >= 0);
234 c1 = c1->command_next;
503dbda6 235 check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
2c5417ad
ZJS
236
237 assert_se(c1->command_next == NULL);
238
0e9800d5
FB
239 log_info("/* trailing semicolon, no whitespace */");
240 r = config_parse_exec(NULL, "fake", 5, "section", 1,
241 "LValue", 0,
242 "-@/RValue argv0 r1 ;",
139891f0 243 &c, u);
0e9800d5
FB
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 ';'",
139891f0 254 &c, u);
0e9800d5
FB
255 assert_se(r >= 0);
256 c1 = c1->command_next;
46a0d98a 257 check_execcommand(c1, "/RValue", "argv0", "r1", ";", true);
0e9800d5 258
c8539536 259 log_info("/* escaped semicolon */");
71a61510 260 r = config_parse_exec(NULL, "fake", 5, "section", 1,
7e1a84f5 261 "LValue", 0,
503dbda6 262 "/bin/find \\;",
139891f0 263 &c, u);
503dbda6
ZJS
264 assert_se(r >= 0);
265 c1 = c1->command_next;
c8539536 266 check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
503dbda6 267
c8539536 268 log_info("/* escaped semicolon with following arg */");
503dbda6
ZJS
269 r = config_parse_exec(NULL, "fake", 5, "section", 1,
270 "LValue", 0,
0e9800d5 271 "/sbin/find \\; /x",
139891f0 272 &c, u);
0e9800d5
FB
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",
139891f0 282 &c, u);
7e1a84f5
OS
283 assert_se(r >= 0);
284 c1 = c1->command_next;
285 check_execcommand(c1,
0e9800d5 286 "/sbin/find", NULL, "\\;x", NULL, false);
c8539536 287
80979f1c
DM
288 log_info("/* encoded semicolon */");
289 r = config_parse_exec(NULL, "fake", 5, "section", 1,
290 "LValue", 0,
291 "/bin/find \\073",
139891f0 292 &c, u);
80979f1c
DM
293 assert_se(r >= 0);
294 c1 = c1->command_next;
ce54255f 295 check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
80979f1c 296
0e9800d5
FB
297 log_info("/* quoted semicolon */");
298 r = config_parse_exec(NULL, "fake", 5, "section", 1,
299 "LValue", 0,
300 "/bin/find \";\"",
139891f0 301 &c, u);
0e9800d5
FB
302 assert_se(r >= 0);
303 c1 = c1->command_next;
46a0d98a 304 check_execcommand(c1, "/bin/find", NULL, ";", NULL, false);
0e9800d5
FB
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",
139891f0 310 &c, u);
0e9800d5
FB
311 assert_se(r >= 0);
312 c1 = c1->command_next;
313 check_execcommand(c1,
46a0d98a 314 "/sbin/find", NULL, ";", "/x", false);
0e9800d5 315
c8539536
ZJS
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",
139891f0 320 &c, u);
c8539536
ZJS
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\"",
139891f0 330 &c, u);
c8539536
ZJS
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'",
139891f0 340 &c, u);
c8539536
ZJS
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'",
139891f0 350 &c, u);
c8539536
ZJS
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\"",
139891f0 360 &c, u);
c8539536
ZJS
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,
139891f0 374 &c, u);
c8539536
ZJS
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",
139891f0 382 &c, u);
c8539536
ZJS
383 assert_se(r >= 0);
384 c1 = c1->command_next;
385 check_execcommand(c1, "/path ", NULL, NULL, NULL, false);
386
80979f1c
DM
387 log_info("/* quoted backslashes */");
388 r = config_parse_exec(NULL, "fake", 5, "section", 1,
389 "LValue", 0,
390 "/bin/grep '\\w+\\K'",
139891f0 391 &c, u);
80979f1c
DM
392 assert_se(r >= 0);
393 c1 = c1->command_next;
394 check_execcommand(c1, "/bin/grep", NULL, "\\w+\\K", NULL, false);
395
396
c8539536
ZJS
397 log_info("/* trailing backslash: \\ */");
398 /* backslash is invalid */
399 r = config_parse_exec(NULL, "fake", 4, "section", 1,
400 "LValue", 0, "/path\\",
139891f0 401 &c, u);
c8539536
ZJS
402 assert_se(r == 0);
403 assert_se(c1->command_next == NULL);
7e1a84f5 404
470dca63
MP
405 log_info("/* missing ending ' */");
406 r = config_parse_exec(NULL, "fake", 4, "section", 1,
407 "LValue", 0, "/path 'foo",
139891f0 408 &c, u);
470dca63
MP
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\\",
139891f0 415 &c, u);
470dca63
MP
416 assert_se(r == 0);
417 assert_se(c1->command_next == NULL);
418
35b1078e
MP
419 log_info("/* invalid space between modifiers */");
420 r = config_parse_exec(NULL, "fake", 4, "section", 1,
421 "LValue", 0, "- /path",
139891f0 422 &c, u);
35b1078e
MP
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, "-",
139891f0 429 &c, u);
35b1078e
MP
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, "",
139891f0 436 &c, u);
35b1078e
MP
437 assert_se(r == 0);
438 assert_se(c == NULL);
439
2c5417ad 440 exec_command_free_list(c);
139891f0
WC
441
442 unit_free(u);
443 manager_free(m);
2c5417ad
ZJS
444}
445
f73141d7
LP
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"
b9893505 459
a3aa7ee6
ZJS
460#define env_file_3 \
461 "#SPAMD_ARGS=\"-d --socketpath=/var/lib/bulwark/spamd \\\n" \
462 "#--nouser-config \\\n" \
463 "normal=line"
464
d3b6d0c2
ZJS
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
58f10d40
ILG
475#define env_file_5 \
476 "a=\n" \
477 "b="
d3b6d0c2 478
b9893505 479static void test_load_env_file_1(void) {
7fd1b19b 480 _cleanup_strv_free_ char **data = NULL;
b9893505
ZJS
481 int r;
482
483 char name[] = "/tmp/test-load-env-file.XXXXXX";
2d5bdf5b
LP
484 _cleanup_close_ int fd;
485
486 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
bdf7026e 487 assert_se(fd >= 0);
b9893505
ZJS
488 assert_se(write(fd, env_file_1, sizeof(env_file_1)) == sizeof(env_file_1));
489
717603e3 490 r = load_env_file(NULL, name, NULL, &data);
bdf7026e
TA
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);
b9893505
ZJS
499 unlink(name);
500}
501
502static void test_load_env_file_2(void) {
7fd1b19b 503 _cleanup_strv_free_ char **data = NULL;
b9893505
ZJS
504 int r;
505
506 char name[] = "/tmp/test-load-env-file.XXXXXX";
2d5bdf5b
LP
507 _cleanup_close_ int fd;
508
509 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
bdf7026e 510 assert_se(fd >= 0);
b9893505
ZJS
511 assert_se(write(fd, env_file_2, sizeof(env_file_2)) == sizeof(env_file_2));
512
717603e3 513 r = load_env_file(NULL, name, NULL, &data);
bdf7026e
TA
514 assert_se(r == 0);
515 assert_se(streq(data[0], "a=a"));
516 assert_se(data[1] == NULL);
b9893505
ZJS
517 unlink(name);
518}
519
a3aa7ee6 520static void test_load_env_file_3(void) {
7fd1b19b 521 _cleanup_strv_free_ char **data = NULL;
a3aa7ee6
ZJS
522 int r;
523
524 char name[] = "/tmp/test-load-env-file.XXXXXX";
2d5bdf5b
LP
525 _cleanup_close_ int fd;
526
527 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
bdf7026e 528 assert_se(fd >= 0);
a3aa7ee6
ZJS
529 assert_se(write(fd, env_file_3, sizeof(env_file_3)) == sizeof(env_file_3));
530
717603e3 531 r = load_env_file(NULL, name, NULL, &data);
bdf7026e
TA
532 assert_se(r == 0);
533 assert_se(data == NULL);
a3aa7ee6
ZJS
534 unlink(name);
535}
536
d3b6d0c2 537static void test_load_env_file_4(void) {
7fd1b19b 538 _cleanup_strv_free_ char **data = NULL;
2d5bdf5b
LP
539 char name[] = "/tmp/test-load-env-file.XXXXXX";
540 _cleanup_close_ int fd;
d3b6d0c2
ZJS
541 int r;
542
2d5bdf5b 543 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
bdf7026e 544 assert_se(fd >= 0);
d3b6d0c2
ZJS
545 assert_se(write(fd, env_file_4, sizeof(env_file_4)) == sizeof(env_file_4));
546
717603e3 547 r = load_env_file(NULL, name, NULL, &data);
bdf7026e
TA
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);
d3b6d0c2
ZJS
553 unlink(name);
554}
555
58f10d40
ILG
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}
d3b6d0c2 574
7742f7e9
ZJS
575static void test_install_printf(void) {
576 char name[] = "name.service",
79413b67
LP
577 path[] = "/run/systemd/system/name.service";
578 UnitFileInstallInfo i = { .name = name, .path = path, };
579 UnitFileInstallInfo i2 = { .name= name, .path = path, };
7742f7e9 580 char name3[] = "name@inst.service",
ad88e758 581 path3[] = "/run/systemd/system/name.service";
79413b67
LP
582 UnitFileInstallInfo i3 = { .name = name3, .path = path3, };
583 UnitFileInstallInfo i4 = { .name = name3, .path = path3, };
7742f7e9 584
79413b67 585 _cleanup_free_ char *mid = NULL, *bid = NULL, *host = NULL, *uid = NULL, *user = NULL;
7742f7e9 586
19f6d710
LP
587 assert_se(specifier_machine_id('m', NULL, NULL, &mid) >= 0 && mid);
588 assert_se(specifier_boot_id('b', NULL, NULL, &bid) >= 0 && bid);
7742f7e9 589 assert_se((host = gethostname_malloc()));
79413b67
LP
590 assert_se((user = getusername_malloc()));
591 assert_se(asprintf(&uid, UID_FMT, getuid()) >= 0);
7742f7e9
ZJS
592
593#define expect(src, pattern, result) \
f73141d7 594 do { \
19f6d710 595 _cleanup_free_ char *t = NULL; \
7fd1b19b 596 _cleanup_free_ char \
7742f7e9 597 *d1 = strdup(i.name), \
79413b67 598 *d2 = strdup(i.path); \
19f6d710 599 assert_se(install_full_printf(&src, pattern, &t) >= 0 || !result); \
7742f7e9
ZJS
600 memzero(i.name, strlen(i.name)); \
601 memzero(i.path, strlen(i.path)); \
79413b67 602 assert_se(d1 && d2); \
7742f7e9
ZJS
603 if (result) { \
604 printf("%s\n", t); \
79413b67
LP
605 assert_se(streq(t, result)); \
606 } else assert_se(t == NULL); \
7742f7e9
ZJS
607 strcpy(i.name, d1); \
608 strcpy(i.path, d2); \
f73141d7 609 } while(false)
7742f7e9 610
7742f7e9
ZJS
611 expect(i, "%n", "name.service");
612 expect(i, "%N", "name");
613 expect(i, "%p", "name");
614 expect(i, "%i", "");
79413b67
LP
615 expect(i, "%u", user);
616 expect(i, "%U", uid);
8fca4e30 617
7742f7e9
ZJS
618 expect(i, "%m", mid);
619 expect(i, "%b", bid);
620 expect(i, "%H", host);
621
79413b67
LP
622 expect(i2, "%u", user);
623 expect(i2, "%U", uid);
7742f7e9
ZJS
624
625 expect(i3, "%n", "name@inst.service");
626 expect(i3, "%N", "name@inst");
627 expect(i3, "%p", "name");
79413b67
LP
628 expect(i3, "%u", user);
629 expect(i3, "%U", uid);
8fca4e30 630
7742f7e9
ZJS
631 expect(i3, "%m", mid);
632 expect(i3, "%b", bid);
633 expect(i3, "%H", host);
634
79413b67
LP
635 expect(i4, "%u", user);
636 expect(i4, "%U", uid);
7742f7e9 637}
b9893505 638
a8107a54
EV
639static uint64_t make_cap(int cap) {
640 return ((uint64_t) 1ULL << (uint64_t) cap);
641}
642
a103496c
IP
643static void test_config_parse_capability_set(void) {
644 /* int config_parse_capability_set(
a8107a54
EV
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;
a103496c 656 uint64_t capability_bounding_set = 0;
a8107a54 657
a103496c 658 r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
a8107a54 659 "CapabilityBoundingSet", 0, "CAP_NET_RAW",
a103496c 660 &capability_bounding_set, NULL);
a8107a54 661 assert_se(r >= 0);
a103496c 662 assert_se(capability_bounding_set == make_cap(CAP_NET_RAW));
a8107a54 663
a103496c 664 r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
a8107a54 665 "CapabilityBoundingSet", 0, "CAP_NET_ADMIN",
a103496c 666 &capability_bounding_set, NULL);
a8107a54 667 assert_se(r >= 0);
a103496c 668 assert_se(capability_bounding_set == (make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN)));
a8107a54 669
a103496c 670 r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
a8107a54 671 "CapabilityBoundingSet", 0, "",
a103496c 672 &capability_bounding_set, NULL);
a8107a54 673 assert_se(r >= 0);
a103496c 674 assert_se(capability_bounding_set == UINT64_C(0));
a8107a54 675
a103496c 676 r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
a8107a54 677 "CapabilityBoundingSet", 0, "~",
a103496c 678 &capability_bounding_set, NULL);
a8107a54 679 assert_se(r >= 0);
a103496c 680 assert_se(cap_test_all(capability_bounding_set));
4b03af4a 681
a103496c
IP
682 capability_bounding_set = 0;
683 r = config_parse_capability_set(NULL, "fake", 1, "section", 1,
4b03af4a 684 "CapabilityBoundingSet", 0, " 'CAP_NET_RAW' WAT_CAP??? CAP_NET_ADMIN CAP'_trailing_garbage",
a103496c 685 &capability_bounding_set, NULL);
4b03af4a 686 assert_se(r >= 0);
a103496c 687 assert_se(capability_bounding_set == (make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN)));
a8107a54
EV
688}
689
a4c18002
LP
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
91518d20
KZ
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
a4c18002
LP
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
91518d20
KZ
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
d0a7c5f6
LP
713 rl[RLIMIT_NOFILE]->rlim_cur = 10;
714 rl[RLIMIT_NOFILE]->rlim_max = 20;
715
716 /* Invalid values don't change rl */
0316f2ae
EV
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
0316f2ae
EV
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
a4c18002
LP
737 rl[RLIMIT_NOFILE] = mfree(rl[RLIMIT_NOFILE]);
738
d0a7c5f6 739 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "56", rl, NULL) >= 0);
a4c18002
LP
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
d0a7c5f6 744 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "57s", rl, NULL) >= 0);
a4c18002
LP
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
d0a7c5f6 749 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "40s:1m", rl, NULL) >= 0);
91518d20
KZ
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
d0a7c5f6 754 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "infinity", rl, NULL) >= 0);
a4c18002
LP
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
d0a7c5f6 759 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "1234ms", rl, NULL) >= 0);
a4c18002
LP
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
d0a7c5f6 766 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58", rl, NULL) >= 0);
a4c18002
LP
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
d0a7c5f6 771 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58:60", rl, NULL) >= 0);
91518d20
KZ
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
d0a7c5f6 776 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s", rl, NULL) >= 0);
a4c18002
LP
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
d0a7c5f6 781 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s:123s", rl, NULL) >= 0);
91518d20
KZ
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
d0a7c5f6 786 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity", rl, NULL) >= 0);
a4c18002
LP
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
d0a7c5f6 791 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity:infinity", rl, NULL) >= 0);
91518d20
KZ
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
d0a7c5f6 796 assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "2345ms", rl, NULL) >= 0);
a4c18002
LP
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
4ad4beec
EV
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
2c5417ad 842int main(int argc, char *argv[]) {
751e7576 843 int r;
2c5417ad 844
c1b6628d
ZJS
845 log_parse_environment();
846 log_open();
847
751e7576 848 r = test_unit_file_get_set();
2c5417ad 849 test_config_parse_exec();
a103496c 850 test_config_parse_capability_set();
a4c18002 851 test_config_parse_rlimit();
4ad4beec 852 test_config_parse_pass_environ();
b9893505
ZJS
853 test_load_env_file_1();
854 test_load_env_file_2();
a3aa7ee6 855 test_load_env_file_3();
d3b6d0c2 856 test_load_env_file_4();
58f10d40 857 test_load_env_file_5();
143bfdaf 858 TEST_REQ_RUNNING_SYSTEMD(test_install_printf());
b5b46d59 859
751e7576 860 return r;
b5b46d59 861}