Extract the common setup and parsing of the input XML into a separate
helper testQemuConfXMLCommon(). The helper has semantics which will
allow us to call it from multiple places so that VIR_TEST_RANGE will
still work properly even when we'll add multiple steps reusing the
prepared data.
Signed-off-by: Peter Krempa <pkrempa(a)redhat.com>
---
tests/qemuxml2argvtest.c | 170 +++++++++++++++++++++++++++++----------
tests/testutilsqemu.h | 6 ++
2 files changed, 133 insertions(+), 43 deletions(-)
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 8b0d4e560e..6552c7f9c2 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -599,23 +599,37 @@ testInfoCheckDuplicate(testQemuInfo *info)
}
-static int
-testCompareXMLToArgv(const void *data)
+/**
+ * testQemuConfXMLCommon: Prepare common test data (e.g. parse input XML)
+ * for a test case.
+ *
+ * @info: test info struct to prepare
+ * @rv: return value that the caller is supposed to return (see below)
+ *
+ * Since some of the prepared data is reused by multiple tests, which can be
+ * potentially skipped via 'VIR_TEST_RANGE', this function is designed to be
+ * callable multiple times but processes data just once.
+ *
+ * Returns 'true' if subsequent tests are expected to run (input XML was parsed
+ * properly and test is not expected to fail on parse error). Otherwise 'false'
+ * is returned and rv is populated according to the following logic:
+ * 1) expected failure of parsing (FLAG_EXPECT_PARSE_ERROR)
+ * - first invocation sets @rv to 0
+ * - other invocations set rv to EXIT_AM_SKIP
+ * 2) unexpected error
+ * - all invocations return -1
+ * - first invocation reports actual error
+ * - other invocations report replacement error
+ */
+static bool
+testQemuConfXMLCommon(testQemuInfo *info,
+ int *rv)
{
- testQemuInfo *info = (void *) data;
- g_autofree char *migrateURI = NULL;
- g_auto(virBuffer) actualBuf = VIR_BUFFER_INITIALIZER;
- g_autofree char *actualargv = NULL;
- unsigned int flags = info->flags;
- unsigned int parseFlags = info->parseFlags;
- int ret = -1;
- virDomainObj *vm = NULL;
- virDomainChrSourceDef monitor_chr = { 0 };
- virError *err = NULL;
- g_autofree char *log = NULL;
- g_autoptr(virCommand) cmd = NULL;
- qemuDomainObjPrivate *priv = NULL;
- g_autoptr(virIdentity) sysident = virIdentityGetSystem();
+ g_autoptr(virDomainDef) def = NULL;
+
+ /* initialize a test just once */
+ if (info->prepared)
+ goto cleanup;
/* mark test case as used */
ignore_value(g_hash_table_remove(info->conf->existingTestCases,
info->infile));
@@ -645,9 +659,6 @@ testCompareXMLToArgv(const void *data)
testUpdateQEMUCapsHostCPUModel(info->qemuCaps, driver.hostarch);
}
- if (virIdentitySetCurrent(sysident) < 0)
- goto cleanup;
-
if (testCheckExclusiveFlags(info->flags) < 0)
goto cleanup;
@@ -656,47 +667,111 @@ testCompareXMLToArgv(const void *data)
if (qemuTestCapsCacheInsert(driver.qemuCapsCache, info->qemuCaps) < 0)
goto cleanup;
- if (info->nbdkitCaps) {
- if (virFileCacheInsertData(driver.nbdkitCapsCache, TEST_NBDKIT_PATH,
- g_object_ref(info->nbdkitCaps)) < 0) {
- g_object_unref(info->nbdkitCaps);
- goto cleanup;
- }
- }
-
- if (info->migrateFrom &&
- !(migrateURI = qemuMigrationDstGetURI(info->migrateFrom,
- info->migrateFd)))
- goto cleanup;
-
- if (!(vm = virDomainObjNew(driver.xmlopt)))
- goto cleanup;
-
if (!virFileExists(info->infile)) {
virReportError(VIR_ERR_INTERNAL_ERROR,
"Input file '%s' not found", info->infile);
goto cleanup;
}
- parseFlags |= VIR_DOMAIN_DEF_PARSE_INACTIVE;
+ if (!(def = virDomainDefParseFile(info->infile, driver.xmlopt, NULL,
+ info->parseFlags |
VIR_DOMAIN_DEF_PARSE_INACTIVE))) {
+ virError *err = virGetLastError();
- if (!(vm->def = virDomainDefParseFile(info->infile, driver.xmlopt, NULL,
parseFlags))) {
- err = virGetLastError();
if (!err) {
VIR_TEST_DEBUG("no error was reported for expected parse error");
goto cleanup;
}
- if (flags & FLAG_EXPECT_PARSE_ERROR) {
+
+ if (info->flags & FLAG_EXPECT_PARSE_ERROR) {
g_autofree char *tmperr = g_strdup_printf("%s\n",
NULLSTR(err->message));
- if (virTestCompareToFile(tmperr, info->errfile) >= 0)
- goto ok;
+ if (virTestCompareToFile(tmperr, info->errfile) >= 0) {
+ info->prep_skip = true;
+ }
}
+
goto cleanup;
}
- if (flags & FLAG_EXPECT_PARSE_ERROR) {
+
+ if (info->flags & FLAG_EXPECT_PARSE_ERROR) {
VIR_TEST_DEBUG("passed instead of expected parse error");
goto cleanup;
}
+
+ info->def = g_steal_pointer(&def);
+
+ cleanup:
+ /* definition is present and correct, return true to signal that caller can continue
*/
+ if (info->def) {
+ info->prepared = true;
+ return true;
+ }
+
+ /* definition is not present, but failure was expected */
+ if (info->prep_skip) {
+ /* first time we report success, any subsequent time EXIT_AM_SKIP */
+ if (!info->prepared)
+ *rv = 0;
+ else
+ *rv = EXIT_AM_SKIP;
+ } else {
+ /* any other failure always results in error in all invocations
+ * so that the user will see all the failures in the final error
+ * message which is suggesting a VIR_TEST_RANGE-limited run for
+ * debugging. */
+ *rv = -1;
+
+ /* report replacement error on subsequent runs */
+ if (!info->prepared)
+ VIR_TEST_VERBOSE("error from testQemuConfXMLCommon() was reported in the
first invocation");
+ }
+
+ info->prepared = true;
+ /* caller is not expected to run tests */
+ return false;
+}
+
+
+static int
+testCompareXMLToArgv(const void *data)
+{
+ testQemuInfo *info = (void *) data;
+ g_autofree char *migrateURI = NULL;
+ g_auto(virBuffer) actualBuf = VIR_BUFFER_INITIALIZER;
+ g_autofree char *actualargv = NULL;
+ unsigned int flags = info->flags;
+ int ret = -1;
+ virDomainObj *vm = NULL;
+ virDomainChrSourceDef monitor_chr = { 0 };
+ virError *err = NULL;
+ g_autofree char *log = NULL;
+ g_autoptr(virCommand) cmd = NULL;
+ qemuDomainObjPrivate *priv = NULL;
+ g_autoptr(virIdentity) sysident = virIdentityGetSystem();
+ int rc = 0;
+
+ if (!testQemuConfXMLCommon(info, &rc))
+ return rc;
+
+ if (virIdentitySetCurrent(sysident) < 0)
+ goto cleanup;
+
+ if (info->nbdkitCaps) {
+ if (virFileCacheInsertData(driver.nbdkitCapsCache, TEST_NBDKIT_PATH,
+ g_object_ref(info->nbdkitCaps)) < 0) {
+ g_object_unref(info->nbdkitCaps);
+ goto cleanup;
+ }
+ }
+
+ if (info->migrateFrom &&
+ !(migrateURI = qemuMigrationDstGetURI(info->migrateFrom,
+ info->migrateFd)))
+ goto cleanup;
+
+ if (!(vm = virDomainObjNew(driver.xmlopt)))
+ goto cleanup;
+
+ vm->def = info->def;
priv = vm->privateData;
if (info->args.fds) {
@@ -770,7 +845,10 @@ testCompareXMLToArgv(const void *data)
if (info->args.capsHostCPUModel)
qemuTestSetHostCPU(&driver, driver.hostarch, NULL);
virDomainChrSourceDefClear(&monitor_chr);
- virObjectUnref(vm);
+ if (vm) {
+ vm->def = NULL;
+ virObjectUnref(vm);
+ }
virIdentitySetCurrent(NULL);
if (info->arch != VIR_ARCH_NONE && info->arch != VIR_ARCH_X86_64)
qemuTestSetHostArch(&driver, VIR_ARCH_NONE);
@@ -848,6 +926,12 @@ testRun(const char *name,
info->errfile = g_strdup_printf("%s/qemuxml2argvdata/%s%s.err",
abs_srcdir, info->name, suffix);
virTestRunLog(ret, testname, testCompareXMLToArgv, info);
+
+ /* clear overriden host cpu */
+ if (info->args.capsHostCPUModel)
+ qemuTestSetHostCPU(&driver, driver.hostarch, NULL);
+ if (info->arch != VIR_ARCH_NONE && info->arch != VIR_ARCH_X86_64)
+ qemuTestSetHostArch(&driver, VIR_ARCH_NONE);
}
diff --git a/tests/testutilsqemu.h b/tests/testutilsqemu.h
index 011a5993f8..89148bd529 100644
--- a/tests/testutilsqemu.h
+++ b/tests/testutilsqemu.h
@@ -112,6 +112,12 @@ struct _testQemuInfo {
virArch arch;
GHashTable *qmpSchema; /* borrowed pointer from the cache */
+ /* Some tests have a common prepare step for multiple cases, but
+ * the common setup needs to be invoked with each virTestRun to facilitate
+ * test skipping */
+ bool prepared;
+ bool prep_skip;
+
struct testQemuArgs args;
struct testQemuConf *conf;
};
--
2.43.0