qemuxmlconftest: Stablilize '-add-fd' arguments

Add code which walks the generated argument list and allows to strip out
and replace by a substitution any field in either JSON or legacy qemu
argument string.

Use it to stabilize 'fd' field of '-add-fd'

This will allow us to rip out code which tries to allocate stable FD
numbers, which doesn't work reliably (e.g. if the environment passes
some FDs).

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
Peter Krempa committed 2026-05-25 13:28:57 +02:00
1 parent a72bbfc4ba
commit 6cf78a55f9
18 files changed
+229 -34

No files matched your search

@@ -28,7 +28,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-aarch64test/.config \
-device '{"driver":"pcie-root-port","port":8,"chassis":1,"id":"pci.1","bus":"pcie.0","multifunction":true,"addr":"0x1"}' \
-device '{"driver":"pcie-pci-bridge","id":"pci.2","bus":"pci.1","addr":"0x0"}' \
-device '{"driver":"pcie-root-port","port":9,"chassis":3,"id":"pci.3","bus":"pcie.0","addr":"0x1.0x1"}' \
-add-fd set=0,fd=1751,opaque=serial0-log \
-add-fd set=0,fd=XXXXXXX,opaque=serial0-log \
-chardev pty,id=charserial0,logfile=/dev/fdset/0,logappend=on \
-device '{"driver":"pci-serial","chardev":"charserial0","id":"serial0","bus":"pci.2","addr":"0x1"}' \
-audiodev '{"id":"audio1","driver":"none"}' \
@@ -29,17 +29,17 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \
-device '{"driver":"virtio-serial-pci","id":"virtio-serial0","bus":"pci.0","addr":"0x3"}' \
-chardev '{"id":"charparallel0","backend":{"type":"parallel","data":{"device":"/dev/parport0"}}}' \
-device '{"driver":"isa-parallel","chardev":"charparallel0","id":"parallel0"}' \
-add-fd set=0,fd=1751,opaque=channel0-log \
-add-fd set=0,fd=XXXXXXX,opaque=channel0-log \
-chardev '{"id":"charchannel0","backend":{"type":"null","data":{"logfile":"/dev/fdset/0","logappend":true}}}' \
-device '{"driver":"virtserialport","bus":"virtio-serial0.0","nr":1,"chardev":"charchannel0","id":"channel0","name":"chardev-null"}' \
-add-fd set=1,fd=1751,opaque=channel1-log \
-add-fd set=1,fd=XXXXXXX,opaque=channel1-log \
-chardev '{"id":"charchannel1","backend":{"type":"vc","data":{"logfile":"/dev/fdset/1","logappend":true}}}' \
-device '{"driver":"virtserialport","bus":"virtio-serial0.0","nr":2,"chardev":"charchannel1","id":"channel1","name":"chardev-vc"}' \
-chardev '{"id":"charchannel2","backend":{"type":"pty","data":{}}}' \
-device '{"driver":"virtserialport","bus":"virtio-serial0.0","nr":3,"chardev":"charchannel2","id":"channel2","name":"chardev-pty"}' \
-chardev '{"id":"charchannel3","backend":{"type":"stdio","data":{}}}' \
-device '{"driver":"virtserialport","bus":"virtio-serial0.0","nr":4,"chardev":"charchannel3","id":"channel3","name":"chardev-stdio"}' \
-add-fd set=2,fd=1750,opaque=channel4-source \
-add-fd set=2,fd=XXXXXXX,opaque=channel4-source \
-chardev '{"id":"charchannel4","backend":{"type":"file","data":{"out":"/dev/fdset/2","append":true}}}' \
-device '{"driver":"virtserialport","bus":"virtio-serial0.0","nr":5,"chardev":"charchannel4","id":"channel4","name":"chardev-file"}' \
-chardev '{"id":"charchannel5","backend":{"type":"pipe","data":{"device":"/path/to/pipe"}}}' \
@@ -29,17 +29,17 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \
-device '{"driver":"virtio-serial-pci","id":"virtio-serial0","bus":"pci.0","addr":"0x3"}' \
-chardev '{"id":"charparallel0","backend":{"type":"parallel","data":{"device":"/dev/parport0"}}}' \
-device '{"driver":"isa-parallel","chardev":"charparallel0","id":"parallel0"}' \
-add-fd set=0,fd=1751,opaque=channel0-log \
-add-fd set=0,fd=XXXXXXX,opaque=channel0-log \
-chardev '{"id":"charchannel0","backend":{"type":"null","data":{"logfile":"/dev/fdset/0","logappend":true}}}' \
-device '{"driver":"virtserialport","bus":"virtio-serial0.0","nr":1,"chardev":"charchannel0","id":"channel0","name":"chardev-null"}' \
-add-fd set=1,fd=1751,opaque=channel1-log \
-add-fd set=1,fd=XXXXXXX,opaque=channel1-log \
-chardev '{"id":"charchannel1","backend":{"type":"vc","data":{"logfile":"/dev/fdset/1","logappend":true}}}' \
-device '{"driver":"virtserialport","bus":"virtio-serial0.0","nr":2,"chardev":"charchannel1","id":"channel1","name":"chardev-vc"}' \
-chardev '{"id":"charchannel2","backend":{"type":"pty","data":{}}}' \
-device '{"driver":"virtserialport","bus":"virtio-serial0.0","nr":3,"chardev":"charchannel2","id":"channel2","name":"chardev-pty"}' \
-chardev '{"id":"charchannel3","backend":{"type":"stdio","data":{}}}' \
-device '{"driver":"virtserialport","bus":"virtio-serial0.0","nr":4,"chardev":"charchannel3","id":"channel3","name":"chardev-stdio"}' \
-add-fd set=2,fd=1750,opaque=channel4-source \
-add-fd set=2,fd=XXXXXXX,opaque=channel4-source \
-chardev '{"id":"charchannel4","backend":{"type":"file","data":{"out":"/dev/fdset/2","append":true}}}' \
-device '{"driver":"virtserialport","bus":"virtio-serial0.0","nr":5,"chardev":"charchannel4","id":"channel4","name":"chardev-file"}' \
-chardev '{"id":"charchannel5","backend":{"type":"pipe","data":{"device":"/path/to/pipe"}}}' \
@@ -29,17 +29,17 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \
-device '{"driver":"virtio-serial-pci","id":"virtio-serial0","bus":"pci.0","addr":"0x3"}' \
-chardev parallel,id=charparallel0,path=/dev/parport0 \
-device '{"driver":"isa-parallel","chardev":"charparallel0","id":"parallel0"}' \
-add-fd set=0,fd=1751,opaque=channel0-log \
-add-fd set=0,fd=XXXXXXX,opaque=channel0-log \
-chardev null,id=charchannel0,logfile=/dev/fdset/0,logappend=on \
-device '{"driver":"virtserialport","bus":"virtio-serial0.0","nr":1,"chardev":"charchannel0","id":"channel0","name":"chardev-null"}' \
-add-fd set=1,fd=1751,opaque=channel1-log \
-add-fd set=1,fd=XXXXXXX,opaque=channel1-log \
-chardev vc,id=charchannel1,logfile=/dev/fdset/1,logappend=on \
-device '{"driver":"virtserialport","bus":"virtio-serial0.0","nr":2,"chardev":"charchannel1","id":"channel1","name":"chardev-vc"}' \
-chardev pty,id=charchannel2 \
-device '{"driver":"virtserialport","bus":"virtio-serial0.0","nr":3,"chardev":"charchannel2","id":"channel2","name":"chardev-pty"}' \
-chardev stdio,id=charchannel3 \
-device '{"driver":"virtserialport","bus":"virtio-serial0.0","nr":4,"chardev":"charchannel3","id":"channel3","name":"chardev-stdio"}' \
-add-fd set=2,fd=1750,opaque=channel4-source \
-add-fd set=2,fd=XXXXXXX,opaque=channel4-source \
-chardev file,id=charchannel4,path=/dev/fdset/2,append=on \
-device '{"driver":"virtserialport","bus":"virtio-serial0.0","nr":5,"chardev":"charchannel4","id":"channel4","name":"chardev-file"}' \
-chardev pipe,id=charchannel5,path=/path/to/pipe \
@@ -29,17 +29,17 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \
-device '{"driver":"virtio-serial-pci","id":"virtio-serial0","bus":"pci.0","addr":"0x3"}' \
-chardev parallel,id=charparallel0,path=/dev/parport0 \
-device '{"driver":"isa-parallel","chardev":"charparallel0","id":"parallel0"}' \
-add-fd set=0,fd=1751,opaque=channel0-log \
-add-fd set=0,fd=XXXXXXX,opaque=channel0-log \
-chardev null,id=charchannel0,logfile=/dev/fdset/0,logappend=on \
-device '{"driver":"virtserialport","bus":"virtio-serial0.0","nr":1,"chardev":"charchannel0","id":"channel0","name":"chardev-null"}' \
-add-fd set=1,fd=1751,opaque=channel1-log \
-add-fd set=1,fd=XXXXXXX,opaque=channel1-log \
-chardev vc,id=charchannel1,logfile=/dev/fdset/1,logappend=on \
-device '{"driver":"virtserialport","bus":"virtio-serial0.0","nr":2,"chardev":"charchannel1","id":"channel1","name":"chardev-vc"}' \
-chardev pty,id=charchannel2 \
-device '{"driver":"virtserialport","bus":"virtio-serial0.0","nr":3,"chardev":"charchannel2","id":"channel2","name":"chardev-pty"}' \
-chardev stdio,id=charchannel3 \
-device '{"driver":"virtserialport","bus":"virtio-serial0.0","nr":4,"chardev":"charchannel3","id":"channel3","name":"chardev-stdio"}' \
-add-fd set=2,fd=1750,opaque=channel4-source \
-add-fd set=2,fd=XXXXXXX,opaque=channel4-source \
-chardev file,id=charchannel4,path=/dev/fdset/2,append=on \
-device '{"driver":"virtserialport","bus":"virtio-serial0.0","nr":5,"chardev":"charchannel4","id":"channel4","name":"chardev-file"}' \
-chardev pipe,id=charchannel5,path=/path/to/pipe \
@@ -27,7 +27,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-machine/.config \
-no-shutdown \
-boot strict=on \
-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \
-add-fd set=0,fd=1750,opaque=serial0-source \
-add-fd set=0,fd=XXXXXXX,opaque=serial0-source \
-chardev file,id=charserial0,path=/dev/fdset/0,append=on \
-device '{"driver":"isa-serial","chardev":"charserial0","id":"serial0","index":0}' \
-chardev socket,id=charserial1,path=/tmp/serial.sock \
@@ -27,26 +27,26 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \
-no-shutdown \
-boot strict=on \
-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \
-add-fd set=5,fd=200,opaque=libvirt-6-storage0 \
-add-fd set=5,fd=205,opaque=libvirt-6-storage1 \
-add-fd set=5,fd=XXXXXXX,opaque=libvirt-6-storage0 \
-add-fd set=5,fd=XXXXXXX,opaque=libvirt-6-storage1 \
-blockdev '{"driver":"file","filename":"/dev/fdset/5","node-name":"libvirt-6-storage","auto-read-only":true,"discard":"unmap"}' \
-blockdev '{"node-name":"libvirt-6-format","read-only":false,"driver":"qcow2","file":"libvirt-6-storage"}' \
-device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x2","drive":"libvirt-6-format","id":"virtio-disk4","bootindex":1}' \
-add-fd set=4,fd=209,opaque=libvirt-5-storage0 \
-add-fd set=4,fd=XXXXXXX,opaque=libvirt-5-storage0 \
-blockdev '{"driver":"file","filename":"/dev/fdset/4","node-name":"libvirt-5-storage","read-only":false,"discard":"unmap"}' \
-blockdev '{"node-name":"libvirt-5-format","read-only":true,"driver":"raw","file":"libvirt-5-storage"}' \
-add-fd set=3,fd=247,opaque=libvirt-4-storage0 \
-add-fd set=3,fd=248,opaque=libvirt-4-storage1 \
-add-fd set=3,fd=XXXXXXX,opaque=libvirt-4-storage0 \
-add-fd set=3,fd=XXXXXXX,opaque=libvirt-4-storage1 \
-blockdev '{"driver":"file","filename":"/dev/fdset/3","node-name":"libvirt-4-storage","auto-read-only":true,"discard":"unmap"}' \
-blockdev '{"node-name":"libvirt-4-format","read-only":true,"driver":"qcow2","file":"libvirt-4-storage","backing":"libvirt-5-format"}' \
-add-fd set=2,fd=204,opaque=libvirt-3-storage0 \
-add-fd set=2,fd=XXXXXXX,opaque=libvirt-3-storage0 \
-blockdev '{"driver":"file","filename":"/dev/fdset/2","node-name":"libvirt-3-storage","read-only":false,"discard":"unmap"}' \
-blockdev '{"node-name":"libvirt-3-format","read-only":false,"driver":"qcow2","file":"libvirt-3-storage","backing":"libvirt-4-format"}' \
-device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x3","drive":"libvirt-3-format","id":"virtio-disk5"}' \
-add-fd set=1,fd=207,opaque=libvirt-2-storage0 \
-add-fd set=1,fd=XXXXXXX,opaque=libvirt-2-storage0 \
-blockdev '{"driver":"file","filename":"/dev/fdset/1","node-name":"libvirt-2-storage","read-only":true}' \
-device '{"driver":"ide-cd","bus":"ide.0","unit":0,"drive":"libvirt-2-storage","id":"ide0-0-0"}' \
-add-fd set=0,fd=208,opaque=libvirt-1-storage0 \
-add-fd set=0,fd=XXXXXXX,opaque=libvirt-1-storage0 \
-blockdev '{"driver":"file","filename":"/dev/fdset/0","node-name":"libvirt-1-storage","read-only":false,"discard":"unmap"}' \
-blockdev '{"node-name":"libvirt-1-format","read-only":true,"driver":"raw","file":"libvirt-1-storage"}' \
-device '{"driver":"ide-cd","bus":"ide.0","unit":1,"drive":"libvirt-1-format","id":"ide0-0-1"}' \
@@ -27,7 +27,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \
-no-shutdown \
-boot strict=on \
-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \
-add-fd set=0,fd=201,opaque=libvirt-1-storage-vdpa \
-add-fd set=0,fd=XXXXXXX,opaque=libvirt-1-storage-vdpa \
-blockdev '{"driver":"virtio-blk-vhost-vdpa","path":"/dev/fdset/0","node-name":"libvirt-1-storage","read-only":false,"cache":{"direct":true,"no-flush":false}}' \
-device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x2","drive":"libvirt-1-storage","id":"virtio-disk0","bootindex":1,"write-cache":"on"}' \
-audiodev '{"id":"audio1","driver":"none"}' \
@@ -34,7 +34,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-foo=1,bar=2/.config \
-device '{"driver":"ccid-card-emulated","backend":"certificates","cert1":"cert1,foo","cert2":"cert2","cert3":"cert3","db":"/etc/pki/nssdb,foo","id":"smartcard0","bus":"ccid0.0"}' \
-chardev serial,id=charserial0,path=/dev/ttyS2,,foo \
-device '{"driver":"isa-serial","chardev":"charserial0","id":"serial0","index":1}' \
-add-fd set=0,fd=1750,opaque=serial1-source \
-add-fd set=0,fd=XXXXXXX,opaque=serial1-source \
-chardev file,id=charserial1,path=/dev/fdset/0,append=on \
-device '{"driver":"isa-serial","chardev":"charserial1","id":"serial1","index":0}' \
-chardev pipe,id=charchannel0,path=/tmp/guestfwd,,foo \
@@ -27,7 +27,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \
-no-shutdown \
-boot strict=on \
-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \
-add-fd set=0,fd=1732,opaque=net0-vdpa \
-add-fd set=0,fd=XXXXXXX,opaque=net0-vdpa \
-netdev '{"type":"vhost-vdpa","vhostdev":"/dev/fdset/0","queues":2,"id":"hostnet0"}' \
-device '{"driver":"virtio-net-pci","mq":true,"vectors":6,"netdev":"hostnet0","id":"net0","mac":"52:54:00:95:db:c0","bus":"pci.0","addr":"0x2"}' \
-audiodev '{"id":"audio1","driver":"none"}' \
@@ -27,7 +27,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \
-no-shutdown \
-boot strict=on \
-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \
-add-fd set=0,fd=1732,opaque=net0-vdpa \
-add-fd set=0,fd=XXXXXXX,opaque=net0-vdpa \
-netdev '{"type":"vhost-vdpa","vhostdev":"/dev/fdset/0","id":"hostnet0"}' \
-device '{"driver":"virtio-net-pci","netdev":"hostnet0","id":"net0","mac":"52:54:00:95:db:c0","bus":"pci.0","addr":"0x2"}' \
-audiodev '{"id":"audio1","driver":"none"}' \
@@ -29,7 +29,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \
-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \
-blockdev '{"driver":"host_device","filename":"/dev/HostVG/QEMUGuest1","node-name":"libvirt-1-storage","read-only":false}' \
-device '{"driver":"ide-hd","bus":"ide.0","unit":0,"drive":"libvirt-1-storage","id":"ide0-0-0","bootindex":1}' \
-add-fd set=0,fd=1750,opaque=serial0-source \
-add-fd set=0,fd=XXXXXXX,opaque=serial0-source \
-chardev file,id=charserial0,path=/dev/fdset/0,append=on \
-device '{"driver":"isa-serial","chardev":"charserial0","id":"serial0","index":0}' \
-audiodev '{"id":"audio1","driver":"none"}' \
@@ -29,8 +29,8 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \
-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \
-blockdev '{"driver":"host_device","filename":"/dev/HostVG/QEMUGuest1","node-name":"libvirt-1-storage","read-only":false}' \
-device '{"driver":"ide-hd","bus":"ide.0","unit":0,"drive":"libvirt-1-storage","id":"ide0-0-0","bootindex":1}' \
-add-fd set=0,fd=1750,opaque=serial0-source \
-add-fd set=1,fd=1751,opaque=serial0-log \
-add-fd set=0,fd=XXXXXXX,opaque=serial0-source \
-add-fd set=1,fd=XXXXXXX,opaque=serial0-log \
-chardev file,id=charserial0,path=/dev/fdset/0,append=on,logfile=/dev/fdset/1,logappend=on \
-device '{"driver":"isa-serial","chardev":"charserial0","id":"serial0","index":0}' \
-audiodev '{"id":"audio1","driver":"none"}' \
@@ -31,7 +31,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \
-device '{"driver":"ide-hd","bus":"ide.0","unit":0,"drive":"libvirt-1-storage","id":"ide0-0-0","bootindex":1}' \
-chardev pty,id=charserial0 \
-device '{"driver":"isa-serial","chardev":"charserial0","id":"serial0","index":0}' \
-add-fd set=0,fd=1750,opaque=serial1-source \
-add-fd set=0,fd=XXXXXXX,opaque=serial1-source \
-chardev file,id=charserial1,path=/dev/fdset/0,append=on \
-device '{"driver":"isa-serial","chardev":"charserial1","id":"serial1","index":1}' \
-audiodev '{"id":"audio1","driver":"none"}' \
@@ -27,8 +27,8 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-TPM-VM/.config \
-no-shutdown \
-boot menu=on,strict=on \
-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \
-add-fd set=0,fd=1730,opaque=tpm0-tpm \
-add-fd set=1,fd=1731,opaque=tpm0-cancel \
-add-fd set=0,fd=XXXXXXX,opaque=tpm0-tpm \
-add-fd set=1,fd=XXXXXXX,opaque=tpm0-cancel \
-tpmdev passthrough,id=tpm-tpm0,path=/dev/fdset/0,cancel-path=/dev/fdset/1 \
-device '{"driver":"tpm-crb","tpmdev":"tpm-tpm0","id":"tpm0"}' \
-audiodev '{"id":"audio1","driver":"none"}' \
@@ -27,8 +27,8 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-TPM-VM/.config \
-no-shutdown \
-boot menu=on,strict=on \
-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \
-add-fd set=0,fd=1730,opaque=tpm0-tpm \
-add-fd set=1,fd=1731,opaque=tpm0-cancel \
-add-fd set=0,fd=XXXXXXX,opaque=tpm0-tpm \
-add-fd set=1,fd=XXXXXXX,opaque=tpm0-cancel \
-tpmdev passthrough,id=tpm-tpm0,path=/dev/fdset/0,cancel-path=/dev/fdset/1 \
-device '{"driver":"tpm-tis","tpmdev":"tpm-tpm0","id":"tpm0"}' \
-audiodev '{"id":"audio1","driver":"none"}' \
+193
View File
@@ -40,6 +40,10 @@
static virQEMUDriver driver;
/* this test case uses virTestDummyFDContextNew so we want to mock dup() to
* track FD hints properly */
#include "virmock.h"
VIR_TEST_MAKE_DUMMY_FD_INSTALL_DUP_MOCK
static void
testQemuPrepareHostdevPCI(virDomainHostdevDef *hostdev)
@@ -344,6 +348,191 @@ testCompareXMLToArgvValidateSchema(virCommand *cmd,
}
struct testCompareXMLToArgvStabilizeOneFindJSONObjectIterData {
const char *field;
bool recurse;
virJSONValue *ret;
};
static int
testCompareXMLToArgvStabilizeOneFindJSONObjectIter(const char *key,
virJSONValue *value,
void *opaque)
{
struct testCompareXMLToArgvStabilizeOneFindJSONObjectIterData *data = opaque;
/* negative value breaks iteration and returns specific return value */
if (STREQ(data->field, key))
return -1;
if (!data->recurse)
return 0;
if (!virJSONValueIsObject(value))
return 0;
if (virJSONValueObjectForeachKeyValue(value,
testCompareXMLToArgvStabilizeOneFindJSONObjectIter,
data) == -2) {
/* -2 means that the callback found something; now if it was the above
* call that found the key we need to fill the pointer to what we've
* called it with */
if (data->ret == NULL)
data->ret = value;
return -1;
}
return 0;
}
/**
* testCompareXMLToArgvStabilizeOne:
* @arg: argument to modify (may be replaced by other memory)
* @field: field to replace
* @substitutions: optional hash-table to look up value of @field and replace
* it with the stored string
*
* Takes one qemu argument @arg and replaces the value of '@field' by a stable
* string, either 'XXXXXXX' if @substitutions is NULL or the value of @field
* wasn't found in @substitutions, or with the string from @substitutions if
* found.
*
* Works both on JSON and normal arguments.
*/
static void
testCompareXMLToArgvStabilizeOne(char **arg,
const char *field,
GHashTable *substitutions,
bool recurseJSON)
{
g_autofree char *oldarg = g_steal_pointer(arg);
if (*oldarg == '{') {
g_autoptr(virJSONValue) j = virJSONValueFromString(oldarg);
struct testCompareXMLToArgvStabilizeOneFindJSONObjectIterData data = {
.field = field,
.recurse = recurseJSON,
};
const char *curstr = NULL;
/* Any JSON args will be validated so this ought not to happen */
if (!j) {
*arg = g_steal_pointer(&oldarg);
return;
}
if (virJSONValueObjectForeachKeyValue(j,
testCompareXMLToArgvStabilizeOneFindJSONObjectIter,
&data) == -2) {
/* -2 means that the callback found something; now if it was the above
* call that found the key we need to fill the pointer to what we've
* called it with */
if (data.ret == NULL)
data.ret = j;
}
if (data.ret) {
virJSONValue *cur = virJSONValueObjectGet(data.ret, field);
if (cur) {
switch (virJSONValueGetType(cur)) {
case VIR_JSON_TYPE_STRING:
curstr = virJSONValueGetString(cur);
break;
case VIR_JSON_TYPE_NUMBER:
curstr = virJSONValueGetNumberString(cur);
break;
case VIR_JSON_TYPE_OBJECT:
case VIR_JSON_TYPE_ARRAY:
case VIR_JSON_TYPE_BOOLEAN:
case VIR_JSON_TYPE_NULL:
break;
}
}
}
if (curstr) {
g_autoptr(virJSONValue) newval = NULL;
const char *subst = NULL;
if (substitutions)
subst = g_hash_table_lookup(substitutions, curstr);
if (!subst)
subst = "XXXXXXX";
newval = virJSONValueNewString(g_strdup(subst));
ignore_value(virJSONValueObjectReplaceKey(data.ret, field, &newval));
*arg = virJSONValueToString(j, false);
return;
} else {
*arg = g_steal_pointer(&oldarg);
return;
}
} else {
g_autofree char *fieldmatch = g_strdup_printf("%s=", field);
char *match;
char *val;
char *rest;
const char *subst = NULL;
if (!(match = strstr(oldarg, fieldmatch))) {
*arg = g_steal_pointer(&oldarg);
return;
}
if ((rest = strchr(match, ',')))
*rest = '\0';
*match = '\0';
val = match + strlen(fieldmatch);
if (substitutions)
subst = g_hash_table_lookup(substitutions, val);
if (!subst)
subst = "XXXXXXX";
if (rest)
*rest = ',';
*arg = g_strdup_printf("%s%s%s%s", oldarg, fieldmatch, subst, NULLSTR_EMPTY(rest));
}
}
static void
testCompareXMLToArgvStabilizeArgs(virCommand *cmd,
GHashTable *fdsubsts)
{
char **args;
size_t nargs;
size_t a;
virCommandArgListAccess(cmd, &args, &nargs);
for (a = 0; a < nargs; a++) {
/* Any following replacements want also an argument for an option so
* so we guarantee that there's at least one extra arg */
if (a + 1 >= nargs)
break;
if (STREQ(args[a], "-add-fd")) {
testCompareXMLToArgvStabilizeOne(&args[a + 1], "fd", fdsubsts, false);
a++;
}
}
}
static int
testInfoCheckDuplicate(testQemuInfo *info)
{
@@ -724,6 +913,8 @@ testCompareXMLToArgv(const void *data)
if (testCompareXMLToArgvValidateSchema(cmd, info) < 0)
goto cleanup;
testCompareXMLToArgvStabilizeArgs(cmd, info->fdsubsts);
if (virCommandToStringBuf(cmd, &actualBuf, true, false) < 0)
goto cleanup;
@@ -801,10 +992,12 @@ testRun(const char *name,
g_autofree char *name_argv = g_strdup_printf("QEMU XML def -> ARGV %s%s", name, suffix);
g_autoptr(testQemuInfo) info = g_new0(testQemuInfo, 1);
va_list ap;
g_autoptr(virTestDummyFDContext) fdsubsts = virTestDummyFDContextNew();
info->name = name;
info->suffix = suffix;
info->conf = testConf;
info->fdsubsts = fdsubsts;
va_start(ap, testConf);
testQemuInfoSetArgs(info, ap);
+2
View File
@@ -120,6 +120,8 @@ struct _testQemuInfo {
struct testQemuArgs args;
struct testQemuConf *conf;
GHashTable *fdsubsts;
};
typedef struct _testQemuInfo testQemuInfo;