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(a)redhat.com>
---
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(a)redhat.com>
+ */
+
+#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(a)redhat.com>
+ */
+
+#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