tests/unit/test-smp-parse: Constify some pointer/struct
[qemu/armbru.git] / tests / unit / test-smp-parse.c
blob0f98c9509ee927dbd6d303ea574325b6d8388dd2
1 /*
2 * SMP parsing unit-tests
4 * Copyright (c) 2021 Huawei Technologies Co., Ltd
6 * Authors:
7 * Yanan Wang <wangyanan55@huawei.com>
9 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
10 * See the COPYING.LIB file in the top-level directory.
13 #include "qemu/osdep.h"
14 #include "qom/object.h"
15 #include "qemu/module.h"
16 #include "qapi/error.h"
18 #include "hw/boards.h"
20 #define T true
21 #define F false
23 #define MIN_CPUS 1 /* set the min CPUs supported by the machine as 1 */
24 #define MAX_CPUS 512 /* set the max CPUs supported by the machine as 512 */
26 #define SMP_MACHINE_NAME "TEST-SMP"
29 * Used to define the generic 3-level CPU topology hierarchy
30 * -sockets/cores/threads
32 #define SMP_CONFIG_GENERIC(ha, a, hb, b, hc, c, hd, d, he, e) \
33 { \
34 .has_cpus = ha, .cpus = a, \
35 .has_sockets = hb, .sockets = b, \
36 .has_cores = hc, .cores = c, \
37 .has_threads = hd, .threads = d, \
38 .has_maxcpus = he, .maxcpus = e, \
41 #define CPU_TOPOLOGY_GENERIC(a, b, c, d, e) \
42 { \
43 .cpus = a, \
44 .sockets = b, \
45 .cores = c, \
46 .threads = d, \
47 .max_cpus = e, \
51 * Currently a 4-level topology hierarchy is supported on PC machines
52 * -sockets/dies/cores/threads
54 #define SMP_CONFIG_WITH_DIES(ha, a, hb, b, hc, c, hd, d, he, e, hf, f) \
55 { \
56 .has_cpus = ha, .cpus = a, \
57 .has_sockets = hb, .sockets = b, \
58 .has_dies = hc, .dies = c, \
59 .has_cores = hd, .cores = d, \
60 .has_threads = he, .threads = e, \
61 .has_maxcpus = hf, .maxcpus = f, \
64 /**
65 * @config - the given SMP configuration
66 * @expect_prefer_sockets - the expected parsing result for the
67 * valid configuration, when sockets are preferred over cores
68 * @expect_prefer_cores - the expected parsing result for the
69 * valid configuration, when cores are preferred over sockets
70 * @expect_error - the expected error report when the given
71 * configuration is invalid
73 typedef struct SMPTestData {
74 SMPConfiguration config;
75 CpuTopology expect_prefer_sockets;
76 CpuTopology expect_prefer_cores;
77 const char *expect_error;
78 } SMPTestData;
81 * List all the possible valid sub-collections of the generic 5
82 * topology parameters (i.e. cpus/maxcpus/sockets/cores/threads),
83 * then test the automatic calculation algorithm of the missing
84 * values in the parser.
86 static const struct SMPTestData data_generic_valid[] = {
88 /* config: no configuration provided
89 * expect: cpus=1,sockets=1,cores=1,threads=1,maxcpus=1 */
90 .config = SMP_CONFIG_GENERIC(F, 0, F, 0, F, 0, F, 0, F, 0),
91 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(1, 1, 1, 1, 1),
92 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(1, 1, 1, 1, 1),
93 }, {
94 /* config: -smp 8
95 * prefer_sockets: cpus=8,sockets=8,cores=1,threads=1,maxcpus=8
96 * prefer_cores: cpus=8,sockets=1,cores=8,threads=1,maxcpus=8 */
97 .config = SMP_CONFIG_GENERIC(T, 8, F, 0, F, 0, F, 0, F, 0),
98 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 8, 1, 1, 8),
99 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 1, 8, 1, 8),
100 }, {
101 /* config: -smp sockets=2
102 * expect: cpus=2,sockets=2,cores=1,threads=1,maxcpus=2 */
103 .config = SMP_CONFIG_GENERIC(F, 0, T, 2, F, 0, F, 0, F, 0),
104 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(2, 2, 1, 1, 2),
105 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(2, 2, 1, 1, 2),
106 }, {
107 /* config: -smp cores=4
108 * expect: cpus=4,sockets=1,cores=4,threads=1,maxcpus=4 */
109 .config = SMP_CONFIG_GENERIC(F, 0, F, 0, T, 4, F, 0, F, 0),
110 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(4, 1, 4, 1, 4),
111 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(4, 1, 4, 1, 4),
112 }, {
113 /* config: -smp threads=2
114 * expect: cpus=2,sockets=1,cores=1,threads=2,maxcpus=2 */
115 .config = SMP_CONFIG_GENERIC(F, 0, F, 0, F, 0, T, 2, F, 0),
116 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(2, 1, 1, 2, 2),
117 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(2, 1, 1, 2, 2),
118 }, {
119 /* config: -smp maxcpus=16
120 * prefer_sockets: cpus=16,sockets=16,cores=1,threads=1,maxcpus=16
121 * prefer_cores: cpus=16,sockets=1,cores=16,threads=1,maxcpus=16 */
122 .config = SMP_CONFIG_GENERIC(F, 0, F, 0, F, 0, F, 0, T, 16),
123 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(16, 16, 1, 1, 16),
124 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(16, 1, 16, 1, 16),
125 }, {
126 /* config: -smp 8,sockets=2
127 * expect: cpus=8,sockets=2,cores=4,threads=1,maxcpus=8 */
128 .config = SMP_CONFIG_GENERIC(T, 8, T, 2, F, 0, F, 0, F, 0),
129 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
130 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
131 }, {
132 /* config: -smp 8,cores=4
133 * expect: cpus=8,sockets=2,cores=4,threads=1,maxcpus=8 */
134 .config = SMP_CONFIG_GENERIC(T, 8, F, 0, T, 4, F, 0, F, 0),
135 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
136 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
137 }, {
138 /* config: -smp 8,threads=2
139 * prefer_sockets: cpus=8,sockets=4,cores=1,threads=2,maxcpus=8
140 * prefer_cores: cpus=8,sockets=1,cores=4,threads=2,maxcpus=8 */
141 .config = SMP_CONFIG_GENERIC(T, 8, F, 0, F, 0, T, 2, F, 0),
142 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 4, 1, 2, 8),
143 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 1, 4, 2, 8),
144 }, {
145 /* config: -smp 8,maxcpus=16
146 * prefer_sockets: cpus=8,sockets=16,cores=1,threads=1,maxcpus=16
147 * prefer_cores: cpus=8,sockets=1,cores=16,threads=1,maxcpus=16 */
148 .config = SMP_CONFIG_GENERIC(T, 8, F, 0, F, 0, F, 0, T, 16),
149 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 16, 1, 1, 16),
150 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 1, 16, 1, 16),
151 }, {
152 /* config: -smp sockets=2,cores=4
153 * expect: cpus=8,sockets=2,cores=4,threads=1,maxcpus=8 */
154 .config = SMP_CONFIG_GENERIC(F, 0, T, 2, T, 4, F, 0, F, 0),
155 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
156 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
157 }, {
158 /* config: -smp sockets=2,threads=2
159 * expect: cpus=4,sockets=2,cores=1,threads=2,maxcpus=4 */
160 .config = SMP_CONFIG_GENERIC(F, 0, T, 2, F, 0, T, 2, F, 0),
161 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(4, 2, 1, 2, 4),
162 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(4, 2, 1, 2, 4),
163 }, {
164 /* config: -smp sockets=2,maxcpus=16
165 * expect: cpus=16,sockets=2,cores=8,threads=1,maxcpus=16 */
166 .config = SMP_CONFIG_GENERIC(F, 0, T, 2, F, 0, F, 0, T, 16),
167 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(16, 2, 8, 1, 16),
168 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(16, 2, 8, 1, 16),
169 }, {
170 /* config: -smp cores=4,threads=2
171 * expect: cpus=8,sockets=1,cores=4,threads=2,maxcpus=8 */
172 .config = SMP_CONFIG_GENERIC(F, 0, F, 0, T, 4, T, 2, F, 0),
173 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 1, 4, 2, 8),
174 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 1, 4, 2, 8),
175 }, {
176 /* config: -smp cores=4,maxcpus=16
177 * expect: cpus=16,sockets=4,cores=4,threads=1,maxcpus=16 */
178 .config = SMP_CONFIG_GENERIC(F, 0, F, 0, T, 4, F, 0, T, 16),
179 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(16, 4, 4, 1, 16),
180 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(16, 4, 4, 1, 16),
181 }, {
182 /* config: -smp threads=2,maxcpus=16
183 * prefer_sockets: cpus=16,sockets=8,cores=1,threads=2,maxcpus=16
184 * prefer_cores: cpus=16,sockets=1,cores=8,threads=2,maxcpus=16 */
185 .config = SMP_CONFIG_GENERIC(F, 0, F, 0, F, 0, T, 2, T, 16),
186 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(16, 8, 1, 2, 16),
187 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(16, 1, 8, 2, 16),
188 }, {
189 /* config: -smp 8,sockets=2,cores=4
190 * expect: cpus=8,sockets=2,cores=4,threads=1,maxcpus=8 */
191 .config = SMP_CONFIG_GENERIC(T, 8, T, 2, T, 4, F, 0, F, 0),
192 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
193 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
194 }, {
195 /* config: -smp 8,sockets=2,threads=2
196 * expect: cpus=8,sockets=2,cores=2,threads=2,maxcpus=8 */
197 .config = SMP_CONFIG_GENERIC(T, 8, T, 2, F, 0, T, 2, F, 0),
198 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 2, 2, 8),
199 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 2, 2, 2, 8),
200 }, {
201 /* config: -smp 8,sockets=2,maxcpus=16
202 * expect: cpus=8,sockets=2,cores=8,threads=1,maxcpus=16 */
203 .config = SMP_CONFIG_GENERIC(T, 8, T, 2, F, 0, F, 0, T, 16),
204 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 8, 1, 16),
205 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 2, 8, 1, 16),
206 }, {
207 /* config: -smp 8,cores=4,threads=2
208 * expect: cpus=8,sockets=1,cores=4,threads=2,maxcpus=8 */
209 .config = SMP_CONFIG_GENERIC(T, 8, F, 0, T, 4, T, 2, F, 0),
210 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 1, 4, 2, 8),
211 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 1, 4, 2, 8),
212 }, {
213 /* config: -smp 8,cores=4,maxcpus=16
214 * expect: cpus=8,sockets=4,cores=4,threads=1,maxcpus=16 */
215 .config = SMP_CONFIG_GENERIC(T, 8, F, 0, T, 4, F, 0, T, 16),
216 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 4, 4, 1, 16),
217 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 4, 4, 1, 16),
218 }, {
219 /* config: -smp 8,threads=2,maxcpus=16
220 * prefer_sockets: cpus=8,sockets=8,cores=1,threads=2,maxcpus=16
221 * prefer_cores: cpus=8,sockets=1,cores=8,threads=2,maxcpus=16 */
222 .config = SMP_CONFIG_GENERIC(T, 8, F, 0, F, 0, T, 2, T, 16),
223 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 8, 1, 2, 16),
224 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 1, 8, 2, 16),
225 }, {
226 /* config: -smp sockets=2,cores=4,threads=2
227 * expect: cpus=16,sockets=2,cores=4,threads=2,maxcpus=16 */
228 .config = SMP_CONFIG_GENERIC(F, 0, T, 2, T, 4, T, 2, F, 0),
229 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
230 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
231 }, {
232 /* config: -smp sockets=2,cores=4,maxcpus=16
233 * expect: cpus=16,sockets=2,cores=4,threads=2,maxcpus=16 */
234 .config = SMP_CONFIG_GENERIC(F, 0, T, 2, T, 4, F, 0, T, 16),
235 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
236 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
237 }, {
238 /* config: -smp sockets=2,threads=2,maxcpus=16
239 * expect: cpus=16,sockets=2,cores=4,threads=2,maxcpus=16 */
240 .config = SMP_CONFIG_GENERIC(F, 0, T, 2, F, 0, T, 2, T, 16),
241 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
242 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
243 }, {
244 /* config: -smp cores=4,threads=2,maxcpus=16
245 * expect: cpus=16,sockets=2,cores=4,threads=2,maxcpus=16 */
246 .config = SMP_CONFIG_GENERIC(F, 0, F, 0, T, 4, T, 2, T, 16),
247 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
248 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
249 }, {
250 /* config: -smp 8,sockets=2,cores=4,threads=1
251 * expect: cpus=8,sockets=2,cores=4,threads=1,maxcpus=8 */
252 .config = SMP_CONFIG_GENERIC(T, 8, T, 2, T, 4, T, 1, F, 0),
253 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
254 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
255 }, {
256 /* config: -smp 8,sockets=2,cores=4,maxcpus=16
257 * expect: cpus=8,sockets=2,cores=4,threads=2,maxcpus=16 */
258 .config = SMP_CONFIG_GENERIC(T, 8, T, 2, T, 4, F, 0, T, 16),
259 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
260 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
261 }, {
262 /* config: -smp 8,sockets=2,threads=2,maxcpus=16
263 * expect: cpus=8,sockets=2,cores=4,threads=2,maxcpus=16 */
264 .config = SMP_CONFIG_GENERIC(T, 8, T, 2, F, 0, T, 2, T, 16),
265 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
266 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
267 }, {
268 /* config: -smp 8,cores=4,threads=2,maxcpus=16
269 * expect: cpus=8,sockets=2,cores=4,threads=2,maxcpus=16 */
270 .config = SMP_CONFIG_GENERIC(T, 8, F, 0, T, 4, T, 2, T, 16),
271 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
272 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
273 }, {
274 /* config: -smp sockets=2,cores=4,threads=2,maxcpus=16
275 * expect: cpus=16,sockets=2,cores=4,threads=2,maxcpus=16 */
276 .config = SMP_CONFIG_GENERIC(F, 0, T, 2, T, 4, T, 2, T, 16),
277 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
278 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
279 }, {
280 /* config: -smp 8,sockets=2,cores=4,threads=2,maxcpus=16
281 * expect: cpus=8,sockets=2,cores=4,threads=2,maxcpus=16 */
282 .config = SMP_CONFIG_GENERIC(T, 8, T, 2, T, 4, T, 2, T, 16),
283 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
284 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
288 static const struct SMPTestData data_generic_invalid[] = {
290 /* config: -smp 2,dies=2 */
291 .config = SMP_CONFIG_WITH_DIES(T, 2, F, 0, T, 2, F, 0, F, 0, F, 0),
292 .expect_error = "dies not supported by this machine's CPU topology",
293 }, {
294 /* config: -smp 8,sockets=2,cores=4,threads=2,maxcpus=8 */
295 .config = SMP_CONFIG_GENERIC(T, 8, T, 2, T, 4, T, 2, T, 8),
296 .expect_error = "Invalid CPU topology: "
297 "product of the hierarchy must match maxcpus: "
298 "sockets (2) * cores (4) * threads (2) "
299 "!= maxcpus (8)",
300 }, {
301 /* config: -smp 18,sockets=2,cores=4,threads=2,maxcpus=16 */
302 .config = SMP_CONFIG_GENERIC(T, 18, T, 2, T, 4, T, 2, T, 16),
303 .expect_error = "Invalid CPU topology: "
304 "maxcpus must be equal to or greater than smp: "
305 "sockets (2) * cores (4) * threads (2) "
306 "== maxcpus (16) < smp_cpus (18)",
307 }, {
308 /* config: -smp 1
309 * should tweak the supported min CPUs to 2 for testing */
310 .config = SMP_CONFIG_GENERIC(T, 1, F, 0, F, 0, F, 0, F, 0),
311 .expect_error = "Invalid SMP CPUs 1. The min CPUs supported "
312 "by machine '" SMP_MACHINE_NAME "' is 2",
313 }, {
314 /* config: -smp 512
315 * should tweak the supported max CPUs to 511 for testing */
316 .config = SMP_CONFIG_GENERIC(T, 512, F, 0, F, 0, F, 0, F, 0),
317 .expect_error = "Invalid SMP CPUs 512. The max CPUs supported "
318 "by machine '" SMP_MACHINE_NAME "' is 511",
322 static const struct SMPTestData data_with_dies_invalid[] = {
324 /* config: -smp 16,sockets=2,dies=2,cores=4,threads=2,maxcpus=16 */
325 .config = SMP_CONFIG_WITH_DIES(T, 16, T, 2, T, 2, T, 4, T, 2, T, 16),
326 .expect_error = "Invalid CPU topology: "
327 "product of the hierarchy must match maxcpus: "
328 "sockets (2) * dies (2) * cores (4) * threads (2) "
329 "!= maxcpus (16)",
330 }, {
331 /* config: -smp 34,sockets=2,dies=2,cores=4,threads=2,maxcpus=32 */
332 .config = SMP_CONFIG_WITH_DIES(T, 34, T, 2, T, 2, T, 4, T, 2, T, 32),
333 .expect_error = "Invalid CPU topology: "
334 "maxcpus must be equal to or greater than smp: "
335 "sockets (2) * dies (2) * cores (4) * threads (2) "
336 "== maxcpus (32) < smp_cpus (34)",
340 static char *smp_config_to_string(SMPConfiguration *config)
342 return g_strdup_printf(
343 "(SMPConfiguration) {\n"
344 " .has_cpus = %5s, cpus = %" PRId64 ",\n"
345 " .has_sockets = %5s, sockets = %" PRId64 ",\n"
346 " .has_dies = %5s, dies = %" PRId64 ",\n"
347 " .has_cores = %5s, cores = %" PRId64 ",\n"
348 " .has_threads = %5s, threads = %" PRId64 ",\n"
349 " .has_maxcpus = %5s, maxcpus = %" PRId64 ",\n"
350 "}",
351 config->has_cpus ? "true" : "false", config->cpus,
352 config->has_sockets ? "true" : "false", config->sockets,
353 config->has_dies ? "true" : "false", config->dies,
354 config->has_cores ? "true" : "false", config->cores,
355 config->has_threads ? "true" : "false", config->threads,
356 config->has_maxcpus ? "true" : "false", config->maxcpus);
359 static char *cpu_topology_to_string(const CpuTopology *topo)
361 return g_strdup_printf(
362 "(CpuTopology) {\n"
363 " .cpus = %u,\n"
364 " .sockets = %u,\n"
365 " .dies = %u,\n"
366 " .cores = %u,\n"
367 " .threads = %u,\n"
368 " .max_cpus = %u,\n"
369 "}",
370 topo->cpus, topo->sockets, topo->dies,
371 topo->cores, topo->threads, topo->max_cpus);
374 static void check_parse(MachineState *ms, SMPConfiguration *config,
375 const CpuTopology *expect_topo, const char *expect_err,
376 bool is_valid)
378 g_autofree char *config_str = smp_config_to_string(config);
379 g_autofree char *expect_topo_str = cpu_topology_to_string(expect_topo);
380 g_autofree char *output_topo_str = NULL;
381 Error *err = NULL;
383 /* call the generic parser smp_parse() */
384 smp_parse(ms, config, &err);
386 output_topo_str = cpu_topology_to_string(&ms->smp);
388 /* when the configuration is supposed to be valid */
389 if (is_valid) {
390 if ((err == NULL) &&
391 (ms->smp.cpus == expect_topo->cpus) &&
392 (ms->smp.sockets == expect_topo->sockets) &&
393 (ms->smp.dies == expect_topo->dies) &&
394 (ms->smp.cores == expect_topo->cores) &&
395 (ms->smp.threads == expect_topo->threads) &&
396 (ms->smp.max_cpus == expect_topo->max_cpus)) {
397 return;
400 if (err != NULL) {
401 g_printerr("Test smp_parse failed!\n"
402 "Input configuration: %s\n"
403 "Should be valid: yes\n"
404 "Expected topology: %s\n\n"
405 "Result is valid: no\n"
406 "Output error report: %s\n",
407 config_str, expect_topo_str, error_get_pretty(err));
408 goto end;
411 g_printerr("Test smp_parse failed!\n"
412 "Input configuration: %s\n"
413 "Should be valid: yes\n"
414 "Expected topology: %s\n\n"
415 "Result is valid: yes\n"
416 "Output topology: %s\n",
417 config_str, expect_topo_str, output_topo_str);
418 goto end;
421 /* when the configuration is supposed to be invalid */
422 if (err != NULL) {
423 if (expect_err == NULL ||
424 g_str_equal(expect_err, error_get_pretty(err))) {
425 error_free(err);
426 return;
429 g_printerr("Test smp_parse failed!\n"
430 "Input configuration: %s\n"
431 "Should be valid: no\n"
432 "Expected error report: %s\n\n"
433 "Result is valid: no\n"
434 "Output error report: %s\n",
435 config_str, expect_err, error_get_pretty(err));
436 goto end;
439 g_printerr("Test smp_parse failed!\n"
440 "Input configuration: %s\n"
441 "Should be valid: no\n"
442 "Expected error report: %s\n\n"
443 "Result is valid: yes\n"
444 "Output topology: %s\n",
445 config_str, expect_err, output_topo_str);
447 end:
448 if (err != NULL) {
449 error_free(err);
452 abort();
455 static void smp_parse_test(MachineState *ms, SMPTestData *data, bool is_valid)
457 MachineClass *mc = MACHINE_GET_CLASS(ms);
459 mc->smp_props.prefer_sockets = true;
460 check_parse(ms, &data->config, &data->expect_prefer_sockets,
461 data->expect_error, is_valid);
463 mc->smp_props.prefer_sockets = false;
464 check_parse(ms, &data->config, &data->expect_prefer_cores,
465 data->expect_error, is_valid);
468 /* The parsed results of the unsupported parameters should be 1 */
469 static void unsupported_params_init(const MachineClass *mc, SMPTestData *data)
471 if (!mc->smp_props.dies_supported) {
472 data->expect_prefer_sockets.dies = 1;
473 data->expect_prefer_cores.dies = 1;
477 static void machine_base_class_init(ObjectClass *oc, void *data)
479 MachineClass *mc = MACHINE_CLASS(oc);
481 mc->smp_props.prefer_sockets = true;
483 mc->name = g_strdup(SMP_MACHINE_NAME);
486 static void machine_generic_valid_class_init(ObjectClass *oc, void *data)
488 MachineClass *mc = MACHINE_CLASS(oc);
490 mc->min_cpus = MIN_CPUS;
491 mc->max_cpus = MAX_CPUS;
493 mc->smp_props.dies_supported = false;
496 static void machine_generic_invalid_class_init(ObjectClass *oc, void *data)
498 MachineClass *mc = MACHINE_CLASS(oc);
500 /* Force invalid min CPUs and max CPUs */
501 mc->min_cpus = 2;
502 mc->max_cpus = 511;
504 mc->smp_props.dies_supported = false;
507 static void machine_with_dies_class_init(ObjectClass *oc, void *data)
509 MachineClass *mc = MACHINE_CLASS(oc);
511 mc->min_cpus = MIN_CPUS;
512 mc->max_cpus = MAX_CPUS;
514 mc->smp_props.dies_supported = true;
517 static void test_generic_valid(const void *opaque)
519 const char *machine_type = opaque;
520 Object *obj = object_new(machine_type);
521 MachineState *ms = MACHINE(obj);
522 MachineClass *mc = MACHINE_GET_CLASS(obj);
523 SMPTestData data = {};
524 int i;
526 for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
527 data = data_generic_valid[i];
528 unsupported_params_init(mc, &data);
530 smp_parse_test(ms, &data, true);
532 /* Unsupported parameters can be provided with their values as 1 */
533 data.config.has_dies = true;
534 data.config.dies = 1;
535 smp_parse_test(ms, &data, true);
538 object_unref(obj);
541 static void test_generic_invalid(const void *opaque)
543 const char *machine_type = opaque;
544 Object *obj = object_new(machine_type);
545 MachineState *ms = MACHINE(obj);
546 MachineClass *mc = MACHINE_GET_CLASS(obj);
547 SMPTestData data = {};
548 int i;
550 for (i = 0; i < ARRAY_SIZE(data_generic_invalid); i++) {
551 data = data_generic_invalid[i];
552 unsupported_params_init(mc, &data);
554 smp_parse_test(ms, &data, false);
557 object_unref(obj);
560 static void test_with_dies(const void *opaque)
562 const char *machine_type = opaque;
563 Object *obj = object_new(machine_type);
564 MachineState *ms = MACHINE(obj);
565 MachineClass *mc = MACHINE_GET_CLASS(obj);
566 SMPTestData data = {};
567 unsigned int num_dies = 2;
568 int i;
570 for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
571 data = data_generic_valid[i];
572 unsupported_params_init(mc, &data);
574 /* when dies parameter is omitted, it will be set as 1 */
575 data.expect_prefer_sockets.dies = 1;
576 data.expect_prefer_cores.dies = 1;
578 smp_parse_test(ms, &data, true);
580 /* when dies parameter is specified */
581 data.config.has_dies = true;
582 data.config.dies = num_dies;
583 if (data.config.has_cpus) {
584 data.config.cpus *= num_dies;
586 if (data.config.has_maxcpus) {
587 data.config.maxcpus *= num_dies;
590 data.expect_prefer_sockets.dies = num_dies;
591 data.expect_prefer_sockets.cpus *= num_dies;
592 data.expect_prefer_sockets.max_cpus *= num_dies;
593 data.expect_prefer_cores.dies = num_dies;
594 data.expect_prefer_cores.cpus *= num_dies;
595 data.expect_prefer_cores.max_cpus *= num_dies;
597 smp_parse_test(ms, &data, true);
600 for (i = 0; i < ARRAY_SIZE(data_with_dies_invalid); i++) {
601 data = data_with_dies_invalid[i];
602 unsupported_params_init(mc, &data);
604 smp_parse_test(ms, &data, false);
607 object_unref(obj);
610 /* Type info of the tested machine */
611 static const TypeInfo smp_machine_types[] = {
613 .name = TYPE_MACHINE,
614 .parent = TYPE_OBJECT,
615 .abstract = true,
616 .class_init = machine_base_class_init,
617 .class_size = sizeof(MachineClass),
618 .instance_size = sizeof(MachineState),
619 }, {
620 .name = MACHINE_TYPE_NAME("smp-generic-valid"),
621 .parent = TYPE_MACHINE,
622 .class_init = machine_generic_valid_class_init,
623 }, {
624 .name = MACHINE_TYPE_NAME("smp-generic-invalid"),
625 .parent = TYPE_MACHINE,
626 .class_init = machine_generic_invalid_class_init,
627 }, {
628 .name = MACHINE_TYPE_NAME("smp-with-dies"),
629 .parent = TYPE_MACHINE,
630 .class_init = machine_with_dies_class_init,
634 DEFINE_TYPES(smp_machine_types)
636 int main(int argc, char *argv[])
638 module_call_init(MODULE_INIT_QOM);
640 g_test_init(&argc, &argv, NULL);
642 g_test_add_data_func("/test-smp-parse/generic/valid",
643 MACHINE_TYPE_NAME("smp-generic-valid"),
644 test_generic_valid);
645 g_test_add_data_func("/test-smp-parse/generic/invalid",
646 MACHINE_TYPE_NAME("smp-generic-invalid"),
647 test_generic_invalid);
648 g_test_add_data_func("/test-smp-parse/with_dies",
649 MACHINE_TYPE_NAME("smp-with-dies"),
650 test_with_dies);
652 g_test_run();
654 return 0;