* [PATCH v2 0/4] Testing libvirt XML -> libxl_domain_config conversion @ 2014-06-03 11:02 Daniel P. Berrange 2014-06-03 11:02 ` [libvirt] [PATCH v2 1/4] util: Introduce virJSONStringCompare for JSON doc comparisons Daniel P. Berrange ` (3 more replies) 0 siblings, 4 replies; 14+ messages in thread From: Daniel P. Berrange @ 2014-06-03 11:02 UTC (permalink / raw) To: libvir-list; +Cc: Jim Fehlig, xen-devel, Daniel P. Berrange, Ian Campbell Version 2 of: https://www.redhat.com/archives/libvir-list/2014-May/msg01102.html This tests the conversion of libvirt XML to libxl_domain_config objects by the libvirt libxl driver. Changed in v2: - Compare the parsed JSON object model instead of strcmp() on the string-ified JSON document - To cope with new additions between Xen 4.3 and 4.4 - Ignore case where actual JSON object has gained new keys. This copes with fact that '/c_info' gained a new key called 'pvh' in 4.4 - Ignore case where actual JSON value has changed from 'null' to a non-'null' value type. This copes with fact that the element at /b_info/device_model_version changed from 'null' to a specific value by default in 4.4. - Use libxl_domain_config_to_json instead of libxl_json.h functions, and disable test if running on Xen version which lacks this function (eg 4.2) - Isolate VNC port allocator from host TCP ports so a predictable VNC port is always in the config. Daniel P. Berrange (4): util: Introduce virJSONStringCompare for JSON doc comparisons util: Allow port allocator to skip bind() check tests: Add more test suite mock helpers libxl: Add a test suite for libxl option generator configure.ac | 2 + src/libvirt_private.syms | 1 + src/libxl/libxl_driver.c | 3 +- src/qemu/qemu_driver.c | 9 +- src/util/virjson.c | 185 ++++++++++++++++++++++++++++++++++ src/util/virjson.h | 22 +++++ src/util/virportallocator.c | 14 ++- src/util/virportallocator.h | 7 +- tests/Makefile.am | 25 ++++- tests/libxlxml2jsondata/minimal.json | 172 ++++++++++++++++++++++++++++++++ tests/libxlxml2jsondata/minimal.xml | 36 +++++++ tests/libxlxml2jsontest.c | 186 +++++++++++++++++++++++++++++++++++ tests/virfirewalltest.c | 4 +- tests/virmock.h | 54 +++++++--- tests/virmocklibxl.c | 87 ++++++++++++++++ tests/virportallocatortest.c | 4 +- tests/virsystemdtest.c | 4 +- 17 files changed, 786 insertions(+), 29 deletions(-) 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 -- 1.9.3 ^ permalink raw reply [flat|nested] 14+ messages in thread
* [libvirt] [PATCH v2 1/4] util: Introduce virJSONStringCompare for JSON doc comparisons 2014-06-03 11:02 [PATCH v2 0/4] Testing libvirt XML -> libxl_domain_config conversion Daniel P. Berrange @ 2014-06-03 11:02 ` Daniel P. Berrange 2014-06-03 21:18 ` Jim Fehlig 2014-06-03 11:02 ` [PATCH v2 2/4] util: Allow port allocator to skip bind() check Daniel P. Berrange ` (2 subsequent siblings) 3 siblings, 1 reply; 14+ messages in thread From: Daniel P. Berrange @ 2014-06-03 11:02 UTC (permalink / raw) To: libvir-list; +Cc: xen-devel, Ian Campbell 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. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/libvirt_private.syms | 1 + src/util/virjson.c | 185 +++++++++++++++++++++++++++++++++++++++++++++++ src/util/virjson.h | 22 ++++++ 3 files changed, 208 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 4c1f61c..5f2b9d9 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1406,6 +1406,7 @@ virISCSIScanTargets; # util/virjson.h +virJSONStringCompare; virJSONValueArrayAppend; virJSONValueArrayGet; virJSONValueArraySize; diff --git a/src/util/virjson.c b/src/util/virjson.c index 35a8252..0a6d1be 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 { @@ -90,6 +95,7 @@ void virJSONValueFree(virJSONValuePtr value) break; case VIR_JSON_TYPE_BOOLEAN: case VIR_JSON_TYPE_NULL: + case VIR_JSON_TYPE_LAST: break; } @@ -1152,3 +1158,182 @@ char *virJSONValueToString(virJSONValuePtr object ATTRIBUTE_UNUSED, return NULL; } #endif + + +static bool +virJSONValueCompare(virJSONValuePtr expect, + virJSONValuePtr actual, + const char *context, + 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: + for (i = 0; i < expect->data.object.npairs; i++) { + bool found = false; + char *childcontext; + 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); + return false; + } + + if (virAsprintf(&childcontext, "%s%s%s", + context, + STREQ(context, "/") ? "" : "/", + expect->data.object.pairs[i].key) < 0) + return false; + + if (!virJSONValueCompare(expect->data.object.pairs[i].value, + actual->data.object.pairs[j].value, + childcontext, + flags)) { + VIR_FREE(childcontext); + return false; + } + VIR_FREE(childcontext); + } + if (!(flags & VIR_JSON_COMPARE_IGNORE_EXTRA_OBJECT_KEYS)) { + for (i = 0; i < actual->data.object.npairs; i++) { + bool found = false; + char *childcontext; + 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); + return false; + } + + if (virAsprintf(&childcontext, "%s%s%s", + STREQ(context, "/") ? "" : "/", + context, actual->data.object.pairs[i].key) < 0) + return false; + + if (!virJSONValueCompare(actual->data.object.pairs[i].value, + expect->data.object.pairs[j].value, + childcontext, + flags)) { + VIR_FREE(childcontext); + return false; + } + 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++) { + char *childcontext; + if (virAsprintf(&childcontext, "%s%s[%zu]", + STREQ(context, "/") ? "" : "/", + context, i) < 0) + return false; + + if (!virJSONValueCompare(expect->data.array.values[i], + actual->data.array.values[i], + childcontext, + flags)) { + VIR_FREE(childcontext); + return false; + } + VIR_FREE(childcontext); + } + 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; +} + + +bool virJSONStringCompare(const char *expect, + const char *actual, + 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, "/", flags); + + cleanup: + virJSONValueFree(expectVal); + virJSONValueFree(actualVal); + return ret; +} diff --git a/src/util/virjson.h b/src/util/virjson.h index db11396..b1f96d3 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; @@ -139,4 +141,24 @@ virJSONValuePtr virJSONValueFromString(const char *jsonstring); char *virJSONValueToString(virJSONValuePtr object, bool pretty); +typedef enum { + /* + * When comparing a pair of Objects, if the 'actual' object + * has keys that are not present in the 'expected' object, + * the existance of these extra keys will be non-fatal. + */ + VIR_JSON_COMPARE_IGNORE_EXTRA_OBJECT_KEYS = (1 << 0), + + /* + * 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 << 1), +} virJSONCompareFlags; + +bool virJSONStringCompare(const char *expect, + const char *actual, + unsigned int flags); + #endif /* __VIR_JSON_H_ */ -- 1.9.3 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [libvirt] [PATCH v2 1/4] util: Introduce virJSONStringCompare for JSON doc comparisons 2014-06-03 11:02 ` [libvirt] [PATCH v2 1/4] util: Introduce virJSONStringCompare for JSON doc comparisons Daniel P. Berrange @ 2014-06-03 21:18 ` Jim Fehlig 0 siblings, 0 replies; 14+ messages in thread From: Jim Fehlig @ 2014-06-03 21:18 UTC (permalink / raw) To: Daniel P. Berrange; +Cc: libvir-list, xen-devel, Ian Campbell Daniel P. Berrange wrote: > 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. > > Signed-off-by: Daniel P. Berrange <berrange@redhat.com> > --- > src/libvirt_private.syms | 1 + > src/util/virjson.c | 185 +++++++++++++++++++++++++++++++++++++++++++++++ > I'm not too familiar with this file, but didn't notice any problems with this patch beyond a little nit below. > src/util/virjson.h | 22 ++++++ > 3 files changed, 208 insertions(+) > > diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms > index 4c1f61c..5f2b9d9 100644 > --- a/src/libvirt_private.syms > +++ b/src/libvirt_private.syms > @@ -1406,6 +1406,7 @@ virISCSIScanTargets; > > > # util/virjson.h > +virJSONStringCompare; > virJSONValueArrayAppend; > virJSONValueArrayGet; > virJSONValueArraySize; > diff --git a/src/util/virjson.c b/src/util/virjson.c > index 35a8252..0a6d1be 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 { > @@ -90,6 +95,7 @@ void virJSONValueFree(virJSONValuePtr value) > break; > case VIR_JSON_TYPE_BOOLEAN: > case VIR_JSON_TYPE_NULL: > + case VIR_JSON_TYPE_LAST: > break; > } > > @@ -1152,3 +1158,182 @@ char *virJSONValueToString(virJSONValuePtr object ATTRIBUTE_UNUSED, > return NULL; > } > #endif > + > + > +static bool > +virJSONValueCompare(virJSONValuePtr expect, > + virJSONValuePtr actual, > + const char *context, > + unsigned int flags) > +{ > + size_t i, j; > + if (expect->type != actual->type) { > Super nit: seems most of libvirt code would have a line between local variable declarations and start of code, but this file is not consistent in that regard anyhow. ACK. Regards, Jim > + 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: > + for (i = 0; i < expect->data.object.npairs; i++) { > + bool found = false; > + char *childcontext; > + 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); > + return false; > + } > + > + if (virAsprintf(&childcontext, "%s%s%s", > + context, > + STREQ(context, "/") ? "" : "/", > + expect->data.object.pairs[i].key) < 0) > + return false; > + > + if (!virJSONValueCompare(expect->data.object.pairs[i].value, > + actual->data.object.pairs[j].value, > + childcontext, > + flags)) { > + VIR_FREE(childcontext); > + return false; > + } > + VIR_FREE(childcontext); > + } > + if (!(flags & VIR_JSON_COMPARE_IGNORE_EXTRA_OBJECT_KEYS)) { > + for (i = 0; i < actual->data.object.npairs; i++) { > + bool found = false; > + char *childcontext; > + 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); > + return false; > + } > + > + if (virAsprintf(&childcontext, "%s%s%s", > + STREQ(context, "/") ? "" : "/", > + context, actual->data.object.pairs[i].key) < 0) > + return false; > + > + if (!virJSONValueCompare(actual->data.object.pairs[i].value, > + expect->data.object.pairs[j].value, > + childcontext, > + flags)) { > + VIR_FREE(childcontext); > + return false; > + } > + 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++) { > + char *childcontext; > + if (virAsprintf(&childcontext, "%s%s[%zu]", > + STREQ(context, "/") ? "" : "/", > + context, i) < 0) > + return false; > + > + if (!virJSONValueCompare(expect->data.array.values[i], > + actual->data.array.values[i], > + childcontext, > + flags)) { > + VIR_FREE(childcontext); > + return false; > + } > + VIR_FREE(childcontext); > + } > + 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; > +} > + > + > +bool virJSONStringCompare(const char *expect, > + const char *actual, > + 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, "/", flags); > + > + cleanup: > + virJSONValueFree(expectVal); > + virJSONValueFree(actualVal); > + return ret; > +} > diff --git a/src/util/virjson.h b/src/util/virjson.h > index db11396..b1f96d3 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; > @@ -139,4 +141,24 @@ virJSONValuePtr virJSONValueFromString(const char *jsonstring); > char *virJSONValueToString(virJSONValuePtr object, > bool pretty); > > +typedef enum { > + /* > + * When comparing a pair of Objects, if the 'actual' object > + * has keys that are not present in the 'expected' object, > + * the existance of these extra keys will be non-fatal. > + */ > + VIR_JSON_COMPARE_IGNORE_EXTRA_OBJECT_KEYS = (1 << 0), > + > + /* > + * 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 << 1), > +} virJSONCompareFlags; > + > +bool virJSONStringCompare(const char *expect, > + const char *actual, > + unsigned int flags); > + > #endif /* __VIR_JSON_H_ */ > ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v2 2/4] util: Allow port allocator to skip bind() check 2014-06-03 11:02 [PATCH v2 0/4] Testing libvirt XML -> libxl_domain_config conversion Daniel P. Berrange 2014-06-03 11:02 ` [libvirt] [PATCH v2 1/4] util: Introduce virJSONStringCompare for JSON doc comparisons Daniel P. Berrange @ 2014-06-03 11:02 ` Daniel P. Berrange 2014-06-03 21:25 ` [libvirt] " Jim Fehlig 2014-06-03 11:02 ` [PATCH v2 3/4] tests: Add more test suite mock helpers Daniel P. Berrange 2014-06-03 11:02 ` [PATCH v2 4/4] libxl: Add a test suite for libxl option generator Daniel P. Berrange 3 siblings, 1 reply; 14+ messages in thread From: Daniel P. Berrange @ 2014-06-03 11:02 UTC (permalink / raw) To: libvir-list; +Cc: Jim Fehlig, xen-devel, Daniel P. Berrange, Ian Campbell Test suites using the port allocator don't want to have different behaviour depending on whether a port is in use on the host. Add a VIR_PORT_ALLOCATOR_SKIP_BIND_CHECK which test suites can use to skip the bind() test. The port allocator will thus only track ports in use by the test suite process itself. This is fine when using the port allocator to generate guest configs which won't actually be launched Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/libxl/libxl_driver.c | 3 ++- src/qemu/qemu_driver.c | 9 ++++++--- src/util/virportallocator.c | 14 ++++++++++---- src/util/virportallocator.h | 7 ++++++- tests/virportallocatortest.c | 4 ++-- 5 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 515d5c9..70f9bb8 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -298,7 +298,8 @@ libxlStateInitialize(bool privileged, if (!(libxl_driver->reservedVNCPorts = virPortAllocatorNew(_("VNC"), LIBXL_VNC_PORT_MIN, - LIBXL_VNC_PORT_MAX))) + LIBXL_VNC_PORT_MAX, + 0))) goto error; if (!(libxl_driver->domains = virDomainObjListNew())) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 3a7622a..b3a9036 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -680,19 +680,22 @@ qemuStateInitialize(bool privileged, if ((qemu_driver->remotePorts = virPortAllocatorNew(_("display"), cfg->remotePortMin, - cfg->remotePortMax)) == NULL) + cfg->remotePortMax, + 0)) == NULL) goto error; if ((qemu_driver->webSocketPorts = virPortAllocatorNew(_("webSocket"), cfg->webSocketPortMin, - cfg->webSocketPortMax)) == NULL) + cfg->webSocketPortMax, + 0)) == NULL) goto error; if ((qemu_driver->migrationPorts = virPortAllocatorNew(_("migration"), cfg->migrationPortMin, - cfg->migrationPortMax)) == NULL) + cfg->migrationPortMax, + 0)) == NULL) goto error; if (qemuSecurityInit(qemu_driver) < 0) diff --git a/src/util/virportallocator.c b/src/util/virportallocator.c index b68133a..fa17475 100644 --- a/src/util/virportallocator.c +++ b/src/util/virportallocator.c @@ -43,6 +43,8 @@ struct _virPortAllocator { unsigned short start; unsigned short end; + + unsigned int flags; }; static virClassPtr virPortAllocatorClass; @@ -71,7 +73,8 @@ VIR_ONCE_GLOBAL_INIT(virPortAllocator) virPortAllocatorPtr virPortAllocatorNew(const char *name, unsigned short start, - unsigned short end) + unsigned short end, + unsigned int flags) { virPortAllocatorPtr pa; @@ -87,6 +90,7 @@ virPortAllocatorPtr virPortAllocatorNew(const char *name, if (!(pa = virObjectLockableNew(virPortAllocatorClass))) return NULL; + pa->flags = flags; pa->start = start; pa->end = end; @@ -193,9 +197,11 @@ int virPortAllocatorAcquire(virPortAllocatorPtr pa, if (used) continue; - if (virPortAllocatorBindToPort(&v6used, i, AF_INET6) < 0 || - virPortAllocatorBindToPort(&used, i, AF_INET) < 0) - goto cleanup; + if (!(pa->flags & VIR_PORT_ALLOCATOR_SKIP_BIND_CHECK)) { + if (virPortAllocatorBindToPort(&v6used, i, AF_INET6) < 0 || + virPortAllocatorBindToPort(&used, i, AF_INET) < 0) + goto cleanup; + } if (!used && !v6used) { /* Add port to bitmap of reserved ports */ diff --git a/src/util/virportallocator.h b/src/util/virportallocator.h index c8aa6de..2fdb8d9 100644 --- a/src/util/virportallocator.h +++ b/src/util/virportallocator.h @@ -28,9 +28,14 @@ typedef struct _virPortAllocator virPortAllocator; typedef virPortAllocator *virPortAllocatorPtr; +typedef enum { + VIR_PORT_ALLOCATOR_SKIP_BIND_CHECK = (1 << 0), +} virPortAllocatorFlags; + virPortAllocatorPtr virPortAllocatorNew(const char *name, unsigned short start, - unsigned short end); + unsigned short end, + unsigned int flags); int virPortAllocatorAcquire(virPortAllocatorPtr pa, unsigned short *port); diff --git a/tests/virportallocatortest.c b/tests/virportallocatortest.c index 48d2c9a..96d2ade 100644 --- a/tests/virportallocatortest.c +++ b/tests/virportallocatortest.c @@ -122,7 +122,7 @@ VIR_LOG_INIT("tests.portallocatortest"); static int testAllocAll(const void *args ATTRIBUTE_UNUSED) { - virPortAllocatorPtr alloc = virPortAllocatorNew("test", 5900, 5909); + virPortAllocatorPtr alloc = virPortAllocatorNew("test", 5900, 5909, 0); int ret = -1; unsigned short p1, p2, p3, p4, p5, p6, p7; @@ -193,7 +193,7 @@ static int testAllocAll(const void *args ATTRIBUTE_UNUSED) static int testAllocReuse(const void *args ATTRIBUTE_UNUSED) { - virPortAllocatorPtr alloc = virPortAllocatorNew("test", 5900, 5910); + virPortAllocatorPtr alloc = virPortAllocatorNew("test", 5900, 5910, 0); int ret = -1; unsigned short p1, p2, p3, p4; -- 1.9.3 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [libvirt] [PATCH v2 2/4] util: Allow port allocator to skip bind() check 2014-06-03 11:02 ` [PATCH v2 2/4] util: Allow port allocator to skip bind() check Daniel P. Berrange @ 2014-06-03 21:25 ` Jim Fehlig 0 siblings, 0 replies; 14+ messages in thread From: Jim Fehlig @ 2014-06-03 21:25 UTC (permalink / raw) To: Daniel P. Berrange; +Cc: libvir-list, xen-devel, Ian Campbell Daniel P. Berrange wrote: > Test suites using the port allocator don't want to have different > behaviour depending on whether a port is in use on the host. Add > a VIR_PORT_ALLOCATOR_SKIP_BIND_CHECK which test suites can use > to skip the bind() test. The port allocator will thus only track > ports in use by the test suite process itself. This is fine when > using the port allocator to generate guest configs which won't > actually be launched > > Signed-off-by: Daniel P. Berrange <berrange@redhat.com> > --- > src/libxl/libxl_driver.c | 3 ++- > src/qemu/qemu_driver.c | 9 ++++++--- > src/util/virportallocator.c | 14 ++++++++++---- > src/util/virportallocator.h | 7 ++++++- > tests/virportallocatortest.c | 4 ++-- > 5 files changed, 26 insertions(+), 11 deletions(-) > > diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c > index 515d5c9..70f9bb8 100644 > --- a/src/libxl/libxl_driver.c > +++ b/src/libxl/libxl_driver.c > @@ -298,7 +298,8 @@ libxlStateInitialize(bool privileged, > if (!(libxl_driver->reservedVNCPorts = > virPortAllocatorNew(_("VNC"), > LIBXL_VNC_PORT_MIN, > - LIBXL_VNC_PORT_MAX))) > + LIBXL_VNC_PORT_MAX, > + 0))) > goto error; > > if (!(libxl_driver->domains = virDomainObjListNew())) > diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c > index 3a7622a..b3a9036 100644 > --- a/src/qemu/qemu_driver.c > +++ b/src/qemu/qemu_driver.c > @@ -680,19 +680,22 @@ qemuStateInitialize(bool privileged, > if ((qemu_driver->remotePorts = > virPortAllocatorNew(_("display"), > cfg->remotePortMin, > - cfg->remotePortMax)) == NULL) > + cfg->remotePortMax, > + 0)) == NULL) > goto error; > > if ((qemu_driver->webSocketPorts = > virPortAllocatorNew(_("webSocket"), > cfg->webSocketPortMin, > - cfg->webSocketPortMax)) == NULL) > + cfg->webSocketPortMax, > + 0)) == NULL) > goto error; > > if ((qemu_driver->migrationPorts = > virPortAllocatorNew(_("migration"), > cfg->migrationPortMin, > - cfg->migrationPortMax)) == NULL) > + cfg->migrationPortMax, > + 0)) == NULL) > goto error; > > if (qemuSecurityInit(qemu_driver) < 0) > diff --git a/src/util/virportallocator.c b/src/util/virportallocator.c > index b68133a..fa17475 100644 > --- a/src/util/virportallocator.c > +++ b/src/util/virportallocator.c > @@ -43,6 +43,8 @@ struct _virPortAllocator { > > unsigned short start; > unsigned short end; > + > + unsigned int flags; > }; > > static virClassPtr virPortAllocatorClass; > @@ -71,7 +73,8 @@ VIR_ONCE_GLOBAL_INIT(virPortAllocator) > > virPortAllocatorPtr virPortAllocatorNew(const char *name, > unsigned short start, > - unsigned short end) > + unsigned short end, > + unsigned int flags) > { > virPortAllocatorPtr pa; > > @@ -87,6 +90,7 @@ virPortAllocatorPtr virPortAllocatorNew(const char *name, > if (!(pa = virObjectLockableNew(virPortAllocatorClass))) > return NULL; > > + pa->flags = flags; > pa->start = start; > pa->end = end; > > @@ -193,9 +197,11 @@ int virPortAllocatorAcquire(virPortAllocatorPtr pa, > if (used) > continue; > > - if (virPortAllocatorBindToPort(&v6used, i, AF_INET6) < 0 || > - virPortAllocatorBindToPort(&used, i, AF_INET) < 0) > - goto cleanup; > + if (!(pa->flags & VIR_PORT_ALLOCATOR_SKIP_BIND_CHECK)) { > + if (virPortAllocatorBindToPort(&v6used, i, AF_INET6) < 0 || > + virPortAllocatorBindToPort(&used, i, AF_INET) < 0) > + goto cleanup; > + } > > if (!used && !v6used) { > /* Add port to bitmap of reserved ports */ > diff --git a/src/util/virportallocator.h b/src/util/virportallocator.h > index c8aa6de..2fdb8d9 100644 > --- a/src/util/virportallocator.h > +++ b/src/util/virportallocator.h > @@ -28,9 +28,14 @@ > typedef struct _virPortAllocator virPortAllocator; > typedef virPortAllocator *virPortAllocatorPtr; > > +typedef enum { > + VIR_PORT_ALLOCATOR_SKIP_BIND_CHECK = (1 << 0), > +} virPortAllocatorFlags; > + > virPortAllocatorPtr virPortAllocatorNew(const char *name, > unsigned short start, > - unsigned short end); > + unsigned short end, > + unsigned int flags); > > int virPortAllocatorAcquire(virPortAllocatorPtr pa, > unsigned short *port); > diff --git a/tests/virportallocatortest.c b/tests/virportallocatortest.c > index 48d2c9a..96d2ade 100644 > --- a/tests/virportallocatortest.c > +++ b/tests/virportallocatortest.c > @@ -122,7 +122,7 @@ VIR_LOG_INIT("tests.portallocatortest"); > > static int testAllocAll(const void *args ATTRIBUTE_UNUSED) > { > - virPortAllocatorPtr alloc = virPortAllocatorNew("test", 5900, 5909); > + virPortAllocatorPtr alloc = virPortAllocatorNew("test", 5900, 5909, 0); > Should these tests be changed to use the new VIR_PORT_ALLOCATOR_SKIP_BIND_CHECK flag? Regards, Jim > int ret = -1; > unsigned short p1, p2, p3, p4, p5, p6, p7; > > @@ -193,7 +193,7 @@ static int testAllocAll(const void *args ATTRIBUTE_UNUSED) > > static int testAllocReuse(const void *args ATTRIBUTE_UNUSED) > { > - virPortAllocatorPtr alloc = virPortAllocatorNew("test", 5900, 5910); > + virPortAllocatorPtr alloc = virPortAllocatorNew("test", 5900, 5910, 0); > int ret = -1; > unsigned short p1, p2, p3, p4; > > ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v2 3/4] tests: Add more test suite mock helpers 2014-06-03 11:02 [PATCH v2 0/4] Testing libvirt XML -> libxl_domain_config conversion Daniel P. Berrange 2014-06-03 11:02 ` [libvirt] [PATCH v2 1/4] util: Introduce virJSONStringCompare for JSON doc comparisons Daniel P. Berrange 2014-06-03 11:02 ` [PATCH v2 2/4] util: Allow port allocator to skip bind() check Daniel P. Berrange @ 2014-06-03 11:02 ` Daniel P. Berrange 2014-06-03 21:30 ` [libvirt] " Jim Fehlig 2014-06-03 11:02 ` [PATCH v2 4/4] libxl: Add a test suite for libxl option generator Daniel P. Berrange 3 siblings, 1 reply; 14+ messages in thread From: Daniel P. Berrange @ 2014-06-03 11:02 UTC (permalink / raw) To: libvir-list; +Cc: Jim Fehlig, xen-devel, Daniel P. Berrange, Ian Campbell Rename the VIR_MOCK_IMPL* macros to VIR_MOCK_WRAP* and add new VIR_MOCK_IMPL macros which let you directly implement overrides in the preloaded source. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- tests/virfirewalltest.c | 4 ++-- tests/virmock.h | 54 +++++++++++++++++++++++++++++++++++++------------ tests/virsystemdtest.c | 4 ++-- 3 files changed, 45 insertions(+), 17 deletions(-) diff --git a/tests/virfirewalltest.c b/tests/virfirewalltest.c index ba2e6ad..81c5557 100644 --- a/tests/virfirewalltest.c +++ b/tests/virfirewalltest.c @@ -67,7 +67,7 @@ static bool fwError; "target prot opt source destination\n" # if WITH_DBUS -VIR_MOCK_IMPL_RET_ARGS(dbus_connection_send_with_reply_and_block, +VIR_MOCK_WRAP_RET_ARGS(dbus_connection_send_with_reply_and_block, DBusMessage *, DBusConnection *, connection, DBusMessage *, message, @@ -82,7 +82,7 @@ VIR_MOCK_IMPL_RET_ARGS(dbus_connection_send_with_reply_and_block, char **args = NULL; char *type = NULL; - VIR_MOCK_IMPL_INIT_REAL(dbus_connection_send_with_reply_and_block); + VIR_MOCK_REAL_INIT(dbus_connection_send_with_reply_and_block); if (STREQ(service, "org.freedesktop.DBus") && STREQ(member, "ListNames")) { diff --git a/tests/virmock.h b/tests/virmock.h index 0dd8bb5..8352e30 100644 --- a/tests/virmock.h +++ b/tests/virmock.h @@ -234,33 +234,61 @@ */ # define VIR_MOCK_IMPL_RET_ARGS(name, rettype, ...) \ + rettype name(VIR_MOCK_ARGTYPENAMES(__VA_ARGS__)); \ + static rettype (*real_##name)(VIR_MOCK_ARGTYPES(__VA_ARGS__)); \ + rettype name(VIR_MOCK_ARGTYPENAMES_UNUSED(__VA_ARGS__)) + +# define VIR_MOCK_IMPL_RET_VOID(name, rettype) \ + rettype name(void); \ + static rettype (*real_##name)(void); \ + rettype name(void) + +# define VIR_MOCK_IMPL_VOID_ARGS(name, ...) \ + void name(VIR_MOCK_ARGTYPENAMES(__VA_ARGS__)); \ + static void (*real_##name)(VIR_MOCK_ARGTYPES(__VA_ARGS__)); \ + void name(VIR_MOCK_ARGTYPENAMES_UNUSED(__VA_ARGS__)) + +# define VIR_MOCK_IMPL_VOID_VOID(name) \ + void name(void); \ + static void (*real_##name)(void); \ + void name(void) + +/* + * The VIR_MOCK_WRAP_NNN_MMM() macros are intended for use in the + * individual test suites. The define a stub implementation of + * the wrapped method and insert the caller provided code snippet + * as the body of the method. + */ + +# define VIR_MOCK_WRAP_RET_ARGS(name, rettype, ...) \ rettype wrap_##name(VIR_MOCK_ARGTYPENAMES(__VA_ARGS__)); \ static rettype (*real_##name)(VIR_MOCK_ARGTYPES(__VA_ARGS__)); \ rettype wrap_##name(VIR_MOCK_ARGTYPENAMES_UNUSED(__VA_ARGS__)) -# define VIR_MOCK_IMPL_INIT_REAL(name) \ - do { \ - if (real_##name == NULL && \ - !(real_##name = dlsym(RTLD_NEXT, \ - #name))) { \ - fprintf(stderr, "Missing symbol '" #name "'\n"); \ - abort(); \ - } \ - } while (0) - -# define VIR_MOCK_IMPL_RET_VOID(name, rettype) \ +# define VIR_MOCK_WRAP_RET_VOID(name, rettype) \ rettype wrap_##name(void); \ static rettype (*real_##name)(void); \ rettype wrap_##name(void) -# define VIR_MOCK_IMPL_VOID_ARGS(name, ...) \ +# define VIR_MOCK_WRAP_VOID_ARGS(name, ...) \ void wrap_##name(VIR_MOCK_ARGTYPENAMES(__VA_ARGS__)); \ static void (*real_##name)(VIR_MOCK_ARGTYPES(__VA_ARGS__)); \ void wrap_##name(VIR_MOCK_ARGTYPENAMES_UNUSED(__VA_ARGS__)) -# define VIR_MOCK_IMPL_VOID_VOID(name) \ +# define VIR_MOCK_WRAP_VOID_VOID(name) \ void wrap_##name(void); \ static void (*real_##name)(void); \ void wrap_##name(void) + +# define VIR_MOCK_REAL_INIT(name) \ + do { \ + if (real_##name == NULL && \ + !(real_##name = dlsym(RTLD_NEXT, \ + #name))) { \ + fprintf(stderr, "Missing symbol '" #name "'\n"); \ + abort(); \ + } \ + } while (0) + #endif /* __VIR_MOCK_H__ */ diff --git a/tests/virsystemdtest.c b/tests/virsystemdtest.c index 8f7b47e..0d57a6a 100644 --- a/tests/virsystemdtest.c +++ b/tests/virsystemdtest.c @@ -34,7 +34,7 @@ VIR_LOG_INIT("tests.systemdtest"); -VIR_MOCK_IMPL_RET_ARGS(dbus_connection_send_with_reply_and_block, +VIR_MOCK_WRAP_RET_ARGS(dbus_connection_send_with_reply_and_block, DBusMessage *, DBusConnection *, connection, DBusMessage *, message, @@ -45,7 +45,7 @@ VIR_MOCK_IMPL_RET_ARGS(dbus_connection_send_with_reply_and_block, const char *service = dbus_message_get_destination(message); const char *member = dbus_message_get_member(message); - VIR_MOCK_IMPL_INIT_REAL(dbus_connection_send_with_reply_and_block); + VIR_MOCK_REAL_INIT(dbus_connection_send_with_reply_and_block); if (STREQ(service, "org.freedesktop.machine1")) { if (getenv("FAIL_BAD_SERVICE")) { -- 1.9.3 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [libvirt] [PATCH v2 3/4] tests: Add more test suite mock helpers 2014-06-03 11:02 ` [PATCH v2 3/4] tests: Add more test suite mock helpers Daniel P. Berrange @ 2014-06-03 21:30 ` Jim Fehlig 0 siblings, 0 replies; 14+ messages in thread From: Jim Fehlig @ 2014-06-03 21:30 UTC (permalink / raw) To: Daniel P. Berrange; +Cc: libvir-list, xen-devel, Ian Campbell Daniel P. Berrange wrote: > Rename the VIR_MOCK_IMPL* macros to VIR_MOCK_WRAP* > and add new VIR_MOCK_IMPL macros which let you directly > implement overrides in the preloaded source. > > Signed-off-by: Daniel P. Berrange <berrange@redhat.com> > --- > tests/virfirewalltest.c | 4 ++-- > tests/virmock.h | 54 +++++++++++++++++++++++++++++++++++++------------ > tests/virsystemdtest.c | 4 ++-- > 3 files changed, 45 insertions(+), 17 deletions(-) > > diff --git a/tests/virfirewalltest.c b/tests/virfirewalltest.c > index ba2e6ad..81c5557 100644 > --- a/tests/virfirewalltest.c > +++ b/tests/virfirewalltest.c > @@ -67,7 +67,7 @@ static bool fwError; > "target prot opt source destination\n" > > # if WITH_DBUS > -VIR_MOCK_IMPL_RET_ARGS(dbus_connection_send_with_reply_and_block, > +VIR_MOCK_WRAP_RET_ARGS(dbus_connection_send_with_reply_and_block, > DBusMessage *, > DBusConnection *, connection, > DBusMessage *, message, > @@ -82,7 +82,7 @@ VIR_MOCK_IMPL_RET_ARGS(dbus_connection_send_with_reply_and_block, > char **args = NULL; > char *type = NULL; > > - VIR_MOCK_IMPL_INIT_REAL(dbus_connection_send_with_reply_and_block); > + VIR_MOCK_REAL_INIT(dbus_connection_send_with_reply_and_block); > > if (STREQ(service, "org.freedesktop.DBus") && > STREQ(member, "ListNames")) { > diff --git a/tests/virmock.h b/tests/virmock.h > index 0dd8bb5..8352e30 100644 > --- a/tests/virmock.h > +++ b/tests/virmock.h > @@ -234,33 +234,61 @@ > */ > > # define VIR_MOCK_IMPL_RET_ARGS(name, rettype, ...) \ > + rettype name(VIR_MOCK_ARGTYPENAMES(__VA_ARGS__)); \ > + static rettype (*real_##name)(VIR_MOCK_ARGTYPES(__VA_ARGS__)); \ > + rettype name(VIR_MOCK_ARGTYPENAMES_UNUSED(__VA_ARGS__)) > + > +# define VIR_MOCK_IMPL_RET_VOID(name, rettype) \ > + rettype name(void); \ > + static rettype (*real_##name)(void); \ > + rettype name(void) > + > +# define VIR_MOCK_IMPL_VOID_ARGS(name, ...) \ > + void name(VIR_MOCK_ARGTYPENAMES(__VA_ARGS__)); \ > + static void (*real_##name)(VIR_MOCK_ARGTYPES(__VA_ARGS__)); \ > + void name(VIR_MOCK_ARGTYPENAMES_UNUSED(__VA_ARGS__)) > + > +# define VIR_MOCK_IMPL_VOID_VOID(name) \ > + void name(void); \ > + static void (*real_##name)(void); \ > + void name(void) > + > +/* > + * The VIR_MOCK_WRAP_NNN_MMM() macros are intended for use in the > + * individual test suites. The define a stub implementation of > s/The/They/ or s/The/The macros/ This is the first time I've looked at virmock.h in any detail, but didn't notice any problems with this patch. ACK. Regards, Jim > + * the wrapped method and insert the caller provided code snippet > + * as the body of the method. > + */ > + > +# define VIR_MOCK_WRAP_RET_ARGS(name, rettype, ...) \ > rettype wrap_##name(VIR_MOCK_ARGTYPENAMES(__VA_ARGS__)); \ > static rettype (*real_##name)(VIR_MOCK_ARGTYPES(__VA_ARGS__)); \ > rettype wrap_##name(VIR_MOCK_ARGTYPENAMES_UNUSED(__VA_ARGS__)) > > -# define VIR_MOCK_IMPL_INIT_REAL(name) \ > - do { \ > - if (real_##name == NULL && \ > - !(real_##name = dlsym(RTLD_NEXT, \ > - #name))) { \ > - fprintf(stderr, "Missing symbol '" #name "'\n"); \ > - abort(); \ > - } \ > - } while (0) > - > -# define VIR_MOCK_IMPL_RET_VOID(name, rettype) \ > +# define VIR_MOCK_WRAP_RET_VOID(name, rettype) \ > rettype wrap_##name(void); \ > static rettype (*real_##name)(void); \ > rettype wrap_##name(void) > > -# define VIR_MOCK_IMPL_VOID_ARGS(name, ...) \ > +# define VIR_MOCK_WRAP_VOID_ARGS(name, ...) \ > void wrap_##name(VIR_MOCK_ARGTYPENAMES(__VA_ARGS__)); \ > static void (*real_##name)(VIR_MOCK_ARGTYPES(__VA_ARGS__)); \ > void wrap_##name(VIR_MOCK_ARGTYPENAMES_UNUSED(__VA_ARGS__)) > > -# define VIR_MOCK_IMPL_VOID_VOID(name) \ > +# define VIR_MOCK_WRAP_VOID_VOID(name) \ > void wrap_##name(void); \ > static void (*real_##name)(void); \ > void wrap_##name(void) > > + > +# define VIR_MOCK_REAL_INIT(name) \ > + do { \ > + if (real_##name == NULL && \ > + !(real_##name = dlsym(RTLD_NEXT, \ > + #name))) { \ > + fprintf(stderr, "Missing symbol '" #name "'\n"); \ > + abort(); \ > + } \ > + } while (0) > + > #endif /* __VIR_MOCK_H__ */ > diff --git a/tests/virsystemdtest.c b/tests/virsystemdtest.c > index 8f7b47e..0d57a6a 100644 > --- a/tests/virsystemdtest.c > +++ b/tests/virsystemdtest.c > @@ -34,7 +34,7 @@ > > VIR_LOG_INIT("tests.systemdtest"); > > -VIR_MOCK_IMPL_RET_ARGS(dbus_connection_send_with_reply_and_block, > +VIR_MOCK_WRAP_RET_ARGS(dbus_connection_send_with_reply_and_block, > DBusMessage *, > DBusConnection *, connection, > DBusMessage *, message, > @@ -45,7 +45,7 @@ VIR_MOCK_IMPL_RET_ARGS(dbus_connection_send_with_reply_and_block, > const char *service = dbus_message_get_destination(message); > const char *member = dbus_message_get_member(message); > > - VIR_MOCK_IMPL_INIT_REAL(dbus_connection_send_with_reply_and_block); > + VIR_MOCK_REAL_INIT(dbus_connection_send_with_reply_and_block); > > if (STREQ(service, "org.freedesktop.machine1")) { > if (getenv("FAIL_BAD_SERVICE")) { > ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v2 4/4] libxl: Add a test suite for libxl option generator 2014-06-03 11:02 [PATCH v2 0/4] Testing libvirt XML -> libxl_domain_config conversion Daniel P. Berrange ` (2 preceding siblings ...) 2014-06-03 11:02 ` [PATCH v2 3/4] tests: Add more test suite mock helpers Daniel P. Berrange @ 2014-06-03 11:02 ` Daniel P. Berrange 2014-06-03 21:45 ` [libvirt] " Jim Fehlig 3 siblings, 1 reply; 14+ messages in thread From: Daniel P. Berrange @ 2014-06-03 11:02 UTC (permalink / raw) To: libvir-list; +Cc: Jim Fehlig, xen-devel, Daniel P. Berrange, Ian Campbell 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> --- configure.ac | 2 + tests/Makefile.am | 25 ++++- tests/libxlxml2jsondata/minimal.json | 172 ++++++++++++++++++++++++++++++++ tests/libxlxml2jsondata/minimal.xml | 36 +++++++ tests/libxlxml2jsontest.c | 186 +++++++++++++++++++++++++++++++++++ tests/virmocklibxl.c | 87 ++++++++++++++++ 6 files changed, 507 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/configure.ac b/configure.ac index 368d094..e87be85 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 f9f2b84..742503d 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..a0f7d88 --- /dev/null +++ b/tests/libxlxml2jsontest.c @@ -0,0 +1,186 @@ +/* + * 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 + +static const char *abs_top_srcdir; +static virCapsPtr xencaps; + +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, + VIR_JSON_COMPARE_IGNORE_EXTRA_OBJECT_KEYS | + 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("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 && 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.9.3 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [libvirt] [PATCH v2 4/4] libxl: Add a test suite for libxl option generator 2014-06-03 11:02 ` [PATCH v2 4/4] libxl: Add a test suite for libxl option generator Daniel P. Berrange @ 2014-06-03 21:45 ` Jim Fehlig 2014-06-16 23:11 ` Jim Fehlig 0 siblings, 1 reply; 14+ messages in thread From: Jim Fehlig @ 2014-06-03 21:45 UTC (permalink / raw) To: Daniel P. Berrange; +Cc: libvir-list, xen-devel, Ian Campbell Daniel P. Berrange wrote: > 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> > --- > configure.ac | 2 + > tests/Makefile.am | 25 ++++- > tests/libxlxml2jsondata/minimal.json | 172 ++++++++++++++++++++++++++++++++ > tests/libxlxml2jsondata/minimal.xml | 36 +++++++ > tests/libxlxml2jsontest.c | 186 +++++++++++++++++++++++++++++++++++ > tests/virmocklibxl.c | 87 ++++++++++++++++ > 6 files changed, 507 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/configure.ac b/configure.ac > index 368d094..e87be85 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]) > This function exists in Xen 4.2 as well, in libxl.h. > ],[ > if test "$with_libxl" = "yes"; then > fail=1 > diff --git a/tests/Makefile.am b/tests/Makefile.am > index f9f2b84..742503d 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": [ > + > + ], > But 4.2 does not have 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, > doesn't have exec_ssidref, > + "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>", > doesn't have iomem or claim_mode, > + "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, > none of the devices have backend_domname, > + "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": [ > + > + ], > and doesn't contain vtpms, so the test fails. Should we base the expected data on Xen 4.2, or look for some other way to disable the test on 4.2? Regards, Jim > + "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..a0f7d88 > --- /dev/null > +++ b/tests/libxlxml2jsontest.c > @@ -0,0 +1,186 @@ > +/* > + * 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 > + > +static const char *abs_top_srcdir; > +static virCapsPtr xencaps; > + > +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, > + VIR_JSON_COMPARE_IGNORE_EXTRA_OBJECT_KEYS | > + 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("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 && 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 */ > ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [libvirt] [PATCH v2 4/4] libxl: Add a test suite for libxl option generator 2014-06-03 21:45 ` [libvirt] " Jim Fehlig @ 2014-06-16 23:11 ` Jim Fehlig 2014-06-17 8:52 ` Ian Campbell 0 siblings, 1 reply; 14+ messages in thread From: Jim Fehlig @ 2014-06-16 23:11 UTC (permalink / raw) To: Daniel P. Berrange; +Cc: libvir-list, xen-devel, Ian Campbell Jim Fehlig wrote: > Daniel P. Berrange wrote: > >> 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> >> --- >> configure.ac | 2 + >> tests/Makefile.am | 25 ++++- >> tests/libxlxml2jsondata/minimal.json | 172 ++++++++++++++++++++++++++++++++ >> tests/libxlxml2jsondata/minimal.xml | 36 +++++++ >> tests/libxlxml2jsontest.c | 186 +++++++++++++++++++++++++++++++++++ >> tests/virmocklibxl.c | 87 ++++++++++++++++ >> 6 files changed, 507 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/configure.ac b/configure.ac >> index 368d094..e87be85 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]) >> >> > > This function exists in Xen 4.2 as well, in libxl.h. > Any ideas on how to handle this? I'm not aware of an existing macro to check for func 'foo' defined in header 'bar'. Is writing a custom macro along these lines a good solution? A bad solution I tried was hacking the test to check libxl version via libxl_get_version_info(), but that API does not work if not running Xen. Regards, Jim >> ],[ >> if test "$with_libxl" = "yes"; then >> fail=1 >> diff --git a/tests/Makefile.am b/tests/Makefile.am >> index f9f2b84..742503d 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": [ >> + >> + ], >> >> > > But 4.2 does not have 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, >> >> > > doesn't have exec_ssidref, > > >> + "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>", >> >> > > doesn't have iomem or claim_mode, > > >> + "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, >> >> > > none of the devices have backend_domname, > > >> + "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": [ >> + >> + ], >> >> > > and doesn't contain vtpms, so the test fails. Should we base the > expected data on Xen 4.2, or look for some other way to disable the test > on 4.2? > > Regards, > Jim > > >> + "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..a0f7d88 >> --- /dev/null >> +++ b/tests/libxlxml2jsontest.c >> @@ -0,0 +1,186 @@ >> +/* >> + * 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 >> + >> +static const char *abs_top_srcdir; >> +static virCapsPtr xencaps; >> + >> +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, >> + VIR_JSON_COMPARE_IGNORE_EXTRA_OBJECT_KEYS | >> + 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("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 && 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 */ >> >> > > -- > libvir-list mailing list > libvir-list@redhat.com > https://www.redhat.com/mailman/listinfo/libvir-list > > ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [libvirt] [PATCH v2 4/4] libxl: Add a test suite for libxl option generator 2014-06-16 23:11 ` Jim Fehlig @ 2014-06-17 8:52 ` Ian Campbell 2014-06-17 18:40 ` Jim Fehlig 0 siblings, 1 reply; 14+ messages in thread From: Ian Campbell @ 2014-06-17 8:52 UTC (permalink / raw) To: Jim Fehlig; +Cc: libvir-list, xen-devel On Mon, 2014-06-16 at 17:11 -0600, Jim Fehlig wrote: > > This function exists in Xen 4.2 as well, in libxl.h. > > > > Any ideas on how to handle this? I'm not aware of an existing macro to > check for func 'foo' defined in header 'bar'. Is writing a custom macro > along these lines a good solution? A bad solution I tried was hacking > the test to check libxl version via libxl_get_version_info(), but that > API does not work if not running Xen. Given that it exists in everything from 4.2 onwards why do you need to check for it? >From the PoV of these tests (or any application generally) I'd have thought you wouldn't really care if you get this function from libxl.h directly or indirectly via libxl.h including _libxl_types.h. Ian. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [libvirt] [PATCH v2 4/4] libxl: Add a test suite for libxl option generator 2014-06-17 8:52 ` Ian Campbell @ 2014-06-17 18:40 ` Jim Fehlig 2014-06-18 8:33 ` Ian Campbell 2014-06-18 9:07 ` Daniel P. Berrange 0 siblings, 2 replies; 14+ messages in thread From: Jim Fehlig @ 2014-06-17 18:40 UTC (permalink / raw) To: Ian Campbell; +Cc: libvir-list, xen-devel Ian Campbell wrote: > On Mon, 2014-06-16 at 17:11 -0600, Jim Fehlig wrote: > >>> This function exists in Xen 4.2 as well, in libxl.h. >>> >>> >> Any ideas on how to handle this? I'm not aware of an existing macro to >> check for func 'foo' defined in header 'bar'. Is writing a custom macro >> along these lines a good solution? A bad solution I tried was hacking >> the test to check libxl version via libxl_get_version_info(), but that >> API does not work if not running Xen. >> > > Given that it exists in everything from 4.2 onwards why do you need to > check for it? > Hrm, right. I had the half-brained idea to use this to solve the failures I saw when testing this series against Xen 4.2 https://www.redhat.com/archives/libvir-list/2014-June/msg00170.html I think the solution to that specific problem is to use Xen 4.2 config as the baseline. But it got me thinking about the general problem you mentioned near the end of this mail https://www.redhat.com/archives/libvir-list/2014-June/msg00032.html With virJSONStringCompare in 1/1, Daniel provides a way to handle existence of new fields showing up in the json. But what if I want to write a test where the expected data is not supported on earlier versions? E.g. how would I add a test to check conversion of '<tpm ...>' to 'vtpms: [ ]' and expect that to work when running 'make check' against a 4.2 libxl where vtpms were not yet supported? I suppose each such test would have to probe for the feature it checks and skip if not found. Regards, Jim ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [libvirt] [PATCH v2 4/4] libxl: Add a test suite for libxl option generator 2014-06-17 18:40 ` Jim Fehlig @ 2014-06-18 8:33 ` Ian Campbell 2014-06-18 9:07 ` Daniel P. Berrange 1 sibling, 0 replies; 14+ messages in thread From: Ian Campbell @ 2014-06-18 8:33 UTC (permalink / raw) To: Jim Fehlig; +Cc: libvir-list, xen-devel, Daniel P. Berrange On Tue, 2014-06-17 at 12:40 -0600, Jim Fehlig wrote: > Ian Campbell wrote: > > On Mon, 2014-06-16 at 17:11 -0600, Jim Fehlig wrote: > > > >>> This function exists in Xen 4.2 as well, in libxl.h. > >>> > >>> > >> Any ideas on how to handle this? I'm not aware of an existing macro to > >> check for func 'foo' defined in header 'bar'. Is writing a custom macro > >> along these lines a good solution? A bad solution I tried was hacking > >> the test to check libxl version via libxl_get_version_info(), but that > >> API does not work if not running Xen. > >> > > > > Given that it exists in everything from 4.2 onwards why do you need to > > check for it? > > > > Hrm, right. I had the half-brained idea to use this to solve the > failures I saw when testing this series against Xen 4.2 > > https://www.redhat.com/archives/libvir-list/2014-June/msg00170.html > > I think the solution to that specific problem is to use Xen 4.2 config > as the baseline. But it got me thinking about the general problem you > mentioned near the end of this mail > > https://www.redhat.com/archives/libvir-list/2014-June/msg00032.html > > With virJSONStringCompare in 1/1, Daniel provides a way to handle > existence of new fields showing up in the json. But what if I want to > write a test where the expected data is not supported on earlier > versions? E.g. how would I add a test to check conversion of '<tpm > ...>' to 'vtpms: [ ]' and expect that to work when running 'make check' > against a 4.2 libxl where vtpms were not yet supported? I suppose each > such test would have to probe for the feature it checks and skip if not > found. Right. You'd probably want to gate such a test case on the corresponding LIBXL_HAVE_XXX #define from libxl.h. Ian. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [libvirt] [PATCH v2 4/4] libxl: Add a test suite for libxl option generator 2014-06-17 18:40 ` Jim Fehlig 2014-06-18 8:33 ` Ian Campbell @ 2014-06-18 9:07 ` Daniel P. Berrange 1 sibling, 0 replies; 14+ messages in thread From: Daniel P. Berrange @ 2014-06-18 9:07 UTC (permalink / raw) To: Jim Fehlig; +Cc: libvir-list, xen-devel, Ian Campbell On Tue, Jun 17, 2014 at 12:40:30PM -0600, Jim Fehlig wrote: > Ian Campbell wrote: > > On Mon, 2014-06-16 at 17:11 -0600, Jim Fehlig wrote: > > > >>> This function exists in Xen 4.2 as well, in libxl.h. > >>> > >>> > >> Any ideas on how to handle this? I'm not aware of an existing macro to > >> check for func 'foo' defined in header 'bar'. Is writing a custom macro > >> along these lines a good solution? A bad solution I tried was hacking > >> the test to check libxl version via libxl_get_version_info(), but that > >> API does not work if not running Xen. > >> > > > > Given that it exists in everything from 4.2 onwards why do you need to > > check for it? > > > > Hrm, right. I had the half-brained idea to use this to solve the > failures I saw when testing this series against Xen 4.2 > > https://www.redhat.com/archives/libvir-list/2014-June/msg00170.html > > I think the solution to that specific problem is to use Xen 4.2 config > as the baseline. But it got me thinking about the general problem you > mentioned near the end of this mail > > https://www.redhat.com/archives/libvir-list/2014-June/msg00032.html > > With virJSONStringCompare in 1/1, Daniel provides a way to handle > existence of new fields showing up in the json. But what if I want to > write a test where the expected data is not supported on earlier > versions? E.g. how would I add a test to check conversion of '<tpm > ...>' to 'vtpms: [ ]' and expect that to work when running 'make check' > against a 4.2 libxl where vtpms were not yet supported? I suppose each > such test would have to probe for the feature it checks and skip if not > found. My last approach was to allow the JSON comparator to skip certain types of missing data but I don't think that's sufficiently flexible anymore. I'm thinking instead, that we could maintain a set of context paths which designate things that are new in each version, which would indicate things that should be skipped with old versions. So we with 4.3, we'd list /c_info/driver_domain /c_info/pvh and any other newly added fields. Then when running the test on 4.2 if the expected XML contained either of those paths, we'd skip them when comparing against the actual JSON. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2014-06-18 9:07 UTC | newest] Thread overview: 14+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2014-06-03 11:02 [PATCH v2 0/4] Testing libvirt XML -> libxl_domain_config conversion Daniel P. Berrange 2014-06-03 11:02 ` [libvirt] [PATCH v2 1/4] util: Introduce virJSONStringCompare for JSON doc comparisons Daniel P. Berrange 2014-06-03 21:18 ` Jim Fehlig 2014-06-03 11:02 ` [PATCH v2 2/4] util: Allow port allocator to skip bind() check Daniel P. Berrange 2014-06-03 21:25 ` [libvirt] " Jim Fehlig 2014-06-03 11:02 ` [PATCH v2 3/4] tests: Add more test suite mock helpers Daniel P. Berrange 2014-06-03 21:30 ` [libvirt] " Jim Fehlig 2014-06-03 11:02 ` [PATCH v2 4/4] libxl: Add a test suite for libxl option generator Daniel P. Berrange 2014-06-03 21:45 ` [libvirt] " Jim Fehlig 2014-06-16 23:11 ` Jim Fehlig 2014-06-17 8:52 ` Ian Campbell 2014-06-17 18:40 ` Jim Fehlig 2014-06-18 8:33 ` Ian Campbell 2014-06-18 9:07 ` Daniel P. Berrange
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).