blob: 74526f3af2b09f73db73dc45293f32ebf76aaa27 [file] [log] [blame]
/*
* Validate -readconfig
*
* Copyright (c) 2022 Red Hat, Inc.
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
#include "qemu/osdep.h"
#include "libqtest.h"
#include "qapi/error.h"
#include "qapi/qapi-visit-machine.h"
#include "qapi/qapi-visit-qom.h"
#include "qapi/qapi-visit-ui.h"
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qlist.h"
#include "qapi/qobject-input-visitor.h"
#include "qapi/qmp/qstring.h"
#include "qemu/units.h"
static QTestState *qtest_init_with_config(const char *cfgdata)
{
GError *error = NULL;
g_autofree char *args = NULL;
int cfgfd = -1;
g_autofree char *cfgpath = NULL;
QTestState *qts;
ssize_t ret;
cfgfd = g_file_open_tmp("readconfig-test-XXXXXX", &cfgpath, &error);
g_assert_no_error(error);
g_assert_cmpint(cfgfd, >=, 0);
ret = qemu_write_full(cfgfd, cfgdata, strlen(cfgdata));
close(cfgfd);
if (ret < 0) {
unlink(cfgpath);
}
g_assert_cmpint(ret, ==, strlen(cfgdata));
args = g_strdup_printf("-nodefaults -machine none -readconfig %s", cfgpath);
qts = qtest_init(args);
unlink(cfgpath);
return qts;
}
static void test_x86_memdev_resp(QObject *res, const char *mem_id, int size)
{
Visitor *v;
g_autoptr(MemdevList) memdevs = NULL;
Memdev *memdev;
g_assert(res);
v = qobject_input_visitor_new(res);
visit_type_MemdevList(v, NULL, &memdevs, &error_abort);
g_assert(memdevs);
g_assert(memdevs->value);
g_assert(!memdevs->next);
memdev = memdevs->value;
g_assert_cmpstr(memdev->id, ==, mem_id);
g_assert_cmpint(memdev->size, ==, size * MiB);
visit_free(v);
}
static void test_x86_memdev(void)
{
QDict *resp;
QTestState *qts;
const char *cfgdata =
"[memory]\n"
"size = \"200\"";
qts = qtest_init_with_config(cfgdata);
/* Test valid command */
resp = qtest_qmp(qts, "{ 'execute': 'query-memdev' }");
test_x86_memdev_resp(qdict_get(resp, "return"), "ram", 200);
qobject_unref(resp);
qtest_quit(qts);
}
/* FIXME: The test is currently broken on FreeBSD */
#if defined(CONFIG_SPICE) && !defined(__FreeBSD__)
static void test_spice_resp(QObject *res)
{
Visitor *v;
g_autoptr(SpiceInfo) spice = NULL;
g_assert(res);
v = qobject_input_visitor_new(res);
visit_type_SpiceInfo(v, "spice", &spice, &error_abort);
g_assert(spice);
g_assert(spice->enabled);
visit_free(v);
}
static void test_spice(void)
{
QDict *resp;
QTestState *qts;
const char *cfgdata =
"[spice]\n"
#ifndef WIN32
"unix = \"on\"\n"
#endif
"disable-ticketing = \"on\"\n";
qts = qtest_init_with_config(cfgdata);
/* Test valid command */
resp = qtest_qmp(qts, "{ 'execute': 'query-spice' }");
test_spice_resp(qdict_get(resp, "return"));
qobject_unref(resp);
qtest_quit(qts);
}
#endif
static void test_object_available(QObject *res, const char *name,
const char *type)
{
Visitor *v;
g_autoptr(ObjectPropertyInfoList) objs = NULL;
ObjectPropertyInfoList *tmp;
ObjectPropertyInfo *obj;
bool object_available = false;
g_autofree char *childtype = g_strdup_printf("child<%s>", type);
g_assert(res);
v = qobject_input_visitor_new(res);
visit_type_ObjectPropertyInfoList(v, NULL, &objs, &error_abort);
g_assert(objs);
tmp = objs;
while (tmp) {
g_assert(tmp->value);
obj = tmp->value;
if (g_str_equal(obj->name, name) && g_str_equal(obj->type, childtype)) {
object_available = true;
break;
}
tmp = tmp->next;
}
g_assert(object_available);
visit_free(v);
}
static void test_object_rng(void)
{
QDict *resp;
QTestState *qts;
const char *cfgdata =
"[object]\n"
"qom-type = \"rng-builtin\"\n"
"id = \"rng0\"\n";
qts = qtest_init_with_config(cfgdata);
/* Test valid command */
resp = qtest_qmp(qts,
"{ 'execute': 'qom-list',"
" 'arguments': {'path': '/objects' }}");
test_object_available(qdict_get(resp, "return"), "rng0", "rng-builtin");
qobject_unref(resp);
qtest_quit(qts);
}
static void test_docs_config_ich9(void)
{
QTestState *qts;
QDict *resp;
QObject *qobj;
qts = qtest_initf("-nodefaults -readconfig docs/config/ich9-ehci-uhci.cfg");
resp = qtest_qmp(qts, "{ 'execute': 'qom-list',"
" 'arguments': {'path': '/machine/peripheral' }}");
qobj = qdict_get(resp, "return");
test_object_available(qobj, "ehci", "ich9-usb-ehci1");
test_object_available(qobj, "uhci-1", "ich9-usb-uhci1");
test_object_available(qobj, "uhci-2", "ich9-usb-uhci2");
test_object_available(qobj, "uhci-3", "ich9-usb-uhci3");
qobject_unref(resp);
qtest_quit(qts);
}
int main(int argc, char *argv[])
{
const char *arch;
g_test_init(&argc, &argv, NULL);
arch = qtest_get_arch();
if (g_str_equal(arch, "i386") ||
g_str_equal(arch, "x86_64")) {
qtest_add_func("readconfig/x86/memdev", test_x86_memdev);
if (qtest_has_device("ich9-usb-ehci1") &&
qtest_has_device("ich9-usb-uhci1")) {
qtest_add_func("readconfig/x86/ich9-ehci-uhci", test_docs_config_ich9);
}
}
#if defined(CONFIG_SPICE) && !defined(__FreeBSD__)
qtest_add_func("readconfig/spice", test_spice);
#endif
qtest_add_func("readconfig/object-rng", test_object_rng);
return g_test_run();
}