>From da0a52c14cbca5f81c349d030b4d19c59233de82 Mon Sep 17 00:00:00 2001
From: Jim Fehlig <jfehlig@suse.com>
Date: Wed, 22 Feb 2017 16:20:29 -0700
Subject: [PATCH 2/2] libxl: Add a test suite for libxl_domain_config generator

The libxl library allows a libxl_domain_config object to be serialized
from/to a JSON string. Use this to allow testing of the XML to
libxl_domain_config conversion process. Test XML is converted to
libxl_domain_config, which is then serialized to json. A json template
corresponding to the test XML is converted to a libxl_domain_config
object using libxl_domain_config_from_json(), and then serialized
back to json using libxl_domain_config_to_json(). The two json
docs are then compared.

Using libxl to convert the json template to a libxl_domain_config
object and then back to json provides a simple way to account for
any changes or additions to the json representation across Xen
releases.

Signed-off-by: Jim Fehlig <jfehlig@suse.com>
---
 m4/virt-driver-libxl.m4                        |   6 +-
 tests/Makefile.am                              |  18 +-
 tests/libxlxml2domconfigdata/basic-hvm.json    |  89 ++++++++++
 tests/libxlxml2domconfigdata/basic-hvm.xml     |  36 ++++
 tests/libxlxml2domconfigdata/basic-pv.json     |  65 ++++++++
 tests/libxlxml2domconfigdata/basic-pv.xml      |  28 ++++
 tests/libxlxml2domconfigdata/moredevs-hvm.json | 111 +++++++++++++
 tests/libxlxml2domconfigdata/moredevs-hvm.xml  |  63 +++++++
 tests/libxlxml2domconfigtest.c                 | 222 +++++++++++++++++++++++++
 tests/virmocklibxl.c                           |  87 ++++++++++
 10 files changed, 722 insertions(+), 3 deletions(-)
 create mode 100644 tests/libxlxml2domconfigdata/basic-hvm.json
 create mode 100644 tests/libxlxml2domconfigdata/basic-hvm.xml
 create mode 100644 tests/libxlxml2domconfigdata/basic-pv.json
 create mode 100644 tests/libxlxml2domconfigdata/basic-pv.xml
 create mode 100644 tests/libxlxml2domconfigdata/moredevs-hvm.json
 create mode 100644 tests/libxlxml2domconfigdata/moredevs-hvm.xml
 create mode 100644 tests/libxlxml2domconfigtest.c
 create mode 100644 tests/virmocklibxl.c

diff --git a/m4/virt-driver-libxl.m4 b/m4/virt-driver-libxl.m4
index 96a9d4736..3d635f0a6 100644
--- a/m4/virt-driver-libxl.m4
+++ b/m4/virt-driver-libxl.m4
@@ -35,7 +35,7 @@ AC_DEFUN([LIBVIRT_DRIVER_CHECK_LIBXL], [
   if test "x$with_libxl" = "xyes" ; then
     LIBXL_FIRMWARE_DIR=$($PKG_CONFIG --variable xenfirmwaredir xenlight)
     LIBXL_EXECBIN_DIR=$($PKG_CONFIG --variable libexec_bin xenlight)
-  fi
+ fi
 
   dnl pkgconfig file not found, fallback to lib probe
   if test "x$with_libxl" = "xno" ; then
@@ -80,6 +80,10 @@ AC_DEFUN([LIBVIRT_DRIVER_CHECK_LIBXL], [
       LIBXL_LIBS="$LIBXL_LIBS -lxenctrl"
     ])
 
+    dnl Check if libxl_domain_config_from_json is available for domXML to
+    dnl libxl_domain_config tests
+    LIBS="$LIBS -lxenlight -lxenctrl"
+    AC_CHECK_FUNCS([libxl_domain_config_from_json])
     CFLAGS="$old_CFLAGS"
     LIBS="$old_LIBS"
   fi
diff --git a/tests/Makefile.am b/tests/Makefile.am
index af69a3a84..34a17dbaa 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -100,6 +100,7 @@ EXTRA_DIST =		\
 	genericxml2xmlindata \
 	genericxml2xmloutdata \
 	interfaceschemadata \
+	libxlxml2domconfigdata \
 	lxcconf2xmldata \
 	lxcxml2xmldata \
 	lxcxml2xmloutdata \
@@ -268,7 +269,8 @@ test_programs += xml2sexprtest sexpr2xmltest \
 endif WITH_XEN
 
 if WITH_LIBXL
-test_programs += xlconfigtest
+test_programs += xlconfigtest libxlxml2domconfigtest
+test_libraries += virmocklibxl.la
 endif WITH_LIBXL
 
 if WITH_QEMU
@@ -522,8 +524,20 @@ xlconfigtest_SOURCES = \
 	xlconfigtest.c testutilsxen.c testutilsxen.h \
 	testutils.c testutils.h
 xlconfigtest_LDADD =$(libxl_LDADDS)
+
+libxlxml2domconfigtest_SOURCES = \
+	libxlxml2domconfigtest.c testutilsxen.c testutilsxen.h \
+	testutils.c testutils.h
+libxlxml2domconfigtest_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
+
 else ! WITH_LIBXL
-EXTRA_DIST += xlconfigtest.c
+EXTRA_DIST += xlconfigtest.c libxlxml2domconfigtest.c
 endif ! WITH_LIBXL
 
 QEMUMONITORTESTUTILS_SOURCES = \
diff --git a/tests/libxlxml2domconfigdata/basic-hvm.json b/tests/libxlxml2domconfigdata/basic-hvm.json
new file mode 100644
index 000000000..e4771920e
--- /dev/null
+++ b/tests/libxlxml2domconfigdata/basic-hvm.json
@@ -0,0 +1,89 @@
+{
+    "c_info": {
+        "type": "hvm",
+        "name": "test-hvm",
+        "uuid": "2147d599-9cc6-c0dc-92ab-4064b5446e9b"
+    },
+    "b_info": {
+        "max_vcpus": 4,
+        "avail_vcpus": [
+            0,
+            1,
+            2,
+            3
+        ],
+        "max_memkb": 1048576,
+        "target_memkb": 1048576,
+        "video_memkb": 8192,
+        "shadow_memkb": 12288,
+        "device_model_version": "qemu_xen",
+        "device_model": "/usr/lib/xen/bin/qemu-system-i386",
+        "sched_params": {
+            "weight": 1000
+        },
+        "type.hvm": {
+            "pae": "True",
+            "apic": "True",
+            "acpi": "True",
+            "vga": {
+                "kind": "cirrus"
+            },
+            "vnc": {
+                "enable": "True",
+                "listen": "0.0.0.0",
+                "findunused": "False"
+            },
+            "sdl": {
+                "enable": "False"
+            },
+            "spice": {
+
+            },
+            "boot": "c",
+            "rdm": {
+
+            }
+        },
+        "arch_arm": {
+
+        }
+    },
+    "disks": [
+        {
+            "pdev_path": "/var/lib/xen/images/test-hvm.img",
+            "vdev": "hda",
+            "backend": "qdisk",
+            "format": "raw",
+            "removable": 1,
+            "readwrite": 1
+        }
+    ],
+    "nics": [
+        {
+            "devid": 0,
+            "mac": "00:16:3e:66:12:b4",
+            "bridge": "br0",
+            "script": "/etc/xen/scripts/vif-bridge",
+            "nictype": "vif_ioemu"
+        }
+    ],
+    "vfbs": [
+        {
+	    "devid": -1,
+            "vnc": {
+                "enable": "True",
+                "listen": "0.0.0.0",
+                "findunused": "False"
+            },
+            "sdl": {
+                "enable": "False"
+            }
+        }
+    ],
+    "vkbs": [
+        {
+            "devid": -1
+        }
+    ],
+    "on_reboot": "restart"
+}
diff --git a/tests/libxlxml2domconfigdata/basic-hvm.xml b/tests/libxlxml2domconfigdata/basic-hvm.xml
new file mode 100644
index 000000000..9dedf1729
--- /dev/null
+++ b/tests/libxlxml2domconfigdata/basic-hvm.xml
@@ -0,0 +1,36 @@
+<domain type='xen'>
+  <name>test-hvm</name>
+  <description>None</description>
+  <uuid>2147d599-9cc6-c0dc-92ab-4064b5446e9b</uuid>
+  <memory>1048576</memory>
+  <currentMemory>1048576</currentMemory>
+  <vcpu>4</vcpu>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <clock sync='utc'/>
+  <os>
+    <type>hvm</type>
+    <loader>/usr/lib/xen/boot/hvmloader</loader>
+    <boot dev='hd'/>
+  </os>
+  <features>
+    <apic/>
+    <acpi/>
+    <pae/>
+  </features>
+  <devices>
+    <emulator>/usr/lib/xen/bin/qemu-system-i386</emulator>
+    <disk type='file' device='disk'>
+      <driver name='qemu'/>
+      <source file='/var/lib/xen/images/test-hvm.img'/>
+      <target dev='hda'/>
+    </disk>
+    <interface type='bridge'>
+      <source bridge='br0'/>
+      <mac address='00:16:3e:66:12:b4'/>
+      <script path='/etc/xen/scripts/vif-bridge'/>
+    </interface>
+    <graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0'/>
+  </devices>
+</domain>
diff --git a/tests/libxlxml2domconfigdata/basic-pv.json b/tests/libxlxml2domconfigdata/basic-pv.json
new file mode 100644
index 000000000..7e1abd3d6
--- /dev/null
+++ b/tests/libxlxml2domconfigdata/basic-pv.json
@@ -0,0 +1,65 @@
+{
+    "c_info": {
+        "type": "pv",
+        "name": "test-pv",
+        "uuid": "039e9ee6-4a84-3055-4c81-8ba426ae2656"
+    },
+    "b_info": {
+        "max_vcpus": 4,
+        "avail_vcpus": [
+            0,
+            1,
+            2,
+            3
+        ],
+        "max_memkb": 524288,
+        "target_memkb": 524288,
+        "sched_params": {
+            "weight": 1000
+        },
+        "type.pv": {
+            "bootloader": "pygrub"
+        },
+        "arch_arm": {
+
+        }
+    },
+    "disks": [
+        {
+            "pdev_path": "/var/lib/xen/images/test-pv.img",
+            "vdev": "xvda",
+            "backend": "qdisk",
+            "format": "raw",
+            "removable": 1,
+            "readwrite": 1
+        }
+    ],
+    "nics": [
+        {
+            "devid": 0,
+            "mac": "00:16:3e:3e:86:60",
+            "bridge": "br0",
+            "script": "/etc/xen/scripts/vif-bridge",
+            "nictype": "vif"
+        }
+    ],
+    "vfbs": [
+        {
+	    "devid": -1,
+            "vnc": {
+                "enable": "True",
+                "listen": "0.0.0.0",
+                "findunused": "False"
+            },
+            "sdl": {
+                "enable": "False"
+            }
+        }
+    ],
+    "vkbs": [
+        {
+	    "devid": -1
+        }
+    ],
+    "on_reboot": "restart"
+}
diff --git a/tests/libxlxml2domconfigdata/basic-pv.xml b/tests/libxlxml2domconfigdata/basic-pv.xml
new file mode 100644
index 000000000..b3bc6012d
--- /dev/null
+++ b/tests/libxlxml2domconfigdata/basic-pv.xml
@@ -0,0 +1,28 @@
+<domain type='xen'>
+  <name>test-pv</name>
+  <uuid>039e9ee6-4a84-3055-4c81-8ba426ae2656</uuid>
+  <memory>524288</memory>
+  <currentMemory>524288</currentMemory>
+  <vcpu>4</vcpu>
+  <bootloader>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>destroy</on_crash>
+  <devices>
+    <disk type='file' device='disk'>
+      <driver name='qemu'/>
+      <source file='/var/lib/xen/images/test-pv.img'/>
+      <target dev='xvda'/>
+    </disk>
+    <interface type='bridge'>
+      <source bridge='br0'/>
+      <mac address='00:16:3e:3e:86:60'/>
+      <script path='/etc/xen/scripts/vif-bridge'/>
+    </interface>
+    <graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0'/>
+  </devices>
+</domain>
diff --git a/tests/libxlxml2domconfigdata/moredevs-hvm.json b/tests/libxlxml2domconfigdata/moredevs-hvm.json
new file mode 100644
index 000000000..70840d2b3
--- /dev/null
+++ b/tests/libxlxml2domconfigdata/moredevs-hvm.json
@@ -0,0 +1,111 @@
+{
+    "c_info": {
+        "type": "hvm",
+        "hap": "True",
+        "name": "test-hvm",
+        "uuid": "2147d599-9cc6-c0dc-92ab-4064b5446e9b"
+    },
+    "b_info": {
+        "max_vcpus": 4,
+        "avail_vcpus": [
+            0,
+            1,
+            2,
+            3
+        ],
+        "tsc_mode": "native",
+        "max_memkb": 1048576,
+        "target_memkb": 1048576,
+        "video_memkb": 8192,
+        "shadow_memkb": 12288,
+        "device_model_version": "qemu_xen",
+        "device_model": "/usr/lib/xen/bin/qemu-system-i386",
+        "sched_params": {
+            "weight": 1000
+        },
+        "type.hvm": {
+            "pae": "True",
+            "apic": "True",
+            "acpi": "True",
+            "hpet": "True",
+            "vga": {
+                "kind": "cirrus"
+            },
+            "vnc": {
+                "enable": "True",
+                "findunused": "False"
+            },
+            "sdl": {
+                "enable": "False"
+            },
+            "spice": {
+
+            },
+            "serial": "pty",
+            "boot": "c",
+            "usbdevice_list": [
+                "mouse",
+                "tablet"
+            ],
+            "rdm": {
+
+            }
+        },
+        "arch_arm": {
+
+        }
+    },
+    "disks": [
+        {
+            "pdev_path": "/var/lib/xen/images/test-hvm.img",
+            "vdev": "hda",
+            "backend": "qdisk",
+            "format": "raw",
+            "removable": 1,
+            "readwrite": 1
+        },
+        {
+            "pdev_path": "/root/boot.iso",
+            "vdev": "hdb",
+            "backend": "qdisk",
+            "format": "raw",
+            "removable": 1,
+            "is_cdrom": 1
+        }
+    ],
+    "nics": [
+        {
+            "devid": 0,
+            "model": "netfront",
+            "mac": "00:16:3e:7a:35:ce",
+            "bridge": "br0",
+            "script": "/etc/xen/scripts/vif-bridge",
+            "nictype": "vif"
+        }
+    ],
+    "pcidevs": [
+        {
+            "dev": 16,
+            "bus": 10,
+	    "rdm_policy": "invalid"
+        }
+    ],
+    "vfbs": [
+        {
+	    "devid": -1,
+            "vnc": {
+                "enable": "True",
+                "findunused": "False"
+            },
+            "sdl": {
+                "enable": "False"
+            }
+        }
+    ],
+    "vkbs": [
+        {
+	    "devid": -1
+        }
+    ],
+    "on_reboot": "restart"
+}
diff --git a/tests/libxlxml2domconfigdata/moredevs-hvm.xml b/tests/libxlxml2domconfigdata/moredevs-hvm.xml
new file mode 100644
index 000000000..e93e153c5
--- /dev/null
+++ b/tests/libxlxml2domconfigdata/moredevs-hvm.xml
@@ -0,0 +1,63 @@
+<domain type='xen'>
+  <name>test-hvm</name>
+  <description>None</description>
+  <uuid>2147d599-9cc6-c0dc-92ab-4064b5446e9b</uuid>
+  <memory>1048576</memory>
+  <currentMemory>1048576</currentMemory>
+  <vcpu>4</vcpu>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <clock offset='variable' adjustment='0' basis='utc'>
+    <timer name='tsc' present='yes' mode='native'/>
+    <timer name='hpet' present='yes'/>
+  </clock>
+  <os>
+    <type>hvm</type>
+    <loader>/usr/lib/xen/boot/hvmloader</loader>
+    <boot dev='hd'/>
+  </os>
+  <features>
+    <apic/>
+    <acpi/>
+    <pae/>
+    <hap/>
+  </features>
+  <devices>
+    <emulator>/usr/lib/xen/bin/qemu-system-i386</emulator>
+    <disk type='file' device='disk'>
+      <driver name='qemu' type='raw' cache='default'/>
+      <source file='/var/lib/xen/images/test-hvm.img'/>
+      <target dev='hda'/>
+    </disk>
+    <disk type='file' device='cdrom'>
+      <driver name='qemu' type='raw' cache='default'/>
+      <source file='/root/boot.iso'/>
+      <target dev='hdb'/>
+    </disk>
+    <interface type='bridge'>
+      <source bridge='br0'/>
+      <mac address='00:16:3e:7a:35:ce'/>
+      <script path='/etc/xen/scripts/vif-bridge'/>
+      <model type='netfront'/>
+    </interface>
+    <interface type='hostdev' managed='yes'>
+      <mac address='00:16:3e:2e:e7:fc'/>
+      <driver name='xen'/>
+      <source>
+        <address type='pci' domain='0x0000' bus='0x0a' slot='0x10' function='0x0'/>
+      </source>
+    </interface>
+    <graphics type='vnc'/>
+    <video>
+      <model type='cirrus' vram='8192' heads='1' primary='yes'/>
+    </video>
+    <console type='pty'>
+      <target port='0'/>
+    </console>
+    <input type='mouse' bus='usb'/>
+    <input type='tablet' bus='usb'/>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+  </devices>
+</domain>
diff --git a/tests/libxlxml2domconfigtest.c b/tests/libxlxml2domconfigtest.c
new file mode 100644
index 000000000..2782eaf4a
--- /dev/null
+++ b/tests/libxlxml2domconfigtest.c
@@ -0,0 +1,222 @@
+/*
+ * libxlxml2domconfigtest.c: test conversion of domXML to
+ * libxl_domain_config structure.
+ *
+ * Copyright (C) 2017 SUSE LINUX Products GmbH, Nuernberg, Germany.
+ *
+ * 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: Jim Fehlig <jfehlig@suse.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) && defined(HAVE_LIBXL_DOMAIN_CONFIG_FROM_JSON)
+
+# include "internal.h"
+# include "viralloc.h"
+# include "libxl/libxl_conf.h"
+# include "datatypes.h"
+# include "virstring.h"
+# include "virmock.h"
+# include "virjson.h"
+# include "testutilsxen.h"
+
+# define VIR_FROM_THIS VIR_FROM_LIBXL
+
+static const char *abs_top_srcdir;
+static virCapsPtr xencaps;
+
+# ifdef LIBXL_EMULATOR_TYPE
+#  undef LIBXL_EMULATOR_TYPE
+#  define LIBXL_EMULATOR_TYPE
+# endif
+
+# ifdef LIBXL_CHECK_EMULATOR
+#  undef LIBXL_CHECK_EMULATOR
+#  undef LIBXL_CHECK_EMULATOR              \
+{                                         \
+    *ret = 0;                             \
+}
+# endif
+
+static int testCompareXMLToDomConfig(const char *xmlfile,
+                                     const char *jsonfile)
+{
+    int ret = -1;
+    libxl_domain_config actualconfig;
+    libxl_domain_config expectconfig;
+    xentoollog_logger *log = NULL;
+    libxl_ctx *ctx = NULL;
+    virPortAllocatorPtr gports = NULL;
+    virDomainXMLOptionPtr xmlopt = NULL;
+    virDomainDefPtr vmdef = NULL;
+    char *actualjson = NULL;
+    char *tempjson = NULL;
+    char *expectjson = NULL;
+
+    libxl_domain_config_init(&actualconfig);
+    libxl_domain_config_init(&expectconfig);
+
+    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,
+                                       VIR_PORT_ALLOCATOR_SKIP_BIND_CHECK)))
+        goto cleanup;
+
+    if (!(xmlopt = libxlCreateXMLConf()))
+        goto cleanup;
+
+    if (!(vmdef = virDomainDefParseFile(xmlfile, xencaps, xmlopt,
+                                        NULL, VIR_DOMAIN_XML_INACTIVE)))
+        goto cleanup;
+
+    if (libxlBuildDomainConfig(gports, vmdef, NULL, ctx, &actualconfig) < 0)
+        goto cleanup;
+
+    if (!(actualjson = libxl_domain_config_to_json(ctx, &actualconfig))) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       "Failed to retrieve JSON doc for libxl_domain_config");
+        goto cleanup;
+    }
+    printf("\nlibvirt converted json:\n%s\n", actualjson);
+
+    virTestLoadFile(jsonfile, &tempjson);
+    if (libxl_domain_config_from_json(ctx, &expectconfig, tempjson) != 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       "Failed to create libxl_domain_config from JSON doc");
+        goto cleanup;
+    }
+    if (!(expectjson = libxl_domain_config_to_json(ctx, &expectconfig))) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       "Failed to retrieve JSON doc for libxl_domain_config");
+        goto cleanup;
+    }
+    printf("\nlibxl converted json:\n%s\n", expectjson);
+
+    if (strcmp(expectjson, actualjson)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       "Expected and actual libxl_domain_config objects do not compare");
+        goto cleanup;
+    }
+
+    ret = 0;
+
+ cleanup:
+    VIR_FREE(expectjson);
+    VIR_FREE(actualjson);
+    VIR_FREE(tempjson);
+    virDomainDefFree(vmdef);
+    virObjectUnref(gports);
+    virObjectUnref(xmlopt);
+    libxl_ctx_free(ctx);
+    libxl_domain_config_dispose(&actualconfig);
+    libxl_domain_config_dispose(&expectconfig);
+    xtl_logger_destroy(log);
+    return ret;
+}
+
+
+struct testInfo {
+    const char *name;
+};
+
+
+static int
+testCompareXMLToDomConfigHelper(const void *data)
+{
+    int ret = -1;
+    const struct testInfo *info = data;
+    char *xmlfile = NULL;
+    char *jsonfile = NULL;
+
+    if (virAsprintf(&xmlfile, "%s/libxlxml2domconfigdata/%s.xml",
+                    abs_srcdir, info->name) < 0 ||
+        virAsprintf(&jsonfile, "%s/libxlxml2domconfigdata/%s.json",
+                    abs_srcdir, info->name) < 0)
+        goto cleanup;
+
+    ret = testCompareXMLToDomConfig(xmlfile, jsonfile);
+
+ cleanup:
+    VIR_FREE(xmlfile);
+    VIR_FREE(jsonfile);
+    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 (virTestRun("LibXL XML-2-JSON " name,                        \
+                        testCompareXMLToDomConfigHelper, &info) < 0)    \
+            ret = -1;                                                   \
+    } while (0)
+
+    DO_TEST("basic-pv");
+    DO_TEST("basic-hvm");
+    DO_TEST("moredevs-hvm");
+
+    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_LIBXL && WITH_YAJL && HAVE_LIBXL_DOMAIN_CONFIG_FROM_JSON */
diff --git a/tests/virmocklibxl.c b/tests/virmocklibxl.c
new file mode 100644
index 000000000..bc4b53d68
--- /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@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 */
-- 
2.13.1

