]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/test/test-unit-file.c
machinectl: show /etc/os-release information of container in status output
[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
23#include <assert.h>
24#include <stdio.h>
25#include <stddef.h>
26#include <string.h>
b9893505 27#include <unistd.h>
2d5bdf5b 28#include <fcntl.h>
b5b46d59
LP
29
30#include "install.h"
7742f7e9
ZJS
31#include "install-printf.h"
32#include "specifier.h"
b5b46d59
LP
33#include "util.h"
34#include "macro.h"
35#include "hashmap.h"
2c5417ad 36#include "load-fragment.h"
b9893505 37#include "strv.h"
a5c32cff 38#include "fileio.h"
143bfdaf 39#include "test-helper.h"
b5b46d59 40
751e7576 41static int test_unit_file_get_set(void) {
b5b46d59
LP
42 int r;
43 Hashmap *h;
44 Iterator i;
45 UnitFileList *p;
46
47 h = hashmap_new(string_hash_func, string_compare_func);
48 assert(h);
49
50 r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h);
552c693e
CR
51
52 if (r == -EPERM || r == -EACCES) {
53 printf("Skipping test: unit_file_get_list: %s", strerror(-r));
54 return EXIT_TEST_SKIP;
55 }
56
751e7576
CH
57 log_full(r == 0 ? LOG_INFO : LOG_ERR,
58 "unit_file_get_list: %s", strerror(-r));
59 if (r < 0)
60 return EXIT_FAILURE;
b5b46d59
LP
61
62 HASHMAP_FOREACH(p, h, i)
63 printf("%s = %s\n", p->path, unit_file_state_to_string(p->state));
64
65 unit_file_list_free(h);
751e7576
CH
66
67 return 0;
2c5417ad
ZJS
68}
69
70static void check_execcommand(ExecCommand *c,
71 const char* path,
72 const char* argv0,
73 const char* argv1,
74 bool ignore) {
75 assert_se(c);
76 log_info("%s %s %s %s",
77 c->path, c->argv[0], c->argv[1], c->argv[2]);
78 assert_se(streq(c->path, path));
79 assert_se(streq(c->argv[0], argv0));
80 assert_se(streq(c->argv[1], argv1));
81 assert_se(c->argv[2] == NULL);
82 assert_se(c->ignore == ignore);
83}
84
85static void test_config_parse_exec(void) {
86 /* int config_parse_exec( */
87 /* const char *filename, */
88 /* unsigned line, */
89 /* const char *section, */
71a61510 90 /* unsigned section_line, */
2c5417ad
ZJS
91 /* const char *lvalue, */
92 /* int ltype, */
93 /* const char *rvalue, */
94 /* void *data, */
95 /* void *userdata) */
96 int r;
97
98 ExecCommand *c = NULL, *c1;
99
100 /* basic test */
71a61510 101 r = config_parse_exec(NULL, "fake", 1, "section", 1,
2c5417ad
ZJS
102 "LValue", 0, "/RValue r1",
103 &c, NULL);
104 assert_se(r >= 0);
105 check_execcommand(c, "/RValue", "/RValue", "r1", false);
106
71a61510 107 r = config_parse_exec(NULL, "fake", 2, "section", 1,
2c5417ad
ZJS
108 "LValue", 0, "/RValue///slashes/// r1",
109 &c, NULL);
110 /* test slashes */
111 assert_se(r >= 0);
112 c1 = c->command_next;
113 check_execcommand(c1, "/RValue/slashes", "/RValue///slashes///",
114 "r1", false);
115
116 /* honour_argv0 */
71a61510 117 r = config_parse_exec(NULL, "fake", 3, "section", 1,
2c5417ad
ZJS
118 "LValue", 0, "@/RValue///slashes2/// argv0 r1",
119 &c, NULL);
120 assert_se(r >= 0);
121 c1 = c1->command_next;
122 check_execcommand(c1, "/RValue/slashes2", "argv0", "r1", false);
123
124 /* ignore && honour_argv0 */
71a61510 125 r = config_parse_exec(NULL, "fake", 4, "section", 1,
2c5417ad
ZJS
126 "LValue", 0, "-@/RValue///slashes3/// argv0a r1",
127 &c, NULL);
128 assert_se(r >= 0);
129 c1 = c1->command_next;
130 check_execcommand(c1,
131 "/RValue/slashes3", "argv0a", "r1", true);
132
0f67f1ef 133 /* ignore && honour_argv0 */
71a61510 134 r = config_parse_exec(NULL, "fake", 4, "section", 1,
0f67f1ef
ZJS
135 "LValue", 0, "@-/RValue///slashes4/// argv0b r1",
136 &c, NULL);
137 assert_se(r >= 0);
138 c1 = c1->command_next;
139 check_execcommand(c1,
140 "/RValue/slashes4", "argv0b", "r1", true);
141
142 /* ignore && ignore */
71a61510 143 r = config_parse_exec(NULL, "fake", 4, "section", 1,
0f67f1ef
ZJS
144 "LValue", 0, "--/RValue argv0 r1",
145 &c, NULL);
146 assert_se(r == 0);
147 assert_se(c1->command_next == NULL);
148
149 /* ignore && ignore */
71a61510 150 r = config_parse_exec(NULL, "fake", 4, "section", 1,
0f67f1ef
ZJS
151 "LValue", 0, "-@-/RValue argv0 r1",
152 &c, NULL);
153 assert_se(r == 0);
154 assert_se(c1->command_next == NULL);
155
2c5417ad 156 /* semicolon */
71a61510 157 r = config_parse_exec(NULL, "fake", 5, "section", 1,
2c5417ad
ZJS
158 "LValue", 0,
159 "-@/RValue argv0 r1 ; "
160 "/goo/goo boo",
161 &c, NULL);
162 assert_se(r >= 0);
163 c1 = c1->command_next;
164 check_execcommand(c1,
165 "/RValue", "argv0", "r1", true);
166
167 c1 = c1->command_next;
168 check_execcommand(c1,
169 "/goo/goo", "/goo/goo", "boo", false);
170
171 /* trailing semicolon */
71a61510 172 r = config_parse_exec(NULL, "fake", 5, "section", 1,
2c5417ad
ZJS
173 "LValue", 0,
174 "-@/RValue argv0 r1 ; ",
175 &c, NULL);
176 assert_se(r >= 0);
177 c1 = c1->command_next;
178 check_execcommand(c1,
179 "/RValue", "argv0", "r1", true);
180
181 assert_se(c1->command_next == NULL);
182
7e1a84f5 183 /* escaped semicolon */
71a61510 184 r = config_parse_exec(NULL, "fake", 5, "section", 1,
7e1a84f5
OS
185 "LValue", 0,
186 "/usr/bin/find \\;",
187 &c, NULL);
188 assert_se(r >= 0);
189 c1 = c1->command_next;
190 check_execcommand(c1,
191 "/usr/bin/find", "/usr/bin/find", ";", false);
192
2c5417ad
ZJS
193 exec_command_free_list(c);
194}
195
f73141d7
LP
196#define env_file_1 \
197 "a=a\n" \
198 "b=b\\\n" \
199 "c\n" \
200 "d=d\\\n" \
201 "e\\\n" \
202 "f\n" \
203 "g=g\\ \n" \
204 "h=h\n" \
205 "i=i\\"
206
207#define env_file_2 \
208 "a=a\\\n"
b9893505 209
a3aa7ee6
ZJS
210#define env_file_3 \
211 "#SPAMD_ARGS=\"-d --socketpath=/var/lib/bulwark/spamd \\\n" \
212 "#--nouser-config \\\n" \
213 "normal=line"
214
d3b6d0c2
ZJS
215#define env_file_4 \
216 "# Generated\n" \
217 "\n" \
218 "HWMON_MODULES=\"coretemp f71882fg\"\n" \
219 "\n" \
220 "# For compatibility reasons\n" \
221 "\n" \
222 "MODULE_0=coretemp\n" \
223 "MODULE_1=f71882fg"
224
225
b9893505 226static void test_load_env_file_1(void) {
7fd1b19b 227 _cleanup_strv_free_ char **data = NULL;
b9893505
ZJS
228 int r;
229
230 char name[] = "/tmp/test-load-env-file.XXXXXX";
2d5bdf5b
LP
231 _cleanup_close_ int fd;
232
233 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
b9893505
ZJS
234 assert(fd >= 0);
235 assert_se(write(fd, env_file_1, sizeof(env_file_1)) == sizeof(env_file_1));
236
717603e3 237 r = load_env_file(NULL, name, NULL, &data);
b9893505 238 assert(r == 0);
f73141d7
LP
239 assert(streq(data[0], "a=a"));
240 assert(streq(data[1], "b=bc"));
241 assert(streq(data[2], "d=def"));
242 assert(streq(data[3], "g=g "));
243 assert(streq(data[4], "h=h"));
244 assert(streq(data[5], "i=i"));
b9893505
ZJS
245 assert(data[6] == NULL);
246 unlink(name);
247}
248
249static void test_load_env_file_2(void) {
7fd1b19b 250 _cleanup_strv_free_ char **data = NULL;
b9893505
ZJS
251 int r;
252
253 char name[] = "/tmp/test-load-env-file.XXXXXX";
2d5bdf5b
LP
254 _cleanup_close_ int fd;
255
256 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
b9893505
ZJS
257 assert(fd >= 0);
258 assert_se(write(fd, env_file_2, sizeof(env_file_2)) == sizeof(env_file_2));
259
717603e3 260 r = load_env_file(NULL, name, NULL, &data);
b9893505 261 assert(r == 0);
f73141d7 262 assert(streq(data[0], "a=a"));
b9893505
ZJS
263 assert(data[1] == NULL);
264 unlink(name);
265}
266
a3aa7ee6 267static void test_load_env_file_3(void) {
7fd1b19b 268 _cleanup_strv_free_ char **data = NULL;
a3aa7ee6
ZJS
269 int r;
270
271 char name[] = "/tmp/test-load-env-file.XXXXXX";
2d5bdf5b
LP
272 _cleanup_close_ int fd;
273
274 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
a3aa7ee6
ZJS
275 assert(fd >= 0);
276 assert_se(write(fd, env_file_3, sizeof(env_file_3)) == sizeof(env_file_3));
277
717603e3 278 r = load_env_file(NULL, name, NULL, &data);
a3aa7ee6
ZJS
279 assert(r == 0);
280 assert(data == NULL);
281 unlink(name);
282}
283
d3b6d0c2 284static void test_load_env_file_4(void) {
7fd1b19b 285 _cleanup_strv_free_ char **data = NULL;
2d5bdf5b
LP
286 char name[] = "/tmp/test-load-env-file.XXXXXX";
287 _cleanup_close_ int fd;
d3b6d0c2
ZJS
288 int r;
289
2d5bdf5b 290 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
d3b6d0c2
ZJS
291 assert(fd >= 0);
292 assert_se(write(fd, env_file_4, sizeof(env_file_4)) == sizeof(env_file_4));
293
717603e3 294 r = load_env_file(NULL, name, NULL, &data);
d3b6d0c2
ZJS
295 assert(r == 0);
296 assert(streq(data[0], "HWMON_MODULES=coretemp f71882fg"));
297 assert(streq(data[1], "MODULE_0=coretemp"));
298 assert(streq(data[2], "MODULE_1=f71882fg"));
299 assert(data[3] == NULL);
300 unlink(name);
301}
302
303
7742f7e9
ZJS
304static void test_install_printf(void) {
305 char name[] = "name.service",
ad88e758 306 path[] = "/run/systemd/system/name.service",
7742f7e9
ZJS
307 user[] = "xxxx-no-such-user";
308 InstallInfo i = {name, path, user};
309 InstallInfo i2 = {name, path, NULL};
310 char name3[] = "name@inst.service",
ad88e758 311 path3[] = "/run/systemd/system/name.service";
7742f7e9
ZJS
312 InstallInfo i3 = {name3, path3, user};
313 InstallInfo i4 = {name3, path3, NULL};
314
7fd1b19b 315 _cleanup_free_ char *mid, *bid, *host;
7742f7e9 316
19f6d710
LP
317 assert_se(specifier_machine_id('m', NULL, NULL, &mid) >= 0 && mid);
318 assert_se(specifier_boot_id('b', NULL, NULL, &bid) >= 0 && bid);
7742f7e9
ZJS
319 assert_se((host = gethostname_malloc()));
320
321#define expect(src, pattern, result) \
f73141d7 322 do { \
19f6d710 323 _cleanup_free_ char *t = NULL; \
7fd1b19b 324 _cleanup_free_ char \
7742f7e9
ZJS
325 *d1 = strdup(i.name), \
326 *d2 = strdup(i.path), \
327 *d3 = strdup(i.user); \
19f6d710 328 assert_se(install_full_printf(&src, pattern, &t) >= 0 || !result); \
7742f7e9
ZJS
329 memzero(i.name, strlen(i.name)); \
330 memzero(i.path, strlen(i.path)); \
331 memzero(i.user, strlen(i.user)); \
332 assert(d1 && d2 && d3); \
333 if (result) { \
334 printf("%s\n", t); \
335 assert(streq(t, result)); \
336 } else assert(t == NULL); \
337 strcpy(i.name, d1); \
338 strcpy(i.path, d2); \
339 strcpy(i.user, d3); \
f73141d7 340 } while(false)
7742f7e9
ZJS
341
342 assert_se(setenv("USER", "root", 1) == 0);
343
344 expect(i, "%n", "name.service");
345 expect(i, "%N", "name");
346 expect(i, "%p", "name");
347 expect(i, "%i", "");
348 expect(i, "%u", "xxxx-no-such-user");
8fca4e30
LP
349
350 DISABLE_WARNING_NONNULL;
7742f7e9 351 expect(i, "%U", NULL);
8fca4e30
LP
352 REENABLE_WARNING;
353
7742f7e9
ZJS
354 expect(i, "%m", mid);
355 expect(i, "%b", bid);
356 expect(i, "%H", host);
357
358 expect(i2, "%u", "root");
359 expect(i2, "%U", "0");
360
361 expect(i3, "%n", "name@inst.service");
362 expect(i3, "%N", "name@inst");
363 expect(i3, "%p", "name");
364 expect(i3, "%u", "xxxx-no-such-user");
8fca4e30
LP
365
366 DISABLE_WARNING_NONNULL;
7742f7e9 367 expect(i3, "%U", NULL);
8fca4e30
LP
368 REENABLE_WARNING;
369
7742f7e9
ZJS
370 expect(i3, "%m", mid);
371 expect(i3, "%b", bid);
372 expect(i3, "%H", host);
373
374 expect(i4, "%u", "root");
375 expect(i4, "%U", "0");
376}
b9893505 377
2c5417ad 378int main(int argc, char *argv[]) {
751e7576 379 int r;
2c5417ad 380
c1b6628d
ZJS
381 log_parse_environment();
382 log_open();
383
751e7576 384 r = test_unit_file_get_set();
2c5417ad 385 test_config_parse_exec();
b9893505
ZJS
386 test_load_env_file_1();
387 test_load_env_file_2();
a3aa7ee6 388 test_load_env_file_3();
d3b6d0c2 389 test_load_env_file_4();
143bfdaf 390 TEST_REQ_RUNNING_SYSTEMD(test_install_printf());
b5b46d59 391
751e7576 392 return r;
b5b46d59 393}