From: Markus Armbruster <armbru@redhat.com>
To: qemu-devel@nongnu.org
Cc: afaerber@suse.de, mst@redhat.com
Subject: [Qemu-devel] [PATCH RFC 1/1] qtest: Add generic PCI device test
Date: Thu, 29 Jan 2015 15:58:40 +0100 [thread overview]
Message-ID: <1422543520-8604-2-git-send-email-armbru@redhat.com> (raw)
In-Reply-To: <1422543520-8604-1-git-send-email-armbru@redhat.com>
Covers only cold plug with -device so far.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
tests/Makefile | 2 +
tests/pci-devs-test.c | 299 ++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 301 insertions(+)
create mode 100644 tests/pci-devs-test.c
diff --git a/tests/Makefile b/tests/Makefile
index c2e2e52..230238d 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -100,6 +100,7 @@ gcov-files-virtio-y += i386-softmmu/hw/char/virtio-serial-bus.c
check-qtest-virtio-y += $(check-qtest-virtioserial-y)
gcov-files-virtio-y += $(gcov-files-virtioserial-y)
+check-qtest-pci-y += tests/pci-devs-test$(EXESUF)
check-qtest-pci-y += tests/e1000-test$(EXESUF)
gcov-files-pci-y += hw/net/e1000.c
check-qtest-pci-y += tests/rtl8139-test$(EXESUF)
@@ -319,6 +320,7 @@ tests/bios-tables-test$(EXESUF): tests/bios-tables-test.o $(libqos-obj-y)
tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(libqos-omap-obj-y)
tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y)
tests/fw_cfg-test$(EXESUF): tests/fw_cfg-test.o $(libqos-pc-obj-y)
+tests/pci-devs-test$(EXESUF): tests/pci-devs-test.o
tests/e1000-test$(EXESUF): tests/e1000-test.o
tests/rtl8139-test$(EXESUF): tests/rtl8139-test.o
tests/pcnet-test$(EXESUF): tests/pcnet-test.o
diff --git a/tests/pci-devs-test.c b/tests/pci-devs-test.c
new file mode 100644
index 0000000..27cbeee
--- /dev/null
+++ b/tests/pci-devs-test.c
@@ -0,0 +1,299 @@
+/*
+ * Generic PCI device test cases.
+ *
+ * Copyright (c) 2015 Red Hat Inc.
+ *
+ * Authors:
+ * Markus Armbruster <armbru@redhat.com>,
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+/*
+ * Covers only cold plug with -device so far. Better than nothing.
+ * Improvements welcome.
+ */
+
+#include "qemu-common.h"
+#include "libqtest.h"
+#include "qapi/qmp/types.h"
+
+typedef struct Prop {
+ const char *name;
+ const char *value;
+} Prop;
+
+typedef struct {
+ Prop prop[16];
+ int nprop;
+ const char *xprops;
+ int nchr;
+ int nblk;
+} TestCase;
+
+static const char *blacklist[] = {
+ /* cannot_instantiate_with_device_add_yet, no way to introspect it */
+ "Bonito",
+ "ICH9 SMB",
+ "ICH9-LPC",
+ "PIIX3",
+ "PIIX3-xen",
+ "PIIX4",
+ "PIIX4_PM",
+ "VT82C686B",
+ "dec-21154",
+ "e500-host-bridge",
+ "grackle",
+ "gt64120_pci",
+ "i440FX",
+ "mch",
+ "pbm-pci",
+ "ppc4xx-host-bridge",
+ "raven",
+ "s390-pcihost",
+ "sh_pci_host",
+ "spapr-pci-host-bridge",
+ "u3-agp",
+ "uni-north-agp",
+ "uni-north-internal-pci",
+ "uni-north-pci",
+ "versatile_pci_host",
+ /* require a suitable host device to pass through */
+ "kvm-pci-assign",
+ "vfio-pci",
+ "vhost-scsi-pci",
+ "xen-pci-passthrough",
+ /* require a backend this test can't setup (yet) */
+ "virtio-9p-pci", /* requires -fsdev ... */
+ "ivshmem", /* requires special chardev */
+ /* test fails */
+ "qxl", /* qemu crashes */
+ "xen-platform" /* qemu crashes */
+};
+
+static struct {
+ const char *name, *propstr;
+} oddball[] = {
+ { "nvme", "serial=foo" },
+ { "xen-pvdevice", "device-id=666" },
+ { "pci-bridge", "chassis_nr=13" },
+};
+
+static bool is_blacklisted(const char *typename)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(blacklist); i++) {
+ if (!strcmp(blacklist[i], typename)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static void add_xprops(TestCase *tcase, const char *typename)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(oddball); i++) {
+ if (!strcmp(oddball[i].name, typename)) {
+ tcase->xprops = oddball[i].propstr;
+ break;
+ }
+ }
+}
+
+static void add_prop(TestCase *tcase, const char *name, const char *value)
+{
+ g_assert(tcase->nprop < ARRAY_SIZE(tcase->prop));
+ tcase->prop[tcase->nprop].name = g_strdup(name);
+ tcase->prop[tcase->nprop].value = g_strdup(value);
+ tcase->nprop++;
+}
+
+static char *fmt_props(const Prop prop[], int nprop, const char *xprops)
+{
+ char **strv = g_new(char *, nprop + 2);
+ int i;
+ char *props;
+
+ for (i = 0; i < nprop; i++) {
+ strv[i] = g_strdup_printf("%s=%s", prop[i].name, prop[i].value);
+ }
+ strv[nprop] = (char *)xprops;
+ strv[nprop + 1] = NULL;
+
+ props = g_strjoinv(",", strv);
+
+ for (i = 0; i < nprop; i++) {
+ g_free(strv[i]);
+ }
+
+ return props;
+}
+
+static char *fmt_blkid(char *buf, size_t sz, int index)
+{
+ size_t len = snprintf(buf, sz, "blk%d", index);
+ g_assert(len < sz);
+ return buf;
+}
+
+static char *fmt_blockdevs(int nblk)
+{
+ char **strv = g_new(char *, nblk + 1);
+ int i;
+ char buf[64];
+ char *blks;
+
+ for (i = 0; i < nblk; i++) {
+ strv[i] = g_strdup_printf("-drive if=none,id=%s,format=raw,file=/dev/null",
+ fmt_blkid(buf, sizeof(buf), i));
+ }
+ strv[nblk] = NULL;
+
+ blks = g_strjoinv(" ", strv);
+
+ for (i = 0; i < nblk; i++) {
+ g_free(strv[i]);
+ }
+
+ return blks;
+}
+
+static char *fmt_chrid(char *buf, size_t sz, int index)
+{
+ size_t len = snprintf(buf, sz, "chr%d", index);
+ g_assert(len < sz);
+ return buf;
+}
+
+static char *fmt_chardevs(int nchr)
+{
+ char **strv = g_new(char *, nchr + 1);
+ int i;
+ char buf[64];
+ char *chrs;
+
+ for (i = 0; i < nchr; i++) {
+ strv[i] = g_strdup_printf("-chardev null,id=%s",
+ fmt_chrid(buf, sizeof(buf), i));
+ }
+ strv[nchr] = NULL;
+
+ chrs = g_strjoinv(" ", strv);
+
+ for (i = 0; i < nchr; i++) {
+ g_free(strv[i]);
+ }
+
+ return chrs;
+}
+
+static void test_device(gconstpointer data)
+{
+ const TestCase *tcase = data;
+ char *blks = fmt_blockdevs(tcase->nblk);
+ char *chrs = fmt_chardevs(tcase->nchr);
+ char *props = fmt_props(tcase->prop, tcase->nprop, tcase->xprops);
+ char *args;
+ QDict *response;
+
+ args = g_strconcat(blks, chrs, " -device '", props, "'", NULL);
+ g_free(props);
+ qtest_start(args);
+ response = qmp("{ 'execute': 'quit' }");
+ g_assert(qdict_haskey(response, "return"));
+ qtest_end();
+ g_free(args);
+}
+
+static void add_backends(TestCase *tcase, const char *typename)
+{
+ QDict *response, *dpinfo;
+ QList *list;
+ const QListEntry *p;
+ QObject *qobj;
+ QString *qstr;
+ const char *name;
+ char buf[64];
+
+ response = qmp("{ 'execute': 'device-list-properties', "
+ "'arguments': { 'typename': %s } }", typename);
+ g_assert(response);
+ list = qdict_get_qlist(response, "return");
+ g_assert(list);
+
+ for (p = qlist_first(list); p; p = qlist_next(p)) {
+ dpinfo = qobject_to_qdict(qlist_entry_obj(p));
+ g_assert(dpinfo);
+ qobj = qdict_get(dpinfo, "name");
+ g_assert(qobj);
+ qstr = qobject_to_qstring(qobj);
+ g_assert(qstr);
+ name = qstring_get_str(qstr);
+
+ if (strstart(name, "chardev", NULL)) {
+ add_prop(tcase, name,
+ fmt_chrid(buf, sizeof(buf), tcase->nchr++));
+ } else if (strstart(name, "drive", NULL)) {
+ add_prop(tcase, name,
+ fmt_blkid(buf, sizeof(buf), tcase->nblk++));
+ }
+ }
+
+ QDECREF(response);
+}
+
+static void add_device_test_cases(void)
+{
+ QDict *response, *otinfo;
+ QList *list;
+ const QListEntry *p;
+ QObject *qobj;
+ QString *qstr;
+ const char *name, *path;
+ TestCase *tcase;
+
+ qtest_start("-machine none");
+ response = qmp("{ 'execute': 'qom-list-types', "
+ "'arguments': { 'implements': 'pci-device' } }");
+ g_assert(response);
+ list = qdict_get_qlist(response, "return");
+ g_assert(list);
+
+ for (p = qlist_first(list); p; p = qlist_next(p)) {
+ otinfo = qobject_to_qdict(qlist_entry_obj(p));
+ g_assert(otinfo);
+ qobj = qdict_get(otinfo, "name");
+ g_assert(qobj);
+ qstr = qobject_to_qstring(qobj);
+ g_assert(qstr);
+ name = qstring_get_str(qstr);
+
+ if (is_blacklisted(name)) {
+ continue;
+ }
+
+ tcase = g_new0(TestCase, 1);
+ add_prop(tcase, "driver", name);
+ add_backends(tcase, name);
+ add_xprops(tcase, name);
+
+ path = g_strdup_printf("/pci-devs/%s", name);
+ g_test_add_data_func(path, tcase, test_device);
+ }
+
+ QDECREF(response);
+ qtest_end();
+}
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+
+ add_device_test_cases();
+
+ return g_test_run();
+}
--
1.9.3
next prev parent reply other threads:[~2015-01-29 14:58 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-01-29 14:58 [Qemu-devel] [PATCH RFC 0/1] qtest: Generic PCI device test Markus Armbruster
2015-01-29 14:58 ` Markus Armbruster [this message]
2015-01-29 17:13 ` Andreas Färber
2015-02-12 14:45 ` Markus Armbruster
2015-01-29 19:46 ` John Snow
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1422543520-8604-2-git-send-email-armbru@redhat.com \
--to=armbru@redhat.com \
--cc=afaerber@suse.de \
--cc=mst@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).