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