mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-27 07:22:07 +03:00
086f37e97a
We use the function to create a virDomainXMLOption object that is required for some functions. However, we don't pass the driver pointer to the object anywhere - rather than pass NULL. This causes trouble later when parsing a domain XML and calling post parse callbacks: Program received signal SIGSEGV, Segmentation fault. 0x000000000043fa3e in qemuDomainDefPostParse (def=0x7d36c0, caps=0x7caf10, opaque=0x0) at qemu/qemu_domain.c:1043 1043 qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache, def->emulator); (gdb) bt #0 0x000000000043fa3e in qemuDomainDefPostParse (def=0x7d36c0, caps=0x7caf10, opaque=0x0) at qemu/qemu_domain.c:1043 #1 0x00007ffff2928bf9 in virDomainDefPostParse (def=0x7d36c0, caps=0x7caf10, xmlopt=0x7c82c0) at conf/domain_conf.c:4269 #2 0x00007ffff294de04 in virDomainDefParseXML (xml=0x7da8c0, root=0x7dab80, ctxt=0x7da980, caps=0x7caf10, xmlopt=0x7c82c0, flags=0) at conf/domain_conf.c:16400 #3 0x00007ffff294e5b5 in virDomainDefParseNode (xml=0x7da8c0, root=0x7dab80, caps=0x7caf10, xmlopt=0x7c82c0, flags=0) at conf/domain_conf.c:16582 #4 0x00007ffff294e424 in virDomainDefParse (xmlStr=0x0, filename=0x7c7ef0 "/home/zippy/work/libvirt/libvirt.git/tests/securityselinuxlabeldata/disks.xml", caps=0x7caf10, xmlopt=0x7c82c0, flags=0) at conf/domain_conf.c:16529 #5 0x00007ffff294e4b2 in virDomainDefParseFile (filename=0x7c7ef0 "/home/zippy/work/libvirt/libvirt.git/tests/securityselinuxlabeldata/disks.xml", caps=0x7caf10, xmlopt=0x7c82c0, flags=0) at conf/domain_conf.c:16553 #6 0x00000000004303ca in testSELinuxLoadDef (testname=0x53c929 "disks") at securityselinuxlabeltest.c:192 #7 0x00000000004309e8 in testSELinuxLabeling (opaque=0x53c929) at securityselinuxlabeltest.c:313 #8 0x0000000000431207 in virtTestRun (title=0x53c92f "Labelling \"disks\"", body=0x430964 <testSELinuxLabeling>, data=0x53c929) at testutils.c:211 #9 0x0000000000430c5d in mymain () at securityselinuxlabeltest.c:373 #10 0x00000000004325c2 in virtTestMain (argc=1, argv=0x7fffffffd7e8, func=0x430b4a <mymain>) at testutils.c:863 #11 0x0000000000430deb in main (argc=1, argv=0x7fffffffd7e8) at securityselinuxlabeltest.c:381 Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
204 lines
6.1 KiB
C
204 lines
6.1 KiB
C
#include <config.h>
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
#include "testutils.h"
|
|
|
|
#ifdef WITH_QEMU
|
|
|
|
# include "internal.h"
|
|
# include "viralloc.h"
|
|
# include "qemu/qemu_monitor.h"
|
|
# include "qemu/qemu_monitor_text.h"
|
|
# include "qemumonitortestutils.h"
|
|
# include "testutilsqemu.h"
|
|
|
|
# define VIR_FROM_THIS VIR_FROM_NONE
|
|
|
|
struct testEscapeString
|
|
{
|
|
const char *unescaped;
|
|
const char *escaped;
|
|
};
|
|
|
|
static struct testEscapeString escapeStrings[] = {
|
|
{ "", "" },
|
|
{ " ", " " },
|
|
{ "\\", "\\\\" },
|
|
{ "\n", "\\n" },
|
|
{ "\r", "\\r" },
|
|
{ "\"", "\\\"" },
|
|
{ "\"\"\"\\\\\n\r\\\\\n\r\"\"\"", "\\\"\\\"\\\"\\\\\\\\\\n\\r\\\\\\\\\\n\\r\\\"\\\"\\\"" },
|
|
{ "drive_add dummy file=foo\\", "drive_add dummy file=foo\\\\" },
|
|
{ "block info", "block info" },
|
|
{ "set_password \":\\\"\"", "set_password \\\":\\\\\\\"\\\"" },
|
|
};
|
|
|
|
static int testEscapeArg(const void *data ATTRIBUTE_UNUSED)
|
|
{
|
|
size_t i;
|
|
char *escaped = NULL;
|
|
for (i = 0; i < ARRAY_CARDINALITY(escapeStrings); ++i) {
|
|
escaped = qemuMonitorEscapeArg(escapeStrings[i].unescaped);
|
|
if (!escaped) {
|
|
VIR_TEST_DEBUG("\nUnescaped string [%s]\n",
|
|
escapeStrings[i].unescaped);
|
|
VIR_TEST_DEBUG("Expect result [%s]\n",
|
|
escapeStrings[i].escaped);
|
|
VIR_TEST_DEBUG("Actual result [(null)]\n");
|
|
return -1;
|
|
}
|
|
if (STRNEQ(escapeStrings[i].escaped, escaped)) {
|
|
virtTestDifference(stderr, escapeStrings[i].escaped, escaped);
|
|
VIR_FREE(escaped);
|
|
return -1;
|
|
}
|
|
VIR_FREE(escaped);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int testUnescapeArg(const void *data ATTRIBUTE_UNUSED)
|
|
{
|
|
size_t i;
|
|
char *unescaped = NULL;
|
|
for (i = 0; i < ARRAY_CARDINALITY(escapeStrings); ++i) {
|
|
unescaped = qemuMonitorUnescapeArg(escapeStrings[i].escaped);
|
|
if (!unescaped) {
|
|
VIR_TEST_DEBUG("\nEscaped string [%s]\n",
|
|
escapeStrings[i].escaped);
|
|
VIR_TEST_DEBUG("Expect result [%s]\n",
|
|
escapeStrings[i].unescaped);
|
|
VIR_TEST_DEBUG("Actual result [(null)]\n");
|
|
return -1;
|
|
}
|
|
if (STRNEQ(escapeStrings[i].unescaped, unescaped)) {
|
|
virtTestDifference(stderr, escapeStrings[i].unescaped, unescaped);
|
|
VIR_FREE(unescaped);
|
|
return -1;
|
|
}
|
|
VIR_FREE(unescaped);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
struct blockInfoData {
|
|
const char *dev;
|
|
qemuBlockStats data;
|
|
};
|
|
|
|
static const struct blockInfoData testBlockInfoData[] =
|
|
{
|
|
/* NAME, rd_req, rd_bytes, wr_req, wr_bytes, rd_total_time, wr_total_time,
|
|
* flush_req, flush_total_time, capacity, physical, wr_highest_offset,
|
|
* wr_highest_offset_valid*/
|
|
{"vda", {11, 12, 13, 14, 15, 16, 17, 18, 0, 0, 0, false}},
|
|
{"vdb", {21, 22, 23, 24, 25, 26, 27, 28, 0, 0, 0, false}},
|
|
{"vdc", {31, 32, 33, -1, 35, 36, 37, 38, 0, 0, 0, false}},
|
|
{"vdd", {-1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, false}},
|
|
{"vde", {41, 42, 43, 44, 45, 46, 47, 48, 0, 0, 0, false}}
|
|
};
|
|
|
|
static const char testBlockInfoReply[] =
|
|
"(qemu) info blockstats\r\n"
|
|
"vda: rd_operations=11 rd_bytes=12 wr_operations=13 wr_bytes=14 rd_total_time_ns=15 wr_total_time_ns=16 flush_operations=17 flush_total_time_ns=18\n"
|
|
"vdb: rd_total_time_ns=25 wr_total_time_ns=26 flush_operations=27 flush_total_time_ns=28 rd_operations=21 rd_bytes=22 wr_operations=23 wr_bytes=24 \n"
|
|
"drive-vdc: rd_operations=31 rd_bytes=32 wr_operations=33 rd_total_time_ns=35 wr_total_time_ns=36 flush_operations=37 flush_total_time_ns=38\n"
|
|
"vdd: \n"
|
|
"vde: rd_operations=41 rd_bytes=42 wr_operations=43 wr_bytes=44 rd_total_time_ns=45 wr_total_time_ns=46 flush_operations=47 flush_total_time_ns=48\n"
|
|
"(qemu) ";
|
|
|
|
static int
|
|
testMonitorTextBlockInfo(const void *opaque)
|
|
{
|
|
virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr) opaque;
|
|
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(false, xmlopt);
|
|
virHashTablePtr blockstats = NULL;
|
|
size_t i;
|
|
int ret = -1;
|
|
|
|
if (!test)
|
|
return -1;
|
|
|
|
if (!(blockstats = virHashCreate(10, virHashValueFree)))
|
|
goto cleanup;
|
|
|
|
if (qemuMonitorTestAddItem(test, "info", testBlockInfoReply) < 0)
|
|
goto cleanup;
|
|
|
|
if (qemuMonitorTextGetAllBlockStatsInfo(qemuMonitorTestGetMonitor(test),
|
|
blockstats) < 0)
|
|
goto cleanup;
|
|
|
|
for (i = 0; i < ARRAY_CARDINALITY(testBlockInfoData); i++) {
|
|
qemuBlockStatsPtr entry;
|
|
|
|
if (!(entry = virHashLookup(blockstats, testBlockInfoData[i].dev))) {
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
"device '%s' was not found in text block stats reply",
|
|
testBlockInfoData[i].dev);
|
|
goto cleanup;
|
|
}
|
|
|
|
if (memcmp(entry, &testBlockInfoData[i].data, sizeof(qemuBlockStats)) != 0) {
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
"block stats for device '%s' differ",
|
|
testBlockInfoData[i].dev);
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
qemuMonitorTestFree(test);
|
|
virHashFree(blockstats);
|
|
return ret;
|
|
}
|
|
|
|
|
|
static int
|
|
mymain(void)
|
|
{
|
|
virQEMUDriver driver;
|
|
int result = 0;
|
|
|
|
if (virThreadInitialize() < 0 ||
|
|
qemuTestDriverInit(&driver) < 0)
|
|
return EXIT_FAILURE;
|
|
|
|
virEventRegisterDefaultImpl();
|
|
|
|
# define DO_TEST(_name) \
|
|
do { \
|
|
if (virtTestRun("qemu monitor "#_name, test##_name, \
|
|
driver.xmlopt) < 0) { \
|
|
result = -1; \
|
|
} \
|
|
} while (0)
|
|
|
|
DO_TEST(EscapeArg);
|
|
DO_TEST(UnescapeArg);
|
|
DO_TEST(MonitorTextBlockInfo);
|
|
|
|
qemuTestDriverFree(&driver);
|
|
|
|
return result == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
|
}
|
|
|
|
VIRT_TEST_MAIN(mymain)
|
|
|
|
#else
|
|
|
|
int main(void)
|
|
{
|
|
return EXIT_AM_SKIP;
|
|
}
|
|
|
|
#endif /* WITH_QEMU */
|