| | vinyl-cache/bin/vinyltest/vtest2/src/vtc_main.c |
| 0 |
|
/*- |
| 1 |
|
* Copyright (c) 2008-2011 Varnish Software AS |
| 2 |
|
* All rights reserved. |
| 3 |
|
* |
| 4 |
|
* Author: Poul-Henning Kamp <phk@phk.freebsd.dk> |
| 5 |
|
* |
| 6 |
|
* SPDX-License-Identifier: BSD-2-Clause |
| 7 |
|
* |
| 8 |
|
* Redistribution and use in source and binary forms, with or without |
| 9 |
|
* modification, are permitted provided that the following conditions |
| 10 |
|
* are met: |
| 11 |
|
* 1. Redistributions of source code must retain the above copyright |
| 12 |
|
* notice, this list of conditions and the following disclaimer. |
| 13 |
|
* 2. Redistributions in binary form must reproduce the above copyright |
| 14 |
|
* notice, this list of conditions and the following disclaimer in the |
| 15 |
|
* documentation and/or other materials provided with the distribution. |
| 16 |
|
* |
| 17 |
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
| 18 |
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 19 |
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 20 |
|
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE |
| 21 |
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 22 |
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 23 |
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 24 |
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 25 |
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 26 |
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 27 |
|
* SUCH DAMAGE. |
| 28 |
|
*/ |
| 29 |
|
|
| 30 |
|
#include "config.h" |
| 31 |
|
|
| 32 |
|
#include <sys/mman.h> |
| 33 |
|
#include <sys/socket.h> |
| 34 |
|
#include <sys/stat.h> |
| 35 |
|
#include <sys/wait.h> |
| 36 |
|
|
| 37 |
|
#include <ctype.h> |
| 38 |
|
#include <dirent.h> |
| 39 |
|
#include <poll.h> |
| 40 |
|
#include <stdio.h> |
| 41 |
|
#include <stdlib.h> |
| 42 |
|
#include <string.h> |
| 43 |
|
#include <unistd.h> |
| 44 |
|
|
| 45 |
|
#include "vtc.h" |
| 46 |
|
|
| 47 |
|
#include "vev.h" |
| 48 |
|
#include "vfil.h" |
| 49 |
|
#include "vnum.h" |
| 50 |
|
#include "vrnd.h" |
| 51 |
|
#include "vsa.h" |
| 52 |
|
#include "vss.h" |
| 53 |
|
#include "vtcp.h" |
| 54 |
|
#include "vtim.h" |
| 55 |
|
#include "vct.h" |
| 56 |
|
|
| 57 |
|
static const char *argv0; |
| 58 |
|
|
| 59 |
|
struct buf { |
| 60 |
|
unsigned magic; |
| 61 |
|
#define BUF_MAGIC 0x39d1258a |
| 62 |
|
VTAILQ_ENTRY(buf) list; |
| 63 |
|
char *buf; |
| 64 |
|
struct vsb *diag; |
| 65 |
|
size_t bufsiz; |
| 66 |
|
}; |
| 67 |
|
|
| 68 |
|
static VTAILQ_HEAD(, buf) free_bufs = VTAILQ_HEAD_INITIALIZER(free_bufs); |
| 69 |
|
|
| 70 |
|
struct vtc_tst { |
| 71 |
|
unsigned magic; |
| 72 |
|
#define TST_MAGIC 0x618d8b88 |
| 73 |
|
VTAILQ_ENTRY(vtc_tst) list; |
| 74 |
|
const char *filename; |
| 75 |
|
char *script; |
| 76 |
|
unsigned ntodo; |
| 77 |
|
unsigned nwait; |
| 78 |
|
}; |
| 79 |
|
|
| 80 |
|
struct vtc_job { |
| 81 |
|
unsigned magic; |
| 82 |
|
#define JOB_MAGIC 0x1b5fc419 |
| 83 |
|
struct vtc_tst *tst; |
| 84 |
|
pid_t child; |
| 85 |
|
struct vev *ev; |
| 86 |
|
struct vev *evt; |
| 87 |
|
struct buf *bp; |
| 88 |
|
char *tmpdir; |
| 89 |
|
double t0; |
| 90 |
|
int killed; |
| 91 |
|
}; |
| 92 |
|
|
| 93 |
|
|
| 94 |
|
int iflg = 0; |
| 95 |
|
vtim_dur vtc_maxdur = 60; |
| 96 |
|
static unsigned vtc_bufsiz = 1024 * 1024; |
| 97 |
|
|
| 98 |
|
static VTAILQ_HEAD(, vtc_tst) tst_head = VTAILQ_HEAD_INITIALIZER(tst_head); |
| 99 |
|
static struct vev_root *vb; |
| 100 |
|
static int njob = 0; |
| 101 |
|
static int npar = 1; /* Number of parallel tests */ |
| 102 |
|
static int vtc_continue; /* Continue on error */ |
| 103 |
|
static int vtc_verbosity = 1; /* Verbosity Level */ |
| 104 |
|
static int vtc_good; |
| 105 |
|
static int vtc_fail; |
| 106 |
|
static int vtc_skip; |
| 107 |
|
static int vtc_use_cleaner = 0; |
| 108 |
|
static int vtc_ntest = 1; /* Run tests this many times */ |
| 109 |
|
static char *tmppath; |
| 110 |
|
static char *cwd = NULL; |
| 111 |
|
char *vmod_path = NULL; |
| 112 |
|
struct vsb *params_vsb = NULL; |
| 113 |
|
int leave_temp; |
| 114 |
|
static struct vsb *cbvsb; |
| 115 |
|
static int bad_backend_fd; |
| 116 |
|
|
| 117 |
|
static int cleaner_fd = -1; |
| 118 |
|
static pid_t cleaner_pid; |
| 119 |
|
const char *default_listen_addr; |
| 120 |
|
|
| 121 |
|
/********************************************************************** |
| 122 |
|
* autocrap test-driver command arguments |
| 123 |
|
*/ |
| 124 |
|
|
| 125 |
|
#define TDARGS(MACRO) \ |
| 126 |
|
MACRO("--test-name", td_test_name) \ |
| 127 |
|
MACRO("--log-file", td_log_file) \ |
| 128 |
|
MACRO("--trs-file", td_trs_file) \ |
| 129 |
|
MACRO("--color-tests", td_color_tests) \ |
| 130 |
|
MACRO("--collect_skipped_logs", td_collect_skipped_logs) \ |
| 131 |
|
MACRO("--expect-failure", td_expect_failure) \ |
| 132 |
|
MACRO("--enable-hard-errors", td_enable_hard_errors) |
| 133 |
|
|
| 134 |
|
#define TDVAR(name, dst) static const char *dst; |
| 135 |
|
TDARGS(TDVAR) |
| 136 |
|
#undef TDVAR |
| 137 |
|
|
| 138 |
|
/**********************************************************************/ |
| 139 |
|
|
| 140 |
|
static struct buf * |
| 141 |
|
get_buf(void) |
| 142 |
|
{ |
| 143 |
5455 |
struct buf *bp; |
| 144 |
|
|
| 145 |
|
bp = VTAILQ_FIRST(&free_bufs); |
| 146 |
|
CHECK_OBJ_ORNULL(bp, BUF_MAGIC); |
| 147 |
5455 |
if (bp != NULL) { |
| 148 |
5455 |
VTAILQ_REMOVE(&free_bufs, bp, list); |
| 149 |
5455 |
VSB_clear(bp->diag); |
| 150 |
250 |
} else { |
| 151 |
250 |
ALLOC_OBJ(bp, BUF_MAGIC); |
| 152 |
250 |
AN(bp); |
| 153 |
5205 |
bp->bufsiz = vtc_bufsiz; |
| 154 |
5205 |
bp->buf = mmap(NULL, bp->bufsiz, PROT_READ|PROT_WRITE, |
| 155 |
5205 |
MAP_ANON | MAP_SHARED, -1, 0); |
| 156 |
5205 |
assert(bp->buf != MAP_FAILED); |
| 157 |
|
bp->diag = VSB_new_auto(); |
| 158 |
5205 |
AN(bp->diag); |
| 159 |
5205 |
} |
| 160 |
5205 |
memset(bp->buf, 0, bp->bufsiz); |
| 161 |
|
return (bp); |
| 162 |
5455 |
} |
| 163 |
5455 |
|
| 164 |
|
static void |
| 165 |
|
rel_buf(struct buf **bp) |
| 166 |
|
{ |
| 167 |
5455 |
CHECK_OBJ_NOTNULL(*bp, BUF_MAGIC); |
| 168 |
|
|
| 169 |
5455 |
VTAILQ_INSERT_HEAD(&free_bufs, (*bp), list); |
| 170 |
|
*bp = NULL; |
| 171 |
5455 |
} |
| 172 |
5455 |
|
| 173 |
5455 |
/********************************************************************** |
| 174 |
|
* Parse a -D option argument into a name/val pair, and insert |
| 175 |
|
* into extmacro list |
| 176 |
|
*/ |
| 177 |
|
|
| 178 |
|
static int |
| 179 |
|
parse_D_opt(char *arg) |
| 180 |
|
{ |
| 181 |
10 |
char *p, *q; |
| 182 |
|
|
| 183 |
|
p = arg; |
| 184 |
|
q = strchr(p, '='); |
| 185 |
10 |
if (!q) |
| 186 |
10 |
return (0); |
| 187 |
10 |
*q++ = '\0'; |
| 188 |
0 |
extmacro_def(p, NULL, "%s", q); |
| 189 |
10 |
|
| 190 |
10 |
return (1); |
| 191 |
|
} |
| 192 |
10 |
|
| 193 |
10 |
/********************************************************************** |
| 194 |
|
* Print usage |
| 195 |
|
*/ |
| 196 |
|
|
| 197 |
|
static void v_noreturn_ |
| 198 |
|
usage(void) |
| 199 |
|
{ |
| 200 |
25 |
fprintf(stderr, "usage: %s [options] file ...\n", argv0); |
| 201 |
|
#define FMT " %-28s # %s\n" |
| 202 |
25 |
fprintf(stderr, FMT, "-b size", |
| 203 |
|
"Set internal buffer size (default: 1M)"); |
| 204 |
25 |
fprintf(stderr, FMT, "-C", "Use cleaner subprocess"); |
| 205 |
|
fprintf(stderr, FMT, "-D name=val", "Define macro"); |
| 206 |
25 |
fprintf(stderr, FMT, "-E extension_shlib", "Load extension"); |
| 207 |
25 |
fprintf(stderr, FMT, "-i", "Find varnish binaries in build tree"); |
| 208 |
25 |
fprintf(stderr, FMT, "-j jobs", "Run this many tests in parallel"); |
| 209 |
25 |
fprintf(stderr, FMT, "-k", "Continue on test failure"); |
| 210 |
25 |
fprintf(stderr, FMT, "-L", "Always leave temporary vtc.*"); |
| 211 |
25 |
fprintf(stderr, FMT, "-l", "Leave temporary vtc.* if test fails"); |
| 212 |
25 |
fprintf(stderr, FMT, "-n iterations", "Run tests this many times"); |
| 213 |
25 |
fprintf(stderr, FMT, "-p name=val", "Pass a varnishd parameter"); |
| 214 |
25 |
fprintf(stderr, FMT, "-q", "Quiet mode: report only failures"); |
| 215 |
25 |
fprintf(stderr, FMT, "-t duration", "Time tests out after this long"); |
| 216 |
25 |
fprintf(stderr, FMT, "-v", "Verbose mode: always report test log"); |
| 217 |
25 |
exit(1); |
| 218 |
25 |
} |
| 219 |
25 |
|
| 220 |
|
/********************************************************************** |
| 221 |
|
* When running many tests, cleaning the tmpdir with "rm -rf" becomes |
| 222 |
|
* chore which limits our performance. |
| 223 |
|
* When the number of tests are above 100, we spawn a child-process |
| 224 |
|
* to do that for us. |
| 225 |
|
*/ |
| 226 |
|
|
| 227 |
|
static void |
| 228 |
|
cleaner_do(const char *dirname) |
| 229 |
|
{ |
| 230 |
5455 |
char buf[BUFSIZ]; |
| 231 |
|
|
| 232 |
|
AZ(memcmp(dirname, tmppath, strlen(tmppath))); |
| 233 |
|
if (cleaner_pid > 0) { |
| 234 |
5455 |
bprintf(buf, "%s\n", dirname); |
| 235 |
5455 |
assert(write(cleaner_fd, buf, strlen(buf)) == strlen(buf)); |
| 236 |
275 |
return; |
| 237 |
275 |
} |
| 238 |
275 |
bprintf(buf, "exec /bin/rm -rf %s\n", dirname); |
| 239 |
|
AZ(system(buf)); |
| 240 |
5180 |
} |
| 241 |
5180 |
|
| 242 |
5455 |
static void |
| 243 |
|
cleaner_setup(void) |
| 244 |
|
{ |
| 245 |
10 |
int p[2], st; |
| 246 |
|
char buf[BUFSIZ]; |
| 247 |
|
char *q; |
| 248 |
|
pid_t pp; |
| 249 |
|
|
| 250 |
|
AZ(pipe(p)); |
| 251 |
|
assert(p[0] > STDERR_FILENO); |
| 252 |
10 |
assert(p[1] > STDERR_FILENO); |
| 253 |
10 |
cleaner_pid = fork(); |
| 254 |
10 |
assert(cleaner_pid >= 0); |
| 255 |
10 |
if (cleaner_pid == 0) { |
| 256 |
10 |
closefd(&p[1]); |
| 257 |
20 |
(void)!nice(1); /* Not important */ |
| 258 |
10 |
setbuf(stdin, NULL); |
| 259 |
10 |
AZ(dup2(p[0], STDIN_FILENO)); |
| 260 |
10 |
while (fgets(buf, sizeof buf, stdin)) { |
| 261 |
10 |
AZ(memcmp(buf, tmppath, strlen(tmppath))); |
| 262 |
285 |
q = buf + strlen(buf); |
| 263 |
275 |
assert(q > buf); |
| 264 |
275 |
assert(q[-1] == '\n'); |
| 265 |
275 |
q[-1] = '\0'; |
| 266 |
275 |
|
| 267 |
275 |
/* Dont expend a shell on running /bin/rm */ |
| 268 |
|
pp = fork(); |
| 269 |
|
assert(pp >= 0); |
| 270 |
275 |
if (pp == 0) |
| 271 |
275 |
exit(execlp( |
| 272 |
550 |
"rm", "rm", "-rf", buf, (char*)0)); |
| 273 |
275 |
assert(waitpid(pp, &st, 0) == pp); |
| 274 |
275 |
AZ(st); |
| 275 |
275 |
} |
| 276 |
275 |
exit(0); |
| 277 |
|
} |
| 278 |
10 |
closefd(&p[0]); |
| 279 |
|
cleaner_fd = p[1]; |
| 280 |
10 |
} |
| 281 |
10 |
|
| 282 |
10 |
static void |
| 283 |
|
cleaner_neuter(void) |
| 284 |
|
{ |
| 285 |
5455 |
if (cleaner_pid > 0) |
| 286 |
|
closefd(&cleaner_fd); |
| 287 |
5455 |
} |
| 288 |
275 |
|
| 289 |
5455 |
static void |
| 290 |
|
cleaner_finish(void) |
| 291 |
|
{ |
| 292 |
5185 |
int st; |
| 293 |
|
|
| 294 |
|
if (cleaner_pid > 0) { |
| 295 |
|
closefd(&cleaner_fd); |
| 296 |
5185 |
assert(waitpid(cleaner_pid, &st, 0) == cleaner_pid); |
| 297 |
10 |
AZ(st); |
| 298 |
10 |
} |
| 299 |
10 |
} |
| 300 |
10 |
|
| 301 |
5185 |
/********************************************************************** |
| 302 |
|
* CallBack |
| 303 |
|
*/ |
| 304 |
|
|
| 305 |
|
static int |
| 306 |
|
tst_cb(const struct vev *ve, int what) |
| 307 |
|
{ |
| 308 |
|
struct vtc_job *jp; |
| 309 |
|
char buf[BUFSIZ]; |
| 310 |
|
int ecode; |
| 311 |
|
int i, stx; |
| 312 |
|
pid_t px; |
| 313 |
|
double t; |
| 314 |
|
FILE *f; |
| 315 |
|
char *p; |
| 316 |
|
|
| 317 |
|
CAST_OBJ_NOTNULL(jp, ve->priv, JOB_MAGIC); |
| 318 |
|
CHECK_OBJ_NOTNULL(jp->tst, TST_MAGIC); |
| 319 |
5500 |
|
| 320 |
|
// printf("CB %p %s %d\n", ve, jp->tst->filename, what); |
| 321 |
|
if (what == 0) { |
| 322 |
|
jp->killed = 1; |
| 323 |
|
AZ(kill(-jp->child, SIGKILL)); /* XXX: Timeout */ |
| 324 |
|
} else { |
| 325 |
|
assert(what & (VEV__RD | VEV__HUP)); |
| 326 |
|
} |
| 327 |
|
|
| 328 |
|
*buf = '\0'; |
| 329 |
|
i = read(ve->fd, buf, sizeof buf); |
| 330 |
5500 |
if (i > 0) |
| 331 |
5500 |
VSB_bcat(jp->bp->diag, buf, i); |
| 332 |
|
if (i == 0) { |
| 333 |
|
|
| 334 |
5500 |
njob--; |
| 335 |
0 |
px = wait4(jp->child, &stx, 0, NULL); |
| 336 |
0 |
assert(px == jp->child); |
| 337 |
0 |
t = VTIM_mono() - jp->t0; |
| 338 |
5500 |
AZ(close(ve->fd)); |
| 339 |
|
|
| 340 |
|
ecode = WTERMSIG(stx); |
| 341 |
5500 |
if (ecode == 0) |
| 342 |
5500 |
ecode = WEXITSTATUS(stx); |
| 343 |
5500 |
|
| 344 |
45 |
AZ(VSB_finish(jp->bp->diag)); |
| 345 |
5500 |
|
| 346 |
|
VSB_clear(cbvsb); |
| 347 |
5455 |
VSB_cat(cbvsb, jp->bp->buf); |
| 348 |
5455 |
p = strchr(jp->bp->buf, '\0'); |
| 349 |
5455 |
if (p > jp->bp->buf && p[-1] != '\n') |
| 350 |
5455 |
VSB_putc(cbvsb, '\n'); |
| 351 |
5455 |
VSB_quote_pfx(cbvsb, "* diag 0.0 ", |
| 352 |
|
VSB_data(jp->bp->diag), -1, VSB_QUOTE_NONL); |
| 353 |
5455 |
AZ(VSB_finish(cbvsb)); |
| 354 |
5455 |
rel_buf(&jp->bp); |
| 355 |
5455 |
|
| 356 |
|
if ((ecode > 1 && vtc_verbosity) || vtc_verbosity > 1) |
| 357 |
5455 |
printf("%s", VSB_data(cbvsb)); |
| 358 |
|
|
| 359 |
5455 |
if (!ecode) |
| 360 |
5455 |
vtc_good++; |
| 361 |
5455 |
else if (ecode == 1) |
| 362 |
5455 |
vtc_skip++; |
| 363 |
0 |
else |
| 364 |
10910 |
vtc_fail++; |
| 365 |
5455 |
|
| 366 |
5455 |
if (leave_temp == 0 || (leave_temp == 1 && ecode <= 1)) { |
| 367 |
5455 |
cleaner_do(jp->tmpdir); |
| 368 |
|
} else { |
| 369 |
5455 |
bprintf(buf, "%s/LOG", jp->tmpdir); |
| 370 |
90 |
f = fopen(buf, "w"); |
| 371 |
|
AN(f); |
| 372 |
5455 |
(void)fprintf(f, "%s\n", VSB_data(cbvsb)); |
| 373 |
5325 |
AZ(fclose(f)); |
| 374 |
130 |
} |
| 375 |
115 |
free(jp->tmpdir); |
| 376 |
|
|
| 377 |
15 |
if (td_log_file != NULL) { |
| 378 |
|
f = fopen(td_log_file, "w"); |
| 379 |
5455 |
AN(f); |
| 380 |
5455 |
(void)fprintf(f, "%s\n", VSB_data(cbvsb)); |
| 381 |
5455 |
AZ(fclose(f)); |
| 382 |
0 |
} |
| 383 |
0 |
if (td_trs_file != NULL) { |
| 384 |
0 |
f = fopen(td_trs_file, "w"); |
| 385 |
0 |
AN(f); |
| 386 |
0 |
if (jp->killed || ecode > 1) { |
| 387 |
|
fprintf(f, ":test-result: FAIL\n"); |
| 388 |
5455 |
fprintf(f, ":copy-in-global-log: yes\n"); |
| 389 |
|
} else if (ecode) { |
| 390 |
5455 |
fprintf(f, ":test-result: SKIP\n"); |
| 391 |
5130 |
fprintf(f, ":copy-in-global-log: yes\n"); |
| 392 |
5130 |
} else { |
| 393 |
5130 |
fprintf(f, ":test-result: PASS\n"); |
| 394 |
5130 |
fprintf(f, ":copy-in-global-log: no\n"); |
| 395 |
5130 |
} |
| 396 |
5455 |
AZ(fclose(f)); |
| 397 |
5130 |
} |
| 398 |
5130 |
|
| 399 |
5130 |
if (jp->killed) |
| 400 |
0 |
printf("# top TEST %s TIMED OUT (kill -9)\n", |
| 401 |
0 |
jp->tst->filename); |
| 402 |
0 |
if (ecode > 1) { |
| 403 |
0 |
printf("# top TEST %s FAILED (%.3f)", |
| 404 |
0 |
jp->tst->filename, t); |
| 405 |
5130 |
if (WIFSIGNALED(stx)) |
| 406 |
85 |
printf(" signal=%d\n", WTERMSIG(stx)); |
| 407 |
85 |
else if (WIFEXITED(stx)) |
| 408 |
85 |
printf(" exit=%d\n", WEXITSTATUS(stx)); |
| 409 |
85 |
if (!vtc_continue && td_trs_file == NULL) { |
| 410 |
85 |
/* XXX kill -9 other jobs ? */ |
| 411 |
85 |
exit(2); |
| 412 |
5045 |
} |
| 413 |
5045 |
} else if (vtc_verbosity) { |
| 414 |
5045 |
printf("# top TEST %s %s (%.3f)\n", |
| 415 |
5045 |
jp->tst->filename, |
| 416 |
5045 |
ecode ? "skipped" : "passed", t); |
| 417 |
|
} |
| 418 |
5130 |
if (jp->evt != NULL) { |
| 419 |
5130 |
VEV_Stop(vb, jp->evt); |
| 420 |
325 |
free(jp->evt); |
| 421 |
0 |
} |
| 422 |
|
jp->tst->nwait--; |
| 423 |
0 |
if (jp->tst->nwait == 0) { |
| 424 |
0 |
free(jp->tst->script); |
| 425 |
325 |
FREE_OBJ(jp->tst); |
| 426 |
15 |
} |
| 427 |
15 |
FREE_OBJ(jp); |
| 428 |
15 |
return (1); |
| 429 |
0 |
} |
| 430 |
15 |
return (0); |
| 431 |
15 |
} |
| 432 |
15 |
|
| 433 |
|
/********************************************************************** |
| 434 |
15 |
* Start Test |
| 435 |
|
*/ |
| 436 |
310 |
|
| 437 |
300 |
static void |
| 438 |
300 |
start_test(void) |
| 439 |
300 |
{ |
| 440 |
300 |
struct vtc_tst *tp; |
| 441 |
|
int p[2], retval; |
| 442 |
5440 |
struct vtc_job *jp; |
| 443 |
5440 |
char tmpdir[PATH_MAX]; |
| 444 |
5440 |
char default_n[PATH_MAX]; |
| 445 |
5440 |
|
| 446 |
5485 |
ALLOC_OBJ(jp, JOB_MAGIC); |
| 447 |
5485 |
AN(jp); |
| 448 |
5395 |
|
| 449 |
5395 |
jp->bp = get_buf(); |
| 450 |
5395 |
|
| 451 |
5440 |
bprintf(tmpdir, "%s/vtc.%d.%08x", tmppath, (int)getpid(), |
| 452 |
5440 |
(unsigned)random()); |
| 453 |
|
AZ(mkdir(tmpdir, 0755)); |
| 454 |
45 |
|
| 455 |
5485 |
bprintf(default_n, "%s/default_n", tmpdir); |
| 456 |
|
|
| 457 |
|
AZ(setenv("VARNISH_DEFAULT_N", default_n, 1)); |
| 458 |
|
|
| 459 |
|
tp = VTAILQ_FIRST(&tst_head); |
| 460 |
|
CHECK_OBJ_NOTNULL(tp, TST_MAGIC); |
| 461 |
|
AN(tp->ntodo); |
| 462 |
5455 |
tp->ntodo--; |
| 463 |
|
VTAILQ_REMOVE(&tst_head, tp, list); |
| 464 |
|
if (tp->ntodo > 0) |
| 465 |
|
VTAILQ_INSERT_TAIL(&tst_head, tp, list); |
| 466 |
|
|
| 467 |
|
jp->tst = tp; |
| 468 |
|
REPLACE(jp->tmpdir, tmpdir); |
| 469 |
|
|
| 470 |
5455 |
AZ(pipe(p)); |
| 471 |
5455 |
assert(p[0] > STDERR_FILENO); |
| 472 |
|
assert(p[1] > STDERR_FILENO); |
| 473 |
5455 |
jp->t0 = VTIM_mono(); |
| 474 |
|
jp->child = fork(); |
| 475 |
5455 |
assert(jp->child >= 0); |
| 476 |
|
if (jp->child == 0) { |
| 477 |
5455 |
cleaner_neuter(); // Too dangerous to have around |
| 478 |
|
AZ(setpgid(getpid(), 0)); |
| 479 |
5455 |
VFIL_null_fd(STDIN_FILENO); |
| 480 |
|
assert(dup2(p[1], STDOUT_FILENO) == STDOUT_FILENO); |
| 481 |
5455 |
assert(dup2(p[1], STDERR_FILENO) == STDERR_FILENO); |
| 482 |
|
retval = exec_file(jp->tst->filename, jp->tst->script, |
| 483 |
5455 |
jp->tmpdir, jp->bp->buf, jp->bp->bufsiz); |
| 484 |
5455 |
exit(retval); |
| 485 |
5455 |
} |
| 486 |
5455 |
closefd(&p[1]); |
| 487 |
5455 |
|
| 488 |
5455 |
jp->ev = VEV_Alloc(); |
| 489 |
45 |
AN(jp->ev); |
| 490 |
|
jp->ev->fd_flags = VEV__RD | VEV__HUP | VEV__ERR; |
| 491 |
5455 |
jp->ev->fd = p[0]; |
| 492 |
5455 |
jp->ev->priv = jp; |
| 493 |
|
jp->ev->callback = tst_cb; |
| 494 |
5455 |
AZ(VEV_Start(vb, jp->ev)); |
| 495 |
5455 |
|
| 496 |
5455 |
jp->evt = VEV_Alloc(); |
| 497 |
5455 |
AN(jp->evt); |
| 498 |
5455 |
jp->evt->fd = -1; |
| 499 |
5455 |
jp->evt->timeout = vtc_maxdur; |
| 500 |
10910 |
jp->evt->priv = jp; |
| 501 |
5455 |
jp->evt->callback = tst_cb; |
| 502 |
5455 |
AZ(VEV_Start(vb, jp->evt)); |
| 503 |
5455 |
} |
| 504 |
5455 |
|
| 505 |
5455 |
/********************************************************************** |
| 506 |
10910 |
* i-mode = "we're inside a src-tree" |
| 507 |
5455 |
* |
| 508 |
5455 |
* Find the abs path to top of source dir from Makefile, if that |
| 509 |
|
* fails, fall back on "../../" |
| 510 |
5455 |
* |
| 511 |
|
* Set PATH to all programs build directories |
| 512 |
5455 |
* Set vmod_path to all vmods build directories |
| 513 |
5455 |
* |
| 514 |
5455 |
*/ |
| 515 |
5455 |
|
| 516 |
5455 |
static char * |
| 517 |
5455 |
top_dir(const char *makefile, const char *top_var) |
| 518 |
5455 |
{ |
| 519 |
|
const char *b, *e; |
| 520 |
5455 |
char *var; |
| 521 |
5455 |
|
| 522 |
5455 |
AN(makefile); |
| 523 |
5455 |
AN(top_var); |
| 524 |
5455 |
assert(*top_var == '\n'); |
| 525 |
5455 |
|
| 526 |
5455 |
b = strstr(makefile, top_var); |
| 527 |
5455 |
top_var++; |
| 528 |
|
|
| 529 |
|
if (b == NULL) { |
| 530 |
|
fprintf(stderr, "could not find '%s' in Makefile\n", top_var); |
| 531 |
|
return (NULL); |
| 532 |
|
} |
| 533 |
|
|
| 534 |
|
e = strchr(b + 1, '\n'); |
| 535 |
|
if (e == NULL) { |
| 536 |
|
fprintf(stderr, "No NL after '%s' in Makefile\n", top_var); |
| 537 |
|
return (NULL); |
| 538 |
|
} |
| 539 |
|
|
| 540 |
|
b = memchr(b, '/', e - b); |
| 541 |
10270 |
if (b == NULL) { |
| 542 |
|
fprintf(stderr, "No '/' after '%s' in Makefile\n", top_var); |
| 543 |
|
return (NULL); |
| 544 |
|
} |
| 545 |
|
var = strndup(b, e - b); |
| 546 |
10270 |
AN(var); |
| 547 |
10270 |
return (var); |
| 548 |
10270 |
} |
| 549 |
|
|
| 550 |
10270 |
static void |
| 551 |
10270 |
build_path(const char *topdir, const char *subdir, |
| 552 |
|
const char *pfx, const char *sfx, struct vsb *vsb) |
| 553 |
10270 |
{ |
| 554 |
0 |
char buf[PATH_MAX]; |
| 555 |
0 |
DIR *dir; |
| 556 |
|
struct dirent *de; |
| 557 |
|
struct stat st; |
| 558 |
10270 |
const char *topsep = ""; |
| 559 |
10270 |
|
| 560 |
0 |
if (*subdir != '\0') |
| 561 |
0 |
topsep = "/"; |
| 562 |
|
bprintf(buf, "%s%s%s/", topdir, topsep, subdir); |
| 563 |
|
dir = opendir(buf); |
| 564 |
10270 |
XXXAN(dir); |
| 565 |
10270 |
while (1) { |
| 566 |
0 |
de = readdir(dir); |
| 567 |
0 |
if (de == NULL) |
| 568 |
|
break; |
| 569 |
10270 |
if (strncmp(de->d_name, pfx, strlen(pfx))) |
| 570 |
10270 |
continue; |
| 571 |
10270 |
bprintf(buf, "%s%s%s/%s", topdir, topsep, subdir, de->d_name); |
| 572 |
10270 |
if (!stat(buf, &st) && S_ISDIR(st.st_mode)) { |
| 573 |
|
VSB_cat(vsb, buf); |
| 574 |
|
VSB_cat(vsb, sfx); |
| 575 |
15405 |
VSB_cat(vsb, ":"); |
| 576 |
|
} |
| 577 |
|
} |
| 578 |
|
AZ(closedir(dir)); |
| 579 |
|
} |
| 580 |
|
|
| 581 |
|
static void |
| 582 |
15405 |
i_mode(void) |
| 583 |
|
{ |
| 584 |
15405 |
struct vsb *vsb; |
| 585 |
10270 |
char *p, *topbuild, *topsrc; |
| 586 |
15405 |
|
| 587 |
15405 |
/* |
| 588 |
15405 |
* This code has a rather intimate knowledge of auto* generated |
| 589 |
66755 |
* makefiles. |
| 590 |
1268360 |
*/ |
| 591 |
1268360 |
|
| 592 |
15405 |
vsb = VSB_new_auto(); |
| 593 |
1252955 |
AN(vsb); |
| 594 |
1201605 |
|
| 595 |
51350 |
p = VFIL_readfile(NULL, "Makefile", NULL); |
| 596 |
51350 |
if (p == NULL) { |
| 597 |
51350 |
fprintf(stderr, "No Makefile to search for -i flag.\n"); |
| 598 |
51350 |
exit(2); |
| 599 |
51350 |
} |
| 600 |
51350 |
|
| 601 |
|
topbuild = top_dir(p, "\nabs_top_builddir"); |
| 602 |
15405 |
topsrc = top_dir(p, "\nabs_top_srcdir"); |
| 603 |
15405 |
free(p); |
| 604 |
|
if (topbuild == NULL || topsrc == NULL) { |
| 605 |
|
free(topbuild); |
| 606 |
5135 |
free(topsrc); |
| 607 |
|
exit(2); |
| 608 |
|
} |
| 609 |
|
extmacro_def("topbuild", NULL, "%s", topbuild); |
| 610 |
|
extmacro_def("topsrc", NULL, "%s", topsrc); |
| 611 |
|
|
| 612 |
|
/* |
| 613 |
|
* Build $PATH which can find all programs in the build tree |
| 614 |
|
*/ |
| 615 |
|
VSB_clear(vsb); |
| 616 |
5135 |
VSB_cat(vsb, "PATH="); |
| 617 |
5135 |
#ifdef VTEST_WITH_VTC_VARNISH |
| 618 |
|
build_path(topbuild, "bin", "varnish", "", vsb); |
| 619 |
5135 |
#endif |
| 620 |
5135 |
|
| 621 |
0 |
#ifdef VTEST_WITH_VTC_VINYL |
| 622 |
0 |
build_path(topbuild, "bin", "vinyl", "", vsb); |
| 623 |
|
#endif |
| 624 |
|
|
| 625 |
5135 |
#ifdef WITH_CONTRIB |
| 626 |
5135 |
VSB_putc(vsb, ':'); |
| 627 |
5135 |
build_path(topsrc, "", "contrib", "", vsb); |
| 628 |
5135 |
#endif |
| 629 |
0 |
VSB_printf(vsb, ":%s", getenv("PATH")); |
| 630 |
0 |
AZ(VSB_finish(vsb)); |
| 631 |
0 |
AZ(putenv(strdup(VSB_data(vsb)))); |
| 632 |
|
|
| 633 |
5135 |
/* |
| 634 |
5135 |
* Build vmod_path which can find all VMODs in the build tree |
| 635 |
|
*/ |
| 636 |
|
|
| 637 |
|
VSB_clear(vsb); |
| 638 |
|
build_path(topbuild, "vmod", ".libs", "", vsb); |
| 639 |
5135 |
AZ(VSB_finish(vsb)); |
| 640 |
5135 |
vmod_path = strdup(VSB_data(vsb)); |
| 641 |
|
AN(vmod_path); |
| 642 |
|
|
| 643 |
|
free(topbuild); |
| 644 |
|
free(topsrc); |
| 645 |
|
VSB_destroy(&vsb); |
| 646 |
5135 |
|
| 647 |
|
/* |
| 648 |
|
* strict jemalloc checking |
| 649 |
|
*/ |
| 650 |
5135 |
AZ(putenv(strdup("MALLOC_CONF=abort:true,junk:true"))); |
| 651 |
5135 |
} |
| 652 |
|
|
| 653 |
5135 |
/********************************************************************** |
| 654 |
5135 |
* Figure out what IP related magic |
| 655 |
5135 |
*/ |
| 656 |
|
|
| 657 |
|
static void |
| 658 |
|
ip_magic(void) |
| 659 |
|
{ |
| 660 |
|
const struct suckaddr *sa; |
| 661 |
5135 |
char abuf[VTCP_ADDRBUFSIZE]; |
| 662 |
5135 |
char pbuf[VTCP_PORTBUFSIZE]; |
| 663 |
5135 |
char *s; |
| 664 |
5135 |
|
| 665 |
5135 |
/* |
| 666 |
|
* In FreeBSD jails localhost/127.0.0.1 becomes the jails IP# |
| 667 |
5135 |
* XXX: IPv6-only hosts would have similar issue, but it is not |
| 668 |
5135 |
* XXX: obvious how to cope. Ideally "127.0.0.1" would be |
| 669 |
5135 |
* XXX: "localhost", but that doesn't work out of the box. |
| 670 |
|
* XXX: Things like "prefer_ipv6" parameter complicates things. |
| 671 |
|
*/ |
| 672 |
|
sa = VSS_ResolveOne(NULL, "127.0.0.1", "0", 0, SOCK_STREAM, 0); |
| 673 |
|
AN(sa); |
| 674 |
5135 |
bad_backend_fd = VTCP_bind(sa, NULL); |
| 675 |
5135 |
if (bad_backend_fd < 0) { |
| 676 |
|
VSA_free(&sa); |
| 677 |
|
sa = VSS_ResolveFirst(NULL, "localhost", "0", 0, SOCK_STREAM, 0); |
| 678 |
|
AN(sa); |
| 679 |
|
bad_backend_fd = VTCP_bind(sa, NULL); |
| 680 |
|
} |
| 681 |
|
assert(bad_backend_fd >= 0); |
| 682 |
5200 |
VTCP_myname(bad_backend_fd, abuf, sizeof abuf, pbuf, sizeof(pbuf)); |
| 683 |
|
extmacro_def("localhost", NULL, "%s", abuf); |
| 684 |
|
s = strdup(abuf); |
| 685 |
|
AN(s); |
| 686 |
|
|
| 687 |
|
#if defined (__APPLE__) |
| 688 |
|
/* |
| 689 |
|
* In macOS a bound socket that is not listening will timeout |
| 690 |
|
* instead of refusing the connection so close it and hope |
| 691 |
|
* for the best. |
| 692 |
|
*/ |
| 693 |
|
VTCP_close(&bad_backend_fd); |
| 694 |
|
#endif |
| 695 |
|
|
| 696 |
5200 |
/* Expose a backend that is forever down. */ |
| 697 |
5200 |
if (VSA_Get_Proto(sa) == AF_INET) |
| 698 |
5200 |
extmacro_def("bad_backend", NULL, "%s:%s", abuf, pbuf); |
| 699 |
5200 |
else |
| 700 |
0 |
extmacro_def("bad_backend", NULL, "[%s]:%s", abuf, pbuf); |
| 701 |
0 |
|
| 702 |
0 |
/* our default bind/listen address */ |
| 703 |
0 |
if (VSA_Get_Proto(sa) == AF_INET) |
| 704 |
0 |
bprintf(abuf, "%s:0", s); |
| 705 |
5200 |
else |
| 706 |
5200 |
bprintf(abuf, "[%s]:0", s); |
| 707 |
5200 |
free(s); |
| 708 |
5200 |
|
| 709 |
5200 |
extmacro_def("listen_addr", NULL, "%s", abuf); |
| 710 |
|
default_listen_addr = strdup(abuf); |
| 711 |
|
AN(default_listen_addr); |
| 712 |
|
VSA_free(&sa); |
| 713 |
|
|
| 714 |
|
/* |
| 715 |
|
* We need an IP number which will not respond, ever, and that is a |
| 716 |
|
* lot harder than it sounds. This IP# is from RFC5737 and a |
| 717 |
|
* C-class broadcast at that. |
| 718 |
|
* If tests involving ${bad_ip} fails and you run linux, you should |
| 719 |
|
* check your /proc/sys/net/ipv4/ip_nonlocal_bind setting. |
| 720 |
|
*/ |
| 721 |
5200 |
|
| 722 |
5200 |
extmacro_def("bad_ip", NULL, "%s", "192.0.2.255"); |
| 723 |
|
} |
| 724 |
0 |
|
| 725 |
|
/********************************************************************** |
| 726 |
|
* Macros |
| 727 |
5200 |
*/ |
| 728 |
5200 |
|
| 729 |
|
static char * v_matchproto_(macro_f) |
| 730 |
0 |
macro_func_date(int argc, char *const *argv, const char **err) |
| 731 |
5200 |
{ |
| 732 |
|
double t; |
| 733 |
5200 |
char *s; |
| 734 |
5200 |
|
| 735 |
5200 |
assert(argc >= 2); |
| 736 |
5200 |
AN(argv); |
| 737 |
|
AN(err); |
| 738 |
|
|
| 739 |
|
if (argc > 2) { |
| 740 |
|
*err = "macro does not take arguments"; |
| 741 |
|
return (NULL); |
| 742 |
|
} |
| 743 |
|
|
| 744 |
|
t = VTIM_real(); |
| 745 |
|
s = malloc(VTIM_FORMAT_SIZE); |
| 746 |
5200 |
AN(s); |
| 747 |
5200 |
VTIM_format(t, s); |
| 748 |
|
return (s); |
| 749 |
|
} |
| 750 |
|
|
| 751 |
|
static char * |
| 752 |
|
macro_func_string_repeat(int argc, char *const *argv, const char **err) |
| 753 |
|
{ |
| 754 |
11516 |
struct vsb vsb[1]; |
| 755 |
|
const char *p; |
| 756 |
|
char *res; |
| 757 |
|
size_t l; |
| 758 |
|
int i; |
| 759 |
11516 |
|
| 760 |
11516 |
if (argc != 4) { |
| 761 |
11516 |
*err = "repeat takes 2 arguments"; |
| 762 |
|
return (NULL); |
| 763 |
11516 |
} |
| 764 |
0 |
|
| 765 |
0 |
p = argv[2]; |
| 766 |
|
i = SF_Parse_Integer(&p, err); |
| 767 |
|
|
| 768 |
11516 |
if (*err != NULL) |
| 769 |
11516 |
return (NULL); |
| 770 |
11516 |
|
| 771 |
11516 |
if (*p != '\0' || i < 0) { |
| 772 |
11516 |
*err = "invalid number of repetitions"; |
| 773 |
11516 |
return (NULL); |
| 774 |
|
} |
| 775 |
|
|
| 776 |
270 |
l = (strlen(argv[3]) * i) + 1; |
| 777 |
|
res = malloc(l); |
| 778 |
|
AN(res); |
| 779 |
|
AN(VSB_init(vsb, res, l)); |
| 780 |
|
while (i > 0) { |
| 781 |
|
AZ(VSB_cat(vsb, argv[3])); |
| 782 |
|
i--; |
| 783 |
|
} |
| 784 |
270 |
AZ(VSB_finish(vsb)); |
| 785 |
0 |
VSB_fini(vsb); |
| 786 |
0 |
return (res); |
| 787 |
|
} |
| 788 |
|
|
| 789 |
270 |
static char * |
| 790 |
270 |
macro_func_string(int argc, char *const *argv, const char **err) |
| 791 |
|
{ |
| 792 |
270 |
|
| 793 |
0 |
assert(argc >= 2); |
| 794 |
|
AN(argv); |
| 795 |
270 |
AN(err); |
| 796 |
0 |
|
| 797 |
0 |
if (argc == 2) { |
| 798 |
|
*err = "missing action"; |
| 799 |
|
return (NULL); |
| 800 |
270 |
} |
| 801 |
270 |
|
| 802 |
270 |
if (!strcmp(argv[2], "repeat")) |
| 803 |
270 |
return (macro_func_string_repeat(argc - 1, argv + 1, err)); |
| 804 |
168050 |
|
| 805 |
167780 |
*err = "unknown action"; |
| 806 |
167780 |
return (NULL); |
| 807 |
|
} |
| 808 |
270 |
|
| 809 |
270 |
/********************************************************************** |
| 810 |
270 |
* Main |
| 811 |
270 |
*/ |
| 812 |
|
|
| 813 |
|
static int |
| 814 |
270 |
read_file(const char *fn) |
| 815 |
|
{ |
| 816 |
|
struct vtc_tst *tp; |
| 817 |
270 |
char *p, *q; |
| 818 |
270 |
|
| 819 |
270 |
p = VFIL_readfile(NULL, fn, NULL); |
| 820 |
|
if (p == NULL) { |
| 821 |
270 |
fprintf(stderr, "Cannot stat file \"%s\": %s\n", |
| 822 |
0 |
fn, strerror(errno)); |
| 823 |
0 |
return (2); |
| 824 |
|
} |
| 825 |
|
for (q = p ;q != NULL && *q != '\0'; q++) { |
| 826 |
270 |
if (vct_islws(*q)) |
| 827 |
270 |
continue; |
| 828 |
|
if (*q != '#') |
| 829 |
0 |
break; |
| 830 |
0 |
q = strchr(q, '\n'); |
| 831 |
270 |
if (q == NULL) |
| 832 |
|
break; |
| 833 |
|
} |
| 834 |
|
|
| 835 |
|
if (q == NULL || *q == '\0') { |
| 836 |
|
fprintf(stderr, "File \"%s\" has no content.\n", fn); |
| 837 |
|
free(p); |
| 838 |
5435 |
return (2); |
| 839 |
|
} |
| 840 |
|
|
| 841 |
|
if ((strncmp(q, "varnishtest", 11) || !isspace(q[11])) && |
| 842 |
|
(strncmp(q, "vtest", 5) || !isspace(q[5]))) { |
| 843 |
5435 |
fprintf(stderr, |
| 844 |
5435 |
"File \"%s\" doesn't start with" |
| 845 |
10 |
" 'vtest' or 'varnishtest'\n", fn); |
| 846 |
5 |
free(p); |
| 847 |
5 |
vtc_skip++; |
| 848 |
|
return (2); |
| 849 |
5440 |
} |
| 850 |
5440 |
ALLOC_OBJ(tp, TST_MAGIC); |
| 851 |
10 |
AN(tp); |
| 852 |
5430 |
tp->filename = fn; |
| 853 |
5430 |
tp->script = p; |
| 854 |
0 |
tp->ntodo = vtc_ntest; |
| 855 |
0 |
tp->nwait = vtc_ntest; |
| 856 |
0 |
VTAILQ_INSERT_TAIL(&tst_head, tp, list); |
| 857 |
0 |
return (0); |
| 858 |
|
} |
| 859 |
5430 |
|
| 860 |
0 |
/********************************************************************** |
| 861 |
0 |
* autocrap test-driver command arguments |
| 862 |
0 |
*/ |
| 863 |
|
|
| 864 |
|
static void |
| 865 |
10810 |
automake_test_driver_arguments(int argc, char *const *argv) |
| 866 |
5380 |
{ |
| 867 |
40 |
|
| 868 |
|
argc -= 1; |
| 869 |
20 |
argv += 1; |
| 870 |
20 |
|
| 871 |
20 |
while (argc > 1) { |
| 872 |
20 |
#define TDSAVE(name, dst) \ |
| 873 |
|
if (!strcmp(*argv, name)) { \ |
| 874 |
5410 |
dst = argv[1]; \ |
| 875 |
5410 |
AN(dst); \ |
| 876 |
5410 |
argc -= 2; \ |
| 877 |
5410 |
argv += 2; \ |
| 878 |
5410 |
continue; \ |
| 879 |
5410 |
} |
| 880 |
5410 |
TDARGS(TDSAVE) |
| 881 |
5410 |
#undef TDSAVE |
| 882 |
5435 |
if (!strcmp(*argv, "--extension")) { |
| 883 |
|
add_extension(argv[1]); |
| 884 |
|
argc -= 2; |
| 885 |
|
argv += 2; |
| 886 |
|
continue; |
| 887 |
|
} |
| 888 |
|
if (strcmp(*argv, "--")) { |
| 889 |
5130 |
fprintf(stderr, "Not '--': '%s'\n", *argv); |
| 890 |
|
usage(); |
| 891 |
|
} |
| 892 |
5130 |
if (read_file(argv[1])) |
| 893 |
5130 |
usage(); |
| 894 |
|
printf("Running test %s\n", argv[1]); |
| 895 |
46170 |
break; |
| 896 |
|
} |
| 897 |
|
vtc_verbosity = 0; |
| 898 |
|
} |
| 899 |
|
|
| 900 |
|
/********************************************************************** |
| 901 |
|
* Usual command arguments |
| 902 |
|
*/ |
| 903 |
|
|
| 904 |
46170 |
static void |
| 905 |
|
usual_arguments(int argc, char *const *argv) |
| 906 |
15390 |
{ |
| 907 |
0 |
int ch; |
| 908 |
0 |
uintmax_t bufsiz; |
| 909 |
0 |
|
| 910 |
0 |
while ((ch = getopt(argc, argv, "b:CD:E:hij:kLln:p:qt:vW")) != -1) { |
| 911 |
|
switch (ch) { |
| 912 |
15390 |
case 'b': |
| 913 |
5130 |
if (VNUM_2bytes(optarg, &bufsiz, 0)) { |
| 914 |
5130 |
fprintf(stderr, "Cannot parse b opt '%s'\n", |
| 915 |
5130 |
optarg); |
| 916 |
5130 |
exit(2); |
| 917 |
|
} |
| 918 |
10260 |
if (bufsiz > UINT_MAX) { |
| 919 |
5130 |
fprintf(stderr, "Invalid b opt '%s'\n", |
| 920 |
5130 |
optarg); |
| 921 |
5130 |
exit(2); |
| 922 |
5130 |
} |
| 923 |
|
vtc_bufsiz = (unsigned)bufsiz; |
| 924 |
5130 |
break; |
| 925 |
0 |
case 'C': |
| 926 |
0 |
vtc_use_cleaner = !vtc_use_cleaner; |
| 927 |
|
break; |
| 928 |
5130 |
case 'D': |
| 929 |
0 |
if (!parse_D_opt(optarg)) { |
| 930 |
5130 |
fprintf(stderr, "Cannot parse D opt '%s'\n", |
| 931 |
|
optarg); |
| 932 |
5130 |
exit(2); |
| 933 |
5130 |
} |
| 934 |
|
break; |
| 935 |
|
case 'E': |
| 936 |
|
add_extension(optarg); |
| 937 |
|
break; |
| 938 |
|
case 'i': |
| 939 |
|
iflg = 1; |
| 940 |
110 |
break; |
| 941 |
|
case 'j': |
| 942 |
|
npar = strtoul(optarg, NULL, 0); |
| 943 |
|
break; |
| 944 |
|
case 'L': |
| 945 |
290 |
leave_temp = 2; |
| 946 |
200 |
break; |
| 947 |
|
case 'l': |
| 948 |
10 |
leave_temp = 1; |
| 949 |
0 |
break; |
| 950 |
0 |
case 'k': |
| 951 |
0 |
vtc_continue = !vtc_continue; |
| 952 |
|
break; |
| 953 |
10 |
case 'n': |
| 954 |
0 |
vtc_ntest = strtoul(optarg, NULL, 0); |
| 955 |
0 |
break; |
| 956 |
0 |
case 'p': |
| 957 |
|
VSB_cat(params_vsb, " -p "); |
| 958 |
10 |
VSB_quote(params_vsb, optarg, -1, 0); |
| 959 |
10 |
break; |
| 960 |
|
case 'q': |
| 961 |
15 |
if (vtc_verbosity > 0) |
| 962 |
15 |
vtc_verbosity--; |
| 963 |
|
break; |
| 964 |
10 |
case 't': |
| 965 |
0 |
vtc_maxdur = strtoul(optarg, NULL, 0); |
| 966 |
0 |
break; |
| 967 |
0 |
case 'v': |
| 968 |
|
if (vtc_verbosity < 2) |
| 969 |
10 |
vtc_verbosity++; |
| 970 |
|
break; |
| 971 |
0 |
default: |
| 972 |
0 |
usage(); |
| 973 |
|
} |
| 974 |
5 |
} |
| 975 |
5 |
argc -= optind; |
| 976 |
|
argv += optind; |
| 977 |
10 |
|
| 978 |
10 |
if (argc < 1) |
| 979 |
|
usage(); |
| 980 |
10 |
|
| 981 |
10 |
for (; argc > 0; argc--, argv++) { |
| 982 |
|
if (!read_file(*argv)) |
| 983 |
15 |
continue; |
| 984 |
15 |
if (!vtc_continue) |
| 985 |
|
exit(2); |
| 986 |
10 |
} |
| 987 |
10 |
} |
| 988 |
|
|
| 989 |
10 |
/********************************************************************** |
| 990 |
10 |
* Main |
| 991 |
|
*/ |
| 992 |
5 |
|
| 993 |
5 |
int |
| 994 |
5 |
main(int argc, char * const *argv) |
| 995 |
|
{ |
| 996 |
10 |
int i; |
| 997 |
10 |
int nstart = 0; |
| 998 |
10 |
const char *p; |
| 999 |
|
char buf[PATH_MAX]; |
| 1000 |
5 |
|
| 1001 |
5 |
argv0 = strrchr(argv[0], '/'); |
| 1002 |
|
if (argv0 == NULL) |
| 1003 |
65 |
argv0 = argv[0]; |
| 1004 |
65 |
else |
| 1005 |
65 |
argv0++; |
| 1006 |
|
|
| 1007 |
20 |
if (getenv("TMPDIR") != NULL) |
| 1008 |
|
tmppath = strdup(getenv("TMPDIR")); |
| 1009 |
|
else |
| 1010 |
90 |
tmppath = strdup("/tmp"); |
| 1011 |
90 |
|
| 1012 |
|
#ifdef PACKAGE_VERSION |
| 1013 |
90 |
extmacro_def("pkg_version", NULL, PACKAGE_VERSION); |
| 1014 |
5 |
#endif |
| 1015 |
|
#ifdef PACKAGE_BRANCH |
| 1016 |
375 |
extmacro_def("pkg_branch", NULL, PACKAGE_BRANCH); |
| 1017 |
305 |
#endif |
| 1018 |
280 |
|
| 1019 |
25 |
cwd = getcwd(buf, sizeof buf); |
| 1020 |
15 |
extmacro_def("pwd", NULL, "%s", cwd); |
| 1021 |
10 |
|
| 1022 |
70 |
extmacro_def("date", macro_func_date, NULL); |
| 1023 |
|
extmacro_def("string", macro_func_string, NULL); |
| 1024 |
|
|
| 1025 |
|
vmod_path = NULL; |
| 1026 |
|
|
| 1027 |
|
params_vsb = VSB_new_auto(); |
| 1028 |
|
AN(params_vsb); |
| 1029 |
5240 |
p = getenv("VTEST_DURATION"); |
| 1030 |
|
if (p == NULL) |
| 1031 |
|
p = getenv("VARNISHTEST_DURATION"); |
| 1032 |
5240 |
if (p != NULL) |
| 1033 |
|
vtc_maxdur = atoi(p); |
| 1034 |
|
|
| 1035 |
|
VRND_SeedAll(); |
| 1036 |
5240 |
cbvsb = VSB_new_auto(); |
| 1037 |
5240 |
AN(cbvsb); |
| 1038 |
0 |
setbuf(stdout, NULL); |
| 1039 |
|
setbuf(stderr, NULL); |
| 1040 |
5240 |
|
| 1041 |
|
if (argc < 2) |
| 1042 |
5240 |
usage(); |
| 1043 |
5230 |
|
| 1044 |
|
if (argv[1][0] == '-' && argv[1][1] == '-') { |
| 1045 |
10 |
automake_test_driver_arguments(argc, argv); |
| 1046 |
|
} else { |
| 1047 |
|
usual_arguments(argc, argv); |
| 1048 |
5240 |
} |
| 1049 |
|
|
| 1050 |
|
|
| 1051 |
5240 |
AZ(VSB_finish(params_vsb)); |
| 1052 |
|
|
| 1053 |
|
ip_magic(); |
| 1054 |
5240 |
|
| 1055 |
5240 |
if (iflg) |
| 1056 |
|
i_mode(); |
| 1057 |
5240 |
|
| 1058 |
5240 |
vb = VEV_New(); |
| 1059 |
|
|
| 1060 |
5240 |
if (vtc_use_cleaner) |
| 1061 |
|
cleaner_setup(); |
| 1062 |
5240 |
|
| 1063 |
5240 |
i = 0; |
| 1064 |
5240 |
while (!VTAILQ_EMPTY(&tst_head) || i) { |
| 1065 |
5240 |
if (!VTAILQ_EMPTY(&tst_head) && njob < npar) { |
| 1066 |
5235 |
start_test(); |
| 1067 |
10465 |
njob++; |
| 1068 |
5 |
/* Stagger ramp-up */ |
| 1069 |
|
if (nstart++ < npar) |
| 1070 |
5240 |
(void)usleep(random() % 100000L); |
| 1071 |
5240 |
i = 1; |
| 1072 |
5240 |
continue; |
| 1073 |
5240 |
} |
| 1074 |
5240 |
i = VEV_Once(vb); |
| 1075 |
|
} |
| 1076 |
5240 |
cleaner_finish(); |
| 1077 |
0 |
(void)close(bad_backend_fd); |
| 1078 |
|
if (td_trs_file != 0) |
| 1079 |
5240 |
return(0); |
| 1080 |
5130 |
if (vtc_continue) |
| 1081 |
5130 |
fprintf(stderr, |
| 1082 |
110 |
"%d tests failed, %d tests skipped, %d tests passed\n", |
| 1083 |
|
vtc_fail, vtc_skip, vtc_good); |
| 1084 |
|
if (vtc_fail) |
| 1085 |
5240 |
return (1); |
| 1086 |
|
if (vtc_skip && !vtc_good) |
| 1087 |
5200 |
return (77); |
| 1088 |
5200 |
return (0); |
| 1089 |
5200 |
} |