Commit 861eb824ca for qemu.org
commit 861eb824ca6a6ac031e82d27c483f3828d2b5048
Author: Marc-André Lureau <marcandre.lureau@redhat.com>
Date: Sun Nov 1 21:17:17 2026 +0100
tests/qmp-cmd-test: assert qapi-type resolves in query-qmp-schema
For every QOM type returned by qom-list-types, call qom-list-properties
and verify that each property's qapi-type value (when present) maps to
a valid entry in the query-qmp-schema introspection output.
The test is gated behind g_test_slow() since it iterates all registered
QOM types.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-ID: <20261101201717.3911097-57-armbru@redhat.com>
diff --git a/tests/qtest/qmp-cmd-test.c b/tests/qtest/qmp-cmd-test.c
index 279a8f5614..acb7b0dd6a 100644
--- a/tests/qtest/qmp-cmd-test.c
+++ b/tests/qtest/qmp-cmd-test.c
@@ -15,6 +15,7 @@
#include "qapi/error.h"
#include "qapi/qapi-visit-introspect.h"
#include "qobject/qdict.h"
+#include "qobject/qlist.h"
#include "qapi/qobject-input-visitor.h"
const char common_args[] = "-nodefaults -machine none";
@@ -131,6 +132,8 @@ typedef struct {
GHashTable *hash;
} QmpSchema;
+static QmpSchema schema;
+
static void qmp_schema_init(QmpSchema *schema)
{
QDict *resp;
@@ -343,9 +346,56 @@ static void test_object_add_failure_modes(void)
qtest_quit(qts);
}
+static void test_qapi_type(void)
+{
+ QTestState *qts;
+ g_autoptr(QDict) resp = NULL;
+ QList *types;
+ QListEntry *type_entry, *prop_entry;
+
+ qts = qtest_init(common_args);
+
+ resp = qtest_qmp(qts,
+ "{ 'execute': 'qom-list-types',"
+ " 'arguments': { 'abstract': true } }");
+ g_assert(qdict_haskey(resp, "return"));
+ types = qdict_get_qlist(resp, "return");
+
+ QLIST_FOREACH_ENTRY(types, type_entry) {
+ QDict *type = qobject_to(QDict, qlist_entry_obj(type_entry));
+ const char *name = qdict_get_str(type, "name");
+ g_autoptr(QDict) props_resp = NULL;
+ QList *props;
+
+ props_resp = qtest_qmp(qts,
+ "{ 'execute': 'qom-list-properties',"
+ " 'arguments': { 'typename': %s } }",
+ name);
+ if (!qdict_haskey(props_resp, "return")) {
+ continue;
+ }
+ props = qdict_get_qlist(props_resp, "return");
+
+ QLIST_FOREACH_ENTRY(props, prop_entry) {
+ QDict *prop = qobject_to(QDict, qlist_entry_obj(prop_entry));
+ const char *qapi_type = qdict_get_try_str(prop, "qapi-type");
+ const char *propname = qdict_get_str(prop, "name");
+ const char *ty = qdict_get_str(prop, "type");
+
+ if (qapi_type) {
+ g_assert_nonnull(qmp_schema_lookup(&schema, qapi_type));
+ } else if (!g_str_has_prefix(ty, "child<") &&
+ !g_str_has_prefix(ty, "link<")) {
+ g_test_message("%s.%s %s has no associated qapi-type",
+ name, propname, ty);
+ }
+ }
+ }
+ qtest_quit(qts);
+}
+
int main(int argc, char *argv[])
{
- QmpSchema schema;
int ret;
g_test_init(&argc, &argv, NULL);
@@ -355,6 +405,9 @@ int main(int argc, char *argv[])
qtest_add_func("qmp/object-add-failure-modes",
test_object_add_failure_modes);
+ if (g_test_slow()) {
+ qtest_add_func("qmp/qapi-type", test_qapi_type);
+ }
ret = g_test_run();