diff --git a/tests/Makefile.am b/tests/Makefile.am index 072b75b1e2..621480dd0c 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -119,6 +119,7 @@ EXTRA_DIST = \ oomtrace.pl \ qemuagentdata \ qemuargv2xmldata \ + qemublocktestdata \ qemucapabilitiesdata \ qemucaps2xmldata \ qemuhotplugtestcpus \ @@ -657,8 +658,10 @@ qemuhotplugtest_LDADD = libqemumonitortestutils.la $(qemu_LDADDS) $(LDADDS) qemublocktest_SOURCES = \ qemublocktest.c \ testutils.h testutils.c \ + testutilsqemu.h testutilsqemu.c \ $(NULL) qemublocktest_LDADD = \ + libqemumonitortestutils.la \ ../src/libvirt_conf.la \ ../src/libvirt_util.la \ $(qemu_LDADDS) \ diff --git a/tests/qemublocktest.c b/tests/qemublocktest.c index 7eef9f286a..efad256df7 100644 --- a/tests/qemublocktest.c +++ b/tests/qemublocktest.c @@ -19,10 +19,15 @@ #include #include "testutils.h" +#include "testutilsqemu.h" +#include "testutilsqemuschema.h" #include "virstoragefile.h" #include "virstring.h" #include "virlog.h" #include "qemu/qemu_block.h" +#include "qemu/qemu_qapi.h" + +#include "qemu/qemu_command.h" #define VIR_FROM_THIS VIR_FROM_NONE @@ -113,11 +118,191 @@ testBackingXMLjsonXML(const void *args) } +struct testQemuDiskXMLToJSONData { + virQEMUDriverPtr driver; + virHashTablePtr schema; + virJSONValuePtr schemaroot; + const char *name; + bool fail; + + virJSONValuePtr *props; + size_t nprops; + + virQEMUCapsPtr qemuCaps; +}; + + +static void +testQemuDiskXMLToPropsClear(struct testQemuDiskXMLToJSONData *data) +{ + size_t i; + + for (i = 0; i < data->nprops; i++) + virJSONValueFree(data->props[i]); + + data->nprops = 0; + VIR_FREE(data->props); +} + + +static const char *testQemuDiskXMLToJSONPath = abs_srcdir "/qemublocktestdata/xml2json/"; + +static int +testQemuDiskXMLToProps(const void *opaque) +{ + struct testQemuDiskXMLToJSONData *data = (void *) opaque; + virDomainDiskDefPtr disk = NULL; + virStorageSourcePtr n; + virJSONValuePtr props = NULL; + char *xmlpath = NULL; + char *xmlstr = NULL; + int ret = -1; + + if (virAsprintf(&xmlpath, "%s%s.xml", + testQemuDiskXMLToJSONPath, data->name) < 0) + goto cleanup; + + if (virTestLoadFile(xmlpath, &xmlstr) < 0) + goto cleanup; + + /* qemu stores node names in the status XML portion */ + if (!(disk = virDomainDiskDefParse(xmlstr, NULL, data->driver->xmlopt, + VIR_DOMAIN_DEF_PARSE_STATUS))) + goto cleanup; + + if (qemuCheckDiskConfig(disk, data->qemuCaps) < 0 || + qemuDomainDeviceDefValidateDisk(disk, data->qemuCaps) < 0) { + VIR_TEST_VERBOSE("invalid configuration for disk\n"); + goto cleanup; + } + + if (qemuDomainPrepareDiskSourceChain(disk, NULL, NULL, data->qemuCaps) < 0) + goto cleanup; + + for (n = disk->src; virStorageSourceIsBacking(n); n = n->backingStore) { + if (!(props = qemuBlockStorageSourceGetBlockdevProps(n))) { + if (!data->fail) { + VIR_TEST_VERBOSE("failed to generate qemu blockdev props\n"); + goto cleanup; + } + } else if (data->fail) { + VIR_TEST_VERBOSE("qemu blockdev props should have failed\n"); + goto cleanup; + } + + if (VIR_APPEND_ELEMENT(data->props, data->nprops, props) < 0) + goto cleanup; + } + + ret = 0; + + cleanup: + virDomainDiskDefFree(disk); + VIR_FREE(xmlpath); + VIR_FREE(xmlstr); + return ret; +} + + +static int +testQemuDiskXMLToPropsValidateSchema(const void *opaque) +{ + struct testQemuDiskXMLToJSONData *data = (void *) opaque; + virBuffer debug = VIR_BUFFER_INITIALIZER; + char *propsstr = NULL; + char *debugmsg = NULL; + int ret = 0; + size_t i; + + if (data->fail) + return EXIT_AM_SKIP; + + for (i = 0; i < data->nprops; i++) { + if (testQEMUSchemaValidate(data->props[i], data->schemaroot, + data->schema, &debug) < 0) { + debugmsg = virBufferContentAndReset(&debug); + propsstr = virJSONValueToString(data->props[i], true); + VIR_TEST_VERBOSE("json does not conform to QAPI schema"); + VIR_TEST_DEBUG("json:\n%s\ndoes not match schema. Debug output:\n %s", + propsstr, NULLSTR(debugmsg)); + VIR_FREE(debugmsg); + VIR_FREE(propsstr); + ret = -1; + } + + virBufferFreeAndReset(&debug); + } + return ret; +} + + +static int +testQemuDiskXMLToPropsValidateFile(const void *opaque) +{ + struct testQemuDiskXMLToJSONData *data = (void *) opaque; + virBuffer buf = VIR_BUFFER_INITIALIZER; + char *jsonpath = NULL; + char *actual = NULL; + int ret = -1; + size_t i; + + if (data->fail) + return EXIT_AM_SKIP; + + if (virAsprintf(&jsonpath, "%s%s.json", + testQemuDiskXMLToJSONPath, data->name) < 0) + goto cleanup; + + for (i = 0; i < data->nprops; i++) { + char *jsonstr; + + if (!(jsonstr = virJSONValueToString(data->props[i], true))) + goto cleanup; + + virBufferAdd(&buf, jsonstr, -1); + VIR_FREE(jsonstr); + } + + if (virBufferCheckError(&buf) < 0) + goto cleanup; + + actual = virBufferContentAndReset(&buf); + + ret = virTestCompareToFile(actual, jsonpath); + + cleanup: + VIR_FREE(jsonpath); + VIR_FREE(actual); + return ret; +} + + static int mymain(void) { int ret = 0; + virQEMUDriver driver; struct testBackingXMLjsonXMLdata xmljsonxmldata; + struct testQemuDiskXMLToJSONData diskxmljsondata; + char *capslatest_x86_64 = NULL; + virQEMUCapsPtr caps_x86_64 = NULL; + + if (qemuTestDriverInit(&driver) < 0) + return EXIT_FAILURE; + + diskxmljsondata.driver = &driver; + + if (!(capslatest_x86_64 = testQemuGetLatestCapsForArch(abs_srcdir "/qemucapabilitiesdata", + "x86_64", "xml"))) + return EXIT_FAILURE; + + VIR_TEST_VERBOSE("\nlatest caps x86_64: %s\n", capslatest_x86_64); + + if (!(caps_x86_64 = qemuTestParseCapabilitiesArch(virArchFromString("x86_64"), + capslatest_x86_64))) + return EXIT_FAILURE; + + diskxmljsondata.qemuCaps = caps_x86_64; virTestCounterReset("qemu storage source xml->json->xml "); @@ -183,6 +368,49 @@ mymain(void) " \n" "\n"); +#define TEST_DISK_TO_JSON_FULL(nme, fl) \ + do { \ + diskxmljsondata.name = nme; \ + diskxmljsondata.props = NULL; \ + diskxmljsondata.nprops = 0; \ + diskxmljsondata.fail = fl; \ + if (virTestRun("disk xml to props " nme, testQemuDiskXMLToProps, \ + &diskxmljsondata) < 0) \ + ret = -1; \ + if (virTestRun("disk xml to props validate schema " nme, \ + testQemuDiskXMLToPropsValidateSchema, &diskxmljsondata) < 0) \ + ret = -1; \ + if (virTestRun("disk xml to props validate file " nme, \ + testQemuDiskXMLToPropsValidateFile, &diskxmljsondata) < 0) \ + ret = -1; \ + testQemuDiskXMLToPropsClear(&diskxmljsondata); \ + } while (0) + +#define TEST_DISK_TO_JSON(nme) TEST_DISK_TO_JSON_FULL(nme, false) + + if (!(diskxmljsondata.schema = testQEMUSchemaLoad())) { + ret = -1; + goto cleanup; + } + + if (virQEMUQAPISchemaPathGet("blockdev-add/arg-type", + diskxmljsondata.schema, + &diskxmljsondata.schemaroot) < 0 || + !diskxmljsondata.schemaroot) { + VIR_TEST_VERBOSE("failed to find schema entry for blockdev-add\n"); + ret = -1; + goto cleanup; + } + + TEST_DISK_TO_JSON_FULL("nodename-long-format", true); + TEST_DISK_TO_JSON_FULL("nodename-long-protocol", true); + + cleanup: + virHashFree(diskxmljsondata.schema); + qemuTestDriverFree(&driver); + VIR_FREE(capslatest_x86_64); + virObjectUnref(caps_x86_64); + return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/tests/qemublocktestdata/xml2json/nodename-long-format.xml b/tests/qemublocktestdata/xml2json/nodename-long-format.xml new file mode 100644 index 0000000000..8fccf850db --- /dev/null +++ b/tests/qemublocktestdata/xml2json/nodename-long-format.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/tests/qemublocktestdata/xml2json/nodename-long-protocol.xml b/tests/qemublocktestdata/xml2json/nodename-long-protocol.xml new file mode 100644 index 0000000000..e60d988325 --- /dev/null +++ b/tests/qemublocktestdata/xml2json/nodename-long-protocol.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + +