[libvirt PATCHv2 00/15] Switch to json-c from yajl

Wow. Such patch. Much series. Ján Tomko (15): util: json: introduce virJSONStringPrettifyBlanks tests: switch to compact empty JSON object formatting build: introduce WITH_JSON ci: install json-c too meson: add option for building with json-c meson: switch checks to depend on json-c as well as yajl build: do not depend on yajl build: link with json_c util: json: write a json-c implementation nss: convert findLeases to use json-c nss: convert findMACs to use json-c meson: do not link anything with yajl anymore meson: options: drop yajl meson: drop yajl detection ci: drop yajl completely ci/buildenv/almalinux-9.sh | 4 +- ci/buildenv/alpine-319.sh | 4 +- ci/buildenv/alpine-edge.sh | 4 +- ci/buildenv/centos-stream-9.sh | 4 +- ci/buildenv/debian-11-cross-aarch64.sh | 2 +- ci/buildenv/debian-11-cross-armv6l.sh | 2 +- ci/buildenv/debian-11-cross-armv7l.sh | 2 +- ci/buildenv/debian-11-cross-i686.sh | 2 +- ci/buildenv/debian-11-cross-mips64el.sh | 2 +- ci/buildenv/debian-11-cross-mipsel.sh | 2 +- ci/buildenv/debian-11-cross-ppc64le.sh | 2 +- ci/buildenv/debian-11-cross-s390x.sh | 2 +- ci/buildenv/debian-11.sh | 2 +- ci/buildenv/debian-12-cross-aarch64.sh | 2 +- ci/buildenv/debian-12-cross-armv6l.sh | 2 +- ci/buildenv/debian-12-cross-armv7l.sh | 2 +- ci/buildenv/debian-12-cross-i686.sh | 2 +- ci/buildenv/debian-12-cross-mips64el.sh | 2 +- ci/buildenv/debian-12-cross-mipsel.sh | 2 +- ci/buildenv/debian-12-cross-ppc64le.sh | 2 +- ci/buildenv/debian-12-cross-s390x.sh | 2 +- ci/buildenv/debian-12.sh | 2 +- ci/buildenv/debian-sid-cross-aarch64.sh | 2 +- ci/buildenv/debian-sid-cross-armv6l.sh | 2 +- ci/buildenv/debian-sid-cross-armv7l.sh | 2 +- ci/buildenv/debian-sid-cross-i686.sh | 2 +- ci/buildenv/debian-sid-cross-mips64el.sh | 2 +- ci/buildenv/debian-sid-cross-ppc64le.sh | 2 +- ci/buildenv/debian-sid-cross-s390x.sh | 2 +- ci/buildenv/debian-sid.sh | 2 +- ci/buildenv/fedora-39.sh | 4 +- ci/buildenv/fedora-40.sh | 4 +- ci/buildenv/fedora-rawhide.sh | 4 +- ci/buildenv/opensuse-leap-15.sh | 2 +- ci/buildenv/opensuse-tumbleweed.sh | 2 +- ci/buildenv/ubuntu-2204.sh | 2 +- ci/buildenv/ubuntu-2404.sh | 2 +- ci/cirrus/freebsd-13.vars | 2 +- ci/cirrus/freebsd-14.vars | 2 +- ci/cirrus/macos-13.vars | 2 +- ci/cirrus/macos-14.vars | 2 +- ci/containers/almalinux-9.Dockerfile | 4 +- ci/containers/alpine-319.Dockerfile | 4 +- ci/containers/alpine-edge.Dockerfile | 4 +- ci/containers/centos-stream-9.Dockerfile | 4 +- .../debian-11-cross-aarch64.Dockerfile | 2 +- .../debian-11-cross-armv6l.Dockerfile | 2 +- .../debian-11-cross-armv7l.Dockerfile | 2 +- ci/containers/debian-11-cross-i686.Dockerfile | 2 +- .../debian-11-cross-mips64el.Dockerfile | 2 +- .../debian-11-cross-mipsel.Dockerfile | 2 +- .../debian-11-cross-ppc64le.Dockerfile | 2 +- .../debian-11-cross-s390x.Dockerfile | 2 +- ci/containers/debian-11.Dockerfile | 2 +- .../debian-12-cross-aarch64.Dockerfile | 2 +- .../debian-12-cross-armv6l.Dockerfile | 2 +- .../debian-12-cross-armv7l.Dockerfile | 2 +- ci/containers/debian-12-cross-i686.Dockerfile | 2 +- .../debian-12-cross-mips64el.Dockerfile | 2 +- .../debian-12-cross-mipsel.Dockerfile | 2 +- .../debian-12-cross-ppc64le.Dockerfile | 2 +- .../debian-12-cross-s390x.Dockerfile | 2 +- ci/containers/debian-12.Dockerfile | 2 +- .../debian-sid-cross-aarch64.Dockerfile | 2 +- .../debian-sid-cross-armv6l.Dockerfile | 2 +- .../debian-sid-cross-armv7l.Dockerfile | 2 +- .../debian-sid-cross-i686.Dockerfile | 2 +- .../debian-sid-cross-mips64el.Dockerfile | 2 +- .../debian-sid-cross-ppc64le.Dockerfile | 2 +- .../debian-sid-cross-s390x.Dockerfile | 2 +- ci/containers/debian-sid.Dockerfile | 2 +- ci/containers/fedora-39.Dockerfile | 4 +- ci/containers/fedora-40.Dockerfile | 4 +- ci/containers/fedora-rawhide.Dockerfile | 4 +- ci/containers/opensuse-leap-15.Dockerfile | 2 +- ci/containers/opensuse-tumbleweed.Dockerfile | 2 +- ci/containers/ubuntu-2204.Dockerfile | 2 +- ci/containers/ubuntu-2404.Dockerfile | 2 +- ci/lcitool/projects/libvirt.yml | 2 +- libvirt.spec.in | 6 +- meson.build | 62 +-- meson_options.txt | 8 +- src/libvirt_private.syms | 1 + src/meson.build | 2 +- src/util/meson.build | 2 +- src/util/virjson.c | 485 +++++------------- src/util/virjson.h | 2 + tests/meson.build | 8 +- tests/qemublocktest.c | 5 +- .../backupmerge/empty-out.json | 4 +- tests/qemumigparamsdata/empty.json | 4 +- tests/qemumigparamstest.c | 5 +- tests/virmacmaptest.c | 5 +- tests/virmacmaptestdata/empty.json | 4 +- tests/virnetdaemontest.c | 2 +- tests/virstoragetest.c | 4 +- tools/nss/libvirt_nss_leases.c | 370 +++++-------- tools/nss/libvirt_nss_macs.c | 278 +++------- tools/nss/meson.build | 4 +- 99 files changed, 475 insertions(+), 972 deletions(-) -- 2.46.0

A horribly named function for unifying formatting when pretty-printing empty JSON arrays and objects. Useful for having stable test output even if different JSON libraries format these differently. Signed-off-by: Ján Tomko <jtomko@redhat.com> Reviewed-by: Peter Krempa <pkrempa@redhat.com> --- src/libvirt_private.syms | 1 + src/util/virjson.c | 34 ++++++++++++++++++++++++++++++++++ src/util/virjson.h | 2 ++ 3 files changed, 37 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index af40e5dca3..d186dc40df 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2612,6 +2612,7 @@ virISCSIScanTargets; # util/virjson.h +virJSONStringPrettifyBlanks; virJSONStringReformat; virJSONValueArrayAppend; virJSONValueArrayAppendString; diff --git a/src/util/virjson.c b/src/util/virjson.c index 57707350da..0edf86cd1c 100644 --- a/src/util/virjson.c +++ b/src/util/virjson.c @@ -1861,6 +1861,40 @@ virJSONStringReformat(const char *jsonstr, return virJSONValueToString(json, pretty); } +/** + * virJSONStringPrettifyBlanks: + * @jsonstr: string to prettify + * + * In the pretty mode of printing, various versions of JSON libraries + * format empty arrays and objects differently. + * + * Unify this to "[]" and "{}" which are used by json-c 0.17 and newer. + * https://github.com/json-c/json-c/issues/778 + * + * This format is also used by Python's 'json.dump' method. + * + * Returns the reformatted JSON string on success. + */ +char *virJSONStringPrettifyBlanks(const char *jsonstr) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + const char *p; + + for (p = jsonstr; *p && p[1]; p++) { + virBufferAddChar(&buf, *p); + + if ((p[0] == '{' || p[0] == '[') && p[1] == '\n') { + const char *q = p + 1; + + virSkipSpaces(&q); + + if (*q == '}' || *q == ']') + p = q - 1; + } + } + + return virBufferContentAndReset(&buf); +} static virJSONValue * virJSONValueObjectDeflattenKeys(virJSONValue *json); diff --git a/src/util/virjson.h b/src/util/virjson.h index e622798fe7..d8481e5890 100644 --- a/src/util/virjson.h +++ b/src/util/virjson.h @@ -271,6 +271,8 @@ virJSONValueCopy(const virJSONValue *in); char * virJSONStringReformat(const char *jsonstr, bool pretty); +char * +virJSONStringPrettifyBlanks(const char *jsonstr); virJSONValue * virJSONValueObjectDeflatten(virJSONValue *json); -- 2.46.0

Some earlier versions of json-c format empty elements differently. Run the tests who use the pretty formatting for readability and diffability through a function that unifies the output. Signed-off-by: Ján Tomko <jtomko@redhat.com> Reviewed-by: Peter Krempa <pkrempa@redhat.com> --- tests/qemublocktest.c | 5 ++++- tests/qemublocktestdata/backupmerge/empty-out.json | 4 +--- tests/qemumigparamsdata/empty.json | 4 +--- tests/qemumigparamstest.c | 5 ++++- tests/virmacmaptest.c | 5 ++++- tests/virmacmaptestdata/empty.json | 4 +--- 6 files changed, 15 insertions(+), 12 deletions(-) diff --git a/tests/qemublocktest.c b/tests/qemublocktest.c index c581bd1748..6c4e735466 100644 --- a/tests/qemublocktest.c +++ b/tests/qemublocktest.c @@ -720,6 +720,7 @@ testQemuBackupIncrementalBitmapCalculate(const void *opaque) g_autofree char *expectpath = NULL; g_autoptr(virStorageSource) target = NULL; g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER; + g_autofree char *actual = NULL; expectpath = g_strdup_printf("%s/%s%s-out.json", abs_srcdir, backupDataPrefix, data->name); @@ -748,7 +749,9 @@ testQemuBackupIncrementalBitmapCalculate(const void *opaque) virBufferAddLit(&buf, "NULL\n"); } - return virTestCompareToFile(virBufferCurrentContent(&buf), expectpath); + actual = virJSONStringPrettifyBlanks(virBufferCurrentContent(&buf)); + + return virTestCompareToFile(actual, expectpath); } diff --git a/tests/qemublocktestdata/backupmerge/empty-out.json b/tests/qemublocktestdata/backupmerge/empty-out.json index 41b42e677b..fe51488c70 100644 --- a/tests/qemublocktestdata/backupmerge/empty-out.json +++ b/tests/qemublocktestdata/backupmerge/empty-out.json @@ -1,3 +1 @@ -[ - -] +[] diff --git a/tests/qemumigparamsdata/empty.json b/tests/qemumigparamsdata/empty.json index 0db3279e44..0967ef424b 100644 --- a/tests/qemumigparamsdata/empty.json +++ b/tests/qemumigparamsdata/empty.json @@ -1,3 +1 @@ -{ - -} +{} diff --git a/tests/qemumigparamstest.c b/tests/qemumigparamstest.c index 5d45a9dd58..67cc14d948 100644 --- a/tests/qemumigparamstest.c +++ b/tests/qemumigparamstest.c @@ -137,6 +137,7 @@ qemuMigParamsTestJSON(const void *opaque) g_autoptr(virJSONValue) paramsIn = NULL; g_autoptr(virJSONValue) paramsOut = NULL; g_autoptr(qemuMigrationParams) migParams = NULL; + g_autofree char *formattedJSON = NULL; g_autofree char *actualJSON = NULL; g_auto(virBuffer) debug = VIR_BUFFER_INITIALIZER; @@ -156,9 +157,11 @@ qemuMigParamsTestJSON(const void *opaque) return -1; if (!(paramsOut = qemuMigrationParamsToJSON(migParams, false)) || - !(actualJSON = virJSONValueToString(paramsOut, true))) + !(formattedJSON = virJSONValueToString(paramsOut, true))) return -1; + actualJSON = virJSONStringPrettifyBlanks(formattedJSON); + if (testQEMUSchemaValidateCommand("migrate-set-parameters", paramsOut, data->qmpschema, diff --git a/tests/virmacmaptest.c b/tests/virmacmaptest.c index 9a28c1bed0..074bc8f659 100644 --- a/tests/virmacmaptest.c +++ b/tests/virmacmaptest.c @@ -118,13 +118,16 @@ testMACFlush(const void *opaque) const struct testData *data = opaque; g_autofree char *file = NULL; g_autofree char *str = NULL; + g_autofree char *actual = NULL; file = g_strdup_printf("%s/virmacmaptestdata/%s.json", abs_srcdir, data->file); if (virMacMapDumpStr(data->mgr, &str) < 0) return -1; - if (virTestCompareToFile(str, file) < 0) + actual = virJSONStringPrettifyBlanks(str); + + if (virTestCompareToFile(actual, file) < 0) return -1; return 0; diff --git a/tests/virmacmaptestdata/empty.json b/tests/virmacmaptestdata/empty.json index 41b42e677b..fe51488c70 100644 --- a/tests/virmacmaptestdata/empty.json +++ b/tests/virmacmaptestdata/empty.json @@ -1,3 +1 @@ -[ - -] +[] -- 2.46.0
participants (1)
-
Ján Tomko