]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-cpu-set-util.c
libudev: hide definition of struct udev_list from other libudev components
[thirdparty/systemd.git] / src / test / test-cpu-set-util.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include "alloc-util.h"
4 #include "cpu-set-util.h"
5 #include "string-util.h"
6 #include "macro.h"
7
8 static void test_parse_cpu_set(void) {
9 CPUSet c = {};
10 _cleanup_free_ char *str = NULL;
11 int cpu;
12
13 log_info("/* %s */", __func__);
14
15 /* Single value */
16 assert_se(parse_cpu_set_full("0", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0);
17 assert_se(c.set);
18 assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8));
19 assert_se(CPU_ISSET_S(0, c.allocated, c.set));
20 assert_se(CPU_COUNT_S(c.allocated, c.set) == 1);
21
22 assert_se(str = cpu_set_to_string(&c));
23 log_info("cpu_set_to_string: %s", str);
24 str = mfree(str);
25 assert_se(str = cpu_set_to_range_string(&c));
26 log_info("cpu_set_to_range_string: %s", str);
27 assert_se(streq(str, "0"));
28 str = mfree(str);
29 cpu_set_reset(&c);
30
31 /* Simple range (from CPUAffinity example) */
32 assert_se(parse_cpu_set_full("1 2 4", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0);
33 assert_se(c.set);
34 assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8));
35 assert_se(CPU_ISSET_S(1, c.allocated, c.set));
36 assert_se(CPU_ISSET_S(2, c.allocated, c.set));
37 assert_se(CPU_ISSET_S(4, c.allocated, c.set));
38 assert_se(CPU_COUNT_S(c.allocated, c.set) == 3);
39
40 assert_se(str = cpu_set_to_string(&c));
41 log_info("cpu_set_to_string: %s", str);
42 str = mfree(str);
43 assert_se(str = cpu_set_to_range_string(&c));
44 log_info("cpu_set_to_range_string: %s", str);
45 assert_se(streq(str, "1-2 4"));
46 str = mfree(str);
47 cpu_set_reset(&c);
48
49 /* A more interesting range */
50 assert_se(parse_cpu_set_full("0 1 2 3 8 9 10 11", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0);
51 assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8));
52 assert_se(CPU_COUNT_S(c.allocated, c.set) == 8);
53 for (cpu = 0; cpu < 4; cpu++)
54 assert_se(CPU_ISSET_S(cpu, c.allocated, c.set));
55 for (cpu = 8; cpu < 12; cpu++)
56 assert_se(CPU_ISSET_S(cpu, c.allocated, c.set));
57
58 assert_se(str = cpu_set_to_string(&c));
59 log_info("cpu_set_to_string: %s", str);
60 str = mfree(str);
61 assert_se(str = cpu_set_to_range_string(&c));
62 log_info("cpu_set_to_range_string: %s", str);
63 assert_se(streq(str, "0-3 8-11"));
64 str = mfree(str);
65 cpu_set_reset(&c);
66
67 /* Quoted strings */
68 assert_se(parse_cpu_set_full("8 '9' 10 \"11\"", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0);
69 assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8));
70 assert_se(CPU_COUNT_S(c.allocated, c.set) == 4);
71 for (cpu = 8; cpu < 12; cpu++)
72 assert_se(CPU_ISSET_S(cpu, c.allocated, c.set));
73 assert_se(str = cpu_set_to_string(&c));
74 log_info("cpu_set_to_string: %s", str);
75 str = mfree(str);
76 assert_se(str = cpu_set_to_range_string(&c));
77 log_info("cpu_set_to_range_string: %s", str);
78 assert_se(streq(str, "8-11"));
79 str = mfree(str);
80 cpu_set_reset(&c);
81
82 /* Use commas as separators */
83 assert_se(parse_cpu_set_full("0,1,2,3 8,9,10,11", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0);
84 assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8));
85 assert_se(CPU_COUNT_S(c.allocated, c.set) == 8);
86 for (cpu = 0; cpu < 4; cpu++)
87 assert_se(CPU_ISSET_S(cpu, c.allocated, c.set));
88 for (cpu = 8; cpu < 12; cpu++)
89 assert_se(CPU_ISSET_S(cpu, c.allocated, c.set));
90 assert_se(str = cpu_set_to_string(&c));
91 log_info("cpu_set_to_string: %s", str);
92 str = mfree(str);
93 cpu_set_reset(&c);
94
95 /* Commas with spaces (and trailing comma, space) */
96 assert_se(parse_cpu_set_full("0, 1, 2, 3, 4, 5, 6, 7, 63, ", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0);
97 assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8));
98 assert_se(CPU_COUNT_S(c.allocated, c.set) == 9);
99 for (cpu = 0; cpu < 8; cpu++)
100 assert_se(CPU_ISSET_S(cpu, c.allocated, c.set));
101
102 assert_se(CPU_ISSET_S(63, c.allocated, c.set));
103 assert_se(str = cpu_set_to_string(&c));
104 log_info("cpu_set_to_string: %s", str);
105 str = mfree(str);
106 assert_se(str = cpu_set_to_range_string(&c));
107 log_info("cpu_set_to_range_string: %s", str);
108 assert_se(streq(str, "0-7 63"));
109 str = mfree(str);
110 cpu_set_reset(&c);
111
112 /* Ranges */
113 assert_se(parse_cpu_set_full("0-3,8-11", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0);
114 assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8));
115 assert_se(CPU_COUNT_S(c.allocated, c.set) == 8);
116 for (cpu = 0; cpu < 4; cpu++)
117 assert_se(CPU_ISSET_S(cpu, c.allocated, c.set));
118 for (cpu = 8; cpu < 12; cpu++)
119 assert_se(CPU_ISSET_S(cpu, c.allocated, c.set));
120 assert_se(str = cpu_set_to_string(&c));
121 log_info("cpu_set_to_string: %s", str);
122 str = mfree(str);
123 cpu_set_reset(&c);
124
125 /* Ranges with trailing comma, space */
126 assert_se(parse_cpu_set_full("0-3 8-11, ", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0);
127 assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8));
128 assert_se(CPU_COUNT_S(c.allocated, c.set) == 8);
129 for (cpu = 0; cpu < 4; cpu++)
130 assert_se(CPU_ISSET_S(cpu, c.allocated, c.set));
131 for (cpu = 8; cpu < 12; cpu++)
132 assert_se(CPU_ISSET_S(cpu, c.allocated, c.set));
133 assert_se(str = cpu_set_to_string(&c));
134 log_info("cpu_set_to_string: %s", str);
135 str = mfree(str);
136 assert_se(str = cpu_set_to_range_string(&c));
137 log_info("cpu_set_to_range_string: %s", str);
138 assert_se(streq(str, "0-3 8-11"));
139 str = mfree(str);
140 cpu_set_reset(&c);
141
142 /* Negative range (returns empty cpu_set) */
143 assert_se(parse_cpu_set_full("3-0", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0);
144 assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8));
145 assert_se(CPU_COUNT_S(c.allocated, c.set) == 0);
146 cpu_set_reset(&c);
147
148 /* Overlapping ranges */
149 assert_se(parse_cpu_set_full("0-7 4-11", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0);
150 assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8));
151 assert_se(CPU_COUNT_S(c.allocated, c.set) == 12);
152 for (cpu = 0; cpu < 12; cpu++)
153 assert_se(CPU_ISSET_S(cpu, c.allocated, c.set));
154 assert_se(str = cpu_set_to_string(&c));
155 log_info("cpu_set_to_string: %s", str);
156 str = mfree(str);
157 assert_se(str = cpu_set_to_range_string(&c));
158 log_info("cpu_set_to_range_string: %s", str);
159 assert_se(streq(str, "0-11"));
160 str = mfree(str);
161 cpu_set_reset(&c);
162
163 /* Mix ranges and individual CPUs */
164 assert_se(parse_cpu_set_full("0,2 4-11", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0);
165 assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8));
166 assert_se(CPU_COUNT_S(c.allocated, c.set) == 10);
167 assert_se(CPU_ISSET_S(0, c.allocated, c.set));
168 assert_se(CPU_ISSET_S(2, c.allocated, c.set));
169 for (cpu = 4; cpu < 12; cpu++)
170 assert_se(CPU_ISSET_S(cpu, c.allocated, c.set));
171 assert_se(str = cpu_set_to_string(&c));
172 log_info("cpu_set_to_string: %s", str);
173 str = mfree(str);
174 assert_se(str = cpu_set_to_range_string(&c));
175 log_info("cpu_set_to_range_string: %s", str);
176 assert_se(streq(str, "0 2 4-11"));
177 str = mfree(str);
178 cpu_set_reset(&c);
179
180 /* Garbage */
181 assert_se(parse_cpu_set_full("0 1 2 3 garbage", &c, true, NULL, "fake", 1, "CPUAffinity") == -EINVAL);
182 assert_se(!c.set);
183 assert_se(c.allocated == 0);
184
185 /* Range with garbage */
186 assert_se(parse_cpu_set_full("0-3 8-garbage", &c, true, NULL, "fake", 1, "CPUAffinity") == -EINVAL);
187 assert_se(!c.set);
188 assert_se(c.allocated == 0);
189
190 /* Empty string */
191 assert_se(parse_cpu_set_full("", &c, true, NULL, "fake", 1, "CPUAffinity") == 0);
192 assert_se(!c.set); /* empty string returns NULL */
193 assert_se(c.allocated == 0);
194
195 /* Runaway quoted string */
196 assert_se(parse_cpu_set_full("0 1 2 3 \"4 5 6 7 ", &c, true, NULL, "fake", 1, "CPUAffinity") == -EINVAL);
197 assert_se(!c.set);
198 assert_se(c.allocated == 0);
199
200 /* Maximum allocation */
201 assert_se(parse_cpu_set_full("8000-8191", &c, true, NULL, "fake", 1, "CPUAffinity") == 0);
202 assert_se(CPU_COUNT_S(c.allocated, c.set) == 192);
203 assert_se(str = cpu_set_to_string(&c));
204 log_info("cpu_set_to_string: %s", str);
205 str = mfree(str);
206 assert_se(str = cpu_set_to_range_string(&c));
207 log_info("cpu_set_to_range_string: %s", str);
208 assert_se(streq(str, "8000-8191"));
209 str = mfree(str);
210 cpu_set_reset(&c);
211 }
212
213 static void test_parse_cpu_set_extend(void) {
214 CPUSet c = {};
215 _cleanup_free_ char *s1 = NULL, *s2 = NULL;
216
217 log_info("/* %s */", __func__);
218
219 assert_se(parse_cpu_set_extend("1 3", &c, true, NULL, "fake", 1, "CPUAffinity") == 0);
220 assert_se(CPU_COUNT_S(c.allocated, c.set) == 2);
221 assert_se(s1 = cpu_set_to_string(&c));
222 log_info("cpu_set_to_string: %s", s1);
223
224 assert_se(parse_cpu_set_extend("4", &c, true, NULL, "fake", 1, "CPUAffinity") == 0);
225 assert_se(CPU_COUNT_S(c.allocated, c.set) == 3);
226 assert_se(s2 = cpu_set_to_string(&c));
227 log_info("cpu_set_to_string: %s", s2);
228
229 assert_se(parse_cpu_set_extend("", &c, true, NULL, "fake", 1, "CPUAffinity") == 0);
230 assert_se(!c.set);
231 assert_se(c.allocated == 0);
232 log_info("cpu_set_to_string: (null)");
233 }
234
235 static void test_cpu_set_to_from_dbus(void) {
236 _cleanup_(cpu_set_reset) CPUSet c = {}, c2 = {};
237 _cleanup_free_ char *s = NULL;
238
239 log_info("/* %s */", __func__);
240
241 assert_se(parse_cpu_set_extend("1 3 8 100-200", &c, true, NULL, "fake", 1, "CPUAffinity") == 0);
242 assert_se(s = cpu_set_to_string(&c));
243 log_info("cpu_set_to_string: %s", s);
244 assert_se(CPU_COUNT_S(c.allocated, c.set) == 104);
245
246 _cleanup_free_ uint8_t *array = NULL;
247 size_t allocated;
248 static const char expected[32] =
249 "\x0A\x01\x00\x00\x00\x00\x00\x00\x00\x00"
250 "\x00\x00\xF0\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
251 "\xFF\xFF\xFF\xFF\xFF\x01";
252
253 assert_se(cpu_set_to_dbus(&c, &array, &allocated) == 0);
254 assert_se(array);
255 assert_se(allocated == c.allocated);
256
257 assert_se(allocated <= sizeof expected);
258 assert_se(allocated >= DIV_ROUND_UP(201u, 8u)); /* We need at least 201 bits for our mask */
259 assert(memcmp(array, expected, allocated) == 0);
260
261 assert_se(cpu_set_from_dbus(array, allocated, &c2) == 0);
262 assert_se(c2.set);
263 assert_se(c2.allocated == c.allocated);
264 assert_se(memcmp(c.set, c2.set, c.allocated) == 0);
265 }
266
267 static void test_cpus_in_affinity_mask(void) {
268 int r;
269
270 r = cpus_in_affinity_mask();
271 assert(r > 0);
272 log_info("cpus_in_affinity_mask: %d", r);
273 }
274
275 int main(int argc, char *argv[]) {
276 log_info("CPU_ALLOC_SIZE(1) = %zu", CPU_ALLOC_SIZE(1));
277 log_info("CPU_ALLOC_SIZE(9) = %zu", CPU_ALLOC_SIZE(9));
278 log_info("CPU_ALLOC_SIZE(64) = %zu", CPU_ALLOC_SIZE(64));
279 log_info("CPU_ALLOC_SIZE(65) = %zu", CPU_ALLOC_SIZE(65));
280 log_info("CPU_ALLOC_SIZE(1024) = %zu", CPU_ALLOC_SIZE(1024));
281 log_info("CPU_ALLOC_SIZE(1025) = %zu", CPU_ALLOC_SIZE(1025));
282 log_info("CPU_ALLOC_SIZE(8191) = %zu", CPU_ALLOC_SIZE(8191));
283
284 test_parse_cpu_set();
285 test_parse_cpu_set_extend();
286 test_cpus_in_affinity_mask();
287 test_cpu_set_to_from_dbus();
288
289 return 0;
290 }