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