]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/test/test-path.c
core/manager: split out function to verify that unit is loaded and not masked
[thirdparty/systemd.git] / src / test / test-path.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
bc999297
RC
2/***
3 This file is part of systemd.
4
5 Copyright 2014 Ronny Chevalier
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
20
bc999297 21#include <stdbool.h>
07630cea 22#include <stdio.h>
edb3ca0d
FB
23#include <sys/stat.h>
24#include <sys/types.h>
bc999297 25
b5efdb8a 26#include "alloc-util.h"
f4f15635
LP
27#include "fd-util.h"
28#include "fs-util.h"
bc999297 29#include "macro.h"
07630cea 30#include "manager.h"
bc999297 31#include "mkdir.h"
c6878637 32#include "rm-rf.h"
07630cea
LP
33#include "string-util.h"
34#include "strv.h"
8b3aa503 35#include "test-helper.h"
d2120590 36#include "tests.h"
07630cea
LP
37#include "unit.h"
38#include "util.h"
bc999297
RC
39
40typedef void (*test_function_t)(Manager *m);
41
42static int setup_test(Manager **m) {
43 char **tests_path = STRV_MAKE("exists", "existsglobFOOBAR", "changed", "modified", "unit",
44 "directorynotempty", "makedirectory");
45 char **test_path;
a7f7d1bd 46 Manager *tmp = NULL;
bc999297
RC
47 int r;
48
49 assert_se(m);
50
651d47d1
ZJS
51 r = enter_cgroup_subroot();
52 if (r == -ENOMEDIUM) {
53 log_notice_errno(r, "Skipping test: cgroupfs not available");
be21bf85 54 return -EXIT_TEST_SKIP;
651d47d1 55 }
8c759b33 56
e8112e67 57 r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_BASIC, &tmp);
8b3aa503 58 if (MANAGER_SKIP_TEST(r)) {
9eec7d12 59 log_notice_errno(r, "Skipping test: manager_new: %m");
bc999297
RC
60 return -EXIT_TEST_SKIP;
61 }
62 assert_se(r >= 0);
63 assert_se(manager_startup(tmp, NULL, NULL) >= 0);
64
65 STRV_FOREACH(test_path, tests_path) {
c6878637
LP
66 _cleanup_free_ char *p = NULL;
67
605405c6 68 p = strjoin("/tmp/test-path_", *test_path);
c6878637
LP
69 assert_se(p);
70
71 (void) rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL);
bc999297
RC
72 }
73
74 *m = tmp;
75
76 return 0;
77}
78
79static void shutdown_test(Manager *m) {
80 assert_se(m);
81
82 manager_free(m);
83}
84
85static void check_stop_unlink(Manager *m, Unit *unit, const char *test_path, const char *service_name) {
86 _cleanup_free_ char *tmp = NULL;
87 Unit *service_unit = NULL;
88 Service *service = NULL;
89 usec_t ts;
90 usec_t timeout = 2 * USEC_PER_SEC;
91
92 assert_se(m);
93 assert_se(unit);
94 assert_se(test_path);
95
96 if (!service_name) {
97 assert_se(tmp = strreplace(unit->id, ".path", ".service"));
98 service_unit = manager_get_unit(m, tmp);
99 } else
100 service_unit = manager_get_unit(m, service_name);
101 assert_se(service_unit);
102 service = SERVICE(service_unit);
103
104 ts = now(CLOCK_MONOTONIC);
f131770b 105 /* We process events until the service related to the path has been successfully started */
9ed794a3 106 while (service->result != SERVICE_SUCCESS || service->state != SERVICE_START) {
bc999297
RC
107 usec_t n;
108 int r;
109
110 r = sd_event_run(m->event, 100 * USEC_PER_MSEC);
111 assert_se(r >= 0);
112
113 printf("%s: state = %s; result = %s \n",
114 service_unit->id,
115 service_state_to_string(service->state),
116 service_result_to_string(service->result));
117
118
119 /* But we timeout if the service has not been started in the allocated time */
120 n = now(CLOCK_MONOTONIC);
121 if (ts + timeout < n) {
122 log_error("Test timeout when testing %s", unit->id);
123 exit(EXIT_FAILURE);
124 }
125 }
126
127 assert_se(UNIT_VTABLE(unit)->stop(unit) >= 0);
c6878637 128 (void) rm_rf(test_path, REMOVE_ROOT|REMOVE_PHYSICAL);
bc999297
RC
129}
130
131static void test_path_exists(Manager *m) {
132 const char *test_path = "/tmp/test-path_exists";
133 Unit *unit = NULL;
134
135 assert_se(m);
136
137 assert_se(manager_load_unit(m, "path-exists.path", NULL, NULL, &unit) >= 0);
138 assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
139
140 assert_se(touch(test_path) >= 0);
141
142 check_stop_unlink(m, unit, test_path, NULL);
143}
144
145static void test_path_existsglob(Manager *m) {
146 const char *test_path = "/tmp/test-path_existsglobFOOBAR";
147 Unit *unit = NULL;
148
149 assert_se(m);
150 assert_se(manager_load_unit(m, "path-existsglob.path", NULL, NULL, &unit) >= 0);
151 assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
152
153 assert_se(touch(test_path) >= 0);
154
155 check_stop_unlink(m, unit, test_path, NULL);
156}
157
158static void test_path_changed(Manager *m) {
159 const char *test_path = "/tmp/test-path_changed";
160 FILE *f;
161 Unit *unit = NULL;
162
163 assert_se(m);
164
165 assert_se(touch(test_path) >= 0);
166
167 assert_se(manager_load_unit(m, "path-changed.path", NULL, NULL, &unit) >= 0);
168 assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
169
170 f = fopen(test_path, "w");
171 assert_se(f);
172 fclose(f);
173
174 check_stop_unlink(m, unit, test_path, NULL);
175}
176
177static void test_path_modified(Manager *m) {
178 _cleanup_fclose_ FILE *f = NULL;
179 const char *test_path = "/tmp/test-path_modified";
180 Unit *unit = NULL;
181
182 assert_se(m);
183
184 assert_se(touch(test_path) >= 0);
185
186 assert_se(manager_load_unit(m, "path-modified.path", NULL, NULL, &unit) >= 0);
187 assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
188
189 f = fopen(test_path, "w");
190 assert_se(f);
191 fputs("test", f);
192
193 check_stop_unlink(m, unit, test_path, NULL);
194}
195
196static void test_path_unit(Manager *m) {
197 const char *test_path = "/tmp/test-path_unit";
198 Unit *unit = NULL;
199
200 assert_se(m);
201
202 assert_se(manager_load_unit(m, "path-unit.path", NULL, NULL, &unit) >= 0);
203 assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
204
205 assert_se(touch(test_path) >= 0);
206
207 check_stop_unlink(m, unit, test_path, "path-mycustomunit.service");
208}
209
210static void test_path_directorynotempty(Manager *m) {
211 const char *test_path = "/tmp/test-path_directorynotempty/";
212 Unit *unit = NULL;
213
214 assert_se(m);
215
216 assert_se(access(test_path, F_OK) < 0);
217
218 assert_se(manager_load_unit(m, "path-directorynotempty.path", NULL, NULL, &unit) >= 0);
219 assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
220
221 /* MakeDirectory default to no */
222 assert_se(access(test_path, F_OK) < 0);
223
224 assert_se(mkdir_p(test_path, 0755) >= 0);
63c372cb 225 assert_se(touch(strjoina(test_path, "test_file")) >= 0);
bc999297
RC
226
227 check_stop_unlink(m, unit, test_path, NULL);
228}
229
230static void test_path_makedirectory_directorymode(Manager *m) {
231 const char *test_path = "/tmp/test-path_makedirectory/";
232 Unit *unit = NULL;
233 struct stat s;
234
235 assert_se(m);
236
237 assert_se(access(test_path, F_OK) < 0);
238
239 assert_se(manager_load_unit(m, "path-makedirectory.path", NULL, NULL, &unit) >= 0);
240 assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
241
242 /* Check if the directory has been created */
243 assert_se(access(test_path, F_OK) >= 0);
244
245 /* Check the mode we specified with DirectoryMode=0744 */
246 assert_se(stat(test_path, &s) >= 0);
247 assert_se((s.st_mode & S_IRWXU) == 0700);
248 assert_se((s.st_mode & S_IRWXG) == 0040);
249 assert_se((s.st_mode & S_IRWXO) == 0004);
250
251 assert_se(UNIT_VTABLE(unit)->stop(unit) >= 0);
c6878637 252 (void) rm_rf(test_path, REMOVE_ROOT|REMOVE_PHYSICAL);
bc999297
RC
253}
254
255int main(int argc, char *argv[]) {
d2120590 256 static const test_function_t tests[] = {
bc999297
RC
257 test_path_exists,
258 test_path_existsglob,
259 test_path_changed,
260 test_path_modified,
261 test_path_unit,
262 test_path_directorynotempty,
263 test_path_makedirectory_directorymode,
264 NULL,
265 };
d2120590 266
f942504e 267 _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
d2120590 268 const test_function_t *test = NULL;
bc999297
RC
269 Manager *m = NULL;
270
edb3ca0d
FB
271 umask(022);
272
bc999297
RC
273 log_parse_environment();
274 log_open();
275
cc100a5a 276 assert_se(set_unit_path(get_testdata_dir("/test-path")) >= 0);
3e29e810 277 assert_se(runtime_dir = setup_fake_runtime_dir());
bc999297
RC
278
279 for (test = tests; test && *test; test++) {
280 int r;
281
282 /* We create a clean environment for each test */
283 r = setup_test(&m);
284 if (r < 0)
285 return -r;
286
287 (*test)(m);
288
289 shutdown_test(m);
290 }
291
292 return 0;
293}