[PATCH v2 0/3] qemuxmlconftest: Add test cases for broken and missing XML files

Patch 3/3 adds the actual test: Changes to v1: - fixed missing NULL termination of the 'skip' array - "backported" g_string_replace into glibcompat.c until we bump minimum glib - started striping 'abs_srcdir' strings from qemuxmlconftest's '.err' output files Peter Krempa (3): glibcompat: "Backport" 'g_string_replace' testQemuConfXMLCommon: Strip 'abs_srcdir' paths from '.err' files in qemuxmlconftest qemuxmlconftest: Add test cases for broken and missing XML files src/libvirt_private.syms | 1 + src/util/glibcompat.c | 65 +++++++++++++++++++ src/util/glibcompat.h | 10 +++ .../broken-xml-invalid.x86_64-latest.err | 3 + tests/qemuxmlconfdata/broken-xml-invalid.xml | 1 + .../nonexistent-file.x86_64-latest.err | 1 + tests/qemuxmlconftest.c | 16 ++++- tests/testutilsqemu.h | 1 + tests/virschematest.c | 12 ++++ 9 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 tests/qemuxmlconfdata/broken-xml-invalid.x86_64-latest.err create mode 100644 tests/qemuxmlconfdata/broken-xml-invalid.xml create mode 100644 tests/qemuxmlconfdata/nonexistent-file.x86_64-latest.err -- 2.45.2

Backport the implementation of 'g_string_replace' until we require at least glib-2.68 Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/libvirt_private.syms | 1 + src/util/glibcompat.c | 65 ++++++++++++++++++++++++++++++++++++++++ src/util/glibcompat.h | 10 +++++++ 3 files changed, 76 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index d15d6a6a9d..0accca442a 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1864,6 +1864,7 @@ vir_g_fsync; vir_g_source_unref; vir_g_strdup_printf; vir_g_strdup_vprintf; +vir_g_string_replace; # util/viracpi.c diff --git a/src/util/glibcompat.c b/src/util/glibcompat.c index d8912b323b..98dcfab389 100644 --- a/src/util/glibcompat.c +++ b/src/util/glibcompat.c @@ -155,3 +155,68 @@ void vir_g_source_unref(GSource *src, GMainContext *ctx) } #endif + + +/** + * Adapted (to pass syntax check) from 'g_string_replace' from + * glib-2.81.1. Drop once minimum glib is bumped to 2.68. + * + * g_string_replace: + * @string: a #GString + * @find: the string to find in @string + * @replace: the string to insert in place of @find + * @limit: the maximum instances of @find to replace with @replace, or `0` for + * no limit + * + * Replaces the string @find with the string @replace in a #GString up to + * @limit times. If the number of instances of @find in the #GString is + * less than @limit, all instances are replaced. If @limit is `0`, + * all instances of @find are replaced. + * + * If @find is the empty string, since versions 2.69.1 and 2.68.4 the + * replacement will be inserted no more than once per possible position + * (beginning of string, end of string and between characters). This did + * not work correctly in earlier versions. + * + * Returns: the number of find and replace operations performed. + * + * Since: 2.68 + */ +guint +vir_g_string_replace(GString *string, + const gchar *find, + const gchar *replace, + guint limit) +{ + gsize f_len, r_len, pos; + gchar *cur, *next; + guint n = 0; + + g_return_val_if_fail(string != NULL, 0); + g_return_val_if_fail(find != NULL, 0); + g_return_val_if_fail(replace != NULL, 0); + + f_len = strlen(find); + r_len = strlen(replace); + cur = string->str; + + while ((next = strstr(cur, find)) != NULL) { + pos = next - string->str; + g_string_erase(string, pos, f_len); + g_string_insert(string, pos, replace); + cur = string->str + pos + r_len; + n++; + /* Only match the empty string once at any given position, to + * avoid infinite loops */ + if (f_len == 0) { + if (cur[0] == '\0') + break; + else + cur++; + } + if (n == limit) + break; + } + + return n; +} diff --git a/src/util/glibcompat.h b/src/util/glibcompat.h index 2542b4d5dc..3518023a41 100644 --- a/src/util/glibcompat.h +++ b/src/util/glibcompat.h @@ -85,6 +85,16 @@ char *vir_g_strdup_vprintf(const char *msg, va_list args) void vir_g_source_unref(GSource *src, GMainContext *ctx); + +/* Drop once we require glib-2.68 at minimum */ +guint +vir_g_string_replace(GString *string, + const gchar *find, + const gchar *replace, + guint limit); +#undef g_string_replace +#define g_string_replace vir_g_string_replace + #if !GLIB_CHECK_VERSION(2, 73, 2) # if (defined(__has_attribute) && __has_attribute(__noinline__)) || G_GNUC_CHECK_VERSION (2, 96) # if defined (__cplusplus) && __cplusplus >= 201103L -- 2.45.2

Upcoming patch will result in having the build directory path in some of the output files. Replace it by a constant 'ABS_SRCDIR' to avoild breaking tests. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- tests/qemuxmlconftest.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c index 7e47c78150..5fe69db15f 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -687,8 +687,12 @@ testQemuConfXMLCommon(testQemuInfo *info, } 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) { + g_autoptr(GString) errstr = g_string_new(NULLSTR(err->message)); + + g_string_replace(errstr, abs_srcdir, "ABS_SRCDIR", 0); + g_string_append_c(errstr, '\n'); + + if (virTestCompareToFile(errstr->str, info->errfile) >= 0) { info->prep_skip = true; } } -- 2.45.2

Add test cases for few edge cases which excercise the XML reporting from libxml2 in anticipation of upcoming changes of behaviour. 'virschematest' must skip parsing of the broken file altogether so this patch adds infrastructure to allow that. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- .../broken-xml-invalid.x86_64-latest.err | 3 +++ tests/qemuxmlconfdata/broken-xml-invalid.xml | 1 + .../nonexistent-file.x86_64-latest.err | 1 + tests/qemuxmlconftest.c | 8 +++++++- tests/testutilsqemu.h | 1 + tests/virschematest.c | 12 ++++++++++++ 6 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxmlconfdata/broken-xml-invalid.x86_64-latest.err create mode 100644 tests/qemuxmlconfdata/broken-xml-invalid.xml create mode 100644 tests/qemuxmlconfdata/nonexistent-file.x86_64-latest.err diff --git a/tests/qemuxmlconfdata/broken-xml-invalid.x86_64-latest.err b/tests/qemuxmlconfdata/broken-xml-invalid.x86_64-latest.err new file mode 100644 index 0000000000..35a1801371 --- /dev/null +++ b/tests/qemuxmlconfdata/broken-xml-invalid.x86_64-latest.err @@ -0,0 +1,3 @@ +ABS_SRCDIR/qemuxmlconfdata/broken-xml-invalid.xml:2: Couldn't find end of Start Tag dom line 1 +(null) +^ diff --git a/tests/qemuxmlconfdata/broken-xml-invalid.xml b/tests/qemuxmlconfdata/broken-xml-invalid.xml new file mode 100644 index 0000000000..9903e61ead --- /dev/null +++ b/tests/qemuxmlconfdata/broken-xml-invalid.xml @@ -0,0 +1 @@ +<dom diff --git a/tests/qemuxmlconfdata/nonexistent-file.x86_64-latest.err b/tests/qemuxmlconfdata/nonexistent-file.x86_64-latest.err new file mode 100644 index 0000000000..0ddf1ea510 --- /dev/null +++ b/tests/qemuxmlconfdata/nonexistent-file.x86_64-latest.err @@ -0,0 +1 @@ +XML error: failed to parse xml document 'ABS_SRCDIR/qemuxmlconfdata/nonexistent-file.xml' diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c index 5fe69db15f..0ac9337775 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -372,6 +372,7 @@ testCheckExclusiveFlags(int flags) FLAG_REAL_CAPS | FLAG_SLIRP_HELPER | FLAG_ALLOW_DUPLICATE_OUTPUT | + FLAG_ALLOW_MISSING_INPUT | 0, -1); return 0; @@ -671,7 +672,8 @@ testQemuConfXMLCommon(testQemuInfo *info, if (qemuTestCapsCacheInsert(driver.qemuCapsCache, info->qemuCaps) < 0) goto cleanup; - if (!virFileExists(info->infile)) { + if (!(info->flags & FLAG_ALLOW_MISSING_INPUT) && + !virFileExists(info->infile)) { virReportError(VIR_ERR_INTERNAL_ERROR, "Input file '%s' not found", info->infile); goto cleanup; @@ -1237,6 +1239,10 @@ mymain(void) g_unsetenv("PIPEWIRE_REMOTE"); g_unsetenv("PIPEWIRE_RUNTIME_DIR"); + DO_TEST_CAPS_ARCH_LATEST_FULL("nonexistent-file", "x86_64", + ARG_FLAGS, FLAG_EXPECT_PARSE_ERROR | FLAG_ALLOW_MISSING_INPUT); + DO_TEST_CAPS_LATEST_PARSE_ERROR("broken-xml-invalid"); + DO_TEST_CAPS_LATEST("x86_64-pc-minimal"); DO_TEST_CAPS_LATEST_ABI_UPDATE("x86_64-pc-minimal"); DO_TEST_CAPS_LATEST("x86_64-q35-minimal"); diff --git a/tests/testutilsqemu.h b/tests/testutilsqemu.h index a5806f244b..90632031ff 100644 --- a/tests/testutilsqemu.h +++ b/tests/testutilsqemu.h @@ -61,6 +61,7 @@ typedef enum { FLAG_REAL_CAPS = 1 << 2, FLAG_SLIRP_HELPER = 1 << 3, FLAG_ALLOW_DUPLICATE_OUTPUT = 1 << 4, /* allow multiple tests with the same output file */ + FLAG_ALLOW_MISSING_INPUT = 1 << 5, } testQemuInfoFlags; struct testQemuConf { diff --git a/tests/virschematest.c b/tests/virschematest.c index 9b6649a6cf..e89730e8dc 100644 --- a/tests/virschematest.c +++ b/tests/virschematest.c @@ -36,6 +36,7 @@ struct testSchemaEntry { const char **exceptions; /* optional NULL terminated list of filenames inside directory where the expected validation result is inverted */ + const char **skip; /* list of files to skip altogether */ const char *dirRegex; const char *file; }; @@ -131,6 +132,10 @@ testSchemaDir(const char *schema, !g_regex_match(filter, ent->d_name, 0, NULL)) continue; + if (entry->skip && + g_strv_contains(entry->skip, ent->d_name)) + continue; + if (entry->exceptions) exception = g_strv_contains(entry->exceptions, ent->d_name); @@ -237,10 +242,17 @@ static const char *exceptions_qemuxmlconfdata[] = { NULL }; +/* skip tests with completely broken XML */ +static const char *skip_qemuxmlconfdata[] = { + "broken-xml-invalid.xml", + NULL +}; + static const struct testSchemaEntry schemaDomain[] = { { .dir = "tests/domainschemadata" }, { .dir = "tests/qemuxmlconfdata", .exceptions = exceptions_qemuxmlconfdata, + .skip = skip_qemuxmlconfdata, }, { .dir = "tests/xmconfigdata" }, { .dir = "tests/lxcxml2xmldata" }, -- 2.45.2

On 8/9/24 14:40, Peter Krempa wrote:
Add test cases for few edge cases which excercise the XML reporting from libxml2 in anticipation of upcoming changes of behaviour.
'virschematest' must skip parsing of the broken file altogether so this patch adds infrastructure to allow that.
Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- .../broken-xml-invalid.x86_64-latest.err | 3 +++ tests/qemuxmlconfdata/broken-xml-invalid.xml | 1 + .../nonexistent-file.x86_64-latest.err | 1 + tests/qemuxmlconftest.c | 8 +++++++- tests/testutilsqemu.h | 1 + tests/virschematest.c | 12 ++++++++++++ 6 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxmlconfdata/broken-xml-invalid.x86_64-latest.err create mode 100644 tests/qemuxmlconfdata/broken-xml-invalid.xml create mode 100644 tests/qemuxmlconfdata/nonexistent-file.x86_64-latest.err
diff --git a/tests/virschematest.c b/tests/virschematest.c index 9b6649a6cf..e89730e8dc 100644 --- a/tests/virschematest.c +++ b/tests/virschematest.c @@ -36,6 +36,7 @@ struct testSchemaEntry { const char **exceptions; /* optional NULL terminated list of filenames inside directory where the expected validation result is inverted */ + const char **skip; /* list of files to skip altogether */
NULL terminated list, please. Michal

On 8/9/24 14:40, Peter Krempa wrote:
Patch 3/3 adds the actual test:
Changes to v1: - fixed missing NULL termination of the 'skip' array - "backported" g_string_replace into glibcompat.c until we bump minimum glib - started striping 'abs_srcdir' strings from qemuxmlconftest's '.err' output files
Peter Krempa (3): glibcompat: "Backport" 'g_string_replace' testQemuConfXMLCommon: Strip 'abs_srcdir' paths from '.err' files in qemuxmlconftest qemuxmlconftest: Add test cases for broken and missing XML files
src/libvirt_private.syms | 1 + src/util/glibcompat.c | 65 +++++++++++++++++++ src/util/glibcompat.h | 10 +++ .../broken-xml-invalid.x86_64-latest.err | 3 + tests/qemuxmlconfdata/broken-xml-invalid.xml | 1 + .../nonexistent-file.x86_64-latest.err | 1 + tests/qemuxmlconftest.c | 16 ++++- tests/testutilsqemu.h | 1 + tests/virschematest.c | 12 ++++ 9 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 tests/qemuxmlconfdata/broken-xml-invalid.x86_64-latest.err create mode 100644 tests/qemuxmlconfdata/broken-xml-invalid.xml create mode 100644 tests/qemuxmlconfdata/nonexistent-file.x86_64-latest.err
Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Michal
participants (2)
-
Michal Prívozník
-
Peter Krempa