xref: /openbmc/qemu/tests/qtest/qmp-cmd-test.c (revision 259ebed4)
11e8a1faeSThomas Huth /*
21e8a1faeSThomas Huth  * QMP command test cases
31e8a1faeSThomas Huth  *
41e8a1faeSThomas Huth  * Copyright (c) 2017 Red Hat Inc.
51e8a1faeSThomas Huth  *
61e8a1faeSThomas Huth  * Authors:
71e8a1faeSThomas Huth  *  Markus Armbruster <armbru@redhat.com>
81e8a1faeSThomas Huth  *
91e8a1faeSThomas Huth  * This work is licensed under the terms of the GNU GPL, version 2 or later.
101e8a1faeSThomas Huth  * See the COPYING file in the top-level directory.
111e8a1faeSThomas Huth  */
121e8a1faeSThomas Huth 
131e8a1faeSThomas Huth #include "qemu/osdep.h"
14907b5105SMarc-André Lureau #include "libqtest.h"
151e8a1faeSThomas Huth #include "qapi/error.h"
161e8a1faeSThomas Huth #include "qapi/qapi-visit-introspect.h"
171e8a1faeSThomas Huth #include "qapi/qmp/qdict.h"
181e8a1faeSThomas Huth #include "qapi/qobject-input-visitor.h"
191e8a1faeSThomas Huth 
201e8a1faeSThomas Huth const char common_args[] = "-nodefaults -machine none";
211e8a1faeSThomas Huth 
221e8a1faeSThomas Huth /* Query smoke tests */
231e8a1faeSThomas Huth 
query_error_class(const char * cmd)241e8a1faeSThomas Huth static int query_error_class(const char *cmd)
251e8a1faeSThomas Huth {
261e8a1faeSThomas Huth     static struct {
271e8a1faeSThomas Huth         const char *cmd;
281e8a1faeSThomas Huth         int err_class;
291e8a1faeSThomas Huth     } fails[] = {
301e8a1faeSThomas Huth         /* Success depends on build configuration: */
311e8a1faeSThomas Huth #ifndef CONFIG_SPICE
321e8a1faeSThomas Huth         { "query-spice", ERROR_CLASS_COMMAND_NOT_FOUND },
331e8a1faeSThomas Huth #endif
349b1c9116SClaudio Fontana #ifndef CONFIG_TCG
359b1c9116SClaudio Fontana         { "query-replay", ERROR_CLASS_COMMAND_NOT_FOUND },
369b1c9116SClaudio Fontana #endif
371e8a1faeSThomas Huth #ifndef CONFIG_VNC
381e8a1faeSThomas Huth         { "query-vnc", ERROR_CLASS_GENERIC_ERROR },
391e8a1faeSThomas Huth         { "query-vnc-servers", ERROR_CLASS_GENERIC_ERROR },
401e8a1faeSThomas Huth #endif
411e8a1faeSThomas Huth #ifndef CONFIG_REPLICATION
421e8a1faeSThomas Huth         { "query-xen-replication-status", ERROR_CLASS_COMMAND_NOT_FOUND },
431e8a1faeSThomas Huth #endif
441e8a1faeSThomas Huth         /* Likewise, and require special QEMU command-line arguments: */
451e8a1faeSThomas Huth         { "query-acpi-ospm-status", ERROR_CLASS_GENERIC_ERROR },
461e8a1faeSThomas Huth         { "query-balloon", ERROR_CLASS_DEVICE_NOT_ACTIVE },
471e8a1faeSThomas Huth         { "query-hotpluggable-cpus", ERROR_CLASS_GENERIC_ERROR },
48*259ebed4SMaciej S. Szmigiero         { "query-hv-balloon-status-report", ERROR_CLASS_GENERIC_ERROR },
491e8a1faeSThomas Huth         { "query-vm-generation-id", ERROR_CLASS_GENERIC_ERROR },
50fc309207SDaniel P. Berrangé         /* Only valid with a USB bus added */
51fc309207SDaniel P. Berrangé         { "x-query-usb", ERROR_CLASS_GENERIC_ERROR },
523a841ab5SDaniel P. Berrangé         /* Only valid with accel=tcg */
533a841ab5SDaniel P. Berrangé         { "x-query-jit", ERROR_CLASS_GENERIC_ERROR },
54b6a7f3e0SDaniel P. Berrangé         { "x-query-opcount", ERROR_CLASS_GENERIC_ERROR },
55507cb64dSJoao Martins         { "xen-event-list", ERROR_CLASS_GENERIC_ERROR },
561e8a1faeSThomas Huth         { NULL, -1 }
571e8a1faeSThomas Huth     };
581e8a1faeSThomas Huth     int i;
591e8a1faeSThomas Huth 
601e8a1faeSThomas Huth     for (i = 0; fails[i].cmd; i++) {
611e8a1faeSThomas Huth         if (!strcmp(cmd, fails[i].cmd)) {
621e8a1faeSThomas Huth             return fails[i].err_class;
631e8a1faeSThomas Huth         }
641e8a1faeSThomas Huth     }
651e8a1faeSThomas Huth     return -1;
661e8a1faeSThomas Huth }
671e8a1faeSThomas Huth 
test_query(const void * data)681e8a1faeSThomas Huth static void test_query(const void *data)
691e8a1faeSThomas Huth {
701e8a1faeSThomas Huth     const char *cmd = data;
711e8a1faeSThomas Huth     int expected_error_class = query_error_class(cmd);
721e8a1faeSThomas Huth     QDict *resp, *error;
731e8a1faeSThomas Huth     const char *error_class;
741e8a1faeSThomas Huth     QTestState *qts;
751e8a1faeSThomas Huth 
761e8a1faeSThomas Huth     qts = qtest_init(common_args);
771e8a1faeSThomas Huth 
781e8a1faeSThomas Huth     resp = qtest_qmp(qts, "{ 'execute': %s }", cmd);
791e8a1faeSThomas Huth     error = qdict_get_qdict(resp, "error");
801e8a1faeSThomas Huth     error_class = error ? qdict_get_str(error, "class") : NULL;
811e8a1faeSThomas Huth 
821e8a1faeSThomas Huth     if (expected_error_class < 0) {
831e8a1faeSThomas Huth         g_assert(qdict_haskey(resp, "return"));
841e8a1faeSThomas Huth     } else {
851e8a1faeSThomas Huth         g_assert(error);
861e8a1faeSThomas Huth         g_assert_cmpint(qapi_enum_parse(&QapiErrorClass_lookup, error_class,
871e8a1faeSThomas Huth                                         -1, &error_abort),
881e8a1faeSThomas Huth                         ==, expected_error_class);
891e8a1faeSThomas Huth     }
901e8a1faeSThomas Huth     qobject_unref(resp);
911e8a1faeSThomas Huth 
921e8a1faeSThomas Huth     qtest_quit(qts);
931e8a1faeSThomas Huth }
941e8a1faeSThomas Huth 
query_is_ignored(const char * cmd)95d97b4b0dSThomas Huth static bool query_is_ignored(const char *cmd)
961e8a1faeSThomas Huth {
97d97b4b0dSThomas Huth     const char *ignored[] = {
981e8a1faeSThomas Huth         /* Not actually queries: */
991e8a1faeSThomas Huth         "add-fd",
1001e8a1faeSThomas Huth         /* Success depends on target arch: */
1011e8a1faeSThomas Huth         "query-cpu-definitions",  /* arm, i386, ppc, s390x */
1021e8a1faeSThomas Huth         "query-gic-capabilities", /* arm */
1031e8a1faeSThomas Huth         /* Success depends on target-specific build configuration: */
1041e8a1faeSThomas Huth         "query-pci",              /* CONFIG_PCI */
105a5ebce38SLaurent Vivier         "x-query-virtio",         /* CONFIG_VIRTIO */
1061e8a1faeSThomas Huth         /* Success depends on launching SEV guest */
1071e8a1faeSThomas Huth         "query-sev-launch-measure",
1081e8a1faeSThomas Huth         /* Success depends on Host or Hypervisor SEV support */
1091e8a1faeSThomas Huth         "query-sev",
1101e8a1faeSThomas Huth         "query-sev-capabilities",
11157d874c4SYang Zhong         "query-sgx",
1120205c4faSYang Zhong         "query-sgx-capabilities",
113f3b2e38cSHyman Huang(黄勇)         /* Success depends on enabling dirty page rate limit */
114f3b2e38cSHyman Huang(黄勇)         "query-vcpu-dirty-limit",
1151e8a1faeSThomas Huth         NULL
1161e8a1faeSThomas Huth     };
1171e8a1faeSThomas Huth     int i;
1181e8a1faeSThomas Huth 
119d97b4b0dSThomas Huth     for (i = 0; ignored[i]; i++) {
120d97b4b0dSThomas Huth         if (!strcmp(cmd, ignored[i])) {
1211e8a1faeSThomas Huth             return true;
1221e8a1faeSThomas Huth         }
1231e8a1faeSThomas Huth     }
1241e8a1faeSThomas Huth     return false;
1251e8a1faeSThomas Huth }
1261e8a1faeSThomas Huth 
1271e8a1faeSThomas Huth typedef struct {
1281e8a1faeSThomas Huth     SchemaInfoList *list;
1291e8a1faeSThomas Huth     GHashTable *hash;
1301e8a1faeSThomas Huth } QmpSchema;
1311e8a1faeSThomas Huth 
qmp_schema_init(QmpSchema * schema)1321e8a1faeSThomas Huth static void qmp_schema_init(QmpSchema *schema)
1331e8a1faeSThomas Huth {
1341e8a1faeSThomas Huth     QDict *resp;
1351e8a1faeSThomas Huth     Visitor *qiv;
1361e8a1faeSThomas Huth     SchemaInfoList *tail;
1371e8a1faeSThomas Huth     QTestState *qts;
1381e8a1faeSThomas Huth 
1391e8a1faeSThomas Huth     qts = qtest_init(common_args);
1401e8a1faeSThomas Huth 
1411e8a1faeSThomas Huth     resp = qtest_qmp(qts, "{ 'execute': 'query-qmp-schema' }");
1421e8a1faeSThomas Huth 
1431e8a1faeSThomas Huth     qiv = qobject_input_visitor_new(qdict_get(resp, "return"));
1441e8a1faeSThomas Huth     visit_type_SchemaInfoList(qiv, NULL, &schema->list, &error_abort);
1451e8a1faeSThomas Huth     visit_free(qiv);
1461e8a1faeSThomas Huth 
1471e8a1faeSThomas Huth     qobject_unref(resp);
1481e8a1faeSThomas Huth     qtest_quit(qts);
1491e8a1faeSThomas Huth 
1501e8a1faeSThomas Huth     schema->hash = g_hash_table_new(g_str_hash, g_str_equal);
1511e8a1faeSThomas Huth 
1521e8a1faeSThomas Huth     /* Build @schema: hash table mapping entity name to SchemaInfo */
1531e8a1faeSThomas Huth     for (tail = schema->list; tail; tail = tail->next) {
1541e8a1faeSThomas Huth         g_hash_table_insert(schema->hash, tail->value->name, tail->value);
1551e8a1faeSThomas Huth     }
1561e8a1faeSThomas Huth }
1571e8a1faeSThomas Huth 
qmp_schema_lookup(QmpSchema * schema,const char * name)1581e8a1faeSThomas Huth static SchemaInfo *qmp_schema_lookup(QmpSchema *schema, const char *name)
1591e8a1faeSThomas Huth {
1601e8a1faeSThomas Huth     return g_hash_table_lookup(schema->hash, name);
1611e8a1faeSThomas Huth }
1621e8a1faeSThomas Huth 
qmp_schema_cleanup(QmpSchema * schema)1631e8a1faeSThomas Huth static void qmp_schema_cleanup(QmpSchema *schema)
1641e8a1faeSThomas Huth {
1651e8a1faeSThomas Huth     qapi_free_SchemaInfoList(schema->list);
1661e8a1faeSThomas Huth     g_hash_table_destroy(schema->hash);
1671e8a1faeSThomas Huth }
1681e8a1faeSThomas Huth 
object_type_has_mandatory_members(SchemaInfo * type)1691e8a1faeSThomas Huth static bool object_type_has_mandatory_members(SchemaInfo *type)
1701e8a1faeSThomas Huth {
1711e8a1faeSThomas Huth     SchemaInfoObjectMemberList *tail;
1721e8a1faeSThomas Huth 
1731e8a1faeSThomas Huth     g_assert(type->meta_type == SCHEMA_META_TYPE_OBJECT);
1741e8a1faeSThomas Huth 
1751e8a1faeSThomas Huth     for (tail = type->u.object.members; tail; tail = tail->next) {
1764b2fc7dbSMarkus Armbruster         if (!tail->value->q_default) {
1771e8a1faeSThomas Huth             return true;
1781e8a1faeSThomas Huth         }
1791e8a1faeSThomas Huth     }
1801e8a1faeSThomas Huth 
1811e8a1faeSThomas Huth     return false;
1821e8a1faeSThomas Huth }
1831e8a1faeSThomas Huth 
add_query_tests(QmpSchema * schema)1841e8a1faeSThomas Huth static void add_query_tests(QmpSchema *schema)
1851e8a1faeSThomas Huth {
1861e8a1faeSThomas Huth     SchemaInfoList *tail;
1871e8a1faeSThomas Huth     SchemaInfo *si, *arg_type, *ret_type;
1881e8a1faeSThomas Huth     char *test_name;
1891e8a1faeSThomas Huth 
1901e8a1faeSThomas Huth     /* Test the query-like commands */
1911e8a1faeSThomas Huth     for (tail = schema->list; tail; tail = tail->next) {
1921e8a1faeSThomas Huth         si = tail->value;
1931e8a1faeSThomas Huth         if (si->meta_type != SCHEMA_META_TYPE_COMMAND) {
1941e8a1faeSThomas Huth             continue;
1951e8a1faeSThomas Huth         }
1961e8a1faeSThomas Huth 
197d97b4b0dSThomas Huth         if (query_is_ignored(si->name)) {
1981e8a1faeSThomas Huth             continue;
1991e8a1faeSThomas Huth         }
2001e8a1faeSThomas Huth 
2011e8a1faeSThomas Huth         arg_type = qmp_schema_lookup(schema, si->u.command.arg_type);
2021e8a1faeSThomas Huth         if (object_type_has_mandatory_members(arg_type)) {
2031e8a1faeSThomas Huth             continue;
2041e8a1faeSThomas Huth         }
2051e8a1faeSThomas Huth 
2061e8a1faeSThomas Huth         ret_type = qmp_schema_lookup(schema, si->u.command.ret_type);
2071e8a1faeSThomas Huth         if (ret_type->meta_type == SCHEMA_META_TYPE_OBJECT
2081e8a1faeSThomas Huth             && !ret_type->u.object.members) {
2091e8a1faeSThomas Huth             continue;
2101e8a1faeSThomas Huth         }
2111e8a1faeSThomas Huth 
2121e8a1faeSThomas Huth         test_name = g_strdup_printf("qmp/%s", si->name);
2131e8a1faeSThomas Huth         qtest_add_data_func(test_name, si->name, test_query);
2141e8a1faeSThomas Huth         g_free(test_name);
2151e8a1faeSThomas Huth     }
2161e8a1faeSThomas Huth }
2171e8a1faeSThomas Huth 
test_object_add_failure_modes(void)2185b88849eSEric Auger static void test_object_add_failure_modes(void)
2191e8a1faeSThomas Huth {
2201e8a1faeSThomas Huth     QTestState *qts;
2211e8a1faeSThomas Huth     QDict *resp;
2221e8a1faeSThomas Huth 
2235b88849eSEric Auger     /* attempt to create an object without props */
2241e8a1faeSThomas Huth     qts = qtest_init(common_args);
2251e8a1faeSThomas Huth     resp = qtest_qmp(qts, "{'execute': 'object-add', 'arguments':"
2261e8a1faeSThomas Huth                      " {'qom-type': 'memory-backend-ram', 'id': 'ram1' } }");
2271e8a1faeSThomas Huth     g_assert_nonnull(resp);
2283bc1b8eeSMarkus Armbruster     qmp_expect_error_and_unref(resp, "GenericError");
2291e8a1faeSThomas Huth 
2305b88849eSEric Auger     /* attempt to create an object without qom-type */
2319fc719b8SEric Auger     resp = qtest_qmp(qts, "{'execute': 'object-add', 'arguments':"
2325b88849eSEric Auger                      " {'id': 'ram1' } }");
2335b88849eSEric Auger     g_assert_nonnull(resp);
2343bc1b8eeSMarkus Armbruster     qmp_expect_error_and_unref(resp, "GenericError");
2355b88849eSEric Auger 
2365b88849eSEric Auger     /* attempt to delete an object that does not exist */
2375b88849eSEric Auger     resp = qtest_qmp(qts, "{'execute': 'object-del', 'arguments':"
2385b88849eSEric Auger                      " {'id': 'ram1' } }");
2395b88849eSEric Auger     g_assert_nonnull(resp);
2403bc1b8eeSMarkus Armbruster     qmp_expect_error_and_unref(resp, "GenericError");
2415b88849eSEric Auger 
2425b88849eSEric Auger     /* attempt to create 2 objects with duplicate id */
2435b88849eSEric Auger     resp = qtest_qmp(qts, "{'execute': 'object-add', 'arguments':"
2445b88849eSEric Auger                      " {'qom-type': 'memory-backend-ram', 'id': 'ram1',"
2459695c3afSKevin Wolf                      " 'size': 1048576 } }");
2469fc719b8SEric Auger     g_assert_nonnull(resp);
2479fc719b8SEric Auger     g_assert(qdict_haskey(resp, "return"));
24815c51f72SLi Qiang     qobject_unref(resp);
24915c51f72SLi Qiang 
2509fc719b8SEric Auger     resp = qtest_qmp(qts, "{'execute': 'object-add', 'arguments':"
2515b88849eSEric Auger                      " {'qom-type': 'memory-backend-ram', 'id': 'ram1',"
2529695c3afSKevin Wolf                      " 'size': 1048576 } }");
2539fc719b8SEric Auger     g_assert_nonnull(resp);
2543bc1b8eeSMarkus Armbruster     qmp_expect_error_and_unref(resp, "GenericError");
2555b88849eSEric Auger 
2565b88849eSEric Auger     /* delete ram1 object */
2575b88849eSEric Auger     resp = qtest_qmp(qts, "{'execute': 'object-del', 'arguments':"
2585b88849eSEric Auger                      " {'id': 'ram1' } }");
2595b88849eSEric Auger     g_assert_nonnull(resp);
2605b88849eSEric Auger     g_assert(qdict_haskey(resp, "return"));
26115c51f72SLi Qiang     qobject_unref(resp);
2625b88849eSEric Auger 
2635b88849eSEric Auger     /* attempt to create an object with a property of a wrong type */
2645b88849eSEric Auger     resp = qtest_qmp(qts, "{'execute': 'object-add', 'arguments':"
2655b88849eSEric Auger                      " {'qom-type': 'memory-backend-ram', 'id': 'ram1',"
2669695c3afSKevin Wolf                      " 'size': '1048576' } }");
2675b88849eSEric Auger     g_assert_nonnull(resp);
2685b88849eSEric Auger     /* now do it right */
2693bc1b8eeSMarkus Armbruster     qmp_expect_error_and_unref(resp, "GenericError");
27015c51f72SLi Qiang 
2715b88849eSEric Auger     resp = qtest_qmp(qts, "{'execute': 'object-add', 'arguments':"
2725b88849eSEric Auger                      " {'qom-type': 'memory-backend-ram', 'id': 'ram1',"
2739695c3afSKevin Wolf                      " 'size': 1048576 } }");
2745b88849eSEric Auger     g_assert_nonnull(resp);
2755b88849eSEric Auger     g_assert(qdict_haskey(resp, "return"));
27615c51f72SLi Qiang     qobject_unref(resp);
2775b88849eSEric Auger 
2785b88849eSEric Auger     /* delete ram1 object */
2795b88849eSEric Auger     resp = qtest_qmp(qts, "{'execute': 'object-del', 'arguments':"
2805b88849eSEric Auger                      " {'id': 'ram1' } }");
2815b88849eSEric Auger     g_assert_nonnull(resp);
2825b88849eSEric Auger     g_assert(qdict_haskey(resp, "return"));
28315c51f72SLi Qiang     qobject_unref(resp);
2845b88849eSEric Auger 
2855b88849eSEric Auger     /* attempt to create an object without the id */
2865b88849eSEric Auger     resp = qtest_qmp(qts, "{'execute': 'object-add', 'arguments':"
2875b88849eSEric Auger                      " {'qom-type': 'memory-backend-ram',"
2889695c3afSKevin Wolf                      " 'size': 1048576 } }");
2895b88849eSEric Auger     g_assert_nonnull(resp);
2903bc1b8eeSMarkus Armbruster     qmp_expect_error_and_unref(resp, "GenericError");
29115c51f72SLi Qiang 
2925b88849eSEric Auger     /* now do it right */
2935b88849eSEric Auger     resp = qtest_qmp(qts, "{'execute': 'object-add', 'arguments':"
2945b88849eSEric Auger                      " {'qom-type': 'memory-backend-ram', 'id': 'ram1',"
2959695c3afSKevin Wolf                      " 'size': 1048576 } }");
2965b88849eSEric Auger     g_assert_nonnull(resp);
2975b88849eSEric Auger     g_assert(qdict_haskey(resp, "return"));
29815c51f72SLi Qiang     qobject_unref(resp);
2995b88849eSEric Auger 
3005b88849eSEric Auger     /* delete ram1 object */
3015b88849eSEric Auger     resp = qtest_qmp(qts, "{'execute': 'object-del', 'arguments':"
3025b88849eSEric Auger                      " {'id': 'ram1' } }");
3035b88849eSEric Auger     g_assert_nonnull(resp);
3045b88849eSEric Auger     g_assert(qdict_haskey(resp, "return"));
30515c51f72SLi Qiang     qobject_unref(resp);
3065b88849eSEric Auger 
3075b88849eSEric Auger     /* attempt to set a non existing property */
3085b88849eSEric Auger     resp = qtest_qmp(qts, "{'execute': 'object-add', 'arguments':"
3095b88849eSEric Auger                      " {'qom-type': 'memory-backend-ram', 'id': 'ram1',"
3109695c3afSKevin Wolf                      " 'sized': 1048576 } }");
3115b88849eSEric Auger     g_assert_nonnull(resp);
3123bc1b8eeSMarkus Armbruster     qmp_expect_error_and_unref(resp, "GenericError");
31315c51f72SLi Qiang 
3145b88849eSEric Auger     /* now do it right */
3155b88849eSEric Auger     resp = qtest_qmp(qts, "{'execute': 'object-add', 'arguments':"
3165b88849eSEric Auger                      " {'qom-type': 'memory-backend-ram', 'id': 'ram1',"
3179695c3afSKevin Wolf                      " 'size': 1048576 } }");
3185b88849eSEric Auger     g_assert_nonnull(resp);
3195b88849eSEric Auger     g_assert(qdict_haskey(resp, "return"));
32015c51f72SLi Qiang     qobject_unref(resp);
3215b88849eSEric Auger 
3225b88849eSEric Auger     /* delete ram1 object without id */
3235b88849eSEric Auger     resp = qtest_qmp(qts, "{'execute': 'object-del', 'arguments':"
3245b88849eSEric Auger                      " {'ida': 'ram1' } }");
3255b88849eSEric Auger     g_assert_nonnull(resp);
32615c51f72SLi Qiang     qobject_unref(resp);
3275b88849eSEric Auger 
3285b88849eSEric Auger     /* delete ram1 object */
3295b88849eSEric Auger     resp = qtest_qmp(qts, "{'execute': 'object-del', 'arguments':"
3305b88849eSEric Auger                      " {'id': 'ram1' } }");
3315b88849eSEric Auger     g_assert_nonnull(resp);
3325b88849eSEric Auger     g_assert(qdict_haskey(resp, "return"));
33315c51f72SLi Qiang     qobject_unref(resp);
3345b88849eSEric Auger 
3355b88849eSEric Auger     /* delete ram1 object that does not exist anymore*/
3365b88849eSEric Auger     resp = qtest_qmp(qts, "{'execute': 'object-del', 'arguments':"
3375b88849eSEric Auger                      " {'id': 'ram1' } }");
3385b88849eSEric Auger     g_assert_nonnull(resp);
3393bc1b8eeSMarkus Armbruster     qmp_expect_error_and_unref(resp, "GenericError");
3405b88849eSEric Auger 
3419fc719b8SEric Auger     qtest_quit(qts);
3429fc719b8SEric Auger }
3439fc719b8SEric Auger 
main(int argc,char * argv[])3441e8a1faeSThomas Huth int main(int argc, char *argv[])
3451e8a1faeSThomas Huth {
3461e8a1faeSThomas Huth     QmpSchema schema;
3471e8a1faeSThomas Huth     int ret;
3481e8a1faeSThomas Huth 
3491e8a1faeSThomas Huth     g_test_init(&argc, &argv, NULL);
3501e8a1faeSThomas Huth 
3511e8a1faeSThomas Huth     qmp_schema_init(&schema);
3521e8a1faeSThomas Huth     add_query_tests(&schema);
3531e8a1faeSThomas Huth 
3545b88849eSEric Auger     qtest_add_func("qmp/object-add-failure-modes",
3555b88849eSEric Auger                    test_object_add_failure_modes);
3561e8a1faeSThomas Huth 
3571e8a1faeSThomas Huth     ret = g_test_run();
3581e8a1faeSThomas Huth 
3591e8a1faeSThomas Huth     qmp_schema_cleanup(&schema);
3601e8a1faeSThomas Huth     return ret;
3611e8a1faeSThomas Huth }
362