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