]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/test/test-install-root.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / test / test-install-root.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
0ec0deaa
LP
2/***
3 This file is part of systemd.
4
5 Copyright 2011 Lennart Poettering
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
21#include "alloc-util.h"
22#include "fileio.h"
23#include "install.h"
24#include "mkdir.h"
25#include "rm-rf.h"
075dafd2 26#include "special.h"
0ec0deaa
LP
27#include "string-util.h"
28
29static void test_basic_mask_and_enable(const char *root) {
30 const char *p;
31 UnitFileState state;
32 UnitFileChange *changes = NULL;
33 unsigned n_changes = 0;
34
198402d3
LP
35 log_set_max_level(LOG_DEBUG);
36
0ec0deaa
LP
37 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", NULL) == -ENOENT);
38 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", NULL) == -ENOENT);
39 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", NULL) == -ENOENT);
40 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", NULL) == -ENOENT);
41
42 p = strjoina(root, "/usr/lib/systemd/system/a.service");
43 assert_se(write_string_file(p,
44 "[Install]\n"
45 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
46
47 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", NULL) >= 0);
48 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
49
50 p = strjoina(root, "/usr/lib/systemd/system/b.service");
51 assert_se(symlink("a.service", p) >= 0);
52
53 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", NULL) >= 0);
54 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
55
56 p = strjoina(root, "/usr/lib/systemd/system/c.service");
57 assert_se(symlink("/usr/lib/systemd/system/a.service", p) >= 0);
58
59 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", NULL) >= 0);
60 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
61
62 p = strjoina(root, "/usr/lib/systemd/system/d.service");
63 assert_se(symlink("c.service", p) >= 0);
64
65 /* This one is interesting, as d follows a relative, then an absolute symlink */
66 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", NULL) >= 0);
67 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
68
b3796dd8 69 assert_se(unit_file_mask(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
70 assert_se(n_changes == 1);
71 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
72 assert_se(streq(changes[0].source, "/dev/null"));
73 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/a.service");
74 assert_se(streq(changes[0].path, p));
75
76 unit_file_changes_free(changes, n_changes);
77 changes = NULL; n_changes = 0;
78
79 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_MASKED);
80 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_MASKED);
81 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_MASKED);
82 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_MASKED);
83
84 /* Enabling a masked unit should fail! */
b3796dd8 85 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("a.service"), &changes, &n_changes) == -ERFKILL);
0ec0deaa
LP
86 unit_file_changes_free(changes, n_changes);
87 changes = NULL; n_changes = 0;
88
b3796dd8 89 assert_se(unit_file_unmask(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
90 assert_se(n_changes == 1);
91 assert_se(changes[0].type == UNIT_FILE_UNLINK);
92 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/a.service");
93 assert_se(streq(changes[0].path, p));
94 unit_file_changes_free(changes, n_changes);
95 changes = NULL; n_changes = 0;
96
b3796dd8 97 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("a.service"), &changes, &n_changes) == 1);
0ec0deaa
LP
98 assert_se(n_changes == 1);
99 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
100 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/a.service"));
101 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service");
102 assert_se(streq(changes[0].path, p));
103 unit_file_changes_free(changes, n_changes);
104 changes = NULL; n_changes = 0;
105
106 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
107 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
108 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
109 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
110
111 /* Enabling it again should succeed but be a NOP */
b3796dd8 112 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
113 assert_se(n_changes == 0);
114 unit_file_changes_free(changes, n_changes);
115 changes = NULL; n_changes = 0;
116
b3796dd8 117 assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
118 assert_se(n_changes == 1);
119 assert_se(changes[0].type == UNIT_FILE_UNLINK);
120 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service");
121 assert_se(streq(changes[0].path, p));
122 unit_file_changes_free(changes, n_changes);
123 changes = NULL; n_changes = 0;
124
125 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
126 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
127 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
128 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
129
130 /* Disabling a disabled unit must suceed but be a NOP */
b3796dd8 131 assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
132 assert_se(n_changes == 0);
133 unit_file_changes_free(changes, n_changes);
134 changes = NULL; n_changes = 0;
135
136 /* Let's enable this indirectly via a symlink */
b3796dd8 137 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("d.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
138 assert_se(n_changes == 1);
139 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
140 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/a.service"));
141 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service");
142 assert_se(streq(changes[0].path, p));
143 unit_file_changes_free(changes, n_changes);
144 changes = NULL; n_changes = 0;
145
146 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
147 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
148 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
149 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
150
151 /* Let's try to reenable */
152
b3796dd8 153 assert_se(unit_file_reenable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("b.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
154 assert_se(n_changes == 2);
155 assert_se(changes[0].type == UNIT_FILE_UNLINK);
156 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service");
157 assert_se(streq(changes[0].path, p));
158 assert_se(changes[1].type == UNIT_FILE_SYMLINK);
159 assert_se(streq(changes[1].source, "/usr/lib/systemd/system/a.service"));
160 assert_se(streq(changes[1].path, p));
161 unit_file_changes_free(changes, n_changes);
162 changes = NULL; n_changes = 0;
163
164 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
165 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
166 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
167 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
168}
169
170static void test_linked_units(const char *root) {
171 const char *p, *q;
172 UnitFileState state;
173 UnitFileChange *changes = NULL;
174 unsigned n_changes = 0, i;
175
176 /*
177 * We'll test three cases here:
178 *
179 * a) a unit file in /opt, that we use "systemctl link" and
180 * "systemctl enable" on to make it available to the system
181 *
182 * b) a unit file in /opt, that is statically linked into
183 * /usr/lib/systemd/system, that "enable" should work on
184 * correctly.
185 *
186 * c) a unit file in /opt, that is linked into
187 * /etc/systemd/system, and where "enable" should result in
188 * -ELOOP, since using information from /etc to generate
189 * information in /etc should not be allowed.
190 */
191
192 p = strjoina(root, "/opt/linked.service");
193 assert_se(write_string_file(p,
194 "[Install]\n"
195 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
196
197 p = strjoina(root, "/opt/linked2.service");
198 assert_se(write_string_file(p,
199 "[Install]\n"
200 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
201
202 p = strjoina(root, "/opt/linked3.service");
203 assert_se(write_string_file(p,
204 "[Install]\n"
205 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
206
207 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", NULL) == -ENOENT);
208 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked2.service", NULL) == -ENOENT);
209 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked3.service", NULL) == -ENOENT);
210
211 p = strjoina(root, "/usr/lib/systemd/system/linked2.service");
212 assert_se(symlink("/opt/linked2.service", p) >= 0);
213
214 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked3.service");
215 assert_se(symlink("/opt/linked3.service", p) >= 0);
216
217 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", &state) == -ENOENT);
218 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked2.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
219 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked3.service", &state) >= 0 && state == UNIT_FILE_LINKED);
220
221 /* First, let's link the unit into the search path */
b3796dd8 222 assert_se(unit_file_link(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("/opt/linked.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
223 assert_se(n_changes == 1);
224 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
225 assert_se(streq(changes[0].source, "/opt/linked.service"));
226 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service");
227 assert_se(streq(changes[0].path, p));
228 unit_file_changes_free(changes, n_changes);
229 changes = NULL; n_changes = 0;
230
231 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", &state) >= 0 && state == UNIT_FILE_LINKED);
232
233 /* Let's unlink it from the search path again */
b3796dd8 234 assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("linked.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
235 assert_se(n_changes == 1);
236 assert_se(changes[0].type == UNIT_FILE_UNLINK);
237 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service");
238 assert_se(streq(changes[0].path, p));
239 unit_file_changes_free(changes, n_changes);
240 changes = NULL; n_changes = 0;
241
242 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", NULL) == -ENOENT);
243
244 /* Now, let's not just link it, but also enable it */
b3796dd8 245 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("/opt/linked.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
246 assert_se(n_changes == 2);
247 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/linked.service");
248 q = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service");
249 for (i = 0 ; i < n_changes; i++) {
250 assert_se(changes[i].type == UNIT_FILE_SYMLINK);
251 assert_se(streq(changes[i].source, "/opt/linked.service"));
252
253 if (p && streq(changes[i].path, p))
254 p = NULL;
255 else if (q && streq(changes[i].path, q))
256 q = NULL;
257 else
258 assert_not_reached("wut?");
259 }
260 assert(!p && !q);
261 unit_file_changes_free(changes, n_changes);
262 changes = NULL; n_changes = 0;
263
264 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
265
266 /* And let's unlink it again */
b3796dd8 267 assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("linked.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
268 assert_se(n_changes == 2);
269 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/linked.service");
270 q = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service");
271 for (i = 0; i < n_changes; i++) {
272 assert_se(changes[i].type == UNIT_FILE_UNLINK);
273
274 if (p && streq(changes[i].path, p))
275 p = NULL;
276 else if (q && streq(changes[i].path, q))
277 q = NULL;
278 else
279 assert_not_reached("wut?");
280 }
281 assert(!p && !q);
282 unit_file_changes_free(changes, n_changes);
283 changes = NULL; n_changes = 0;
284
285 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", NULL) == -ENOENT);
286
b3796dd8 287 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("linked2.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
288 assert_se(n_changes == 2);
289 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/linked2.service");
290 q = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked2.service");
291 for (i = 0 ; i < n_changes; i++) {
292 assert_se(changes[i].type == UNIT_FILE_SYMLINK);
293 assert_se(streq(changes[i].source, "/opt/linked2.service"));
294
295 if (p && streq(changes[i].path, p))
296 p = NULL;
297 else if (q && streq(changes[i].path, q))
298 q = NULL;
299 else
300 assert_not_reached("wut?");
301 }
302 assert(!p && !q);
303 unit_file_changes_free(changes, n_changes);
304 changes = NULL; n_changes = 0;
305
b3796dd8 306 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("linked3.service"), &changes, &n_changes) >= 0);
f777b434
ZJS
307 assert_se(n_changes == 1);
308 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
309 assert_se(startswith(changes[0].path, root));
310 assert_se(endswith(changes[0].path, "linked3.service"));
311 assert_se(streq(changes[0].source, "/opt/linked3.service"));
0ec0deaa
LP
312 unit_file_changes_free(changes, n_changes);
313 changes = NULL; n_changes = 0;
314}
315
316static void test_default(const char *root) {
317 _cleanup_free_ char *def = NULL;
318 UnitFileChange *changes = NULL;
319 unsigned n_changes = 0;
320 const char *p;
321
322 p = strjoina(root, "/usr/lib/systemd/system/test-default-real.target");
323 assert_se(write_string_file(p, "# pretty much empty", WRITE_STRING_FILE_CREATE) >= 0);
324
325 p = strjoina(root, "/usr/lib/systemd/system/test-default.target");
326 assert_se(symlink("test-default-real.target", p) >= 0);
327
328 assert_se(unit_file_get_default(UNIT_FILE_SYSTEM, root, &def) == -ENOENT);
329
b3796dd8 330 assert_se(unit_file_set_default(UNIT_FILE_SYSTEM, 0, root, "idontexist.target", &changes, &n_changes) == -ENOENT);
59108fbe
ZJS
331 assert_se(n_changes == 1);
332 assert_se(changes[0].type == -ENOENT);
333 assert_se(streq_ptr(changes[0].path, "idontexist.target"));
0ec0deaa
LP
334 unit_file_changes_free(changes, n_changes);
335 changes = NULL; n_changes = 0;
336
337 assert_se(unit_file_get_default(UNIT_FILE_SYSTEM, root, &def) == -ENOENT);
338
b3796dd8 339 assert_se(unit_file_set_default(UNIT_FILE_SYSTEM, 0, root, "test-default.target", &changes, &n_changes) >= 0);
0ec0deaa
LP
340 assert_se(n_changes == 1);
341 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
342 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/test-default-real.target"));
075dafd2 343 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH "/" SPECIAL_DEFAULT_TARGET);
0ec0deaa
LP
344 assert_se(streq(changes[0].path, p));
345 unit_file_changes_free(changes, n_changes);
346 changes = NULL; n_changes = 0;
347
348 assert_se(unit_file_get_default(UNIT_FILE_SYSTEM, root, &def) >= 0);
349 assert_se(streq_ptr(def, "test-default-real.target"));
350}
351
352static void test_add_dependency(const char *root) {
353 UnitFileChange *changes = NULL;
354 unsigned n_changes = 0;
355 const char *p;
356
357 p = strjoina(root, "/usr/lib/systemd/system/real-add-dependency-test-target.target");
358 assert_se(write_string_file(p, "# pretty much empty", WRITE_STRING_FILE_CREATE) >= 0);
359
360 p = strjoina(root, "/usr/lib/systemd/system/add-dependency-test-target.target");
361 assert_se(symlink("real-add-dependency-test-target.target", p) >= 0);
362
363 p = strjoina(root, "/usr/lib/systemd/system/real-add-dependency-test-service.service");
364 assert_se(write_string_file(p, "# pretty much empty", WRITE_STRING_FILE_CREATE) >= 0);
365
366 p = strjoina(root, "/usr/lib/systemd/system/add-dependency-test-service.service");
367 assert_se(symlink("real-add-dependency-test-service.service", p) >= 0);
368
b3796dd8 369 assert_se(unit_file_add_dependency(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("add-dependency-test-service.service"), "add-dependency-test-target.target", UNIT_WANTS, &changes, &n_changes) >= 0);
0ec0deaa
LP
370 assert_se(n_changes == 1);
371 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
372 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/real-add-dependency-test-service.service"));
373 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/real-add-dependency-test-target.target.wants/real-add-dependency-test-service.service");
374 assert_se(streq(changes[0].path, p));
375 unit_file_changes_free(changes, n_changes);
376 changes = NULL; n_changes = 0;
377}
378
379static void test_template_enable(const char *root) {
380 UnitFileChange *changes = NULL;
381 unsigned n_changes = 0;
382 UnitFileState state;
383 const char *p;
384
5cd8ae31
ZJS
385 log_info("== %s ==", __func__);
386
0ec0deaa
LP
387 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) == -ENOENT);
388 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) == -ENOENT);
389 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) == -ENOENT);
390 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) == -ENOENT);
391
392 p = strjoina(root, "/usr/lib/systemd/system/template@.service");
393 assert_se(write_string_file(p,
394 "[Install]\n"
395 "DefaultInstance=def\n"
396 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
397
398 p = strjoina(root, "/usr/lib/systemd/system/template-symlink@.service");
399 assert_se(symlink("template@.service", p) >= 0);
400
401 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
402 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
403 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
404 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
405 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
406 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
407
5cd8ae31
ZJS
408 log_info("== %s with template@.service enabled ==", __func__);
409
b3796dd8 410 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("template@.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
411 assert_se(n_changes == 1);
412 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
413 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/template@.service"));
414 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/template@def.service");
415 assert_se(streq(changes[0].path, p));
416 unit_file_changes_free(changes, n_changes);
417 changes = NULL; n_changes = 0;
418
419 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
420 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
421 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
422 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
423 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
424 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
425
b3796dd8 426 assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("template@.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
427 assert_se(n_changes == 1);
428 assert_se(changes[0].type == UNIT_FILE_UNLINK);
429 assert_se(streq(changes[0].path, p));
430 unit_file_changes_free(changes, n_changes);
431 changes = NULL; n_changes = 0;
432
433 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
434 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
435 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
436 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
437 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
438 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
439
5cd8ae31
ZJS
440 log_info("== %s with template@foo.service enabled ==", __func__);
441
b3796dd8 442 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("template@foo.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
443 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
444 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/template@.service"));
445 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/template@foo.service");
446 assert_se(streq(changes[0].path, p));
447 unit_file_changes_free(changes, n_changes);
448 changes = NULL; n_changes = 0;
449
d9b4b48f 450 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
0ec0deaa
LP
451 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
452 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
453 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
454 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
455 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
456
b3796dd8 457 assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("template@foo.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
458 assert_se(n_changes == 1);
459 assert_se(changes[0].type == UNIT_FILE_UNLINK);
460 assert_se(streq(changes[0].path, p));
461 unit_file_changes_free(changes, n_changes);
462 changes = NULL; n_changes = 0;
463
464 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
465 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
466 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
467 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@quux.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
468 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
469 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
470 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
471 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@quux.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
472
5cd8ae31
ZJS
473 log_info("== %s with template-symlink@quux.service enabled ==", __func__);
474
b3796dd8 475 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("template-symlink@quux.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
476 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
477 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/template@.service"));
478 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/template@quux.service");
479 assert_se(streq(changes[0].path, p));
480 unit_file_changes_free(changes, n_changes);
481 changes = NULL; n_changes = 0;
482
d9b4b48f 483 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
0ec0deaa
LP
484 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
485 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
486 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@quux.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
d9b4b48f 487 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
0ec0deaa
LP
488 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
489 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
490 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@quux.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
491}
492
493static void test_indirect(const char *root) {
494 UnitFileChange *changes = NULL;
495 unsigned n_changes = 0;
496 UnitFileState state;
497 const char *p;
498
499 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirecta.service", &state) == -ENOENT);
500 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectb.service", &state) == -ENOENT);
501 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectc.service", &state) == -ENOENT);
502
503 p = strjoina(root, "/usr/lib/systemd/system/indirecta.service");
504 assert_se(write_string_file(p,
505 "[Install]\n"
506 "Also=indirectb.service\n", WRITE_STRING_FILE_CREATE) >= 0);
507
508 p = strjoina(root, "/usr/lib/systemd/system/indirectb.service");
509 assert_se(write_string_file(p,
510 "[Install]\n"
511 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
512
513 p = strjoina(root, "/usr/lib/systemd/system/indirectc.service");
514 assert_se(symlink("indirecta.service", p) >= 0);
515
516 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirecta.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
517 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectb.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
518 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectc.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
519
b3796dd8 520 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("indirectc.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
521 assert_se(n_changes == 1);
522 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
523 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/indirectb.service"));
524 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/indirectb.service");
525 assert_se(streq(changes[0].path, p));
526 unit_file_changes_free(changes, n_changes);
527 changes = NULL; n_changes = 0;
528
529 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirecta.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
530 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectb.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
531 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectc.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
532
b3796dd8 533 assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("indirectc.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
534 assert_se(n_changes == 1);
535 assert_se(changes[0].type == UNIT_FILE_UNLINK);
536 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/indirectb.service");
537 assert_se(streq(changes[0].path, p));
538 unit_file_changes_free(changes, n_changes);
539 changes = NULL; n_changes = 0;
540}
541
542static void test_preset_and_list(const char *root) {
543 UnitFileChange *changes = NULL;
544 unsigned n_changes = 0, i;
545 const char *p, *q;
546 UnitFileState state;
547 bool got_yes = false, got_no = false;
548 Iterator j;
549 UnitFileList *fl;
550 Hashmap *h;
551
552 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) == -ENOENT);
553 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) == -ENOENT);
554
555 p = strjoina(root, "/usr/lib/systemd/system/preset-yes.service");
556 assert_se(write_string_file(p,
557 "[Install]\n"
558 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
559
560 p = strjoina(root, "/usr/lib/systemd/system/preset-no.service");
561 assert_se(write_string_file(p,
562 "[Install]\n"
563 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
564
565 p = strjoina(root, "/usr/lib/systemd/system-preset/test.preset");
566 assert_se(write_string_file(p,
567 "enable *-yes.*\n"
568 "disable *\n", WRITE_STRING_FILE_CREATE) >= 0);
569
570 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
571 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
572
b3796dd8 573 assert_se(unit_file_preset(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("preset-yes.service"), UNIT_FILE_PRESET_FULL, &changes, &n_changes) >= 0);
0ec0deaa
LP
574 assert_se(n_changes == 1);
575 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
576 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/preset-yes.service"));
577 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/preset-yes.service");
578 assert_se(streq(changes[0].path, p));
579 unit_file_changes_free(changes, n_changes);
580 changes = NULL; n_changes = 0;
581
582 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
583 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
584
b3796dd8 585 assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("preset-yes.service"), &changes, &n_changes) >= 0);
0ec0deaa
LP
586 assert_se(n_changes == 1);
587 assert_se(changes[0].type == UNIT_FILE_UNLINK);
588 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/preset-yes.service");
589 assert_se(streq(changes[0].path, p));
590 unit_file_changes_free(changes, n_changes);
591 changes = NULL; n_changes = 0;
592
593 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
594 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
595
b3796dd8 596 assert_se(unit_file_preset(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("preset-no.service"), UNIT_FILE_PRESET_FULL, &changes, &n_changes) >= 0);
0ec0deaa
LP
597 assert_se(n_changes == 0);
598 unit_file_changes_free(changes, n_changes);
599 changes = NULL; n_changes = 0;
600
601 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
602 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
603
b3796dd8 604 assert_se(unit_file_preset_all(UNIT_FILE_SYSTEM, 0, root, UNIT_FILE_PRESET_FULL, &changes, &n_changes) >= 0);
0ec0deaa
LP
605
606 assert_se(n_changes > 0);
607
608 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/preset-yes.service");
609
610 for (i = 0; i < n_changes; i++) {
611
612 if (changes[i].type == UNIT_FILE_SYMLINK) {
613 assert_se(streq(changes[i].source, "/usr/lib/systemd/system/preset-yes.service"));
614 assert_se(streq(changes[i].path, p));
615 } else
616 assert_se(changes[i].type == UNIT_FILE_UNLINK);
617 }
618
619 unit_file_changes_free(changes, n_changes);
620 changes = NULL; n_changes = 0;
621
622 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
623 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
624
625 assert_se(h = hashmap_new(&string_hash_ops));
313fe66f 626 assert_se(unit_file_get_list(UNIT_FILE_SYSTEM, root, h, NULL, NULL) >= 0);
0ec0deaa
LP
627
628 p = strjoina(root, "/usr/lib/systemd/system/preset-yes.service");
629 q = strjoina(root, "/usr/lib/systemd/system/preset-no.service");
630
631 HASHMAP_FOREACH(fl, h, j) {
632 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, basename(fl->path), &state) >= 0);
633 assert_se(fl->state == state);
634
635 if (streq(fl->path, p)) {
636 got_yes = true;
637 assert_se(fl->state == UNIT_FILE_ENABLED);
638 } else if (streq(fl->path, q)) {
639 got_no = true;
640 assert_se(fl->state == UNIT_FILE_DISABLED);
641 } else
642 assert_se(IN_SET(fl->state, UNIT_FILE_DISABLED, UNIT_FILE_STATIC, UNIT_FILE_INDIRECT));
643 }
644
645 unit_file_list_free(h);
646
647 assert_se(got_yes && got_no);
648}
649
344ca755
LP
650static void test_revert(const char *root) {
651 const char *p;
652 UnitFileState state;
653 UnitFileChange *changes = NULL;
654 unsigned n_changes = 0;
655
656 assert(root);
657
658 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "xx.service", NULL) == -ENOENT);
659 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "yy.service", NULL) == -ENOENT);
660
661 p = strjoina(root, "/usr/lib/systemd/system/xx.service");
662 assert_se(write_string_file(p, "# Empty\n", WRITE_STRING_FILE_CREATE) >= 0);
663
664 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "xx.service", NULL) >= 0);
665 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "xx.service", &state) >= 0 && state == UNIT_FILE_STATIC);
666
667 /* Initially there's nothing to revert */
668 assert_se(unit_file_revert(UNIT_FILE_SYSTEM, root, STRV_MAKE("xx.service"), &changes, &n_changes) >= 0);
669 assert_se(n_changes == 0);
670 unit_file_changes_free(changes, n_changes);
671 changes = NULL; n_changes = 0;
672
673 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/xx.service");
674 assert_se(write_string_file(p, "# Empty override\n", WRITE_STRING_FILE_CREATE) >= 0);
675
676 /* Revert the override file */
677 assert_se(unit_file_revert(UNIT_FILE_SYSTEM, root, STRV_MAKE("xx.service"), &changes, &n_changes) >= 0);
678 assert_se(n_changes == 1);
679 assert_se(changes[0].type == UNIT_FILE_UNLINK);
680 assert_se(streq(changes[0].path, p));
681 unit_file_changes_free(changes, n_changes);
682 changes = NULL; n_changes = 0;
683
684 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/xx.service.d/dropin.conf");
685 assert_se(mkdir_parents(p, 0755) >= 0);
686 assert_se(write_string_file(p, "# Empty dropin\n", WRITE_STRING_FILE_CREATE) >= 0);
687
688 /* Revert the dropin file */
689 assert_se(unit_file_revert(UNIT_FILE_SYSTEM, root, STRV_MAKE("xx.service"), &changes, &n_changes) >= 0);
690 assert_se(n_changes == 2);
691 assert_se(changes[0].type == UNIT_FILE_UNLINK);
692 assert_se(streq(changes[0].path, p));
693
694 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/xx.service.d");
695 assert_se(changes[1].type == UNIT_FILE_UNLINK);
696 assert_se(streq(changes[1].path, p));
697 unit_file_changes_free(changes, n_changes);
698 changes = NULL; n_changes = 0;
699}
700
622d3705
AC
701static void test_preset_order(const char *root) {
702 UnitFileChange *changes = NULL;
703 unsigned n_changes = 0;
704 const char *p;
705 UnitFileState state;
706
707 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-1.service", &state) == -ENOENT);
708 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-2.service", &state) == -ENOENT);
709
710 p = strjoina(root, "/usr/lib/systemd/system/prefix-1.service");
711 assert_se(write_string_file(p,
712 "[Install]\n"
713 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
714
715 p = strjoina(root, "/usr/lib/systemd/system/prefix-2.service");
716 assert_se(write_string_file(p,
717 "[Install]\n"
718 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
719
720 p = strjoina(root, "/usr/lib/systemd/system-preset/test.preset");
721 assert_se(write_string_file(p,
722 "enable prefix-1.service\n"
723 "disable prefix-*.service\n"
724 "enable prefix-2.service\n", WRITE_STRING_FILE_CREATE) >= 0);
725
726 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-1.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
727 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-2.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
728
b3796dd8 729 assert_se(unit_file_preset(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("prefix-1.service"), UNIT_FILE_PRESET_FULL, &changes, &n_changes) >= 0);
622d3705
AC
730 assert_se(n_changes == 1);
731 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
732 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/prefix-1.service"));
733 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/prefix-1.service");
734 assert_se(streq(changes[0].path, p));
735 unit_file_changes_free(changes, n_changes);
736 changes = NULL; n_changes = 0;
737
738 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-1.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
739 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-2.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
740
b3796dd8 741 assert_se(unit_file_preset(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("prefix-2.service"), UNIT_FILE_PRESET_FULL, &changes, &n_changes) >= 0);
622d3705
AC
742 assert_se(n_changes == 0);
743
744 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-1.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
745 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-2.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
746}
747
dfead90d
LP
748static void test_static_instance(const char *root) {
749 UnitFileState state;
750 const char *p;
751
752 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "static-instance@.service", &state) == -ENOENT);
753 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "static-instance@foo.service", &state) == -ENOENT);
754
755 p = strjoina(root, "/usr/lib/systemd/system/static-instance@.service");
756 assert_se(write_string_file(p,
757 "[Install]\n"
758 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
759
760 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "static-instance@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
761 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "static-instance@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
762
763 p = strjoina(root, "/usr/lib/systemd/system/static-instance@foo.service");
764 assert_se(symlink("static-instance@.service", p) >= 0);
765
766 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "static-instance@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
767 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "static-instance@foo.service", &state) >= 0 && state == UNIT_FILE_STATIC);
768}
769
142468d8
JL
770static void test_with_dropin(const char *root) {
771 const char *p;
772 UnitFileState state;
773 UnitFileChange *changes = NULL;
774 unsigned n_changes = 0;
775
776 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-1.service", &state) == -ENOENT);
777 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-2.service", &state) == -ENOENT);
778 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3.service", &state) == -ENOENT);
779 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-4a.service", &state) == -ENOENT);
780 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-4b.service", &state) == -ENOENT);
781
782 p = strjoina(root, "/usr/lib/systemd/system/with-dropin-1.service");
783 assert_se(write_string_file(p,
784 "[Install]\n"
785 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
786
787 p = strjoina(root, "/usr/lib/systemd/system/with-dropin-1.service.d/dropin.conf");
788 assert_se(mkdir_parents(p, 0755) >= 0);
789 assert_se(write_string_file(p,
790 "[Install]\n"
791 "WantedBy=graphical.target\n", WRITE_STRING_FILE_CREATE) >= 0);
792
793 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-1.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
794
795 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/with-dropin-2.service");
796 assert_se(write_string_file(p,
797 "[Install]\n"
798 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
799
800 p = strjoina(root, "/usr/lib/systemd/system/with-dropin-2.service.d/dropin.conf");
801 assert_se(mkdir_parents(p, 0755) >= 0);
802 assert_se(write_string_file(p,
803 "[Install]\n"
804 "WantedBy=graphical.target\n", WRITE_STRING_FILE_CREATE) >= 0);
805
806 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-2.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
807
808 p = strjoina(root, "/usr/lib/systemd/system/with-dropin-3.service");
809 assert_se(write_string_file(p,
810 "[Install]\n"
811 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
812
813 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/with-dropin-3.service.d/dropin.conf");
814 assert_se(mkdir_parents(p, 0755) >= 0);
815 assert_se(write_string_file(p,
816 "[Install]\n"
817 "WantedBy=graphical.target\n", WRITE_STRING_FILE_CREATE) >= 0);
818
819 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
820
821 p = strjoina(root, "/usr/lib/systemd/system/with-dropin-4a.service");
822 assert_se(write_string_file(p,
823 "[Install]\n"
824 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
825
826 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/with-dropin-4a.service.d/dropin.conf");
827 assert_se(mkdir_parents(p, 0755) >= 0);
828 assert_se(write_string_file(p,
829 "[Install]\n"
830 "Also=with-dropin-4b.service\n", WRITE_STRING_FILE_CREATE) >= 0);
831
832 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-4a.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
833
834 p = strjoina(root, "/usr/lib/systemd/system/with-dropin-4b.service");
835 assert_se(write_string_file(p,
836 "[Install]\n"
837 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
838
839 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-4b.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
840
841 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("with-dropin-1.service"), &changes, &n_changes) == 1);
842 assert_se(n_changes == 2);
843 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
844 assert_se(changes[1].type == UNIT_FILE_SYMLINK);
845 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/with-dropin-1.service"));
846 assert_se(streq(changes[1].source, "/usr/lib/systemd/system/with-dropin-1.service"));
847 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/with-dropin-1.service");
848 assert_se(streq(changes[0].path, p));
849 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/graphical.target.wants/with-dropin-1.service");
850 assert_se(streq(changes[1].path, p));
851 unit_file_changes_free(changes, n_changes);
852 changes = NULL; n_changes = 0;
853
854 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("with-dropin-2.service"), &changes, &n_changes) == 1);
855 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-2.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
856 assert_se(n_changes == 2);
857 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
858 assert_se(changes[1].type == UNIT_FILE_SYMLINK);
859 assert_se(streq(changes[0].source, SYSTEM_CONFIG_UNIT_PATH"/with-dropin-2.service"));
860 assert_se(streq(changes[1].source, SYSTEM_CONFIG_UNIT_PATH"/with-dropin-2.service"));
861 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/with-dropin-2.service");
862 assert_se(streq(changes[0].path, p));
863 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/graphical.target.wants/with-dropin-2.service");
864 assert_se(streq(changes[1].path, p));
865 unit_file_changes_free(changes, n_changes);
866 changes = NULL; n_changes = 0;
867
868 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("with-dropin-3.service"), &changes, &n_changes) == 1);
869 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
870 assert_se(n_changes == 2);
871 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
872 assert_se(changes[1].type == UNIT_FILE_SYMLINK);
873 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/with-dropin-3.service"));
874 assert_se(streq(changes[1].source, "/usr/lib/systemd/system/with-dropin-3.service"));
875 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/with-dropin-3.service");
876 assert_se(streq(changes[0].path, p));
877 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/graphical.target.wants/with-dropin-3.service");
878 assert_se(streq(changes[1].path, p));
879 unit_file_changes_free(changes, n_changes);
880 changes = NULL; n_changes = 0;
881
882 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("with-dropin-4a.service"), &changes, &n_changes) == 1);
883 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
884 assert_se(n_changes == 2);
885 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
886 assert_se(changes[1].type == UNIT_FILE_SYMLINK);
887 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/with-dropin-4a.service"));
888 assert_se(streq(changes[1].source, "/usr/lib/systemd/system/with-dropin-4b.service"));
889 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/with-dropin-4a.service");
890 assert_se(streq(changes[0].path, p));
891 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/with-dropin-4b.service");
892 assert_se(streq(changes[1].path, p));
893 unit_file_changes_free(changes, n_changes);
894 changes = NULL; n_changes = 0;
895
896 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-1.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
897 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-2.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
898 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
899 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-4a.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
900 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-4b.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
901}
902
903static void test_with_dropin_template(const char *root) {
904 const char *p;
905 UnitFileState state;
906 UnitFileChange *changes = NULL;
907 unsigned n_changes = 0;
908
909 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-1@.service", &state) == -ENOENT);
910 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-2@.service", &state) == -ENOENT);
911 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3@.service", &state) == -ENOENT);
912
913 p = strjoina(root, "/usr/lib/systemd/system/with-dropin-1@.service");
914 assert_se(write_string_file(p,
915 "[Install]\n"
916 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
917
918 p = strjoina(root, "/usr/lib/systemd/system/with-dropin-1@.service.d/dropin.conf");
919 assert_se(mkdir_parents(p, 0755) >= 0);
920 assert_se(write_string_file(p,
921 "[Install]\n"
922 "WantedBy=graphical.target\n", WRITE_STRING_FILE_CREATE) >= 0);
923
924 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-1@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
925
926 p = strjoina(root, "/usr/lib/systemd/system/with-dropin-2@.service");
927 assert_se(write_string_file(p,
928 "[Install]\n"
929 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
930
931 p = strjoina(root, "/usr/lib/systemd/system/with-dropin-2@instance-1.service.d/dropin.conf");
932 assert_se(mkdir_parents(p, 0755) >= 0);
933 assert_se(write_string_file(p,
934 "[Install]\n"
935 "WantedBy=graphical.target\n", WRITE_STRING_FILE_CREATE) >= 0);
936
937 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-2@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
938
939 p = strjoina(root, "/usr/lib/systemd/system/with-dropin-3@.service");
940 assert_se(write_string_file(p,
941 "[Install]\n"
942 "DefaultInstance=instance-1\n"
943 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
944
945 p = strjoina(root, "/usr/lib/systemd/system/with-dropin-3@.service.d/dropin.conf");
946 assert_se(mkdir_parents(p, 0755) >= 0);
947 assert_se(write_string_file(p,
948 "[Install]\n"
949 "DefaultInstance=instance-2\n", WRITE_STRING_FILE_CREATE) >= 0);
950
951 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
952
953 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("with-dropin-1@instance-1.service"), &changes, &n_changes) == 1);
954 assert_se(n_changes == 2);
955 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
956 assert_se(changes[1].type == UNIT_FILE_SYMLINK);
957 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/with-dropin-1@.service"));
958 assert_se(streq(changes[1].source, "/usr/lib/systemd/system/with-dropin-1@.service"));
959 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/with-dropin-1@instance-1.service");
960 assert_se(streq(changes[0].path, p));
961 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/graphical.target.wants/with-dropin-1@instance-1.service");
962 assert_se(streq(changes[1].path, p));
963 unit_file_changes_free(changes, n_changes);
964 changes = NULL; n_changes = 0;
965
966 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("with-dropin-2@instance-1.service"), &changes, &n_changes) == 1);
967 assert_se(n_changes == 2);
968 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
969 assert_se(changes[1].type == UNIT_FILE_SYMLINK);
970 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/with-dropin-2@.service"));
971 assert_se(streq(changes[1].source, "/usr/lib/systemd/system/with-dropin-2@.service"));
972 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/with-dropin-2@instance-1.service");
973 assert_se(streq(changes[0].path, p));
974 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/graphical.target.wants/with-dropin-2@instance-1.service");
975 assert_se(streq(changes[1].path, p));
976 unit_file_changes_free(changes, n_changes);
977 changes = NULL; n_changes = 0;
978
979 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("with-dropin-2@instance-2.service"), &changes, &n_changes) == 1);
980 assert_se(n_changes == 1);
981 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
982 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/with-dropin-2@.service"));
983 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/with-dropin-2@instance-2.service");
984 assert_se(streq(changes[0].path, p));
985 unit_file_changes_free(changes, n_changes);
986 changes = NULL; n_changes = 0;
987
988 assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("with-dropin-3@.service"), &changes, &n_changes) == 1);
989 assert_se(n_changes == 1);
990 assert_se(changes[0].type == UNIT_FILE_SYMLINK);
991 assert_se(streq(changes[0].source, "/usr/lib/systemd/system/with-dropin-3@.service"));
992 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/with-dropin-3@instance-2.service");
993 assert_se(streq(changes[0].path, p));
994 unit_file_changes_free(changes, n_changes);
995 changes = NULL; n_changes = 0;
996
997 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-1@instance-1.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
998 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-2@instance-1.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
999 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-2@instance-2.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
1000 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3@instance-1.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
1001 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3@instance-2.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
1002}
1003
0ec0deaa
LP
1004int main(int argc, char *argv[]) {
1005 char root[] = "/tmp/rootXXXXXX";
1006 const char *p;
1007
1008 assert_se(mkdtemp(root));
1009
1010 p = strjoina(root, "/usr/lib/systemd/system/");
1011 assert_se(mkdir_p(p, 0755) >= 0);
1012
1013 p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/");
1014 assert_se(mkdir_p(p, 0755) >= 0);
1015
1016 p = strjoina(root, "/run/systemd/system/");
1017 assert_se(mkdir_p(p, 0755) >= 0);
1018
1019 p = strjoina(root, "/opt/");
1020 assert_se(mkdir_p(p, 0755) >= 0);
1021
1022 p = strjoina(root, "/usr/lib/systemd/system-preset/");
1023 assert_se(mkdir_p(p, 0755) >= 0);
1024
1025 test_basic_mask_and_enable(root);
1026 test_linked_units(root);
1027 test_default(root);
1028 test_add_dependency(root);
1029 test_template_enable(root);
1030 test_indirect(root);
1031 test_preset_and_list(root);
622d3705 1032 test_preset_order(root);
344ca755 1033 test_revert(root);
dfead90d 1034 test_static_instance(root);
142468d8
JL
1035 test_with_dropin(root);
1036 test_with_dropin_template(root);
0ec0deaa
LP
1037
1038 assert_se(rm_rf(root, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
1039
1040 return 0;
1041}