]>
Commit | Line | Data |
---|---|---|
1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ | |
2 | ||
3 | #include <unistd.h> | |
4 | ||
5 | #include "cgroup-setup.h" | |
6 | #include "cgroup-util.h" | |
7 | #include "errno-util.h" | |
8 | #include "fd-util.h" | |
9 | #include "path-util.h" | |
10 | #include "process-util.h" | |
11 | #include "string-util.h" | |
12 | #include "tests.h" | |
13 | ||
14 | TEST(cg_split_spec) { | |
15 | char *c, *p; | |
16 | ||
17 | assert_se(cg_split_spec("foobar:/", &c, &p) == 0); | |
18 | ASSERT_STREQ(c, "foobar"); | |
19 | ASSERT_STREQ(p, "/"); | |
20 | c = mfree(c); | |
21 | p = mfree(p); | |
22 | ||
23 | assert_se(cg_split_spec("foobar:", &c, &p) == 0); | |
24 | c = mfree(c); | |
25 | p = mfree(p); | |
26 | ||
27 | assert_se(cg_split_spec("foobar:asdfd", &c, &p) < 0); | |
28 | assert_se(cg_split_spec(":///", &c, &p) < 0); | |
29 | assert_se(cg_split_spec(":", &c, &p) < 0); | |
30 | assert_se(cg_split_spec("", &c, &p) < 0); | |
31 | assert_se(cg_split_spec("fo/obar:/", &c, &p) < 0); | |
32 | ||
33 | assert_se(cg_split_spec("/", &c, &p) >= 0); | |
34 | ASSERT_NULL(c); | |
35 | ASSERT_STREQ(p, "/"); | |
36 | p = mfree(p); | |
37 | ||
38 | assert_se(cg_split_spec("foo", &c, &p) >= 0); | |
39 | ASSERT_STREQ(c, "foo"); | |
40 | ASSERT_NULL(p); | |
41 | c = mfree(c); | |
42 | } | |
43 | ||
44 | TEST(cg_create) { | |
45 | int r; | |
46 | ||
47 | r = cg_unified_cached(false); | |
48 | if (IN_SET(r, -ENOMEDIUM, -ENOENT)) { | |
49 | log_tests_skipped("cgroupfs is not mounted"); | |
50 | return; | |
51 | } | |
52 | assert_se(r >= 0); | |
53 | ||
54 | _cleanup_free_ char *here = NULL; | |
55 | assert_se(cg_pid_get_path_shifted(0, NULL, &here) >= 0); | |
56 | ||
57 | const char *test_a = prefix_roota(here, "/test-a"), | |
58 | *test_b = prefix_roota(here, "/test-b"), | |
59 | *test_c = prefix_roota(here, "/test-b/test-c"), | |
60 | *test_d = prefix_roota(here, "/test-b/test-d"); | |
61 | char *path; | |
62 | ||
63 | log_info("Paths for test:\n%s\n%s", test_a, test_b); | |
64 | ||
65 | /* Possibly clean up left-overs from aboted previous runs */ | |
66 | (void) cg_trim(SYSTEMD_CGROUP_CONTROLLER, test_a, /* delete_root= */ true); | |
67 | (void) cg_trim(SYSTEMD_CGROUP_CONTROLLER, test_b, /* delete_root= */ true); | |
68 | ||
69 | r = cg_create(SYSTEMD_CGROUP_CONTROLLER, test_a); | |
70 | if (IN_SET(r, -EPERM, -EACCES, -EROFS)) { | |
71 | log_info_errno(r, "Skipping %s: %m", __func__); | |
72 | return; | |
73 | } | |
74 | ||
75 | assert_se(r == 1); | |
76 | assert_se(cg_create(SYSTEMD_CGROUP_CONTROLLER, test_a) == 0); | |
77 | assert_se(cg_create(SYSTEMD_CGROUP_CONTROLLER, test_b) == 1); | |
78 | assert_se(cg_create(SYSTEMD_CGROUP_CONTROLLER, test_c) == 1); | |
79 | assert_se(cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, test_b, 0) == 0); | |
80 | ||
81 | assert_se(cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, getpid_cached(), &path) == 0); | |
82 | ASSERT_STREQ(path, test_b); | |
83 | free(path); | |
84 | ||
85 | assert_se(cg_attach(SYSTEMD_CGROUP_CONTROLLER, test_a, 0) == 0); | |
86 | ||
87 | assert_se(cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, getpid_cached(), &path) == 0); | |
88 | assert_se(path_equal(path, test_a)); | |
89 | free(path); | |
90 | ||
91 | assert_se(cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, test_d, 0) == 1); | |
92 | ||
93 | assert_se(cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, getpid_cached(), &path) == 0); | |
94 | assert_se(path_equal(path, test_d)); | |
95 | free(path); | |
96 | ||
97 | assert_se(cg_get_path(SYSTEMD_CGROUP_CONTROLLER, test_d, NULL, &path) == 0); | |
98 | log_debug("test_d: %s", path); | |
99 | const char *full_d; | |
100 | if (cg_all_unified()) | |
101 | full_d = strjoina("/sys/fs/cgroup", test_d); | |
102 | else if (cg_hybrid_unified()) | |
103 | full_d = strjoina("/sys/fs/cgroup/unified", test_d); | |
104 | else | |
105 | full_d = strjoina("/sys/fs/cgroup/systemd", test_d); | |
106 | assert_se(path_equal(path, full_d)); | |
107 | free(path); | |
108 | ||
109 | assert_se(cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, test_a) > 0); | |
110 | assert_se(cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, test_b) > 0); | |
111 | assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, test_a) > 0); | |
112 | assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, test_b) == 0); | |
113 | ||
114 | assert_se(cg_kill_recursive(test_a, 0, 0, NULL, NULL, NULL) == 0); | |
115 | assert_se(cg_kill_recursive(test_b, 0, 0, NULL, NULL, NULL) > 0); | |
116 | ||
117 | assert_se(cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, test_b, SYSTEMD_CGROUP_CONTROLLER, test_a, 0) > 0); | |
118 | ||
119 | assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, test_a) == 0); | |
120 | assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, test_b) > 0); | |
121 | ||
122 | assert_se(cg_kill_recursive(test_a, 0, 0, NULL, NULL, NULL) > 0); | |
123 | assert_se(cg_kill_recursive(test_b, 0, 0, NULL, NULL, NULL) == 0); | |
124 | ||
125 | (void) cg_trim(SYSTEMD_CGROUP_CONTROLLER, test_b, false); | |
126 | ||
127 | assert_se(cg_rmdir(SYSTEMD_CGROUP_CONTROLLER, test_b) == 0); | |
128 | assert_se(cg_rmdir(SYSTEMD_CGROUP_CONTROLLER, test_a) < 0); | |
129 | assert_se(cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, test_a, SYSTEMD_CGROUP_CONTROLLER, here, 0) > 0); | |
130 | assert_se(cg_rmdir(SYSTEMD_CGROUP_CONTROLLER, test_a) == 0); | |
131 | } | |
132 | ||
133 | TEST(id) { | |
134 | _cleanup_free_ char *p = NULL, *p2 = NULL; | |
135 | _cleanup_close_ int fd = -EBADF, fd2 = -EBADF; | |
136 | uint64_t id, id2; | |
137 | int r; | |
138 | ||
139 | r = cg_all_unified(); | |
140 | if (r == 0) { | |
141 | log_tests_skipped("skipping cgroupid test, not running in unified mode"); | |
142 | return; | |
143 | } | |
144 | if (IN_SET(r, -ENOMEDIUM, -ENOENT)) { | |
145 | log_tests_skipped("cgroupfs is not mounted"); | |
146 | return; | |
147 | } | |
148 | assert_se(r > 0); | |
149 | ||
150 | fd = cg_path_open(SYSTEMD_CGROUP_CONTROLLER, "/"); | |
151 | assert_se(fd >= 0); | |
152 | ||
153 | assert_se(fd_get_path(fd, &p) >= 0); | |
154 | assert_se(path_equal(p, "/sys/fs/cgroup")); | |
155 | ||
156 | assert_se(cg_fd_get_cgroupid(fd, &id) >= 0); | |
157 | ||
158 | fd2 = cg_cgroupid_open(fd, id); | |
159 | ||
160 | if (ERRNO_IS_NEG_PRIVILEGE(fd2)) | |
161 | log_notice("Skipping open-by-cgroup-id test because lacking privs."); | |
162 | else { | |
163 | assert_se(fd2 >= 0); | |
164 | ||
165 | assert_se(fd_get_path(fd2, &p2) >= 0); | |
166 | assert_se(path_equal(p2, "/sys/fs/cgroup")); | |
167 | ||
168 | assert_se(cg_fd_get_cgroupid(fd2, &id2) >= 0); | |
169 | ||
170 | assert_se(id == id2); | |
171 | ||
172 | assert_se(inode_same_at(fd, NULL, fd2, NULL, AT_EMPTY_PATH) > 0); | |
173 | } | |
174 | } | |
175 | ||
176 | DEFINE_TEST_MAIN(LOG_DEBUG); |