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