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