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