The libxl library allows a libxl_domain_config object to be serialized to a JSON string. Use this to allow testing of the XML -> libxl_domain_config conversion process Signed-off-by: Daniel P. Berrange <berrange@xxxxxxxxxx> --- tests/Makefile.am | 25 +++- tests/libxlxml2jsondata/minimal.json | 172 +++++++++++++++++++++++++++ tests/libxlxml2jsondata/minimal.xml | 36 ++++++ tests/libxlxml2jsontest.c | 219 +++++++++++++++++++++++++++++++++++ tests/virmocklibxl.c | 87 ++++++++++++++ 5 files changed, 538 insertions(+), 1 deletion(-) create mode 100644 tests/libxlxml2jsondata/minimal.json create mode 100644 tests/libxlxml2jsondata/minimal.xml create mode 100644 tests/libxlxml2jsontest.c create mode 100644 tests/virmocklibxl.c diff --git a/tests/Makefile.am b/tests/Makefile.am index 5ef8940..a988342 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -82,6 +82,7 @@ EXTRA_DIST = \ domainsnapshotxml2xmlout \ fchostdata \ interfaceschemadata \ + libxlxml2jsondata \ lxcconf2xmldata \ lxcxml2xmldata \ lxcxml2xmloutdata \ @@ -216,6 +217,9 @@ if WITH_XEN test_programs += xml2sexprtest sexpr2xmltest \ xmconfigtest xencapstest statstest reconnect endif WITH_XEN +if WITH_LIBXL +test_programs += libxlxml2jsontest +endif WITH_LIBXL if WITH_QEMU test_programs += qemuxml2argvtest qemuxml2xmltest qemuxmlnstest \ qemuargv2xmltest qemuhelptest domainsnapshotxml2xmltest \ @@ -378,7 +382,9 @@ test_libraries += libqemumonitortestutils.la \ qemuxml2argvmock.la \ $(NULL) endif WITH_QEMU - +if WITH_LIBXL +test_libraries += virmocklibxl.la +endif WITH_LIBXL if WITH_BHYVE test_libraries += bhyvexml2argvmock.la endif WITH_BHYVE @@ -577,6 +583,23 @@ EXTRA_DIST += qemuxml2argvtest.c qemuxml2xmltest.c qemuargv2xmltest.c \ $(QEMUMONITORTESTUTILS_SOURCES) endif ! WITH_QEMU +if WITH_LIBXL +libxl_LDADDS = ../src/libvirt_driver_libxl_impl.la +libxl_LDADDS += $(LDADDS) + +libxlxml2jsontest_SOURCES = \ + libxlxml2jsontest.c testutilsxen.c testutilsxen.h \ + testutils.c testutils.h +libxlxml2jsontest_LDADD = $(libxl_LDADDS) $(LIBXML_LIBS) + +virmocklibxl_la_SOURCES = \ + virmocklibxl.c +virmocklibxl_la_CFLAGS = $(AM_CFLAGS) +virmocklibxl_la_LDFLAGS = -module -avoid-version \ + -rpath /evil/libtool/hack/to/force/shared/lib/creation + +endif WITH_LIBXL + if WITH_LXC lxc_LDADDS = ../src/libvirt_driver_lxc_impl.la diff --git a/tests/libxlxml2jsondata/minimal.json b/tests/libxlxml2jsondata/minimal.json new file mode 100644 index 0000000..930e1d8 --- /dev/null +++ b/tests/libxlxml2jsondata/minimal.json @@ -0,0 +1,172 @@ +{ + "c_info": { + "type": "pv", + "hap": "<default>", + "oos": "<default>", + "ssidref": 0, + "name": "rhel5pv", + "uuid": "8f07fe28-753f-2729-d76d-bdbd892f949a", + "xsdata": { + + }, + "platformdata": { + + }, + "poolid": 0, + "run_hotplug_scripts": "<default>" + }, + "b_info": { + "max_vcpus": 4, + "avail_vcpus": [ + 0, + 1, + 2, + 3 + ], + "cpumap": [ + + ], + "nodemap": [ + + ], + "numa_placement": "<default>", + "tsc_mode": "default", + "max_memkb": 2560000, + "target_memkb": 307200, + "video_memkb": -1, + "shadow_memkb": -1, + "rtc_timeoffset": 0, + "exec_ssidref": 0, + "localtime": "<default>", + "disable_migrate": "<default>", + "cpuid": [ + + ], + "blkdev_start": null, + "device_model_version": null, + "device_model_stubdomain": "<default>", + "device_model": null, + "device_model_ssidref": 0, + "extra": [ + + ], + "extra_pv": [ + + ], + "extra_hvm": [ + + ], + "sched_params": { + "sched": "unknown", + "weight": 1000, + "cap": -1, + "period": -1, + "slice": -1, + "latency": -1, + "extratime": -1 + }, + "ioports": [ + + ], + "irqs": [ + + ], + "iomem": [ + + ], + "claim_mode": "<default>", + "u": { + "kernel": null, + "slack_memkb": -1, + "bootloader": "/usr/bin/pygrub", + "bootloader_args": [ + + ], + "cmdline": null, + "ramdisk": null, + "e820_host": "<default>" + } + }, + "disks": [ + { + "backend_domid": 0, + "backend_domname": null, + "pdev_path": "/var/lib/xen/images/rhel5pv.img", + "vdev": "xvda", + "backend": "tap", + "format": "raw", + "script": null, + "removable": 1, + "readwrite": 1, + "is_cdrom": 0 + }, + { + "backend_domid": 0, + "backend_domname": null, + "pdev_path": "/root/qcow1-xen.img", + "vdev": "xvdd", + "backend": "qdisk", + "format": "qcow", + "script": null, + "removable": 1, + "readwrite": 1, + "is_cdrom": 0 + } + ], + "nics": [ + { + "backend_domid": 0, + "backend_domname": null, + "devid": 0, + "mtu": 0, + "model": null, + "mac": "00:16:3e:60:36:ba", + "ip": null, + "bridge": "xenbr0", + "ifname": null, + "script": null, + "nictype": "vif", + "rate_bytes_per_interval": 0, + "rate_interval_usecs": 0, + "gatewaydev": null + } + ], + "pcidevs": [ + + ], + "vfbs": [ + { + "backend_domid": 0, + "backend_domname": null, + "devid": -1, + "vnc": { + "enable": "True", + "listen": "0.0.0.0", + "passwd": null, + "display": 0, + "findunused": "False" + }, + "sdl": { + "enable": "<default>", + "opengl": "<default>", + "display": null, + "xauthority": null + }, + "keymap": null + } + ], + "vkbs": [ + { + "backend_domid": 0, + "backend_domname": null, + "devid": -1 + } + ], + "vtpms": [ + + ], + "on_poweroff": null, + "on_reboot": "destroy", + "on_watchdog": null, + "on_crash": "destroy" +} diff --git a/tests/libxlxml2jsondata/minimal.xml b/tests/libxlxml2jsondata/minimal.xml new file mode 100644 index 0000000..1361028 --- /dev/null +++ b/tests/libxlxml2jsondata/minimal.xml @@ -0,0 +1,36 @@ +<domain type='xen'> + <name>rhel5pv</name> + <uuid>8f07fe28-753f-2729-d76d-bdbd892f949a</uuid> + <memory>2560000</memory> + <currentMemory>307200</currentMemory> + <vcpu>4</vcpu> + <bootloader>/usr/bin/pygrub</bootloader> + <os> + <type arch='i686' machine='xenpv'>linux</type> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> + <devices> + <disk type='file' device='disk'> + <driver name='tap' type='aio'/> + <source file='/var/lib/xen/images/rhel5pv.img'/> + <target dev='xvda' bus='xen'/> + </disk> + <disk type='file' device='disk'> + <driver name='tap' type='qcow'/> + <source file='/root/qcow1-xen.img'/> + <target dev='xvdd' bus='xen'/> + </disk> + <interface type='bridge'> + <mac address='00:16:3e:60:36:ba'/> + <source bridge='xenbr0'/> + </interface> + <console type='pty'> + <target port='0'/> + </console> + <input type='mouse' bus='xen'/> + <graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0'/> + </devices> +</domain> diff --git a/tests/libxlxml2jsontest.c b/tests/libxlxml2jsontest.c new file mode 100644 index 0000000..02808b7 --- /dev/null +++ b/tests/libxlxml2jsontest.c @@ -0,0 +1,219 @@ +/* + * Copyright (C) 2014 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + * + * Author: Daniel P. Berrange <berrange@xxxxxxxxxx> + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +#include <sys/types.h> +#include <fcntl.h> + +#include "testutils.h" + +#if defined(WITH_LIBXL) && defined(WITH_YAJL) + +# include "internal.h" +# include "viralloc.h" +# include "libxl/libxl_conf.h" +# include "datatypes.h" +# include "virstring.h" +# include "virmock.h" +# include "testutilsxen.h" + +# ifdef WITH_YAJL2 +# define HAVE_YAJL_V2 +# endif + +# include <yajl/yajl_gen.h> +# include <libxl_json.h> + +# define VIR_FROM_THIS VIR_FROM_XEN + +static const char *abs_top_srcdir; +static virCapsPtr xencaps; + +# ifdef WITH_YAJL2 +# define yajl_size_t size_t +# else +# define yajl_size_t unsigned int +# endif + +static int testCompareXMLToJSONFiles(const char *xml, + const char *cmdline) +{ + char *expectargv = NULL; + int ret = -1; + virDomainDefPtr vmdef = NULL; + virPortAllocatorPtr gports = NULL; + libxl_ctx *ctx = NULL; + libxl_domain_config config; + xentoollog_logger *log = NULL; + virDomainXMLOptionPtr xmlopt = NULL; + yajl_gen gen; +# ifndef WITH_YAJL2 + yajl_gen_config conf = { 1, " " }; +# endif + const unsigned char *actualargv; + yajl_size_t actualargvlen; + + libxl_domain_config_init(&config); + +# ifdef WITH_YAJL2 + gen = yajl_gen_alloc(NULL); + if (gen) { + yajl_gen_config(gen, yajl_gen_beautify, 1); + yajl_gen_config(gen, yajl_gen_indent_string, " "); + yajl_gen_config(gen, yajl_gen_validate_utf8, 1); + } +# else + gen = yajl_gen_alloc(&conf, NULL); +# endif + if (!gen) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + "Unable to create JSON formatter"); + goto cleanup; + } + + if (!(log = (xentoollog_logger *)xtl_createlogger_stdiostream(stderr, XTL_DEBUG, 0))) + goto cleanup; + + if (libxl_ctx_alloc(&ctx, LIBXL_VERSION, 0, log) < 0) + goto cleanup; + + if (!(gports = virPortAllocatorNew("vnc", 5900, 6000))) + goto cleanup; + + if (!(xmlopt = libxlCreateXMLConf())) + goto cleanup; + + if (!(vmdef = virDomainDefParseFile(xml, xencaps, xmlopt, + 1 << VIR_DOMAIN_VIRT_XEN, + VIR_DOMAIN_XML_INACTIVE))) + goto cleanup; + + if (libxlBuildDomainConfig(gports, vmdef, ctx, &config) < 0) + goto cleanup; + + libxl_domain_config_gen_json(gen, &config); + + if (yajl_gen_get_buf(gen, &actualargv, &actualargvlen) != yajl_gen_status_ok) { + virReportOOMError(); + goto cleanup; + } + + virtTestLoadFile(cmdline, &expectargv); + + if (STRNEQ(expectargv, (char *)actualargv)) { + virtTestDifference(stderr, expectargv, (char *)actualargv); + goto cleanup; + } + + ret = 0; + + cleanup: + yajl_gen_free(gen); + VIR_FREE(expectargv); + virDomainDefFree(vmdef); + virObjectUnref(gports); + virObjectUnref(xmlopt); + libxl_ctx_free(ctx); + libxl_domain_config_dispose(&config); + xtl_logger_destroy(log); + return ret; +} + + +struct testInfo { + const char *name; +}; + +static int +testCompareXMLToJSONHelper(const void *data) +{ + int ret = -1; + const struct testInfo *info = data; + char *xml = NULL; + char *args = NULL; + + if (virAsprintf(&xml, "%s/libxlxml2jsondata/%s.xml", + abs_srcdir, info->name) < 0 || + virAsprintf(&args, "%s/libxlxml2jsondata/%s.json", + abs_srcdir, info->name) < 0) + goto cleanup; + + ret = testCompareXMLToJSONFiles(xml, args); + + cleanup: + VIR_FREE(xml); + VIR_FREE(args); + return ret; +} + + +static int +mymain(void) +{ + int ret = 0; + + abs_top_srcdir = getenv("abs_top_srcdir"); + if (!abs_top_srcdir) + abs_top_srcdir = abs_srcdir "/.."; + + /* Set the timezone because we are mocking the time() function. + * If we don't do that, then localtime() may return unpredictable + * results. In order to detect things that just work by a blind + * chance, we need to set an virtual timezone that no libvirt + * developer resides in. */ + if (setenv("TZ", "VIR00:30", 1) < 0) { + perror("setenv"); + return EXIT_FAILURE; + } + + if ((xencaps = testXenCapsInit()) == NULL) + return EXIT_FAILURE; + +# define DO_TEST(name) \ + do { \ + static struct testInfo info = { \ + name, \ + }; \ + if (virtTestRun("LibXL XML-2-JSON " name, \ + testCompareXMLToJSONHelper, &info) < 0) \ + ret = -1; \ + } while (0) + + DO_TEST("minimal"); + + return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; +} + +VIRT_TEST_MAIN_PRELOAD(mymain, abs_builddir "/.libs/virmocklibxl.so") + +#else + +int main(void) +{ + return EXIT_AM_SKIP; +} + +#endif /* WITH_XEN && WITH_YAJL */ diff --git a/tests/virmocklibxl.c b/tests/virmocklibxl.c new file mode 100644 index 0000000..bc4b53d --- /dev/null +++ b/tests/virmocklibxl.c @@ -0,0 +1,87 @@ +/* + * virmocklibxl.c: mocking of xenstore/libxs for libxl + * + * Copyright (C) 2014 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + * + * Author: Daniel P. Berrange <berrange@xxxxxxxxxx> + */ + +#include <config.h> + +#if defined(WITH_LIBXL) && defined(WITH_YAJL) +# include "virmock.h" +# include <sys/stat.h> +# include <unistd.h> +# include <libxl.h> +# include <xenstore.h> +# include <xenctrl.h> + +VIR_MOCK_IMPL_RET_VOID(xs_daemon_open, + struct xs_handle *) +{ + VIR_MOCK_REAL_INIT(xs_daemon_open); + return (void*)0x1; +} + +VIR_MOCK_IMPL_RET_ARGS(xc_interface_open, + xc_interface *, + xentoollog_logger *, logger, + xentoollog_logger *, dombuild_logger, + unsigned, open_flags) +{ + VIR_MOCK_REAL_INIT(xc_interface_open); + return (void*)0x1; +} + + +VIR_MOCK_STUB_RET_ARGS(xc_interface_close, + int, 0, + xc_interface *, handle) + +VIR_MOCK_STUB_VOID_ARGS(xs_daemon_close, + struct xs_handle *, handle) + +VIR_MOCK_IMPL_RET_ARGS(__xstat, int, + int, ver, + const char *, path, + struct stat *, sb) +{ + VIR_MOCK_REAL_INIT(__xstat); + + if (strstr(path, "xenstored.pid")) { + memset(sb, 0, sizeof(*sb)); + return 0; + } + + return real___xstat(ver, path, sb); +} + +VIR_MOCK_IMPL_RET_ARGS(stat, int, + const char *, path, + struct stat *, sb) +{ + VIR_MOCK_REAL_INIT(stat); + + if (strstr(path, "xenstored.pid")) { + memset(sb, 0, sizeof(*sb)); + return 0; + } + + return real_stat(path, sb); +} + +#endif /* WITH_LIBXL && WITH_YAJL */ -- 1.9.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list