testutils.c 31.8 KB
Newer Older
K
Karel Zak 已提交
1
/*
2
 * testutils.c: basic test utils
K
Karel Zak 已提交
3
 *
4
 * Copyright (C) 2005-2015 Red Hat, Inc.
K
Karel Zak 已提交
5
 *
O
Osier Yang 已提交
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/>.
K
Karel Zak 已提交
19 20
 */

21
#include <config.h>
22

23
#include <stdarg.h>
K
Karel Zak 已提交
24
#include <sys/time.h>
25 26 27
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
28
#include <fcntl.h>
K
Karel Zak 已提交
29
#include "testutils.h"
30
#include "internal.h"
31
#include "viralloc.h"
32
#include "virutil.h"
33
#include "virthread.h"
34
#include "virerror.h"
35
#include "virbuffer.h"
36
#include "virlog.h"
37
#include "vircommand.h"
38
#include "virrandom.h"
39
#include "virprocess.h"
40
#include "virstring.h"
41

42 43
#define VIR_FROM_THIS VIR_FROM_NONE

44 45
VIR_LOG_INIT("tests.testutils");

46
#include "virbitmap.h"
E
Eric Blake 已提交
47
#include "virfile.h"
48

49
static unsigned int testDebug = -1;
50
static unsigned int testVerbose = -1;
51
static unsigned int testExpensive = -1;
52
static unsigned int testRegenerate = -1;
53

54

55
static size_t testCounter;
56
static virBitmapPtr testBitmap;
57
static virBitmapPtr failedTests;
58

59 60 61 62 63 64 65 66 67
virArch virTestHostArch = VIR_ARCH_X86_64;

virArch
virArchFromHost(void)
{
    return virTestHostArch;
}


68
static int virTestUseTerminalColors(void)
69
{
70
    return isatty(STDOUT_FILENO);
71 72
}

73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
static unsigned int
virTestGetFlag(const char *name)
{
    char *flagStr;
    unsigned int flag;

    if ((flagStr = getenv(name)) == NULL)
        return 0;

    if (virStrToLong_ui(flagStr, NULL, 10, &flag) < 0)
        return 0;

    return flag;
}

88

89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
/**
 * virTestPropagateLibvirtError:
 *
 * In cases when a libvirt utility function which reports libvirt errors is
 * used in the test suite outside of the virTestRun call and the failure of such
 * a function would cause an test failure the error message reported by that
 * function will not be propagated to the user as the error callback is not
 * invoked.
 *
 * In cases when the error message may be beneficial in debugging this helper
 * provides means to dispatch the errors including invocation of the error
 * callback.
 */
void
virTestPropagateLibvirtError(void)
{
    if (virGetLastErrorCode() == VIR_ERR_OK)
        return;

    if (virTestGetVerbose() || virTestGetDebug())
        virDispatchError(NULL);
}


113
/*
114
 * Runs test
115 116
 *
 * returns: -1 = error, 0 = success
K
Karel Zak 已提交
117 118
 */
int
119 120
virTestRun(const char *title,
           int (*body)(const void *data), const void *data)
K
Karel Zak 已提交
121
{
122
    int ret = 0;
123

124 125 126
    /* Some test are fragile about environ settings.  If that's
     * the case, don't poison it. */
    if (getenv("VIR_TEST_MOCK_PROGNAME"))
127
        g_setenv("VIR_TEST_MOCK_TESTNAME", title, TRUE);
128

129 130 131
    if (testCounter == 0 && !virTestGetVerbose())
        fprintf(stderr, "      ");

132
    testCounter++;
133

134 135

    /* Skip tests if out of range */
136
    if (testBitmap && !virBitmapIsBitSet(testBitmap, testCounter))
137 138
        return 0;

D
Daniel P. Berrange 已提交
139 140
    if (virTestGetVerbose())
        fprintf(stderr, "%2zu) %-65s ... ", testCounter, title);
141

142 143
    virResetLastError();
    ret = body(data);
144
    virTestPropagateLibvirtError();
145

D
Daniel P. Berrange 已提交
146
    if (virTestGetVerbose()) {
147
        if (ret == 0)
148
            if (virTestUseTerminalColors())
149 150 151
                fprintf(stderr, "\e[32mOK\e[0m\n");  /* green */
            else
                fprintf(stderr, "OK\n");
D
Daniel P. Berrange 已提交
152
        else if (ret == EXIT_AM_SKIP)
153
            if (virTestUseTerminalColors())
154 155 156
                fprintf(stderr, "\e[34m\e[1mSKIP\e[0m\n");  /* bold blue */
            else
                fprintf(stderr, "SKIP\n");
D
Daniel P. Berrange 已提交
157
        else
158
            if (virTestUseTerminalColors())
159 160 161
                fprintf(stderr, "\e[31m\e[1mFAILED\e[0m\n");  /* bold red */
            else
                fprintf(stderr, "FAILED\n");
D
Daniel P. Berrange 已提交
162 163 164 165 166
    } else {
        if (testCounter != 1 &&
            !((testCounter-1) % 40)) {
            fprintf(stderr, " %-3zu\n", (testCounter-1));
            fprintf(stderr, "      ");
167
        }
D
Daniel P. Berrange 已提交
168
        if (ret == 0)
169
                fprintf(stderr, ".");
D
Daniel P. Berrange 已提交
170 171 172 173
        else if (ret == EXIT_AM_SKIP)
            fprintf(stderr, "_");
        else
            fprintf(stderr, "!");
174
    }
175

176 177 178
    if (ret != 0)
        ignore_value(virBitmapSetBitExpand(failedTests, testCounter));

179
    g_unsetenv("VIR_TEST_MOCK_TESTNAME");
180
    return ret;
K
Karel Zak 已提交
181
}
182

183 184 185 186 187 188 189 190 191 192 193

/**
 * virTestLoadFile:
 * @file: name of the file to load
 * @buf: buffer to load the file into
 *
 * Allocates @buf to the size of FILE. Reads FILE into buffer BUF.
 * Upon any failure, error is printed to stderr and -1 is returned. 'errno' is
 * not preserved. On success 0 is returned. Caller is responsible for freeing
 * @buf.
 */
194
int
195
virTestLoadFile(const char *file, char **buf)
196
{
197
    FILE *fp = fopen(file, "r");
198
    struct stat st;
199 200
    char *tmp;
    int len, tmplen, buflen;
201

202
    if (!fp) {
203
        fprintf(stderr, "%s: failed to open: %s\n", file, g_strerror(errno));
204
        return -1;
205
    }
206 207

    if (fstat(fileno(fp), &st) < 0) {
208
        fprintf(stderr, "%s: failed to fstat: %s\n", file, g_strerror(errno));
209
        VIR_FORCE_FCLOSE(fp);
210 211 212
        return -1;
    }

213 214 215
    tmplen = buflen = st.st_size + 1;

    if (VIR_ALLOC_N(*buf, buflen) < 0) {
216
        VIR_FORCE_FCLOSE(fp);
217 218 219
        return -1;
    }

220
    tmp = *buf;
221
    (*buf)[0] = '\0';
222
    if (st.st_size) {
223 224 225
        /* read the file line by line */
        while (fgets(tmp, tmplen, fp) != NULL) {
            len = strlen(tmp);
226 227 228
            /* stop on an empty line */
            if (len == 0)
                break;
229 230 231 232 233 234 235 236 237 238
            /* remove trailing backslash-newline pair */
            if (len >= 2 && tmp[len-2] == '\\' && tmp[len-1] == '\n') {
                len -= 2;
                tmp[len] = '\0';
            }
            /* advance the temporary buffer pointer */
            tmp += len;
            tmplen -= len;
        }
        if (ferror(fp)) {
239
            fprintf(stderr, "%s: read failed: %s\n", file, g_strerror(errno));
240
            VIR_FORCE_FCLOSE(fp);
241
            VIR_FREE(*buf);
242 243
            return -1;
        }
244 245
    }

246
    VIR_FORCE_FCLOSE(fp);
247
    return 0;
248 249
}

250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281

static char *
virTestLoadFileGetPath(const char *p,
                       va_list ap)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    char *path = NULL;

    virBufferAddLit(&buf, abs_srcdir "/");

    if (p) {
        virBufferAdd(&buf, p, -1);
        virBufferStrcatVArgs(&buf, ap);
    }

    if (!(path = virBufferContentAndReset(&buf)))
        VIR_TEST_VERBOSE("failed to format file path");

    return path;
}


/**
 * virTestLoadFilePath:
 * @...: file name components terminated with a NULL
 *
 * Constructs the test file path from variable arguments and loads the file.
 * 'abs_srcdir' is automatically prepended.
 */
char *
virTestLoadFilePath(const char *p, ...)
{
J
Ján Tomko 已提交
282
    g_autofree char *path = NULL;
283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299
    char *ret = NULL;
    va_list ap;

    va_start(ap, p);

    if (!(path = virTestLoadFileGetPath(p, ap)))
        goto cleanup;

    ignore_value(virTestLoadFile(path, &ret));

 cleanup:
    va_end(ap);

    return ret;
}


300 301 302 303 304 305 306 307 308 309 310
/**
 * virTestLoadFileJSON:
 * @...: name components terminated with a NULL
 *
 * Constructs the test file path from variable arguments and loads and parses
 * the JSON file. 'abs_srcdir' is automatically prepended to the path.
 */
virJSONValuePtr
virTestLoadFileJSON(const char *p, ...)
{
    virJSONValuePtr ret = NULL;
J
Ján Tomko 已提交
311 312
    g_autofree char *jsonstr = NULL;
    g_autofree char *path = NULL;
313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
    va_list ap;

    va_start(ap, p);

    if (!(path = virTestLoadFileGetPath(p, ap)))
        goto cleanup;

    if (virTestLoadFile(path, &jsonstr) < 0)
        goto cleanup;

    if (!(ret = virJSONValueFromString(jsonstr)))
        VIR_TEST_VERBOSE("failed to parse json from file '%s'", path);

 cleanup:
    va_end(ap);
    return ret;
}


332 333 334
static int
virTestRewrapFile(const char *filename)
{
J
Ján Tomko 已提交
335
    g_autofree char *script = NULL;
J
Ján Tomko 已提交
336
    g_autoptr(virCommand) cmd = NULL;
337

338 339
    if (!(virStringHasSuffix(filename, ".args") ||
          virStringHasSuffix(filename, ".ldargs")))
J
Ján Tomko 已提交
340 341
        return 0;

342
    script = g_strdup_printf("%s/scripts/test-wrap-argv.py", abs_top_srcdir);
343

344
    cmd = virCommandNewArgList(PYTHON, script, "--in-place", filename, NULL);
345
    if (virCommandRun(cmd, NULL) < 0)
346
        return -1;
347

348
    return 0;
349
}
350 351

/**
352
 * @param stream: output stream to write differences to
353
 * @param expect: expected output text
354
 * @param expectName: name designator of the expected text
355
 * @param actual: actual output text
356
 * @param actualName: name designator of the actual text
357
 * @param regenerate: enable or disable regenerate functionality
358
 *
359 360 361
 * Display expected and actual output text, trimmed to first and last
 * characters at which differences occur. Displays names of the text strings if
 * non-NULL.
362
 */
363
static int
364 365 366 367 368 369
virTestDifferenceFullInternal(FILE *stream,
                              const char *expect,
                              const char *expectName,
                              const char *actual,
                              const char *actualName,
                              bool regenerate)
370
{
371 372 373 374 375 376 377 378 379 380 381 382 383 384
    const char *expectStart;
    const char *expectEnd;
    const char *actualStart;
    const char *actualEnd;

    if (!expect)
        expect = "";
    if (!actual)
        actual = "";

    expectStart = expect;
    expectEnd = expect + (strlen(expect)-1);
    actualStart = actual;
    actualEnd = actual + (strlen(actual)-1);
385

386
    if (expectName && regenerate && (virTestGetRegenerate() > 0)) {
387 388
        if (virFileWriteStr(expectName, actual, 0666) < 0) {
            virDispatchError(NULL);
389
            return -1;
390
        }
391

392 393
        if (virTestRewrapFile(expectName) < 0) {
            virDispatchError(NULL);
394
            return -1;
395
        }
396 397
    }

398
    if (!virTestGetDebug())
399 400
        return 0;

401
    if (virTestGetDebug() < 2) {
402 403 404 405 406 407
        /* Skip to first character where they differ */
        while (*expectStart && *actualStart &&
               *actualStart == *expectStart) {
            actualStart++;
            expectStart++;
        }
408

409 410 411 412 413 414 415
        /* Work backwards to last character where they differ */
        while (actualEnd > actualStart &&
               expectEnd > expectStart &&
               *actualEnd == *expectEnd) {
            actualEnd--;
            expectEnd--;
        }
416 417 418
    }

    /* Show the trimmed differences */
419 420
    if (expectName)
        fprintf(stream, "\nIn '%s':", expectName);
E
Eric Blake 已提交
421
    fprintf(stream, "\nOffset %d\nExpect [", (int) (expectStart - expect));
422 423 424 425
    if ((expectEnd - expectStart + 1) &&
        fwrite(expectStart, (expectEnd-expectStart+1), 1, stream) != 1)
        return -1;
    fprintf(stream, "]\n");
426 427
    if (actualName)
        fprintf(stream, "In '%s':\n", actualName);
428 429 430 431 432 433 434 435 436 437 438
    fprintf(stream, "Actual [");
    if ((actualEnd - actualStart + 1) &&
        fwrite(actualStart, (actualEnd-actualStart+1), 1, stream) != 1)
        return -1;
    fprintf(stream, "]\n");

    /* Pad to line up with test name ... in virTestRun */
    fprintf(stream, "                                                                      ... ");

    return 0;
}
439

440 441 442 443 444 445 446 447 448 449 450 451 452
/**
 * @param stream: output stream to write differences to
 * @param expect: expected output text
 * @param expectName: name designator of the expected text
 * @param actual: actual output text
 * @param actualName: name designator of the actual text
 *
 * Display expected and actual output text, trimmed to first and last
 * characters at which differences occur. Displays names of the text strings if
 * non-NULL. If VIR_TEST_REGENERATE_OUTPUT is used, this function will
 * regenerate the expected file.
 */
int
453 454 455 456 457
virTestDifferenceFull(FILE *stream,
                      const char *expect,
                      const char *expectName,
                      const char *actual,
                      const char *actualName)
458
{
459 460
    return virTestDifferenceFullInternal(stream, expect, expectName,
                                         actual, actualName, true);
461 462 463 464 465 466 467 468 469 470 471 472 473 474 475
}

/**
 * @param stream: output stream to write differences to
 * @param expect: expected output text
 * @param expectName: name designator of the expected text
 * @param actual: actual output text
 * @param actualName: name designator of the actual text
 *
 * Display expected and actual output text, trimmed to first and last
 * characters at which differences occur. Displays names of the text strings if
 * non-NULL. If VIR_TEST_REGENERATE_OUTPUT is used, this function will not
 * regenerate the expected file.
 */
int
476 477 478 479 480
virTestDifferenceFullNoRegenerate(FILE *stream,
                                  const char *expect,
                                  const char *expectName,
                                  const char *actual,
                                  const char *actualName)
481
{
482 483
    return virTestDifferenceFullInternal(stream, expect, expectName,
                                         actual, actualName, false);
484 485
}

486
/**
487
 * @param stream: output stream to write differences to
488 489 490 491 492 493
 * @param expect: expected output text
 * @param actual: actual output text
 *
 * Display expected and actual output text, trimmed to
 * first and last characters at which differences occur
 */
494
int
495 496 497
virTestDifference(FILE *stream,
                  const char *expect,
                  const char *actual)
498
{
499 500 501
    return virTestDifferenceFullNoRegenerate(stream,
                                             expect, NULL,
                                             actual, NULL);
502 503 504
}


505
/**
506
 * @param stream: output stream to write differences to
507 508 509 510 511 512
 * @param expect: expected output text
 * @param actual: actual output text
 *
 * Display expected and actual output text, trimmed to
 * first and last characters at which differences occur
 */
513 514 515 516
int virTestDifferenceBin(FILE *stream,
                         const char *expect,
                         const char *actual,
                         size_t length)
517 518 519 520 521 522 523 524 525
{
    size_t start = 0, end = length;
    ssize_t i;

    if (!virTestGetDebug())
        return 0;

    if (virTestGetDebug() < 2) {
        /* Skip to first character where they differ */
526
        for (i = 0; i < length; i++) {
527 528 529 530 531 532 533
            if (expect[i] != actual[i]) {
                start = i;
                break;
            }
        }

        /* Work backwards to last character where they differ */
534
        for (i = (length -1); i >= 0; i--) {
535 536 537 538 539 540
            if (expect[i] != actual[i]) {
                end = i;
                break;
            }
        }
    }
E
Eric Blake 已提交
541
    /* Round to nearest boundary of 4, except that last word can be short */
542 543 544 545 546 547 548
    start -= (start % 4);
    end += 4 - (end % 4);
    if (end >= length)
        end = length - 1;

    /* Show the trimmed differences */
    fprintf(stream, "\nExpect [ Region %d-%d", (int)start, (int)end);
549
    for (i = start; i < end; i++) {
550 551 552 553 554 555
        if ((i % 4) == 0)
            fprintf(stream, "\n    ");
        fprintf(stream, "0x%02x, ", ((int)expect[i])&0xff);
    }
    fprintf(stream, "]\n");
    fprintf(stream, "Actual [ Region %d-%d", (int)start, (int)end);
556
    for (i = start; i < end; i++) {
557 558 559 560 561 562 563 564 565 566 567 568
        if ((i % 4) == 0)
            fprintf(stream, "\n    ");
        fprintf(stream, "0x%02x, ", ((int)actual[i])&0xff);
    }
    fprintf(stream, "]\n");

    /* Pad to line up with test name ... in virTestRun */
    fprintf(stream, "                                                                      ... ");

    return 0;
}

C
Cole Robinson 已提交
569
/*
570 571
 * @param actual: String input content
 * @param filename: File to compare @actual against
572
 *
573
 * If @actual is NULL, it's treated as an empty string.
C
Cole Robinson 已提交
574 575
 */
int
576
virTestCompareToFile(const char *actual,
577
                     const char *filename)
C
Cole Robinson 已提交
578
{
J
Ján Tomko 已提交
579 580
    g_autofree char *filecontent = NULL;
    g_autofree char *fixedcontent = NULL;
581
    const char *cmpcontent = actual;
C
Cole Robinson 已提交
582

583 584 585
    if (!cmpcontent)
        cmpcontent = "";

586
    if (virTestLoadFile(filename, &filecontent) < 0 && !virTestGetRegenerate())
587
        return -1;
C
Cole Robinson 已提交
588

589 590
    if (filecontent) {
        size_t filecontentLen = strlen(filecontent);
591
        size_t cmpcontentLen = strlen(cmpcontent);
592 593 594

        if (filecontentLen > 0 &&
            filecontent[filecontentLen - 1] == '\n' &&
595
            (cmpcontentLen == 0 || cmpcontent[cmpcontentLen - 1] != '\n')) {
596
            fixedcontent = g_strdup_printf("%s\n", cmpcontent);
597 598
            cmpcontent = fixedcontent;
        }
C
Cole Robinson 已提交
599 600
    }

601
    if (STRNEQ_NULLABLE(cmpcontent, filecontent)) {
602 603
        virTestDifferenceFull(stderr,
                              filecontent, filename,
604
                              cmpcontent, NULL);
605
        return -1;
C
Cole Robinson 已提交
606 607
    }

608
    return 0;
C
Cole Robinson 已提交
609 610
}

611
int
612 613
virTestCompareToULL(unsigned long long expect,
                    unsigned long long actual)
614
{
615 616
    g_autofree char *expectStr = NULL;
    g_autofree char *actualStr = NULL;
617

618
    expectStr = g_strdup_printf("%llu", expect);
619

620
    actualStr = g_strdup_printf("%llu", actual);
621

622
    return virTestCompareToString(expectStr, actualStr);
623 624
}

J
Jim Fehlig 已提交
625
int
626 627
virTestCompareToString(const char *expect,
                       const char *actual)
J
Jim Fehlig 已提交
628
{
629 630
    if (STRNEQ_NULLABLE(expect, actual)) {
        virTestDifference(stderr, expect, actual);
J
Jim Fehlig 已提交
631 632 633 634 635 636
        return -1;
    }

    return 0;
}

637
static void
J
Ján Tomko 已提交
638 639
virTestErrorFuncQuiet(void *data G_GNUC_UNUSED,
                      virErrorPtr err G_GNUC_UNUSED)
640
{ }
641 642 643 644


/* register an error handler in tests when using connections */
void
645
virTestQuiesceLibvirtErrors(bool always)
646 647
{
    if (always || !virTestGetVerbose())
648
        virSetErrorFunc(NULL, virTestErrorFuncQuiet);
649
}
650

651 652 653 654 655 656
struct virtTestLogData {
    virBuffer buf;
};

static struct virtTestLogData testLog = { VIR_BUFFER_INITIALIZER };

657
static void
J
Ján Tomko 已提交
658 659 660 661 662
virtTestLogOutput(virLogSourcePtr source G_GNUC_UNUSED,
                  virLogPriority priority G_GNUC_UNUSED,
                  const char *filename G_GNUC_UNUSED,
                  int lineno G_GNUC_UNUSED,
                  const char *funcname G_GNUC_UNUSED,
663
                  const char *timestamp,
J
Ján Tomko 已提交
664 665
                  virLogMetadataPtr metadata G_GNUC_UNUSED,
                  const char *rawstr G_GNUC_UNUSED,
666 667
                  const char *str,
                  void *data)
668 669
{
    struct virtTestLogData *log = data;
670
    virBufferAsprintf(&log->buf, "%s: %s", timestamp, str);
671 672 673 674 675 676 677 678 679 680 681 682 683
}

static void
virtTestLogClose(void *data)
{
    struct virtTestLogData *log = data;

    virBufferFreeAndReset(&log->buf);
}

/* Return a malloc'd string (possibly with strlen of 0) of all data
 * logged since the last call to this function, or NULL on failure.  */
char *
684
virTestLogContentAndReset(void)
685 686 687 688
{
    char *ret;

    ret = virBufferContentAndReset(&testLog.buf);
689
    if (!ret)
690
        ret = g_strdup("");
691
    return ret;
692 693
}

694

695
unsigned int
696 697
virTestGetDebug(void)
{
698 699
    if (testDebug == -1)
        testDebug = virTestGetFlag("VIR_TEST_DEBUG");
700 701
    return testDebug;
}
702

703
unsigned int
704 705
virTestGetVerbose(void)
{
706 707 708 709 710
    if (testVerbose == -1)
        testVerbose = virTestGetFlag("VIR_TEST_VERBOSE");
    return testVerbose || virTestGetDebug();
}

711
unsigned int
712 713
virTestGetExpensive(void)
{
714 715 716 717 718
    if (testExpensive == -1)
        testExpensive = virTestGetFlag("VIR_TEST_EXPENSIVE");
    return testExpensive;
}

719 720 721 722 723 724 725 726
unsigned int
virTestGetRegenerate(void)
{
    if (testRegenerate == -1)
        testRegenerate = virTestGetFlag("VIR_TEST_REGENERATE_OUTPUT");
    return testRegenerate;
}

M
Michal Privoznik 已提交
727 728 729 730
static int
virTestSetEnvPath(void)
{
    const char *path = getenv("PATH");
J
Ján Tomko 已提交
731
    g_autofree char *new_path = NULL;
M
Michal Privoznik 已提交
732

733
    if (path) {
734 735
        if (strstr(path, abs_builddir) != path)
            new_path = g_strdup_printf("%s:%s", abs_builddir, path);
736
    } else {
737
        new_path = g_strdup(abs_builddir);
738 739
    }

740
    if (new_path &&
741
        g_setenv("PATH", new_path, TRUE) == FALSE)
742
        return -1;
M
Michal Privoznik 已提交
743

744
    return 0;
M
Michal Privoznik 已提交
745 746
}

747 748 749 750
int virTestMain(int argc,
                char **argv,
                int (*func)(void),
                ...)
751
{
752 753
    const char *lib;
    va_list ap;
754
    int ret;
755
    char *testRange = NULL;
756 757 758
    size_t noutputs = 0;
    virLogOutputPtr output = NULL;
    virLogOutputPtr *outputs = NULL;
759 760
    g_autofree char *baseprogname = NULL;
    const char *progname;
761 762 763 764 765 766 767 768 769
    g_autofree const char **preloads = NULL;
    size_t npreloads = 0;
    g_autofree char *mock = NULL;

    if (getenv("VIR_TEST_FILE_ACCESS")) {
        preloads = g_renew(const char *, preloads, npreloads + 2);
        preloads[npreloads++] = VIR_TEST_MOCK("virtest");
        preloads[npreloads] = NULL;
    }
770

771
    va_start(ap, func);
772 773 774 775 776 777 778 779 780 781
    while ((lib = va_arg(ap, const char *))) {
        if (!virFileIsExecutable(lib)) {
            perror(lib);
            return EXIT_FAILURE;
        }

        preloads = g_renew(const char *, preloads, npreloads + 2);
        preloads[npreloads++] = lib;
        preloads[npreloads] = NULL;
    }
782
    va_end(ap);
783

784 785 786 787 788
    if (preloads) {
        mock = g_strjoinv(":", (char **)preloads);
        VIR_TEST_PRELOAD(mock);
    }

789
    progname = baseprogname = g_path_get_basename(argv[0]);
790 791 792
    if (STRPREFIX(progname, "lt-"))
        progname += 3;

793
    g_setenv("VIR_TEST_MOCK_PROGNAME", progname, TRUE);
794

795
    virFileActivateDirOverrideForProg(argv[0]);
796

M
Michal Privoznik 已提交
797 798 799
    if (virTestSetEnvPath() < 0)
        return EXIT_AM_HARDFAIL;

800
    if (!virFileExists(abs_srcdir))
801
        return EXIT_AM_HARDFAIL;
E
Eric Blake 已提交
802 803 804

    if (argc > 1) {
        fprintf(stderr, "Usage: %s\n", argv[0]);
805 806
        fputs("effective environment variables:\n"
              "VIR_TEST_VERBOSE set to show names of individual tests\n"
807
              "VIR_TEST_DEBUG set to show information for debugging failures",
808
              stderr);
E
Eric Blake 已提交
809 810 811
        return EXIT_FAILURE;
    }
    fprintf(stderr, "TEST: %s\n", progname);
812

813
    if (virErrorInitialize() < 0)
814
        return EXIT_FAILURE;
815

816
    virLogSetFromEnv();
817
    if (!getenv("LIBVIRT_DEBUG") && !virLogGetNbOutputs()) {
818 819 820 821 822 823 824
        if (!(output = virLogOutputNew(virtTestLogOutput, virtTestLogClose,
                                       &testLog, VIR_LOG_DEBUG,
                                       VIR_LOG_TO_STDERR, NULL)) ||
            VIR_APPEND_ELEMENT(outputs, noutputs, output) < 0 ||
            virLogDefineOutputs(outputs, noutputs) < 0) {
            virLogOutputFree(output);
            virLogOutputListFree(outputs, noutputs);
825
            return EXIT_FAILURE;
826
        }
827
    }
828

829
    if ((testRange = getenv("VIR_TEST_RANGE")) != NULL) {
830
        if (!(testBitmap = virBitmapParseUnlimited(testRange))) {
831 832 833 834 835
            fprintf(stderr, "Cannot parse range %s\n", testRange);
            return EXIT_FAILURE;
        }
    }

836 837 838
    if (!(failedTests = virBitmapNew(1)))
        return EXIT_FAILURE;

E
Eric Blake 已提交
839
    ret = (func)();
840 841

    virResetLastError();
842
    if (!virTestGetVerbose() && ret != EXIT_AM_SKIP) {
E
Eric Blake 已提交
843
        if (testCounter == 0 || testCounter % 40)
844 845
            fprintf(stderr, "%*s", 40 - (int)(testCounter % 40), "");
        fprintf(stderr, " %-3zu %s\n", testCounter, ret == 0 ? "OK" : "FAIL");
846
    }
847 848 849 850 851
    if (ret == EXIT_FAILURE && !virBitmapIsAllClear(failedTests)) {
        g_autofree char *failed = virBitmapFormat(failedTests);
        fprintf(stderr, "Some tests failed. Run them using:\n");
        fprintf(stderr, "VIR_TEST_DEBUG=1 VIR_TEST_RANGE=%s %s\n", failed, argv[0]);
    }
852
    virLogReset();
853
    return ret;
854
}
855 856


857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874
/*
 * @cmdset contains a list of command line args, eg
 *
 * "/usr/sbin/iptables --table filter --insert INPUT --in-interface virbr0 --protocol tcp --destination-port 53 --jump ACCEPT
 *  /usr/sbin/iptables --table filter --insert INPUT --in-interface virbr0 --protocol udp --destination-port 53 --jump ACCEPT
 *  /usr/sbin/iptables --table filter --insert FORWARD --in-interface virbr0 --jump REJECT
 *  /usr/sbin/iptables --table filter --insert FORWARD --out-interface virbr0 --jump REJECT
 *  /usr/sbin/iptables --table filter --insert FORWARD --in-interface virbr0 --out-interface virbr0 --jump ACCEPT"
 *
 * And we're munging it in-place to strip the path component
 * of the command line, to produce
 *
 * "iptables --table filter --insert INPUT --in-interface virbr0 --protocol tcp --destination-port 53 --jump ACCEPT
 *  iptables --table filter --insert INPUT --in-interface virbr0 --protocol udp --destination-port 53 --jump ACCEPT
 *  iptables --table filter --insert FORWARD --in-interface virbr0 --jump REJECT
 *  iptables --table filter --insert FORWARD --out-interface virbr0 --jump REJECT
 *  iptables --table filter --insert FORWARD --in-interface virbr0 --out-interface virbr0 --jump ACCEPT"
 */
875
void virTestClearCommandPath(char *cmdset)
876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907
{
    size_t offset = 0;
    char *lineStart = cmdset;
    char *lineEnd = strchr(lineStart, '\n');

    while (lineStart) {
        char *dirsep;
        char *movestart;
        size_t movelen;
        dirsep = strchr(lineStart, ' ');
        if (dirsep) {
            while (dirsep > lineStart && *dirsep != '/')
                dirsep--;
            if (*dirsep == '/')
                dirsep++;
            movestart = dirsep;
        } else {
            movestart = lineStart;
        }
        movelen = lineEnd ? lineEnd - movestart : strlen(movestart);

        if (movelen) {
            memmove(cmdset + offset, movestart, movelen + 1);
            offset += movelen + 1;
        }
        lineStart = lineEnd ? lineEnd + 1 : NULL;
        lineEnd = lineStart ? strchr(lineStart, '\n') : NULL;
    }
    cmdset[offset] = '\0';
}


908 909
virCapsPtr virTestGenericCapsInit(void)
{
J
Ján Tomko 已提交
910
    g_autoptr(virCaps) caps = NULL;
911 912 913
    virCapsGuestPtr guest;

    if ((caps = virCapabilitiesNew(VIR_ARCH_X86_64,
914
                                   false, false)) == NULL)
915 916
        return NULL;

917
    if ((guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_HVM, VIR_ARCH_I686,
918 919
                                         "/usr/bin/acme-virt", NULL,
                                         0, NULL)) == NULL)
920
        return NULL;
921

922
    if (!virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_TEST, NULL, NULL, 0, NULL))
923
        return NULL;
924 925
    if (!virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_QEMU,
                                       NULL, NULL, 0, NULL))
926
        return NULL;
927 928
    if (!virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_KVM,
                                       NULL, NULL, 0, NULL))
929
        return NULL;
930

931
    if ((guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_HVM, VIR_ARCH_X86_64,
932 933
                                         "/usr/bin/acme-virt", NULL,
                                         0, NULL)) == NULL)
934
        return NULL;
935

936
    if (!virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_TEST, NULL, NULL, 0, NULL))
937
        return NULL;
938 939
    if (!virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_QEMU,
                                       NULL, NULL, 0, NULL))
940
        return NULL;
941 942
    if (!virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_KVM,
                                       NULL, NULL, 0, NULL))
943
        return NULL;
944 945


946
    if (virTestGetDebug() > 1) {
J
Ján Tomko 已提交
947
        g_autofree char *caps_str = NULL;
948 949 950

        caps_str = virCapabilitiesFormatXML(caps);
        if (!caps_str)
951
            return NULL;
952

953
        VIR_TEST_DEBUG("Generic driver capabilities:\n%s", caps_str);
954 955
    }

J
Ján Tomko 已提交
956
    return g_steal_pointer(&caps);
957 958
}

959 960 961 962 963 964 965 966 967

#define MAX_CELLS 4
#define MAX_CPUS_IN_CELL 2
#define MAX_MEM_IN_CELL 2097152

/*
 * Build NUMA topology with cell id starting from (0 + seq)
 * for testing
 */
968 969
virCapsHostNUMAPtr
virTestCapsBuildNUMATopology(int seq)
970
{
J
Ján Tomko 已提交
971
    g_autoptr(virCapsHostNUMA) caps = virCapabilitiesHostNUMANew();
972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991
    virCapsHostNUMACellCPUPtr cell_cpus = NULL;
    int core_id, cell_id;
    int id;

    id = 0;
    for (cell_id = 0; cell_id < MAX_CELLS; cell_id++) {
        if (VIR_ALLOC_N(cell_cpus, MAX_CPUS_IN_CELL) < 0)
            goto error;

        for (core_id = 0; core_id < MAX_CPUS_IN_CELL; core_id++) {
            cell_cpus[core_id].id = id + core_id;
            cell_cpus[core_id].socket_id = cell_id + seq;
            cell_cpus[core_id].core_id = id + core_id;
            if (!(cell_cpus[core_id].siblings =
                  virBitmapNew(MAX_CPUS_IN_CELL)))
                goto error;
            ignore_value(virBitmapSetBit(cell_cpus[core_id].siblings, id));
        }
        id++;

992 993 994 995 996
        virCapabilitiesHostNUMAAddCell(caps, cell_id + seq,
                                       MAX_MEM_IN_CELL,
                                       MAX_CPUS_IN_CELL, cell_cpus,
                                       VIR_ARCH_NONE, NULL,
                                       VIR_ARCH_NONE, NULL);
997 998 999 1000

        cell_cpus = NULL;
    }

J
Ján Tomko 已提交
1001
    return g_steal_pointer(&caps);
1002 1003 1004

 error:
    VIR_FREE(cell_cpus);
1005
    return NULL;
1006 1007
}

1008 1009 1010
static virDomainDefParserConfig virTestGenericDomainDefParserConfig = {
    .features = VIR_DOMAIN_DEF_FEATURE_INDIVIDUAL_VCPUS,
};
1011 1012 1013 1014

virDomainXMLOptionPtr virTestGenericDomainXMLConfInit(void)
{
    return virDomainXMLOptionNew(&virTestGenericDomainDefParserConfig,
1015
                                 NULL, NULL, NULL, NULL);
1016
}
1017 1018


1019
int
1020 1021
testCompareDomXML2XMLFiles(virCapsPtr caps G_GNUC_UNUSED,
                           virDomainXMLOptionPtr xmlopt,
1022
                           const char *infile, const char *outfile, bool live,
1023
                           unsigned int parseFlags,
1024
                           testCompareDomXML2XMLResult expectResult)
1025
{
J
Ján Tomko 已提交
1026
    g_autofree char *actual = NULL;
1027
    int ret = -1;
1028
    testCompareDomXML2XMLResult result;
1029 1030 1031
    virDomainDefPtr def = NULL;
    unsigned int parse_flags = live ? 0 : VIR_DOMAIN_DEF_PARSE_INACTIVE;
    unsigned int format_flags = VIR_DOMAIN_DEF_FORMAT_SECURE;
1032 1033 1034

    parse_flags |= parseFlags;

1035 1036 1037 1038 1039
    if (!virFileExists(infile)) {
        VIR_TEST_DEBUG("Test input file '%s' is missing", infile);
        return -1;
    }

1040 1041 1042
    if (!live)
        format_flags |= VIR_DOMAIN_DEF_FORMAT_INACTIVE;

1043
    if (!(def = virDomainDefParseFile(infile, xmlopt, NULL, parse_flags))) {
1044 1045 1046
        result = TEST_COMPARE_DOM_XML2XML_RESULT_FAIL_PARSE;
        goto out;
    }
1047

1048
    if (!virDomainDefCheckABIStability(def, def, xmlopt)) {
1049
        VIR_TEST_DEBUG("ABI stability check failed on %s", infile);
1050 1051
        result = TEST_COMPARE_DOM_XML2XML_RESULT_FAIL_STABILITY;
        goto out;
1052 1053
    }

1054
    if (!(actual = virDomainDefFormat(def, xmlopt, format_flags))) {
1055 1056 1057
        result = TEST_COMPARE_DOM_XML2XML_RESULT_FAIL_FORMAT;
        goto out;
    }
1058

1059
    if (virTestCompareToFile(actual, outfile) < 0) {
1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077
        result = TEST_COMPARE_DOM_XML2XML_RESULT_FAIL_COMPARE;
        goto out;
    }

    result = TEST_COMPARE_DOM_XML2XML_RESULT_SUCCESS;

 out:
    if (result == expectResult) {
        ret = 0;
        if (expectResult != TEST_COMPARE_DOM_XML2XML_RESULT_SUCCESS) {
            VIR_TEST_DEBUG("Got expected failure code=%d msg=%s",
                           result, virGetLastErrorMessage());
        }
    } else {
        ret = -1;
        VIR_TEST_DEBUG("Expected result code=%d but received code=%d",
                       expectResult, result);
    }
1078 1079 1080 1081 1082 1083

    virDomainDefFree(def);
    return ret;
}


1084 1085 1086 1087 1088 1089
static int virtTestCounter;
static char virtTestCounterStr[128];
static char *virtTestCounterPrefixEndOffset;


/**
1090
 * virTestCounterReset:
1091 1092 1093
 * @prefix: name of the test group
 *
 * Resets the counter and sets up the test group name to use with
1094
 * virTestCounterNext(). This function is not thread safe.
1095 1096 1097 1098 1099
 *
 * Note: The buffer for the assembled message is 128 bytes long. Longer test
 * case names (including the number index) will be silently truncated.
 */
void
1100
virTestCounterReset(const char *prefix)
1101 1102 1103 1104
{
    virtTestCounter = 0;

    ignore_value(virStrcpyStatic(virtTestCounterStr, prefix));
1105
    virtTestCounterPrefixEndOffset = virtTestCounterStr + strlen(virtTestCounterStr);
1106 1107 1108 1109
}


/**
1110
 * virTestCounterNext:
1111 1112 1113 1114 1115
 *
 * This function is designed to ease test creation and reordering by adding
 * a way to do automagic test case numbering.
 *
 * Returns string consisting of test name prefix configured via
1116
 * virTestCounterReset() and a number that increments in every call of this
1117 1118 1119 1120 1121 1122
 * function. This function is not thread safe.
 *
 * Note: The buffer for the assembled message is 128 bytes long. Longer test
 * case names (including the number index) will be silently truncated.
 */
const char
1123
*virTestCounterNext(void)
1124
{
1125
    size_t len = G_N_ELEMENTS(virtTestCounterStr);
1126 1127 1128 1129

    /* calculate length of the rest of the string */
    len -= (virtTestCounterPrefixEndOffset - virtTestCounterStr);

1130
    g_snprintf(virtTestCounterPrefixEndOffset, len, "%d", ++virtTestCounter);
1131 1132 1133

    return virtTestCounterStr;
}