Test that we run 'mdevctl' with the proper arguments when creating new
mediated devices with virNodeDeviceCreateXML().
Signed-off-by: Jonathon Jongsma <jjongsma(a)redhat.com>
---
build-aux/syntax-check.mk | 2 +-
tests/Makefile.am | 14 +
...019_36ea_4111_8f0a_8c9a70e21366-start.argv | 1 +
...019_36ea_4111_8f0a_8c9a70e21366-start.json | 1 +
...d39_495e_4243_ad9f_beb3f14c23d9-start.argv | 1 +
...d39_495e_4243_ad9f_beb3f14c23d9-start.json | 1 +
...916_1ca8_49ac_b176_871d16c13076-start.argv | 1 +
...916_1ca8_49ac_b176_871d16c13076-start.json | 1 +
tests/nodedevmdevctltest.c | 262 ++++++++++++++++++
...v_d069d019_36ea_4111_8f0a_8c9a70e21366.xml | 7 +
...v_d2441d39_495e_4243_ad9f_beb3f14c23d9.xml | 9 +
...v_fedc4916_1ca8_49ac_b176_871d16c13076.xml | 8 +
12 files changed, 307 insertions(+), 1 deletion(-)
create mode 100644
tests/nodedevmdevctldata/mdev_d069d019_36ea_4111_8f0a_8c9a70e21366-start.argv
create mode 100644
tests/nodedevmdevctldata/mdev_d069d019_36ea_4111_8f0a_8c9a70e21366-start.json
create mode 100644
tests/nodedevmdevctldata/mdev_d2441d39_495e_4243_ad9f_beb3f14c23d9-start.argv
create mode 100644
tests/nodedevmdevctldata/mdev_d2441d39_495e_4243_ad9f_beb3f14c23d9-start.json
create mode 100644
tests/nodedevmdevctldata/mdev_fedc4916_1ca8_49ac_b176_871d16c13076-start.argv
create mode 100644
tests/nodedevmdevctldata/mdev_fedc4916_1ca8_49ac_b176_871d16c13076-start.json
create mode 100644 tests/nodedevmdevctltest.c
create mode 100644 tests/nodedevschemadata/mdev_d069d019_36ea_4111_8f0a_8c9a70e21366.xml
create mode 100644 tests/nodedevschemadata/mdev_d2441d39_495e_4243_ad9f_beb3f14c23d9.xml
create mode 100644 tests/nodedevschemadata/mdev_fedc4916_1ca8_49ac_b176_871d16c13076.xml
diff --git a/build-aux/syntax-check.mk b/build-aux/syntax-check.mk
index bf8832a2a5..d47a92b530 100644
--- a/build-aux/syntax-check.mk
+++ b/build-aux/syntax-check.mk
@@ -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$$)
diff --git a/tests/Makefile.am b/tests/Makefile.am
index f5766a7790..13cbdbb31e 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -388,6 +388,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 +974,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
index 0000000000..eb7262035e
--- /dev/null
+++ b/tests/nodedevmdevctldata/mdev_d069d019_36ea_4111_8f0a_8c9a70e21366-start.argv
@@ -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
index 0000000000..bfc6dcace3
--- /dev/null
+++ b/tests/nodedevmdevctldata/mdev_d069d019_36ea_4111_8f0a_8c9a70e21366-start.json
@@ -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
index 0000000000..eb7262035e
--- /dev/null
+++ b/tests/nodedevmdevctldata/mdev_d2441d39_495e_4243_ad9f_beb3f14c23d9-start.argv
@@ -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
index 0000000000..e5b22b2c44
--- /dev/null
+++ b/tests/nodedevmdevctldata/mdev_d2441d39_495e_4243_ad9f_beb3f14c23d9-start.json
@@ -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
index 0000000000..eb7262035e
--- /dev/null
+++ b/tests/nodedevmdevctldata/mdev_fedc4916_1ca8_49ac_b176_871d16c13076-start.argv
@@ -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
index 0000000000..2e03d0bd8e
--- /dev/null
+++ b/tests/nodedevmdevctldata/mdev_fedc4916_1ca8_49ac_b176_871d16c13076-start.json
@@ -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
index 0000000000..8d226e012b
--- /dev/null
+++ b/tests/nodedevmdevctltest.c
@@ -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, false, &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
index 0000000000..d6a2e99edc
--- /dev/null
+++ b/tests/nodedevschemadata/mdev_d069d019_36ea_4111_8f0a_8c9a70e21366.xml
@@ -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
index 0000000000..89568d06ce
--- /dev/null
+++ b/tests/nodedevschemadata/mdev_d2441d39_495e_4243_ad9f_beb3f14c23d9.xml
@@ -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
index 0000000000..7cd0a46e3d
--- /dev/null
+++ b/tests/nodedevschemadata/mdev_fedc4916_1ca8_49ac_b176_871d16c13076.xml
@@ -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>
--
2.21.3