1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
6 #include "cgroup-util.h"
10 #include "string-util.h"
14 #define ASSERT_CGROUP_MASK(got, expected) \
15 log_cgroup_mask(got, expected); \
16 assert_se(got == expected)
18 #define ASSERT_CGROUP_MASK_JOINED(got, expected) ASSERT_CGROUP_MASK(got, CGROUP_MASK_EXTEND_JOINED(expected))
20 static void log_cgroup_mask(CGroupMask got
, CGroupMask expected
) {
21 _cleanup_free_
char *e_store
= NULL
, *g_store
= NULL
;
23 ASSERT_OK(cg_mask_to_string(expected
, &e_store
));
24 log_info("Expected mask: %s", e_store
);
25 ASSERT_OK(cg_mask_to_string(got
, &g_store
));
26 log_info("Got mask: %s", g_store
);
29 TEST_RET(cgroup_mask
, .sd_booted
= true) {
30 _cleanup_(rm_rf_physical_and_freep
) char *runtime_dir
= NULL
;
31 _cleanup_(manager_freep
) Manager
*m
= NULL
;
32 Unit
*son
, *daughter
, *parent
, *root
, *grandchild
, *parent_deep
, *nomem_parent
, *nomem_leaf
;
34 CGroupMask cpu_accounting_mask
= get_cpu_accounting_mask();
36 r
= enter_cgroup_subroot(NULL
);
38 return log_tests_skipped("cgroupfs not available");
40 /* Prepare the manager. */
41 _cleanup_free_
char *unit_dir
= NULL
;
42 ASSERT_OK(get_testdata_dir("units", &unit_dir
));
43 ASSERT_OK(set_unit_path(unit_dir
));
44 assert_se(runtime_dir
= setup_fake_runtime_dir());
45 r
= manager_new(RUNTIME_SCOPE_USER
, MANAGER_TEST_RUN_BASIC
, &m
);
46 if (IN_SET(r
, -EPERM
, -EACCES
)) {
47 log_error_errno(r
, "manager_new: %m");
48 return log_tests_skipped("cannot create manager");
53 /* Turn off all kinds of default accounting, so that we can
54 * verify the masks resulting of our configuration and nothing
56 m
->defaults
.cpu_accounting
=
57 m
->defaults
.memory_accounting
=
58 m
->defaults
.blockio_accounting
=
59 m
->defaults
.io_accounting
=
60 m
->defaults
.tasks_accounting
= false;
61 m
->defaults
.tasks_max
= CGROUP_TASKS_MAX_UNSET
;
63 assert_se(manager_startup(m
, NULL
, NULL
, NULL
) >= 0);
65 /* Load units and verify hierarchy. */
66 ASSERT_OK(manager_load_startable_unit_or_warn(m
, "parent.slice", NULL
, &parent
));
67 ASSERT_OK(manager_load_startable_unit_or_warn(m
, "son.service", NULL
, &son
));
68 ASSERT_OK(manager_load_startable_unit_or_warn(m
, "daughter.service", NULL
, &daughter
));
69 ASSERT_OK(manager_load_startable_unit_or_warn(m
, "grandchild.service", NULL
, &grandchild
));
70 ASSERT_OK(manager_load_startable_unit_or_warn(m
, "parent-deep.slice", NULL
, &parent_deep
));
71 ASSERT_OK(manager_load_startable_unit_or_warn(m
, "nomem.slice", NULL
, &nomem_parent
));
72 ASSERT_OK(manager_load_startable_unit_or_warn(m
, "nomemleaf.service", NULL
, &nomem_leaf
));
73 assert_se(UNIT_GET_SLICE(son
) == parent
);
74 assert_se(UNIT_GET_SLICE(daughter
) == parent
);
75 assert_se(UNIT_GET_SLICE(parent_deep
) == parent
);
76 assert_se(UNIT_GET_SLICE(grandchild
) == parent_deep
);
77 assert_se(UNIT_GET_SLICE(nomem_leaf
) == nomem_parent
);
78 root
= UNIT_GET_SLICE(parent
);
79 assert_se(UNIT_GET_SLICE(nomem_parent
) == root
);
81 /* Verify per-unit cgroups settings. */
82 ASSERT_CGROUP_MASK_JOINED(unit_get_own_mask(son
), CGROUP_MASK_CPU
);
83 ASSERT_CGROUP_MASK_JOINED(unit_get_own_mask(daughter
), cpu_accounting_mask
);
84 ASSERT_CGROUP_MASK_JOINED(unit_get_own_mask(grandchild
), 0);
85 ASSERT_CGROUP_MASK_JOINED(unit_get_own_mask(parent_deep
), CGROUP_MASK_MEMORY
);
86 ASSERT_CGROUP_MASK_JOINED(unit_get_own_mask(parent
), (CGROUP_MASK_IO
| CGROUP_MASK_BLKIO
));
87 ASSERT_CGROUP_MASK_JOINED(unit_get_own_mask(nomem_parent
), 0);
88 ASSERT_CGROUP_MASK_JOINED(unit_get_own_mask(nomem_leaf
), (CGROUP_MASK_IO
| CGROUP_MASK_BLKIO
| CGROUP_MASK_MEMORY
));
89 ASSERT_CGROUP_MASK_JOINED(unit_get_own_mask(root
), 0);
91 /* Verify aggregation of member masks */
92 ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(son
), 0);
93 ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(daughter
), 0);
94 ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(grandchild
), 0);
95 ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(parent_deep
), 0);
96 ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(parent
), (CGROUP_MASK_CPU
| cpu_accounting_mask
| CGROUP_MASK_MEMORY
));
97 ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(nomem_parent
), (CGROUP_MASK_IO
| CGROUP_MASK_BLKIO
| CGROUP_MASK_MEMORY
));
98 ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(nomem_leaf
), 0);
99 ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(root
), (CGROUP_MASK_CPU
| cpu_accounting_mask
| CGROUP_MASK_IO
| CGROUP_MASK_BLKIO
| CGROUP_MASK_MEMORY
));
101 /* Verify aggregation of sibling masks. */
102 ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(son
), (CGROUP_MASK_CPU
| cpu_accounting_mask
| CGROUP_MASK_MEMORY
));
103 ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(daughter
), (CGROUP_MASK_CPU
| cpu_accounting_mask
| CGROUP_MASK_MEMORY
));
104 ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(grandchild
), 0);
105 ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(parent_deep
), (CGROUP_MASK_CPU
| cpu_accounting_mask
| CGROUP_MASK_MEMORY
));
106 ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(parent
), (CGROUP_MASK_CPU
| cpu_accounting_mask
| CGROUP_MASK_IO
| CGROUP_MASK_BLKIO
| CGROUP_MASK_MEMORY
));
107 ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(nomem_parent
), (CGROUP_MASK_CPU
| CGROUP_MASK_CPUACCT
| CGROUP_MASK_IO
| CGROUP_MASK_BLKIO
| CGROUP_MASK_MEMORY
));
108 ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(nomem_leaf
), (CGROUP_MASK_IO
| CGROUP_MASK_BLKIO
| CGROUP_MASK_MEMORY
));
109 ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(root
), (CGROUP_MASK_CPU
| cpu_accounting_mask
| CGROUP_MASK_IO
| CGROUP_MASK_BLKIO
| CGROUP_MASK_MEMORY
));
111 /* Verify aggregation of target masks. */
112 ASSERT_CGROUP_MASK(unit_get_target_mask(son
), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_CPU
| cpu_accounting_mask
| CGROUP_MASK_MEMORY
) & m
->cgroup_supported
));
113 ASSERT_CGROUP_MASK(unit_get_target_mask(daughter
), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_CPU
| cpu_accounting_mask
| CGROUP_MASK_MEMORY
) & m
->cgroup_supported
));
114 ASSERT_CGROUP_MASK(unit_get_target_mask(grandchild
), 0);
115 ASSERT_CGROUP_MASK(unit_get_target_mask(parent_deep
), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_CPU
| cpu_accounting_mask
| CGROUP_MASK_MEMORY
) & m
->cgroup_supported
));
116 ASSERT_CGROUP_MASK(unit_get_target_mask(parent
), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_CPU
| cpu_accounting_mask
| CGROUP_MASK_IO
| CGROUP_MASK_BLKIO
| CGROUP_MASK_MEMORY
) & m
->cgroup_supported
));
117 ASSERT_CGROUP_MASK(unit_get_target_mask(nomem_parent
), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_CPU
| CGROUP_MASK_CPUACCT
| CGROUP_MASK_IO
| CGROUP_MASK_BLKIO
) & m
->cgroup_supported
));
118 ASSERT_CGROUP_MASK(unit_get_target_mask(nomem_leaf
), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_IO
| CGROUP_MASK_BLKIO
) & m
->cgroup_supported
));
119 ASSERT_CGROUP_MASK(unit_get_target_mask(root
), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_CPU
| cpu_accounting_mask
| CGROUP_MASK_IO
| CGROUP_MASK_BLKIO
| CGROUP_MASK_MEMORY
) & m
->cgroup_supported
));
121 /* Verify aggregation of enable masks. */
122 ASSERT_CGROUP_MASK(unit_get_enable_mask(son
), 0);
123 ASSERT_CGROUP_MASK(unit_get_enable_mask(daughter
), 0);
124 ASSERT_CGROUP_MASK(unit_get_enable_mask(grandchild
), 0);
125 ASSERT_CGROUP_MASK(unit_get_enable_mask(parent_deep
), 0);
126 ASSERT_CGROUP_MASK(unit_get_enable_mask(parent
), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_CPU
| cpu_accounting_mask
| CGROUP_MASK_MEMORY
) & m
->cgroup_supported
));
127 ASSERT_CGROUP_MASK(unit_get_enable_mask(nomem_parent
), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_IO
| CGROUP_MASK_BLKIO
) & m
->cgroup_supported
));
128 ASSERT_CGROUP_MASK(unit_get_enable_mask(nomem_leaf
), 0);
129 ASSERT_CGROUP_MASK(unit_get_enable_mask(root
), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_CPU
| cpu_accounting_mask
| CGROUP_MASK_IO
| CGROUP_MASK_BLKIO
| CGROUP_MASK_MEMORY
) & m
->cgroup_supported
));
134 static void test_cg_mask_to_string_one(CGroupMask mask
, const char *t
) {
135 _cleanup_free_
char *b
= NULL
;
137 assert_se(cg_mask_to_string(mask
, &b
) >= 0);
141 TEST(cg_mask_to_string
) {
142 test_cg_mask_to_string_one(0, NULL
);
143 test_cg_mask_to_string_one(_CGROUP_MASK_ALL
, "cpu cpuacct cpuset io blkio memory devices pids bpf-firewall bpf-devices bpf-foreign bpf-socket-bind bpf-restrict-network-interfaces");
144 test_cg_mask_to_string_one(CGROUP_MASK_CPU
, "cpu");
145 test_cg_mask_to_string_one(CGROUP_MASK_CPUACCT
, "cpuacct");
146 test_cg_mask_to_string_one(CGROUP_MASK_CPUSET
, "cpuset");
147 test_cg_mask_to_string_one(CGROUP_MASK_IO
, "io");
148 test_cg_mask_to_string_one(CGROUP_MASK_BLKIO
, "blkio");
149 test_cg_mask_to_string_one(CGROUP_MASK_MEMORY
, "memory");
150 test_cg_mask_to_string_one(CGROUP_MASK_DEVICES
, "devices");
151 test_cg_mask_to_string_one(CGROUP_MASK_PIDS
, "pids");
152 test_cg_mask_to_string_one(CGROUP_MASK_CPU
|CGROUP_MASK_CPUACCT
, "cpu cpuacct");
153 test_cg_mask_to_string_one(CGROUP_MASK_CPU
|CGROUP_MASK_PIDS
, "cpu pids");
154 test_cg_mask_to_string_one(CGROUP_MASK_CPUACCT
|CGROUP_MASK_PIDS
, "cpuacct pids");
155 test_cg_mask_to_string_one(CGROUP_MASK_DEVICES
|CGROUP_MASK_PIDS
, "devices pids");
156 test_cg_mask_to_string_one(CGROUP_MASK_IO
|CGROUP_MASK_BLKIO
, "io blkio");
159 static void cgroup_device_permissions_test_normalize(const char *a
, const char *b
) {
160 ASSERT_STREQ(cgroup_device_permissions_to_string(cgroup_device_permissions_from_string(a
)), b
);
163 TEST(cgroup_device_permissions
) {
164 for (CGroupDevicePermissions p
= 0; p
< _CGROUP_DEVICE_PERMISSIONS_MAX
; p
++) {
167 assert_se(s
= cgroup_device_permissions_to_string(p
));
168 assert_se(cgroup_device_permissions_from_string(s
) == p
);
171 cgroup_device_permissions_test_normalize("", "");
172 cgroup_device_permissions_test_normalize("rw", "rw");
173 cgroup_device_permissions_test_normalize("wr", "rw");
174 cgroup_device_permissions_test_normalize("wwrr", "rw");
175 cgroup_device_permissions_test_normalize("mmmmmmmmmmmmmm", "m");
176 cgroup_device_permissions_test_normalize("mmmmrrrrmmmwwmwmwmwmwmrmrmr", "rwm");
178 assert_se(cgroup_device_permissions_from_string(NULL
) == -EINVAL
);
179 assert_se(cgroup_device_permissions_from_string("rwq") == -EINVAL
);
180 assert_se(cgroup_device_permissions_from_string("RW") == -EINVAL
);
181 assert_se(cgroup_device_permissions_from_string("") == 0);
184 DEFINE_TEST_MAIN(LOG_DEBUG
);