]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/test/test-cgroup-util.c
shared: add process-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
ZJS
22
23#include "util.h"
24#include "cgroup-util.h"
143bfdaf 25#include "test-helper.h"
6482f626 26#include "formats-util.h"
0b452006 27#include "process-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");
7027ff61
LP
43 check_p_d_u("getty@.service/", -EINVAL, NULL);
44 check_p_d_u("getty@.service", -EINVAL, NULL);
45 check_p_d_u("getty.service", 0, "getty.service");
46 check_p_d_u("getty", -EINVAL, NULL);
d7bd3de0
LP
47 check_p_d_u("getty/waldo", -EINVAL, NULL);
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
LP
66 check_p_g_u("/system.slice/getty@tty6.service/tty5", 0, "getty@tty6.service");
67 check_p_g_u("sadfdsafsda", -EINVAL, NULL);
d7bd3de0 68 check_p_g_u("/system.slice/getty####@tty6.service/xxx", -EINVAL, 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
ZJS
71 check_p_g_u("/user.slice/user-1000.slice/user@1000.service/server.service", 0, "user@1000.service");
72 check_p_g_u("/user.slice/user-1000.slice/user@.service/server.service", -EINVAL, 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");
90 check_p_g_u_u("/user.slice/user-1000.slice/session-2.scope/waldo/waldo/uuuux", -EINVAL, 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");
9444b1f2 94 check_p_g_u_u("/meh.service", -ENOENT, 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");
d4fffc4b 98 check_p_g_u_u("/user.slice/user-1000.slice/user@.service/server.service", -ENOENT, 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");
a13ee4c7
ZJS
111 check_p_g_s("/session-.scope", -ENOENT, NULL);
112 check_p_g_s("", -ENOENT, 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);
9444b1f2
LP
125 check_p_g_o_u("", -ENOENT, 0);
126}
7027ff61 127
9444b1f2
LP
128static void test_get_paths(void) {
129 _cleanup_free_ char *a = NULL;
130
131 assert_se(cg_get_root_path(&a) >= 0);
132 log_info("Root = %s", a);
7027ff61
LP
133}
134
aff38e74
LP
135static void test_proc(void) {
136 _cleanup_closedir_ DIR *d = NULL;
137 struct dirent *de;
138 int r;
139
140 d = opendir("/proc");
141 assert_se(d);
142
143 FOREACH_DIRENT(de, d, break) {
e9174f29 144 _cleanup_free_ char *path = NULL, *path_shifted = NULL, *session = NULL, *unit = NULL, *user_unit = NULL, *machine = NULL, *slice = NULL;
aff38e74 145 pid_t pid;
fed1e721 146 uid_t uid = UID_INVALID;
aff38e74
LP
147
148 if (de->d_type != DT_DIR &&
149 de->d_type != DT_UNKNOWN)
150 continue;
151
152 r = parse_pid(de->d_name, &pid);
153 if (r < 0)
154 continue;
155
ae018d9b
LP
156 if (is_kernel_thread(pid))
157 continue;
158
aff38e74 159 cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &path);
e9174f29 160 cg_pid_get_path_shifted(pid, NULL, &path_shifted);
ae018d9b 161 cg_pid_get_owner_uid(pid, &uid);
aff38e74
LP
162 cg_pid_get_session(pid, &session);
163 cg_pid_get_unit(pid, &unit);
164 cg_pid_get_user_unit(pid, &user_unit);
165 cg_pid_get_machine_name(pid, &machine);
1021b21b 166 cg_pid_get_slice(pid, &slice);
aff38e74 167
de0671ee
ZJS
168 printf(PID_FMT"\t%s\t%s\t"UID_FMT"\t%s\t%s\t%s\t%s\t%s\n",
169 pid,
aff38e74 170 path,
aff38e74 171 path_shifted,
de0671ee 172 uid,
aff38e74
LP
173 session,
174 unit,
175 user_unit,
1021b21b
LP
176 machine,
177 slice);
aff38e74
LP
178 }
179}
180
ae018d9b
LP
181static void test_escape_one(const char *s, const char *r) {
182 _cleanup_free_ char *b;
183
184 b = cg_escape(s);
185 assert_se(b);
186 assert_se(streq(b, r));
187
188 assert_se(streq(cg_unescape(b), s));
189}
190
191static void test_escape(void) {
192 test_escape_one("foobar", "foobar");
a0ab5665 193 test_escape_one(".foobar", "_.foobar");
ae018d9b
LP
194 test_escape_one("foobar.service", "foobar.service");
195 test_escape_one("cgroup.service", "_cgroup.service");
ae018d9b 196 test_escape_one("tasks", "_tasks");
e13bb5d2
KS
197 if (access("/sys/fs/cgroup/cpu", F_OK) == 0)
198 test_escape_one("cpu.service", "_cpu.service");
ae018d9b 199 test_escape_one("_foobar", "__foobar");
a0ab5665
LP
200 test_escape_one("", "_");
201 test_escape_one("_", "__");
202 test_escape_one(".", "_.");
ae018d9b
LP
203}
204
78edb35a
LP
205static void test_controller_is_valid(void) {
206 assert_se(cg_controller_is_valid("foobar", false));
207 assert_se(cg_controller_is_valid("foo_bar", false));
208 assert_se(cg_controller_is_valid("name=foo", true));
209 assert_se(!cg_controller_is_valid("", false));
210 assert_se(!cg_controller_is_valid("name=", true));
211 assert_se(!cg_controller_is_valid("=", false));
212 assert_se(!cg_controller_is_valid("cpu,cpuacct", false));
213 assert_se(!cg_controller_is_valid("_", false));
214 assert_se(!cg_controller_is_valid("_foobar", false));
215 assert_se(!cg_controller_is_valid("tatü", false));
216}
217
a016b922
LP
218static void test_slice_to_path_one(const char *unit, const char *path, int error) {
219 _cleanup_free_ char *ret = NULL;
220
221 assert_se(cg_slice_to_path(unit, &ret) == error);
222 assert_se(streq_ptr(ret, path));
223}
224
225static void test_slice_to_path(void) {
226
227 test_slice_to_path_one("foobar.slice", "foobar.slice", 0);
228 test_slice_to_path_one("foobar-waldo.slice", "foobar.slice/foobar-waldo.slice", 0);
229 test_slice_to_path_one("foobar-waldo.service", NULL, -EINVAL);
230 test_slice_to_path_one("-.slice", NULL, -EINVAL);
231 test_slice_to_path_one("-foo-.slice", NULL, -EINVAL);
232 test_slice_to_path_one("-foo.slice", NULL, -EINVAL);
233 test_slice_to_path_one("a-b.slice", "a.slice/a-b.slice", 0);
234 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);
235}
236
751bc6ac
LP
237static void test_shift_path_one(const char *raw, const char *root, const char *shifted) {
238 const char *s = NULL;
239
240 assert_se(cg_shift_path(raw, root, &s) >= 0);
241 assert_se(streq(s, shifted));
242}
243
244static void test_shift_path(void) {
245
246 test_shift_path_one("/foobar/waldo", "/", "/foobar/waldo");
247 test_shift_path_one("/foobar/waldo", "", "/foobar/waldo");
248 test_shift_path_one("/foobar/waldo", "/foobar", "/waldo");
249 test_shift_path_one("/foobar/waldo", "/fuckfuck", "/foobar/waldo");
250}
251
96cde13a 252int main(void) {
7027ff61 253 test_path_decode_unit();
6c03089c 254 test_path_get_unit();
7027ff61 255 test_path_get_user_unit();
9444b1f2
LP
256 test_path_get_session();
257 test_path_get_owner_uid();
143bfdaf 258 TEST_REQ_RUNNING_SYSTEMD(test_get_paths());
aff38e74 259 test_proc();
143bfdaf 260 TEST_REQ_RUNNING_SYSTEMD(test_escape());
78edb35a 261 test_controller_is_valid();
a016b922 262 test_slice_to_path();
751bc6ac 263 test_shift_path();
96cde13a
ZJS
264
265 return 0;
266}