2010-10-07 22:35:17 +08:00
|
|
|
/*
|
|
|
|
* cputest.c: Test the libvirtd internal CPU APIs
|
|
|
|
*
|
2011-04-30 00:21:20 +08:00
|
|
|
* Copyright (C) 2010-2011 Red Hat, Inc.
|
2010-10-07 22:35:17 +08:00
|
|
|
*
|
|
|
|
* 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, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*
|
|
|
|
* Author: Jiri Denemark <jdenemar@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 "internal.h"
|
|
|
|
#include "xml.h"
|
|
|
|
#include "memory.h"
|
|
|
|
#include "buf.h"
|
|
|
|
#include "testutils.h"
|
|
|
|
#include "cpu_conf.h"
|
|
|
|
#include "cpu/cpu.h"
|
|
|
|
#include "cpu/cpu_map.h"
|
|
|
|
|
|
|
|
static const char *abs_top_srcdir;
|
|
|
|
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_CPU
|
|
|
|
#define MAX_FILE 4096
|
|
|
|
|
|
|
|
enum compResultShadow {
|
|
|
|
ERROR = VIR_CPU_COMPARE_ERROR,
|
|
|
|
INCOMPATIBLE = VIR_CPU_COMPARE_INCOMPATIBLE,
|
|
|
|
IDENTICAL = VIR_CPU_COMPARE_IDENTICAL,
|
|
|
|
SUPERSET = VIR_CPU_COMPARE_SUPERSET
|
|
|
|
};
|
|
|
|
|
|
|
|
enum cpuTestBoolWithError {
|
|
|
|
FAIL = -1,
|
|
|
|
NO = 0,
|
|
|
|
YES = 1
|
|
|
|
};
|
|
|
|
|
|
|
|
enum api {
|
|
|
|
API_COMPARE,
|
|
|
|
API_GUEST_DATA,
|
|
|
|
API_BASELINE,
|
|
|
|
API_UPDATE,
|
|
|
|
API_HAS_FEATURE
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *apis[] = {
|
|
|
|
"compare",
|
|
|
|
"guest data",
|
|
|
|
"baseline",
|
|
|
|
"update",
|
|
|
|
"has feature"
|
|
|
|
};
|
|
|
|
|
|
|
|
struct data {
|
|
|
|
const char *arch;
|
|
|
|
enum api api;
|
|
|
|
const char *host;
|
|
|
|
const char *name;
|
|
|
|
const char **models;
|
|
|
|
const char *modelsName;
|
|
|
|
unsigned int nmodels;
|
|
|
|
const char *preferred;
|
|
|
|
int result;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static virCPUDefPtr
|
|
|
|
cpuTestLoadXML(const char *arch, const char *name)
|
|
|
|
{
|
|
|
|
char xml[PATH_MAX];
|
|
|
|
xmlDocPtr doc = NULL;
|
|
|
|
xmlXPathContextPtr ctxt = NULL;
|
|
|
|
virCPUDefPtr cpu = NULL;
|
|
|
|
|
|
|
|
snprintf(xml, PATH_MAX,
|
|
|
|
"%s/cputestdata/%s-%s.xml",
|
|
|
|
abs_srcdir, arch, name);
|
|
|
|
|
|
|
|
if (!(doc = virXMLParseFile(xml)) ||
|
|
|
|
!(ctxt = xmlXPathNewContext(doc)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ctxt->node = xmlDocGetRootElement(doc);
|
|
|
|
cpu = virCPUDefParseXML(ctxt->node, ctxt, VIR_CPU_TYPE_AUTO);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
xmlXPathFreeContext(ctxt);
|
|
|
|
xmlFreeDoc(doc);
|
|
|
|
return cpu;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static virCPUDefPtr *
|
|
|
|
cpuTestLoadMultiXML(const char *arch,
|
|
|
|
const char *name,
|
|
|
|
unsigned int *count)
|
|
|
|
{
|
|
|
|
char xml[PATH_MAX];
|
|
|
|
xmlDocPtr doc = NULL;
|
|
|
|
xmlXPathContextPtr ctxt = NULL;
|
|
|
|
xmlNodePtr *nodes = NULL;
|
|
|
|
virCPUDefPtr *cpus = NULL;
|
|
|
|
int n;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
snprintf(xml, PATH_MAX,
|
|
|
|
"%s/cputestdata/%s-%s.xml",
|
|
|
|
abs_srcdir, arch, name);
|
|
|
|
|
|
|
|
if (!(doc = virXMLParseFile(xml)) ||
|
|
|
|
!(ctxt = xmlXPathNewContext(doc)))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
ctxt->node = xmlDocGetRootElement(doc);
|
|
|
|
|
|
|
|
n = virXPathNodeSet("/cpuTest/cpu", ctxt, &nodes);
|
|
|
|
if (n <= 0 || !(cpus = calloc(n, sizeof(virCPUDefPtr))))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
ctxt->node = nodes[i];
|
|
|
|
cpus[i] = virCPUDefParseXML(nodes[i], ctxt, VIR_CPU_TYPE_HOST);
|
|
|
|
if (!cpus[i])
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
*count = n;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
free(nodes);
|
|
|
|
xmlXPathFreeContext(ctxt);
|
|
|
|
xmlFreeDoc(doc);
|
|
|
|
return cpus;
|
|
|
|
|
|
|
|
error:
|
|
|
|
if (cpus) {
|
|
|
|
for (i = 0; i < n; i++)
|
|
|
|
virCPUDefFree(cpus[i]);
|
|
|
|
free(cpus);
|
|
|
|
cpus = NULL;
|
|
|
|
}
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
cpuTestCompareXML(const char *arch,
|
|
|
|
const virCPUDefPtr cpu,
|
|
|
|
const char *name)
|
|
|
|
{
|
|
|
|
char xml[PATH_MAX];
|
|
|
|
char expected[MAX_FILE];
|
|
|
|
char *expectedPtr = &(expected[0]);
|
|
|
|
char *actual = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
snprintf(xml, PATH_MAX,
|
|
|
|
"%s/cputestdata/%s-%s.xml",
|
|
|
|
abs_srcdir, arch, name);
|
|
|
|
|
|
|
|
if (virtTestLoadFile(xml, &expectedPtr, MAX_FILE) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!(actual = virCPUDefFormat(cpu, NULL, 0)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (STRNEQ(expected, actual)) {
|
|
|
|
virtTestDifference(stderr, expected, actual);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
free(actual);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
cpuTestCompResStr(virCPUCompareResult result)
|
|
|
|
{
|
|
|
|
switch (result) {
|
|
|
|
case VIR_CPU_COMPARE_ERROR: return "ERROR";
|
|
|
|
case VIR_CPU_COMPARE_INCOMPATIBLE: return "INCOMPATIBLE";
|
|
|
|
case VIR_CPU_COMPARE_IDENTICAL: return "IDENTICAL";
|
|
|
|
case VIR_CPU_COMPARE_SUPERSET: return "SUPERSET";
|
|
|
|
}
|
|
|
|
|
|
|
|
return "unknown";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
cpuTestBoolWithErrorStr(enum cpuTestBoolWithError result)
|
|
|
|
{
|
|
|
|
switch (result) {
|
|
|
|
case FAIL: return "FAIL";
|
|
|
|
case NO: return "NO";
|
|
|
|
case YES: return "YES";
|
|
|
|
}
|
|
|
|
|
|
|
|
return "unknown";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
cpuTestCompare(const void *arg)
|
|
|
|
{
|
|
|
|
const struct data *data = arg;
|
|
|
|
int ret = -1;
|
|
|
|
virCPUDefPtr host = NULL;
|
|
|
|
virCPUDefPtr cpu = NULL;
|
|
|
|
virCPUCompareResult result;
|
|
|
|
|
|
|
|
if (!(host = cpuTestLoadXML(data->arch, data->host)) ||
|
|
|
|
!(cpu = cpuTestLoadXML(data->arch, data->name)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
result = cpuCompare(host, cpu);
|
|
|
|
if (data->result == VIR_CPU_COMPARE_ERROR)
|
|
|
|
virResetLastError();
|
|
|
|
|
|
|
|
if (data->result != result) {
|
|
|
|
if (virTestGetVerbose()) {
|
|
|
|
fprintf(stderr, "\nExpected result %s, got %s\n",
|
|
|
|
cpuTestCompResStr(data->result),
|
|
|
|
cpuTestCompResStr(result));
|
|
|
|
/* Pad to line up with test name ... in virTestRun */
|
|
|
|
fprintf(stderr, "%74s", "... ");
|
|
|
|
}
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virCPUDefFree(host);
|
|
|
|
virCPUDefFree(cpu);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
cpuTestGuestData(const void *arg)
|
|
|
|
{
|
|
|
|
const struct data *data = arg;
|
|
|
|
int ret = -1;
|
|
|
|
virCPUDefPtr host = NULL;
|
|
|
|
virCPUDefPtr cpu = NULL;
|
|
|
|
virCPUDefPtr guest = NULL;
|
|
|
|
union cpuData *guestData = NULL;
|
|
|
|
virCPUCompareResult cmpResult;
|
|
|
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
|
|
|
char *result = NULL;
|
|
|
|
|
|
|
|
if (!(host = cpuTestLoadXML(data->arch, data->host)) ||
|
|
|
|
!(cpu = cpuTestLoadXML(data->arch, data->name)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
cmpResult = cpuGuestData(host, cpu, &guestData);
|
|
|
|
if (cmpResult == VIR_CPU_COMPARE_ERROR ||
|
|
|
|
cmpResult == VIR_CPU_COMPARE_INCOMPATIBLE)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (VIR_ALLOC(guest) < 0 || !(guest->arch = strdup(host->arch)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
guest->type = VIR_CPU_TYPE_GUEST;
|
|
|
|
guest->match = VIR_CPU_MATCH_EXACT;
|
|
|
|
if (cpuDecode(guest, guestData, data->models,
|
|
|
|
data->nmodels, data->preferred) < 0) {
|
|
|
|
if (data->result < 0) {
|
|
|
|
virResetLastError();
|
|
|
|
ret = 0;
|
|
|
|
}
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
virBufferVSprintf(&buf, "%s+%s", data->host, data->name);
|
|
|
|
if (data->nmodels)
|
|
|
|
virBufferVSprintf(&buf, ",%s", data->modelsName);
|
|
|
|
if (data->preferred)
|
|
|
|
virBufferVSprintf(&buf, ",%s", data->preferred);
|
|
|
|
virBufferAddLit(&buf, "-result");
|
|
|
|
|
|
|
|
if (virBufferError(&buf)) {
|
|
|
|
virBufferFreeAndReset(&buf);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
result = virBufferContentAndReset(&buf);
|
|
|
|
|
|
|
|
ret = cpuTestCompareXML(data->arch, guest, result);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(result);
|
|
|
|
if (host)
|
|
|
|
cpuDataFree(host->arch, guestData);
|
|
|
|
virCPUDefFree(host);
|
|
|
|
virCPUDefFree(cpu);
|
|
|
|
virCPUDefFree(guest);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
cpuTestBaseline(const void *arg)
|
|
|
|
{
|
|
|
|
const struct data *data = arg;
|
|
|
|
int ret = -1;
|
|
|
|
virCPUDefPtr *cpus = NULL;
|
|
|
|
virCPUDefPtr baseline = NULL;
|
|
|
|
unsigned int ncpus = 0;
|
|
|
|
char result[PATH_MAX];
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
if (!(cpus = cpuTestLoadMultiXML(data->arch, data->name, &ncpus)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
baseline = cpuBaseline(cpus, ncpus, NULL, 0);
|
|
|
|
if (data->result < 0) {
|
|
|
|
virResetLastError();
|
|
|
|
if (!baseline)
|
|
|
|
ret = 0;
|
|
|
|
else if (virTestGetVerbose()) {
|
|
|
|
fprintf(stderr, "\n%-70s... ",
|
|
|
|
"cpuBaseline was expected to fail but it succeeded");
|
|
|
|
}
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (!baseline)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
snprintf(result, PATH_MAX, "%s-result", data->name);
|
|
|
|
if (cpuTestCompareXML(data->arch, baseline, result) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
for (i = 0; i < ncpus; i++) {
|
|
|
|
virCPUCompareResult cmp;
|
|
|
|
|
|
|
|
cmp = cpuCompare(cpus[i], baseline);
|
|
|
|
if (cmp != VIR_CPU_COMPARE_SUPERSET &&
|
|
|
|
cmp != VIR_CPU_COMPARE_IDENTICAL) {
|
|
|
|
if (virTestGetVerbose()) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"\nbaseline CPU is incompatible with CPU %u\n", i);
|
|
|
|
fprintf(stderr, "%74s", "... ");
|
|
|
|
}
|
|
|
|
ret = -1;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (cpus) {
|
|
|
|
for (i = 0; i < ncpus; i++)
|
|
|
|
virCPUDefFree(cpus[i]);
|
|
|
|
free(cpus);
|
|
|
|
}
|
|
|
|
virCPUDefFree(baseline);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
cpuTestUpdate(const void *arg)
|
|
|
|
{
|
|
|
|
const struct data *data = arg;
|
|
|
|
int ret = -1;
|
|
|
|
virCPUDefPtr host = NULL;
|
|
|
|
virCPUDefPtr cpu = NULL;
|
|
|
|
char result[PATH_MAX];
|
|
|
|
|
|
|
|
if (!(host = cpuTestLoadXML(data->arch, data->host)) ||
|
|
|
|
!(cpu = cpuTestLoadXML(data->arch, data->name)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (cpuUpdate(cpu, host) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
snprintf(result, PATH_MAX, "%s+%s", data->host, data->name);
|
|
|
|
ret = cpuTestCompareXML(data->arch, cpu, result);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virCPUDefFree(host);
|
|
|
|
virCPUDefFree(cpu);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
cpuTestHasFeature(const void *arg)
|
|
|
|
{
|
|
|
|
const struct data *data = arg;
|
|
|
|
int ret = -1;
|
|
|
|
virCPUDefPtr host = NULL;
|
|
|
|
union cpuData *hostData = NULL;
|
|
|
|
int result;
|
|
|
|
|
|
|
|
if (!(host = cpuTestLoadXML(data->arch, data->host)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (cpuEncode(host->arch, host, NULL, &hostData,
|
|
|
|
NULL, NULL, NULL, NULL) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
result = cpuHasFeature(host->arch, hostData, data->name);
|
|
|
|
if (data->result == -1)
|
|
|
|
virResetLastError();
|
|
|
|
|
|
|
|
if (data->result != result) {
|
|
|
|
if (virTestGetVerbose()) {
|
|
|
|
fprintf(stderr, "\nExpected result %s, got %s\n",
|
|
|
|
cpuTestBoolWithErrorStr(data->result),
|
|
|
|
cpuTestBoolWithErrorStr(result));
|
|
|
|
/* Pad to line up with test name ... in virTestRun */
|
|
|
|
fprintf(stderr, "%74s", "... ");
|
|
|
|
}
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (host)
|
|
|
|
cpuDataFree(host->arch, hostData);
|
|
|
|
virCPUDefFree(host);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int (*cpuTest[])(const void *) = {
|
|
|
|
cpuTestCompare,
|
|
|
|
cpuTestGuestData,
|
|
|
|
cpuTestBaseline,
|
|
|
|
cpuTestUpdate,
|
|
|
|
cpuTestHasFeature
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
cpuTestRun(const char *name, const struct data *data)
|
|
|
|
{
|
|
|
|
char label[PATH_MAX];
|
|
|
|
|
|
|
|
snprintf(label, PATH_MAX, "CPU %s(%s): %s",
|
|
|
|
apis[data->api], data->arch, name);
|
|
|
|
|
|
|
|
free(virtTestLogContentAndReset());
|
|
|
|
|
|
|
|
if (virtTestRun(label, 1, cpuTest[data->api], data) < 0) {
|
|
|
|
if (virTestGetDebug()) {
|
|
|
|
char *log;
|
|
|
|
if ((log = virtTestLogContentAndReset()) &&
|
|
|
|
strlen(log) > 0)
|
|
|
|
fprintf(stderr, "\n%s\n", log);
|
|
|
|
free(log);
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static const char *model486[] = { "486" };
|
|
|
|
static const char *nomodel[] = { "nomodel" };
|
|
|
|
static const char *models[] = { "qemu64", "core2duo", "Nehalem" };
|
|
|
|
|
|
|
|
static int
|
2011-04-30 00:21:20 +08:00
|
|
|
mymain(void)
|
2010-10-07 22:35:17 +08:00
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
char map[PATH_MAX];
|
|
|
|
|
|
|
|
abs_top_srcdir = getenv("abs_top_srcdir");
|
|
|
|
if (!abs_top_srcdir)
|
|
|
|
abs_top_srcdir = "..";
|
|
|
|
|
|
|
|
snprintf(map, PATH_MAX, "%s/src/cpu/cpu_map.xml", abs_top_srcdir);
|
|
|
|
if (cpuMapOverride(map) < 0)
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
|
|
|
|
#define DO_TEST(arch, api, name, host, cpu, \
|
|
|
|
models, nmodels, preferred, result) \
|
|
|
|
do { \
|
|
|
|
struct data data = { \
|
|
|
|
arch, api, host, cpu, models, \
|
|
|
|
models == NULL ? NULL : #models, \
|
|
|
|
nmodels, preferred, result \
|
|
|
|
}; \
|
|
|
|
if (cpuTestRun(name, &data) < 0) \
|
|
|
|
ret = -1; \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define DO_TEST_COMPARE(arch, host, cpu, result) \
|
|
|
|
DO_TEST(arch, API_COMPARE, \
|
|
|
|
host "/" cpu " (" #result ")", \
|
|
|
|
host, cpu, NULL, 0, NULL, result)
|
|
|
|
|
|
|
|
#define DO_TEST_UPDATE(arch, host, cpu, result) \
|
|
|
|
do { \
|
|
|
|
DO_TEST(arch, API_UPDATE, \
|
|
|
|
cpu " on " host, \
|
|
|
|
host, cpu, NULL, 0, NULL, 0); \
|
|
|
|
DO_TEST_COMPARE(arch, host, host "+" cpu, result); \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define DO_TEST_BASELINE(arch, name, result) \
|
|
|
|
DO_TEST(arch, API_BASELINE, name, NULL, "baseline-" name, \
|
|
|
|
NULL, 0, NULL, result)
|
|
|
|
|
|
|
|
#define DO_TEST_HASFEATURE(arch, host, feature, result) \
|
|
|
|
DO_TEST(arch, API_HAS_FEATURE, \
|
|
|
|
host "/" feature " (" #result ")", \
|
|
|
|
host, feature, NULL, 0, NULL, result)
|
|
|
|
|
|
|
|
#define DO_TEST_GUESTDATA(arch, host, cpu, models, preferred, result) \
|
|
|
|
DO_TEST(arch, API_GUEST_DATA, \
|
|
|
|
host "/" cpu " (" #models ", pref=" #preferred ")", \
|
|
|
|
host, cpu, models, \
|
|
|
|
models == NULL ? 0 : sizeof(models) / sizeof(char *), \
|
|
|
|
preferred, result)
|
|
|
|
|
|
|
|
/* host to host comparison */
|
|
|
|
DO_TEST_COMPARE("x86", "host", "host", IDENTICAL);
|
|
|
|
DO_TEST_COMPARE("x86", "host", "host-better", INCOMPATIBLE);
|
|
|
|
DO_TEST_COMPARE("x86", "host", "host-worse", SUPERSET);
|
|
|
|
DO_TEST_COMPARE("x86", "host", "host-amd-fake", INCOMPATIBLE);
|
|
|
|
DO_TEST_COMPARE("x86", "host", "host-incomp-arch", INCOMPATIBLE);
|
|
|
|
DO_TEST_COMPARE("x86", "host", "host-no-vendor", IDENTICAL);
|
|
|
|
DO_TEST_COMPARE("x86", "host-no-vendor", "host", INCOMPATIBLE);
|
|
|
|
|
|
|
|
/* guest to host comparison */
|
|
|
|
DO_TEST_COMPARE("x86", "host", "bogus-model", ERROR);
|
|
|
|
DO_TEST_COMPARE("x86", "host", "bogus-feature", ERROR);
|
|
|
|
DO_TEST_COMPARE("x86", "host", "min", SUPERSET);
|
|
|
|
DO_TEST_COMPARE("x86", "host", "pentium3", SUPERSET);
|
|
|
|
DO_TEST_COMPARE("x86", "host", "exact", SUPERSET);
|
|
|
|
DO_TEST_COMPARE("x86", "host", "exact-forbid", INCOMPATIBLE);
|
|
|
|
DO_TEST_COMPARE("x86", "host", "exact-forbid-extra", SUPERSET);
|
|
|
|
DO_TEST_COMPARE("x86", "host", "exact-disable", SUPERSET);
|
|
|
|
DO_TEST_COMPARE("x86", "host", "exact-disable2", SUPERSET);
|
|
|
|
DO_TEST_COMPARE("x86", "host", "exact-disable-extra", SUPERSET);
|
|
|
|
DO_TEST_COMPARE("x86", "host", "exact-require", SUPERSET);
|
|
|
|
DO_TEST_COMPARE("x86", "host", "exact-require-extra", INCOMPATIBLE);
|
|
|
|
DO_TEST_COMPARE("x86", "host", "exact-force", SUPERSET);
|
|
|
|
DO_TEST_COMPARE("x86", "host", "strict", INCOMPATIBLE);
|
|
|
|
DO_TEST_COMPARE("x86", "host", "strict-full", IDENTICAL);
|
|
|
|
DO_TEST_COMPARE("x86", "host", "strict-disable", IDENTICAL);
|
|
|
|
DO_TEST_COMPARE("x86", "host", "strict-force-extra", IDENTICAL);
|
|
|
|
DO_TEST_COMPARE("x86", "host", "guest", SUPERSET);
|
|
|
|
DO_TEST_COMPARE("x86", "host", "pentium3-amd", INCOMPATIBLE);
|
|
|
|
DO_TEST_COMPARE("x86", "host-amd", "pentium3-amd", SUPERSET);
|
|
|
|
DO_TEST_COMPARE("x86", "host-worse", "nehalem-force", IDENTICAL);
|
|
|
|
|
|
|
|
/* guest updates for migration
|
|
|
|
* automatically compares host CPU with the result */
|
|
|
|
DO_TEST_UPDATE("x86", "host", "min", IDENTICAL);
|
|
|
|
DO_TEST_UPDATE("x86", "host", "pentium3", IDENTICAL);
|
|
|
|
DO_TEST_UPDATE("x86", "host", "guest", SUPERSET);
|
|
|
|
|
|
|
|
/* computing baseline CPUs */
|
|
|
|
DO_TEST_BASELINE("x86", "incompatible-vendors", -1);
|
|
|
|
DO_TEST_BASELINE("x86", "no-vendor", 0);
|
|
|
|
DO_TEST_BASELINE("x86", "some-vendors", 0);
|
|
|
|
DO_TEST_BASELINE("x86", "1", 0);
|
|
|
|
DO_TEST_BASELINE("x86", "2", 0);
|
|
|
|
|
|
|
|
/* CPU features */
|
|
|
|
DO_TEST_HASFEATURE("x86", "host", "vmx", YES);
|
|
|
|
DO_TEST_HASFEATURE("x86", "host", "lm", YES);
|
|
|
|
DO_TEST_HASFEATURE("x86", "host", "sse4.1", YES);
|
|
|
|
DO_TEST_HASFEATURE("x86", "host", "3dnowext", NO);
|
|
|
|
DO_TEST_HASFEATURE("x86", "host", "skinit", NO);
|
|
|
|
DO_TEST_HASFEATURE("x86", "host", "foo", FAIL);
|
|
|
|
|
|
|
|
/* computing guest data and decoding the data into a guest CPU XML */
|
|
|
|
DO_TEST_GUESTDATA("x86", "host", "guest", NULL, NULL, 0);
|
|
|
|
DO_TEST_GUESTDATA("x86", "host-better", "pentium3", NULL, NULL, 0);
|
|
|
|
DO_TEST_GUESTDATA("x86", "host-better", "pentium3", NULL, "pentium3", 0);
|
|
|
|
DO_TEST_GUESTDATA("x86", "host-better", "pentium3", NULL, "core2duo", 0);
|
|
|
|
DO_TEST_GUESTDATA("x86", "host-worse", "guest", NULL, NULL, 0);
|
|
|
|
DO_TEST_GUESTDATA("x86", "host", "strict-force-extra", NULL, NULL, 0);
|
|
|
|
DO_TEST_GUESTDATA("x86", "host", "nehalem-force", NULL, NULL, 0);
|
|
|
|
DO_TEST_GUESTDATA("x86", "host", "guest", model486, NULL, 0);
|
|
|
|
DO_TEST_GUESTDATA("x86", "host", "guest", models, NULL, 0);
|
|
|
|
DO_TEST_GUESTDATA("x86", "host", "guest", models, "Penryn", 0);
|
|
|
|
DO_TEST_GUESTDATA("x86", "host", "guest", models, "qemu64", 0);
|
|
|
|
DO_TEST_GUESTDATA("x86", "host", "guest", nomodel, NULL, -1);
|
|
|
|
|
|
|
|
return (ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
VIRT_TEST_MAIN(mymain)
|