@samitouri / QOSamiQemu / commits / 6ba08f4ace

tests/qtest/test-x86-cpuid-compat: Switch test_feature_flag to data-driven

As with add_cpuid_test(), the add_feature_test() function also allocates memory that is leaked if the test case is not run. Fix this in the same way, by moving all the allocations into test_feature_flag() and passing it a pointer to a struct with the necessary parameters which is a compile-time constant. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Fabiano Rosas <farosas@suse.de> Signed-off-by: Fabiano Rosas <farosas@suse.de>

Peter Maydell committed Mar 8, 2026 at 18:54 UTC 6ba08f4acec830d12f6983b0988c901258654a12
1 file changed +73 -63
tests/qtest/test-x86-cpuid-compat.c
+73 -63
@@ -94,8 +94,12 @@ static void test_cpuid_prop(const void *data)
94
95 /* Parameters to a add_feature_test() test case */
96 typedef struct FeatureTestArgs {
97 - /* cmdline to start QEMU */
98 - const char *cmdline;
97 + /* Test name */
98 + const char *name;
99 + /* CPU type */
100 + const char *cpu;
101 + /* CPU features, may be NULL */
102 + const char *cpufeat;
103 /*
104 * cpuid-input-eax and cpuid-input-ecx values to look for,
105 * in "feature-words" and "filtered-features" properties.
@@ -140,10 +144,17 @@ static void test_feature_flag(const void *data)
144 {
145 const FeatureTestArgs *args = data;
146 char *path;
147 + char *cmdline;
148 QList *present, *filtered;
149 uint32_t value;
150
146 - qtest_start(args->cmdline);
151 + if (args->cpufeat) {
152 + cmdline = g_strdup_printf("-cpu %s,%s", args->cpu, args->cpufeat);
153 + } else {
154 + cmdline = g_strdup_printf("-cpu %s", args->cpu);
155 + }
156 +
157 + qtest_start(cmdline);
158 path = get_cpu0_qom_path();
159 present = qobject_to(QList, qom_get(path, "feature-words"));
160 filtered = qobject_to(QList, qom_get(path, "filtered-features"));
@@ -156,40 +167,7 @@ static void test_feature_flag(const void *data)
167 qobject_unref(present);
168 qobject_unref(filtered);
169 g_free(path);
159 - g_free((void *)args->cmdline);
160 - g_free((void *)data);
161 -}
162 -
163 -/*
164 - * Add test case to ensure that a given feature flag is set in
165 - * either "feature-words" or "filtered-features", when running QEMU
166 - * using cmdline
167 - */
168 -static void add_feature_test(const char *name, const char *cpu,
169 - const char *cpufeat, uint32_t eax,
170 - uint32_t ecx, const char *reg,
171 - int bitnr, bool expected_value)
172 -{
173 - FeatureTestArgs *args = g_new0(FeatureTestArgs, 1);
174 - char *cmdline;
175 -
176 - if (!qtest_has_cpu_model(cpu)) {
177 - return;
178 - }
179 -
180 - if (cpufeat) {
181 - cmdline = g_strdup_printf("-cpu %s,%s", cpu, cpufeat);
182 - } else {
183 - cmdline = g_strdup_printf("-cpu %s", cpu);
184 - }
185 -
186 - args->cmdline = cmdline;
187 - args->in_eax = eax;
188 - args->in_ecx = ecx;
189 - args->reg = reg;
190 - args->bitnr = bitnr;
191 - args->expected_value = expected_value;
192 - qtest_add_data_func(name, args, test_feature_flag);
170 + g_free(cmdline);
171 }
172
173 static void test_plus_minus_subprocess(void)
@@ -381,6 +359,56 @@ static const CpuidTestArgs cpuid_tests[] = {
359 },
360 };
361
362 +/*
363 + * Test cases to ensure that a given feature flag is set in
364 + * either "feature-words" or "filtered-features", when running QEMU
365 + * using cmdline
366 + */
367 +static const FeatureTestArgs feature_tests[] = {
368 + /* Test feature parsing */
369 + {
370 + "x86/cpuid/features/plus",
371 + "486", "+arat",
372 + 6, 0, "EAX", 2, true,
373 + },
374 + {
375 + "x86/cpuid/features/minus",
376 + "pentium", "-mmx",
377 + 1, 0, "EDX", 23, false,
378 + },
379 + {
380 + "x86/cpuid/features/on",
381 + "486", "arat=on",
382 + 6, 0, "EAX", 2, true,
383 + },
384 + {
385 + "x86/cpuid/features/off",
386 + "pentium", "mmx=off",
387 + 1, 0, "EDX", 23, false,
388 + },
389 +
390 + {
391 + "x86/cpuid/features/max-plus-invtsc",
392 + "max" , "+invtsc",
393 + 0x80000007, 0, "EDX", 8, true,
394 + },
395 + {
396 + "x86/cpuid/features/max-invtsc-on",
397 + "max", "invtsc=on",
398 + 0x80000007, 0, "EDX", 8, true,
399 + },
400 + {
401 + "x86/cpuid/features/max-minus-mmx",
402 + "max", "-mmx",
403 + 1, 0, "EDX", 23, false,
404 + },
405 + {
406 + "x86/cpuid/features/max-invtsc-on,mmx=off",
407 + "max", "mmx=off",
408 + 1, 0, "EDX", 23, false,
409 + },
410 +};
411 +
412 int main(int argc, char **argv)
413 {
414 g_test_init(&argc, &argv, NULL);
@@ -397,32 +425,14 @@ int main(int argc, char **argv)
425 &cpuid_tests[i], test_cpuid_prop);
426 }
427
400 - /* Test feature parsing */
401 - add_feature_test("x86/cpuid/features/plus",
402 - "486", "+arat",
403 - 6, 0, "EAX", 2, true);
404 - add_feature_test("x86/cpuid/features/minus",
405 - "pentium", "-mmx",
406 - 1, 0, "EDX", 23, false);
407 - add_feature_test("x86/cpuid/features/on",
408 - "486", "arat=on",
409 - 6, 0, "EAX", 2, true);
410 - add_feature_test("x86/cpuid/features/off",
411 - "pentium", "mmx=off",
412 - 1, 0, "EDX", 23, false);
413 -
414 - add_feature_test("x86/cpuid/features/max-plus-invtsc",
415 - "max" , "+invtsc",
416 - 0x80000007, 0, "EDX", 8, true);
417 - add_feature_test("x86/cpuid/features/max-invtsc-on",
418 - "max", "invtsc=on",
419 - 0x80000007, 0, "EDX", 8, true);
420 - add_feature_test("x86/cpuid/features/max-minus-mmx",
421 - "max", "-mmx",
422 - 1, 0, "EDX", 23, false);
423 - add_feature_test("x86/cpuid/features/max-invtsc-on,mmx=off",
424 - "max", "mmx=off",
425 - 1, 0, "EDX", 23, false);
428 +
429 + for (int i = 0; i < ARRAY_SIZE(feature_tests); i++) {
430 + if (!qtest_has_cpu_model(feature_tests[i].cpu)) {
431 + continue;
432 + }
433 + qtest_add_data_func(feature_tests[i].name,
434 + &feature_tests[i], test_feature_flag);
435 + }
436
437 return g_test_run();
438 }