libvirt/tests/qemucapabilitiestest.c

232 lines
6.1 KiB
C
Raw Normal View History

/*
* Copyright (C) 2011-2013 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/>.
*
*/
#include <config.h>
#include "testutils.h"
#include "testutilsqemu.h"
#include "qemumonitortestutils.h"
#define LIBVIRT_QEMU_CAPSPRIV_H_ALLOW
#include "qemu/qemu_capspriv.h"
#define LIBVIRT_QEMU_MONITOR_PRIV_H_ALLOW
#include "qemu/qemu_monitor_priv.h"
#define LIBVIRT_QEMU_PROCESSPRIV_H_ALLOW
#include "qemu/qemu_processpriv.h"
#define VIR_FROM_THIS VIR_FROM_NONE
typedef struct _testQemuData testQemuData;
struct _testQemuData {
virQEMUDriver driver;
const char *inputDir;
const char *outputDir;
const char *prefix;
const char *version;
const char *archName;
const char *variant;
const char *suffix;
int ret;
};
bool isHVF = false;
bool
virQEMUCapsProbeHVF(virQEMUCaps *qemuCaps G_GNUC_UNUSED)
{
return isHVF;
}
static int
testQemuDataInit(testQemuData *data)
{
if (qemuTestDriverInit(&data->driver) < 0)
return -1;
data->outputDir = TEST_QEMU_CAPS_PATH;
data->ret = 0;
return 0;
}
static void
testQemuDataReset(testQemuData *data)
{
qemuTestDriverFree(&data->driver);
}
static int
testQemuCaps(const void *opaque)
{
testQemuData *data = (void *) opaque;
g_autofree char *repliesFile = NULL;
g_autofree char *capsFile = NULL;
g_autoptr(qemuMonitorTest) mon = NULL;
g_autoptr(virQEMUCaps) capsActual = NULL;
g_autofree char *binary = NULL;
g_autofree char *actual = NULL;
unsigned int fakeMicrocodeVersion = 0;
const char *p;
repliesFile = g_strdup_printf("%s/%s_%s_%s%s.%s",
data->inputDir, data->prefix, data->version,
data->archName, data->variant, data->suffix);
capsFile = g_strdup_printf("%s/%s_%s_%s%s.xml",
data->outputDir, data->prefix, data->version,
data->archName, data->variant);
if (!(mon = qemuMonitorTestNewFromFileFull(repliesFile, &data->driver, NULL,
NULL)))
return -1;
isHVF = STREQ(data->variant, "+hvf");
if (qemuProcessQMPInitMonitor(qemuMonitorTestGetMonitor(mon)) < 0)
return -1;
binary = g_strdup_printf("/usr/bin/qemu-system-%s",
data->archName);
capsActual = virQEMUCapsNewBinary(binary);
if (virQEMUCapsInitQMPMonitor(capsActual, qemuMonitorTestGetMonitor(mon)) < 0)
return -1;
if (virQEMUCapsHaveAccel(capsActual) &&
virQEMUCapsGet(capsActual, QEMU_CAPS_TCG)) {
qemuMonitorResetCommandID(qemuMonitorTestGetMonitor(mon));
if (qemuProcessQMPInitMonitor(qemuMonitorTestGetMonitor(mon)) < 0)
return -1;
if (virQEMUCapsInitQMPMonitorTCG(capsActual,
qemuMonitorTestGetMonitor(mon)) < 0)
return -1;
/* calculate fake microcode version based on filename for a reproducible
* number for testing which does not change with the contents */
for (p = data->archName; *p; p++)
fakeMicrocodeVersion += *p;
fakeMicrocodeVersion *= 100000;
for (p = data->version; *p; p++)
fakeMicrocodeVersion += *p;
virQEMUCapsSetMicrocodeVersion(capsActual, fakeMicrocodeVersion);
}
if (!(actual = virQEMUCapsFormatCache(capsActual)))
return -1;
if (virTestCompareToFile(actual, capsFile) < 0)
return -1;
return 0;
}
static int
testQemuCapsCopy(const void *opaque)
{
const testQemuData *data = opaque;
g_autofree char *capsFile = NULL;
g_autoptr(virQEMUCaps) orig = NULL;
g_autoptr(virQEMUCaps) copy = NULL;
g_autofree char *actual = NULL;
capsFile = g_strdup_printf("%s/%s_%s_%s%s.xml",
data->outputDir, data->prefix, data->version,
data->archName, data->variant);
if (!(orig = qemuTestParseCapabilitiesArch(
virArchFromString(data->archName), capsFile)))
return -1;
copy = virQEMUCapsNewCopy(orig);
if (!(actual = virQEMUCapsFormatCache(copy)))
return -1;
if (virTestCompareToFile(actual, capsFile) < 0)
return -1;
return 0;
}
static int
doCapsTest(const char *inputDir,
const char *prefix,
const char *version,
const char *archName,
const char *variant,
const char *suffix,
void *opaque)
{
testQemuData *data = (testQemuData *) opaque;
g_autofree char *title = NULL;
g_autofree char *copyTitle = NULL;
title = g_strdup_printf("%s (%s)", version, archName);
copyTitle = g_strdup_printf("copy %s (%s)", version, archName);
data->inputDir = inputDir;
data->prefix = prefix;
data->version = version;
data->archName = archName;
data->variant = variant,
data->suffix = suffix;
if (virTestRun(title, testQemuCaps, data) < 0)
data->ret = -1;
if (virTestRun(copyTitle, testQemuCapsCopy, data) < 0)
data->ret = -1;
return 0;
}
static int
mymain(void)
{
testQemuData data;
virEventRegisterDefaultImpl();
if (testQemuDataInit(&data) < 0)
return EXIT_FAILURE;
if (testQemuCapsIterate(".replies", doCapsTest, &data) < 0)
return EXIT_FAILURE;
/* See documentation in qemucapabilitiesdata/README.rst */
testQemuDataReset(&data);
tests: Avoid use of virQEMUDriverCreateXMLConf(NULL) 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>
2015-09-22 14:27:57 +00:00
return (data.ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}
VIR_TEST_MAIN_PRELOAD(mymain,
VIR_TEST_MOCK("domaincaps"))