xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
* [PATCH V4 0/3] Testing libvirt XML -> libxl_domain_config conversion
@ 2014-09-11 23:09 Jim Fehlig
  2014-09-11 23:09 ` [PATCH V4 1/3] util: Introduce virJSONStringCompare for JSON doc comparisons Jim Fehlig
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Jim Fehlig @ 2014-09-11 23:09 UTC (permalink / raw)
  To: libvir-list; +Cc: xen-devel

This is version 4 of the work started by danpb:

  https://www.redhat.com/archives/libvir-list/2014-May/msg01102.html

This series tests the conversion of libvirt XML to libxl_domain_config
objects by the libvirt libxl driver.

Changed in V4:

 - V3 patches 2-4 have been pushed
 - Patch 1 is unchanged from V3
 - Patch 2 is new and adds tests for virJSONStringCompare
 - Cleanup of ignored context paths definition in patch 3
   (was #5 in V3) 

Daniel P. Berrange (2):
  util: Introduce virJSONStringCompare for JSON doc comparisons
  libxl: Add a test suite for libxl option generator

Jim Fehlig (1):
  tests: add tests for virJSONStringCompare

 configure.ac                           |   2 +
 src/libvirt_private.syms               |   1 +
 src/util/virjson.c                     | 242 +++++++++++++++++++++++++++++++++
 src/util/virjson.h                     |  16 +++
 tests/Makefile.am                      |  25 +++-
 tests/jsontest.c                       |  63 ++++++++-
 tests/libxlxml2jsondata/basic-hvm.json | 217 +++++++++++++++++++++++++++++
 tests/libxlxml2jsondata/basic-hvm.xml  |  36 +++++
 tests/libxlxml2jsondata/basic-pv.json  | 163 ++++++++++++++++++++++
 tests/libxlxml2jsondata/basic-pv.xml   |  28 ++++
 tests/libxlxml2jsontest.c              | 228 +++++++++++++++++++++++++++++++
 tests/virmocklibxl.c                   |  87 ++++++++++++
 12 files changed, 1102 insertions(+), 6 deletions(-)
 create mode 100644 tests/libxlxml2jsondata/basic-hvm.json
 create mode 100644 tests/libxlxml2jsondata/basic-hvm.xml
 create mode 100644 tests/libxlxml2jsondata/basic-pv.json
 create mode 100644 tests/libxlxml2jsondata/basic-pv.xml
 create mode 100644 tests/libxlxml2jsontest.c
 create mode 100644 tests/virmocklibxl.c

-- 
1.8.4.5

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH V4 1/3] util: Introduce virJSONStringCompare for JSON doc comparisons
  2014-09-11 23:09 [PATCH V4 0/3] Testing libvirt XML -> libxl_domain_config conversion Jim Fehlig
@ 2014-09-11 23:09 ` Jim Fehlig
  2014-09-11 23:09 ` [PATCH V4 2/3] tests: add tests for virJSONStringCompare Jim Fehlig
  2014-09-11 23:09 ` [PATCH V4 3/3] libxl: Add a test suite for libxl option generator Jim Fehlig
  2 siblings, 0 replies; 4+ messages in thread
From: Jim Fehlig @ 2014-09-11 23:09 UTC (permalink / raw)
  To: libvir-list; +Cc: Jim Fehlig, Daniel P. Berrange, xen-devel

From: "Daniel P. Berrange" <berrange@redhat.com>

Comparing JSON docs using strcmp is simple, but is not flexible
as it is sensitive to whitespace used in the doc generation.
When comparing objects it may also be desirable to treat the
existance of keys in the actual object but not expected object
as non-fatal. Introduce a virJSONStringCompare function which
takes two strings representing expected and actual JSON docs
and then does a DOM comparison.  Comparison is controled with
the ignore_contexts and flags parameters.  No comparison is
done on context paths specified in ignore_contexts.  The
VIR_JSON_COMPARE_IGNORE_EXPECTED_NULL flag can be used to
ignore actual values that have changed from an expected value
of null.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Signed-off-by: Jim Fehlig <jfehlig@suse.com>
---

Beyond rebasing, unchanged from V3.

 src/libvirt_private.syms |   1 +
 src/util/virjson.c       | 242 +++++++++++++++++++++++++++++++++++++++++++++++
 src/util/virjson.h       |  16 ++++
 3 files changed, 259 insertions(+)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index fdf4548..b0c0625 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1446,6 +1446,7 @@ virISCSIScanTargets;
 
 
 # util/virjson.h
+virJSONStringCompare;
 virJSONValueArrayAppend;
 virJSONValueArrayGet;
 virJSONValueArraySize;
diff --git a/src/util/virjson.c b/src/util/virjson.c
index ec83b2f..73b71f4 100644
--- a/src/util/virjson.c
+++ b/src/util/virjson.c
@@ -47,6 +47,11 @@
 
 VIR_LOG_INIT("util.json");
 
+VIR_ENUM_DECL(virJSONType)
+VIR_ENUM_IMPL(virJSONType, VIR_JSON_TYPE_LAST,
+              "object", "array", "string",
+              "number", "boolean", "null")
+
 typedef struct _virJSONParserState virJSONParserState;
 typedef virJSONParserState *virJSONParserStatePtr;
 struct _virJSONParserState {
@@ -91,6 +96,7 @@ virJSONValueFree(virJSONValuePtr value)
         break;
     case VIR_JSON_TYPE_BOOLEAN:
     case VIR_JSON_TYPE_NULL:
+    case VIR_JSON_TYPE_LAST:
         break;
     }
 
@@ -1107,6 +1113,204 @@ virJSONParserHandleEndArray(void *ctx)
 }
 
 
+static bool
+virJSONValueCompare(virJSONValuePtr expect,
+                    virJSONValuePtr actual,
+                    const char *context,
+                    const char **ignore_contexts,
+                    unsigned int flags)
+{
+    size_t i, j;
+
+    if (expect->type != actual->type) {
+        if (expect->type == VIR_JSON_TYPE_NULL &&
+            (flags & VIR_JSON_COMPARE_IGNORE_EXPECTED_NULL))
+            return true;
+
+        const char *expectType = virJSONTypeTypeToString(expect->type);
+        const char *actualType = virJSONTypeTypeToString(actual->type);
+
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Expected value type '%s' but got value type '%s' at '%s'"),
+                       expectType, actualType, context);
+        return false;
+    }
+
+    switch (expect->type) {
+    case VIR_JSON_TYPE_OBJECT:
+        /* Ensure actual data contains all expected data */
+        for (i = 0; i < expect->data.object.npairs; i++) {
+            bool found = false;
+            char *childcontext;
+
+            if (virAsprintf(&childcontext, "%s%s%s",
+                            context,
+                            STREQ(context, "/") ? "" : "/",
+                            expect->data.object.pairs[i].key) < 0)
+                return false;
+
+            /* Bypass paths we've been asked to ignore */
+            if (ignore_contexts) {
+                bool ignored = false;
+
+                j = 0;
+                while (ignore_contexts[j]) {
+                    if (STREQ(childcontext, ignore_contexts[j])) {
+                        ignored = true;
+                        break;
+                    }
+                    j++;
+                }
+
+                if (ignored)
+                    continue;
+            }
+
+           for (j = 0; j < actual->data.object.npairs; j++) {
+                if (STREQ(expect->data.object.pairs[i].key,
+                          actual->data.object.pairs[j].key)) {
+                    found = true;
+                    break;
+                }
+            }
+
+            if (!found) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("Expected object key '%s' not found in actual object at '%s'"),
+                               expect->data.object.pairs[i].key, context);
+                VIR_FREE(childcontext);
+                return false;
+            }
+
+            if (!virJSONValueCompare(expect->data.object.pairs[i].value,
+                                     actual->data.object.pairs[j].value,
+                                     childcontext,
+                                     ignore_contexts,
+                                     flags)) {
+                VIR_FREE(childcontext);
+                return false;
+            }
+            VIR_FREE(childcontext);
+        }
+
+        /* Ensure expected data contains all actual data */
+        for (i = 0; i < actual->data.object.npairs; i++) {
+            bool found = false;
+            char *childcontext;
+
+            if (virAsprintf(&childcontext, "%s%s%s",
+                            context,
+                            STREQ(context, "/") ? "" : "/",
+                            actual->data.object.pairs[i].key) < 0)
+                return false;
+
+            /* Bypass paths we've been asked to ignore */
+            if (ignore_contexts) {
+                bool ignored = false;
+
+                j = 0;
+                while (ignore_contexts[j]) {
+                    if (STREQ(childcontext, ignore_contexts[j])) {
+                        ignored = true;
+                        break;
+                    }
+                    j++;
+                }
+
+                if (ignored)
+                    continue;
+            }
+
+            for (j = 0; j < expect->data.object.npairs; j++) {
+                if (STREQ(actual->data.object.pairs[i].key,
+                          expect->data.object.pairs[j].key)) {
+                    found = true;
+                    break;
+                }
+            }
+
+            if (!found) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("Actual object key '%s' not found in expected object at '%s'"),
+                               actual->data.object.pairs[i].key, context);
+                VIR_FREE(childcontext);
+                return false;
+            }
+
+            if (!virJSONValueCompare(actual->data.object.pairs[i].value,
+                                     expect->data.object.pairs[j].value,
+                                     childcontext,
+                                     ignore_contexts,
+                                     flags)) {
+                VIR_FREE(childcontext);
+            }
+        }
+        break;
+
+    case VIR_JSON_TYPE_ARRAY:
+        if (expect->data.array.nvalues !=
+            actual->data.array.nvalues) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Expected array size '%zu' but got size '%zu' at '%s'"),
+                           expect->data.array.nvalues,
+                           actual->data.array.nvalues,
+                           context);
+            return false;
+        }
+
+        for (i = 0; i < expect->data.array.nvalues; i++) {
+            if (!virJSONValueCompare(expect->data.array.values[i],
+                                     actual->data.array.values[i],
+                                     context,
+                                     ignore_contexts,
+                                     flags))
+                return false;
+        }
+        break;
+
+    case VIR_JSON_TYPE_STRING:
+        if (STRNEQ(expect->data.string,
+                   actual->data.string)) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Expected string value '%s' but got '%s' at '%s'"),
+                           expect->data.string, actual->data.string, context);
+            return false;
+        }
+        break;
+
+    case VIR_JSON_TYPE_NUMBER:
+        if (STRNEQ(expect->data.number,
+                   actual->data.number)) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Expected number value '%s' but got '%s' at '%s'"),
+                           expect->data.number, actual->data.number, context);
+            return false;
+        }
+        break;
+
+    case VIR_JSON_TYPE_BOOLEAN:
+        if (expect->data.boolean !=
+            actual->data.boolean) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Expected bool value '%d' but got '%d' at '%s'"),
+                           expect->data.boolean, actual->data.boolean, context);
+            return false;
+        }
+        break;
+
+    case VIR_JSON_TYPE_NULL:
+        /* trivially equal */
+        break;
+
+    case VIR_JSON_TYPE_LAST:
+        /* nothing */
+        break;
+    }
+
+    return true;
+}
+
+
 static const yajl_callbacks parserCallbacks = {
     virJSONParserHandleNull,
     virJSONParserHandleBoolean,
@@ -1306,6 +1510,30 @@ virJSONValueToString(virJSONValuePtr object,
 }
 
 
+bool
+virJSONStringCompare(const char *expect,
+                     const char *actual,
+                     const char **ignore_contexts,
+                     unsigned int flags)
+{
+    virJSONValuePtr expectVal = NULL;
+    virJSONValuePtr actualVal = NULL;
+    int ret = false;
+
+    if (!(expectVal = virJSONValueFromString(expect)))
+        goto cleanup;
+    if (!(actualVal = virJSONValueFromString(actual)))
+        goto cleanup;
+
+    ret = virJSONValueCompare(expectVal, actualVal, "/", ignore_contexts, flags);
+
+ cleanup:
+    virJSONValueFree(expectVal);
+    virJSONValueFree(actualVal);
+    return ret;
+}
+
+
 #else
 virJSONValuePtr
 virJSONValueFromString(const char *jsonstring ATTRIBUTE_UNUSED)
@@ -1324,4 +1552,18 @@ virJSONValueToString(virJSONValuePtr object ATTRIBUTE_UNUSED,
                    _("No JSON parser implementation is available"));
     return NULL;
 }
+
+
+bool
+virJSONStringCompare(const char *expect ATTRIBUTE_UNUSED,
+                     const char *actual ATTRIBUTE_UNUSED,
+                     const char **ignore_contexts ATTRIBUTE_UNUSED,
+                     unsigned int flags)
+{
+    virCheckFlags(VIR_JSON_COMPARE_IGNORE_EXPECTED_NULL, false);
+
+    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                   _("No JSON parser implementation is available"));
+    return false;
+}
 #endif
diff --git a/src/util/virjson.h b/src/util/virjson.h
index 9487729..5dc948f 100644
--- a/src/util/virjson.h
+++ b/src/util/virjson.h
@@ -34,6 +34,8 @@ typedef enum {
     VIR_JSON_TYPE_NUMBER,
     VIR_JSON_TYPE_BOOLEAN,
     VIR_JSON_TYPE_NULL,
+
+    VIR_JSON_TYPE_LAST,
 } virJSONType;
 
 typedef struct _virJSONValue virJSONValue;
@@ -141,4 +143,18 @@ virJSONValuePtr virJSONValueFromString(const char *jsonstring);
 char *virJSONValueToString(virJSONValuePtr object,
                            bool pretty);
 
+typedef enum {
+    /*
+     * when comparing two values, if their types are different,
+     * and the 'expected' value type is 'null', then this will
+     * be considered non-fatal.
+     */
+    VIR_JSON_COMPARE_IGNORE_EXPECTED_NULL = (1 << 0),
+} virJSONCompareFlags;
+
+bool virJSONStringCompare(const char *expect,
+                          const char *actual,
+                          const char **ignore_contexts,
+                          unsigned int flags);
+
 #endif /* __VIR_JSON_H_ */
-- 
1.8.4.5

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH V4 2/3] tests: add tests for virJSONStringCompare
  2014-09-11 23:09 [PATCH V4 0/3] Testing libvirt XML -> libxl_domain_config conversion Jim Fehlig
  2014-09-11 23:09 ` [PATCH V4 1/3] util: Introduce virJSONStringCompare for JSON doc comparisons Jim Fehlig
@ 2014-09-11 23:09 ` Jim Fehlig
  2014-09-11 23:09 ` [PATCH V4 3/3] libxl: Add a test suite for libxl option generator Jim Fehlig
  2 siblings, 0 replies; 4+ messages in thread
From: Jim Fehlig @ 2014-09-11 23:09 UTC (permalink / raw)
  To: libvir-list; +Cc: Jim Fehlig, xen-devel

Signed-off-by: Jim Fehlig <jfehlig@suse.com>
---

This patch is new to V4.

 tests/jsontest.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 58 insertions(+), 5 deletions(-)

diff --git a/tests/jsontest.c b/tests/jsontest.c
index a2a42e3..5d5f619 100644
--- a/tests/jsontest.c
+++ b/tests/jsontest.c
@@ -12,6 +12,7 @@
 struct testInfo {
     const char *doc;
     const char *expect;
+    const char **ignore_contexts;
     bool pass;
 };
 
@@ -131,22 +132,45 @@ testJSONAddRemove(const void *data)
 
 
 static int
+testJSONCompare(const void *data)
+{
+    const struct testInfo *info = data;
+    bool ret;
+
+    ret = virJSONStringCompare(info->expect,
+                               info->doc,
+                               info->ignore_contexts,
+                               0);
+
+    if (ret == info->pass)
+        return 0;
+    else
+        return -1;
+}
+
+
+static int
 mymain(void)
 {
     int ret = 0;
+    const char *ignore_paths[] = {
+        "/dict1/key3",
+        "/key4",
+        NULL
+    };
 
-#define DO_TEST_FULL(name, cmd, doc, expect, pass)                  \
+#define DO_TEST_FULL(name, cmd, doc, expect, ignore_ctx, pass)      \
     do {                                                            \
-        struct testInfo info = { doc, expect, pass };               \
+        struct testInfo info = { doc, expect, ignore_ctx, pass };   \
         if (virtTestRun(name, testJSON ## cmd, &info) < 0)          \
             ret = -1;                                               \
     } while (0)
 
 #define DO_TEST_PARSE(name, doc)                \
-    DO_TEST_FULL(name, FromString, doc, NULL, true)
+    DO_TEST_FULL(name, FromString, doc, NULL, NULL, true)
 
 #define DO_TEST_PARSE_FAIL(name, doc)           \
-    DO_TEST_FULL(name, FromString, doc, NULL, false)
+    DO_TEST_FULL(name, FromString, doc, NULL, NULL, false)
 
 
     DO_TEST_PARSE("Simple", "{\"return\": {}, \"id\": \"libvirt-1\"}");
@@ -188,9 +212,10 @@ mymain(void)
     DO_TEST_FULL("add and remove", AddRemove,
                  "{\"name\": \"sample\", \"value\": true}",
                  "{\"value\":true,\"newname\":\"foo\"}",
+                 NULL,
                  true);
     DO_TEST_FULL("add and remove", AddRemove,
-                 "[ 1 ]", NULL, false);
+                 "[ 1 ]", NULL, NULL, false);
 
 
     DO_TEST_PARSE("almost nothing", "[]");
@@ -214,6 +239,34 @@ mymain(void)
                        "[ {[\"key1\", \"key2\"]: \"value\"} ]");
     DO_TEST_PARSE_FAIL("object with unterminated key", "{ \"key:7 }");
 
+    DO_TEST_FULL("Compare identical docs", Compare,
+                 "{ \"key1\" : \"value1\", \"key2\" : \"value2\"}",
+                 "{ \"key1\" : \"value1\", \"key2\" : \"value2\"}",
+                 NULL, true);
+
+    DO_TEST_FULL("Compare different docs", Compare,
+                 "{\"dict1\" : { \"key1\" : \"value1\", \"key2\" : \"value2\", "
+                 "\"key3\" : [\"elem1\", \"elemfoo\"]}}",
+                 "{\"dict1\" : { \"key1\" : \"value1\", \"key2\" : \"value2\", "
+                 "\"key3\" : [\"elem1\", \"elem2\"]}}",
+                 NULL, false);
+
+    DO_TEST_FULL("Compare docs and ignore differing contexts", Compare,
+                 "{\"dict1\" : { \"key1\" : \"value1\", \"key2\" : \"value2\", "
+                 "\"key3\" : \"valuefoo\"}, \"key4\" : \"valuebar\"}",
+                 "{\"dict1\" : { \"key1\" : \"value1\", \"key2\" : \"value2\", "
+                 "\"key3\" : \"value3\"}, \"key4\" : \"value4\"}",
+                 ignore_paths, true);
+
+    DO_TEST_FULL("Compare docs with insufficient ignored contexts", Compare,
+                 "{\"dict1\" : { \"key1\" : \"value1\", \"key2\" : \"value2\", "
+                 "\"key3\" : \"valuefoo\"}, \"key4\" : \"valuebar\", "
+                 "\"key5\" : \"valuebaz\"}",
+                 "{\"dict1\" : { \"key1\" : \"value1\", \"key2\" : \"value2\", "
+                 "\"key3\" : \"value3\"}, \"key4\" : \"value4\", "
+                 "\"key5\" : \"value5\"}",
+                 ignore_paths, false);
+
     return (ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
 }
 
-- 
1.8.4.5

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH V4 3/3] libxl: Add a test suite for libxl option generator
  2014-09-11 23:09 [PATCH V4 0/3] Testing libvirt XML -> libxl_domain_config conversion Jim Fehlig
  2014-09-11 23:09 ` [PATCH V4 1/3] util: Introduce virJSONStringCompare for JSON doc comparisons Jim Fehlig
  2014-09-11 23:09 ` [PATCH V4 2/3] tests: add tests for virJSONStringCompare Jim Fehlig
@ 2014-09-11 23:09 ` Jim Fehlig
  2 siblings, 0 replies; 4+ messages in thread
From: Jim Fehlig @ 2014-09-11 23:09 UTC (permalink / raw)
  To: libvir-list; +Cc: Jim Fehlig, Daniel P. Berrange, xen-devel

From: "Daniel P. Berrange" <berrange@redhat.com>

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@redhat.com>
Signed-off-by: Jim Fehlig <jfehlig@suse.com>
---

V4: Cleanup definition of ignored context paths

 configure.ac                           |   2 +
 tests/Makefile.am                      |  25 +++-
 tests/libxlxml2jsondata/basic-hvm.json | 217 +++++++++++++++++++++++++++++++
 tests/libxlxml2jsondata/basic-hvm.xml  |  36 ++++++
 tests/libxlxml2jsondata/basic-pv.json  | 163 +++++++++++++++++++++++
 tests/libxlxml2jsondata/basic-pv.xml   |  28 ++++
 tests/libxlxml2jsontest.c              | 228 +++++++++++++++++++++++++++++++++
 tests/virmocklibxl.c                   |  87 +++++++++++++
 8 files changed, 785 insertions(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac
index b4fb99a..80c331f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -875,6 +875,8 @@ if test "$with_libxl" != "no" ; then
     AC_CHECK_LIB([xenlight], [libxl_ctx_alloc], [
         with_libxl=yes
         LIBXL_LIBS="$LIBXL_LIBS -lxenlight -lxenctrl"
+        LIBS="$LIBS -lxenlight -lxenctrl"
+        AC_CHECK_FUNCS([libxl_domain_config_to_json])
     ],[
         if test "$with_libxl" = "yes"; then
             fail=1
diff --git a/tests/Makefile.am b/tests/Makefile.am
index d6c3cfb..a8e4e88 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -84,6 +84,7 @@ EXTRA_DIST =		\
 	domainsnapshotxml2xmlout \
 	fchostdata \
 	interfaceschemadata \
+	libxlxml2jsondata \
 	lxcconf2xmldata \
 	lxcxml2xmldata \
 	lxcxml2xmloutdata \
@@ -222,6 +223,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 \
@@ -393,7 +397,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
@@ -593,6 +599,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/basic-hvm.json b/tests/libxlxml2jsondata/basic-hvm.json
new file mode 100644
index 0000000..b02e299
--- /dev/null
+++ b/tests/libxlxml2jsondata/basic-hvm.json
@@ -0,0 +1,217 @@
+{
+    "c_info": {
+        "type": "hvm",
+        "hap": "<default>",
+        "oos": "<default>",
+        "ssidref": 0,
+        "name": "sles-hvm",
+        "uuid": "2147d599-9cc6-c0dc-92ab-4064b5446e9b",
+        "xsdata": {
+
+        },
+        "platformdata": {
+
+        },
+        "poolid": 0,
+        "run_hotplug_scripts": "<default>",
+        "pvh": "<default>",
+        "driver_domain": "<default>"
+    },
+    "b_info": {
+        "max_vcpus": 4,
+        "avail_vcpus": [
+            0,
+            1,
+            2,
+            3
+        ],
+        "cpumap": [
+
+        ],
+        "nodemap": [
+
+        ],
+        "numa_placement": "<default>",
+        "tsc_mode": "default",
+        "max_memkb": 1048576,
+        "target_memkb": 1048576,
+        "video_memkb": -1,
+        "shadow_memkb": 12288,
+        "rtc_timeoffset": 0,
+        "exec_ssidref": 0,
+        "localtime": "<default>",
+        "disable_migrate": "<default>",
+        "cpuid": [
+
+        ],
+        "blkdev_start": null,
+        "device_model_version": "unknown",
+        "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>",
+        "event_channels": 0,
+        "u": {
+            "firmware": null,
+            "kernel": null,
+            "cmdline": null,
+            "ramdisk": null,
+            "bios": "unknown",
+            "pae": "True",
+            "apic": "True",
+            "acpi": "True",
+            "acpi_s3": "<default>",
+            "acpi_s4": "<default>",
+            "nx": "<default>",
+            "viridian": "<default>",
+            "timeoffset": null,
+            "hpet": "<default>",
+            "vpt_align": "<default>",
+            "timer_mode": "unknown",
+            "nested_hvm": "<default>",
+            "smbios_firmware": null,
+            "acpi_firmware": null,
+            "nographic": "<default>",
+            "vga": {
+               "kind": "cirrus"
+            },
+            "vnc": {
+                "enable": "True",
+                "listen": "0.0.0.0",
+                "passwd": null,
+                "display": 0,
+                "findunused": "False"
+            },
+            "keymap": null,
+            "sdl": {
+                "enable": "<default>",
+                "opengl": "<default>",
+                "display": null,
+                "xauthority": null
+            },
+            "spice": {
+                "enable": "<default>",
+                "port": 0,
+                "tls_port": 0,
+                "host": null,
+                "disable_ticketing": "<default>",
+                "passwd": null,
+                "agent_mouse": "<default>",
+                "vdagent": "<default>",
+                "clipboard_sharing": "<default>",
+                "usbredirection": 0
+            },
+            "gfx_passthru": "<default>",
+            "serial": null,
+            "boot": "c",
+            "usb": "<default>",
+            "usbversion": 0,
+            "usbdevice": null,
+            "soundhw": null,
+            "xen_platform_pci": "<default>",
+            "usbdevice_list": [
+
+            ],
+            "vendor_device": "none",
+            "watchdog": null,
+            "watchdog_action": null
+         }
+    },
+    "disks": [
+        {
+            "backend_domid": 0,
+            "backend_domname": null,
+            "pdev_path": "/var/lib/xen/images/sles-hvm.img",
+            "vdev": "hda",
+            "backend": "qdisk",
+            "format": "raw",
+            "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:66:12:b4",
+            "ip": null,
+            "bridge": "br0",
+            "ifname": null,
+            "script": "/etc/xen/scripts/vif-bridge",
+            "nictype": "vif_ioemu",
+            "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": "destroy",
+    "on_reboot": "restart",
+    "on_watchdog": "destroy",
+    "on_crash": "destroy"
+}
diff --git a/tests/libxlxml2jsondata/basic-hvm.xml b/tests/libxlxml2jsondata/basic-hvm.xml
new file mode 100644
index 0000000..693a715
--- /dev/null
+++ b/tests/libxlxml2jsondata/basic-hvm.xml
@@ -0,0 +1,36 @@
+<domain type='xen'>
+  <name>sles-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/sles-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/libxlxml2jsondata/basic-pv.json b/tests/libxlxml2jsondata/basic-pv.json
new file mode 100644
index 0000000..326b705
--- /dev/null
+++ b/tests/libxlxml2jsondata/basic-pv.json
@@ -0,0 +1,163 @@
+{
+    "c_info": {
+        "type": "pv",
+        "hap": "<default>",
+        "oos": "<default>",
+        "ssidref": 0,
+        "name": "sles11-pv",
+        "uuid": "039e9ee6-4a84-3055-4c81-8ba426ae2656",
+        "xsdata": {
+
+        },
+        "platformdata": {
+
+        },
+        "poolid": 0,
+        "run_hotplug_scripts": "<default>",
+        "pvh": "<default>",
+        "driver_domain": "<default>"
+    },
+    "b_info": {
+        "max_vcpus": 4,
+        "avail_vcpus": [
+            0,
+            1,
+            2,
+            3
+        ],
+        "cpumap": [
+
+        ],
+        "nodemap": [
+
+        ],
+        "numa_placement": "<default>",
+        "tsc_mode": "default",
+        "max_memkb": 524288,
+        "target_memkb": 524288,
+        "video_memkb": -1,
+        "shadow_memkb": -1,
+        "rtc_timeoffset": 0,
+        "exec_ssidref": 0,
+        "localtime": "<default>",
+        "disable_migrate": "<default>",
+        "cpuid": [
+
+        ],
+        "blkdev_start": null,
+        "device_model_version": "unknown",
+        "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>",
+        "event_channels": 0,
+        "u": {
+            "kernel": null,
+            "slack_memkb": -1,
+            "bootloader": "pygrub",
+            "bootloader_args": [
+
+            ],
+            "cmdline": null,
+            "ramdisk": null,
+            "e820_host": "<default>"
+        }
+    },
+    "disks": [
+        {
+            "backend_domid": 0,
+            "backend_domname": null,
+            "pdev_path": "/var/lib/xen/images/sles11-pv.img",
+            "vdev": "xvda",
+            "backend": "qdisk",
+            "format": "raw",
+            "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:3e:86:60",
+            "ip": null,
+            "bridge": "br0",
+            "ifname": null,
+            "script": "/etc/xen/scripts/vif-bridge",
+            "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": "destroy",
+    "on_reboot": "restart",
+    "on_watchdog": "destroy",
+    "on_crash": "destroy"
+}
diff --git a/tests/libxlxml2jsondata/basic-pv.xml b/tests/libxlxml2jsondata/basic-pv.xml
new file mode 100644
index 0000000..109e657
--- /dev/null
+++ b/tests/libxlxml2jsondata/basic-pv.xml
@@ -0,0 +1,28 @@
+<domain type='xen'>
+  <name>sles11-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/sles11-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/libxlxml2jsontest.c b/tests/libxlxml2jsontest.c
new file mode 100644
index 0000000..f427d3e
--- /dev/null
+++ b/tests/libxlxml2jsontest.c
@@ -0,0 +1,228 @@
+/*
+ * 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>
+
+#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_TO_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_XEN
+
+# if defined LIBXL_HAVE_BUILDINFO_HVM_VENDOR_DEVICE
+#  define VIR_LIBXL_VERSION 4004
+# elif defined LIBXL_HAVE_DOMAIN_NODEAFFINITY
+#  define VIR_LIBXL_VERSION 4003
+# else
+#  define VIR_LIBXL_VERSION 4002
+# endif
+
+static const char *abs_top_srcdir;
+static virCapsPtr xencaps;
+static const char *ignore_paths[] = {
+# if VIR_LIBXL_VERSION < 4004
+    "/c_info/pvh",
+    "/c_info/driver_domain",
+    "/b_info/device_model_version",
+    "/b_info/event_channels",
+    "/b_info/u/kernel",
+    "/b_info/u/cmdline",
+    "/b_info/u/ramdisk",
+    "/b_info/u/bios",
+    "/b_info/u/timer_mode",
+    "/b_info/u/vga/kind",
+    "/b_info/u/spice/vdagent",
+    "/b_info/u/spice/clipboard_sharing",
+    "/b_info/u/spice/usbredirection",
+    "/b_info/u/usbversion",
+    "/b_info/u/vendor_device",
+    "/on_watchdog",
+# endif
+# if VIR_LIBXL_VERSION < 4003
+    "/b_info/nodemap",
+    "/b_info/exec_ssidref",
+    "/b_info/iomem",
+    "/b_info/claim_mode",
+    "/b_info/u/usbdevice_list",
+    "/disks/backend_domname",
+    "/nics/backend_domname",
+    "/vfbs/backend_domname",
+    "/vkbs/backend_domname",
+    "/vtpms",
+# endif
+    NULL
+};
+
+
+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;
+    char *actualargv;
+
+    libxl_domain_config_init(&config);
+
+    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(xml, xencaps, xmlopt,
+                                        1 << VIR_DOMAIN_VIRT_XEN,
+                                        VIR_DOMAIN_XML_INACTIVE)))
+        goto cleanup;
+
+    if (libxlBuildDomainConfig(gports, vmdef, ctx, &config) < 0)
+        goto cleanup;
+
+    if (!(actualargv = libxl_domain_config_to_json(ctx, &config))) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       "Failed to create JSON doc for xl config");
+        goto cleanup;
+    }
+
+    virtTestLoadFile(cmdline, &expectargv);
+
+    if (!virJSONStringCompare(expectargv, actualargv, ignore_paths,
+                              VIR_JSON_COMPARE_IGNORE_EXPECTED_NULL))
+        goto cleanup;
+
+    ret = 0;
+
+ cleanup:
+    VIR_FREE(expectargv);
+    VIR_FREE(actualargv);
+    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("basic-pv");
+    DO_TEST("basic-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_XEN && WITH_YAJL && HAVE_LIBXL_DOMAIN_CONFIG_TO_JSON */
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@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.8.4.5

^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2014-09-11 23:09 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-09-11 23:09 [PATCH V4 0/3] Testing libvirt XML -> libxl_domain_config conversion Jim Fehlig
2014-09-11 23:09 ` [PATCH V4 1/3] util: Introduce virJSONStringCompare for JSON doc comparisons Jim Fehlig
2014-09-11 23:09 ` [PATCH V4 2/3] tests: add tests for virJSONStringCompare Jim Fehlig
2014-09-11 23:09 ` [PATCH V4 3/3] libxl: Add a test suite for libxl option generator Jim Fehlig

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).