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