]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-unit-file.c
hashmap: introduce hash_ops to make struct Hashmap smaller
[thirdparty/systemd.git] / src / test / test-unit-file.c
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
7 Copyright 2013 Zbigniew Jędrzejewski-Szmek
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>
27 #include <unistd.h>
28 #include <fcntl.h>
29
30 #include "install.h"
31 #include "install-printf.h"
32 #include "specifier.h"
33 #include "util.h"
34 #include "macro.h"
35 #include "hashmap.h"
36 #include "load-fragment.h"
37 #include "strv.h"
38 #include "fileio.h"
39 #include "test-helper.h"
40
41 static int test_unit_file_get_set(void) {
42 int r;
43 Hashmap *h;
44 Iterator i;
45 UnitFileList *p;
46
47 h = hashmap_new(&string_hash_ops);
48 assert(h);
49
50 r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h);
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
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;
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);
66
67 return 0;
68 }
69
70 static 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
85 static void test_config_parse_exec(void) {
86 /* int config_parse_exec( */
87 /* const char *filename, */
88 /* unsigned line, */
89 /* const char *section, */
90 /* unsigned section_line, */
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 */
101 r = config_parse_exec(NULL, "fake", 1, "section", 1,
102 "LValue", 0, "/RValue r1",
103 &c, NULL);
104 assert_se(r >= 0);
105 check_execcommand(c, "/RValue", "/RValue", "r1", false);
106
107 r = config_parse_exec(NULL, "fake", 2, "section", 1,
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 */
117 r = config_parse_exec(NULL, "fake", 3, "section", 1,
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 */
125 r = config_parse_exec(NULL, "fake", 4, "section", 1,
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
133 /* ignore && honour_argv0 */
134 r = config_parse_exec(NULL, "fake", 4, "section", 1,
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 */
143 r = config_parse_exec(NULL, "fake", 4, "section", 1,
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 */
150 r = config_parse_exec(NULL, "fake", 4, "section", 1,
151 "LValue", 0, "-@-/RValue argv0 r1",
152 &c, NULL);
153 assert_se(r == 0);
154 assert_se(c1->command_next == NULL);
155
156 /* semicolon */
157 r = config_parse_exec(NULL, "fake", 5, "section", 1,
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 */
172 r = config_parse_exec(NULL, "fake", 5, "section", 1,
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
183 /* escaped semicolon */
184 r = config_parse_exec(NULL, "fake", 5, "section", 1,
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
193 exec_command_free_list(c);
194 }
195
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"
209
210 #define env_file_3 \
211 "#SPAMD_ARGS=\"-d --socketpath=/var/lib/bulwark/spamd \\\n" \
212 "#--nouser-config \\\n" \
213 "normal=line"
214
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
226 static void test_load_env_file_1(void) {
227 _cleanup_strv_free_ char **data = NULL;
228 int r;
229
230 char name[] = "/tmp/test-load-env-file.XXXXXX";
231 _cleanup_close_ int fd;
232
233 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
234 assert(fd >= 0);
235 assert_se(write(fd, env_file_1, sizeof(env_file_1)) == sizeof(env_file_1));
236
237 r = load_env_file(NULL, name, NULL, &data);
238 assert(r == 0);
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"));
245 assert(data[6] == NULL);
246 unlink(name);
247 }
248
249 static void test_load_env_file_2(void) {
250 _cleanup_strv_free_ char **data = NULL;
251 int r;
252
253 char name[] = "/tmp/test-load-env-file.XXXXXX";
254 _cleanup_close_ int fd;
255
256 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
257 assert(fd >= 0);
258 assert_se(write(fd, env_file_2, sizeof(env_file_2)) == sizeof(env_file_2));
259
260 r = load_env_file(NULL, name, NULL, &data);
261 assert(r == 0);
262 assert(streq(data[0], "a=a"));
263 assert(data[1] == NULL);
264 unlink(name);
265 }
266
267 static void test_load_env_file_3(void) {
268 _cleanup_strv_free_ char **data = NULL;
269 int r;
270
271 char name[] = "/tmp/test-load-env-file.XXXXXX";
272 _cleanup_close_ int fd;
273
274 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
275 assert(fd >= 0);
276 assert_se(write(fd, env_file_3, sizeof(env_file_3)) == sizeof(env_file_3));
277
278 r = load_env_file(NULL, name, NULL, &data);
279 assert(r == 0);
280 assert(data == NULL);
281 unlink(name);
282 }
283
284 static void test_load_env_file_4(void) {
285 _cleanup_strv_free_ char **data = NULL;
286 char name[] = "/tmp/test-load-env-file.XXXXXX";
287 _cleanup_close_ int fd;
288 int r;
289
290 fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC);
291 assert(fd >= 0);
292 assert_se(write(fd, env_file_4, sizeof(env_file_4)) == sizeof(env_file_4));
293
294 r = load_env_file(NULL, name, NULL, &data);
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
304 static void test_install_printf(void) {
305 char name[] = "name.service",
306 path[] = "/run/systemd/system/name.service",
307 user[] = "xxxx-no-such-user";
308 InstallInfo i = {name, path, user};
309 InstallInfo i2 = {name, path, NULL};
310 char name3[] = "name@inst.service",
311 path3[] = "/run/systemd/system/name.service";
312 InstallInfo i3 = {name3, path3, user};
313 InstallInfo i4 = {name3, path3, NULL};
314
315 _cleanup_free_ char *mid, *bid, *host;
316
317 assert_se(specifier_machine_id('m', NULL, NULL, &mid) >= 0 && mid);
318 assert_se(specifier_boot_id('b', NULL, NULL, &bid) >= 0 && bid);
319 assert_se((host = gethostname_malloc()));
320
321 #define expect(src, pattern, result) \
322 do { \
323 _cleanup_free_ char *t = NULL; \
324 _cleanup_free_ char \
325 *d1 = strdup(i.name), \
326 *d2 = strdup(i.path), \
327 *d3 = strdup(i.user); \
328 assert_se(install_full_printf(&src, pattern, &t) >= 0 || !result); \
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); \
340 } while(false)
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");
349
350 DISABLE_WARNING_NONNULL;
351 expect(i, "%U", NULL);
352 REENABLE_WARNING;
353
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");
365
366 DISABLE_WARNING_NONNULL;
367 expect(i3, "%U", NULL);
368 REENABLE_WARNING;
369
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 }
377
378 int main(int argc, char *argv[]) {
379 int r;
380
381 log_parse_environment();
382 log_open();
383
384 r = test_unit_file_get_set();
385 test_config_parse_exec();
386 test_load_env_file_1();
387 test_load_env_file_2();
388 test_load_env_file_3();
389 test_load_env_file_4();
390 TEST_REQ_RUNNING_SYSTEMD(test_install_printf());
391
392 return r;
393 }