1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Zbigniew Jędrzejewski-Szmek
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.
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.
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/>.
25 #include "cgroup-util.h"
27 static void check_p_d_u(const char *path, int code, const char *result) {
28 _cleanup_free_ char *unit = NULL;
30 assert_se(cg_path_decode_unit(path, &unit) == code);
31 assert_se(streq_ptr(unit, result));
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);
43 static void check_p_g_u(const char *path, int code, const char *result) {
44 _cleanup_free_ char *unit = NULL;
46 assert_se(cg_path_get_unit(path, &unit) == code);
47 assert_se(streq_ptr(unit, result));
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");
61 static void check_p_g_u_u(const char *path, int code, const char *result) {
62 _cleanup_free_ char *unit = NULL;
64 assert_se(cg_path_get_user_unit(path, &unit) == code);
65 assert_se(streq_ptr(unit, result));
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);
80 static void check_p_g_s(const char *path, int code, const char *result) {
81 _cleanup_free_ char *s = NULL;
83 assert_se(cg_path_get_session(path, &s) == code);
84 assert_se(streq_ptr(s, result));
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);
93 static void check_p_g_o_u(const char *path, int code, uid_t result) {
96 assert_se(cg_path_get_owner_uid(path, &uid) == code);
97 assert_se(uid == result);
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);
106 static void check_p_g_m_n(const char *path, int code, const char *result) {
107 _cleanup_free_ char *m = NULL;
109 assert_se(cg_path_get_machine_name(path, &m) == code);
110 assert_se(streq_ptr(m, result));
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);
121 static void test_get_paths(void) {
122 _cleanup_free_ char *a = NULL;
124 assert_se(cg_get_root_path(&a) >= 0);
125 log_info("Root = %s", a);
128 static void test_proc(void) {
129 _cleanup_closedir_ DIR *d = NULL;
133 d = opendir("/proc");
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;
139 uid_t uid = (uid_t) -1;
141 if (de->d_type != DT_DIR &&
142 de->d_type != DT_UNKNOWN)
145 r = parse_pid(de->d_name, &pid);
149 if (is_kernel_thread(pid))
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);
161 printf("%lu\t%s\t%s\t%s\t%lu\t%s\t%s\t%s\t%s\t%s\n",
175 static void test_escape_one(const char *s, const char *r) {
176 _cleanup_free_ char *b;
180 assert_se(streq(b, r));
182 assert_se(streq(cg_unescape(b), s));
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(".", "_.");
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));
211 static void test_slice_to_path_one(const char *unit, const char *path, int error) {
212 _cleanup_free_ char *ret = NULL;
214 assert_se(cg_slice_to_path(unit, &ret) == error);
215 assert_se(streq_ptr(ret, path));
218 static void test_slice_to_path(void) {
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);
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();
240 test_controller_is_valid();
241 test_slice_to_path();