qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH RFC 1/1] qtest: Add generic PCI device test


From: Markus Armbruster
Subject: [Qemu-devel] [PATCH RFC 1/1] qtest: Add generic PCI device test
Date: Thu, 29 Jan 2015 15:58:40 +0100

Covers only cold plug with -device so far.

Signed-off-by: Markus Armbruster <address@hidden>
---
 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 <address@hidden>,
+ *
+ * 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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]