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