cputest.c 22.4 KB
Newer Older
1 2 3
/*
 * cputest.c: Test the libvirtd internal CPU APIs
 *
4
 * Copyright (C) 2010-2014 Red Hat, Inc.
5 6 7 8 9 10 11 12 13 14 15 16
 *
 * 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
17
 * License along with this library.  If not, see
O
Osier Yang 已提交
18
 * <http://www.gnu.org/licenses/>.
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
 *
 * 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"
34
#include "virxml.h"
35
#include "viralloc.h"
36
#include "virbuffer.h"
37 38 39 40
#include "testutils.h"
#include "cpu_conf.h"
#include "cpu/cpu.h"
#include "cpu/cpu_map.h"
41
#include "virstring.h"
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75

#define VIR_FROM_THIS VIR_FROM_CPU

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;
76
    unsigned int flags;
77 78 79 80 81 82 83
    int result;
};


static virCPUDefPtr
cpuTestLoadXML(const char *arch, const char *name)
{
84
    char *xml = NULL;
85 86 87 88
    xmlDocPtr doc = NULL;
    xmlXPathContextPtr ctxt = NULL;
    virCPUDefPtr cpu = NULL;

89 90
    if (virAsprintf(&xml, "%s/cputestdata/%s-%s.xml", abs_srcdir, arch, name) < 0)
        goto cleanup;
91

92
    if (!(doc = virXMLParseFileCtxt(xml, &ctxt)))
93 94 95 96
        goto cleanup;

    cpu = virCPUDefParseXML(ctxt->node, ctxt, VIR_CPU_TYPE_AUTO);

97
 cleanup:
98 99
    xmlXPathFreeContext(ctxt);
    xmlFreeDoc(doc);
100
    VIR_FREE(xml);
101 102 103 104 105 106 107 108 109
    return cpu;
}


static virCPUDefPtr *
cpuTestLoadMultiXML(const char *arch,
                    const char *name,
                    unsigned int *count)
{
110
    char *xml = NULL;
111 112 113 114 115
    xmlDocPtr doc = NULL;
    xmlXPathContextPtr ctxt = NULL;
    xmlNodePtr *nodes = NULL;
    virCPUDefPtr *cpus = NULL;
    int n;
116
    size_t i;
117

118 119
    if (virAsprintf(&xml, "%s/cputestdata/%s-%s.xml", abs_srcdir, arch, name) < 0)
        goto cleanup;
120

121
    if (!(doc = virXMLParseFileCtxt(xml, &ctxt)))
J
Jiri Denemark 已提交
122
        goto cleanup;
123 124

    n = virXPathNodeSet("/cpuTest/cpu", ctxt, &nodes);
125 126
    if (n <= 0 || (VIR_ALLOC_N(cpus, n) < 0)) {
        fprintf(stderr, "\nNo /cpuTest/cpu elements found in %s\n", xml);
J
Jiri Denemark 已提交
127
        goto cleanup;
128
    }
129 130 131 132 133

    for (i = 0; i < n; i++) {
        ctxt->node = nodes[i];
        cpus[i] = virCPUDefParseXML(nodes[i], ctxt, VIR_CPU_TYPE_HOST);
        if (!cpus[i])
J
Jiri Denemark 已提交
134
            goto cleanup_cpus;
135 136 137 138
    }

    *count = n;

139
 cleanup:
140 141
    VIR_FREE(xml);
    VIR_FREE(nodes);
142 143 144 145
    xmlXPathFreeContext(ctxt);
    xmlFreeDoc(doc);
    return cpus;

146
 cleanup_cpus:
J
Jiri Denemark 已提交
147 148 149
    for (i = 0; i < n; i++)
        virCPUDefFree(cpus[i]);
    VIR_FREE(cpus);
150 151 152 153 154 155
    goto cleanup;
}


static int
cpuTestCompareXML(const char *arch,
E
Eric Blake 已提交
156
                  virCPUDef *cpu,
157
                  const char *name,
158
                  bool updateCPU)
159
{
160
    char *xml = NULL;
161 162 163
    char *actual = NULL;
    int ret = -1;

164 165 166
    if (virAsprintf(&xml, "%s/cputestdata/%s-%s.xml",
                    abs_srcdir, arch, name) < 0)
        goto cleanup;
167

168
    if (!(actual = virCPUDefFormat(cpu, NULL, updateCPU)))
169 170
        goto cleanup;

C
Cole Robinson 已提交
171
    if (virtTestCompareToFile(actual, xml) < 0)
172 173 174 175
        goto cleanup;

    ret = 0;

176
 cleanup:
177 178
    VIR_FREE(xml);
    VIR_FREE(actual);
179 180 181 182 183 184 185 186 187 188 189 190
    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";
191
    case VIR_CPU_COMPARE_LAST:          break;
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
    }

    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;

224
    result = cpuCompare(host, cpu, false);
225 226 227 228
    if (data->result == VIR_CPU_COMPARE_ERROR)
        virResetLastError();

    if (data->result != result) {
229
        VIR_TEST_VERBOSE("\nExpected result %s, got %s\n",
230 231
                    cpuTestCompResStr(data->result),
                    cpuTestCompResStr(result));
232 233
        /* Pad to line up with test name ... in virTestRun */
        VIR_TEST_VERBOSE("%74s", "... ");
234 235 236 237 238
        goto cleanup;
    }

    ret = 0;

239
 cleanup:
240 241 242 243 244 245 246 247 248 249
    virCPUDefFree(host);
    virCPUDefFree(cpu);
    return ret;
}


static int
cpuTestGuestData(const void *arg)
{
    const struct data *data = arg;
250
    int ret = -2;
251 252 253
    virCPUDefPtr host = NULL;
    virCPUDefPtr cpu = NULL;
    virCPUDefPtr guest = NULL;
254
    virCPUDataPtr guestData = NULL;
255 256 257 258 259 260 261 262
    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;

263
    cmpResult = cpuGuestData(host, cpu, &guestData, NULL);
264
    if (cmpResult == VIR_CPU_COMPARE_ERROR ||
265 266
        cmpResult == VIR_CPU_COMPARE_INCOMPATIBLE) {
        ret = -1;
267
        goto cleanup;
268
    }
269

270
    if (VIR_ALLOC(guest) < 0)
271 272
        goto cleanup;

273
    guest->arch = host->arch;
274 275
    guest->type = VIR_CPU_TYPE_GUEST;
    guest->match = VIR_CPU_MATCH_EXACT;
276
    guest->fallback = cpu->fallback;
277 278
    if (cpuDecode(guest, guestData, data->models,
                  data->nmodels, data->preferred) < 0) {
279
        ret = -1;
280 281 282
        goto cleanup;
    }

283
    virBufferAsprintf(&buf, "%s+%s", data->host, data->name);
284
    if (data->nmodels)
285
        virBufferAsprintf(&buf, ",%s", data->modelsName);
286
    if (data->preferred)
287
        virBufferAsprintf(&buf, ",%s", data->preferred);
288 289 290 291 292 293 294 295
    virBufferAddLit(&buf, "-result");

    if (virBufferError(&buf)) {
        virBufferFreeAndReset(&buf);
        goto cleanup;
    }
    result = virBufferContentAndReset(&buf);

296 297 298 299
    if (cpuTestCompareXML(data->arch, guest, result, false) < 0)
        goto cleanup;

    ret = 0;
300

301
 cleanup:
302
    VIR_FREE(result);
J
Jiri Denemark 已提交
303
    cpuDataFree(guestData);
304 305 306
    virCPUDefFree(host);
    virCPUDefFree(cpu);
    virCPUDefFree(guest);
307 308 309 310 311 312 313 314 315 316 317 318 319 320

    if (ret == data->result) {
        /* We got the result we expected, whether it was
         * a success or a failure */
        virResetLastError();
        ret = 0;
    } else {
        VIR_TEST_VERBOSE("\nExpected result %d, got %d\n",
                         data->result, ret);
        /* Pad to line up with test name ... in virTestRun */
        VIR_TEST_VERBOSE("%74s", "... ");
        ret = -1;
    }

321 322 323 324 325 326 327 328 329 330 331 332
    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;
333
    char *result = NULL;
334
    const char *suffix;
335
    size_t i;
336 337 338 339

    if (!(cpus = cpuTestLoadMultiXML(data->arch, data->name, &ncpus)))
        goto cleanup;

340
    baseline = cpuBaseline(cpus, ncpus, NULL, 0, data->flags);
341 342
    if (data->result < 0) {
        virResetLastError();
343
        if (!baseline) {
344
            ret = 0;
345 346
        } else {
            VIR_TEST_VERBOSE("\n%-70s... ",
347 348 349 350 351 352 353
                    "cpuBaseline was expected to fail but it succeeded");
        }
        goto cleanup;
    }
    if (!baseline)
        goto cleanup;

354 355
    if (data->flags & VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES)
        suffix = "expanded";
356 357
    else if (data->flags & VIR_CONNECT_BASELINE_CPU_MIGRATABLE)
        suffix = "migratable";
358 359 360
    else
        suffix = "result";
    if (virAsprintf(&result, "%s-%s", data->name, suffix) < 0)
361 362
        goto cleanup;

363
    if (cpuTestCompareXML(data->arch, baseline, result, false) < 0)
364 365 366 367 368
        goto cleanup;

    for (i = 0; i < ncpus; i++) {
        virCPUCompareResult cmp;

369
        cmp = cpuCompare(cpus[i], baseline, false);
370 371
        if (cmp != VIR_CPU_COMPARE_SUPERSET &&
            cmp != VIR_CPU_COMPARE_IDENTICAL) {
372 373 374
            VIR_TEST_VERBOSE("\nbaseline CPU is incompatible with CPU %zu\n",
                             i);
            VIR_TEST_VERBOSE("%74s", "... ");
375 376 377 378 379 380 381
            ret = -1;
            goto cleanup;
        }
    }

    ret = 0;

382
 cleanup:
383 384 385
    if (cpus) {
        for (i = 0; i < ncpus; i++)
            virCPUDefFree(cpus[i]);
386
        VIR_FREE(cpus);
387 388
    }
    virCPUDefFree(baseline);
389
    VIR_FREE(result);
390 391 392 393 394 395 396 397 398 399 400
    return ret;
}


static int
cpuTestUpdate(const void *arg)
{
    const struct data *data = arg;
    int ret = -1;
    virCPUDefPtr host = NULL;
    virCPUDefPtr cpu = NULL;
401
    char *result = NULL;
402 403 404 405 406 407 408 409

    if (!(host = cpuTestLoadXML(data->arch, data->host)) ||
        !(cpu = cpuTestLoadXML(data->arch, data->name)))
        goto cleanup;

    if (cpuUpdate(cpu, host) < 0)
        goto cleanup;

410 411 412
    if (virAsprintf(&result, "%s+%s", data->host, data->name) < 0)
        goto cleanup;

413
    ret = cpuTestCompareXML(data->arch, cpu, result, true);
414

415
 cleanup:
416 417
    virCPUDefFree(host);
    virCPUDefFree(cpu);
418
    VIR_FREE(result);
419 420 421 422 423 424 425 426 427 428
    return ret;
}


static int
cpuTestHasFeature(const void *arg)
{
    const struct data *data = arg;
    int ret = -1;
    virCPUDefPtr host = NULL;
429
    virCPUDataPtr hostData = NULL;
430 431 432 433 434 435 436 437 438
    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;

J
Jiri Denemark 已提交
439
    result = cpuHasFeature(hostData, data->name);
440 441 442 443
    if (data->result == -1)
        virResetLastError();

    if (data->result != result) {
444 445 446 447 448
        VIR_TEST_VERBOSE("\nExpected result %s, got %s\n",
            cpuTestBoolWithErrorStr(data->result),
            cpuTestBoolWithErrorStr(result));
        /* Pad to line up with test name ... in virTestRun */
        VIR_TEST_VERBOSE("%74s", "... ");
449 450 451 452 453
        goto cleanup;
    }

    ret = 0;

454
 cleanup:
J
Jiri Denemark 已提交
455
    cpuDataFree(hostData);
456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472
    virCPUDefFree(host);
    return ret;
}


static int (*cpuTest[])(const void *) = {
    cpuTestCompare,
    cpuTestGuestData,
    cpuTestBaseline,
    cpuTestUpdate,
    cpuTestHasFeature
};


static int
cpuTestRun(const char *name, const struct data *data)
{
473
    char *label = NULL;
474
    char *tmp;
475

476 477
    if (virAsprintf(&label, "CPU %s(%s): %s", apis[data->api], data->arch, name) < 0)
        return -1;
478

479 480
    tmp = virtTestLogContentAndReset();
    VIR_FREE(tmp);
481

482
    if (virtTestRun(label, cpuTest[data->api], data) < 0) {
483 484 485 486
        if (virTestGetDebug()) {
            char *log;
            if ((log = virtTestLogContentAndReset()) &&
                 strlen(log) > 0)
487
                VIR_TEST_DEBUG("\n%s\n", log);
488
            VIR_FREE(log);
489
        }
490

491
        VIR_FREE(label);
492 493 494
        return -1;
    }

495
    VIR_FREE(label);
496 497 498 499 500 501 502
    return 0;
}


static const char *model486[]   = { "486" };
static const char *nomodel[]    = { "nomodel" };
static const char *models[]     = { "qemu64", "core2duo", "Nehalem" };
503
static const char *haswell[]    = { "SandyBridge", "Haswell" };
504
static const char *ppc_models[] = { "POWER6", "POWER7", "POWER8" };
505 506

static int
E
Eric Blake 已提交
507
mymain(void)
508 509 510 511
{
    int ret = 0;

#define DO_TEST(arch, api, name, host, cpu,                             \
512
                models, nmodels, preferred, flags, result)              \
513
    do {                                                                \
514
        static struct data data = {                                     \
515 516
            arch, api, host, cpu, models,                               \
            models == NULL ? NULL : #models,                            \
517
            nmodels, preferred, flags, result                           \
518 519 520 521 522 523 524 525
        };                                                              \
        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 ")",                              \
526
            host, cpu, NULL, 0, NULL, 0, result)
527 528 529 530 531

#define DO_TEST_UPDATE(arch, host, cpu, result)                         \
    do {                                                                \
        DO_TEST(arch, API_UPDATE,                                       \
                cpu " on " host,                                        \
532
                host, cpu, NULL, 0, NULL, 0, 0);                        \
533 534 535
        DO_TEST_COMPARE(arch, host, host "+" cpu, result);              \
    } while (0)

536
#define DO_TEST_BASELINE(arch, name, flags, result)                     \
537 538 539 540 541
    do {                                                                \
        const char *suffix = "";                                        \
        char *label;                                                    \
        if ((flags) & VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES)         \
            suffix = " (expanded)";                                     \
542 543
        if ((flags) & VIR_CONNECT_BASELINE_CPU_MIGRATABLE)              \
            suffix = " (migratable)";                                   \
544 545 546 547 548 549 550 551
        if (virAsprintf(&label, "%s%s", name, suffix) < 0) {            \
            ret = -1;                                                   \
        } else {                                                        \
            DO_TEST(arch, API_BASELINE, label, NULL, "baseline-" name,  \
                    NULL, 0, NULL, flags, result);                      \
        }                                                               \
        VIR_FREE(label);                                                \
    } while (0)
552 553 554 555

#define DO_TEST_HASFEATURE(arch, host, feature, result)                 \
    DO_TEST(arch, API_HAS_FEATURE,                                      \
            host "/" feature " (" #result ")",                          \
556
            host, feature, NULL, 0, NULL, 0, result)
557 558 559 560 561 562

#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 *),       \
563
            preferred, 0, result)
564 565

    /* host to host comparison */
566 567 568 569 570 571 572
    DO_TEST_COMPARE("x86", "host", "host", VIR_CPU_COMPARE_IDENTICAL);
    DO_TEST_COMPARE("x86", "host", "host-better", VIR_CPU_COMPARE_INCOMPATIBLE);
    DO_TEST_COMPARE("x86", "host", "host-worse", VIR_CPU_COMPARE_SUPERSET);
    DO_TEST_COMPARE("x86", "host", "host-amd-fake", VIR_CPU_COMPARE_INCOMPATIBLE);
    DO_TEST_COMPARE("x86", "host", "host-incomp-arch", VIR_CPU_COMPARE_INCOMPATIBLE);
    DO_TEST_COMPARE("x86", "host", "host-no-vendor", VIR_CPU_COMPARE_IDENTICAL);
    DO_TEST_COMPARE("x86", "host-no-vendor", "host", VIR_CPU_COMPARE_INCOMPATIBLE);
573

574 575 576 577 578 579 580
    DO_TEST_COMPARE("ppc64", "host", "host", VIR_CPU_COMPARE_IDENTICAL);
    DO_TEST_COMPARE("ppc64", "host", "host-better", VIR_CPU_COMPARE_INCOMPATIBLE);
    DO_TEST_COMPARE("ppc64", "host", "host-worse", VIR_CPU_COMPARE_INCOMPATIBLE);
    DO_TEST_COMPARE("ppc64", "host", "host-incomp-arch", VIR_CPU_COMPARE_INCOMPATIBLE);
    DO_TEST_COMPARE("ppc64", "host", "host-no-vendor", VIR_CPU_COMPARE_IDENTICAL);
    DO_TEST_COMPARE("ppc64", "host-no-vendor", "host", VIR_CPU_COMPARE_INCOMPATIBLE);

581
    /* guest to host comparison */
582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602
    DO_TEST_COMPARE("x86", "host", "bogus-model", VIR_CPU_COMPARE_ERROR);
    DO_TEST_COMPARE("x86", "host", "bogus-feature", VIR_CPU_COMPARE_ERROR);
    DO_TEST_COMPARE("x86", "host", "min", VIR_CPU_COMPARE_SUPERSET);
    DO_TEST_COMPARE("x86", "host", "pentium3", VIR_CPU_COMPARE_SUPERSET);
    DO_TEST_COMPARE("x86", "host", "exact", VIR_CPU_COMPARE_SUPERSET);
    DO_TEST_COMPARE("x86", "host", "exact-forbid", VIR_CPU_COMPARE_INCOMPATIBLE);
    DO_TEST_COMPARE("x86", "host", "exact-forbid-extra", VIR_CPU_COMPARE_SUPERSET);
    DO_TEST_COMPARE("x86", "host", "exact-disable", VIR_CPU_COMPARE_SUPERSET);
    DO_TEST_COMPARE("x86", "host", "exact-disable2", VIR_CPU_COMPARE_SUPERSET);
    DO_TEST_COMPARE("x86", "host", "exact-disable-extra", VIR_CPU_COMPARE_SUPERSET);
    DO_TEST_COMPARE("x86", "host", "exact-require", VIR_CPU_COMPARE_SUPERSET);
    DO_TEST_COMPARE("x86", "host", "exact-require-extra", VIR_CPU_COMPARE_INCOMPATIBLE);
    DO_TEST_COMPARE("x86", "host", "exact-force", VIR_CPU_COMPARE_SUPERSET);
    DO_TEST_COMPARE("x86", "host", "strict", VIR_CPU_COMPARE_INCOMPATIBLE);
    DO_TEST_COMPARE("x86", "host", "strict-full", VIR_CPU_COMPARE_IDENTICAL);
    DO_TEST_COMPARE("x86", "host", "strict-disable", VIR_CPU_COMPARE_IDENTICAL);
    DO_TEST_COMPARE("x86", "host", "strict-force-extra", VIR_CPU_COMPARE_IDENTICAL);
    DO_TEST_COMPARE("x86", "host", "guest", VIR_CPU_COMPARE_SUPERSET);
    DO_TEST_COMPARE("x86", "host", "pentium3-amd", VIR_CPU_COMPARE_INCOMPATIBLE);
    DO_TEST_COMPARE("x86", "host-amd", "pentium3-amd", VIR_CPU_COMPARE_SUPERSET);
    DO_TEST_COMPARE("x86", "host-worse", "nehalem-force", VIR_CPU_COMPARE_IDENTICAL);
603
    DO_TEST_COMPARE("x86", "host-SandyBridge", "exact-force-Haswell", VIR_CPU_COMPARE_IDENTICAL);
604

605 606
    DO_TEST_COMPARE("ppc64", "host", "guest-strict", VIR_CPU_COMPARE_IDENTICAL);
    DO_TEST_COMPARE("ppc64", "host", "guest-exact", VIR_CPU_COMPARE_INCOMPATIBLE);
607 608 609
    DO_TEST_COMPARE("ppc64", "host", "guest-legacy", VIR_CPU_COMPARE_IDENTICAL);
    DO_TEST_COMPARE("ppc64", "host", "guest-legacy-incompatible", VIR_CPU_COMPARE_INCOMPATIBLE);
    DO_TEST_COMPARE("ppc64", "host", "guest-legacy-invalid", VIR_CPU_COMPARE_ERROR);
610

611 612
    /* guest updates for migration
     * automatically compares host CPU with the result */
613 614 615 616 617 618
    DO_TEST_UPDATE("x86", "host", "min", VIR_CPU_COMPARE_IDENTICAL);
    DO_TEST_UPDATE("x86", "host", "pentium3", VIR_CPU_COMPARE_IDENTICAL);
    DO_TEST_UPDATE("x86", "host", "guest", VIR_CPU_COMPARE_SUPERSET);
    DO_TEST_UPDATE("x86", "host", "host-model", VIR_CPU_COMPARE_IDENTICAL);
    DO_TEST_UPDATE("x86", "host", "host-model-nofallback", VIR_CPU_COMPARE_IDENTICAL);
    DO_TEST_UPDATE("x86", "host", "host-passthrough", VIR_CPU_COMPARE_IDENTICAL);
619
    DO_TEST_UPDATE("x86", "host-invtsc", "host-model", VIR_CPU_COMPARE_SUPERSET);
620 621

    /* computing baseline CPUs */
622 623 624 625 626
    DO_TEST_BASELINE("x86", "incompatible-vendors", 0, -1);
    DO_TEST_BASELINE("x86", "no-vendor", 0, 0);
    DO_TEST_BASELINE("x86", "some-vendors", 0, 0);
    DO_TEST_BASELINE("x86", "1", 0, 0);
    DO_TEST_BASELINE("x86", "2", 0, 0);
627
    DO_TEST_BASELINE("x86", "3", 0, 0);
628
    DO_TEST_BASELINE("x86", "3", VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES, 0);
629 630 631 632
    DO_TEST_BASELINE("x86", "4", 0, 0);
    DO_TEST_BASELINE("x86", "4", VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES, 0);
    DO_TEST_BASELINE("x86", "5", 0, 0);
    DO_TEST_BASELINE("x86", "5", VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES, 0);
633 634
    DO_TEST_BASELINE("x86", "6", 0, 0);
    DO_TEST_BASELINE("x86", "6", VIR_CONNECT_BASELINE_CPU_MIGRATABLE, 0);
635 636
    DO_TEST_BASELINE("x86", "7", 0, 0);
    DO_TEST_BASELINE("x86", "8", 0, 0);
637

638 639
    DO_TEST_BASELINE("ppc64", "incompatible-vendors", 0, -1);
    DO_TEST_BASELINE("ppc64", "no-vendor", 0, 0);
640 641 642
    DO_TEST_BASELINE("ppc64", "incompatible-models", 0, -1);
    DO_TEST_BASELINE("ppc64", "same-model", 0, 0);
    DO_TEST_BASELINE("ppc64", "legacy", 0, -1);
643

644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664
    /* 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);
665
    DO_TEST_GUESTDATA("x86", "host", "guest-nofallback", models, "Penryn", -1);
666 667 668
    DO_TEST_GUESTDATA("x86", "host", "host+host-model", models, "Penryn", 0);
    DO_TEST_GUESTDATA("x86", "host", "host+host-model-nofallback",
                      models, "Penryn", -1);
669 670 671 672 673 674 675 676
    DO_TEST_GUESTDATA("x86", "host-Haswell-noTSX", "Haswell",
                      haswell, "Haswell", 0);
    DO_TEST_GUESTDATA("x86", "host-Haswell-noTSX", "Haswell-noTSX",
                      haswell, "Haswell-noTSX", 0);
    DO_TEST_GUESTDATA("x86", "host-Haswell-noTSX", "Haswell-noTSX-nofallback",
                      haswell, "Haswell-noTSX", -1);
    DO_TEST_GUESTDATA("x86", "host-Haswell-noTSX", "Haswell-noTSX",
                      NULL, "Haswell-noTSX", 0);
677

678
    DO_TEST_GUESTDATA("ppc64", "host", "guest", ppc_models, NULL, 0);
679
    DO_TEST_GUESTDATA("ppc64", "host", "guest-nofallback", ppc_models, "POWER8", -1);
680 681 682
    DO_TEST_GUESTDATA("ppc64", "host", "guest-legacy", ppc_models, NULL, 0);
    DO_TEST_GUESTDATA("ppc64", "host", "guest-legacy-incompatible", ppc_models, NULL, -1);
    DO_TEST_GUESTDATA("ppc64", "host", "guest-legacy-invalid", ppc_models, NULL, -1);
683

684
    return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
685 686 687
}

VIRT_TEST_MAIN(mymain)