chiark / gitweb /
cgroup: always validate cgroup controller names
[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 check_p_g_u_u(const char *path, int code, const char *result) {
51         _cleanup_free_ char *unit = NULL;
52
53         assert_se(cg_path_get_user_unit(path, &unit) == code);
54         assert_se(streq_ptr(unit, result));
55 }
56
57 static void test_path_get_unit(void) {
58         check_p_g_u("/system/foobar.service/sdfdsaf", 0, "foobar.service");
59         check_p_g_u("/system/getty@.service/getty@tty5.service", 0, "getty@tty5.service");
60         check_p_g_u("/system/getty@.service/getty@tty5.service/aaa/bbb", 0, "getty@tty5.service");
61         check_p_g_u("/system/getty@.service/getty@tty5.service/", 0, "getty@tty5.service");
62         check_p_g_u("/system/getty@tty6.service/tty5", 0, "getty@tty6.service");
63         check_p_g_u("sadfdsafsda", -ENOENT, NULL);
64         check_p_g_u("/system/getty####@tty6.service/tty5", -EINVAL, NULL);
65 }
66
67 static void test_path_get_user_unit(void) {
68         check_p_g_u_u("/user/lennart/2/systemd-21548/foobar.service", 0, "foobar.service");
69         check_p_g_u_u("/user/lennart/2/systemd-21548/foobar.service/waldo", 0, "foobar.service");
70         check_p_g_u_u("/user/lennart/2/systemd-21548/foobar.service/waldo/uuuux", 0, "foobar.service");
71         check_p_g_u_u("/user/lennart/2/systemd-21548/waldo/waldo/uuuux", -EINVAL, NULL);
72         check_p_g_u_u("/user/lennart/2/foobar.service", -ENOENT, NULL);
73         check_p_g_u_u("/user/lennart/2/systemd-21548/foobar@.service/foobar@pie.service/pa/po", 0, "foobar@pie.service");
74 }
75
76 static void test_get_paths(void) {
77         _cleanup_free_ char *a = NULL, *b = NULL, *c = NULL, *d = NULL;
78
79         assert_se(cg_get_root_path(&a) >= 0);
80         log_info("Root = %s", a);
81
82         assert_se(cg_get_system_path(&b) >= 0);
83         log_info("System = %s", b);
84
85         assert_se(cg_get_user_path(&c) >= 0);
86         log_info("User = %s", c);
87
88         assert_se(cg_get_machine_path(&d) >= 0);
89         log_info("Machine = %s", d);
90 }
91
92 static void test_proc(void) {
93         _cleanup_closedir_ DIR *d = NULL;
94         struct dirent *de;
95         int r;
96
97         d = opendir("/proc");
98         assert_se(d);
99
100         FOREACH_DIRENT(de, d, break) {
101                 _cleanup_free_ char *path = NULL, *path_shifted = NULL, *session = NULL, *unit = NULL, *user_unit = NULL, *machine = NULL, *prefix = NULL;
102                 pid_t pid;
103                 uid_t uid = (uid_t) -1;
104
105                 if (de->d_type != DT_DIR &&
106                     de->d_type != DT_UNKNOWN)
107                         continue;
108
109                 r = parse_pid(de->d_name, &pid);
110                 if (r < 0)
111                         continue;
112
113                 if (is_kernel_thread(pid))
114                         continue;
115
116                 cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &path);
117                 cg_pid_get_path_shifted(pid, &prefix, &path_shifted);
118                 cg_pid_get_owner_uid(pid, &uid);
119                 cg_pid_get_session(pid, &session);
120                 cg_pid_get_unit(pid, &unit);
121                 cg_pid_get_user_unit(pid, &user_unit);
122                 cg_pid_get_machine_name(pid, &machine);
123
124                 printf("%lu\t%s\t%s\t%s\t%lu\t%s\t%s\t%s\t%s\n",
125                        (unsigned long) pid,
126                        path,
127                        prefix,
128                        path_shifted,
129                        (unsigned long) uid,
130                        session,
131                        unit,
132                        user_unit,
133                        machine);
134         }
135 }
136
137 static void test_escape_one(const char *s, const char *r) {
138         _cleanup_free_ char *b;
139
140         b = cg_escape(s);
141         assert_se(b);
142         assert_se(streq(b, r));
143
144         assert_se(streq(cg_unescape(b), s));
145 }
146
147 static void test_escape(void) {
148         test_escape_one("foobar", "foobar");
149         test_escape_one("foobar.service", "foobar.service");
150         test_escape_one("cgroup.service", "_cgroup.service");
151         test_escape_one("cpu.service", "_cpu.service");
152         test_escape_one("tasks", "_tasks");
153         test_escape_one("_foobar", "__foobar");
154 }
155
156 static void test_controller_is_valid(void) {
157         assert_se(cg_controller_is_valid("foobar", false));
158         assert_se(cg_controller_is_valid("foo_bar", false));
159         assert_se(cg_controller_is_valid("name=foo", true));
160         assert_se(!cg_controller_is_valid("", false));
161         assert_se(!cg_controller_is_valid("name=", true));
162         assert_se(!cg_controller_is_valid("=", false));
163         assert_se(!cg_controller_is_valid("cpu,cpuacct", false));
164         assert_se(!cg_controller_is_valid("_", false));
165         assert_se(!cg_controller_is_valid("_foobar", false));
166         assert_se(!cg_controller_is_valid("tatü", false));
167 }
168
169 int main(void) {
170         test_path_decode_unit();
171         test_path_get_unit();
172         test_path_get_user_unit();
173         test_get_paths();
174         test_proc();
175         test_escape();
176         test_controller_is_valid();
177
178         return 0;
179 }