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
        struct buf *bp;
144
145 23331
        bp = VTAILQ_FIRST(&free_bufs);
146
        CHECK_OBJ_ORNULL(bp, BUF_MAGIC);
147
        if (bp != NULL) {
148
                VTAILQ_REMOVE(&free_bufs, bp, list);
149 23331
                VSB_clear(bp->diag);
150 23331
        } else {
151 23331
                ALLOC_OBJ(bp, BUF_MAGIC);
152 1071
                AN(bp);
153 1071
                bp->bufsiz = vtc_bufsiz;
154 1071
                bp->buf = mmap(NULL, bp->bufsiz, PROT_READ|PROT_WRITE,
155 22260
                    MAP_ANON | MAP_SHARED, -1, 0);
156 22260
                assert(bp->buf != MAP_FAILED);
157 22260
                bp->diag = VSB_new_auto();
158 22260
                AN(bp->diag);
159
        }
160 22260
        memset(bp->buf, 0, bp->bufsiz);
161 22260
        return (bp);
162 22260
}
163
164 23331
static void
165 23331
rel_buf(struct buf **bp)
166
{
167
        CHECK_OBJ_NOTNULL(*bp, BUF_MAGIC);
168
169 23331
        VTAILQ_INSERT_HEAD(&free_bufs, (*bp), list);
170
        *bp = NULL;
171 23331
}
172
173 23331
/**********************************************************************
174 23331
 * Parse a -D option argument into a name/val pair, and insert
175 23331
 * into extmacro list
176
 */
177
178
static int
179
parse_D_opt(char *arg)
180
{
181
        char *p, *q;
182
183 42
        p = arg;
184
        q = strchr(p, '=');
185
        if (!q)
186
                return (0);
187 42
        *q++ = '\0';
188 42
        extmacro_def(p, NULL, "%s", q);
189 42
190 0
        return (1);
191 42
}
192 42
193
/**********************************************************************
194 42
 * Print usage
195 42
 */
196
197
static void v_noreturn_
198
usage(void)
199
{
200
        fprintf(stderr, "usage: %s [options] file ...\n", argv0);
201
#define FMT "    %-28s # %s\n"
202 105
        fprintf(stderr, FMT, "-b size",
203
            "Set internal buffer size (default: 1M)");
204 105
        fprintf(stderr, FMT, "-C", "Use cleaner subprocess");
205
        fprintf(stderr, FMT, "-D name=val", "Define macro");
206 105
        fprintf(stderr, FMT, "-E extension_shlib", "Load extension");
207
        fprintf(stderr, FMT, "-i", "Find varnish binaries in build tree");
208 105
        fprintf(stderr, FMT, "-j jobs", "Run this many tests in parallel");
209 105
        fprintf(stderr, FMT, "-k", "Continue on test failure");
210 105
        fprintf(stderr, FMT, "-L", "Always leave temporary vtc.*");
211 105
        fprintf(stderr, FMT, "-l", "Leave temporary vtc.* if test fails");
212 105
        fprintf(stderr, FMT, "-n iterations", "Run tests this many times");
213 105
        fprintf(stderr, FMT, "-p name=val", "Pass a varnishd parameter");
214 105
        fprintf(stderr, FMT, "-q", "Quiet mode: report only failures");
215 105
        fprintf(stderr, FMT, "-t duration", "Time tests out after this long");
216 105
        fprintf(stderr, FMT, "-v", "Verbose mode: always report test log");
217 105
        exit(1);
218 105
}
219 105
220 105
/**********************************************************************
221 105
 * When running many tests, cleaning the tmpdir with "rm -rf" becomes
222 105
 * 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
        char buf[BUFSIZ];
231
232
        AZ(memcmp(dirname, tmppath, strlen(tmppath)));
233 23331
        if (cleaner_pid > 0) {
234
                bprintf(buf, "%s\n", dirname);
235
                assert(write(cleaner_fd, buf, strlen(buf)) == strlen(buf));
236
                return;
237 23331
        }
238 23331
        bprintf(buf, "exec /bin/rm -rf %s\n", dirname);
239 1176
        AZ(system(buf));
240 1176
}
241 1176
242
static void
243 22155
cleaner_setup(void)
244 22155
{
245 23331
        int p[2], st;
246
        char buf[BUFSIZ];
247
        char *q;
248 42
        pid_t pp;
249
250
        AZ(pipe(p));
251
        assert(p[0] > STDERR_FILENO);
252
        assert(p[1] > STDERR_FILENO);
253
        cleaner_pid = fork();
254
        assert(cleaner_pid >= 0);
255 42
        if (cleaner_pid == 0) {
256 42
                closefd(&p[1]);
257 42
                (void)!nice(1);         /* Not important */
258 42
                setbuf(stdin, NULL);
259 42
                AZ(dup2(p[0], STDIN_FILENO));
260 84
                while (fgets(buf, sizeof buf, stdin)) {
261 42
                        AZ(memcmp(buf, tmppath, strlen(tmppath)));
262 42
                        q = buf + strlen(buf);
263 42
                        assert(q > buf);
264 42
                        assert(q[-1] == '\n');
265 1218
                        q[-1] = '\0';
266 1176
267 1176
                        /* Dont expend a shell on running /bin/rm */
268 1176
                        pp = fork();
269 1176
                        assert(pp >= 0);
270 1176
                        if (pp == 0)
271
                                exit(execlp(
272
                                    "rm", "rm", "-rf", buf, (char*)0));
273 1176
                        assert(waitpid(pp, &st, 0) == pp);
274 1176
                        AZ(st);
275 2352
                }
276 1176
                exit(0);
277 1176
        }
278 1176
        closefd(&p[0]);
279 1176
        cleaner_fd = p[1];
280
}
281 42
282
static void
283 42
cleaner_neuter(void)
284 42
{
285 42
        if (cleaner_pid > 0)
286
                closefd(&cleaner_fd);
287
}
288 23331
289
static void
290 23331
cleaner_finish(void)
291 1176
{
292 23331
        int st;
293
294
        if (cleaner_pid > 0) {
295 22176
                closefd(&cleaner_fd);
296
                assert(waitpid(cleaner_pid, &st, 0) == cleaner_pid);
297
                AZ(st);
298
        }
299 22176
}
300 42
301 42
/**********************************************************************
302 42
 * CallBack
303 42
 */
304 22176
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
320
        // printf("CB %p %s %d\n", ve, jp->tst->filename, what);
321
        if (what == 0) {
322 23522
                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
        if (i > 0)
331
                VSB_bcat(jp->bp->diag, buf, i);
332
        if (i == 0) {
333 23522
334 23522
                njob--;
335
                px = wait4(jp->child, &stx, 0, NULL);
336
                assert(px == jp->child);
337 23522
                t = VTIM_mono() - jp->t0;
338 0
                AZ(close(ve->fd));
339 0
340 0
                ecode = WTERMSIG(stx);
341 23522
                if (ecode == 0)
342
                        ecode = WEXITSTATUS(stx);
343
344 23522
                AZ(VSB_finish(jp->bp->diag));
345 23522
346 23522
                VSB_clear(cbvsb);
347 191
                VSB_cat(cbvsb, jp->bp->buf);
348 23522
                p = strchr(jp->bp->buf, '\0');
349
                if (p > jp->bp->buf && p[-1] != '\n')
350 23331
                        VSB_putc(cbvsb, '\n');
351 23331
                VSB_quote_pfx(cbvsb, "*    diag  0.0 ",
352 23331
                    VSB_data(jp->bp->diag), -1, VSB_QUOTE_NONL);
353 23331
                AZ(VSB_finish(cbvsb));
354 23331
                rel_buf(&jp->bp);
355
356 23331
                if ((ecode > 1 && vtc_verbosity) || vtc_verbosity > 1)
357 23331
                        printf("%s", VSB_data(cbvsb));
358 23331
359
                if (!ecode)
360 23331
                        vtc_good++;
361
                else if (ecode == 1)
362 23331
                        vtc_skip++;
363 23331
                else
364 23331
                        vtc_fail++;
365 23331
366 0
                if (leave_temp == 0 || (leave_temp == 1 && ecode <= 1)) {
367 46662
                        cleaner_do(jp->tmpdir);
368 23331
                } else {
369 23331
                        bprintf(buf, "%s/LOG", jp->tmpdir);
370 23331
                        f = fopen(buf, "w");
371
                        AN(f);
372 23331
                        (void)fprintf(f, "%s\n", VSB_data(cbvsb));
373 378
                        AZ(fclose(f));
374
                }
375 23331
                free(jp->tmpdir);
376 22763
377 568
                if (td_log_file != NULL) {
378 505
                        f = fopen(td_log_file, "w");
379
                        AN(f);
380 63
                        (void)fprintf(f, "%s\n", VSB_data(cbvsb));
381
                        AZ(fclose(f));
382 23331
                }
383 23331
                if (td_trs_file != NULL) {
384 23331
                        f = fopen(td_trs_file, "w");
385 0
                        AN(f);
386 0
                        if (jp->killed || ecode > 1) {
387 0
                                fprintf(f, ":test-result: FAIL\n");
388 0
                                fprintf(f, ":copy-in-global-log: yes\n");
389 0
                        } else if (ecode) {
390
                                fprintf(f, ":test-result: SKIP\n");
391 23331
                                fprintf(f, ":copy-in-global-log: yes\n");
392
                        } else {
393 23331
                                fprintf(f, ":test-result: PASS\n");
394 21945
                                fprintf(f, ":copy-in-global-log: no\n");
395 21945
                        }
396 21945
                        AZ(fclose(f));
397 21945
                }
398 21945
399 23331
                if (jp->killed)
400 21945
                        printf("#    top  TEST %s TIMED OUT (kill -9)\n",
401 21945
                            jp->tst->filename);
402 21945
                if (ecode > 1) {
403 0
                        printf("#    top  TEST %s FAILED (%.3f)",
404 0
                            jp->tst->filename, t);
405 0
                        if (WIFSIGNALED(stx))
406 0
                                printf(" signal=%d\n", WTERMSIG(stx));
407 0
                        else if (WIFEXITED(stx))
408 21945
                                printf(" exit=%d\n", WEXITSTATUS(stx));
409 379
                        if (!vtc_continue && td_trs_file == NULL) {
410 379
                                /* XXX kill -9 other jobs ? */
411 379
                                exit(2);
412 379
                        }
413 379
                } else if (vtc_verbosity) {
414 379
                        printf("#    top  TEST %s %s (%.3f)\n",
415 21566
                            jp->tst->filename,
416 21566
                            ecode ? "skipped" : "passed", t);
417 21566
                }
418 21566
                if (jp->evt != NULL) {
419 21566
                        VEV_Stop(vb, jp->evt);
420
                        free(jp->evt);
421 21945
                }
422 21945
                jp->tst->nwait--;
423 1386
                if (jp->tst->nwait == 0) {
424 0
                        free(jp->tst->script);
425
                        FREE_OBJ(jp->tst);
426 0
                }
427 0
                FREE_OBJ(jp);
428 1386
                return (1);
429 63
        }
430 63
        return (0);
431 63
}
432 0
433 63
/**********************************************************************
434 63
 * Start Test
435 63
 */
436
437 63
static void
438
start_test(void)
439 1323
{
440 1281
        struct vtc_tst *tp;
441 1281
        int p[2], retval;
442 1281
        struct vtc_job *jp;
443 1281
        char tmpdir[PATH_MAX];
444
        char default_n[PATH_MAX];
445 23268
446 23268
        ALLOC_OBJ(jp, JOB_MAGIC);
447 23268
        AN(jp);
448 23268
449 23457
        jp->bp = get_buf();
450 23457
451 23079
        bprintf(tmpdir, "%s/vtc.%d.%08x", tmppath, (int)getpid(),
452 23079
                (unsigned)random());
453 23079
        AZ(mkdir(tmpdir, 0755));
454 23268
455 23268
        bprintf(default_n, "%s/default_n", tmpdir);
456
457 191
        AZ(setenv("VARNISH_DEFAULT_N", default_n, 1));
458 23459
459
        tp = VTAILQ_FIRST(&tst_head);
460
        CHECK_OBJ_NOTNULL(tp, TST_MAGIC);
461
        AN(tp->ntodo);
462
        tp->ntodo--;
463
        VTAILQ_REMOVE(&tst_head, tp, list);
464
        if (tp->ntodo > 0)
465 23331
                VTAILQ_INSERT_TAIL(&tst_head, tp, list);
466
467
        jp->tst = tp;
468
        REPLACE(jp->tmpdir, tmpdir);
469
470
        AZ(pipe(p));
471
        assert(p[0] > STDERR_FILENO);
472
        assert(p[1] > STDERR_FILENO);
473 23331
        jp->t0 = VTIM_mono();
474 23331
        jp->child = fork();
475
        assert(jp->child >= 0);
476 23331
        if (jp->child == 0) {
477
                cleaner_neuter();       // Too dangerous to have around
478 23331
                AZ(setpgid(getpid(), 0));
479
                VFIL_null_fd(STDIN_FILENO);
480 23331
                assert(dup2(p[1], STDOUT_FILENO) == STDOUT_FILENO);
481
                assert(dup2(p[1], STDERR_FILENO) == STDERR_FILENO);
482 23331
                retval = exec_file(jp->tst->filename, jp->tst->script,
483
                    jp->tmpdir, jp->bp->buf, jp->bp->bufsiz);
484 23331
                exit(retval);
485
        }
486 23331
        closefd(&p[1]);
487 23331
488 23331
        jp->ev = VEV_Alloc();
489 23331
        AN(jp->ev);
490 23331
        jp->ev->fd_flags = VEV__RD | VEV__HUP | VEV__ERR;
491 23331
        jp->ev->fd = p[0];
492 189
        jp->ev->priv = jp;
493
        jp->ev->callback = tst_cb;
494 23331
        AZ(VEV_Start(vb, jp->ev));
495 23331
496
        jp->evt = VEV_Alloc();
497 23331
        AN(jp->evt);
498 23331
        jp->evt->fd = -1;
499 23331
        jp->evt->timeout = vtc_maxdur;
500 23331
        jp->evt->priv = jp;
501 23331
        jp->evt->callback = tst_cb;
502 23331
        AZ(VEV_Start(vb, jp->evt));
503 46662
}
504 23331
505 23331
/**********************************************************************
506 23331
 * i-mode = "we're inside a src-tree"
507 23331
 *
508 23331
 * Find the abs path to top of source dir from Makefile, if that
509 46662
 * fails, fall back on "../../"
510 23331
 *
511 23331
 * Set PATH to all programs build directories
512
 * Set vmod_path to all vmods build directories
513 23331
 *
514
 */
515 23331
516 23331
static char *
517 23331
top_dir(const char *makefile, const char *top_var)
518 23331
{
519 23331
        const char *b, *e;
520 23331
        char *var;
521 23331
522
        AN(makefile);
523 23331
        AN(top_var);
524 23331
        assert(*top_var == '\n');
525 23331
526 23331
        b = strstr(makefile, top_var);
527 23331
        top_var++;
528 23331
529 23331
        if (b == NULL) {
530 23331
                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
        if (b == NULL) {
542
                fprintf(stderr, "No '/' after '%s' in Makefile\n", top_var);
543
                return (NULL);
544 43932
        }
545
        var = strndup(b, e - b);
546
        AN(var);
547
        return (var);
548
}
549 43932
550 43932
static void
551 43932
build_path(const char *topdir, const char *subdir,
552
    const char *pfx, const char *sfx, struct vsb *vsb)
553 43932
{
554 43932
        char buf[PATH_MAX];
555
        DIR *dir;
556 43932
        struct dirent *de;
557 0
        struct stat st;
558 0
        const char *topsep = "";
559
560
        if (*subdir != '\0')
561 43932
                topsep = "/";
562 43932
        bprintf(buf, "%s%s%s/", topdir, topsep, subdir);
563 0
        dir = opendir(buf);
564 0
        XXXAN(dir);
565
        while (1) {
566
                de = readdir(dir);
567 43932
                if (de == NULL)
568 43932
                        break;
569 0
                if (strncmp(de->d_name, pfx, strlen(pfx)))
570 0
                        continue;
571
                bprintf(buf, "%s%s%s/%s", topdir, topsep, subdir, de->d_name);
572 43932
                if (!stat(buf, &st) && S_ISDIR(st.st_mode)) {
573 43932
                        VSB_cat(vsb, buf);
574 43932
                        VSB_cat(vsb, sfx);
575 43932
                        VSB_cat(vsb, ":");
576
                }
577
        }
578 65898
        AZ(closedir(dir));
579
}
580
581
static void
582
i_mode(void)
583
{
584
        struct vsb *vsb;
585 65898
        char *p, *topbuild, *topsrc;
586
587 65898
        /*
588 43932
         * This code has a rather intimate knowledge of auto* generated
589 65898
         * makefiles.
590 65898
         */
591 65898
592 285558
        vsb = VSB_new_auto();
593 5491563
        AN(vsb);
594 5491563
595 65898
        p = VFIL_readfile(NULL, "Makefile", NULL);
596 5425665
        if (p == NULL) {
597 5206005
                fprintf(stderr, "No Makefile to search for -i flag.\n");
598 219660
                exit(2);
599 219660
        }
600 219660
601 219660
        topbuild = top_dir(p, "\nabs_top_builddir");
602 219660
        topsrc = top_dir(p, "\nabs_top_srcdir");
603 219660
        free(p);
604
        if (topbuild == NULL || topsrc == NULL) {
605 65898
                free(topbuild);
606 65898
                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
        VSB_cat(vsb, "PATH=");
617
#ifdef VTEST_WITH_VTC_VARNISH
618
        build_path(topbuild, "bin", "varnish", "", vsb);
619
#endif
620
621 21966
#ifdef VTEST_WITH_VTC_VINYL
622
        build_path(topbuild, "bin", "vinyl", "", vsb);
623
#endif
624
625
#ifdef WITH_CONTRIB
626
        VSB_putc(vsb, ':');
627
        build_path(topsrc, "", "contrib", "", vsb);
628
#endif
629
        VSB_printf(vsb, ":%s", getenv("PATH"));
630
        AZ(VSB_finish(vsb));
631 21966
        AZ(putenv(strdup(VSB_data(vsb))));
632 21966
633
        /*
634 21966
         * Build vmod_path which can find all VMODs in the build tree
635 21966
         */
636 0
637 0
        VSB_clear(vsb);
638
        build_path(topbuild, "vmod", ".libs", "", vsb);
639
        AZ(VSB_finish(vsb));
640 21966
        vmod_path = strdup(VSB_data(vsb));
641 21966
        AN(vmod_path);
642 21966
643 21966
        free(topbuild);
644 0
        free(topsrc);
645 0
        VSB_destroy(&vsb);
646 0
647
        /*
648 21966
         * strict jemalloc checking
649 21966
         */
650
        AZ(putenv(strdup("MALLOC_CONF=abort:true,junk:true")));
651
}
652
653
/**********************************************************************
654 21966
 * Figure out what IP related magic
655 21966
 */
656
657
static void
658
ip_magic(void)
659
{
660
        const struct suckaddr *sa;
661
        char abuf[VTCP_ADDRBUFSIZE];
662 21966
        char pbuf[VTCP_PORTBUFSIZE];
663 21966
        char *s;
664
665
        /*
666
         * In FreeBSD jails localhost/127.0.0.1 becomes the jails IP#
667 21966
         * XXX: IPv6-only hosts would have similar issue, but it is not
668 21966
         * XXX: obvious how to cope.  Ideally "127.0.0.1" would be
669
         * XXX: "localhost", but that doesn't work out of the box.
670
         * XXX: Things like "prefer_ipv6" parameter complicates things.
671
         */
672 21966
        sa = VSS_ResolveOne(NULL, "127.0.0.1", "0", 0, SOCK_STREAM, 0);
673 0
        AN(sa);
674 0
        bad_backend_fd = VTCP_bind(sa, NULL);
675 0
        if (bad_backend_fd < 0) {
676 0
                VSA_free(&sa);
677
                sa = VSS_ResolveFirst(NULL, "localhost", "0", 0, SOCK_STREAM, 0);
678 21966
                AN(sa);
679 21966
                bad_backend_fd = VTCP_bind(sa, NULL);
680 21966
        }
681
        assert(bad_backend_fd >= 0);
682
        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 21966
687 21966
#if defined (__APPLE__)
688 21966
        /*
689 21966
         * In macOS a bound socket that is not listening will timeout
690 21966
         * instead of refusing the connection so close it and hope
691
         * for the best.
692 21966
         */
693 21966
        VTCP_close(&bad_backend_fd);
694 21966
#endif
695
696
        /* Expose a backend that is forever down. */
697
        if (VSA_Get_Proto(sa) == AF_INET)
698
                extmacro_def("bad_backend", NULL, "%s:%s", abuf, pbuf);
699 21966
        else
700 21966
                extmacro_def("bad_backend", NULL, "[%s]:%s", abuf, pbuf);
701
702
        /* our default bind/listen address */
703
        if (VSA_Get_Proto(sa) == AF_INET)
704
                bprintf(abuf, "%s:0", s);
705 0
        else
706
                bprintf(abuf, "[%s]:0", s);
707
        free(s);
708
709
        extmacro_def("listen_addr", NULL, "%s", abuf);
710 0
        default_listen_addr = strdup(abuf);
711 0
        AN(default_listen_addr);
712 0
        VSA_free(&sa);
713 0
714 0
        /*
715 0
         * 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 0
         * C-class broadcast at that.
718 0
         * 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
722
        extmacro_def("bad_ip", NULL, "%s", "192.0.2.255");
723
}
724
725
/**********************************************************************
726 22239
 * Macros
727
 */
728
729
static char * v_matchproto_(macro_f)
730
macro_func_date(int argc, char *const *argv, const char **err)
731
{
732
        double t;
733
        char *s;
734
735
        assert(argc >= 2);
736
        AN(argv);
737
        AN(err);
738
739
        if (argc > 2) {
740 22239
                *err = "macro does not take arguments";
741 22239
                return (NULL);
742 22239
        }
743 22239
744 0
        t = VTIM_real();
745 0
        s = malloc(VTIM_FORMAT_SIZE);
746 0
        AN(s);
747 0
        VTIM_format(t, s);
748 0
        return (s);
749 22239
}
750 22239
751 22239
static char *
752 22239
macro_func_string_repeat(int argc, char *const *argv, const char **err)
753 22239
{
754
        struct vsb vsb[1];
755
        const char *p;
756
        char *res;
757
        size_t l;
758
        int i;
759
760
        if (argc != 4) {
761
                *err = "repeat takes 2 arguments";
762
                return (NULL);
763
        }
764
765 22239
        p = argv[2];
766 22239
        i = SF_Parse_Integer(&p, err);
767
768 0
        if (*err != NULL)
769
                return (NULL);
770
771 22239
        if (*p != '\0' || i < 0) {
772 22239
                *err = "invalid number of repetitions";
773
                return (NULL);
774 0
        }
775 22239
776
        l = (strlen(argv[3]) * i) + 1;
777 22239
        res = malloc(l);
778 22239
        AN(res);
779 22239
        AN(VSB_init(vsb, res, l));
780 22239
        while (i > 0) {
781
                AZ(VSB_cat(vsb, argv[3]));
782
                i--;
783
        }
784
        AZ(VSB_finish(vsb));
785
        VSB_fini(vsb);
786
        return (res);
787
}
788
789
static char *
790 22239
macro_func_string(int argc, char *const *argv, const char **err)
791 22239
{
792
793
        assert(argc >= 2);
794
        AN(argv);
795
        AN(err);
796
797
        if (argc == 2) {
798 50008
                *err = "missing action";
799
                return (NULL);
800
        }
801
802
        if (!strcmp(argv[2], "repeat"))
803 50008
                return (macro_func_string_repeat(argc - 1, argv + 1, err));
804 50008
805 50008
        *err = "unknown action";
806
        return (NULL);
807 50008
}
808 0
809 0
/**********************************************************************
810
 * Main
811
 */
812 50008
813 50008
static int
814 50008
read_file(const char *fn)
815 50008
{
816 50008
        struct vtc_tst *tp;
817 50008
        char *p, *q;
818
819
        p = VFIL_readfile(NULL, fn, NULL);
820 1176
        if (p == NULL) {
821
                fprintf(stderr, "Cannot stat file \"%s\": %s\n",
822
                    fn, strerror(errno));
823
                return (2);
824
        }
825
        for (q = p ;q != NULL && *q != '\0'; q++) {
826
                if (vct_islws(*q))
827
                        continue;
828 1176
                if (*q != '#')
829 0
                        break;
830 0
                q = strchr(q, '\n');
831
                if (q == NULL)
832
                        break;
833 1176
        }
834 1176
835
        if (q == NULL || *q == '\0') {
836 1176
                fprintf(stderr, "File \"%s\" has no content.\n", fn);
837 0
                free(p);
838
                return (2);
839 1176
        }
840 0
841 0
        if ((strncmp(q, "varnishtest", 11) || !isspace(q[11])) &&
842
            (strncmp(q, "vtest", 5) || !isspace(q[5]))) {
843
                fprintf(stderr,
844 1176
                    "File \"%s\" doesn't start with"
845 1176
                    " 'vtest' or 'varnishtest'\n", fn);
846 1176
                free(p);
847 1176
                vtc_skip++;
848 890652
                return (2);
849 889476
        }
850 889476
        ALLOC_OBJ(tp, TST_MAGIC);
851
        AN(tp);
852 1176
        tp->filename = fn;
853 1176
        tp->script = p;
854 1176
        tp->ntodo = vtc_ntest;
855 1176
        tp->nwait = vtc_ntest;
856
        VTAILQ_INSERT_TAIL(&tst_head, tp, list);
857
        return (0);
858 1176
}
859
860
/**********************************************************************
861 1176
 * autocrap test-driver command arguments
862 1176
 */
863 1176
864
static void
865 1176
automake_test_driver_arguments(int argc, char *const *argv)
866 0
{
867 0
868
        argc -= 1;
869
        argv += 1;
870 1176
871 1176
        while (argc > 1) {
872
#define TDSAVE(name, dst) \
873 0
                if (!strcmp(*argv, name)) { \
874 0
                        dst = argv[1]; \
875 1176
                        AN(dst); \
876
                        argc -= 2; \
877
                        argv += 2; \
878
                        continue; \
879
                }
880
        TDARGS(TDSAVE)
881
#undef TDSAVE
882 23247
                if (!strcmp(*argv, "--extension")) {
883
                        add_extension(argv[1]);
884
                        argc -= 2;
885
                        argv += 2;
886
                        continue;
887 23247
                }
888 23247
                if (strcmp(*argv, "--")) {
889 42
                        fprintf(stderr, "Not '--': '%s'\n", *argv);
890 21
                        usage();
891 21
                }
892
                if (read_file(argv[1]))
893 23268
                        usage();
894 23268
                printf("Running test %s\n", argv[1]);
895 42
                break;
896 23226
        }
897 23226
        vtc_verbosity = 0;
898 0
}
899 0
900 0
/**********************************************************************
901 0
 * Usual command arguments
902
 */
903 23226
904 0
static void
905 0
usual_arguments(int argc, char *const *argv)
906 0
{
907
        int ch;
908
        uintmax_t bufsiz;
909 46242
910 23016
        while ((ch = getopt(argc, argv, "b:CD:E:hij:kLln:p:qt:vW")) != -1) {
911 168
                switch (ch) {
912
                case 'b':
913 84
                        if (VNUM_2bytes(optarg, &bufsiz, 0)) {
914 84
                                fprintf(stderr, "Cannot parse b opt '%s'\n",
915 84
                                    optarg);
916 84
                                exit(2);
917
                        }
918 23142
                        if (bufsiz > UINT_MAX) {
919 23142
                                fprintf(stderr, "Invalid b opt '%s'\n",
920 23142
                                    optarg);
921 23142
                                exit(2);
922 23142
                        }
923 23142
                        vtc_bufsiz = (unsigned)bufsiz;
924 23142
                        break;
925 23142
                case 'C':
926 23247
                        vtc_use_cleaner = !vtc_use_cleaner;
927
                        break;
928
                case 'D':
929
                        if (!parse_D_opt(optarg)) {
930
                                fprintf(stderr, "Cannot parse D opt '%s'\n",
931
                                    optarg);
932
                                exit(2);
933 21945
                        }
934
                        break;
935
                case 'E':
936 21945
                        add_extension(optarg);
937 21945
                        break;
938
                case 'i':
939 197505
                        iflg = 1;
940
                        break;
941
                case 'j':
942
                        npar = strtoul(optarg, NULL, 0);
943
                        break;
944
                case 'L':
945
                        leave_temp = 2;
946
                        break;
947
                case 'l':
948 197505
                        leave_temp = 1;
949
                        break;
950 65835
                case 'k':
951 0
                        vtc_continue = !vtc_continue;
952 0
                        break;
953 0
                case 'n':
954 0
                        vtc_ntest = strtoul(optarg, NULL, 0);
955
                        break;
956 65835
                case 'p':
957 21945
                        VSB_cat(params_vsb, " -p ");
958 21945
                        VSB_quote(params_vsb, optarg, -1, 0);
959 21945
                        break;
960 21945
                case 'q':
961
                        if (vtc_verbosity > 0)
962 43890
                                vtc_verbosity--;
963 21945
                        break;
964 21945
                case 't':
965 21945
                        vtc_maxdur = strtoul(optarg, NULL, 0);
966 21945
                        break;
967
                case 'v':
968 21945
                        if (vtc_verbosity < 2)
969 0
                                vtc_verbosity++;
970 0
                        break;
971
                default:
972 21945
                        usage();
973 0
                }
974 21945
        }
975
        argc -= optind;
976 21945
        argv += optind;
977 21945
978
        if (argc < 1)
979
                usage();
980
981
        for (; argc > 0; argc--, argv++) {
982
                if (!read_file(*argv))
983
                        continue;
984 462
                if (!vtc_continue)
985
                        exit(2);
986
        }
987
}
988
989 1218
/**********************************************************************
990 840
 * Main
991
 */
992 42
993 0
int
994 0
main(int argc, char * const *argv)
995 0
{
996
        int i;
997 42
        int nstart = 0;
998 0
        const char *p;
999 0
        char buf[PATH_MAX];
1000 0
1001
        argv0 = strrchr(argv[0], '/');
1002 42
        if (argv0 == NULL)
1003 42
                argv0 = argv[0];
1004
        else
1005 63
                argv0++;
1006 63
1007
        if (getenv("TMPDIR") != NULL)
1008 42
                tmppath = strdup(getenv("TMPDIR"));
1009 0
        else
1010 0
                tmppath = strdup("/tmp");
1011 0
1012
#ifdef PACKAGE_VERSION
1013 42
        extmacro_def("pkg_version", NULL, PACKAGE_VERSION);
1014
#endif
1015 0
#ifdef PACKAGE_BRANCH
1016 0
        extmacro_def("pkg_branch", NULL, PACKAGE_BRANCH);
1017
#endif
1018 21
1019 21
        cwd = getcwd(buf, sizeof buf);
1020
        extmacro_def("pwd", NULL, "%s", cwd);
1021 42
1022 42
        extmacro_def("date", macro_func_date, NULL);
1023
        extmacro_def("string", macro_func_string, NULL);
1024 42
1025 42
        vmod_path = NULL;
1026
1027 63
        params_vsb = VSB_new_auto();
1028 63
        AN(params_vsb);
1029
        p = getenv("VTEST_DURATION");
1030 42
        if (p == NULL)
1031 42
                p = getenv("VARNISHTEST_DURATION");
1032
        if (p != NULL)
1033 42
                vtc_maxdur = atoi(p);
1034 42
1035
        VRND_SeedAll();
1036 21
        cbvsb = VSB_new_auto();
1037 21
        AN(cbvsb);
1038 21
        setbuf(stdout, NULL);
1039
        setbuf(stderr, NULL);
1040 42
1041 42
        if (argc < 2)
1042 42
                usage();
1043
1044 21
        if (argv[1][0] == '-' && argv[1][1] == '-') {
1045 21
                automake_test_driver_arguments(argc, argv);
1046
        } else {
1047 0
                usual_arguments(argc, argv);
1048 0
        }
1049
1050 273
1051 273
        AZ(VSB_finish(params_vsb));
1052 273
1053
        ip_magic();
1054 84
1055
        if (iflg)
1056
                i_mode();
1057 378
1058 378
        vb = VEV_New();
1059
1060 378
        if (vtc_use_cleaner)
1061 21
                cleaner_setup();
1062
1063 1596
        i = 0;
1064 1302
        while (!VTAILQ_EMPTY(&tst_head) || i) {
1065 1197
                if (!VTAILQ_EMPTY(&tst_head) && njob < npar) {
1066 105
                        start_test();
1067 63
                        njob++;
1068 42
                        /* Stagger ramp-up */
1069 294
                        if (nstart++ < npar)
1070
                                (void)usleep(random() % 100000L);
1071
                        i = 1;
1072
                        continue;
1073
                }
1074
                i = VEV_Once(vb);
1075
        }
1076 22407
        cleaner_finish();
1077
        (void)close(bad_backend_fd);
1078
        if (td_trs_file != 0)
1079 22407
                return(0);
1080
        if (vtc_continue)
1081
                fprintf(stderr,
1082
                    "%d tests failed, %d tests skipped, %d tests passed\n",
1083 22407
                    vtc_fail, vtc_skip, vtc_good);
1084 22407
        if (vtc_fail)
1085 0
                return (1);
1086
        if (vtc_skip && !vtc_good)
1087 22407
                return (77);
1088
        return (0);
1089 22407
}