testutils.c 20.3 KB
Newer Older
K
Karel Zak 已提交
1
/*
2
 * testutils.c: basic test utils
K
Karel Zak 已提交
3
 *
4
 * Copyright (C) 2005-2013 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 22
 *
 * Karel Zak <kzak@redhat.com>
 */

23
#include <config.h>
24

K
Karel Zak 已提交
25 26 27
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
28 29
#include <sys/types.h>
#include <sys/stat.h>
30 31
#include <sys/wait.h>
#include <regex.h>
32
#include <unistd.h>
33
#include <string.h>
34 35
#include <fcntl.h>
#include <limits.h>
K
Karel Zak 已提交
36
#include "testutils.h"
37
#include "internal.h"
38
#include "viralloc.h"
39
#include "virutil.h"
40
#include "virthread.h"
41
#include "virerror.h"
42
#include "virbuffer.h"
43
#include "virlog.h"
44
#include "vircommand.h"
45
#include "virrandom.h"
E
Eric Blake 已提交
46
#include "dirname.h"
47
#include "virprocess.h"
48
#include "virstring.h"
49 50

#if TEST_OOM_TRACE
51
# include <execinfo.h>
52
#endif
K
Karel Zak 已提交
53

54
#ifdef HAVE_PATHS_H
55
# include <paths.h>
56 57
#endif

58 59
#define VIR_FROM_THIS VIR_FROM_NONE

K
Karel Zak 已提交
60
#define GETTIMEOFDAY(T) gettimeofday(T, NULL)
61
#define DIFF_MSEC(T, U)                                 \
62
    ((((int) ((T)->tv_sec - (U)->tv_sec)) * 1000000.0 + \
63
      ((int) ((T)->tv_usec - (U)->tv_usec))) / 1000.0)
K
Karel Zak 已提交
64

E
Eric Blake 已提交
65
#include "virfile.h"
66

67
static unsigned int testDebug = -1;
68
static unsigned int testVerbose = -1;
69

70 71 72
static unsigned int testOOM = 0;
static unsigned int testCounter = 0;

E
Eric Blake 已提交
73 74 75
char *progname;
char *abs_srcdir;

K
Karel Zak 已提交
76 77 78
double
virtTestCountAverage(double *items, int nitems)
{
79
    long double sum = 0;
80
    size_t i;
K
Karel Zak 已提交
81

82 83
    for (i=1; i < nitems; i++)
        sum += items[i];
K
Karel Zak 已提交
84

85
    return (double) (sum / nitems);
K
Karel Zak 已提交
86 87
}

88

89 90 91 92 93
void virtTestResult(const char *name, int ret, const char *msg, ...)
{
    va_list vargs;
    va_start(vargs, msg);

94 95 96
    if (testCounter == 0 && !virTestGetVerbose())
        fprintf(stderr, "      ");

97 98 99 100 101 102 103 104
    testCounter++;
    if (virTestGetVerbose()) {
        fprintf(stderr, "%3d) %-60s ", testCounter, name);
        if (ret == 0)
            fprintf(stderr, "OK\n");
        else {
            fprintf(stderr, "FAILED\n");
            if (msg) {
105
                char *str;
106
                if (virVasprintfQuiet(&str, msg, vargs) == 0) {
107 108 109
                    fprintf(stderr, "%s", str);
                    VIR_FREE(str);
                }
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
            }
        }
    } else {
        if (testCounter != 1 &&
            !((testCounter-1) % 40)) {
            fprintf(stderr, " %-3d\n", (testCounter-1));
            fprintf(stderr, "      ");
        }
        if (ret == 0)
            fprintf(stderr, ".");
        else
            fprintf(stderr, "!");
    }

    va_end(vargs);
}

127
/*
K
Karel Zak 已提交
128
 * Runs test and count average time (if the nloops is grater than 1)
129 130
 *
 * returns: -1 = error, 0 = success
K
Karel Zak 已提交
131 132
 */
int
133
virtTestRun(const char *title, int nloops, int (*body)(const void *data), const void *data)
K
Karel Zak 已提交
134
{
135 136
    int ret = 0;
    size_t i;
137
    double *ts = NULL;
138

139 140 141
    if (testCounter == 0 && !virTestGetVerbose())
        fprintf(stderr, "      ");

142
    testCounter++;
143

144
    if (testOOM < 2) {
145 146
        if (virTestGetVerbose())
            fprintf(stderr, "%2d) %-65s ... ", testCounter, title);
147
    }
148

149
    if (nloops > 1 && (VIR_ALLOC_N(ts, nloops) < 0))
150 151 152 153 154 155 156
        return -1;

    for (i=0; i < nloops; i++) {
        struct timeval before, after;

        if (ts)
            GETTIMEOFDAY(&before);
157

158
        virResetLastError();
159
        ret = body(data);
160
        virErrorPtr err = virGetLastError();
161 162 163 164 165 166 167 168 169 170
        if (err) {
            if (virTestGetVerbose() || virTestGetDebug())
                virDispatchError(NULL);
        }

        if (ret != 0) {
            break;
        }

        if (ts) {
171 172 173 174
            GETTIMEOFDAY(&after);
            ts[i] = DIFF_MSEC(&after, &before);
        }
    }
175
    if (testOOM < 2) {
176 177 178 179 180 181
        if (virTestGetVerbose()) {
            if (ret == 0 && ts)
                fprintf(stderr, "OK     [%.5f ms]\n",
                        virtTestCountAverage(ts, nloops));
            else if (ret == 0)
                fprintf(stderr, "OK\n");
182 183
            else if (ret == EXIT_AM_SKIP)
                fprintf(stderr, "SKIP\n");
184 185 186 187 188 189 190 191 192 193
            else
                fprintf(stderr, "FAILED\n");
        } else {
            if (testCounter != 1 &&
                !((testCounter-1) % 40)) {
                fprintf(stderr, " %-3d\n", (testCounter-1));
                fprintf(stderr, "      ");
            }
            if (ret == 0)
                fprintf(stderr, ".");
194 195
            else if (ret == EXIT_AM_SKIP)
                fprintf(stderr, "_");
196 197 198
            else
                fprintf(stderr, "!");
        }
199
    }
200

201
    VIR_FREE(ts);
202
    return ret;
K
Karel Zak 已提交
203
}
204

205 206 207 208 209 210
/* Allocate BUF to the size of FILE. Read FILE into buffer BUF.
   Upon any failure, diagnose it and return -1, but don't bother trying
   to preserve errno. Otherwise, return the number of bytes copied into BUF. */
int
virtTestLoadFile(const char *file, char **buf)
{
211
    FILE *fp = fopen(file, "r");
212
    struct stat st;
213 214
    char *tmp;
    int len, tmplen, buflen;
215

216
    if (!fp) {
217
        fprintf(stderr, "%s: failed to open: %s\n", file, strerror(errno));
218
        return -1;
219
    }
220 221

    if (fstat(fileno(fp), &st) < 0) {
222
        fprintf(stderr, "%s: failed to fstat: %s\n", file, strerror(errno));
223
        VIR_FORCE_FCLOSE(fp);
224 225 226
        return -1;
    }

227 228 229
    tmplen = buflen = st.st_size + 1;

    if (VIR_ALLOC_N(*buf, buflen) < 0) {
230
        fprintf(stderr, "%s: larger than available memory (> %d)\n", file, buflen);
231
        VIR_FORCE_FCLOSE(fp);
232 233 234
        return -1;
    }

235
    tmp = *buf;
236
    (*buf)[0] = '\0';
237
    if (st.st_size) {
238 239 240
        /* read the file line by line */
        while (fgets(tmp, tmplen, fp) != NULL) {
            len = strlen(tmp);
241 242 243
            /* stop on an empty line */
            if (len == 0)
                break;
244 245 246 247 248 249 250 251 252 253
            /* 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)) {
254
            fprintf(stderr, "%s: read failed: %s\n", file, strerror(errno));
255
            VIR_FORCE_FCLOSE(fp);
256
            VIR_FREE(*buf);
257 258
            return -1;
        }
259 260
    }

261
    VIR_FORCE_FCLOSE(fp);
262
    return strlen(*buf);
263 264
}

A
Atsushi SAKAI 已提交
265
#ifndef WIN32
266 267
static
void virtTestCaptureProgramExecChild(const char *const argv[],
268
                                     int pipefd) {
269
    size_t i;
270 271 272 273
    int open_max;
    int stdinfd = -1;
    const char *const env[] = {
        "LANG=C",
274
# if WITH_DRIVER_MODULES
275
        "LIBVIRT_DRIVER_DIR=" TEST_DRIVER_DIR,
276
# endif
277 278 279
        NULL
    };

280
    if ((stdinfd = open("/dev/null", O_RDONLY)) < 0)
281 282
        goto cleanup;

283
    open_max = sysconf(_SC_OPEN_MAX);
J
John Ferlan 已提交
284 285 286
    if (open_max < 0)
        goto cleanup;

287 288
    for (i = 0; i < open_max; i++) {
        if (i != stdinfd &&
289
            i != pipefd) {
290 291
            int tmpfd;
            tmpfd = i;
292 293
            VIR_FORCE_CLOSE(tmpfd);
        }
294 295 296 297 298 299
    }

    if (dup2(stdinfd, STDIN_FILENO) != STDIN_FILENO)
        goto cleanup;
    if (dup2(pipefd, STDOUT_FILENO) != STDOUT_FILENO)
        goto cleanup;
300
    if (dup2(pipefd, STDERR_FILENO) != STDERR_FILENO)
301 302 303 304
        goto cleanup;

    /* SUS is crazy here, hence the cast */
    execve(argv[0], (char *const*)argv, (char *const*)env);
305 306

 cleanup:
307
    VIR_FORCE_CLOSE(stdinfd);
308 309
}

310 311 312
int
virtTestCaptureProgramOutput(const char *const argv[], char **buf, int maxlen)
{
313
    int pipefd[2];
314
    int len;
315 316 317 318

    if (pipe(pipefd) < 0)
        return -1;

319
    pid_t pid = fork();
320
    switch (pid) {
321
    case 0:
322
        VIR_FORCE_CLOSE(pipefd[0]);
323 324
        virtTestCaptureProgramExecChild(argv, pipefd[1]);

325
        VIR_FORCE_CLOSE(pipefd[1]);
326
        _exit(EXIT_FAILURE);
327

328 329
    case -1:
        return -1;
330

331
    default:
332 333 334
        VIR_FORCE_CLOSE(pipefd[1]);
        len = virFileReadLimFD(pipefd[0], maxlen, buf);
        VIR_FORCE_CLOSE(pipefd[0]);
335
        if (virProcessWait(pid, NULL) < 0)
E
Eric Blake 已提交
336
            return -1;
337

338
        return len;
339
    }
340
}
341
#else /* !WIN32 */
342 343 344 345 346
int
virtTestCaptureProgramOutput(const char *const argv[] ATTRIBUTE_UNUSED,
                             char **buf ATTRIBUTE_UNUSED,
                             int maxlen ATTRIBUTE_UNUSED)
{
347 348
    return -1;
}
A
Atsushi SAKAI 已提交
349
#endif /* !WIN32 */
350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368


/**
 * @param stream: output stream write to differences to
 * @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
 */
int virtTestDifference(FILE *stream,
                       const char *expect,
                       const char *actual)
{
    const char *expectStart = expect;
    const char *expectEnd = expect + (strlen(expect)-1);
    const char *actualStart = actual;
    const char *actualEnd = actual + (strlen(actual)-1);

369
    if (!virTestGetDebug())
370 371
        return 0;

372
    if (virTestGetDebug() < 2) {
373 374 375 376 377 378
        /* Skip to first character where they differ */
        while (*expectStart && *actualStart &&
               *actualStart == *expectStart) {
            actualStart++;
            expectStart++;
        }
379

380 381 382 383 384 385 386
        /* Work backwards to last character where they differ */
        while (actualEnd > actualStart &&
               expectEnd > expectStart &&
               *actualEnd == *expectEnd) {
            actualEnd--;
            expectEnd--;
        }
387 388 389
    }

    /* Show the trimmed differences */
E
Eric Blake 已提交
390
    fprintf(stream, "\nOffset %d\nExpect [", (int) (expectStart - expect));
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405
    if ((expectEnd - expectStart + 1) &&
        fwrite(expectStart, (expectEnd-expectStart+1), 1, stream) != 1)
        return -1;
    fprintf(stream, "]\n");
    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;
}
406

407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427
/**
 * @param stream: output stream write to differences to
 * @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
 */
int virtTestDifferenceBin(FILE *stream,
                          const char *expect,
                          const char *actual,
                          size_t length)
{
    size_t start = 0, end = length;
    ssize_t i;

    if (!virTestGetDebug())
        return 0;

    if (virTestGetDebug() < 2) {
        /* Skip to first character where they differ */
428
        for (i = 0; i < length; i++) {
429 430 431 432 433 434 435
            if (expect[i] != actual[i]) {
                start = i;
                break;
            }
        }

        /* Work backwards to last character where they differ */
436
        for (i = (length -1); i >= 0; i--) {
437 438 439 440 441 442
            if (expect[i] != actual[i]) {
                end = i;
                break;
            }
        }
    }
E
Eric Blake 已提交
443
    /* Round to nearest boundary of 4, except that last word can be short */
444 445 446 447 448 449 450
    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);
451
    for (i = start; i < end; i++) {
452 453 454 455 456 457
        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);
458
    for (i = start; i < end; i++) {
459 460 461 462 463 464 465 466 467 468 469 470
        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;
}

471
#if TEST_OOM
472 473 474 475
static void
virtTestErrorFuncQuiet(void *data ATTRIBUTE_UNUSED,
                       virErrorPtr err ATTRIBUTE_UNUSED)
{ }
476
#endif
477

478 479 480 481 482 483
struct virtTestLogData {
    virBuffer buf;
};

static struct virtTestLogData testLog = { VIR_BUFFER_INITIALIZER };

484
static void
485
virtTestLogOutput(virLogSource source ATTRIBUTE_UNUSED,
486
                  virLogPriority priority ATTRIBUTE_UNUSED,
487 488
                  const char *filename ATTRIBUTE_UNUSED,
                  int lineno ATTRIBUTE_UNUSED,
489
                  const char *funcname ATTRIBUTE_UNUSED,
490
                  const char *timestamp,
M
Miloslav Trmač 已提交
491
                  virLogMetadataPtr metadata ATTRIBUTE_UNUSED,
492
                  unsigned int flags,
493
                  const char *rawstr ATTRIBUTE_UNUSED,
494 495
                  const char *str,
                  void *data)
496 497
{
    struct virtTestLogData *log = data;
498
    virCheckFlags(VIR_LOG_STACK_TRACE,);
499
    virBufferAsprintf(&log->buf, "%s: %s", timestamp, str);
500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519
}

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 *
virtTestLogContentAndReset(void)
{
    char *ret;

    if (virBufferError(&testLog.buf))
        return NULL;
    ret = virBufferContentAndReset(&testLog.buf);
520 521 522
    if (!ret)
        ignore_value(VIR_STRDUP(ret, ""));
    return ret;
523 524
}

525
#if TEST_OOM_TRACE
526
static void
527
virtTestErrorHook(int n, void *data ATTRIBUTE_UNUSED)
528 529 530
{
    void *trace[30];
    int ntrace = ARRAY_CARDINALITY(trace);
531
    size_t i;
532 533 534 535 536
    char **symbols = NULL;

    ntrace = backtrace(trace, ntrace);
    symbols = backtrace_symbols(trace, ntrace);
    if (symbols) {
537
        fprintf(stderr, "Failing allocation %d at:\n", n);
538
        for (i = 0; i < ntrace; i++) {
539 540 541
            if (symbols[i])
                fprintf(stderr, "  TRACE:  %s\n", symbols[i]);
        }
542
        VIR_FREE(symbols);
543 544
    }
}
545
#endif
546

547 548 549 550
static unsigned int
virTestGetFlag(const char *name) {
    char *flagStr;
    unsigned int flag;
551

552
    if ((flagStr = getenv(name)) == NULL)
553 554
        return 0;

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

558 559 560 561
    return flag;
}

unsigned int
562
virTestGetDebug(void) {
563 564
    if (testDebug == -1)
        testDebug = virTestGetFlag("VIR_TEST_DEBUG");
565 566
    return testDebug;
}
567

568
unsigned int
569
virTestGetVerbose(void) {
570 571 572 573 574
    if (testVerbose == -1)
        testVerbose = virTestGetFlag("VIR_TEST_VERBOSE");
    return testVerbose || virTestGetDebug();
}

575 576
int virtTestMain(int argc,
                 char **argv,
E
Eric Blake 已提交
577
                 int (*func)(void))
578 579
{
    int ret;
580
    bool abs_srcdir_cleanup = false;
581
#if TEST_OOM
582 583
    int approxAlloc = 0;
    int n;
584
    char *oomStr = NULL;
585
    int oomCount;
586 587 588
    int mp = 0;
    pid_t *workers;
    int worker = 0;
589 590
#endif

E
Eric Blake 已提交
591
    abs_srcdir = getenv("abs_srcdir");
592 593 594 595
    if (!abs_srcdir) {
        abs_srcdir = getcwd(NULL, 0);
        abs_srcdir_cleanup = true;
    }
E
Eric Blake 已提交
596
    if (!abs_srcdir)
597
        return EXIT_AM_HARDFAIL;
E
Eric Blake 已提交
598

E
Eric Blake 已提交
599 600 601
    progname = last_component(argv[0]);
    if (STRPREFIX(progname, "lt-"))
        progname += 3;
E
Eric Blake 已提交
602 603
    if (argc > 1) {
        fprintf(stderr, "Usage: %s\n", argv[0]);
604 605 606 607
        fputs("effective environment variables:\n"
              "VIR_TEST_VERBOSE set to show names of individual tests\n"
              "VIR_TEST_DEBUG set to show information for debugging failures\n",
              stderr);
E
Eric Blake 已提交
608 609 610
        return EXIT_FAILURE;
    }
    fprintf(stderr, "TEST: %s\n", progname);
611

612
    if (virThreadInitialize() < 0 ||
613
        virErrorInitialize() < 0)
614
        return EXIT_FAILURE;
615

616
    virLogSetFromEnv();
617 618
    if (!getenv("LIBVIRT_DEBUG") && !virLogGetNbOutputs()) {
        if (virLogDefineOutput(virtTestLogOutput, virtTestLogClose, &testLog,
619
                               VIR_LOG_DEBUG, VIR_LOG_TO_STDERR, NULL, 0) < 0)
620
            return EXIT_FAILURE;
621
    }
622

623
#if TEST_OOM
624 625 626 627 628 629 630 631 632 633
    if ((oomStr = getenv("VIR_TEST_OOM")) != NULL) {
        if (virStrToLong_i(oomStr, NULL, 10, &oomCount) < 0)
            oomCount = 0;

        if (oomCount < 0)
            oomCount = 0;
        if (oomCount)
            testOOM = 1;
    }

634 635 636
    if (getenv("VIR_TEST_MP") != NULL) {
        mp = sysconf(_SC_NPROCESSORS_ONLN);
        fprintf(stderr, "Using %d worker processes\n", mp);
637 638 639 640
        if (VIR_ALLOC_N(workers, mp) < 0) {
            ret = EXIT_FAILURE;
            goto cleanup;
        }
641 642
    }

D
Daniel P. Berrange 已提交
643
    /* Run once to prime any static allocations & ensure it passes */
E
Eric Blake 已提交
644
    ret = (func)();
645
    if (ret != EXIT_SUCCESS)
646
        goto cleanup;
647

648
# if TEST_OOM_TRACE
649
    if (virTestGetDebug())
650
        virAllocTestHook(virtTestErrorHook, NULL);
651
# endif
652 653 654 655 656 657

    if (testOOM) {
        /* Makes next test runs quiet... */
        testOOM++;
        virSetErrorFunc(NULL, virtTestErrorFuncQuiet);

D
Daniel P. Berrange 已提交
658 659 660
        virAllocTestInit();

        /* Run again to count allocs, and ensure it passes :-) */
E
Eric Blake 已提交
661
        ret = (func)();
D
Daniel P. Berrange 已提交
662 663 664
        if (ret != EXIT_SUCCESS)
            goto cleanup;

665 666
        approxAlloc = virAllocTestCount();
        testCounter++;
667
        if (virTestGetDebug())
668 669 670 671
            fprintf(stderr, "%d) OOM...\n", testCounter);
        else
            fprintf(stderr, "%d) OOM of %d allocs ", testCounter, approxAlloc);

672
        if (mp) {
673
            size_t i;
674
            for (i = 0; i < mp; i++) {
675 676 677 678 679 680 681 682
                workers[i] = fork();
                if (workers[i] == 0) {
                    worker = i + 1;
                    break;
                }
            }
        }

683 684
        /* Run once for each alloc, failing a different one
           and validating that the test case failed */
685
        for (n = 0; n < approxAlloc && (!mp || worker); n++) {
686 687
            if (mp &&
                (n % mp) != (worker - 1))
688
                continue;
689
            if (!virTestGetDebug()) {
690 691 692 693
                if (mp)
                    fprintf(stderr, "%d", worker);
                else
                    fprintf(stderr, ".");
694 695 696 697
                fflush(stderr);
            }
            virAllocTestOOM(n+1, oomCount);

E
Eric Blake 已提交
698
            if (((func)()) != EXIT_FAILURE) {
699 700 701 702 703
                ret = EXIT_FAILURE;
                break;
            }
        }

704 705 706 707
        if (mp) {
            if (worker) {
                _exit(ret);
            } else {
708
                size_t i;
709
                for (i = 0; i < mp; i++) {
710
                    if (virProcessWait(workers[i], NULL) < 0)
711 712 713 714 715 716
                        ret = EXIT_FAILURE;
                }
                VIR_FREE(workers);
            }
        }

717
        if (virTestGetDebug())
718 719 720 721 722 723 724
            fprintf(stderr, " ... OOM of %d allocs", approxAlloc);

        if (ret == EXIT_SUCCESS)
            fprintf(stderr, " OK\n");
        else
            fprintf(stderr, " FAILED\n");
    }
725
cleanup:
726
#else
E
Eric Blake 已提交
727
    ret = (func)();
728
#endif
729

730 731
    if (abs_srcdir_cleanup)
        VIR_FREE(abs_srcdir);
732
    virResetLastError();
733
    if (!virTestGetVerbose() && ret != EXIT_AM_SKIP) {
E
Eric Blake 已提交
734 735
        if (testCounter == 0 || testCounter % 40)
            fprintf(stderr, "%*s", 40 - (testCounter % 40), "");
736 737
        fprintf(stderr, " %-3d %s\n", testCounter, ret == 0 ? "OK" : "FAIL");
    }
738
    return ret;
739
}
740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784


int virtTestClearLineRegex(const char *pattern,
                           char *str)
{
    regex_t reg;
    char *lineStart = str;
    char *lineEnd = strchr(str, '\n');

    if (regcomp(&reg, pattern, REG_EXTENDED | REG_NOSUB) != 0)
        return -1;

    while (lineStart) {
        int ret;
        if (lineEnd)
            *lineEnd = '\0';


        ret = regexec(&reg, lineStart, 0, NULL, 0);
        //fprintf(stderr, "Match %d '%s' '%s'\n", ret, lineStart, pattern);
        if (ret == 0) {
            if (lineEnd) {
                memmove(lineStart, lineEnd + 1, strlen(lineEnd+1) + 1);
                /* Don't update lineStart - just iterate again on this
                   location */
                lineEnd = strchr(lineStart, '\n');
            } else {
                *lineStart = '\0';
                lineStart = NULL;
            }
        } else {
            if (lineEnd) {
                *lineEnd = '\n';
                lineStart = lineEnd + 1;
                lineEnd = strchr(lineStart, '\n');
            } else {
                lineStart = NULL;
            }
        }
    }

    regfree(&reg);

    return 0;
}