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