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