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@xxxxxxxxxx> --- 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 _______________________________________________ Devel mailing list -- devel@xxxxxxxxxxxxxxxxx To unsubscribe send an email to devel-leave@xxxxxxxxxxxxxxxxx