]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/test/test-cgroup-util.c
util-lib: introduce dirent-util.[ch] for directory entry calls
[thirdparty/systemd.git] / src / test / test-cgroup-util.c
CommitLineData
6c03089c
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2013 Zbigniew Jędrzejewski-Szmek
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
96cde13a 22#include "cgroup-util.h"
a0956174 23#include "dirent-util.h"
3ffd4af2 24#include "fd-util.h"
6482f626 25#include "formats-util.h"
6bedfcbb 26#include "parse-util.h"
0b452006 27#include "process-util.h"
07630cea 28#include "string-util.h"
3ffd4af2
LP
29#include "test-helper.h"
30#include "util.h"
96cde13a 31
7027ff61 32static void check_p_d_u(const char *path, int code, const char *result) {
6c03089c 33 _cleanup_free_ char *unit = NULL;
d4fffc4b 34 int r;
96cde13a 35
d4fffc4b
ZJS
36 r = cg_path_decode_unit(path, &unit);
37 printf("%s: %s → %s %d expected %s %d\n", __func__, path, unit, r, result, code);
38 assert_se(r == code);
6c03089c
LP
39 assert_se(streq_ptr(unit, result));
40}
96cde13a 41
7027ff61 42static void test_path_decode_unit(void) {
d7bd3de0
LP
43 check_p_d_u("getty@tty2.service", 0, "getty@tty2.service");
44 check_p_d_u("getty@tty2.service/", 0, "getty@tty2.service");
45 check_p_d_u("getty@tty2.service/xxx", 0, "getty@tty2.service");
cfeaa44a
LP
46 check_p_d_u("getty@.service/", -ENXIO, NULL);
47 check_p_d_u("getty@.service", -ENXIO, NULL);
7027ff61 48 check_p_d_u("getty.service", 0, "getty.service");
cfeaa44a
LP
49 check_p_d_u("getty", -ENXIO, NULL);
50 check_p_d_u("getty/waldo", -ENXIO, NULL);
d7bd3de0 51 check_p_d_u("_cpu.service", 0, "cpu.service");
6c03089c
LP
52}
53
54static void check_p_g_u(const char *path, int code, const char *result) {
55 _cleanup_free_ char *unit = NULL;
d4fffc4b 56 int r;
6c03089c 57
d4fffc4b
ZJS
58 r = cg_path_get_unit(path, &unit);
59 printf("%s: %s → %s %d expected %s %d\n", __func__, path, unit, r, result, code);
60 assert_se(r == code);
6c03089c
LP
61 assert_se(streq_ptr(unit, result));
62}
63
9444b1f2
LP
64static void test_path_get_unit(void) {
65 check_p_g_u("/system.slice/foobar.service/sdfdsaf", 0, "foobar.service");
d7bd3de0
LP
66 check_p_g_u("/system.slice/getty@tty5.service", 0, "getty@tty5.service");
67 check_p_g_u("/system.slice/getty@tty5.service/aaa/bbb", 0, "getty@tty5.service");
68 check_p_g_u("/system.slice/getty@tty5.service/", 0, "getty@tty5.service");
9444b1f2 69 check_p_g_u("/system.slice/getty@tty6.service/tty5", 0, "getty@tty6.service");
cfeaa44a
LP
70 check_p_g_u("sadfdsafsda", -ENXIO, NULL);
71 check_p_g_u("/system.slice/getty####@tty6.service/xxx", -ENXIO, NULL);
9444b1f2 72 check_p_g_u("/system.slice/system-waldo.slice/foobar.service/sdfdsaf", 0, "foobar.service");
d7bd3de0 73 check_p_g_u("/system.slice/system-waldo.slice/_cpu.service/sdfdsaf", 0, "cpu.service");
d4fffc4b 74 check_p_g_u("/user.slice/user-1000.slice/user@1000.service/server.service", 0, "user@1000.service");
cfeaa44a 75 check_p_g_u("/user.slice/user-1000.slice/user@.service/server.service", -ENXIO, NULL);
9444b1f2
LP
76}
77
6c03089c
LP
78static void check_p_g_u_u(const char *path, int code, const char *result) {
79 _cleanup_free_ char *unit = NULL;
d4fffc4b 80 int r;
6c03089c 81
d4fffc4b
ZJS
82 r = cg_path_get_user_unit(path, &unit);
83 printf("%s: %s → %s %d expected %s %d\n", __func__, path, unit, r, result, code);
84 assert_se(r == code);
6c03089c
LP
85 assert_se(streq_ptr(unit, result));
86}
87
9444b1f2 88static void test_path_get_user_unit(void) {
374ec6ab
LP
89 check_p_g_u_u("/user.slice/user-1000.slice/session-2.scope/foobar.service", 0, "foobar.service");
90 check_p_g_u_u("/user.slice/user-1000.slice/session-2.scope/waldo.slice/foobar.service", 0, "foobar.service");
91 check_p_g_u_u("/user.slice/user-1002.slice/session-2.scope/foobar.service/waldo", 0, "foobar.service");
92 check_p_g_u_u("/user.slice/user-1000.slice/session-2.scope/foobar.service/waldo/uuuux", 0, "foobar.service");
cfeaa44a 93 check_p_g_u_u("/user.slice/user-1000.slice/session-2.scope/waldo/waldo/uuuux", -ENXIO, NULL);
d7bd3de0
LP
94 check_p_g_u_u("/user.slice/user-1000.slice/session-2.scope/foobar@pie.service/pa/po", 0, "foobar@pie.service");
95 check_p_g_u_u("/session-2.scope/foobar@pie.service/pa/po", 0, "foobar@pie.service");
96 check_p_g_u_u("/xyz.slice/xyz-waldo.slice/session-77.scope/foobar@pie.service/pa/po", 0, "foobar@pie.service");
cfeaa44a 97 check_p_g_u_u("/meh.service", -ENXIO, NULL);
d7bd3de0 98 check_p_g_u_u("/session-3.scope/_cpu.service", 0, "cpu.service");
d4fffc4b 99 check_p_g_u_u("/user.slice/user-1000.slice/user@1000.service/server.service", 0, "server.service");
32081481 100 check_p_g_u_u("/user.slice/user-1000.slice/user@1000.service/foobar.slice/foobar@pie.service", 0, "foobar@pie.service");
cfeaa44a 101 check_p_g_u_u("/user.slice/user-1000.slice/user@.service/server.service", -ENXIO, NULL);
7027ff61 102}
6c03089c 103
9444b1f2
LP
104static void check_p_g_s(const char *path, int code, const char *result) {
105 _cleanup_free_ char *s = NULL;
106
107 assert_se(cg_path_get_session(path, &s) == code);
108 assert_se(streq_ptr(s, result));
96cde13a
ZJS
109}
110
9444b1f2 111static void test_path_get_session(void) {
374ec6ab
LP
112 check_p_g_s("/user.slice/user-1000.slice/session-2.scope/foobar.service", 0, "2");
113 check_p_g_s("/session-3.scope", 0, "3");
cfeaa44a
LP
114 check_p_g_s("/session-.scope", -ENXIO, NULL);
115 check_p_g_s("", -ENXIO, NULL);
9444b1f2 116}
7027ff61 117
9444b1f2
LP
118static void check_p_g_o_u(const char *path, int code, uid_t result) {
119 uid_t uid = 0;
7027ff61 120
9444b1f2
LP
121 assert_se(cg_path_get_owner_uid(path, &uid) == code);
122 assert_se(uid == result);
123}
124
125static void test_path_get_owner_uid(void) {
374ec6ab
LP
126 check_p_g_o_u("/user.slice/user-1000.slice/session-2.scope/foobar.service", 0, 1000);
127 check_p_g_o_u("/user.slice/user-1006.slice", 0, 1006);
cfeaa44a 128 check_p_g_o_u("", -ENXIO, 0);
9444b1f2 129}
7027ff61 130
8b0849e9
LP
131static void check_p_g_slice(const char *path, int code, const char *result) {
132 _cleanup_free_ char *s = NULL;
133
134 assert_se(cg_path_get_slice(path, &s) == code);
135 assert_se(streq_ptr(s, result));
136}
137
138static void test_path_get_slice(void) {
139 check_p_g_slice("/user.slice", 0, "user.slice");
140 check_p_g_slice("/foobar", 0, "-.slice");
141 check_p_g_slice("/user.slice/user-waldo.slice", 0, "user-waldo.slice");
142 check_p_g_slice("", 0, "-.slice");
143 check_p_g_slice("foobar", 0, "-.slice");
144 check_p_g_slice("foobar.slice", 0, "foobar.slice");
145 check_p_g_slice("foo.slice/foo-bar.slice/waldo.service", 0, "foo-bar.slice");
146}
147
329ac4bc
LP
148static void check_p_g_u_slice(const char *path, int code, const char *result) {
149 _cleanup_free_ char *s = NULL;
150
151 assert_se(cg_path_get_user_slice(path, &s) == code);
152 assert_se(streq_ptr(s, result));
153}
154
155static void test_path_get_user_slice(void) {
156 check_p_g_u_slice("/user.slice", -ENXIO, NULL);
157 check_p_g_u_slice("/foobar", -ENXIO, NULL);
158 check_p_g_u_slice("/user.slice/user-waldo.slice", -ENXIO, NULL);
159 check_p_g_u_slice("", -ENXIO, NULL);
160 check_p_g_u_slice("foobar", -ENXIO, NULL);
161 check_p_g_u_slice("foobar.slice", -ENXIO, NULL);
162 check_p_g_u_slice("foo.slice/foo-bar.slice/waldo.service", -ENXIO, NULL);
163
164 check_p_g_u_slice("foo.slice/foo-bar.slice/user@1000.service", 0, "-.slice");
165 check_p_g_u_slice("foo.slice/foo-bar.slice/user@1000.service/", 0, "-.slice");
166 check_p_g_u_slice("foo.slice/foo-bar.slice/user@1000.service///", 0, "-.slice");
167 check_p_g_u_slice("foo.slice/foo-bar.slice/user@1000.service/waldo.service", 0, "-.slice");
168 check_p_g_u_slice("foo.slice/foo-bar.slice/user@1000.service/piep.slice/foo.service", 0, "piep.slice");
169 check_p_g_u_slice("/foo.slice//foo-bar.slice/user@1000.service/piep.slice//piep-pap.slice//foo.service", 0, "piep-pap.slice");
170}
171
9444b1f2
LP
172static void test_get_paths(void) {
173 _cleanup_free_ char *a = NULL;
174
175 assert_se(cg_get_root_path(&a) >= 0);
176 log_info("Root = %s", a);
7027ff61
LP
177}
178
aff38e74
LP
179static void test_proc(void) {
180 _cleanup_closedir_ DIR *d = NULL;
181 struct dirent *de;
182 int r;
183
184 d = opendir("/proc");
185 assert_se(d);
186
187 FOREACH_DIRENT(de, d, break) {
e9174f29 188 _cleanup_free_ char *path = NULL, *path_shifted = NULL, *session = NULL, *unit = NULL, *user_unit = NULL, *machine = NULL, *slice = NULL;
aff38e74 189 pid_t pid;
fed1e721 190 uid_t uid = UID_INVALID;
aff38e74
LP
191
192 if (de->d_type != DT_DIR &&
193 de->d_type != DT_UNKNOWN)
194 continue;
195
196 r = parse_pid(de->d_name, &pid);
197 if (r < 0)
198 continue;
199
ae018d9b
LP
200 if (is_kernel_thread(pid))
201 continue;
202
aff38e74 203 cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &path);
e9174f29 204 cg_pid_get_path_shifted(pid, NULL, &path_shifted);
ae018d9b 205 cg_pid_get_owner_uid(pid, &uid);
aff38e74
LP
206 cg_pid_get_session(pid, &session);
207 cg_pid_get_unit(pid, &unit);
208 cg_pid_get_user_unit(pid, &user_unit);
209 cg_pid_get_machine_name(pid, &machine);
1021b21b 210 cg_pid_get_slice(pid, &slice);
aff38e74 211
de0671ee
ZJS
212 printf(PID_FMT"\t%s\t%s\t"UID_FMT"\t%s\t%s\t%s\t%s\t%s\n",
213 pid,
aff38e74 214 path,
aff38e74 215 path_shifted,
de0671ee 216 uid,
aff38e74
LP
217 session,
218 unit,
219 user_unit,
1021b21b
LP
220 machine,
221 slice);
aff38e74
LP
222 }
223}
224
ae018d9b
LP
225static void test_escape_one(const char *s, const char *r) {
226 _cleanup_free_ char *b;
227
228 b = cg_escape(s);
229 assert_se(b);
230 assert_se(streq(b, r));
231
232 assert_se(streq(cg_unescape(b), s));
233}
234
235static void test_escape(void) {
236 test_escape_one("foobar", "foobar");
a0ab5665 237 test_escape_one(".foobar", "_.foobar");
ae018d9b
LP
238 test_escape_one("foobar.service", "foobar.service");
239 test_escape_one("cgroup.service", "_cgroup.service");
ae018d9b 240 test_escape_one("tasks", "_tasks");
e13bb5d2
KS
241 if (access("/sys/fs/cgroup/cpu", F_OK) == 0)
242 test_escape_one("cpu.service", "_cpu.service");
ae018d9b 243 test_escape_one("_foobar", "__foobar");
a0ab5665
LP
244 test_escape_one("", "_");
245 test_escape_one("_", "__");
246 test_escape_one(".", "_.");
ae018d9b
LP
247}
248
78edb35a 249static void test_controller_is_valid(void) {
185a0874
DJL
250 assert_se(cg_controller_is_valid("foobar"));
251 assert_se(cg_controller_is_valid("foo_bar"));
252 assert_se(cg_controller_is_valid("name=foo"));
253 assert_se(!cg_controller_is_valid(""));
254 assert_se(!cg_controller_is_valid("name="));
255 assert_se(!cg_controller_is_valid("="));
256 assert_se(!cg_controller_is_valid("cpu,cpuacct"));
257 assert_se(!cg_controller_is_valid("_"));
258 assert_se(!cg_controller_is_valid("_foobar"));
259 assert_se(!cg_controller_is_valid("tatü"));
78edb35a
LP
260}
261
a016b922
LP
262static void test_slice_to_path_one(const char *unit, const char *path, int error) {
263 _cleanup_free_ char *ret = NULL;
264
265 assert_se(cg_slice_to_path(unit, &ret) == error);
266 assert_se(streq_ptr(ret, path));
267}
268
269static void test_slice_to_path(void) {
270
271 test_slice_to_path_one("foobar.slice", "foobar.slice", 0);
272 test_slice_to_path_one("foobar-waldo.slice", "foobar.slice/foobar-waldo.slice", 0);
273 test_slice_to_path_one("foobar-waldo.service", NULL, -EINVAL);
c96cc582
LP
274 test_slice_to_path_one("-.slice", "", 0);
275 test_slice_to_path_one("--.slice", NULL, -EINVAL);
276 test_slice_to_path_one("-", NULL, -EINVAL);
a016b922
LP
277 test_slice_to_path_one("-foo-.slice", NULL, -EINVAL);
278 test_slice_to_path_one("-foo.slice", NULL, -EINVAL);
c96cc582 279 test_slice_to_path_one("foo-.slice", NULL, -EINVAL);
e66e5b61 280 test_slice_to_path_one("foo--bar.slice", NULL, -EINVAL);
c96cc582 281 test_slice_to_path_one("foo.slice/foo--bar.slice", NULL, -EINVAL);
a016b922
LP
282 test_slice_to_path_one("a-b.slice", "a.slice/a-b.slice", 0);
283 test_slice_to_path_one("a-b-c-d-e.slice", "a.slice/a-b.slice/a-b-c.slice/a-b-c-d.slice/a-b-c-d-e.slice", 0);
284}
285
751bc6ac
LP
286static void test_shift_path_one(const char *raw, const char *root, const char *shifted) {
287 const char *s = NULL;
288
289 assert_se(cg_shift_path(raw, root, &s) >= 0);
290 assert_se(streq(s, shifted));
291}
292
293static void test_shift_path(void) {
294
295 test_shift_path_one("/foobar/waldo", "/", "/foobar/waldo");
296 test_shift_path_one("/foobar/waldo", "", "/foobar/waldo");
297 test_shift_path_one("/foobar/waldo", "/foobar", "/waldo");
298 test_shift_path_one("/foobar/waldo", "/fuckfuck", "/foobar/waldo");
299}
300
5f4c5fef
LP
301static void test_mask_supported(void) {
302
303 CGroupMask m;
304 CGroupController c;
305
306 assert_se(cg_mask_supported(&m) >= 0);
307
308 for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++)
309 printf("'%s' is supported: %s\n", cgroup_controller_to_string(c), yes_no(m & CGROUP_CONTROLLER_TO_MASK(c)));
310}
311
96cde13a 312int main(void) {
7027ff61 313 test_path_decode_unit();
6c03089c 314 test_path_get_unit();
7027ff61 315 test_path_get_user_unit();
9444b1f2
LP
316 test_path_get_session();
317 test_path_get_owner_uid();
8b0849e9 318 test_path_get_slice();
329ac4bc 319 test_path_get_user_slice();
143bfdaf 320 TEST_REQ_RUNNING_SYSTEMD(test_get_paths());
aff38e74 321 test_proc();
143bfdaf 322 TEST_REQ_RUNNING_SYSTEMD(test_escape());
78edb35a 323 test_controller_is_valid();
a016b922 324 test_slice_to_path();
751bc6ac 325 test_shift_path();
b3a7ba89 326 TEST_REQ_RUNNING_SYSTEMD(test_mask_supported());
96cde13a
ZJS
327
328 return 0;
329}