chiark / gitweb /
logind: add infrastructure to keep track of machines, and move to slices
[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;
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
160                 printf("%lu\t%s\t%s\t%s\t%lu\t%s\t%s\t%s\t%s\n",
161                        (unsigned long) pid,
162                        path,
163                        prefix,
164                        path_shifted,
165                        (unsigned long) uid,
166                        session,
167                        unit,
168                        user_unit,
169                        machine);
170         }
171 }
172
173 static void test_escape_one(const char *s, const char *r) {
174         _cleanup_free_ char *b;
175
176         b = cg_escape(s);
177         assert_se(b);
178         assert_se(streq(b, r));
179
180         assert_se(streq(cg_unescape(b), s));
181 }
182
183 static void test_escape(void) {
184         test_escape_one("foobar", "foobar");
185         test_escape_one(".foobar", "_.foobar");
186         test_escape_one("foobar.service", "foobar.service");
187         test_escape_one("cgroup.service", "_cgroup.service");
188         test_escape_one("cpu.service", "_cpu.service");
189         test_escape_one("tasks", "_tasks");
190         test_escape_one("_foobar", "__foobar");
191         test_escape_one("", "_");
192         test_escape_one("_", "__");
193         test_escape_one(".", "_.");
194 }
195
196 static void test_controller_is_valid(void) {
197         assert_se(cg_controller_is_valid("foobar", false));
198         assert_se(cg_controller_is_valid("foo_bar", false));
199         assert_se(cg_controller_is_valid("name=foo", true));
200         assert_se(!cg_controller_is_valid("", false));
201         assert_se(!cg_controller_is_valid("name=", true));
202         assert_se(!cg_controller_is_valid("=", false));
203         assert_se(!cg_controller_is_valid("cpu,cpuacct", false));
204         assert_se(!cg_controller_is_valid("_", false));
205         assert_se(!cg_controller_is_valid("_foobar", false));
206         assert_se(!cg_controller_is_valid("tatü", false));
207 }
208
209 static void test_slice_to_path_one(const char *unit, const char *path, int error) {
210         _cleanup_free_ char *ret = NULL;
211
212         assert_se(cg_slice_to_path(unit, &ret) == error);
213         assert_se(streq_ptr(ret, path));
214 }
215
216 static void test_slice_to_path(void) {
217
218         test_slice_to_path_one("foobar.slice", "foobar.slice", 0);
219         test_slice_to_path_one("foobar-waldo.slice", "foobar.slice/foobar-waldo.slice", 0);
220         test_slice_to_path_one("foobar-waldo.service", NULL, -EINVAL);
221         test_slice_to_path_one("-.slice", NULL, -EINVAL);
222         test_slice_to_path_one("-foo-.slice", NULL, -EINVAL);
223         test_slice_to_path_one("-foo.slice", NULL, -EINVAL);
224         test_slice_to_path_one("a-b.slice", "a.slice/a-b.slice", 0);
225         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);
226 }
227
228 int main(void) {
229         test_path_decode_unit();
230         test_path_get_unit();
231         test_path_get_user_unit();
232         test_path_get_session();
233         test_path_get_owner_uid();
234         test_path_get_machine_name();
235         test_get_paths();
236         test_proc();
237         test_escape();
238         test_controller_is_valid();
239         test_slice_to_path();
240
241         return 0;
242 }