This patch adds a test case which validates the argv -> XML convertor for QEMU. This re-uses the existing XML data files from the XML -> argv test. This has a few complications though because we can't roundtrip all the data. So I have a couple really seriously evil regexes which splice out the XML lines we know won't match - name, uuid, memory and disk sharing modes. This isn't ideal, but I figure it is better todo this and get coverage over 90% of the code, than to have no test coverage. Thanks to Cole for this testsuite suggestion Daniel diff -r 453b896e0e3f .hgignore --- a/.hgignore Tue May 19 18:43:32 2009 +0100 +++ b/.hgignore Tue May 19 18:43:50 2009 +0100 @@ -270,6 +270,7 @@ tests/object-locking tests/object-locking-files.txt tests/object-locking.cmi tests/object-locking.cmx +tests/qemuargv2xmltest tests/qemuxml2argvtest tests/qemuxml2xmltest tests/qparamtest diff -r 453b896e0e3f tests/.cvsignore --- a/tests/.cvsignore Tue May 19 18:43:32 2009 +0100 +++ b/tests/.cvsignore Tue May 19 18:43:50 2009 +0100 @@ -11,6 +11,7 @@ xmconfigtest xencapstest qemuxml2xmltest qemuxml2argvtest +qemuargv2xmltest nodedevxml2xmltest nodeinfotest statstest diff -r 453b896e0e3f tests/.gitignore --- a/tests/.gitignore Tue May 19 18:43:32 2009 +0100 +++ b/tests/.gitignore Tue May 19 18:43:50 2009 +0100 @@ -11,6 +11,7 @@ xmconfigtest xencapstest qemuxml2xmltest qemuxml2argvtest +qemuargv2xmltest nodedevxml2xmltest nodeinfotest statstest diff -r 453b896e0e3f tests/Makefile.am --- a/tests/Makefile.am Tue May 19 18:43:32 2009 +0100 +++ b/tests/Makefile.am Tue May 19 18:43:50 2009 +0100 @@ -61,7 +61,7 @@ noinst_PROGRAMS += xml2sexprtest sexpr2x reconnect xmconfigtest xencapstest endif if WITH_QEMU -noinst_PROGRAMS += qemuxml2argvtest qemuxml2xmltest +noinst_PROGRAMS += qemuxml2argvtest qemuxml2xmltest qemuargv2xmltest endif if WITH_SECDRIVER_SELINUX @@ -119,7 +119,7 @@ endif endif if WITH_QEMU -TESTS += qemuxml2argvtest qemuxml2xmltest +TESTS += qemuxml2argvtest qemuxml2xmltest qemuargv2xmltest endif if WITH_SECDRIVER_SELINUX @@ -194,8 +194,13 @@ qemuxml2xmltest_SOURCES = \ qemuxml2xmltest.c testutilsqemu.c testutilsqemu.h \ testutils.c testutils.h qemuxml2xmltest_LDADD = ../src/libvirt_driver_qemu.la $(LDADDS) + +qemuargv2xmltest_SOURCES = \ + qemuargv2xmltest.c testutilsqemu.c testutilsqemu.h \ + testutils.c testutils.h +qemuargv2xmltest_LDADD = ../src/libvirt_driver_qemu.la $(LDADDS) else -EXTRA_DIST += qemuxml2argvtest.c qemuxml2xmltest.c testutilsqemu.c testutilsqemu.h +EXTRA_DIST += qemuxml2argvtest.c qemuxml2xmltest.c qemuargv2xmltest.c testutilsqemu.c testutilsqemu.h endif nodedevxml2xmltest_SOURCES = \ diff -r 453b896e0e3f tests/qemuargv2xmltest.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/qemuargv2xmltest.c Tue May 19 18:43:50 2009 +0100 @@ -0,0 +1,235 @@ +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +#include <sys/types.h> +#include <fcntl.h> + +#ifdef WITH_QEMU + +#include "internal.h" +#include "testutils.h" +#include "qemu_conf.h" + +#include "testutilsqemu.h" + +static char *progname; +static char *abs_srcdir; +static struct qemud_driver driver; + +#define MAX_FILE 4096 + +static int blankProblemElements(char *data) +{ + if (virtTestClearLineRegex("<name>[[:alnum:]]+</name>", data) < 0 || + virtTestClearLineRegex("<uuid>([[:alnum:]]|-)+</uuid>", data) < 0 || + virtTestClearLineRegex("<memory>[[:digit:]]+</memory>", data) < 0 || + virtTestClearLineRegex("<currentMemory>[[:digit:]]+</currentMemory>", data) < 0 || + virtTestClearLineRegex("<readonly/>", data) < 0 || + virtTestClearLineRegex("<sharable/>", data) < 0) + return -1; + return 0; +} + +static int testCompareXMLToArgvFiles(const char *xml, + const char *cmdfile) { + char xmlData[MAX_FILE]; + char cmdData[MAX_FILE]; + char *expectxml = &(xmlData[0]); + char *actualxml = NULL; + char *cmd = &(cmdData[0]); + int ret = -1; + virDomainDefPtr vmdef = NULL; + + if (virtTestLoadFile(cmdfile, &cmd, MAX_FILE) < 0) + goto fail; + if (virtTestLoadFile(xml, &expectxml, MAX_FILE) < 0) + goto fail; + + if (!(vmdef = qemuParseCommandLineString(NULL, cmd))) + goto fail; + + if (!(actualxml = virDomainDefFormat(NULL, vmdef, 0))) + goto fail; + + if (blankProblemElements(expectxml) < 0 || + blankProblemElements(actualxml) < 0) + goto fail; + + if (STRNEQ(expectxml, actualxml)) { + virtTestDifference(stderr, expectxml, actualxml); + goto fail; + } + + ret = 0; + + fail: + free(actualxml); + virDomainDefFree(vmdef); + return ret; +} + + +struct testInfo { + const char *name; + int extraFlags; + const char *migrateFrom; +}; + +static int testCompareXMLToArgvHelper(const void *data) { + const struct testInfo *info = data; + char xml[PATH_MAX]; + char args[PATH_MAX]; + snprintf(xml, PATH_MAX, "%s/qemuxml2argvdata/qemuxml2argv-%s.xml", + abs_srcdir, info->name); + snprintf(args, PATH_MAX, "%s/qemuxml2argvdata/qemuxml2argv-%s.args", + abs_srcdir, info->name); + return testCompareXMLToArgvFiles(xml, args); +} + + + +static int +mymain(int argc, char **argv) +{ + int ret = 0; + char cwd[PATH_MAX]; + + progname = argv[0]; + + if (argc > 1) { + fprintf(stderr, "Usage: %s\n", progname); + return (EXIT_FAILURE); + } + + abs_srcdir = getenv("abs_srcdir"); + if (!abs_srcdir) + abs_srcdir = getcwd(cwd, sizeof(cwd)); + + if ((driver.caps = testQemuCapsInit()) == NULL) + return EXIT_FAILURE; + if((driver.stateDir = strdup("/nowhere")) == NULL) + return EXIT_FAILURE; + +#define DO_TEST_FULL(name, extraFlags, migrateFrom) \ + do { \ + const struct testInfo info = { name, extraFlags, migrateFrom }; \ + if (virtTestRun("QEMU ARGV-2-XML " name, \ + 1, testCompareXMLToArgvHelper, &info) < 0) \ + ret = -1; \ + } while (0) + +#define DO_TEST(name, extraFlags) \ + DO_TEST_FULL(name, extraFlags, NULL) + + setenv("PATH", "/bin", 1); + setenv("USER", "test", 1); + setenv("LOGNAME", "test", 1); + setenv("HOME", "/home/test", 1); + unsetenv("TMPDIR"); + unsetenv("LD_PRELOAD"); + unsetenv("LD_LIBRARY_PATH"); + + /* Can't roundtrip vcpu cpuset attribute */ + /*DO_TEST("minimal", QEMUD_CMD_FLAG_NAME);*/ + DO_TEST("boot-cdrom", 0); + DO_TEST("boot-network", 0); + DO_TEST("boot-floppy", 0); + /* Can't roundtrip xenner arch */ + /*DO_TEST("bootloader", 0);*/ + DO_TEST("clock-utc", 0); + DO_TEST("clock-localtime", 0); + DO_TEST("disk-cdrom", 0); + DO_TEST("disk-cdrom-empty", QEMUD_CMD_FLAG_DRIVE); + DO_TEST("disk-floppy", 0); + DO_TEST("disk-many", 0); + DO_TEST("disk-virtio", QEMUD_CMD_FLAG_DRIVE | + QEMUD_CMD_FLAG_DRIVE_BOOT); + DO_TEST("disk-xenvbd", QEMUD_CMD_FLAG_DRIVE | + QEMUD_CMD_FLAG_DRIVE_BOOT); + DO_TEST("disk-drive-boot-disk", QEMUD_CMD_FLAG_DRIVE | + QEMUD_CMD_FLAG_DRIVE_BOOT); + DO_TEST("disk-drive-boot-cdrom", QEMUD_CMD_FLAG_DRIVE | + QEMUD_CMD_FLAG_DRIVE_BOOT); + DO_TEST("disk-drive-fmt-qcow", QEMUD_CMD_FLAG_DRIVE | + QEMUD_CMD_FLAG_DRIVE_BOOT); + /* Can't roundtrip shareable+cache mode option */ + /*DO_TEST("disk-drive-shared", QEMUD_CMD_FLAG_DRIVE);*/ + /* Can't roundtrip v1 writethrough option */ + /*DO_TEST("disk-drive-cache-v1-wt", QEMUD_CMD_FLAG_DRIVE);*/ + DO_TEST("disk-drive-cache-v1-wb", QEMUD_CMD_FLAG_DRIVE); + DO_TEST("disk-drive-cache-v1-none", QEMUD_CMD_FLAG_DRIVE); + DO_TEST("disk-drive-cache-v2-wt", QEMUD_CMD_FLAG_DRIVE | + QEMUD_CMD_FLAG_DRIVE_CACHE_V2); + DO_TEST("disk-drive-cache-v2-wb", QEMUD_CMD_FLAG_DRIVE | + QEMUD_CMD_FLAG_DRIVE_CACHE_V2); + DO_TEST("disk-drive-cache-v2-none", QEMUD_CMD_FLAG_DRIVE | + QEMUD_CMD_FLAG_DRIVE_CACHE_V2); + DO_TEST("disk-usb", 0); + DO_TEST("graphics-vnc", 0); + + driver.vncSASL = 1; + driver.vncSASLdir = strdup("/root/.sasl2"); + DO_TEST("graphics-vnc-sasl", 0); + driver.vncTLS = 1; + driver.vncTLSx509verify = 1; + driver.vncTLSx509certdir = strdup("/etc/pki/tls/qemu"); + DO_TEST("graphics-vnc-tls", 0); + driver.vncSASL = driver.vncTLSx509verify = driver.vncTLS = 0; + free(driver.vncSASLdir); + free(driver.vncTLSx509certdir); + driver.vncSASLdir = driver.vncTLSx509certdir = NULL; + + DO_TEST("graphics-sdl", 0); + DO_TEST("graphics-sdl-fullscreen", 0); + DO_TEST("input-usbmouse", 0); + DO_TEST("input-usbtablet", 0); + /* Can't rountrip xenner arch */ + /*DO_TEST("input-xen", 0);*/ + DO_TEST("misc-acpi", 0); + DO_TEST("misc-no-reboot", 0); + DO_TEST("misc-uuid", QEMUD_CMD_FLAG_NAME | + QEMUD_CMD_FLAG_UUID | QEMUD_CMD_FLAG_DOMID); + DO_TEST("net-user", 0); + DO_TEST("net-virtio", 0); + DO_TEST("net-eth", 0); + DO_TEST("net-eth-ifname", 0); + + DO_TEST("serial-vc", 0); + DO_TEST("serial-pty", 0); + DO_TEST("serial-dev", 0); + DO_TEST("serial-file", 0); + DO_TEST("serial-unix", 0); + DO_TEST("serial-tcp", 0); + DO_TEST("serial-udp", 0); + DO_TEST("serial-tcp-telnet", 0); + DO_TEST("serial-many", 0); + DO_TEST("parallel-tcp", 0); + DO_TEST("console-compat", 0); + DO_TEST("sound", 0); + + DO_TEST("hostdev-usb-product", 0); + DO_TEST("hostdev-usb-address", 0); + + DO_TEST("hostdev-pci-address", 0); + + DO_TEST_FULL("restore-v1", QEMUD_CMD_FLAG_MIGRATE_KVM_STDIO, "stdio"); + DO_TEST_FULL("restore-v2", QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC, "stdio"); + DO_TEST_FULL("restore-v2", QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC, "exec:cat"); + DO_TEST_FULL("migrate", QEMUD_CMD_FLAG_MIGRATE_QEMU_TCP, "tcp:10.0.0.1:5000"); + + virCapabilitiesFree(driver.caps); + + return(ret==0 ? EXIT_SUCCESS : EXIT_FAILURE); +} + +VIRT_TEST_MAIN(mymain) + +#else + +int main (void) { return (77); /* means 'test skipped' for automake */ } + +#endif /* WITH_QEMU */ diff -r 453b896e0e3f tests/qemuxml2argvdata/qemuxml2argv-bootloader.args --- a/tests/qemuxml2argvdata/qemuxml2argv-bootloader.args Tue May 19 18:43:32 2009 +0100 +++ b/tests/qemuxml2argvdata/qemuxml2argv-bootloader.args Tue May 19 18:43:50 2009 +0100 @@ -1,1 +1,1 @@ -LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu-kvm -S -M xenner -m 214 -smp 1 -nographic -monitor pty -no-acpi -bootloader /usr/bin/pygrub -cdrom /dev/cdrom -net none -serial none -parallel none -usb +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/xenner -S -M xenner -m 214 -smp 1 -nographic -monitor pty -no-acpi -bootloader /usr/bin/pygrub -cdrom /dev/cdrom -net none -serial none -parallel none -usb diff -r 453b896e0e3f tests/qemuxml2argvdata/qemuxml2argv-bootloader.xml --- a/tests/qemuxml2argvdata/qemuxml2argv-bootloader.xml Tue May 19 18:43:32 2009 +0100 +++ b/tests/qemuxml2argvdata/qemuxml2argv-bootloader.xml Tue May 19 18:43:50 2009 +0100 @@ -13,7 +13,7 @@ <on_reboot>restart</on_reboot> <on_crash>destroy</on_crash> <devices> - <emulator>/usr/bin/qemu-kvm</emulator> + <emulator>/usr/bin/xenner</emulator> <disk type='block' device='cdrom'> <source dev='/dev/cdrom'/> <target dev='hdc' bus='ide'/> diff -r 453b896e0e3f tests/qemuxml2argvdata/qemuxml2argv-disk-cdrom-empty.xml --- a/tests/qemuxml2argvdata/qemuxml2argv-disk-cdrom-empty.xml Tue May 19 18:43:32 2009 +0100 +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-cdrom-empty.xml Tue May 19 18:43:50 2009 +0100 @@ -24,4 +24,3 @@ </disk> </devices> </domain> - diff -r 453b896e0e3f tests/qemuxml2argvdata/qemuxml2argv-hostdev-pci-address.xml --- a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-pci-address.xml Tue May 19 18:43:32 2009 +0100 +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-pci-address.xml Tue May 19 18:43:50 2009 +0100 @@ -18,7 +18,7 @@ <source dev='/dev/HostVG/QEMUGuest2'/> <target dev='hda' bus='ide'/> </disk> - <hostdev mode='subsystem' type='pci' managed='no'> + <hostdev mode='subsystem' type='pci' managed='yes'> <source> <address domain='0x0000' bus='0x06' slot='0x12' function='0x5'/> </source> diff -r 453b896e0e3f tests/testutils.c --- a/tests/testutils.c Tue May 19 18:43:32 2009 +0100 +++ b/tests/testutils.c Tue May 19 18:43:50 2009 +0100 @@ -18,6 +18,7 @@ #ifndef WIN32 #include <sys/wait.h> #endif +#include <regex.h> #include <unistd.h> #include <string.h> #include <fcntl.h> @@ -457,3 +458,48 @@ cleanup: virResetLastError(); return ret; } + + +int virtTestClearLineRegex(const char *pattern, + char *str) +{ + regex_t reg; + char *lineStart = str; + char *lineEnd = strchr(str, '\n'); + + if (regcomp(®, pattern, REG_EXTENDED | REG_NOSUB) != 0) + return -1; + + while (lineStart) { + int ret; + if (lineEnd) + *lineEnd = '\0'; + + + ret = regexec(®, lineStart, 0, NULL, 0); + //fprintf(stderr, "Match %d '%s' '%s'\n", ret, lineStart, pattern); + if (ret == 0) { + if (lineEnd) { + memmove(lineStart, lineEnd + 1, strlen(lineEnd+1) + 1); + /* Don't update lineStart - just iterate again on this + location */ + lineEnd = strchr(lineStart, '\n'); + } else { + *lineStart = '\0'; + lineStart = NULL; + } + } else { + if (lineEnd) { + *lineEnd = '\n'; + lineStart = lineEnd + 1; + lineEnd = strchr(lineStart, '\n'); + } else { + lineStart = NULL; + } + } + } + + regfree(®); + + return 0; +} diff -r 453b896e0e3f tests/testutils.h --- a/tests/testutils.h Tue May 19 18:43:32 2009 +0100 +++ b/tests/testutils.h Tue May 19 18:43:50 2009 +0100 @@ -27,6 +27,8 @@ int virtTestCaptureProgramOutput(const c char **buf, int buflen); +int virtTestClearLineRegex(const char *pattern, + char *string); int virtTestDifference(FILE *stream, const char *expect, -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list