1f6a5f380SDaniel P. Berrangé /* 2f6a5f380SDaniel P. Berrangé * Validate -readconfig 3f6a5f380SDaniel P. Berrangé * 4f6a5f380SDaniel P. Berrangé * Copyright (c) 2022 Red Hat, Inc. 5f6a5f380SDaniel P. Berrangé * 6f6a5f380SDaniel P. Berrangé * This work is licensed under the terms of the GNU GPL, version 2 or later. 7f6a5f380SDaniel P. Berrangé * See the COPYING file in the top-level directory. 8f6a5f380SDaniel P. Berrangé */ 9f6a5f380SDaniel P. Berrangé 10f6a5f380SDaniel P. Berrangé #include "qemu/osdep.h" 11f6a5f380SDaniel P. Berrangé #include "libqtest.h" 12f6a5f380SDaniel P. Berrangé #include "qapi/error.h" 13f6a5f380SDaniel P. Berrangé #include "qapi/qapi-visit-machine.h" 14f6a5f380SDaniel P. Berrangé #include "qapi/qapi-visit-qom.h" 15f6a5f380SDaniel P. Berrangé #include "qapi/qapi-visit-ui.h" 16*407bc4bfSDaniel P. Berrangé #include "qobject/qdict.h" 17*407bc4bfSDaniel P. Berrangé #include "qobject/qlist.h" 18f6a5f380SDaniel P. Berrangé #include "qapi/qobject-input-visitor.h" 19*407bc4bfSDaniel P. Berrangé #include "qobject/qstring.h" 20f6a5f380SDaniel P. Berrangé #include "qemu/units.h" 21f6a5f380SDaniel P. Berrangé 22f6a5f380SDaniel P. Berrangé static QTestState *qtest_init_with_config(const char *cfgdata) 23f6a5f380SDaniel P. Berrangé { 24f6a5f380SDaniel P. Berrangé GError *error = NULL; 25f6a5f380SDaniel P. Berrangé g_autofree char *args = NULL; 26f6a5f380SDaniel P. Berrangé int cfgfd = -1; 27f6a5f380SDaniel P. Berrangé g_autofree char *cfgpath = NULL; 28f6a5f380SDaniel P. Berrangé QTestState *qts; 29f6a5f380SDaniel P. Berrangé ssize_t ret; 30f6a5f380SDaniel P. Berrangé 31f6a5f380SDaniel P. Berrangé cfgfd = g_file_open_tmp("readconfig-test-XXXXXX", &cfgpath, &error); 32f6a5f380SDaniel P. Berrangé g_assert_no_error(error); 33f6a5f380SDaniel P. Berrangé g_assert_cmpint(cfgfd, >=, 0); 34f6a5f380SDaniel P. Berrangé 35f6a5f380SDaniel P. Berrangé ret = qemu_write_full(cfgfd, cfgdata, strlen(cfgdata)); 369c23d719SDaniel P. Berrangé close(cfgfd); 37f6a5f380SDaniel P. Berrangé if (ret < 0) { 38f6a5f380SDaniel P. Berrangé unlink(cfgpath); 39f6a5f380SDaniel P. Berrangé } 40f6a5f380SDaniel P. Berrangé g_assert_cmpint(ret, ==, strlen(cfgdata)); 41f6a5f380SDaniel P. Berrangé 42f6a5f380SDaniel P. Berrangé args = g_strdup_printf("-nodefaults -machine none -readconfig %s", cfgpath); 43f6a5f380SDaniel P. Berrangé 44f6a5f380SDaniel P. Berrangé qts = qtest_init(args); 45f6a5f380SDaniel P. Berrangé 46f6a5f380SDaniel P. Berrangé unlink(cfgpath); 47f6a5f380SDaniel P. Berrangé 48f6a5f380SDaniel P. Berrangé return qts; 49f6a5f380SDaniel P. Berrangé } 50f6a5f380SDaniel P. Berrangé 515a7d4dc9SThomas Huth static void test_x86_memdev_resp(QObject *res, const char *mem_id, int size) 52f6a5f380SDaniel P. Berrangé { 53f6a5f380SDaniel P. Berrangé Visitor *v; 54f6a5f380SDaniel P. Berrangé g_autoptr(MemdevList) memdevs = NULL; 55f6a5f380SDaniel P. Berrangé Memdev *memdev; 56f6a5f380SDaniel P. Berrangé 57f6a5f380SDaniel P. Berrangé g_assert(res); 58f6a5f380SDaniel P. Berrangé v = qobject_input_visitor_new(res); 59f6a5f380SDaniel P. Berrangé visit_type_MemdevList(v, NULL, &memdevs, &error_abort); 60f6a5f380SDaniel P. Berrangé 61f6a5f380SDaniel P. Berrangé g_assert(memdevs); 62f6a5f380SDaniel P. Berrangé g_assert(memdevs->value); 63f6a5f380SDaniel P. Berrangé g_assert(!memdevs->next); 64f6a5f380SDaniel P. Berrangé 65f6a5f380SDaniel P. Berrangé memdev = memdevs->value; 665a7d4dc9SThomas Huth g_assert_cmpstr(memdev->id, ==, mem_id); 675a7d4dc9SThomas Huth g_assert_cmpint(memdev->size, ==, size * MiB); 68f6a5f380SDaniel P. Berrangé 69f6a5f380SDaniel P. Berrangé visit_free(v); 70f6a5f380SDaniel P. Berrangé } 71f6a5f380SDaniel P. Berrangé 72f6a5f380SDaniel P. Berrangé static void test_x86_memdev(void) 73f6a5f380SDaniel P. Berrangé { 74f6a5f380SDaniel P. Berrangé QDict *resp; 75f6a5f380SDaniel P. Berrangé QTestState *qts; 76f6a5f380SDaniel P. Berrangé const char *cfgdata = 77f6a5f380SDaniel P. Berrangé "[memory]\n" 78f6a5f380SDaniel P. Berrangé "size = \"200\""; 79f6a5f380SDaniel P. Berrangé 80f6a5f380SDaniel P. Berrangé qts = qtest_init_with_config(cfgdata); 81f6a5f380SDaniel P. Berrangé /* Test valid command */ 82f6a5f380SDaniel P. Berrangé resp = qtest_qmp(qts, "{ 'execute': 'query-memdev' }"); 835a7d4dc9SThomas Huth test_x86_memdev_resp(qdict_get(resp, "return"), "ram", 200); 84f6a5f380SDaniel P. Berrangé qobject_unref(resp); 85f6a5f380SDaniel P. Berrangé 86f6a5f380SDaniel P. Berrangé qtest_quit(qts); 87f6a5f380SDaniel P. Berrangé } 88f6a5f380SDaniel P. Berrangé 8901013d2cSThomas Huth /* FIXME: The test is currently broken on FreeBSD */ 9001013d2cSThomas Huth #if defined(CONFIG_SPICE) && !defined(__FreeBSD__) 91f6a5f380SDaniel P. Berrangé static void test_spice_resp(QObject *res) 92f6a5f380SDaniel P. Berrangé { 93f6a5f380SDaniel P. Berrangé Visitor *v; 94f6a5f380SDaniel P. Berrangé g_autoptr(SpiceInfo) spice = NULL; 95f6a5f380SDaniel P. Berrangé 96f6a5f380SDaniel P. Berrangé g_assert(res); 97f6a5f380SDaniel P. Berrangé v = qobject_input_visitor_new(res); 989c23d719SDaniel P. Berrangé visit_type_SpiceInfo(v, "spice", &spice, &error_abort); 99f6a5f380SDaniel P. Berrangé 100f6a5f380SDaniel P. Berrangé g_assert(spice); 101f6a5f380SDaniel P. Berrangé g_assert(spice->enabled); 102f6a5f380SDaniel P. Berrangé 103f6a5f380SDaniel P. Berrangé visit_free(v); 104f6a5f380SDaniel P. Berrangé } 105f6a5f380SDaniel P. Berrangé 106f6a5f380SDaniel P. Berrangé static void test_spice(void) 107f6a5f380SDaniel P. Berrangé { 108f6a5f380SDaniel P. Berrangé QDict *resp; 109f6a5f380SDaniel P. Berrangé QTestState *qts; 110f6a5f380SDaniel P. Berrangé const char *cfgdata = 111f6a5f380SDaniel P. Berrangé "[spice]\n" 112beecc4b7SMarc-André Lureau #ifndef WIN32 113beecc4b7SMarc-André Lureau "unix = \"on\"\n" 114beecc4b7SMarc-André Lureau #endif 115beecc4b7SMarc-André Lureau "disable-ticketing = \"on\"\n"; 116f6a5f380SDaniel P. Berrangé 117f6a5f380SDaniel P. Berrangé qts = qtest_init_with_config(cfgdata); 118f6a5f380SDaniel P. Berrangé /* Test valid command */ 119f6a5f380SDaniel P. Berrangé resp = qtest_qmp(qts, "{ 'execute': 'query-spice' }"); 120f6a5f380SDaniel P. Berrangé test_spice_resp(qdict_get(resp, "return")); 121f6a5f380SDaniel P. Berrangé qobject_unref(resp); 122f6a5f380SDaniel P. Berrangé 123f6a5f380SDaniel P. Berrangé qtest_quit(qts); 124f6a5f380SDaniel P. Berrangé } 125f6a5f380SDaniel P. Berrangé #endif 126f6a5f380SDaniel P. Berrangé 12779571e7fSThomas Huth static void test_object_available(QObject *res, const char *name, 12879571e7fSThomas Huth const char *type) 129f6a5f380SDaniel P. Berrangé { 130f6a5f380SDaniel P. Berrangé Visitor *v; 131f6a5f380SDaniel P. Berrangé g_autoptr(ObjectPropertyInfoList) objs = NULL; 132f6a5f380SDaniel P. Berrangé ObjectPropertyInfoList *tmp; 133f6a5f380SDaniel P. Berrangé ObjectPropertyInfo *obj; 13479571e7fSThomas Huth bool object_available = false; 13579571e7fSThomas Huth g_autofree char *childtype = g_strdup_printf("child<%s>", type); 136f6a5f380SDaniel P. Berrangé 137f6a5f380SDaniel P. Berrangé g_assert(res); 138f6a5f380SDaniel P. Berrangé v = qobject_input_visitor_new(res); 139f6a5f380SDaniel P. Berrangé visit_type_ObjectPropertyInfoList(v, NULL, &objs, &error_abort); 140f6a5f380SDaniel P. Berrangé 141f6a5f380SDaniel P. Berrangé g_assert(objs); 142f6a5f380SDaniel P. Berrangé tmp = objs; 143f6a5f380SDaniel P. Berrangé while (tmp) { 144f6a5f380SDaniel P. Berrangé g_assert(tmp->value); 145f6a5f380SDaniel P. Berrangé 146f6a5f380SDaniel P. Berrangé obj = tmp->value; 14779571e7fSThomas Huth if (g_str_equal(obj->name, name) && g_str_equal(obj->type, childtype)) { 14879571e7fSThomas Huth object_available = true; 1499c23d719SDaniel P. Berrangé break; 150f6a5f380SDaniel P. Berrangé } 151f6a5f380SDaniel P. Berrangé 152f6a5f380SDaniel P. Berrangé tmp = tmp->next; 153f6a5f380SDaniel P. Berrangé } 154f6a5f380SDaniel P. Berrangé 15579571e7fSThomas Huth g_assert(object_available); 156f6a5f380SDaniel P. Berrangé 157f6a5f380SDaniel P. Berrangé visit_free(v); 158f6a5f380SDaniel P. Berrangé } 159f6a5f380SDaniel P. Berrangé 160f6a5f380SDaniel P. Berrangé static void test_object_rng(void) 161f6a5f380SDaniel P. Berrangé { 162f6a5f380SDaniel P. Berrangé QDict *resp; 163f6a5f380SDaniel P. Berrangé QTestState *qts; 164f6a5f380SDaniel P. Berrangé const char *cfgdata = 165f6a5f380SDaniel P. Berrangé "[object]\n" 166f6a5f380SDaniel P. Berrangé "qom-type = \"rng-builtin\"\n" 167f6a5f380SDaniel P. Berrangé "id = \"rng0\"\n"; 168f6a5f380SDaniel P. Berrangé 169f6a5f380SDaniel P. Berrangé qts = qtest_init_with_config(cfgdata); 170f6a5f380SDaniel P. Berrangé /* Test valid command */ 171f6a5f380SDaniel P. Berrangé resp = qtest_qmp(qts, 172f6a5f380SDaniel P. Berrangé "{ 'execute': 'qom-list'," 173f6a5f380SDaniel P. Berrangé " 'arguments': {'path': '/objects' }}"); 17479571e7fSThomas Huth test_object_available(qdict_get(resp, "return"), "rng0", "rng-builtin"); 175f6a5f380SDaniel P. Berrangé qobject_unref(resp); 176f6a5f380SDaniel P. Berrangé 177f6a5f380SDaniel P. Berrangé qtest_quit(qts); 178f6a5f380SDaniel P. Berrangé } 179f6a5f380SDaniel P. Berrangé 180201aa17eSThomas Huth static void test_docs_config_ich9(void) 181201aa17eSThomas Huth { 182201aa17eSThomas Huth QTestState *qts; 183201aa17eSThomas Huth QDict *resp; 184201aa17eSThomas Huth QObject *qobj; 185201aa17eSThomas Huth 186201aa17eSThomas Huth qts = qtest_initf("-nodefaults -readconfig docs/config/ich9-ehci-uhci.cfg"); 187201aa17eSThomas Huth 188201aa17eSThomas Huth resp = qtest_qmp(qts, "{ 'execute': 'qom-list'," 189201aa17eSThomas Huth " 'arguments': {'path': '/machine/peripheral' }}"); 190201aa17eSThomas Huth qobj = qdict_get(resp, "return"); 191201aa17eSThomas Huth test_object_available(qobj, "ehci", "ich9-usb-ehci1"); 192201aa17eSThomas Huth test_object_available(qobj, "uhci-1", "ich9-usb-uhci1"); 193201aa17eSThomas Huth test_object_available(qobj, "uhci-2", "ich9-usb-uhci2"); 194201aa17eSThomas Huth test_object_available(qobj, "uhci-3", "ich9-usb-uhci3"); 195201aa17eSThomas Huth qobject_unref(resp); 196201aa17eSThomas Huth 197201aa17eSThomas Huth qtest_quit(qts); 198201aa17eSThomas Huth } 199201aa17eSThomas Huth 200bc55e2eaSThomas Huth #if defined(CONFIG_POSIX) && defined(CONFIG_SLIRP) 201bc55e2eaSThomas Huth 202bc55e2eaSThomas Huth static char *make_temp_img(const char *template, const char *format, int size) 203bc55e2eaSThomas Huth { 204bc55e2eaSThomas Huth GError *error = NULL; 205bc55e2eaSThomas Huth char *temp_name; 206bc55e2eaSThomas Huth int fd; 207bc55e2eaSThomas Huth 208bc55e2eaSThomas Huth /* Create a temporary image names */ 209bc55e2eaSThomas Huth fd = g_file_open_tmp(template, &temp_name, &error); 210bc55e2eaSThomas Huth if (fd == -1) { 211bc55e2eaSThomas Huth fprintf(stderr, "unable to create file: %s\n", error->message); 212bc55e2eaSThomas Huth g_error_free(error); 213bc55e2eaSThomas Huth return NULL; 214bc55e2eaSThomas Huth } 215bc55e2eaSThomas Huth close(fd); 216bc55e2eaSThomas Huth 217bc55e2eaSThomas Huth if (!mkimg(temp_name, format, size)) { 218bc55e2eaSThomas Huth fprintf(stderr, "qemu-img failed to create %s\n", temp_name); 219bc55e2eaSThomas Huth g_free(temp_name); 220bc55e2eaSThomas Huth return NULL; 221bc55e2eaSThomas Huth } 222bc55e2eaSThomas Huth 223bc55e2eaSThomas Huth return temp_name; 224bc55e2eaSThomas Huth } 225bc55e2eaSThomas Huth 226bc55e2eaSThomas Huth struct device { 227bc55e2eaSThomas Huth const char *name; 228bc55e2eaSThomas Huth const char *type; 229bc55e2eaSThomas Huth }; 230bc55e2eaSThomas Huth 231bc55e2eaSThomas Huth static void test_docs_q35(const char *input_file, struct device *devices) 232bc55e2eaSThomas Huth { 233bc55e2eaSThomas Huth QTestState *qts; 234bc55e2eaSThomas Huth QDict *resp; 235bc55e2eaSThomas Huth QObject *qobj; 236bc55e2eaSThomas Huth int ret, i; 237bc55e2eaSThomas Huth g_autofree char *cfg_file = NULL, *sedcmd = NULL; 238bc55e2eaSThomas Huth g_autofree char *hd_file = NULL, *cd_file = NULL; 239bc55e2eaSThomas Huth 240bc55e2eaSThomas Huth /* Check that all the devices are available in the QEMU binary */ 241bc55e2eaSThomas Huth for (i = 0; devices[i].name; i++) { 242bc55e2eaSThomas Huth if (!qtest_has_device(devices[i].type)) { 243bc55e2eaSThomas Huth g_test_skip("one of the required devices is not available"); 244bc55e2eaSThomas Huth return; 245bc55e2eaSThomas Huth } 246bc55e2eaSThomas Huth } 247bc55e2eaSThomas Huth 248bc55e2eaSThomas Huth hd_file = make_temp_img("qtest_disk_XXXXXX.qcow2", "qcow2", 1); 249bc55e2eaSThomas Huth cd_file = make_temp_img("qtest_cdrom_XXXXXX.iso", "raw", 1); 250bc55e2eaSThomas Huth if (!hd_file || !cd_file) { 251bc55e2eaSThomas Huth g_test_skip("could not create disk images"); 252bc55e2eaSThomas Huth goto cleanup; 253bc55e2eaSThomas Huth } 254bc55e2eaSThomas Huth 255bc55e2eaSThomas Huth /* Create a temporary config file where we replace the disk image names */ 256bc55e2eaSThomas Huth ret = g_file_open_tmp("q35-emulated-XXXXXX.cfg", &cfg_file, NULL); 257bc55e2eaSThomas Huth if (ret == -1) { 258bc55e2eaSThomas Huth g_test_skip("could not create temporary config file"); 259bc55e2eaSThomas Huth goto cleanup; 260bc55e2eaSThomas Huth } 261bc55e2eaSThomas Huth close(ret); 262bc55e2eaSThomas Huth 263bc55e2eaSThomas Huth sedcmd = g_strdup_printf("sed -e 's,guest.qcow2,%s,' -e 's,install.iso,%s,'" 264bc55e2eaSThomas Huth " %s %s > '%s'", 265bc55e2eaSThomas Huth hd_file, cd_file, 266bc55e2eaSThomas Huth !qtest_has_accel("kvm") ? "-e '/accel/d'" : "", 267bc55e2eaSThomas Huth input_file, cfg_file); 268bc55e2eaSThomas Huth ret = system(sedcmd); 269bc55e2eaSThomas Huth if (ret) { 270bc55e2eaSThomas Huth g_test_skip("could not modify temporary config file"); 271bc55e2eaSThomas Huth goto cleanup; 272bc55e2eaSThomas Huth } 273bc55e2eaSThomas Huth 274bc55e2eaSThomas Huth qts = qtest_initf("-machine none -nodefaults -readconfig %s", cfg_file); 275bc55e2eaSThomas Huth 276bc55e2eaSThomas Huth /* Check memory size */ 277bc55e2eaSThomas Huth resp = qtest_qmp(qts, "{ 'execute': 'query-memdev' }"); 278bc55e2eaSThomas Huth test_x86_memdev_resp(qdict_get(resp, "return"), "pc.ram", 1024); 279bc55e2eaSThomas Huth qobject_unref(resp); 280bc55e2eaSThomas Huth 281bc55e2eaSThomas Huth resp = qtest_qmp(qts, "{ 'execute': 'qom-list'," 282bc55e2eaSThomas Huth " 'arguments': {'path': '/machine/peripheral' }}"); 283bc55e2eaSThomas Huth qobj = qdict_get(resp, "return"); 284bc55e2eaSThomas Huth 285bc55e2eaSThomas Huth /* Check that all the devices have been created */ 286bc55e2eaSThomas Huth for (i = 0; devices[i].name; i++) { 287bc55e2eaSThomas Huth test_object_available(qobj, devices[i].name, devices[i].type); 288bc55e2eaSThomas Huth } 289bc55e2eaSThomas Huth 290bc55e2eaSThomas Huth qobject_unref(resp); 291bc55e2eaSThomas Huth 292bc55e2eaSThomas Huth qtest_quit(qts); 293bc55e2eaSThomas Huth 294bc55e2eaSThomas Huth cleanup: 295bc55e2eaSThomas Huth if (hd_file) { 296bc55e2eaSThomas Huth unlink(hd_file); 297bc55e2eaSThomas Huth } 298bc55e2eaSThomas Huth if (cd_file) { 299bc55e2eaSThomas Huth unlink(cd_file); 300bc55e2eaSThomas Huth } 301bc55e2eaSThomas Huth if (cfg_file) { 302bc55e2eaSThomas Huth unlink(cfg_file); 303bc55e2eaSThomas Huth } 304bc55e2eaSThomas Huth } 305bc55e2eaSThomas Huth 306bc55e2eaSThomas Huth static void test_docs_q35_emulated(void) 307bc55e2eaSThomas Huth { 308bc55e2eaSThomas Huth struct device devices[] = { 309bc55e2eaSThomas Huth { "ich9-pcie-port-1", "ioh3420" }, 310bc55e2eaSThomas Huth { "ich9-pcie-port-2", "ioh3420" }, 311bc55e2eaSThomas Huth { "ich9-pcie-port-3", "ioh3420" }, 312bc55e2eaSThomas Huth { "ich9-pcie-port-4", "ioh3420" }, 313bc55e2eaSThomas Huth { "ich9-pci-bridge", "i82801b11-bridge" }, 314bc55e2eaSThomas Huth { "ich9-ehci-1", "ich9-usb-ehci1" }, 315bc55e2eaSThomas Huth { "ich9-ehci-2", "ich9-usb-ehci2" }, 316bc55e2eaSThomas Huth { "ich9-uhci-1", "ich9-usb-uhci1" }, 317bc55e2eaSThomas Huth { "ich9-uhci-2", "ich9-usb-uhci2" }, 318bc55e2eaSThomas Huth { "ich9-uhci-3", "ich9-usb-uhci3" }, 319bc55e2eaSThomas Huth { "ich9-uhci-4", "ich9-usb-uhci4" }, 320bc55e2eaSThomas Huth { "ich9-uhci-5", "ich9-usb-uhci5" }, 321bc55e2eaSThomas Huth { "ich9-uhci-6", "ich9-usb-uhci6" }, 322bc55e2eaSThomas Huth { "sata-disk", "ide-hd" }, 323bc55e2eaSThomas Huth { "sata-optical-disk", "ide-cd" }, 324bc55e2eaSThomas Huth { "net", "e1000" }, 325bc55e2eaSThomas Huth { "video", "VGA" }, 326bc55e2eaSThomas Huth { "ich9-hda-audio", "ich9-intel-hda" }, 327bc55e2eaSThomas Huth { "ich9-hda-duplex", "hda-duplex" }, 328bc55e2eaSThomas Huth { NULL, NULL } 329bc55e2eaSThomas Huth }; 330bc55e2eaSThomas Huth 331bc55e2eaSThomas Huth test_docs_q35("docs/config/q35-emulated.cfg", devices); 332bc55e2eaSThomas Huth } 333bc55e2eaSThomas Huth 334bc55e2eaSThomas Huth static void test_docs_q35_virtio_graphical(void) 335bc55e2eaSThomas Huth { 336bc55e2eaSThomas Huth struct device devices[] = { 337bc55e2eaSThomas Huth { "pcie.1", "pcie-root-port" }, 338bc55e2eaSThomas Huth { "pcie.2", "pcie-root-port" }, 339bc55e2eaSThomas Huth { "pcie.3", "pcie-root-port" }, 340bc55e2eaSThomas Huth { "pcie.4", "pcie-root-port" }, 341bc55e2eaSThomas Huth { "pcie.5", "pcie-root-port" }, 342bc55e2eaSThomas Huth { "pcie.6", "pcie-root-port" }, 343bc55e2eaSThomas Huth { "pcie.7", "pcie-root-port" }, 344bc55e2eaSThomas Huth { "pcie.8", "pcie-root-port" }, 345bc55e2eaSThomas Huth { "scsi", "virtio-scsi-pci" }, 346bc55e2eaSThomas Huth { "scsi-disk", "scsi-hd" }, 347bc55e2eaSThomas Huth { "scsi-optical-disk", "scsi-cd" }, 348bc55e2eaSThomas Huth { "net", "virtio-net-pci" }, 349bc55e2eaSThomas Huth { "usb", "nec-usb-xhci" }, 350bc55e2eaSThomas Huth { "tablet", "usb-tablet" }, 351bc55e2eaSThomas Huth { "video", "qxl-vga" }, 352bc55e2eaSThomas Huth { "sound", "ich9-intel-hda" }, 353bc55e2eaSThomas Huth { "duplex", "hda-duplex" }, 354bc55e2eaSThomas Huth { NULL, NULL } 355bc55e2eaSThomas Huth }; 356bc55e2eaSThomas Huth 357bc55e2eaSThomas Huth test_docs_q35("docs/config/q35-virtio-graphical.cfg", devices); 358bc55e2eaSThomas Huth } 359bc55e2eaSThomas Huth 360bc55e2eaSThomas Huth static void test_docs_q35_virtio_serial(void) 361bc55e2eaSThomas Huth { 362bc55e2eaSThomas Huth struct device devices[] = { 363bc55e2eaSThomas Huth { "pcie.1", "pcie-root-port" }, 364bc55e2eaSThomas Huth { "pcie.2", "pcie-root-port" }, 365bc55e2eaSThomas Huth { "pcie.3", "pcie-root-port" }, 366bc55e2eaSThomas Huth { "pcie.4", "pcie-root-port" }, 367bc55e2eaSThomas Huth { "pcie.5", "pcie-root-port" }, 368bc55e2eaSThomas Huth { "pcie.6", "pcie-root-port" }, 369bc55e2eaSThomas Huth { "pcie.7", "pcie-root-port" }, 370bc55e2eaSThomas Huth { "pcie.8", "pcie-root-port" }, 371bc55e2eaSThomas Huth { "scsi", "virtio-scsi-pci" }, 372bc55e2eaSThomas Huth { "scsi-disk", "scsi-hd" }, 373bc55e2eaSThomas Huth { "scsi-optical-disk", "scsi-cd" }, 374bc55e2eaSThomas Huth { "net", "virtio-net-pci" }, 375bc55e2eaSThomas Huth { NULL, NULL } 376bc55e2eaSThomas Huth }; 377bc55e2eaSThomas Huth 378bc55e2eaSThomas Huth test_docs_q35("docs/config/q35-virtio-serial.cfg", devices); 379bc55e2eaSThomas Huth } 380bc55e2eaSThomas Huth 381bc55e2eaSThomas Huth #endif /* CONFIG_LINUX */ 382bc55e2eaSThomas Huth 383f6a5f380SDaniel P. Berrangé int main(int argc, char *argv[]) 384f6a5f380SDaniel P. Berrangé { 385f6a5f380SDaniel P. Berrangé const char *arch; 386f6a5f380SDaniel P. Berrangé g_test_init(&argc, &argv, NULL); 387f6a5f380SDaniel P. Berrangé 388f6a5f380SDaniel P. Berrangé arch = qtest_get_arch(); 389f6a5f380SDaniel P. Berrangé 390f6a5f380SDaniel P. Berrangé if (g_str_equal(arch, "i386") || 391f6a5f380SDaniel P. Berrangé g_str_equal(arch, "x86_64")) { 392f6a5f380SDaniel P. Berrangé qtest_add_func("readconfig/x86/memdev", test_x86_memdev); 393335da811SThomas Huth if (qtest_has_device("ich9-usb-ehci1") && 394335da811SThomas Huth qtest_has_device("ich9-usb-uhci1")) { 395201aa17eSThomas Huth qtest_add_func("readconfig/x86/ich9-ehci-uhci", test_docs_config_ich9); 396f6a5f380SDaniel P. Berrangé } 397bc55e2eaSThomas Huth #if defined(CONFIG_POSIX) && defined(CONFIG_SLIRP) 398bc55e2eaSThomas Huth qtest_add_func("readconfig/x86/q35-emulated", test_docs_q35_emulated); 399bc55e2eaSThomas Huth qtest_add_func("readconfig/x86/q35-virtio-graphical", 400bc55e2eaSThomas Huth test_docs_q35_virtio_graphical); 401bc55e2eaSThomas Huth if (g_test_slow()) { 402bc55e2eaSThomas Huth /* 403bc55e2eaSThomas Huth * q35-virtio-serial.cfg is a subset of q35-virtio-graphical.cfg, 404bc55e2eaSThomas Huth * so we can skip the test in quick mode 405bc55e2eaSThomas Huth */ 406bc55e2eaSThomas Huth qtest_add_func("readconfig/x86/q35-virtio-serial", 407bc55e2eaSThomas Huth test_docs_q35_virtio_serial); 408bc55e2eaSThomas Huth } 409bc55e2eaSThomas Huth #endif 410335da811SThomas Huth } 41101013d2cSThomas Huth #if defined(CONFIG_SPICE) && !defined(__FreeBSD__) 412f6a5f380SDaniel P. Berrangé qtest_add_func("readconfig/spice", test_spice); 413f6a5f380SDaniel P. Berrangé #endif 414f6a5f380SDaniel P. Berrangé 415f6a5f380SDaniel P. Berrangé qtest_add_func("readconfig/object-rng", test_object_rng); 416f6a5f380SDaniel P. Berrangé 417f6a5f380SDaniel P. Berrangé return g_test_run(); 418f6a5f380SDaniel P. Berrangé } 419