[PATCH 0/5] qemuhotplug: Introduce interface-network-hostdev
*** BLURB HERE *** Michal Prívozník (5): tests: Drop WITH_QEMU from qemu specific tests binaries/libraries qemuxmlconftest: Separate fake drivers into a separate file virnetworkportxml2xmldata: Use different PCI address in plug-hostdev-pci.xml qemuhotplugtest: Use fake drivers qemuhotplug: Introduce interface-network-hostdev tests/meson.build | 5 +- tests/qemudomaincheckpointxml2xmltest.c | 31 +- tests/qemudomainsnapshotxml2xmltest.c | 29 +- tests/qemufakedrivers.c | 368 +++++++++++++++ tests/qemufakedrivers.h | 19 + tests/qemuhotplugtest.c | 20 + .../qemuhotplug-interface-network-hostdev.xml | 4 + ...ug-base-live+interface-network-hostdev.xml | 63 +++ tests/qemumemlocktest.c | 25 +- ...-virtio-teaming-network.x86_64-latest.args | 2 +- tests/qemuxmlconftest.c | 443 +++--------------- tests/testutilsqemu.c | 43 +- tests/testutilsqemu.h | 23 +- .../plug-hostdev-pci.xml | 2 +- 14 files changed, 588 insertions(+), 489 deletions(-) create mode 100644 tests/qemufakedrivers.c create mode 100644 tests/qemufakedrivers.h create mode 100644 tests/qemuhotplugtestdevices/qemuhotplug-interface-network-hostdev.xml create mode 100644 tests/qemuhotplugtestdomains/qemuhotplug-base-live+interface-network-hostdev.xml -- 2.52.0
From: Michal Privoznik <mprivozn@redhat.com> Inside of tests/meson.build there is a section that builds QEMU related tests conditionally (for instance qemudomaincheckpointxml2xmltest). It makes no sense to have the same check inside source file. Or even provide alternative implementation for cases when building without QEMU (EXIT_AM_SKIP). When building without QEMU driver the test is not even compiled, so EXIT_AM_SKIP is dead code. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- tests/qemudomaincheckpointxml2xmltest.c | 31 ++----- tests/qemudomainsnapshotxml2xmltest.c | 29 ++---- tests/qemumemlocktest.c | 25 ++---- tests/qemuxmlconftest.c | 114 +++++++++++------------- tests/testutilsqemu.c | 43 +++++---- tests/testutilsqemu.h | 23 +++-- 6 files changed, 104 insertions(+), 161 deletions(-) diff --git a/tests/qemudomaincheckpointxml2xmltest.c b/tests/qemudomaincheckpointxml2xmltest.c index 0e195dae8d..e6d9bf1a4f 100644 --- a/tests/qemudomaincheckpointxml2xmltest.c +++ b/tests/qemudomaincheckpointxml2xmltest.c @@ -9,15 +9,12 @@ #include <fcntl.h> #include "testutils.h" +#include "internal.h" +#include "qemu/qemu_conf.h" +#include "checkpoint_conf.h" +#include "testutilsqemu.h" -#ifdef WITH_QEMU - -# include "internal.h" -# include "qemu/qemu_conf.h" -# include "checkpoint_conf.h" -# include "testutilsqemu.h" - -# define VIR_FROM_THIS VIR_FROM_NONE +#define VIR_FROM_THIS VIR_FROM_NONE static virQEMUDriver driver; @@ -145,7 +142,7 @@ mymain(void) virDomainXMLOptionSetMomentPostParse(driver.xmlopt, testCheckpointPostParse); -# define DO_TEST(prefix, name, inpath, outpath, time, flags) \ +#define DO_TEST(prefix, name, inpath, outpath, time, flags) \ do { \ const struct testInfo info = {abs_srcdir "/" inpath "/" name ".xml", \ abs_srcdir "/" outpath "/" name ".xml", \ @@ -155,17 +152,17 @@ mymain(void) ret = -1; \ } while (0) -# define DO_TEST_INOUT(name, time, flags) \ +#define DO_TEST_INOUT(name, time, flags) \ DO_TEST("in->out", name, \ "qemudomaincheckpointxml2xmlin", \ "qemudomaincheckpointxml2xmlout", \ time, flags) -# define DO_TEST_OUT(name, flags) \ +#define DO_TEST_OUT(name, flags) \ DO_TEST("out->out", name, \ "qemudomaincheckpointxml2xmlout", \ "qemudomaincheckpointxml2xmlout", \ 0, flags | TEST_REDEFINE) -# define DO_TEST_INVALID(name) \ +#define DO_TEST_INVALID(name) \ DO_TEST("in->out", name, \ "qemudomaincheckpointxml2xmlin", \ "qemudomaincheckpointxml2xmlout", \ @@ -196,13 +193,3 @@ mymain(void) } VIR_TEST_MAIN(mymain) - -#else - -int -main(void) -{ - return EXIT_AM_SKIP; -} - -#endif /* WITH_QEMU */ diff --git a/tests/qemudomainsnapshotxml2xmltest.c b/tests/qemudomainsnapshotxml2xmltest.c index 035c275b14..9b9168ac21 100644 --- a/tests/qemudomainsnapshotxml2xmltest.c +++ b/tests/qemudomainsnapshotxml2xmltest.c @@ -6,14 +6,11 @@ #include <fcntl.h> #include "testutils.h" +#include "internal.h" +#include "qemu/qemu_conf.h" +#include "testutilsqemu.h" -#ifdef WITH_QEMU - -# include "internal.h" -# include "qemu/qemu_conf.h" -# include "testutilsqemu.h" - -# define VIR_FROM_THIS VIR_FROM_NONE +#define VIR_FROM_THIS VIR_FROM_NONE static virQEMUDriver driver; @@ -123,7 +120,7 @@ mymain(void) virDomainXMLOptionSetMomentPostParse(driver.xmlopt, testSnapshotPostParse); -# define DO_TEST(prefix, name, inpath, outpath, uuid, time, flags) \ +#define DO_TEST(prefix, name, inpath, outpath, uuid, time, flags) \ do { \ const struct testInfo info = {abs_srcdir "/" inpath "/" name ".xml", \ abs_srcdir "/" outpath "/" name ".xml", \ @@ -133,16 +130,16 @@ mymain(void) ret = -1; \ } while (0) -# define DO_TEST_IN(name, uuid) DO_TEST("in->in", name, \ +#define DO_TEST_IN(name, uuid) DO_TEST("in->in", name, \ "qemudomainsnapshotxml2xmlin", \ "qemudomainsnapshotxml2xmlin", \ uuid, 0, 0) -# define DO_TEST_OUT(name, uuid, internal) \ +#define DO_TEST_OUT(name, uuid, internal) \ DO_TEST("out->out", name, "qemudomainsnapshotxml2xmlout", \ "qemudomainsnapshotxml2xmlout", uuid, 0, internal | TEST_REDEFINE) -# define DO_TEST_INOUT(name, uuid, time, flags) \ +#define DO_TEST_INOUT(name, uuid, time, flags) \ DO_TEST("in->out", name, \ "qemudomainsnapshotxml2xmlin",\ "qemudomainsnapshotxml2xmlout",\ @@ -190,13 +187,3 @@ mymain(void) } VIR_TEST_MAIN(mymain) - -#else - -int -main(void) -{ - return EXIT_AM_SKIP; -} - -#endif /* WITH_QEMU */ diff --git a/tests/qemumemlocktest.c b/tests/qemumemlocktest.c index a2888732f7..0f22594ad4 100644 --- a/tests/qemumemlocktest.c +++ b/tests/qemumemlocktest.c @@ -6,16 +6,13 @@ #include <fcntl.h> #include "testutils.h" +#include "internal.h" +#include "conf/domain_conf.h" +#include "qemu/qemu_domain.h" -#ifdef WITH_QEMU +#include "testutilsqemu.h" -# include "internal.h" -# include "conf/domain_conf.h" -# include "qemu/qemu_domain.h" - -# include "testutilsqemu.h" - -# define VIR_FROM_THIS VIR_FROM_QEMU +#define VIR_FROM_THIS VIR_FROM_QEMU static virQEMUDriver driver; @@ -52,7 +49,7 @@ mymain(void) if (qemuTestDriverInit(&driver) < 0) return EXIT_FAILURE; -# define DO_TEST(name, memlock) \ +#define DO_TEST(name, memlock) \ do { \ static struct testInfo info = { \ name, memlock \ @@ -127,13 +124,3 @@ mymain(void) VIR_TEST_MAIN_PRELOAD(mymain, VIR_TEST_MOCK("virpci"), VIR_TEST_MOCK("domaincaps")) - -#else - -int -main(void) -{ - return EXIT_AM_SKIP; -} - -#endif /* WITH_QEMU */ diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c index 187f90c9dc..cf147e70d4 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -6,33 +6,30 @@ #include <fcntl.h> #include "testutils.h" +#include "internal.h" +#include "viralloc.h" +#include "viridentity.h" +#include "qemu/qemu_block.h" +#include "qemu/qemu_capabilities.h" +#include "qemu/qemu_domain.h" +#include "qemu/qemu_migration.h" +#include "qemu/qemu_passt.h" +#include "qemu/qemu_process.h" +#include "qemu/qemu_slirp.h" +#include "qemu/qemu_virtiofs.h" +#include "qemu/qemu_vhost_user.h" +#include "datatypes.h" +#include "conf/storage_conf.h" +#include "virfilewrapper.h" +#include "configmake.h" +#include "testutilsqemuschema.h" -#ifdef WITH_QEMU +#define LIBVIRT_QEMU_CAPSPRIV_H_ALLOW +#include "qemu/qemu_capspriv.h" -# include "internal.h" -# include "viralloc.h" -# include "viridentity.h" -# include "qemu/qemu_block.h" -# include "qemu/qemu_capabilities.h" -# include "qemu/qemu_domain.h" -# include "qemu/qemu_migration.h" -# include "qemu/qemu_passt.h" -# include "qemu/qemu_process.h" -# include "qemu/qemu_slirp.h" -# include "qemu/qemu_virtiofs.h" -# include "qemu/qemu_vhost_user.h" -# include "datatypes.h" -# include "conf/storage_conf.h" -# include "virfilewrapper.h" -# include "configmake.h" -# include "testutilsqemuschema.h" +#include "testutilsqemu.h" -# define LIBVIRT_QEMU_CAPSPRIV_H_ALLOW -# include "qemu/qemu_capspriv.h" - -# include "testutilsqemu.h" - -# define VIR_FROM_THIS VIR_FROM_QEMU +#define VIR_FROM_THIS VIR_FROM_QEMU static virQEMUDriver driver; @@ -95,7 +92,7 @@ static virSecretDriver fakeSecretDriver = { }; -# define STORAGE_POOL_XML_PATH "storagepoolxml2xmlout/" +#define STORAGE_POOL_XML_PATH "storagepoolxml2xmlout/" static const unsigned char fakeUUID[VIR_UUID_BUFLEN] = "fakeuuid"; static virStoragePoolPtr @@ -743,7 +740,7 @@ testQemuConfXMLCommon(testQemuInfo *info, if (testInfoCheckDuplicate(info) < 0) goto cleanup; -# if !WITH_NBDKIT +#if !WITH_NBDKIT /* when compiled without nbdkit support we want to skip the test after * marking it as used */ if (info->args.fakeNbdkitCaps) { @@ -751,7 +748,7 @@ testQemuConfXMLCommon(testQemuInfo *info, info->prepared = true; goto cleanup; } -# endif /* !WITH_NBDKIT */ +#endif /* !WITH_NBDKIT */ if (info->arch != VIR_ARCH_NONE && info->arch != VIR_ARCH_X86_64) qemuTestSetHostArch(&driver, info->arch); @@ -1302,64 +1299,64 @@ mymain(void) * the test cases should be forked using DO_TEST_CAPS_VER with the appropriate * version. */ -# define DO_TEST_FULL(_name, _suffix, ...) \ +#define DO_TEST_FULL(_name, _suffix, ...) \ testRun(_name, _suffix, &ret, &testConf, __VA_ARGS__); -# define DO_TEST_CAPS_INTERNAL(name, arch, ver, ...) \ +#define DO_TEST_CAPS_INTERNAL(name, arch, ver, ...) \ DO_TEST_FULL(name, "." arch "-" ver, \ ARG_CAPS_ARCH, arch, \ ARG_CAPS_VER, ver, \ __VA_ARGS__, \ ARG_END) -# define DO_TEST_CAPS_ARCH_LATEST_FULL(name, arch, ...) \ +#define DO_TEST_CAPS_ARCH_LATEST_FULL(name, arch, ...) \ DO_TEST_CAPS_INTERNAL(name, arch, "latest", __VA_ARGS__) -# define DO_TEST_CAPS_ARCH_VER_FULL(name, arch, ver, ...) \ +#define DO_TEST_CAPS_ARCH_VER_FULL(name, arch, ver, ...) \ DO_TEST_CAPS_INTERNAL(name, arch, ver, __VA_ARGS__) -# define DO_TEST_CAPS_ARCH_LATEST(name, arch) \ +#define DO_TEST_CAPS_ARCH_LATEST(name, arch) \ DO_TEST_CAPS_ARCH_LATEST_FULL(name, arch, ARG_END) -# define DO_TEST_CAPS_ARCH_LATEST_ABI_UPDATE(name, arch) \ +#define DO_TEST_CAPS_ARCH_LATEST_ABI_UPDATE(name, arch) \ DO_TEST_FULL(name, "." arch "-latest.abi-update", \ ARG_CAPS_ARCH, arch, \ ARG_CAPS_VER, "latest", \ ARG_PARSEFLAGS, VIR_DOMAIN_DEF_PARSE_ABI_UPDATE, \ ARG_END) -# define DO_TEST_CAPS_ARCH_VER(name, arch, ver) \ +#define DO_TEST_CAPS_ARCH_VER(name, arch, ver) \ DO_TEST_CAPS_ARCH_VER_FULL(name, arch, ver, ARG_END) -# define DO_TEST_CAPS_LATEST_NBDKIT(name, ...) \ +#define DO_TEST_CAPS_LATEST_NBDKIT(name, ...) \ DO_TEST_CAPS_ARCH_LATEST_FULL(name, "x86_64", ARG_NBDKIT_CAPS, __VA_ARGS__, QEMU_NBDKIT_CAPS_LAST, ARG_END) -# define DO_TEST_CAPS_LATEST(name) \ +#define DO_TEST_CAPS_LATEST(name) \ DO_TEST_CAPS_ARCH_LATEST(name, "x86_64") -# define DO_TEST_CAPS_LATEST_ABI_UPDATE(name) \ +#define DO_TEST_CAPS_LATEST_ABI_UPDATE(name) \ DO_TEST_CAPS_ARCH_LATEST_ABI_UPDATE(name, "x86_64") -# define DO_TEST_CAPS_VER(name, ver) \ +#define DO_TEST_CAPS_VER(name, ver) \ DO_TEST_CAPS_ARCH_VER(name, "x86_64", ver) -# define DO_TEST_CAPS_LATEST_PPC64(name) \ +#define DO_TEST_CAPS_LATEST_PPC64(name) \ DO_TEST_CAPS_ARCH_LATEST(name, "ppc64") -# define DO_TEST_CAPS_LATEST_PPC64_HOSTCPU(name, hostcpu) \ +#define DO_TEST_CAPS_LATEST_PPC64_HOSTCPU(name, hostcpu) \ DO_TEST_CAPS_ARCH_LATEST_FULL(name, "ppc64", \ ARG_CAPS_HOST_CPU_MODEL, hostcpu) -# define DO_TEST_CAPS_LATEST_PPC64_HOSTCPU_FAILURE(name, hostcpu) \ +#define DO_TEST_CAPS_LATEST_PPC64_HOSTCPU_FAILURE(name, hostcpu) \ DO_TEST_CAPS_ARCH_LATEST_FULL(name, "ppc64", \ ARG_CAPS_HOST_CPU_MODEL, hostcpu, \ ARG_FLAGS, FLAG_EXPECT_FAILURE) -# define DO_TEST_CAPS_ARCH_LATEST_FAILURE(name, arch) \ +#define DO_TEST_CAPS_ARCH_LATEST_FAILURE(name, arch) \ DO_TEST_CAPS_ARCH_LATEST_FULL(name, arch, \ ARG_FLAGS, FLAG_EXPECT_FAILURE) -# define DO_TEST_CAPS_ARCH_LATEST_ABI_UPDATE_FAILURE(name, arch) \ +#define DO_TEST_CAPS_ARCH_LATEST_ABI_UPDATE_FAILURE(name, arch) \ DO_TEST_FULL(name, "." arch "-latest.abi-update", \ ARG_CAPS_ARCH, arch, \ ARG_CAPS_VER, "latest", \ @@ -1367,24 +1364,24 @@ mymain(void) ARG_FLAGS, FLAG_EXPECT_FAILURE, \ ARG_END) -# define DO_TEST_CAPS_ARCH_VER_FAILURE(name, arch, ver) \ +#define DO_TEST_CAPS_ARCH_VER_FAILURE(name, arch, ver) \ DO_TEST_CAPS_ARCH_VER_FULL(name, arch, ver, \ ARG_FLAGS, FLAG_EXPECT_FAILURE) -# define DO_TEST_CAPS_LATEST_FAILURE(name) \ +#define DO_TEST_CAPS_LATEST_FAILURE(name) \ DO_TEST_CAPS_ARCH_LATEST_FAILURE(name, "x86_64") -# define DO_TEST_CAPS_LATEST_ABI_UPDATE_FAILURE(name) \ +#define DO_TEST_CAPS_LATEST_ABI_UPDATE_FAILURE(name) \ DO_TEST_CAPS_ARCH_LATEST_ABI_UPDATE_FAILURE(name, "x86_64") -# define DO_TEST_CAPS_VER_FAILURE(name, ver) \ +#define DO_TEST_CAPS_VER_FAILURE(name, ver) \ DO_TEST_CAPS_ARCH_VER_FAILURE(name, "x86_64", ver) -# define DO_TEST_CAPS_ARCH_LATEST_PARSE_ERROR(name, arch) \ +#define DO_TEST_CAPS_ARCH_LATEST_PARSE_ERROR(name, arch) \ DO_TEST_CAPS_ARCH_LATEST_FULL(name, arch, \ ARG_FLAGS, FLAG_EXPECT_PARSE_ERROR) -# define DO_TEST_CAPS_ARCH_LATEST_ABI_UPDATE_PARSE_ERROR(name, arch) \ +#define DO_TEST_CAPS_ARCH_LATEST_ABI_UPDATE_PARSE_ERROR(name, arch) \ DO_TEST_FULL(name, "." arch "-latest.abi-update", \ ARG_CAPS_ARCH, arch, \ ARG_CAPS_VER, "latest", \ @@ -1392,20 +1389,20 @@ mymain(void) ARG_FLAGS, FLAG_EXPECT_PARSE_ERROR, \ ARG_END) -# define DO_TEST_CAPS_ARCH_VER_PARSE_ERROR(name, arch, ver) \ +#define DO_TEST_CAPS_ARCH_VER_PARSE_ERROR(name, arch, ver) \ DO_TEST_CAPS_ARCH_VER_FULL(name, arch, ver, \ ARG_FLAGS, FLAG_EXPECT_PARSE_ERROR) -# define DO_TEST_CAPS_LATEST_PARSE_ERROR(name) \ +#define DO_TEST_CAPS_LATEST_PARSE_ERROR(name) \ DO_TEST_CAPS_ARCH_LATEST_PARSE_ERROR(name, "x86_64") -# define DO_TEST_CAPS_LATEST_ABI_UPDATE_PARSE_ERROR(name) \ +#define DO_TEST_CAPS_LATEST_ABI_UPDATE_PARSE_ERROR(name) \ DO_TEST_CAPS_ARCH_LATEST_ABI_UPDATE_PARSE_ERROR(name, "x86_64") -# define DO_TEST_CAPS_VER_PARSE_ERROR(name, ver) \ +#define DO_TEST_CAPS_VER_PARSE_ERROR(name, ver) \ DO_TEST_CAPS_ARCH_VER_PARSE_ERROR(name, "x86_64", ver) -# define DO_TEST_GIC(name, ver, gic) \ +#define DO_TEST_GIC(name, ver, gic) \ DO_TEST_CAPS_ARCH_VER_FULL(name, "aarch64", ver, ARG_GIC, gic, ARG_FLAGS, FLAG_ALLOW_DUPLICATE_OUTPUT, ARG_END) /* Unset or set all envvars here that are copied in qemudBuildCommandLine @@ -3418,12 +3415,3 @@ VIR_TEST_MAIN_PRELOAD(mymain, VIR_TEST_MOCK("virrandom"), VIR_TEST_MOCK("qemucpu"), VIR_TEST_MOCK("virnuma")) - -#else - -int main(void) -{ - return EXIT_AM_SKIP; -} - -#endif /* WITH_QEMU */ diff --git a/tests/testutilsqemu.c b/tests/testutilsqemu.c index d7f2e55330..e00e52d2a8 100644 --- a/tests/testutilsqemu.c +++ b/tests/testutilsqemu.c @@ -1,23 +1,22 @@ #include <config.h> -#ifdef WITH_QEMU -# include "testutilsqemu.h" -# include "testutilsqemuschema.h" -# include "testutilshostcpus.h" -# include "testutils.h" -# include "viralloc.h" -# include "cpu_conf.h" -# include "qemu/qemu_domain.h" -# define LIBVIRT_QEMU_CAPSPRIV_H_ALLOW -# include "qemu/qemu_capspriv.h" -# include "virstring.h" -# include "virfilecache.h" -# include "virtpm.h" +#include <sys/types.h> +#include <fcntl.h> -# include <sys/types.h> -# include <fcntl.h> +#include "testutilsqemu.h" +#include "testutilsqemuschema.h" +#include "testutilshostcpus.h" +#include "testutils.h" +#include "viralloc.h" +#include "cpu_conf.h" +#include "qemu/qemu_domain.h" +#define LIBVIRT_QEMU_CAPSPRIV_H_ALLOW +#include "qemu/qemu_capspriv.h" +#include "virstring.h" +#include "virfilecache.h" +#include "virtpm.h" -# define VIR_FROM_THIS VIR_FROM_QEMU +#define VIR_FROM_THIS VIR_FROM_QEMU static virCPUDef *cpuDefault; static virCPUDef *cpuHaswell; @@ -289,8 +288,8 @@ qemuTestCapsCacheInsert(virFileCache *cache, return 0; } -# define STATEDIRTEMPLATE abs_builddir "/qemustatedir-XXXXXX" -# define CONFIGDIRTEMPLATE abs_builddir "/qemuconfigdir-XXXXXX" +#define STATEDIRTEMPLATE abs_builddir "/qemustatedir-XXXXXX" +#define CONFIGDIRTEMPLATE abs_builddir "/qemuconfigdir-XXXXXX" int qemuTestDriverInit(virQEMUDriver *driver) { @@ -443,8 +442,8 @@ testQemuCapsSetGIC(virQEMUCaps *qemuCaps, gicCapabilities = g_new0(virGICCapability, 2); -# define IMPL_BOTH \ - VIR_GIC_IMPLEMENTATION_KERNEL|VIR_GIC_IMPLEMENTATION_EMULATED +#define IMPL_BOTH \ + VIR_GIC_IMPLEMENTATION_KERNEL|VIR_GIC_IMPLEMENTATION_EMULATED if (gic & GIC_V2) { gicCapabilities[ngicCapabilities].version = VIR_GIC_VERSION_2; @@ -457,7 +456,7 @@ testQemuCapsSetGIC(virQEMUCaps *qemuCaps, ngicCapabilities++; } -# undef IMPL_BOTH +#undef IMPL_BOTH virQEMUCapsSetGICCapabilities(qemuCaps, gicCapabilities, ngicCapabilities); @@ -465,8 +464,6 @@ testQemuCapsSetGIC(virQEMUCaps *qemuCaps, return 0; } -#endif - struct testQemuCapsFile { unsigned long long ver; diff --git a/tests/testutilsqemu.h b/tests/testutilsqemu.h index a8e0fefa84..dbc8e2dbdf 100644 --- a/tests/testutilsqemu.h +++ b/tests/testutilsqemu.h @@ -16,19 +16,17 @@ #pragma once -#ifdef WITH_QEMU +#include "capabilities.h" +#include "virfilecache.h" +#include "domain_conf.h" +#include "qemu/qemu_capabilities.h" +#include "qemu/qemu_conf.h" -# include "capabilities.h" -# include "virfilecache.h" -# include "domain_conf.h" -# include "qemu/qemu_capabilities.h" -# include "qemu/qemu_conf.h" - -# define TEST_QEMU_CAPS_PATH abs_srcdir "/qemucapabilitiesdata" -# define TEST_TPM_ENV_VAR "VIR_TEST_MOCK_FAKE_TPM_VERSION" -# define TPM_VER_1_2 "1.2" -# define TPM_VER_2_0 "2.0" -# define TEST_NBDKIT_PATH "/fakebindir/nbdkit" +#define TEST_QEMU_CAPS_PATH abs_srcdir "/qemucapabilitiesdata" +#define TEST_TPM_ENV_VAR "VIR_TEST_MOCK_FAKE_TPM_VERSION" +#define TPM_VER_1_2 "1.2" +#define TPM_VER_2_0 "2.0" +#define TEST_NBDKIT_PATH "/fakebindir/nbdkit" enum { GIC_NONE = 0, @@ -187,4 +185,3 @@ testQemuInsertRealCaps(virFileCache *cache, GHashTable *capsCache, GHashTable *schemaCache, GHashTable **schema); -#endif -- 2.52.0
From: Michal Privoznik <mprivozn@redhat.com> One of the tests that qemuxmlconftest does is generate cmd line for given domain XML. This process might involve talking to other drivers (secret/storage/nwfilter/network). To produce predictable output the test comes with fake implementation of APIs of those drivers. Well, move that implementation into a separate file so that it can be reused by other tests (notably, qemuhotplugtest is going to use it). Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- tests/meson.build | 5 +- tests/qemufakedrivers.c | 368 ++++++++++++++++++++++++++++++++++++++++ tests/qemufakedrivers.h | 19 +++ tests/qemuxmlconftest.c | 331 +----------------------------------- 4 files changed, 396 insertions(+), 327 deletions(-) create mode 100644 tests/qemufakedrivers.c create mode 100644 tests/qemufakedrivers.h diff --git a/tests/meson.build b/tests/meson.build index 847538d2e4..83aa0104bb 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -151,7 +151,10 @@ endif if conf.has('WITH_QEMU') test_utils_qemu_lib = static_library( 'test_utils_qemu', - [ 'testutilsqemu.c', 'testutilsqemuschema.c' ], + [ 'qemufakedrivers.c', + 'testutilsqemu.c', + 'testutilsqemuschema.c', + ], dependencies: [ tests_dep ], ) diff --git a/tests/qemufakedrivers.c b/tests/qemufakedrivers.c new file mode 100644 index 0000000000..94ad5aeb0b --- /dev/null +++ b/tests/qemufakedrivers.c @@ -0,0 +1,368 @@ +/* + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include <config.h> + +#include "qemufakedrivers.h" +#include "testutils.h" +#include "datatypes.h" +#include "storage_conf.h" + +#define VIR_FROM_THIS VIR_FROM_QEMU + +static unsigned char * +fakeSecretGetValue(virSecretPtr obj G_GNUC_UNUSED, + size_t *value_size, + unsigned int fakeflags G_GNUC_UNUSED) +{ + char *secret; + secret = g_strdup("AQCVn5hO6HzFAhAAq0NCv8jtJcIcE+HOBlMQ1A"); + *value_size = strlen(secret); + return (unsigned char *) secret; +} + + +static virSecretPtr +fakeSecretLookupByUsage(virConnectPtr conn, + int usageType, + const char *usageID) +{ + unsigned char uuid[VIR_UUID_BUFLEN]; + if (usageType == VIR_SECRET_USAGE_TYPE_VOLUME) { + if (!STRPREFIX(usageID, "/storage/guest_disks/")) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "test provided invalid volume storage prefix '%s'", + usageID); + return NULL; + } + } else if (STRNEQ(usageID, "mycluster_myname") && + STRNEQ(usageID, "client.admin secret")) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "test provided incorrect usage '%s'", usageID); + return NULL; + } + + if (virUUIDGenerate(uuid) < 0) + return NULL; + + return virGetSecret(conn, uuid, usageType, usageID); +} + + +static virSecretPtr +fakeSecretLookupByUUID(virConnectPtr conn, + const unsigned char *uuid) +{ + /* NB: This mocked value could be "tls" or "volume" depending on + * which test is being run, we'll leave at NONE (or 0) */ + return virGetSecret(conn, uuid, VIR_SECRET_USAGE_TYPE_NONE, ""); +} + + +static virSecretDriver fakeSecretDriver = { + .connectNumOfSecrets = NULL, + .connectListSecrets = NULL, + .secretLookupByUUID = fakeSecretLookupByUUID, + .secretLookupByUsage = fakeSecretLookupByUsage, + .secretDefineXML = NULL, + .secretGetXMLDesc = NULL, + .secretSetValue = NULL, + .secretGetValue = fakeSecretGetValue, + .secretUndefine = NULL, +}; + + +virSecretDriver * +testQemuGetFakeSecretDriver(void) +{ + return &fakeSecretDriver; +} + + +#define STORAGE_POOL_XML_PATH "storagepoolxml2xmlout/" +static const unsigned char fakeUUID[VIR_UUID_BUFLEN] = "fakeuuid"; + +static virStoragePoolPtr +fakeStoragePoolLookupByName(virConnectPtr conn, + const char *name) +{ + g_autofree char *xmlpath = NULL; + + if (STRNEQ(name, "inactive")) { + xmlpath = g_strdup_printf("%s/%s%s.xml", abs_srcdir, + STORAGE_POOL_XML_PATH, name); + + if (!virFileExists(xmlpath)) { + virReportError(VIR_ERR_NO_STORAGE_POOL, + "File '%s' not found", xmlpath); + return NULL; + } + } + + return virGetStoragePool(conn, name, fakeUUID, NULL, NULL); +} + + +static virStorageVolPtr +fakeStorageVolLookupByName(virStoragePoolPtr pool, + const char *name) +{ + g_auto(GStrv) volinfo = NULL; + + if (STREQ(pool->name, "inactive")) { + virReportError(VIR_ERR_OPERATION_INVALID, + "storage pool '%s' is not active", pool->name); + return NULL; + } + + if (STREQ(name, "nonexistent")) { + virReportError(VIR_ERR_NO_STORAGE_VOL, + "no storage vol with matching name '%s'", name); + return NULL; + } + + if (!(volinfo = g_strsplit(name, "+", 2))) + return NULL; + + if (!volinfo[1]) { + return virGetStorageVol(pool->conn, pool->name, name, "block", NULL, NULL); + } + + return virGetStorageVol(pool->conn, pool->name, volinfo[1], volinfo[0], + NULL, NULL); +} + + +static int +fakeStorageVolGetInfo(virStorageVolPtr vol, + virStorageVolInfoPtr info) +{ + memset(info, 0, sizeof(*info)); + + info->type = virStorageVolTypeFromString(vol->key); + + if (info->type < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "Invalid volume type '%s'", vol->key); + return -1; + } + + return 0; +} + + +static char * +fakeStorageVolGetPath(virStorageVolPtr vol) +{ + return g_strdup_printf("/some/%s/device/%s", vol->key, vol->name); +} + + +static char * +fakeStoragePoolGetXMLDesc(virStoragePoolPtr pool, + unsigned int flags_unused G_GNUC_UNUSED) +{ + g_autofree char *xmlpath = NULL; + char *xmlbuf = NULL; + + if (STREQ(pool->name, "inactive")) { + virReportError(VIR_ERR_NO_STORAGE_POOL, NULL); + return NULL; + } + + xmlpath = g_strdup_printf("%s/%s%s.xml", abs_srcdir, STORAGE_POOL_XML_PATH, + pool->name); + + if (virTestLoadFile(xmlpath, &xmlbuf) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "failed to load XML file '%s'", + xmlpath); + return NULL; + } + + return xmlbuf; +} + + +static int +fakeStoragePoolIsActive(virStoragePoolPtr pool) +{ + if (STREQ(pool->name, "inactive")) + return 0; + + return 1; +} + + +/* Test storage pool implementation + * + * These functions aid testing of storage pool related stuff when creating a + * qemu command line. + * + * There are a few "magic" values to pass to these functions: + * + * 1) "inactive" as a pool name to create an inactive pool. All other names are + * interpreted as file names in storagepoolxml2xmlout/ and are used as the + * definition for the pool. If the file doesn't exist the pool doesn't exist. + * + * 2) "nonexistent" returns an error while looking up a volume. Otherwise + * pattern VOLUME_TYPE+VOLUME_PATH can be used to simulate a volume in a pool. + * This creates a fake path for this volume. If the '+' sign is omitted, block + * type is assumed. + */ +static virStorageDriver fakeStorageDriver = { + .storagePoolLookupByName = fakeStoragePoolLookupByName, + .storageVolLookupByName = fakeStorageVolLookupByName, + .storagePoolGetXMLDesc = fakeStoragePoolGetXMLDesc, + .storageVolGetPath = fakeStorageVolGetPath, + .storageVolGetInfo = fakeStorageVolGetInfo, + .storagePoolIsActive = fakeStoragePoolIsActive, +}; + + +virStorageDriver * +testQemuGetFakeStorageDriver(void) +{ + return &fakeStorageDriver; +} + + +/* virNetDevOpenvswitchGetVhostuserIfname mocks a portdev name - handle that */ +static virNWFilterBindingPtr +fakeNWFilterBindingLookupByPortDev(virConnectPtr conn, + const char *portdev) +{ + if (STREQ(portdev, "vhost-user0")) + return virGetNWFilterBinding(conn, "fake_vnet0", "fakeFilterName"); + + virReportError(VIR_ERR_NO_NWFILTER_BINDING, + "no nwfilter binding for port dev '%s'", portdev); + return NULL; +} + + +static int +fakeNWFilterBindingDelete(virNWFilterBindingPtr binding G_GNUC_UNUSED) +{ + return 0; +} + + +static virNWFilterDriver fakeNWFilterDriver = { + .nwfilterBindingLookupByPortDev = fakeNWFilterBindingLookupByPortDev, + .nwfilterBindingDelete = fakeNWFilterBindingDelete, +}; + + +virNWFilterDriver * +testQemuGetFakeNWFilterDriver(void) +{ + return &fakeNWFilterDriver; +} + + +/* name of the fake network shall be constructed as: + * NETWORKXMLNAME;NETWORKPORTXMLNAME + * where: + * NETWORKXMLNAME resolves to abs_srcdir/networkxmlconfdata/NETWORKXMLNAME.xml + * NETWORKPORTXMLNAME resolves to abs_srcdir/virnetworkportxml2xmldata/NETWORKPORTXMLNAME.xml + */ +static virNetworkPtr +fakeNetworkLookupByName(virConnectPtr conn, + const char *name) +{ + unsigned char uuid[VIR_UUID_BUFLEN]; + g_autofree char *netname = g_strdup(name); + g_autofree char *path = NULL; + char *tmp; + + memset(uuid, 0, VIR_UUID_BUFLEN); + + if ((tmp = strchr(netname, ';'))) { + *tmp = '\0'; + } else { + virReportError(VIR_ERR_NO_NETWORK, + "Malformed fake network name '%s'. See fakeNetworkLookupByName.", + name); + return NULL; + } + + path = g_strdup_printf(abs_srcdir "/networkxmlconfdata/%s.xml", netname); + + if (!virFileExists(path)) { + virReportError(VIR_ERR_NO_NETWORK, "fake network '%s' not found", path); + return NULL; + } + + return virGetNetwork(conn, name, uuid); +} + + +static char * +fakeNetworkGetXMLDesc(virNetworkPtr network, + unsigned int noflags G_GNUC_UNUSED) +{ + g_autofree char *netname = g_strdup(network->name); + g_autofree char *path = NULL; + char *xml = NULL; + + *(strchr(netname, ';')) = '\0'; + + path = g_strdup_printf(abs_srcdir "/networkxmlconfdata/%s.xml", netname); + + if (virFileReadAll(path, 4 * 1024, &xml) < 0) + return NULL; + + return xml; +} + + +static virNetworkPortPtr +fakeNetworkPortCreateXML(virNetworkPtr net, + const char *xmldesc G_GNUC_UNUSED, + unsigned int noflags G_GNUC_UNUSED) +{ + unsigned char uuid[VIR_UUID_BUFLEN]; + g_autofree char *portname = g_strdup(strchr(net->name, ';') + 1); + g_autofree char *path = g_strdup_printf(abs_srcdir "/virnetworkportxml2xmldata/%s.xml", portname); + + memset(uuid, 0, VIR_UUID_BUFLEN); + + if (!virFileExists(path)) { + virReportError(VIR_ERR_NO_NETWORK_PORT, "fake network port '%s' not found", path); + return NULL; + } + + return virGetNetworkPort(net, uuid); +} + + +static char * +fakeNetworkPortGetXMLDesc(virNetworkPortPtr port, + unsigned int noflags G_GNUC_UNUSED) +{ + g_autofree char *portname = g_strdup(strchr(port->net->name, ';') + 1); + g_autofree char *path = g_strdup_printf(abs_srcdir "/virnetworkportxml2xmldata/%s.xml", portname); + char *xml = NULL; + + if (virFileReadAll(path, 4 * 1024, &xml) < 0) + return NULL; + + return xml; +} + + +static virNetworkDriver fakeNetworkDriver = { + .networkLookupByName = fakeNetworkLookupByName, + .networkGetXMLDesc = fakeNetworkGetXMLDesc, + .networkPortCreateXML = fakeNetworkPortCreateXML, + .networkPortGetXMLDesc = fakeNetworkPortGetXMLDesc, +}; + + +virNetworkDriver * +testQemuGetFakeNetworkDriver(void) +{ + return &fakeNetworkDriver; +} diff --git a/tests/qemufakedrivers.h b/tests/qemufakedrivers.h new file mode 100644 index 0000000000..172ae48451 --- /dev/null +++ b/tests/qemufakedrivers.h @@ -0,0 +1,19 @@ +/* + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#pragma once + +#include "driver.h" + +virSecretDriver * +testQemuGetFakeSecretDriver(void); + +virStorageDriver * +testQemuGetFakeStorageDriver(void); + +virNWFilterDriver * +testQemuGetFakeNWFilterDriver(void); + +virNetworkDriver * +testQemuGetFakeNetworkDriver(void); diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c index cf147e70d4..32eb42dd19 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -23,6 +23,7 @@ #include "virfilewrapper.h" #include "configmake.h" #include "testutilsqemuschema.h" +#include "qemufakedrivers.h" #define LIBVIRT_QEMU_CAPSPRIV_H_ALLOW #include "qemu/qemu_capspriv.h" @@ -33,320 +34,6 @@ static virQEMUDriver driver; -static unsigned char * -fakeSecretGetValue(virSecretPtr obj G_GNUC_UNUSED, - size_t *value_size, - unsigned int fakeflags G_GNUC_UNUSED) -{ - char *secret; - secret = g_strdup("AQCVn5hO6HzFAhAAq0NCv8jtJcIcE+HOBlMQ1A"); - *value_size = strlen(secret); - return (unsigned char *) secret; -} - -static virSecretPtr -fakeSecretLookupByUsage(virConnectPtr conn, - int usageType, - const char *usageID) -{ - unsigned char uuid[VIR_UUID_BUFLEN]; - if (usageType == VIR_SECRET_USAGE_TYPE_VOLUME) { - if (!STRPREFIX(usageID, "/storage/guest_disks/")) { - virReportError(VIR_ERR_INTERNAL_ERROR, - "test provided invalid volume storage prefix '%s'", - usageID); - return NULL; - } - } else if (STRNEQ(usageID, "mycluster_myname") && - STRNEQ(usageID, "client.admin secret")) { - virReportError(VIR_ERR_INTERNAL_ERROR, - "test provided incorrect usage '%s'", usageID); - return NULL; - } - - if (virUUIDGenerate(uuid) < 0) - return NULL; - - return virGetSecret(conn, uuid, usageType, usageID); -} - -static virSecretPtr -fakeSecretLookupByUUID(virConnectPtr conn, - const unsigned char *uuid) -{ - /* NB: This mocked value could be "tls" or "volume" depending on - * which test is being run, we'll leave at NONE (or 0) */ - return virGetSecret(conn, uuid, VIR_SECRET_USAGE_TYPE_NONE, ""); -} - -static virSecretDriver fakeSecretDriver = { - .connectNumOfSecrets = NULL, - .connectListSecrets = NULL, - .secretLookupByUUID = fakeSecretLookupByUUID, - .secretLookupByUsage = fakeSecretLookupByUsage, - .secretDefineXML = NULL, - .secretGetXMLDesc = NULL, - .secretSetValue = NULL, - .secretGetValue = fakeSecretGetValue, - .secretUndefine = NULL, -}; - - -#define STORAGE_POOL_XML_PATH "storagepoolxml2xmlout/" -static const unsigned char fakeUUID[VIR_UUID_BUFLEN] = "fakeuuid"; - -static virStoragePoolPtr -fakeStoragePoolLookupByName(virConnectPtr conn, - const char *name) -{ - g_autofree char *xmlpath = NULL; - - if (STRNEQ(name, "inactive")) { - xmlpath = g_strdup_printf("%s/%s%s.xml", abs_srcdir, - STORAGE_POOL_XML_PATH, name); - - if (!virFileExists(xmlpath)) { - virReportError(VIR_ERR_NO_STORAGE_POOL, - "File '%s' not found", xmlpath); - return NULL; - } - } - - return virGetStoragePool(conn, name, fakeUUID, NULL, NULL); -} - - -static virStorageVolPtr -fakeStorageVolLookupByName(virStoragePoolPtr pool, - const char *name) -{ - g_auto(GStrv) volinfo = NULL; - - if (STREQ(pool->name, "inactive")) { - virReportError(VIR_ERR_OPERATION_INVALID, - "storage pool '%s' is not active", pool->name); - return NULL; - } - - if (STREQ(name, "nonexistent")) { - virReportError(VIR_ERR_NO_STORAGE_VOL, - "no storage vol with matching name '%s'", name); - return NULL; - } - - if (!(volinfo = g_strsplit(name, "+", 2))) - return NULL; - - if (!volinfo[1]) { - return virGetStorageVol(pool->conn, pool->name, name, "block", NULL, NULL); - } - - return virGetStorageVol(pool->conn, pool->name, volinfo[1], volinfo[0], - NULL, NULL); -} - -static int -fakeStorageVolGetInfo(virStorageVolPtr vol, - virStorageVolInfoPtr info) -{ - memset(info, 0, sizeof(*info)); - - info->type = virStorageVolTypeFromString(vol->key); - - if (info->type < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - "Invalid volume type '%s'", vol->key); - return -1; - } - - return 0; -} - - -static char * -fakeStorageVolGetPath(virStorageVolPtr vol) -{ - return g_strdup_printf("/some/%s/device/%s", vol->key, vol->name); -} - - -static char * -fakeStoragePoolGetXMLDesc(virStoragePoolPtr pool, - unsigned int flags_unused G_GNUC_UNUSED) -{ - g_autofree char *xmlpath = NULL; - char *xmlbuf = NULL; - - if (STREQ(pool->name, "inactive")) { - virReportError(VIR_ERR_NO_STORAGE_POOL, NULL); - return NULL; - } - - xmlpath = g_strdup_printf("%s/%s%s.xml", abs_srcdir, STORAGE_POOL_XML_PATH, - pool->name); - - if (virTestLoadFile(xmlpath, &xmlbuf) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - "failed to load XML file '%s'", - xmlpath); - return NULL; - } - - return xmlbuf; -} - -static int -fakeStoragePoolIsActive(virStoragePoolPtr pool) -{ - if (STREQ(pool->name, "inactive")) - return 0; - - return 1; -} - -/* Test storage pool implementation - * - * These functions aid testing of storage pool related stuff when creating a - * qemu command line. - * - * There are a few "magic" values to pass to these functions: - * - * 1) "inactive" as a pool name to create an inactive pool. All other names are - * interpreted as file names in storagepoolxml2xmlout/ and are used as the - * definition for the pool. If the file doesn't exist the pool doesn't exist. - * - * 2) "nonexistent" returns an error while looking up a volume. Otherwise - * pattern VOLUME_TYPE+VOLUME_PATH can be used to simulate a volume in a pool. - * This creates a fake path for this volume. If the '+' sign is omitted, block - * type is assumed. - */ -static virStorageDriver fakeStorageDriver = { - .storagePoolLookupByName = fakeStoragePoolLookupByName, - .storageVolLookupByName = fakeStorageVolLookupByName, - .storagePoolGetXMLDesc = fakeStoragePoolGetXMLDesc, - .storageVolGetPath = fakeStorageVolGetPath, - .storageVolGetInfo = fakeStorageVolGetInfo, - .storagePoolIsActive = fakeStoragePoolIsActive, -}; - - -/* virNetDevOpenvswitchGetVhostuserIfname mocks a portdev name - handle that */ -static virNWFilterBindingPtr -fakeNWFilterBindingLookupByPortDev(virConnectPtr conn, - const char *portdev) -{ - if (STREQ(portdev, "vhost-user0")) - return virGetNWFilterBinding(conn, "fake_vnet0", "fakeFilterName"); - - virReportError(VIR_ERR_NO_NWFILTER_BINDING, - "no nwfilter binding for port dev '%s'", portdev); - return NULL; -} - - -static int -fakeNWFilterBindingDelete(virNWFilterBindingPtr binding G_GNUC_UNUSED) -{ - return 0; -} - - -static virNWFilterDriver fakeNWFilterDriver = { - .nwfilterBindingLookupByPortDev = fakeNWFilterBindingLookupByPortDev, - .nwfilterBindingDelete = fakeNWFilterBindingDelete, -}; - - -/* name of the fake network shall be constructed as: - * NETWORKXMLNAME;NETWORKPORTXMLNAME - * where: - * NETWORKXMLNAME resolves to abs_srcdir/networkxmlconfdata/NETWORKXMLNAME.xml - * NETWORKPORTXMLNAME resolves to abs_srcdir/virnetworkportxml2xmldata/NETWORKPORTXMLNAME.xml - */ -static virNetworkPtr -fakeNetworkLookupByName(virConnectPtr conn, - const char *name) -{ - unsigned char uuid[VIR_UUID_BUFLEN]; - g_autofree char *netname = g_strdup(name); - g_autofree char *path = NULL; - char *tmp; - - memset(uuid, 0, VIR_UUID_BUFLEN); - - if ((tmp = strchr(netname, ';'))) { - *tmp = '\0'; - } else { - virReportError(VIR_ERR_NO_NETWORK, - "Malformed fake network name '%s'. See fakeNetworkLookupByName.", - name); - return NULL; - } - - path = g_strdup_printf(abs_srcdir "/networkxmlconfdata/%s.xml", netname); - - if (!virFileExists(path)) { - virReportError(VIR_ERR_NO_NETWORK, "fake network '%s' not found", path); - return NULL; - } - - return virGetNetwork(conn, name, uuid); -} - - -static char * -fakeNetworkGetXMLDesc(virNetworkPtr network, - unsigned int noflags G_GNUC_UNUSED) -{ - g_autofree char *netname = g_strdup(network->name); - g_autofree char *path = NULL; - char *xml = NULL; - - *(strchr(netname, ';')) = '\0'; - - path = g_strdup_printf(abs_srcdir "/networkxmlconfdata/%s.xml", netname); - - if (virFileReadAll(path, 4 * 1024, &xml) < 0) - return NULL; - - return xml; -} - - -static virNetworkPortPtr -fakeNetworkPortCreateXML(virNetworkPtr net, - const char *xmldesc G_GNUC_UNUSED, - unsigned int noflags G_GNUC_UNUSED) -{ - unsigned char uuid[VIR_UUID_BUFLEN]; - g_autofree char *portname = g_strdup(strchr(net->name, ';') + 1); - g_autofree char *path = g_strdup_printf(abs_srcdir "/virnetworkportxml2xmldata/%s.xml", portname); - - memset(uuid, 0, VIR_UUID_BUFLEN); - - if (!virFileExists(path)) { - virReportError(VIR_ERR_NO_NETWORK_PORT, "fake network port '%s' not found", path); - return NULL; - } - - return virGetNetworkPort(net, uuid); -} - - -static char * -fakeNetworkPortGetXMLDesc(virNetworkPortPtr port, - unsigned int noflags G_GNUC_UNUSED) -{ - g_autofree char *portname = g_strdup(strchr(port->net->name, ';') + 1); - g_autofree char *path = g_strdup_printf(abs_srcdir "/virnetworkportxml2xmldata/%s.xml", portname); - char *xml = NULL; - - if (virFileReadAll(path, 4 * 1024, &xml) < 0) - return NULL; - - return xml; -} - static void testQemuPrepareHostdevPCI(virDomainHostdevDef *hostdev) @@ -418,14 +105,6 @@ testQemuPrepareHostdev(virDomainObj *vm) } -static virNetworkDriver fakeNetworkDriver = { - .networkLookupByName = fakeNetworkLookupByName, - .networkGetXMLDesc = fakeNetworkGetXMLDesc, - .networkPortCreateXML = fakeNetworkPortCreateXML, - .networkPortGetXMLDesc = fakeNetworkPortGetXMLDesc, -}; - - static void testUpdateQEMUCapsHostCPUModel(virQEMUCaps *qemuCaps, virArch hostArch) { @@ -1273,10 +952,10 @@ mymain(void) if (!(conn = virGetConnect())) return EXIT_FAILURE; - conn->secretDriver = &fakeSecretDriver; - conn->storageDriver = &fakeStorageDriver; - conn->nwfilterDriver = &fakeNWFilterDriver; - conn->networkDriver = &fakeNetworkDriver; + conn->secretDriver = testQemuGetFakeSecretDriver(); + conn->storageDriver = testQemuGetFakeStorageDriver(); + conn->nwfilterDriver = testQemuGetFakeNWFilterDriver(); + conn->networkDriver = testQemuGetFakeNetworkDriver(); virSetConnectInterface(conn); virSetConnectNetwork(conn); -- 2.52.0
On 3/12/26 3:57 AM, Michal Privoznik via Devel wrote:
From: Michal Privoznik <mprivozn@redhat.com>
One of the tests that qemuxmlconftest does is generate cmd line for given domain XML. This process might involve talking to other drivers (secret/storage/nwfilter/network). To produce predictable output the test comes with fake implementation of APIs of those drivers. Well, move that implementation into a separate file so that it can be reused by other tests (notably, qemuhotplugtest is going to use it).
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
This is all code movement, so "not your problem", but it did make me notice the redundant ".secretBlah = NULL," initializers for the fake secret driver - they don't hurt anything, but are using up precious bits :-).
--- tests/meson.build | 5 +- tests/qemufakedrivers.c | 368 ++++++++++++++++++++++++++++++++++++++++ tests/qemufakedrivers.h | 19 +++ tests/qemuxmlconftest.c | 331 +----------------------------------- 4 files changed, 396 insertions(+), 327 deletions(-) create mode 100644 tests/qemufakedrivers.c create mode 100644 tests/qemufakedrivers.h
diff --git a/tests/meson.build b/tests/meson.build index 847538d2e4..83aa0104bb 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -151,7 +151,10 @@ endif if conf.has('WITH_QEMU') test_utils_qemu_lib = static_library( 'test_utils_qemu', - [ 'testutilsqemu.c', 'testutilsqemuschema.c' ], + [ 'qemufakedrivers.c', + 'testutilsqemu.c', + 'testutilsqemuschema.c', + ], dependencies: [ tests_dep ], )
diff --git a/tests/qemufakedrivers.c b/tests/qemufakedrivers.c new file mode 100644 index 0000000000..94ad5aeb0b --- /dev/null +++ b/tests/qemufakedrivers.c @@ -0,0 +1,368 @@ +/* + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include <config.h> + +#include "qemufakedrivers.h" +#include "testutils.h" +#include "datatypes.h" +#include "storage_conf.h" + +#define VIR_FROM_THIS VIR_FROM_QEMU + +static unsigned char * +fakeSecretGetValue(virSecretPtr obj G_GNUC_UNUSED, + size_t *value_size, + unsigned int fakeflags G_GNUC_UNUSED) +{ + char *secret; + secret = g_strdup("AQCVn5hO6HzFAhAAq0NCv8jtJcIcE+HOBlMQ1A"); + *value_size = strlen(secret); + return (unsigned char *) secret; +} + + +static virSecretPtr +fakeSecretLookupByUsage(virConnectPtr conn, + int usageType, + const char *usageID) +{ + unsigned char uuid[VIR_UUID_BUFLEN]; + if (usageType == VIR_SECRET_USAGE_TYPE_VOLUME) { + if (!STRPREFIX(usageID, "/storage/guest_disks/")) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "test provided invalid volume storage prefix '%s'", + usageID); + return NULL; + } + } else if (STRNEQ(usageID, "mycluster_myname") && + STRNEQ(usageID, "client.admin secret")) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "test provided incorrect usage '%s'", usageID); + return NULL; + } + + if (virUUIDGenerate(uuid) < 0) + return NULL; + + return virGetSecret(conn, uuid, usageType, usageID); +} + + +static virSecretPtr +fakeSecretLookupByUUID(virConnectPtr conn, + const unsigned char *uuid) +{ + /* NB: This mocked value could be "tls" or "volume" depending on + * which test is being run, we'll leave at NONE (or 0) */ + return virGetSecret(conn, uuid, VIR_SECRET_USAGE_TYPE_NONE, ""); +} + + +static virSecretDriver fakeSecretDriver = { + .connectNumOfSecrets = NULL, + .connectListSecrets = NULL, + .secretLookupByUUID = fakeSecretLookupByUUID, + .secretLookupByUsage = fakeSecretLookupByUsage, + .secretDefineXML = NULL, + .secretGetXMLDesc = NULL, + .secretSetValue = NULL, + .secretGetValue = fakeSecretGetValue, + .secretUndefine = NULL, +}; + + +virSecretDriver * +testQemuGetFakeSecretDriver(void) +{ + return &fakeSecretDriver; +} + + +#define STORAGE_POOL_XML_PATH "storagepoolxml2xmlout/" +static const unsigned char fakeUUID[VIR_UUID_BUFLEN] = "fakeuuid"; + +static virStoragePoolPtr +fakeStoragePoolLookupByName(virConnectPtr conn, + const char *name) +{ + g_autofree char *xmlpath = NULL; + + if (STRNEQ(name, "inactive")) { + xmlpath = g_strdup_printf("%s/%s%s.xml", abs_srcdir, + STORAGE_POOL_XML_PATH, name); + + if (!virFileExists(xmlpath)) { + virReportError(VIR_ERR_NO_STORAGE_POOL, + "File '%s' not found", xmlpath); + return NULL; + } + } + + return virGetStoragePool(conn, name, fakeUUID, NULL, NULL); +} + + +static virStorageVolPtr +fakeStorageVolLookupByName(virStoragePoolPtr pool, + const char *name) +{ + g_auto(GStrv) volinfo = NULL; + + if (STREQ(pool->name, "inactive")) { + virReportError(VIR_ERR_OPERATION_INVALID, + "storage pool '%s' is not active", pool->name); + return NULL; + } + + if (STREQ(name, "nonexistent")) { + virReportError(VIR_ERR_NO_STORAGE_VOL, + "no storage vol with matching name '%s'", name); + return NULL; + } + + if (!(volinfo = g_strsplit(name, "+", 2))) + return NULL; + + if (!volinfo[1]) { + return virGetStorageVol(pool->conn, pool->name, name, "block", NULL, NULL); + } + + return virGetStorageVol(pool->conn, pool->name, volinfo[1], volinfo[0], + NULL, NULL); +} + + +static int +fakeStorageVolGetInfo(virStorageVolPtr vol, + virStorageVolInfoPtr info) +{ + memset(info, 0, sizeof(*info)); + + info->type = virStorageVolTypeFromString(vol->key); + + if (info->type < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "Invalid volume type '%s'", vol->key); + return -1; + } + + return 0; +} + + +static char * +fakeStorageVolGetPath(virStorageVolPtr vol) +{ + return g_strdup_printf("/some/%s/device/%s", vol->key, vol->name); +} + + +static char * +fakeStoragePoolGetXMLDesc(virStoragePoolPtr pool, + unsigned int flags_unused G_GNUC_UNUSED) +{ + g_autofree char *xmlpath = NULL; + char *xmlbuf = NULL; + + if (STREQ(pool->name, "inactive")) { + virReportError(VIR_ERR_NO_STORAGE_POOL, NULL); + return NULL; + } + + xmlpath = g_strdup_printf("%s/%s%s.xml", abs_srcdir, STORAGE_POOL_XML_PATH, + pool->name); + + if (virTestLoadFile(xmlpath, &xmlbuf) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "failed to load XML file '%s'", + xmlpath); + return NULL; + } + + return xmlbuf; +} + + +static int +fakeStoragePoolIsActive(virStoragePoolPtr pool) +{ + if (STREQ(pool->name, "inactive")) + return 0; + + return 1; +} + + +/* Test storage pool implementation + * + * These functions aid testing of storage pool related stuff when creating a + * qemu command line. + * + * There are a few "magic" values to pass to these functions: + * + * 1) "inactive" as a pool name to create an inactive pool. All other names are + * interpreted as file names in storagepoolxml2xmlout/ and are used as the + * definition for the pool. If the file doesn't exist the pool doesn't exist. + * + * 2) "nonexistent" returns an error while looking up a volume. Otherwise + * pattern VOLUME_TYPE+VOLUME_PATH can be used to simulate a volume in a pool. + * This creates a fake path for this volume. If the '+' sign is omitted, block + * type is assumed. + */ +static virStorageDriver fakeStorageDriver = { + .storagePoolLookupByName = fakeStoragePoolLookupByName, + .storageVolLookupByName = fakeStorageVolLookupByName, + .storagePoolGetXMLDesc = fakeStoragePoolGetXMLDesc, + .storageVolGetPath = fakeStorageVolGetPath, + .storageVolGetInfo = fakeStorageVolGetInfo, + .storagePoolIsActive = fakeStoragePoolIsActive, +}; + + +virStorageDriver * +testQemuGetFakeStorageDriver(void) +{ + return &fakeStorageDriver; +} + + +/* virNetDevOpenvswitchGetVhostuserIfname mocks a portdev name - handle that */ +static virNWFilterBindingPtr +fakeNWFilterBindingLookupByPortDev(virConnectPtr conn, + const char *portdev) +{ + if (STREQ(portdev, "vhost-user0")) + return virGetNWFilterBinding(conn, "fake_vnet0", "fakeFilterName"); + + virReportError(VIR_ERR_NO_NWFILTER_BINDING, + "no nwfilter binding for port dev '%s'", portdev); + return NULL; +} + + +static int +fakeNWFilterBindingDelete(virNWFilterBindingPtr binding G_GNUC_UNUSED) +{ + return 0; +} + + +static virNWFilterDriver fakeNWFilterDriver = { + .nwfilterBindingLookupByPortDev = fakeNWFilterBindingLookupByPortDev, + .nwfilterBindingDelete = fakeNWFilterBindingDelete, +}; + + +virNWFilterDriver * +testQemuGetFakeNWFilterDriver(void) +{ + return &fakeNWFilterDriver; +} + + +/* name of the fake network shall be constructed as: + * NETWORKXMLNAME;NETWORKPORTXMLNAME + * where: + * NETWORKXMLNAME resolves to abs_srcdir/networkxmlconfdata/NETWORKXMLNAME.xml + * NETWORKPORTXMLNAME resolves to abs_srcdir/virnetworkportxml2xmldata/NETWORKPORTXMLNAME.xml + */ +static virNetworkPtr +fakeNetworkLookupByName(virConnectPtr conn, + const char *name) +{ + unsigned char uuid[VIR_UUID_BUFLEN]; + g_autofree char *netname = g_strdup(name); + g_autofree char *path = NULL; + char *tmp; + + memset(uuid, 0, VIR_UUID_BUFLEN); + + if ((tmp = strchr(netname, ';'))) { + *tmp = '\0'; + } else { + virReportError(VIR_ERR_NO_NETWORK, + "Malformed fake network name '%s'. See fakeNetworkLookupByName.", + name); + return NULL; + } + + path = g_strdup_printf(abs_srcdir "/networkxmlconfdata/%s.xml", netname); + + if (!virFileExists(path)) { + virReportError(VIR_ERR_NO_NETWORK, "fake network '%s' not found", path); + return NULL; + } + + return virGetNetwork(conn, name, uuid); +} + + +static char * +fakeNetworkGetXMLDesc(virNetworkPtr network, + unsigned int noflags G_GNUC_UNUSED) +{ + g_autofree char *netname = g_strdup(network->name); + g_autofree char *path = NULL; + char *xml = NULL; + + *(strchr(netname, ';')) = '\0'; + + path = g_strdup_printf(abs_srcdir "/networkxmlconfdata/%s.xml", netname); + + if (virFileReadAll(path, 4 * 1024, &xml) < 0) + return NULL; + + return xml; +} + + +static virNetworkPortPtr +fakeNetworkPortCreateXML(virNetworkPtr net, + const char *xmldesc G_GNUC_UNUSED, + unsigned int noflags G_GNUC_UNUSED) +{ + unsigned char uuid[VIR_UUID_BUFLEN]; + g_autofree char *portname = g_strdup(strchr(net->name, ';') + 1); + g_autofree char *path = g_strdup_printf(abs_srcdir "/virnetworkportxml2xmldata/%s.xml", portname); + + memset(uuid, 0, VIR_UUID_BUFLEN); + + if (!virFileExists(path)) { + virReportError(VIR_ERR_NO_NETWORK_PORT, "fake network port '%s' not found", path); + return NULL; + } + + return virGetNetworkPort(net, uuid); +} + + +static char * +fakeNetworkPortGetXMLDesc(virNetworkPortPtr port, + unsigned int noflags G_GNUC_UNUSED) +{ + g_autofree char *portname = g_strdup(strchr(port->net->name, ';') + 1); + g_autofree char *path = g_strdup_printf(abs_srcdir "/virnetworkportxml2xmldata/%s.xml", portname); + char *xml = NULL; + + if (virFileReadAll(path, 4 * 1024, &xml) < 0) + return NULL; + + return xml; +} + + +static virNetworkDriver fakeNetworkDriver = { + .networkLookupByName = fakeNetworkLookupByName, + .networkGetXMLDesc = fakeNetworkGetXMLDesc, + .networkPortCreateXML = fakeNetworkPortCreateXML, + .networkPortGetXMLDesc = fakeNetworkPortGetXMLDesc, +}; + + +virNetworkDriver * +testQemuGetFakeNetworkDriver(void) +{ + return &fakeNetworkDriver; +} diff --git a/tests/qemufakedrivers.h b/tests/qemufakedrivers.h new file mode 100644 index 0000000000..172ae48451 --- /dev/null +++ b/tests/qemufakedrivers.h @@ -0,0 +1,19 @@ +/* + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#pragma once + +#include "driver.h" + +virSecretDriver * +testQemuGetFakeSecretDriver(void); + +virStorageDriver * +testQemuGetFakeStorageDriver(void); + +virNWFilterDriver * +testQemuGetFakeNWFilterDriver(void); + +virNetworkDriver * +testQemuGetFakeNetworkDriver(void); diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c index cf147e70d4..32eb42dd19 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -23,6 +23,7 @@ #include "virfilewrapper.h" #include "configmake.h" #include "testutilsqemuschema.h" +#include "qemufakedrivers.h"
#define LIBVIRT_QEMU_CAPSPRIV_H_ALLOW #include "qemu/qemu_capspriv.h" @@ -33,320 +34,6 @@
static virQEMUDriver driver;
-static unsigned char * -fakeSecretGetValue(virSecretPtr obj G_GNUC_UNUSED, - size_t *value_size, - unsigned int fakeflags G_GNUC_UNUSED) -{ - char *secret; - secret = g_strdup("AQCVn5hO6HzFAhAAq0NCv8jtJcIcE+HOBlMQ1A"); - *value_size = strlen(secret); - return (unsigned char *) secret; -} - -static virSecretPtr -fakeSecretLookupByUsage(virConnectPtr conn, - int usageType, - const char *usageID) -{ - unsigned char uuid[VIR_UUID_BUFLEN]; - if (usageType == VIR_SECRET_USAGE_TYPE_VOLUME) { - if (!STRPREFIX(usageID, "/storage/guest_disks/")) { - virReportError(VIR_ERR_INTERNAL_ERROR, - "test provided invalid volume storage prefix '%s'", - usageID); - return NULL; - } - } else if (STRNEQ(usageID, "mycluster_myname") && - STRNEQ(usageID, "client.admin secret")) { - virReportError(VIR_ERR_INTERNAL_ERROR, - "test provided incorrect usage '%s'", usageID); - return NULL; - } - - if (virUUIDGenerate(uuid) < 0) - return NULL; - - return virGetSecret(conn, uuid, usageType, usageID); -} - -static virSecretPtr -fakeSecretLookupByUUID(virConnectPtr conn, - const unsigned char *uuid) -{ - /* NB: This mocked value could be "tls" or "volume" depending on - * which test is being run, we'll leave at NONE (or 0) */ - return virGetSecret(conn, uuid, VIR_SECRET_USAGE_TYPE_NONE, ""); -} - -static virSecretDriver fakeSecretDriver = { - .connectNumOfSecrets = NULL, - .connectListSecrets = NULL, - .secretLookupByUUID = fakeSecretLookupByUUID, - .secretLookupByUsage = fakeSecretLookupByUsage, - .secretDefineXML = NULL, - .secretGetXMLDesc = NULL, - .secretSetValue = NULL, - .secretGetValue = fakeSecretGetValue, - .secretUndefine = NULL, -}; - - -#define STORAGE_POOL_XML_PATH "storagepoolxml2xmlout/" -static const unsigned char fakeUUID[VIR_UUID_BUFLEN] = "fakeuuid"; - -static virStoragePoolPtr -fakeStoragePoolLookupByName(virConnectPtr conn, - const char *name) -{ - g_autofree char *xmlpath = NULL; - - if (STRNEQ(name, "inactive")) { - xmlpath = g_strdup_printf("%s/%s%s.xml", abs_srcdir, - STORAGE_POOL_XML_PATH, name); - - if (!virFileExists(xmlpath)) { - virReportError(VIR_ERR_NO_STORAGE_POOL, - "File '%s' not found", xmlpath); - return NULL; - } - } - - return virGetStoragePool(conn, name, fakeUUID, NULL, NULL); -} - - -static virStorageVolPtr -fakeStorageVolLookupByName(virStoragePoolPtr pool, - const char *name) -{ - g_auto(GStrv) volinfo = NULL; - - if (STREQ(pool->name, "inactive")) { - virReportError(VIR_ERR_OPERATION_INVALID, - "storage pool '%s' is not active", pool->name); - return NULL; - } - - if (STREQ(name, "nonexistent")) { - virReportError(VIR_ERR_NO_STORAGE_VOL, - "no storage vol with matching name '%s'", name); - return NULL; - } - - if (!(volinfo = g_strsplit(name, "+", 2))) - return NULL; - - if (!volinfo[1]) { - return virGetStorageVol(pool->conn, pool->name, name, "block", NULL, NULL); - } - - return virGetStorageVol(pool->conn, pool->name, volinfo[1], volinfo[0], - NULL, NULL); -} - -static int -fakeStorageVolGetInfo(virStorageVolPtr vol, - virStorageVolInfoPtr info) -{ - memset(info, 0, sizeof(*info)); - - info->type = virStorageVolTypeFromString(vol->key); - - if (info->type < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - "Invalid volume type '%s'", vol->key); - return -1; - } - - return 0; -} - - -static char * -fakeStorageVolGetPath(virStorageVolPtr vol) -{ - return g_strdup_printf("/some/%s/device/%s", vol->key, vol->name); -} - - -static char * -fakeStoragePoolGetXMLDesc(virStoragePoolPtr pool, - unsigned int flags_unused G_GNUC_UNUSED) -{ - g_autofree char *xmlpath = NULL; - char *xmlbuf = NULL; - - if (STREQ(pool->name, "inactive")) { - virReportError(VIR_ERR_NO_STORAGE_POOL, NULL); - return NULL; - } - - xmlpath = g_strdup_printf("%s/%s%s.xml", abs_srcdir, STORAGE_POOL_XML_PATH, - pool->name); - - if (virTestLoadFile(xmlpath, &xmlbuf) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - "failed to load XML file '%s'", - xmlpath); - return NULL; - } - - return xmlbuf; -} - -static int -fakeStoragePoolIsActive(virStoragePoolPtr pool) -{ - if (STREQ(pool->name, "inactive")) - return 0; - - return 1; -} - -/* Test storage pool implementation - * - * These functions aid testing of storage pool related stuff when creating a - * qemu command line. - * - * There are a few "magic" values to pass to these functions: - * - * 1) "inactive" as a pool name to create an inactive pool. All other names are - * interpreted as file names in storagepoolxml2xmlout/ and are used as the - * definition for the pool. If the file doesn't exist the pool doesn't exist. - * - * 2) "nonexistent" returns an error while looking up a volume. Otherwise - * pattern VOLUME_TYPE+VOLUME_PATH can be used to simulate a volume in a pool. - * This creates a fake path for this volume. If the '+' sign is omitted, block - * type is assumed. - */ -static virStorageDriver fakeStorageDriver = { - .storagePoolLookupByName = fakeStoragePoolLookupByName, - .storageVolLookupByName = fakeStorageVolLookupByName, - .storagePoolGetXMLDesc = fakeStoragePoolGetXMLDesc, - .storageVolGetPath = fakeStorageVolGetPath, - .storageVolGetInfo = fakeStorageVolGetInfo, - .storagePoolIsActive = fakeStoragePoolIsActive, -}; - - -/* virNetDevOpenvswitchGetVhostuserIfname mocks a portdev name - handle that */ -static virNWFilterBindingPtr -fakeNWFilterBindingLookupByPortDev(virConnectPtr conn, - const char *portdev) -{ - if (STREQ(portdev, "vhost-user0")) - return virGetNWFilterBinding(conn, "fake_vnet0", "fakeFilterName"); - - virReportError(VIR_ERR_NO_NWFILTER_BINDING, - "no nwfilter binding for port dev '%s'", portdev); - return NULL; -} - - -static int -fakeNWFilterBindingDelete(virNWFilterBindingPtr binding G_GNUC_UNUSED) -{ - return 0; -} - - -static virNWFilterDriver fakeNWFilterDriver = { - .nwfilterBindingLookupByPortDev = fakeNWFilterBindingLookupByPortDev, - .nwfilterBindingDelete = fakeNWFilterBindingDelete, -}; - - -/* name of the fake network shall be constructed as: - * NETWORKXMLNAME;NETWORKPORTXMLNAME - * where: - * NETWORKXMLNAME resolves to abs_srcdir/networkxmlconfdata/NETWORKXMLNAME.xml - * NETWORKPORTXMLNAME resolves to abs_srcdir/virnetworkportxml2xmldata/NETWORKPORTXMLNAME.xml - */ -static virNetworkPtr -fakeNetworkLookupByName(virConnectPtr conn, - const char *name) -{ - unsigned char uuid[VIR_UUID_BUFLEN]; - g_autofree char *netname = g_strdup(name); - g_autofree char *path = NULL; - char *tmp; - - memset(uuid, 0, VIR_UUID_BUFLEN); - - if ((tmp = strchr(netname, ';'))) { - *tmp = '\0'; - } else { - virReportError(VIR_ERR_NO_NETWORK, - "Malformed fake network name '%s'. See fakeNetworkLookupByName.", - name); - return NULL; - } - - path = g_strdup_printf(abs_srcdir "/networkxmlconfdata/%s.xml", netname); - - if (!virFileExists(path)) { - virReportError(VIR_ERR_NO_NETWORK, "fake network '%s' not found", path); - return NULL; - } - - return virGetNetwork(conn, name, uuid); -} - - -static char * -fakeNetworkGetXMLDesc(virNetworkPtr network, - unsigned int noflags G_GNUC_UNUSED) -{ - g_autofree char *netname = g_strdup(network->name); - g_autofree char *path = NULL; - char *xml = NULL; - - *(strchr(netname, ';')) = '\0'; - - path = g_strdup_printf(abs_srcdir "/networkxmlconfdata/%s.xml", netname); - - if (virFileReadAll(path, 4 * 1024, &xml) < 0) - return NULL; - - return xml; -} - - -static virNetworkPortPtr -fakeNetworkPortCreateXML(virNetworkPtr net, - const char *xmldesc G_GNUC_UNUSED, - unsigned int noflags G_GNUC_UNUSED) -{ - unsigned char uuid[VIR_UUID_BUFLEN]; - g_autofree char *portname = g_strdup(strchr(net->name, ';') + 1); - g_autofree char *path = g_strdup_printf(abs_srcdir "/virnetworkportxml2xmldata/%s.xml", portname); - - memset(uuid, 0, VIR_UUID_BUFLEN); - - if (!virFileExists(path)) { - virReportError(VIR_ERR_NO_NETWORK_PORT, "fake network port '%s' not found", path); - return NULL; - } - - return virGetNetworkPort(net, uuid); -} - - -static char * -fakeNetworkPortGetXMLDesc(virNetworkPortPtr port, - unsigned int noflags G_GNUC_UNUSED) -{ - g_autofree char *portname = g_strdup(strchr(port->net->name, ';') + 1); - g_autofree char *path = g_strdup_printf(abs_srcdir "/virnetworkportxml2xmldata/%s.xml", portname); - char *xml = NULL; - - if (virFileReadAll(path, 4 * 1024, &xml) < 0) - return NULL; - - return xml; -} -
static void testQemuPrepareHostdevPCI(virDomainHostdevDef *hostdev) @@ -418,14 +105,6 @@ testQemuPrepareHostdev(virDomainObj *vm) }
-static virNetworkDriver fakeNetworkDriver = { - .networkLookupByName = fakeNetworkLookupByName, - .networkGetXMLDesc = fakeNetworkGetXMLDesc, - .networkPortCreateXML = fakeNetworkPortCreateXML, - .networkPortGetXMLDesc = fakeNetworkPortGetXMLDesc, -}; - - static void testUpdateQEMUCapsHostCPUModel(virQEMUCaps *qemuCaps, virArch hostArch) { @@ -1273,10 +952,10 @@ mymain(void) if (!(conn = virGetConnect())) return EXIT_FAILURE;
- conn->secretDriver = &fakeSecretDriver; - conn->storageDriver = &fakeStorageDriver; - conn->nwfilterDriver = &fakeNWFilterDriver; - conn->networkDriver = &fakeNetworkDriver; + conn->secretDriver = testQemuGetFakeSecretDriver(); + conn->storageDriver = testQemuGetFakeStorageDriver(); + conn->nwfilterDriver = testQemuGetFakeNWFilterDriver(); + conn->networkDriver = testQemuGetFakeNetworkDriver();
virSetConnectInterface(conn); virSetConnectNetwork(conn);
From: Michal Privoznik <mprivozn@redhat.com> Inside of plug-hostdev-pci.xml there's a PCI address of an allocated PCI device for an <interface type='network'/>. Currently, there's some made up address. But this specific file is going to be used from qemuhotplugtest soon and as such it needs an PCI address that virpcimock creates. Switch it to 0000:06:12.2. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- .../net-virtio-teaming-network.x86_64-latest.args | 2 +- tests/virnetworkportxml2xmldata/plug-hostdev-pci.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/qemuxmlconfdata/net-virtio-teaming-network.x86_64-latest.args b/tests/qemuxmlconfdata/net-virtio-teaming-network.x86_64-latest.args index 0c07ec4c70..a3dada0f07 100644 --- a/tests/qemuxmlconfdata/net-virtio-teaming-network.x86_64-latest.args +++ b/tests/qemuxmlconfdata/net-virtio-teaming-network.x86_64-latest.args @@ -32,7 +32,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ -netdev '{"type":"tap","fd":"102","vhost":true,"vhostfd":"44","id":"hostua-backup0"}' \ -device '{"driver":"virtio-net-pci","failover":true,"netdev":"hostua-backup0","id":"ua-backup0","mac":"00:11:22:33:44:55","bus":"pci.0","addr":"0x2"}' \ -audiodev '{"id":"audio1","driver":"none"}' \ --device '{"driver":"vfio-pci","host":"0001:02:03.4","id":"hostdev0","failover_pair_id":"ua-backup0","bus":"pci.0","addr":"0x3"}' \ +-device '{"driver":"vfio-pci","host":"0000:06:12.2","id":"hostdev0","failover_pair_id":"ua-backup0","bus":"pci.0","addr":"0x3"}' \ -device '{"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.0","addr":"0x4"}' \ -sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ -msg timestamp=on diff --git a/tests/virnetworkportxml2xmldata/plug-hostdev-pci.xml b/tests/virnetworkportxml2xmldata/plug-hostdev-pci.xml index 7354e1d48c..8b058d9244 100644 --- a/tests/virnetworkportxml2xmldata/plug-hostdev-pci.xml +++ b/tests/virnetworkportxml2xmldata/plug-hostdev-pci.xml @@ -6,6 +6,6 @@ </owner> <mac address='52:54:00:7b:35:93'/> <plug type='hostdev-pci' managed='yes'> - <address domain='0x0001' bus='0x02' slot='0x03' function='0x4'/> + <address domain='0x0000' bus='0x06' slot='0x12' function='0x2'/> </plug> </networkport> -- 2.52.0
From: Michal Privoznik <mprivozn@redhat.com> Hotplugging a device may require talking to other drivers (e.g. network), similar to when starting a domain anew (qemuxmlconftest). Register fake drivers for future benefit of the test. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- tests/qemuhotplugtest.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/qemuhotplugtest.c b/tests/qemuhotplugtest.c index 146e9e33c1..ae29f47c16 100644 --- a/tests/qemuhotplugtest.c +++ b/tests/qemuhotplugtest.c @@ -28,6 +28,7 @@ #include "testutilsqemuschema.h" #include "virhostdev.h" #include "virfile.h" +#include "qemufakedrivers.h" #define LIBVIRT_QEMU_CAPSPRIV_H_ALLOW #include "qemu/qemu_capspriv.h" @@ -483,6 +484,7 @@ static int mymain(void) { int ret = 0; + g_autoptr(virConnect) conn = NULL; g_autoptr(virQEMUDriverConfig) cfg = NULL; g_autoptr(GHashTable) capsLatestFiles = testQemuGetLatestCaps(); g_autoptr(GHashTable) capsCache = virHashNew(virObjectUnref); @@ -499,6 +501,20 @@ mymain(void) cfg = virQEMUDriverGetConfig(&driver); + if (!(conn = virGetConnect())) + return EXIT_FAILURE; + + conn->secretDriver = testQemuGetFakeSecretDriver(); + conn->storageDriver = testQemuGetFakeStorageDriver(); + conn->nwfilterDriver = testQemuGetFakeNWFilterDriver(); + conn->networkDriver = testQemuGetFakeNetworkDriver(); + + virSetConnectInterface(conn); + virSetConnectNetwork(conn); + virSetConnectNWFilter(conn); + virSetConnectNodeDev(conn); + virSetConnectSecret(conn); + virSetConnectStorage(conn); virEventRegisterDefaultImpl(); driver.lockManager = virLockManagerPluginNew("nop", "qemu", -- 2.52.0
From: Michal Privoznik <mprivozn@redhat.com> Inspired by commit of v12.1.0-37-g25662b3700. We already have a test case for <interface type='hostdev'/>, but what we are missing is <interface type='network'/> where the network is of a <forward mode='hostdev'/>. Apparently, we had a crasher there too. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- tests/qemuhotplugtest.c | 4 ++ .../qemuhotplug-interface-network-hostdev.xml | 4 ++ ...ug-base-live+interface-network-hostdev.xml | 63 +++++++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 tests/qemuhotplugtestdevices/qemuhotplug-interface-network-hostdev.xml create mode 100644 tests/qemuhotplugtestdomains/qemuhotplug-base-live+interface-network-hostdev.xml diff --git a/tests/qemuhotplugtest.c b/tests/qemuhotplugtest.c index ae29f47c16..ea9d3243f8 100644 --- a/tests/qemuhotplugtest.c +++ b/tests/qemuhotplugtest.c @@ -724,6 +724,10 @@ mymain(void) "device_add", QMP_OK); DO_TEST_DETACH("x86_64", "base-live", "interface-hostdev", false, false, "device_del", QMP_DEVICE_DELETED("hostdev0") QMP_OK); + DO_TEST_ATTACH("x86_64", "base-live", "interface-network-hostdev", false, true, + "device_add", QMP_OK); + DO_TEST_DETACH("x86_64", "base-live", "interface-network-hostdev", false, false, + "device_del", QMP_DEVICE_DELETED("hostdev0") QMP_OK); #endif DO_TEST_ATTACH("x86_64", "base-live", "interface-vdpa", false, true, "query-fdsets", "{\"return\":[{\"fdset-id\":99999}]}", diff --git a/tests/qemuhotplugtestdevices/qemuhotplug-interface-network-hostdev.xml b/tests/qemuhotplugtestdevices/qemuhotplug-interface-network-hostdev.xml new file mode 100644 index 0000000000..b4324126d8 --- /dev/null +++ b/tests/qemuhotplugtestdevices/qemuhotplug-interface-network-hostdev.xml @@ -0,0 +1,4 @@ +<interface type='network'> + <mac address='52:54:00:7b:35:93'/> + <source network='hostdev;plug-hostdev-pci'/> +</interface> diff --git a/tests/qemuhotplugtestdomains/qemuhotplug-base-live+interface-network-hostdev.xml b/tests/qemuhotplugtestdomains/qemuhotplug-base-live+interface-network-hostdev.xml new file mode 100644 index 0000000000..6775fdc3f3 --- /dev/null +++ b/tests/qemuhotplugtestdomains/qemuhotplug-base-live+interface-network-hostdev.xml @@ -0,0 +1,63 @@ +<domain type='kvm' id='7'> + <name>hotplug</name> + <uuid>d091ea82-29e6-2e34-3005-f02617b36e87</uuid> + <memory unit='KiB'>4194304</memory> + <currentMemory unit='KiB'>4194304</currentMemory> + <vcpu placement='static'>4</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='usb' index='0' model='piix3-uhci'> + <alias name='usb'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='ide' index='0'> + <alias name='ide'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='scsi' index='0' model='virtio-scsi'> + <alias name='scsi0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </controller> + <controller type='pci' index='0' model='pci-root'> + <alias name='pci'/> + </controller> + <controller type='virtio-serial' index='0'> + <alias name='virtio-serial0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + </controller> + <interface type='hostdev' managed='yes'> + <mac address='52:54:00:7b:35:93'/> + <driver name='vfio'/> + <source> + <address type='pci' domain='0x0000' bus='0x06' slot='0x12' function='0x2'/> + </source> + <alias name='hostdev0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </interface> + <input type='mouse' bus='ps2'> + <alias name='input0'/> + </input> + <input type='keyboard' bus='ps2'> + <alias name='input1'/> + </input> + <audio id='1' type='none'/> + <memballoon model='none'/> + </devices> + <seclabel type='none' model='none'/> +</domain> -- 2.52.0
Reviewed-by: Laine Stump <laine@redhat.com> for the series. On 3/12/26 3:57 AM, Michal Privoznik via Devel wrote:
*** BLURB HERE ***
Michal Prívozník (5): tests: Drop WITH_QEMU from qemu specific tests binaries/libraries qemuxmlconftest: Separate fake drivers into a separate file virnetworkportxml2xmldata: Use different PCI address in plug-hostdev-pci.xml qemuhotplugtest: Use fake drivers qemuhotplug: Introduce interface-network-hostdev
tests/meson.build | 5 +- tests/qemudomaincheckpointxml2xmltest.c | 31 +- tests/qemudomainsnapshotxml2xmltest.c | 29 +- tests/qemufakedrivers.c | 368 +++++++++++++++ tests/qemufakedrivers.h | 19 + tests/qemuhotplugtest.c | 20 + .../qemuhotplug-interface-network-hostdev.xml | 4 + ...ug-base-live+interface-network-hostdev.xml | 63 +++ tests/qemumemlocktest.c | 25 +- ...-virtio-teaming-network.x86_64-latest.args | 2 +- tests/qemuxmlconftest.c | 443 +++--------------- tests/testutilsqemu.c | 43 +- tests/testutilsqemu.h | 23 +- .../plug-hostdev-pci.xml | 2 +- 14 files changed, 588 insertions(+), 489 deletions(-) create mode 100644 tests/qemufakedrivers.c create mode 100644 tests/qemufakedrivers.h create mode 100644 tests/qemuhotplugtestdevices/qemuhotplug-interface-network-hostdev.xml create mode 100644 tests/qemuhotplugtestdomains/qemuhotplug-base-live+interface-network-hostdev.xml
participants (2)
-
Laine Stump -
Michal Privoznik