]> git.ipfire.org Git - thirdparty/systemd.git/blame_incremental - src/test/test-cgroup-util.c
bus: fix return message if StartServiceByName() in the driver fails due
[thirdparty/systemd.git] / src / test / test-cgroup-util.c
... / ...
CommitLineData
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
28static 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
38static 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
50static 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
60static 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
74static 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
84static 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
99static 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
106static 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
112static 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
119static 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
125static void check_p_g_m_n(const char *path, int code, const char *result) {
126 _cleanup_free_ char *m = NULL;
127
128 assert_se(cg_path_get_machine_name(path, &m) == code);
129 assert_se(streq_ptr(m, result));
130}
131
132static void test_path_get_machine_name(void) {
133 check_p_g_m_n("/user.slice/machine-foobar.scope", 0, "foobar");
134 check_p_g_m_n("/machine-foobar.scope", 0, "foobar");
135 check_p_g_m_n("/user.slice/user-kuux.slice/machine-foobar.scope", 0, "foobar");
136 check_p_g_m_n("/user.slice/user-kuux.slice/machine-foobar.scope/asjhdkj", 0, "foobar");
137 check_p_g_m_n("", -ENOENT, NULL);
138}
139
140static void test_get_paths(void) {
141 _cleanup_free_ char *a = NULL;
142
143 assert_se(cg_get_root_path(&a) >= 0);
144 log_info("Root = %s", a);
145}
146
147static void test_proc(void) {
148 _cleanup_closedir_ DIR *d = NULL;
149 struct dirent *de;
150 int r;
151
152 d = opendir("/proc");
153 assert_se(d);
154
155 FOREACH_DIRENT(de, d, break) {
156 _cleanup_free_ char *path = NULL, *path_shifted = NULL, *session = NULL, *unit = NULL, *user_unit = NULL, *machine = NULL, *slice = NULL;
157 pid_t pid;
158 uid_t uid = (uid_t) -1;
159
160 if (de->d_type != DT_DIR &&
161 de->d_type != DT_UNKNOWN)
162 continue;
163
164 r = parse_pid(de->d_name, &pid);
165 if (r < 0)
166 continue;
167
168 if (is_kernel_thread(pid))
169 continue;
170
171 cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &path);
172 cg_pid_get_path_shifted(pid, NULL, &path_shifted);
173 cg_pid_get_owner_uid(pid, &uid);
174 cg_pid_get_session(pid, &session);
175 cg_pid_get_unit(pid, &unit);
176 cg_pid_get_user_unit(pid, &user_unit);
177 cg_pid_get_machine_name(pid, &machine);
178 cg_pid_get_slice(pid, &slice);
179
180 printf("%lu\t%s\t%s\t%lu\t%s\t%s\t%s\t%s\t%s\n",
181 (unsigned long) pid,
182 path,
183 path_shifted,
184 (unsigned long) uid,
185 session,
186 unit,
187 user_unit,
188 machine,
189 slice);
190 }
191}
192
193static void test_escape_one(const char *s, const char *r) {
194 _cleanup_free_ char *b;
195
196 b = cg_escape(s);
197 assert_se(b);
198 assert_se(streq(b, r));
199
200 assert_se(streq(cg_unescape(b), s));
201}
202
203static void test_escape(void) {
204 test_escape_one("foobar", "foobar");
205 test_escape_one(".foobar", "_.foobar");
206 test_escape_one("foobar.service", "foobar.service");
207 test_escape_one("cgroup.service", "_cgroup.service");
208 test_escape_one("tasks", "_tasks");
209 if (access("/sys/fs/cgroup/cpu", F_OK) == 0)
210 test_escape_one("cpu.service", "_cpu.service");
211 test_escape_one("_foobar", "__foobar");
212 test_escape_one("", "_");
213 test_escape_one("_", "__");
214 test_escape_one(".", "_.");
215}
216
217static void test_controller_is_valid(void) {
218 assert_se(cg_controller_is_valid("foobar", false));
219 assert_se(cg_controller_is_valid("foo_bar", false));
220 assert_se(cg_controller_is_valid("name=foo", true));
221 assert_se(!cg_controller_is_valid("", false));
222 assert_se(!cg_controller_is_valid("name=", true));
223 assert_se(!cg_controller_is_valid("=", false));
224 assert_se(!cg_controller_is_valid("cpu,cpuacct", false));
225 assert_se(!cg_controller_is_valid("_", false));
226 assert_se(!cg_controller_is_valid("_foobar", false));
227 assert_se(!cg_controller_is_valid("tatü", false));
228}
229
230static void test_slice_to_path_one(const char *unit, const char *path, int error) {
231 _cleanup_free_ char *ret = NULL;
232
233 assert_se(cg_slice_to_path(unit, &ret) == error);
234 assert_se(streq_ptr(ret, path));
235}
236
237static void test_slice_to_path(void) {
238
239 test_slice_to_path_one("foobar.slice", "foobar.slice", 0);
240 test_slice_to_path_one("foobar-waldo.slice", "foobar.slice/foobar-waldo.slice", 0);
241 test_slice_to_path_one("foobar-waldo.service", NULL, -EINVAL);
242 test_slice_to_path_one("-.slice", NULL, -EINVAL);
243 test_slice_to_path_one("-foo-.slice", NULL, -EINVAL);
244 test_slice_to_path_one("-foo.slice", NULL, -EINVAL);
245 test_slice_to_path_one("a-b.slice", "a.slice/a-b.slice", 0);
246 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);
247}
248
249int 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_path_get_machine_name();
256 TEST_REQ_RUNNING_SYSTEMD(test_get_paths());
257 test_proc();
258 TEST_REQ_RUNNING_SYSTEMD(test_escape());
259 test_controller_is_valid();
260 test_slice_to_path();
261
262 return 0;
263}