chiark / gitweb /
core: general cgroup rework
[elogind.git] / src / test / test-cgroup-util.c
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
22 #include <assert.h>
23
24 #include "util.h"
25 #include "cgroup-util.h"
26
27 static void check_p_d_u(const char *path, int code, const char *result) {
28         _cleanup_free_ char *unit = NULL;
29
30         assert_se(cg_path_decode_unit(path, &unit) == code);
31         assert_se(streq_ptr(unit, result));
32 }
33
34 static void test_path_decode_unit(void) {
35         check_p_d_u("getty@.service/getty@tty2.service", 0, "getty@tty2.service");
36         check_p_d_u("getty@.service/getty@tty2.service/xxx", 0, "getty@tty2.service");
37         check_p_d_u("getty@.service/", -EINVAL, NULL);
38         check_p_d_u("getty@.service", -EINVAL, NULL);
39         check_p_d_u("getty.service", 0, "getty.service");
40         check_p_d_u("getty", -EINVAL, NULL);
41 }
42
43 static void check_p_g_u(const char *path, int code, const char *result) {
44         _cleanup_free_ char *unit = NULL;
45
46         assert_se(cg_path_get_unit(path, &unit) == code);
47         assert_se(streq_ptr(unit, result));
48 }
49
50 static void test_path_get_unit(void) {
51         check_p_g_u("/system.slice/foobar.service/sdfdsaf", 0, "foobar.service");
52         check_p_g_u("/system.slice/getty@.service/getty@tty5.service", 0, "getty@tty5.service");
53         check_p_g_u("/system.slice/getty@.service/getty@tty5.service/aaa/bbb", 0, "getty@tty5.service");
54         check_p_g_u("/system.slice/getty@.service/getty@tty5.service/", 0, "getty@tty5.service");
55         check_p_g_u("/system.slice/getty@tty6.service/tty5", 0, "getty@tty6.service");
56         check_p_g_u("sadfdsafsda", -EINVAL, NULL);
57         check_p_g_u("/system.slice/getty####@tty6.service/tty5", -EINVAL, NULL);
58         check_p_g_u("/system.slice/system-waldo.slice/foobar.service/sdfdsaf", 0, "foobar.service");
59 }
60
61 static void check_p_g_u_u(const char *path, int code, const char *result) {
62         _cleanup_free_ char *unit = NULL;
63
64         assert_se(cg_path_get_user_unit(path, &unit) == code);
65         assert_se(streq_ptr(unit, result));
66 }
67
68 static void test_path_get_user_unit(void) {
69         check_p_g_u_u("/user.slice/1000.user/2.session/systemd-21548/foobar.service", 0, "foobar.service");
70         check_p_g_u_u("/user.slice/1002.user/2.session/systemd-21548/foobar.service/waldo", 0, "foobar.service");
71         check_p_g_u_u("/user.slice/1000.user/2.session/systemd-21548/foobar.service/waldo/uuuux", 0, "foobar.service");
72         check_p_g_u_u("/user.slice/1000.user/2.session/systemd-21548/waldo/waldo/uuuux", -EINVAL, NULL);
73         check_p_g_u_u("/user.slice/1000.user/2.session/foobar.service", 0, "foobar.service");
74         check_p_g_u_u("/user.slice/1000.user/2.session/systemd-21548/foobar@.service/foobar@pie.service/pa/po", 0, "foobar@pie.service");
75         check_p_g_u_u("/2.session/systemd-21548/foobar@.service/foobar@pie.service/pa/po", 0, "foobar@pie.service");
76         check_p_g_u_u("/xyz.slice/xyz-waldo.slice/77.session/systemd-21548/foobar@.service/foobar@pie.service/pa/po", 0, "foobar@pie.service");
77         check_p_g_u_u("/meh.service", -ENOENT, NULL);
78 }
79
80 static void check_p_g_s(const char *path, int code, const char *result) {
81         _cleanup_free_ char *s = NULL;
82
83         assert_se(cg_path_get_session(path, &s) == code);
84         assert_se(streq_ptr(s, result));
85 }
86
87 static void test_path_get_session(void) {
88         check_p_g_s("/user.slice/1000.user/2.session/systemd-21548/foobar.service", 0, "2");
89         check_p_g_s("/3.session", 0, "3");
90         check_p_g_s("", -ENOENT, 0);
91 }
92
93 static void check_p_g_o_u(const char *path, int code, uid_t result) {
94         uid_t uid = 0;
95
96         assert_se(cg_path_get_owner_uid(path, &uid) == code);
97         assert_se(uid == result);
98 }
99
100 static void test_path_get_owner_uid(void) {
101         check_p_g_o_u("/user.slice/1000.user/2.session/systemd-21548/foobar.service", 0, 1000);
102         check_p_g_o_u("/1006.user", 0, 1006);
103         check_p_g_o_u("", -ENOENT, 0);
104 }
105
106 static void check_p_g_m_n(const char *path, int code, const char *result) {
107         _cleanup_free_ char *m = NULL;
108
109         assert_se(cg_path_get_machine_name(path, &m) == code);
110         assert_se(streq_ptr(m, result));
111 }
112
113 static void test_path_get_machine_name(void) {
114         check_p_g_m_n("/user.slice/foobar.machine", 0, "foobar");
115         check_p_g_m_n("/foobar.machine", 0, "foobar");
116         check_p_g_m_n("/user.slice/user-kuux.slice/foobar.machine", 0, "foobar");
117         check_p_g_m_n("/user.slice/user-kuux.slice/foobar.machine/asjhdkj", 0, "foobar");
118         check_p_g_m_n("", -ENOENT, NULL);
119 }
120
121 static void test_get_paths(void) {
122         _cleanup_free_ char *a = NULL;
123
124         assert_se(cg_get_root_path(&a) >= 0);
125         log_info("Root = %s", a);
126 }
127
128 static void test_proc(void) {
129         _cleanup_closedir_ DIR *d = NULL;
130         struct dirent *de;
131         int r;
132
133         d = opendir("/proc");
134         assert_se(d);
135
136         FOREACH_DIRENT(de, d, break) {
137                 _cleanup_free_ char *path = NULL, *path_shifted = NULL, *session = NULL, *unit = NULL, *user_unit = NULL, *machine = NULL, *prefix = NULL, *slice = NULL;
138                 pid_t pid;
139                 uid_t uid = (uid_t) -1;
140
141                 if (de->d_type != DT_DIR &&
142                     de->d_type != DT_UNKNOWN)
143                         continue;
144
145                 r = parse_pid(de->d_name, &pid);
146                 if (r < 0)
147                         continue;
148
149                 if (is_kernel_thread(pid))
150                         continue;
151
152                 cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &path);
153                 cg_pid_get_path_shifted(pid, &prefix, &path_shifted);
154                 cg_pid_get_owner_uid(pid, &uid);
155                 cg_pid_get_session(pid, &session);
156                 cg_pid_get_unit(pid, &unit);
157                 cg_pid_get_user_unit(pid, &user_unit);
158                 cg_pid_get_machine_name(pid, &machine);
159                 cg_pid_get_slice(pid, &slice);
160
161                 printf("%lu\t%s\t%s\t%s\t%lu\t%s\t%s\t%s\t%s\t%s\n",
162                        (unsigned long) pid,
163                        path,
164                        prefix,
165                        path_shifted,
166                        (unsigned long) uid,
167                        session,
168                        unit,
169                        user_unit,
170                        machine,
171                        slice);
172         }
173 }
174
175 static void test_escape_one(const char *s, const char *r) {
176         _cleanup_free_ char *b;
177
178         b = cg_escape(s);
179         assert_se(b);
180         assert_se(streq(b, r));
181
182         assert_se(streq(cg_unescape(b), s));
183 }
184
185 static void test_escape(void) {
186         test_escape_one("foobar", "foobar");
187         test_escape_one(".foobar", "_.foobar");
188         test_escape_one("foobar.service", "foobar.service");
189         test_escape_one("cgroup.service", "_cgroup.service");
190         test_escape_one("cpu.service", "_cpu.service");
191         test_escape_one("tasks", "_tasks");
192         test_escape_one("_foobar", "__foobar");
193         test_escape_one("", "_");
194         test_escape_one("_", "__");
195         test_escape_one(".", "_.");
196 }
197
198 static void test_controller_is_valid(void) {
199         assert_se(cg_controller_is_valid("foobar", false));
200         assert_se(cg_controller_is_valid("foo_bar", false));
201         assert_se(cg_controller_is_valid("name=foo", true));
202         assert_se(!cg_controller_is_valid("", false));
203         assert_se(!cg_controller_is_valid("name=", true));
204         assert_se(!cg_controller_is_valid("=", false));
205         assert_se(!cg_controller_is_valid("cpu,cpuacct", false));
206         assert_se(!cg_controller_is_valid("_", false));
207         assert_se(!cg_controller_is_valid("_foobar", false));
208         assert_se(!cg_controller_is_valid("tatü", false));
209 }
210
211 static void test_slice_to_path_one(const char *unit, const char *path, int error) {
212         _cleanup_free_ char *ret = NULL;
213
214         assert_se(cg_slice_to_path(unit, &ret) == error);
215         assert_se(streq_ptr(ret, path));
216 }
217
218 static void test_slice_to_path(void) {
219
220         test_slice_to_path_one("foobar.slice", "foobar.slice", 0);
221         test_slice_to_path_one("foobar-waldo.slice", "foobar.slice/foobar-waldo.slice", 0);
222         test_slice_to_path_one("foobar-waldo.service", NULL, -EINVAL);
223         test_slice_to_path_one("-.slice", NULL, -EINVAL);
224         test_slice_to_path_one("-foo-.slice", NULL, -EINVAL);
225         test_slice_to_path_one("-foo.slice", NULL, -EINVAL);
226         test_slice_to_path_one("a-b.slice", "a.slice/a-b.slice", 0);
227         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);
228 }
229
230 int main(void) {
231         test_path_decode_unit();
232         test_path_get_unit();
233         test_path_get_user_unit();
234         test_path_get_session();
235         test_path_get_owner_uid();
236         test_path_get_machine_name();
237         test_get_paths();
238         test_proc();
239         test_escape();
240         test_controller_is_valid();
241         test_slice_to_path();
242
243         return 0;
244 }