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