]> xenbits.xensource.com Git - libvirt.git/commitdiff
nodedev: Add testing for 'mdevctl start'
authorJonathon Jongsma <jjongsma@redhat.com>
Thu, 18 Jun 2020 21:06:01 +0000 (16:06 -0500)
committerErik Skultety <eskultet@redhat.com>
Fri, 19 Jun 2020 08:39:55 +0000 (10:39 +0200)
Test that we run 'mdevctl' with the proper arguments when creating new
mediated devices with virNodeDeviceCreateXML().

Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com>
Reviewed-by: Erik Skultety <eskultet@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
12 files changed:
build-aux/syntax-check.mk
tests/Makefile.am
tests/nodedevmdevctldata/mdev_d069d019_36ea_4111_8f0a_8c9a70e21366-start.argv [new file with mode: 0644]
tests/nodedevmdevctldata/mdev_d069d019_36ea_4111_8f0a_8c9a70e21366-start.json [new file with mode: 0644]
tests/nodedevmdevctldata/mdev_d2441d39_495e_4243_ad9f_beb3f14c23d9-start.argv [new file with mode: 0644]
tests/nodedevmdevctldata/mdev_d2441d39_495e_4243_ad9f_beb3f14c23d9-start.json [new file with mode: 0644]
tests/nodedevmdevctldata/mdev_fedc4916_1ca8_49ac_b176_871d16c13076-start.argv [new file with mode: 0644]
tests/nodedevmdevctldata/mdev_fedc4916_1ca8_49ac_b176_871d16c13076-start.json [new file with mode: 0644]
tests/nodedevmdevctltest.c [new file with mode: 0644]
tests/nodedevschemadata/mdev_d069d019_36ea_4111_8f0a_8c9a70e21366.xml [new file with mode: 0644]
tests/nodedevschemadata/mdev_d2441d39_495e_4243_ad9f_beb3f14c23d9.xml [new file with mode: 0644]
tests/nodedevschemadata/mdev_fedc4916_1ca8_49ac_b176_871d16c13076.xml [new file with mode: 0644]

index bf8832a2a5ce26054e654f848b6f2c1d0e86c3d8..d47a92b530f5be854b7fe836208d08ca440547c0 100644 (file)
@@ -2015,7 +2015,7 @@ exclude_file_name_regexp--sc_prohibit_close = \
   (\.p[yl]$$|\.spec\.in$$|^docs/|^(src/util/vir(file|event)\.c|src/libvirt-stream\.c|tests/(vir.+mock\.c|commandhelper\.c|qemusecuritymock\.c)|tools/nss/libvirt_nss_(leases|macs)\.c)$$)
 
 exclude_file_name_regexp--sc_prohibit_empty_lines_at_EOF = \
-  (^tests/(virhostcpu|virpcitest)data/|docs/js/.*\.js|docs/fonts/.*\.woff|\.diff|tests/virconfdata/no-newline\.conf$$)
+  (^tests/(nodedevmdevctl|virhostcpu|virpcitest)data/|docs/js/.*\.js|docs/fonts/.*\.woff|\.diff|tests/virconfdata/no-newline\.conf$$)
 
 exclude_file_name_regexp--sc_prohibit_fork_wrappers = \
   (^(src/(util/(vircommand|virdaemon)|lxc/lxc_controller)|tests/testutils)\.c$$)
index f5766a77904b99f5ceae95dcd98f29d4d79286bb..3505c40f42aac4e585627484a1964903345ed9e1 100644 (file)
@@ -103,6 +103,7 @@ EXTRA_DIST = \
        networkxml2xmlupdatein \
        networkxml2xmlupdateout \
        nodedevschemadata \
+       nodedevmdevctldata \
        virhostcpudata \
        nssdata \
        nwfilterxml2firewalldata \
@@ -388,6 +389,10 @@ test_programs += storagevolxml2xmltest
 
 test_programs += nodedevxml2xmltest
 
+if WITH_NODE_DEVICES
+test_programs += nodedevmdevctltest
+endif WITH_NODE_DEVICES
+
 test_programs += interfacexml2xmltest
 
 test_programs += cputest
@@ -970,6 +975,16 @@ nodedevxml2xmltest_SOURCES = \
        testutils.c testutils.h
 nodedevxml2xmltest_LDADD = $(LDADDS)
 
+if WITH_NODE_DEVICES
+nodedevmdevctltest_SOURCES = \
+       nodedevmdevctltest.c \
+       testutils.c testutils.h
+
+nodedevmdevctltest_LDADD = \
+       ../src/libvirt_driver_nodedev_impl.la \
+       $(LDADDS)
+endif WITH_NODE_DEVICES
+
 interfacexml2xmltest_SOURCES = \
        interfacexml2xmltest.c \
        testutils.c testutils.h
diff --git a/tests/nodedevmdevctldata/mdev_d069d019_36ea_4111_8f0a_8c9a70e21366-start.argv b/tests/nodedevmdevctldata/mdev_d069d019_36ea_4111_8f0a_8c9a70e21366-start.argv
new file mode 100644 (file)
index 0000000..eb72620
--- /dev/null
@@ -0,0 +1 @@
+$MDEVCTL_BINARY$ start -p 0000:00:02.0 --jsonfile /dev/stdin
diff --git a/tests/nodedevmdevctldata/mdev_d069d019_36ea_4111_8f0a_8c9a70e21366-start.json b/tests/nodedevmdevctldata/mdev_d069d019_36ea_4111_8f0a_8c9a70e21366-start.json
new file mode 100644 (file)
index 0000000..bfc6dca
--- /dev/null
@@ -0,0 +1 @@
+{"mdev_type":"i915-GVTg_V5_8","start":"manual"}
\ No newline at end of file
diff --git a/tests/nodedevmdevctldata/mdev_d2441d39_495e_4243_ad9f_beb3f14c23d9-start.argv b/tests/nodedevmdevctldata/mdev_d2441d39_495e_4243_ad9f_beb3f14c23d9-start.argv
new file mode 100644 (file)
index 0000000..eb72620
--- /dev/null
@@ -0,0 +1 @@
+$MDEVCTL_BINARY$ start -p 0000:00:02.0 --jsonfile /dev/stdin
diff --git a/tests/nodedevmdevctldata/mdev_d2441d39_495e_4243_ad9f_beb3f14c23d9-start.json b/tests/nodedevmdevctldata/mdev_d2441d39_495e_4243_ad9f_beb3f14c23d9-start.json
new file mode 100644 (file)
index 0000000..e5b22b2
--- /dev/null
@@ -0,0 +1 @@
+{"mdev_type":"i915-GVTg_V5_8","start":"manual","attrs":[{"example-attribute-1":"attribute-value-1"},{"example-attribute-2":"attribute-value-2"}]}
\ No newline at end of file
diff --git a/tests/nodedevmdevctldata/mdev_fedc4916_1ca8_49ac_b176_871d16c13076-start.argv b/tests/nodedevmdevctldata/mdev_fedc4916_1ca8_49ac_b176_871d16c13076-start.argv
new file mode 100644 (file)
index 0000000..eb72620
--- /dev/null
@@ -0,0 +1 @@
+$MDEVCTL_BINARY$ start -p 0000:00:02.0 --jsonfile /dev/stdin
diff --git a/tests/nodedevmdevctldata/mdev_fedc4916_1ca8_49ac_b176_871d16c13076-start.json b/tests/nodedevmdevctldata/mdev_fedc4916_1ca8_49ac_b176_871d16c13076-start.json
new file mode 100644 (file)
index 0000000..2e03d0b
--- /dev/null
@@ -0,0 +1 @@
+{"mdev_type":"i915-GVTg_V5_8","start":"manual","attrs":[{"example-attribute":"attribute-value"}]}
\ No newline at end of file
diff --git a/tests/nodedevmdevctltest.c b/tests/nodedevmdevctltest.c
new file mode 100644 (file)
index 0000000..4b029c7
--- /dev/null
@@ -0,0 +1,262 @@
+#include <config.h>
+
+#include "internal.h"
+#include "testutils.h"
+#include "datatypes.h"
+#include "node_device/node_device_driver.h"
+#include "vircommand.h"
+#define LIBVIRT_VIRCOMMANDPRIV_H_ALLOW
+#include "vircommandpriv.h"
+
+#define VIR_FROM_THIS VIR_FROM_NODEDEV
+
+struct startTestInfo {
+    const char *virt_type;
+    int create;
+    const char *filename;
+};
+
+/* capture stdin passed to command */
+static void
+testCommandDryRunCallback(const char *const*args G_GNUC_UNUSED,
+                          const char *const*env G_GNUC_UNUSED,
+                          const char *input,
+                          char **output G_GNUC_UNUSED,
+                          char **error G_GNUC_UNUSED,
+                          int *status G_GNUC_UNUSED,
+                          void *opaque G_GNUC_UNUSED)
+{
+    char **stdinbuf = opaque;
+
+    *stdinbuf = g_strdup(input);
+}
+
+/* We don't want the result of the test to depend on the path to the mdevctl
+ * binary on the developer's machine, so replace the path to mdevctl with a
+ * placeholder string before comparing to the expected output */
+static int
+nodedevCompareToFile(const char *actual,
+                     const char *filename)
+{
+    g_autofree char *replacedCmdline = NULL;
+
+    replacedCmdline = virStringReplace(actual, MDEVCTL, "$MDEVCTL_BINARY$");
+
+    return virTestCompareToFile(replacedCmdline, filename);
+}
+
+static int
+testMdevctlStart(const char *virt_type,
+                 int create,
+                 const char *mdevxml,
+                 const char *startcmdfile,
+                 const char *startjsonfile)
+{
+    g_autoptr(virNodeDeviceDef) def = NULL;
+    virNodeDeviceObjPtr obj = NULL;
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    const char *actualCmdline = NULL;
+    int ret = -1;
+    g_autofree char *uuid = NULL;
+    g_autofree char *stdinbuf = NULL;
+    g_autoptr(virCommand) cmd = NULL;
+
+    if (!(def = virNodeDeviceDefParseFile(mdevxml, create, virt_type)))
+        goto cleanup;
+
+    /* this function will set a stdin buffer containing the json configuration
+     * of the device. The json value is captured in the callback above */
+    cmd = nodeDeviceGetMdevctlStartCommand(def, &uuid);
+
+    if (!cmd)
+        goto cleanup;
+
+    virCommandSetDryRun(&buf, testCommandDryRunCallback, &stdinbuf);
+    if (virCommandRun(cmd, NULL) < 0)
+        goto cleanup;
+
+    if (!(actualCmdline = virBufferCurrentContent(&buf)))
+        goto cleanup;
+
+    if (nodedevCompareToFile(actualCmdline, startcmdfile) < 0)
+        goto cleanup;
+
+    if (virTestCompareToFile(stdinbuf, startjsonfile) < 0)
+        goto cleanup;
+
+    ret = 0;
+
+ cleanup:
+    virBufferFreeAndReset(&buf);
+    virCommandSetDryRun(NULL, NULL, NULL);
+    virNodeDeviceObjEndAPI(&obj);
+    return ret;
+}
+
+static int
+testMdevctlStartHelper(const void *data)
+{
+    const struct startTestInfo *info = data;
+
+    g_autofree char *mdevxml = g_strdup_printf("%s/nodedevschemadata/%s.xml",
+                                               abs_srcdir, info->filename);
+    g_autofree char *cmdlinefile = g_strdup_printf("%s/nodedevmdevctldata/%s-start.argv",
+                                                   abs_srcdir, info->filename);
+    g_autofree char *jsonfile = g_strdup_printf("%s/nodedevmdevctldata/%s-start.json",
+                                                   abs_srcdir, info->filename);
+
+    return testMdevctlStart(info->virt_type,
+                            info->create, mdevxml, cmdlinefile,
+                            jsonfile);
+}
+
+static void
+nodedevTestDriverFree(virNodeDeviceDriverStatePtr drv)
+{
+    if (!drv)
+        return;
+
+    virNodeDeviceObjListFree(drv->devs);
+    virCondDestroy(&drv->initCond);
+    virMutexDestroy(&drv->lock);
+    VIR_FREE(drv->stateDir);
+    VIR_FREE(drv);
+}
+
+/* Add a fake root 'computer' device */
+static virNodeDeviceDefPtr
+fakeRootDevice(void)
+{
+    virNodeDeviceDefPtr def = NULL;
+
+    if (VIR_ALLOC(def) != 0 || VIR_ALLOC(def->caps) != 0) {
+        virNodeDeviceDefFree(def);
+        return NULL;
+    }
+
+    def->name = g_strdup("computer");
+
+    return def;
+}
+
+/* Add a fake pci device that can be used as a parent device for mediated
+ * devices. For our purposes, it only needs to have a name that matches the
+ * parent of the mdev, and it needs a PCI address
+ */
+static virNodeDeviceDefPtr
+fakeParentDevice(void)
+{
+    virNodeDeviceDefPtr def = NULL;
+    virNodeDevCapPCIDevPtr pci_dev;
+
+    if (VIR_ALLOC(def) != 0 || VIR_ALLOC(def->caps) != 0) {
+        virNodeDeviceDefFree(def);
+        return NULL;
+    }
+
+    def->name = g_strdup("pci_0000_00_02_0");
+    def->parent = g_strdup("computer");
+
+    def->caps->data.type = VIR_NODE_DEV_CAP_PCI_DEV;
+    pci_dev = &def->caps->data.pci_dev;
+    pci_dev->domain = 0;
+    pci_dev->bus = 0;
+    pci_dev->slot = 2;
+    pci_dev->function = 0;
+
+    return def;
+}
+
+static int
+addDevice(virNodeDeviceDefPtr def)
+{
+    if (!def)
+        return -1;
+
+    virNodeDeviceObjPtr obj = virNodeDeviceObjListAssignDef(driver->devs, def);
+
+    if (!obj) {
+        virNodeDeviceDefFree(def);
+        return -1;
+    }
+
+    virNodeDeviceObjEndAPI(&obj);
+    return 0;
+}
+
+static int
+nodedevTestDriverAddTestDevices(void)
+{
+    if (addDevice(fakeRootDevice()) < 0 ||
+        addDevice(fakeParentDevice()) < 0)
+        return -1;
+
+    return 0;
+}
+
+/* Bare minimum driver init to be able to test nodedev functionality */
+static int
+nodedevTestDriverInit(void)
+{
+    int ret = -1;
+    if (VIR_ALLOC(driver) < 0)
+        return -1;
+
+    driver->lockFD = -1;
+    if (virMutexInit(&driver->lock) < 0 ||
+        virCondInit(&driver->initCond) < 0) {
+        VIR_TEST_DEBUG("Unable to initialize test nodedev driver");
+        goto error;
+    }
+
+    if (!(driver->devs = virNodeDeviceObjListNew()))
+        goto error;
+
+    return 0;
+
+ error:
+    nodedevTestDriverFree(driver);
+    return ret;
+}
+
+static int
+mymain(void)
+{
+    int ret = 0;
+
+    if (nodedevTestDriverInit() < 0)
+        return EXIT_FAILURE;
+
+    /* add a mock device to the device list so it can be used as a parent
+     * reference */
+    if (nodedevTestDriverAddTestDevices() < 0) {
+        ret = EXIT_FAILURE;
+        goto done;
+    }
+
+#define DO_TEST_FULL(desc, func, info) \
+    if (virTestRun(desc, func, &info) < 0) \
+        ret = -1;
+
+#define DO_TEST_START_FULL(virt_type, create, filename) \
+    do { \
+        struct startTestInfo info = { virt_type, create, filename }; \
+        DO_TEST_FULL("mdevctl start " filename, testMdevctlStartHelper, info); \
+       } \
+    while (0);
+
+#define DO_TEST_START(filename) \
+    DO_TEST_START_FULL("QEMU", CREATE_DEVICE, filename)
+
+    /* Test mdevctl start commands */
+    DO_TEST_START("mdev_d069d019_36ea_4111_8f0a_8c9a70e21366");
+    DO_TEST_START("mdev_fedc4916_1ca8_49ac_b176_871d16c13076");
+    DO_TEST_START("mdev_d2441d39_495e_4243_ad9f_beb3f14c23d9");
+
+ done:
+    nodedevTestDriverFree(driver);
+
+    return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
+VIR_TEST_MAIN(mymain)
diff --git a/tests/nodedevschemadata/mdev_d069d019_36ea_4111_8f0a_8c9a70e21366.xml b/tests/nodedevschemadata/mdev_d069d019_36ea_4111_8f0a_8c9a70e21366.xml
new file mode 100644 (file)
index 0000000..d6a2e99
--- /dev/null
@@ -0,0 +1,7 @@
+<device>
+  <name>mdev_d069d019_36ea_4111_8f0a_8c9a70e21366</name>
+  <parent>pci_0000_00_02_0</parent>
+  <capability type='mdev'>
+    <type id='i915-GVTg_V5_8'/>
+  </capability>
+</device>
diff --git a/tests/nodedevschemadata/mdev_d2441d39_495e_4243_ad9f_beb3f14c23d9.xml b/tests/nodedevschemadata/mdev_d2441d39_495e_4243_ad9f_beb3f14c23d9.xml
new file mode 100644 (file)
index 0000000..89568d0
--- /dev/null
@@ -0,0 +1,9 @@
+<device>
+  <name>mdev_d2441d39_495e_4243_ad9f_beb3f14c23d9</name>
+  <parent>pci_0000_00_02_0</parent>
+  <capability type='mdev'>
+    <type id='i915-GVTg_V5_8'/>
+    <attr name='example-attribute-1' value='attribute-value-1'/>
+    <attr name='example-attribute-2' value='attribute-value-2'/>
+  </capability>
+</device>
diff --git a/tests/nodedevschemadata/mdev_fedc4916_1ca8_49ac_b176_871d16c13076.xml b/tests/nodedevschemadata/mdev_fedc4916_1ca8_49ac_b176_871d16c13076.xml
new file mode 100644 (file)
index 0000000..7cd0a46
--- /dev/null
@@ -0,0 +1,8 @@
+<device>
+  <name>mdev_fedc4916_1ca8_49ac_b176_871d16c13076</name>
+  <parent>pci_0000_00_02_0</parent>
+  <capability type='mdev'>
+    <type id='i915-GVTg_V5_8'/>
+    <attr name='example-attribute' value='attribute-value'/>
+  </capability>
+</device>