]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-install-root.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2011 Lennart Poettering
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.
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.
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/>.
21 #include "alloc-util.h"
27 #include "string-util.h"
29 static void test_basic_mask_and_enable(const char *root
) {
32 UnitFileChange
*changes
= NULL
;
33 unsigned n_changes
= 0;
35 log_set_max_level(LOG_DEBUG
);
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
);
42 p
= strjoina(root
, "/usr/lib/systemd/system/a.service");
43 assert_se(write_string_file(p
,
45 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
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
);
50 p
= strjoina(root
, "/usr/lib/systemd/system/b.service");
51 assert_se(symlink("a.service", p
) >= 0);
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
);
56 p
= strjoina(root
, "/usr/lib/systemd/system/c.service");
57 assert_se(symlink("/usr/lib/systemd/system/a.service", p
) >= 0);
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
);
62 p
= strjoina(root
, "/usr/lib/systemd/system/d.service");
63 assert_se(symlink("c.service", p
) >= 0);
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
);
69 assert_se(unit_file_mask(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("a.service"), &changes
, &n_changes
) >= 0);
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
));
76 unit_file_changes_free(changes
, n_changes
);
77 changes
= NULL
; n_changes
= 0;
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
);
84 /* Enabling a masked unit should fail! */
85 assert_se(unit_file_enable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("a.service"), &changes
, &n_changes
) == -ERFKILL
);
86 unit_file_changes_free(changes
, n_changes
);
87 changes
= NULL
; n_changes
= 0;
89 assert_se(unit_file_unmask(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("a.service"), &changes
, &n_changes
) >= 0);
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;
97 assert_se(unit_file_enable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("a.service"), &changes
, &n_changes
) == 1);
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;
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
);
111 /* Enabling it again should succeed but be a NOP */
112 assert_se(unit_file_enable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("a.service"), &changes
, &n_changes
) >= 0);
113 assert_se(n_changes
== 0);
114 unit_file_changes_free(changes
, n_changes
);
115 changes
= NULL
; n_changes
= 0;
117 assert_se(unit_file_disable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("a.service"), &changes
, &n_changes
) >= 0);
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;
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
);
130 /* Disabling a disabled unit must suceed but be a NOP */
131 assert_se(unit_file_disable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("a.service"), &changes
, &n_changes
) >= 0);
132 assert_se(n_changes
== 0);
133 unit_file_changes_free(changes
, n_changes
);
134 changes
= NULL
; n_changes
= 0;
136 /* Let's enable this indirectly via a symlink */
137 assert_se(unit_file_enable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("d.service"), &changes
, &n_changes
) >= 0);
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;
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
);
151 /* Let's try to reenable */
153 assert_se(unit_file_reenable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("b.service"), &changes
, &n_changes
) >= 0);
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;
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
);
170 static void test_linked_units(const char *root
) {
173 UnitFileChange
*changes
= NULL
;
174 unsigned n_changes
= 0, i
;
177 * We'll test three cases here:
179 * a) a unit file in /opt, that we use "systemctl link" and
180 * "systemctl enable" on to make it available to the system
182 * b) a unit file in /opt, that is statically linked into
183 * /usr/lib/systemd/system, that "enable" should work on
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.
192 p
= strjoina(root
, "/opt/linked.service");
193 assert_se(write_string_file(p
,
195 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
197 p
= strjoina(root
, "/opt/linked2.service");
198 assert_se(write_string_file(p
,
200 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
202 p
= strjoina(root
, "/opt/linked3.service");
203 assert_se(write_string_file(p
,
205 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
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
);
211 p
= strjoina(root
, "/usr/lib/systemd/system/linked2.service");
212 assert_se(symlink("/opt/linked2.service", p
) >= 0);
214 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/linked3.service");
215 assert_se(symlink("/opt/linked3.service", p
) >= 0);
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
);
221 /* First, let's link the unit into the search path */
222 assert_se(unit_file_link(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("/opt/linked.service"), &changes
, &n_changes
) >= 0);
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;
231 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "linked.service", &state
) >= 0 && state
== UNIT_FILE_LINKED
);
233 /* Let's unlink it from the search path again */
234 assert_se(unit_file_disable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("linked.service"), &changes
, &n_changes
) >= 0);
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;
242 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "linked.service", NULL
) == -ENOENT
);
244 /* Now, let's not just link it, but also enable it */
245 assert_se(unit_file_enable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("/opt/linked.service"), &changes
, &n_changes
) >= 0);
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"));
253 if (p
&& streq(changes
[i
].path
, p
))
255 else if (q
&& streq(changes
[i
].path
, q
))
258 assert_not_reached("wut?");
261 unit_file_changes_free(changes
, n_changes
);
262 changes
= NULL
; n_changes
= 0;
264 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "linked.service", &state
) >= 0 && state
== UNIT_FILE_ENABLED
);
266 /* And let's unlink it again */
267 assert_se(unit_file_disable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("linked.service"), &changes
, &n_changes
) >= 0);
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
);
274 if (p
&& streq(changes
[i
].path
, p
))
276 else if (q
&& streq(changes
[i
].path
, q
))
279 assert_not_reached("wut?");
282 unit_file_changes_free(changes
, n_changes
);
283 changes
= NULL
; n_changes
= 0;
285 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "linked.service", NULL
) == -ENOENT
);
287 assert_se(unit_file_enable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("linked2.service"), &changes
, &n_changes
) >= 0);
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"));
295 if (p
&& streq(changes
[i
].path
, p
))
297 else if (q
&& streq(changes
[i
].path
, q
))
300 assert_not_reached("wut?");
303 unit_file_changes_free(changes
, n_changes
);
304 changes
= NULL
; n_changes
= 0;
306 assert_se(unit_file_enable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("linked3.service"), &changes
, &n_changes
) >= 0);
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"));
312 unit_file_changes_free(changes
, n_changes
);
313 changes
= NULL
; n_changes
= 0;
316 static void test_default(const char *root
) {
317 _cleanup_free_
char *def
= NULL
;
318 UnitFileChange
*changes
= NULL
;
319 unsigned n_changes
= 0;
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);
325 p
= strjoina(root
, "/usr/lib/systemd/system/test-default.target");
326 assert_se(symlink("test-default-real.target", p
) >= 0);
328 assert_se(unit_file_get_default(UNIT_FILE_SYSTEM
, root
, &def
) == -ENOENT
);
330 assert_se(unit_file_set_default(UNIT_FILE_SYSTEM
, 0, root
, "idontexist.target", &changes
, &n_changes
) == -ENOENT
);
331 assert_se(n_changes
== 1);
332 assert_se(changes
[0].type
== -ENOENT
);
333 assert_se(streq_ptr(changes
[0].path
, "idontexist.target"));
334 unit_file_changes_free(changes
, n_changes
);
335 changes
= NULL
; n_changes
= 0;
337 assert_se(unit_file_get_default(UNIT_FILE_SYSTEM
, root
, &def
) == -ENOENT
);
339 assert_se(unit_file_set_default(UNIT_FILE_SYSTEM
, 0, root
, "test-default.target", &changes
, &n_changes
) >= 0);
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"));
343 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/" SPECIAL_DEFAULT_TARGET
);
344 assert_se(streq(changes
[0].path
, p
));
345 unit_file_changes_free(changes
, n_changes
);
346 changes
= NULL
; n_changes
= 0;
348 assert_se(unit_file_get_default(UNIT_FILE_SYSTEM
, root
, &def
) >= 0);
349 assert_se(streq_ptr(def
, "test-default-real.target"));
352 static void test_add_dependency(const char *root
) {
353 UnitFileChange
*changes
= NULL
;
354 unsigned n_changes
= 0;
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);
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);
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);
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);
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);
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;
379 static void test_template_enable(const char *root
) {
380 UnitFileChange
*changes
= NULL
;
381 unsigned n_changes
= 0;
385 log_info("== %s ==", __func__
);
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
);
392 p
= strjoina(root
, "/usr/lib/systemd/system/template@.service");
393 assert_se(write_string_file(p
,
395 "DefaultInstance=def\n"
396 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
398 p
= strjoina(root
, "/usr/lib/systemd/system/template-symlink@.service");
399 assert_se(symlink("template@.service", p
) >= 0);
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
);
408 log_info("== %s with template@.service enabled ==", __func__
);
410 assert_se(unit_file_enable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("template@.service"), &changes
, &n_changes
) >= 0);
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;
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
);
426 assert_se(unit_file_disable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("template@.service"), &changes
, &n_changes
) >= 0);
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;
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
);
440 log_info("== %s with template@foo.service enabled ==", __func__
);
442 assert_se(unit_file_enable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("template@foo.service"), &changes
, &n_changes
) >= 0);
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;
450 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template@.service", &state
) >= 0 && state
== UNIT_FILE_INDIRECT
);
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
);
457 assert_se(unit_file_disable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("template@foo.service"), &changes
, &n_changes
) >= 0);
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;
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
);
473 log_info("== %s with template-symlink@quux.service enabled ==", __func__
);
475 assert_se(unit_file_enable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("template-symlink@quux.service"), &changes
, &n_changes
) >= 0);
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;
483 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template@.service", &state
) >= 0 && state
== UNIT_FILE_INDIRECT
);
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
);
487 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "template-symlink@.service", &state
) >= 0 && state
== UNIT_FILE_INDIRECT
);
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
);
493 static void test_indirect(const char *root
) {
494 UnitFileChange
*changes
= NULL
;
495 unsigned n_changes
= 0;
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
);
503 p
= strjoina(root
, "/usr/lib/systemd/system/indirecta.service");
504 assert_se(write_string_file(p
,
506 "Also=indirectb.service\n", WRITE_STRING_FILE_CREATE
) >= 0);
508 p
= strjoina(root
, "/usr/lib/systemd/system/indirectb.service");
509 assert_se(write_string_file(p
,
511 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
513 p
= strjoina(root
, "/usr/lib/systemd/system/indirectc.service");
514 assert_se(symlink("indirecta.service", p
) >= 0);
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
);
520 assert_se(unit_file_enable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("indirectc.service"), &changes
, &n_changes
) >= 0);
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;
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
);
533 assert_se(unit_file_disable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("indirectc.service"), &changes
, &n_changes
) >= 0);
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;
542 static void test_preset_and_list(const char *root
) {
543 UnitFileChange
*changes
= NULL
;
544 unsigned n_changes
= 0, i
;
547 bool got_yes
= false, got_no
= false;
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
);
555 p
= strjoina(root
, "/usr/lib/systemd/system/preset-yes.service");
556 assert_se(write_string_file(p
,
558 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
560 p
= strjoina(root
, "/usr/lib/systemd/system/preset-no.service");
561 assert_se(write_string_file(p
,
563 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
565 p
= strjoina(root
, "/usr/lib/systemd/system-preset/test.preset");
566 assert_se(write_string_file(p
,
568 "disable *\n", WRITE_STRING_FILE_CREATE
) >= 0);
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
);
573 assert_se(unit_file_preset(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("preset-yes.service"), UNIT_FILE_PRESET_FULL
, &changes
, &n_changes
) >= 0);
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;
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
);
585 assert_se(unit_file_disable(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("preset-yes.service"), &changes
, &n_changes
) >= 0);
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;
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
);
596 assert_se(unit_file_preset(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("preset-no.service"), UNIT_FILE_PRESET_FULL
, &changes
, &n_changes
) >= 0);
597 assert_se(n_changes
== 0);
598 unit_file_changes_free(changes
, n_changes
);
599 changes
= NULL
; n_changes
= 0;
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
);
604 assert_se(unit_file_preset_all(UNIT_FILE_SYSTEM
, 0, root
, UNIT_FILE_PRESET_FULL
, &changes
, &n_changes
) >= 0);
606 assert_se(n_changes
> 0);
608 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/multi-user.target.wants/preset-yes.service");
610 for (i
= 0; i
< n_changes
; i
++) {
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
));
616 assert_se(changes
[i
].type
== UNIT_FILE_UNLINK
);
619 unit_file_changes_free(changes
, n_changes
);
620 changes
= NULL
; n_changes
= 0;
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
);
625 assert_se(h
= hashmap_new(&string_hash_ops
));
626 assert_se(unit_file_get_list(UNIT_FILE_SYSTEM
, root
, h
, NULL
, NULL
) >= 0);
628 p
= strjoina(root
, "/usr/lib/systemd/system/preset-yes.service");
629 q
= strjoina(root
, "/usr/lib/systemd/system/preset-no.service");
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
);
635 if (streq(fl
->path
, p
)) {
637 assert_se(fl
->state
== UNIT_FILE_ENABLED
);
638 } else if (streq(fl
->path
, q
)) {
640 assert_se(fl
->state
== UNIT_FILE_DISABLED
);
642 assert_se(IN_SET(fl
->state
, UNIT_FILE_DISABLED
, UNIT_FILE_STATIC
, UNIT_FILE_INDIRECT
));
645 unit_file_list_free(h
);
647 assert_se(got_yes
&& got_no
);
650 static void test_revert(const char *root
) {
653 UnitFileChange
*changes
= NULL
;
654 unsigned n_changes
= 0;
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
);
661 p
= strjoina(root
, "/usr/lib/systemd/system/xx.service");
662 assert_se(write_string_file(p
, "# Empty\n", WRITE_STRING_FILE_CREATE
) >= 0);
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
);
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;
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);
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;
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);
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
));
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;
701 static void test_preset_order(const char *root
) {
702 UnitFileChange
*changes
= NULL
;
703 unsigned n_changes
= 0;
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
);
710 p
= strjoina(root
, "/usr/lib/systemd/system/prefix-1.service");
711 assert_se(write_string_file(p
,
713 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
715 p
= strjoina(root
, "/usr/lib/systemd/system/prefix-2.service");
716 assert_se(write_string_file(p
,
718 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
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);
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
);
729 assert_se(unit_file_preset(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("prefix-1.service"), UNIT_FILE_PRESET_FULL
, &changes
, &n_changes
) >= 0);
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;
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
);
741 assert_se(unit_file_preset(UNIT_FILE_SYSTEM
, 0, root
, STRV_MAKE("prefix-2.service"), UNIT_FILE_PRESET_FULL
, &changes
, &n_changes
) >= 0);
742 assert_se(n_changes
== 0);
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
);
748 static void test_static_instance(const char *root
) {
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
);
755 p
= strjoina(root
, "/usr/lib/systemd/system/static-instance@.service");
756 assert_se(write_string_file(p
,
758 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
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
);
763 p
= strjoina(root
, "/usr/lib/systemd/system/static-instance@foo.service");
764 assert_se(symlink("static-instance@.service", p
) >= 0);
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
);
770 static void test_with_dropin(const char *root
) {
773 UnitFileChange
*changes
= NULL
;
774 unsigned n_changes
= 0;
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
);
782 p
= strjoina(root
, "/usr/lib/systemd/system/with-dropin-1.service");
783 assert_se(write_string_file(p
,
785 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
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
,
791 "WantedBy=graphical.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
793 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "with-dropin-1.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
795 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/with-dropin-2.service");
796 assert_se(write_string_file(p
,
798 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
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
,
804 "WantedBy=graphical.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
806 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "with-dropin-2.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
808 p
= strjoina(root
, "/usr/lib/systemd/system/with-dropin-3.service");
809 assert_se(write_string_file(p
,
811 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
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
,
817 "WantedBy=graphical.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
819 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "with-dropin-3.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
821 p
= strjoina(root
, "/usr/lib/systemd/system/with-dropin-4a.service");
822 assert_se(write_string_file(p
,
824 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
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
,
830 "Also=with-dropin-4b.service\n", WRITE_STRING_FILE_CREATE
) >= 0);
832 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "with-dropin-4a.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
834 p
= strjoina(root
, "/usr/lib/systemd/system/with-dropin-4b.service");
835 assert_se(write_string_file(p
,
837 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
839 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "with-dropin-4b.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
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;
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;
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;
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;
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
);
903 static void test_with_dropin_template(const char *root
) {
906 UnitFileChange
*changes
= NULL
;
907 unsigned n_changes
= 0;
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
);
913 p
= strjoina(root
, "/usr/lib/systemd/system/with-dropin-1@.service");
914 assert_se(write_string_file(p
,
916 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
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
,
922 "WantedBy=graphical.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
924 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "with-dropin-1@.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
926 p
= strjoina(root
, "/usr/lib/systemd/system/with-dropin-2@.service");
927 assert_se(write_string_file(p
,
929 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
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
,
935 "WantedBy=graphical.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
937 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "with-dropin-2@.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
939 p
= strjoina(root
, "/usr/lib/systemd/system/with-dropin-3@.service");
940 assert_se(write_string_file(p
,
942 "DefaultInstance=instance-1\n"
943 "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE
) >= 0);
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
,
949 "DefaultInstance=instance-2\n", WRITE_STRING_FILE_CREATE
) >= 0);
951 assert_se(unit_file_get_state(UNIT_FILE_SYSTEM
, root
, "with-dropin-3@.service", &state
) >= 0 && state
== UNIT_FILE_DISABLED
);
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;
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;
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;
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;
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
);
1004 int main(int argc
, char *argv
[]) {
1005 char root
[] = "/tmp/rootXXXXXX";
1008 assert_se(mkdtemp(root
));
1010 p
= strjoina(root
, "/usr/lib/systemd/system/");
1011 assert_se(mkdir_p(p
, 0755) >= 0);
1013 p
= strjoina(root
, SYSTEM_CONFIG_UNIT_PATH
"/");
1014 assert_se(mkdir_p(p
, 0755) >= 0);
1016 p
= strjoina(root
, "/run/systemd/system/");
1017 assert_se(mkdir_p(p
, 0755) >= 0);
1019 p
= strjoina(root
, "/opt/");
1020 assert_se(mkdir_p(p
, 0755) >= 0);
1022 p
= strjoina(root
, "/usr/lib/systemd/system-preset/");
1023 assert_se(mkdir_p(p
, 0755) >= 0);
1025 test_basic_mask_and_enable(root
);
1026 test_linked_units(root
);
1028 test_add_dependency(root
);
1029 test_template_enable(root
);
1030 test_indirect(root
);
1031 test_preset_and_list(root
);
1032 test_preset_order(root
);
1034 test_static_instance(root
);
1035 test_with_dropin(root
);
1036 test_with_dropin_template(root
);
1038 assert_se(rm_rf(root
, REMOVE_ROOT
|REMOVE_PHYSICAL
) >= 0);