varnish-cache/bin/varnishtest/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 "vsub.h"
54
#include "vtcp.h"
55
#include "vtim.h"
56
#include "vct.h"
57
58
static const char *argv0;
59
60
struct buf {
61
        unsigned                magic;
62
#define BUF_MAGIC               0x39d1258a
63
        VTAILQ_ENTRY(buf)       list;
64
        char                    *buf;
65
        struct vsb              *diag;
66
        size_t                  bufsiz;
67
};
68
69
static VTAILQ_HEAD(, buf) free_bufs = VTAILQ_HEAD_INITIALIZER(free_bufs);
70
71
struct vtc_tst {
72
        unsigned                magic;
73
#define TST_MAGIC               0x618d8b88
74
        VTAILQ_ENTRY(vtc_tst)   list;
75
        const char              *filename;
76
        char                    *script;
77
        unsigned                ntodo;
78
        unsigned                nwait;
79
};
80
81
struct vtc_job {
82
        unsigned                magic;
83
#define JOB_MAGIC               0x1b5fc419
84
        struct vtc_tst          *tst;
85
        pid_t                   child;
86
        struct vev              *ev;
87
        struct vev              *evt;
88
        struct buf              *bp;
89
        char                    *tmpdir;
90
        double                  t0;
91
        int                     killed;
92
};
93
94
95
int iflg = 0;
96
vtim_dur vtc_maxdur = 60;
97
static unsigned vtc_bufsiz = 1024 * 1024;
98
99
static VTAILQ_HEAD(, vtc_tst) tst_head = VTAILQ_HEAD_INITIALIZER(tst_head);
100
static struct vev_root *vb;
101
static int njob = 0;
102
static int npar = 1;                    /* Number of parallel tests */
103
static int vtc_continue;                /* Continue on error */
104
static int vtc_verbosity = 1;           /* Verbosity Level */
105
static int vtc_good;
106
static int vtc_fail;
107
static int vtc_skip;
108
static char *tmppath;
109
static char *cwd = NULL;
110
char *vmod_path = NULL;
111
struct vsb *params_vsb = NULL;
112
int leave_temp;
113
static struct vsb *cbvsb;
114
static int bad_backend_fd;
115
116
static int cleaner_fd = -1;
117
static pid_t cleaner_pid;
118
const char *default_listen_addr;
119
120
static struct buf *
121
get_buf(void)
122
{
123
        struct buf *bp;
124
125
        bp = VTAILQ_FIRST(&free_bufs);
126
        CHECK_OBJ_ORNULL(bp, BUF_MAGIC);
127
        if (bp != NULL) {
128
                VTAILQ_REMOVE(&free_bufs, bp, list);
129
                VSB_clear(bp->diag);
130
        } else {
131
                ALLOC_OBJ(bp, BUF_MAGIC);
132
                AN(bp);
133
                bp->bufsiz = vtc_bufsiz;
134
                bp->buf = mmap(NULL, bp->bufsiz, PROT_READ|PROT_WRITE,
135
                    MAP_ANON | MAP_SHARED, -1, 0);
136
                assert(bp->buf != MAP_FAILED);
137
                bp->diag = VSB_new_auto();
138
                AN(bp->diag);
139
        }
140
        memset(bp->buf, 0, bp->bufsiz);
141 41400
        return (bp);
142
}
143
144
static void
145 41400
rel_buf(struct buf **bp)
146 41400
{
147 41400
        CHECK_OBJ_NOTNULL(*bp, BUF_MAGIC);
148 760
149 760
        VTAILQ_INSERT_HEAD(&free_bufs, (*bp), list);
150 760
        *bp = NULL;
151 40640
}
152 40640
153 40640
/**********************************************************************
154 40640
 * Parse a -D option argument into a name/val pair, and insert
155
 * into extmacro list
156 40640
 */
157 40640
158 40640
static int
159
parse_D_opt(char *arg)
160 41400
{
161 41400
        char *p, *q;
162
163
        p = arg;
164
        q = strchr(p, '=');
165 41400
        if (!q)
166
                return (0);
167 41400
        *q++ = '\0';
168
        extmacro_def(p, NULL, "%s", q);
169 41400
170 41400
        return (1);
171 41400
}
172
173
/**********************************************************************
174
 * Print usage
175
 */
176
177
static void v_noreturn_
178
usage(void)
179 40
{
180
        fprintf(stderr, "usage: %s [options] file ...\n", argv0);
181
#define FMT "    %-28s # %s\n"
182
        fprintf(stderr, FMT, "-b size",
183 40
            "Set internal buffer size (default: 1M)");
184 40
        fprintf(stderr, FMT, "-C", "Use cleaner subprocess");
185 40
        fprintf(stderr, FMT, "-D name=val", "Define macro");
186 0
        fprintf(stderr, FMT, "-i", "Find varnish binaries in build tree");
187 40
        fprintf(stderr, FMT, "-j jobs", "Run this many tests in parallel");
188 40
        fprintf(stderr, FMT, "-k", "Continue on test failure");
189
        fprintf(stderr, FMT, "-L", "Always leave temporary vtc.*");
190 40
        fprintf(stderr, FMT, "-l", "Leave temporary vtc.* if test fails");
191 40
        fprintf(stderr, FMT, "-n iterations", "Run tests this many times");
192
        fprintf(stderr, FMT, "-p name=val", "Pass a varnishd parameter");
193
        fprintf(stderr, FMT, "-q", "Quiet mode: report only failures");
194
        fprintf(stderr, FMT, "-t duration", "Time tests out after this long");
195
        fprintf(stderr, FMT, "-v", "Verbose mode: always report test log");
196
        exit(1);
197
}
198 120
199
/**********************************************************************
200 120
 * When running many tests, cleaning the tmpdir with "rm -rf" becomes
201
 * chore which limits our performance.
202 120
 * When the number of tests are above 100, we spawn a child-process
203
 * to do that for us.
204 120
 */
205 120
206 120
static void
207 120
cleaner_do(const char *dirname)
208 120
{
209 120
        char buf[BUFSIZ];
210 120
211 120
        AZ(memcmp(dirname, tmppath, strlen(tmppath)));
212 120
        if (cleaner_pid > 0) {
213 120
                bprintf(buf, "%s\n", dirname);
214 120
                assert(write(cleaner_fd, buf, strlen(buf)) == strlen(buf));
215 120
                return;
216 120
        }
217 120
        bprintf(buf, "exec /bin/rm -rf %s\n", dirname);
218
        AZ(system(buf));
219
}
220
221
static void
222
cleaner_setup(void)
223
{
224
        int p[2], st;
225
        char buf[BUFSIZ];
226
        char *q;
227
        pid_t pp;
228 41400
229
        AZ(pipe(p));
230
        assert(p[0] > STDERR_FILENO);
231
        assert(p[1] > STDERR_FILENO);
232 41400
        cleaner_pid = fork();
233 41400
        assert(cleaner_pid >= 0);
234 960
        if (cleaner_pid == 0) {
235 960
                closefd(&p[1]);
236 960
                (void)!nice(1);         /* Not important */
237
                setbuf(stdin, NULL);
238 40440
                AZ(dup2(p[0], STDIN_FILENO));
239 40440
                while (fgets(buf, sizeof buf, stdin)) {
240 41400
                        AZ(memcmp(buf, tmppath, strlen(tmppath)));
241
                        q = buf + strlen(buf);
242
                        assert(q > buf);
243 80
                        assert(q[-1] == '\n');
244
                        q[-1] = '\0';
245
246
                        /* Dont expend a shell on running /bin/rm */
247
                        pp = fork();
248
                        assert(pp >= 0);
249
                        if (pp == 0)
250 80
                                exit(execlp(
251 80
                                    "rm", "rm", "-rf", buf, (char*)0));
252 80
                        assert(waitpid(pp, &st, 0) == pp);
253 80
                        AZ(st);
254 80
                }
255 160
                exit(0);
256 80
        }
257 80
        closefd(&p[0]);
258 80
        cleaner_fd = p[1];
259 80
}
260 1040
261 960
static void
262 960
cleaner_neuter(void)
263 960
{
264 960
        if (cleaner_pid > 0)
265 960
                closefd(&cleaner_fd);
266
}
267
268 960
static void
269 960
cleaner_finish(void)
270 1920
{
271 960
        int st;
272 960
273 960
        if (cleaner_pid > 0) {
274 960
                closefd(&cleaner_fd);
275
                assert(waitpid(cleaner_pid, &st, 0) == cleaner_pid);
276 80
                AZ(st);
277
        }
278 80
}
279 80
280 80
/**********************************************************************
281
 * CallBack
282
 */
283 41400
284
static int
285 41400
tst_cb(const struct vev *ve, int what)
286 960
{
287 41400
        struct vtc_job *jp;
288
        char buf[BUFSIZ];
289
        int ecode;
290 40520
        int i, stx;
291
        pid_t px;
292
        double t;
293
        FILE *f;
294 40520
        char *p;
295 80
296 80
        CAST_OBJ_NOTNULL(jp, ve->priv, JOB_MAGIC);
297 80
        CHECK_OBJ_NOTNULL(jp->tst, TST_MAGIC);
298 80
299 40520
        // printf("CB %p %s %d\n", ve, jp->tst->filename, what);
300
        if (what == 0) {
301
                jp->killed = 1;
302
                AZ(kill(-jp->child, SIGKILL)); /* XXX: Timeout */
303
        } else {
304
                assert(what & (VEV__RD | VEV__HUP));
305
        }
306 41722
307
        *buf = '\0';
308
        i = read(ve->fd, buf, sizeof buf);
309
        if (i > 0)
310
                VSB_bcat(jp->bp->diag, buf, i);
311
        if (i == 0) {
312
313
                njob--;
314
                px = wait4(jp->child, &stx, 0, NULL);
315
                assert(px == jp->child);
316
                t = VTIM_mono() - jp->t0;
317 41722
                AZ(close(ve->fd));
318 41722
319
                ecode = WTERMSIG(stx);
320
                if (ecode == 0)
321 41722
                        ecode = WEXITSTATUS(stx);
322 0
323 0
                AZ(VSB_finish(jp->bp->diag));
324 0
325 41722
                VSB_clear(cbvsb);
326
                VSB_cat(cbvsb, jp->bp->buf);
327
                p = strchr(jp->bp->buf, '\0');
328 41722
                if (p > jp->bp->buf && p[-1] != '\n')
329 41722
                        VSB_putc(cbvsb, '\n');
330 41722
                VSB_quote_pfx(cbvsb, "*    diag  0.0 ",
331 322
                    VSB_data(jp->bp->diag), -1, VSB_QUOTE_NONL);
332 41722
                AZ(VSB_finish(cbvsb));
333
                rel_buf(&jp->bp);
334 41400
335 41400
                if ((ecode > 1 && vtc_verbosity) || vtc_verbosity > 1)
336 41400
                        printf("%s", VSB_data(cbvsb));
337 41400
338 41400
                if (!ecode)
339
                        vtc_good++;
340 41400
                else if (ecode == 1)
341 41400
                        vtc_skip++;
342 41400
                else
343
                        vtc_fail++;
344 41400
345
                if (leave_temp == 0 || (leave_temp == 1 && ecode <= 1)) {
346 41400
                        cleaner_do(jp->tmpdir);
347 41400
                } else {
348 41400
                        bprintf(buf, "%s/LOG", jp->tmpdir);
349 41400
                        f = fopen(buf, "w");
350 0
                        AN(f);
351 82800
                        (void)fprintf(f, "%s\n", VSB_data(cbvsb));
352 41400
                        AZ(fclose(f));
353 41400
                }
354 41400
                free(jp->tmpdir);
355
356 41400
                if (jp->killed)
357 40800
                        printf("#    top  TEST %s TIMED OUT (kill -9)\n",
358
                            jp->tst->filename);
359 41400
                if (ecode > 1) {
360 40720
                        printf("#    top  TEST %s FAILED (%.3f)",
361 680
                            jp->tst->filename, t);
362 640
                        if (WIFSIGNALED(stx))
363
                                printf(" signal=%d\n", WTERMSIG(stx));
364 40
                        else if (WIFEXITED(stx))
365
                                printf(" exit=%d\n", WEXITSTATUS(stx));
366 41400
                        if (!vtc_continue) {
367 41400
                                /* XXX kill -9 other jobs ? */
368 41400
                                exit(2);
369 0
                        }
370 0
                } else if (vtc_verbosity) {
371 0
                        printf("#    top  TEST %s %s (%.3f)\n",
372 0
                            jp->tst->filename,
373 0
                            ecode ? "skipped" : "passed", t);
374
                }
375 41400
                if (jp->evt != NULL) {
376
                        VEV_Stop(vb, jp->evt);
377 41400
                        free(jp->evt);
378 0
                }
379 0
                jp->tst->nwait--;
380 0
                if (jp->tst->nwait == 0) {
381 0
                        free(jp->tst->script);
382 0
                        FREE_OBJ(jp->tst);
383 0
                }
384 0
                FREE_OBJ(jp);
385 0
                return (1);
386 0
        }
387 0
        return (0);
388 0
}
389 0
390 0
/**********************************************************************
391 0
 * Start Test
392 0
 */
393 0
394 0
static void
395
start_test(void)
396 0
{
397 0
        struct vtc_tst *tp;
398
        int p[2], retval;
399 0
        struct vtc_job *jp;
400 0
        char tmpdir[PATH_MAX];
401 0
        char default_n[PATH_MAX];
402 41400
403 40
        ALLOC_OBJ(jp, JOB_MAGIC);
404 40
        AN(jp);
405 40
406 0
        jp->bp = get_buf();
407 40
408 40
        bprintf(tmpdir, "%s/vtc.%d.%08x", tmppath, (int)getpid(),
409 40
                (unsigned)random());
410
        AZ(mkdir(tmpdir, 0755));
411 40
412
        bprintf(default_n, "%s/default_n", tmpdir);
413 41360
414 41320
        AZ(setenv("VARNISH_DEFAULT_N", default_n, 1));
415 41320
416 41320
        tp = VTAILQ_FIRST(&tst_head);
417 41320
        CHECK_OBJ_NOTNULL(tp, TST_MAGIC);
418 41360
        AN(tp->ntodo);
419 41360
        tp->ntodo--;
420 41360
        VTAILQ_REMOVE(&tst_head, tp, list);
421 41360
        if (tp->ntodo > 0)
422 41720
                VTAILQ_INSERT_TAIL(&tst_head, tp, list);
423 41720
424 41000
        jp->tst = tp;
425 41000
        REPLACE(jp->tmpdir, tmpdir);
426 41000
427 41360
        AZ(pipe(p));
428 41360
        assert(p[0] > STDERR_FILENO);
429
        assert(p[1] > STDERR_FILENO);
430 322
        jp->t0 = VTIM_mono();
431 41682
        jp->child = fork();
432
        assert(jp->child >= 0);
433
        if (jp->child == 0) {
434
                cleaner_neuter();       // Too dangerous to have around
435
                AZ(setpgid(getpid(), 0));
436
                VFIL_null_fd(STDIN_FILENO);
437
                assert(dup2(p[1], STDOUT_FILENO) == STDOUT_FILENO);
438 41400
                assert(dup2(p[1], STDERR_FILENO) == STDERR_FILENO);
439
                VSUB_closefrom(STDERR_FILENO + 1);
440
                retval = exec_file(jp->tst->filename, jp->tst->script,
441
                    jp->tmpdir, jp->bp->buf, jp->bp->bufsiz);
442
                exit(retval);
443
        }
444
        closefd(&p[1]);
445
446 41400
        jp->ev = VEV_Alloc();
447 41400
        AN(jp->ev);
448
        jp->ev->fd_flags = VEV__RD | VEV__HUP | VEV__ERR;
449 41400
        jp->ev->fd = p[0];
450
        jp->ev->priv = jp;
451 41400
        jp->ev->callback = tst_cb;
452
        AZ(VEV_Start(vb, jp->ev));
453 41400
454
        jp->evt = VEV_Alloc();
455 41400
        AN(jp->evt);
456
        jp->evt->fd = -1;
457 41400
        jp->evt->timeout = vtc_maxdur;
458
        jp->evt->priv = jp;
459 41400
        jp->evt->callback = tst_cb;
460 41400
        AZ(VEV_Start(vb, jp->evt));
461 41400
}
462 41400
463 41400
/**********************************************************************
464 41400
 * i-mode = "we're inside a src-tree"
465 360
 *
466
 * Find the abs path to top of source dir from Makefile, if that
467 41400
 * fails, fall back on "../../"
468 41400
 *
469
 * Set PATH to all programs build directories
470 41400
 * Set vmod_path to all vmods build directories
471 41400
 *
472 41400
 */
473 41400
474 41400
static char *
475 41400
top_dir(const char *makefile, const char *top_var)
476 82800
{
477 41400
        const char *b, *e;
478 41400
        char *var;
479 41400
480 41400
        AN(makefile);
481 41400
        AN(top_var);
482 82800
        assert(*top_var == '\n');
483 41400
484 41400
        b = strstr(makefile, top_var);
485
        top_var++;
486 41400
487
        if (b == NULL) {
488 41400
                fprintf(stderr, "could not find '%s' in Makefile\n", top_var);
489 41400
                return (NULL);
490 41400
        }
491 41400
492 41400
        e = strchr(b + 1, '\n');
493 41400
        if (e == NULL) {
494 41400
                fprintf(stderr, "No NL after '%s' in Makefile\n", top_var);
495
                return (NULL);
496 41400
        }
497 41400
498 41400
        b = memchr(b, '/', e - b);
499 41400
        if (b == NULL) {
500 41400
                fprintf(stderr, "No '/' after '%s' in Makefile\n", top_var);
501 41400
                return (NULL);
502 41400
        }
503 41400
        var = strndup(b, e - b);
504
        AN(var);
505
        return (var);
506
}
507
508
static void
509
build_path(const char *topdir, const char *subdir,
510
    const char *pfx, const char *sfx, struct vsb *vsb)
511
{
512
        char buf[PATH_MAX];
513
        DIR *dir;
514
        struct dirent *de;
515
        struct stat st;
516
        const char *topsep = "", *sep = "";
517 80560
518
        if (*subdir != '\0')
519
                topsep = "/";
520
        bprintf(buf, "%s%s%s/", topdir, topsep, subdir);
521
        dir = opendir(buf);
522 80560
        XXXAN(dir);
523 80560
        while (1) {
524 80560
                de = readdir(dir);
525
                if (de == NULL)
526 80560
                        break;
527 80560
                if (strncmp(de->d_name, pfx, strlen(pfx)))
528
                        continue;
529 80560
                bprintf(buf, "%s%s%s/%s", topdir, topsep, subdir, de->d_name);
530 0
                if (!stat(buf, &st) && S_ISDIR(st.st_mode)) {
531 0
                        VSB_cat(vsb, sep);
532
                        VSB_cat(vsb, buf);
533
                        VSB_cat(vsb, sfx);
534 80560
                        sep = ":";
535 80560
                }
536 0
        }
537 0
        AZ(closedir(dir));
538
}
539
540 80560
static void
541 80560
i_mode(void)
542 0
{
543 0
        struct vsb *vsb;
544
        char *p, *topbuild, *topsrc;
545 80560
546 80560
        /*
547 80560
         * This code has a rather intimate knowledge of auto* generated
548 80560
         * makefiles.
549
         */
550
551 120840
        vsb = VSB_new_auto();
552
        AN(vsb);
553
554
        p = VFIL_readfile(NULL, "Makefile", NULL);
555
        if (p == NULL) {
556
                fprintf(stderr, "No Makefile to search for -i flag.\n");
557
                exit(2);
558 120840
        }
559
560 120840
        topbuild = top_dir(p, "\nabs_top_builddir");
561 80560
        topsrc = top_dir(p, "\nabs_top_srcdir");
562 120840
        free(p);
563 120840
        if (topbuild == NULL || topsrc == NULL) {
564 120840
                free(topbuild);
565 523640
                free(topsrc);
566 9949280
                exit(2);
567 9949280
        }
568 120840
        extmacro_def("topbuild", NULL, "%s", topbuild);
569 9828440
        extmacro_def("topsrc", NULL, "%s", topsrc);
570 9425640
571 402800
        /*
572 402800
         * Build $PATH which can find all programs in the build tree
573 402800
         */
574 402800
        VSB_clear(vsb);
575 402800
        VSB_cat(vsb, "PATH=");
576 402800
        build_path(topbuild, "bin", "varnish", "", vsb);
577 402800
#ifdef WITH_CONTRIB
578
        VSB_putc(vsb, ':');
579 120840
        build_path(topsrc, "", "contrib", "", vsb);
580 120840
#endif
581
        VSB_printf(vsb, ":%s", getenv("PATH"));
582
        AZ(VSB_finish(vsb));
583 40280
        AZ(putenv(strdup(VSB_data(vsb))));
584
585
        /*
586
         * Build vmod_path which can find all VMODs in the build tree
587
         */
588
589
        VSB_clear(vsb);
590
        build_path(topbuild, "vmod", ".libs", "", vsb);
591
        AZ(VSB_finish(vsb));
592
        vmod_path = strdup(VSB_data(vsb));
593 40280
        AN(vmod_path);
594 40280
595
        free(topbuild);
596 40280
        free(topsrc);
597 40280
        VSB_destroy(&vsb);
598 0
599 0
        /*
600
         * strict jemalloc checking
601
         */
602 40280
        AZ(putenv(strdup("MALLOC_CONF=abort:true,junk:true")));
603 40280
}
604 40280
605 40280
/**********************************************************************
606 0
 * Figure out what IP related magic
607 0
 */
608 0
609
static void
610 40280
ip_magic(void)
611 40280
{
612
        const struct suckaddr *sa;
613
        char abuf[VTCP_ADDRBUFSIZE];
614
        char pbuf[VTCP_PORTBUFSIZE];
615
        char *s;
616 40280
617 40280
        /*
618 40280
         * In FreeBSD jails localhost/127.0.0.1 becomes the jails IP#
619
         * XXX: IPv6-only hosts would have similar issue, but it is not
620 40280
         * XXX: obvious how to cope.  Ideally "127.0.0.1" would be
621 40280
         * XXX: "localhost", but that doesn't work out of the box.
622
         * XXX: Things like "prefer_ipv6" parameter complicates things.
623 40280
         */
624 40280
        sa = VSS_ResolveOne(NULL, "127.0.0.1", "0", 0, SOCK_STREAM, 0);
625 40280
        AN(sa);
626
        bad_backend_fd = VTCP_bind(sa, NULL);
627
        if (bad_backend_fd < 0) {
628
                VSA_free(&sa);
629
                sa = VSS_ResolveFirst(NULL, "localhost", "0", 0, SOCK_STREAM, 0);
630
                AN(sa);
631 40280
                bad_backend_fd = VTCP_bind(sa, NULL);
632 40280
        }
633 40280
        assert(bad_backend_fd >= 0);
634 40280
        VTCP_myname(bad_backend_fd, abuf, sizeof abuf, pbuf, sizeof(pbuf));
635 40280
        extmacro_def("localhost", NULL, "%s", abuf);
636
        s = strdup(abuf);
637 40280
        AN(s);
638 40280
639 40280
#if defined (__APPLE__)
640
        /*
641
         * In macOS a bound socket that is not listening will timeout
642
         * instead of refusing the connection so close it and hope
643
         * for the best.
644 40280
         */
645 40280
        VTCP_close(&bad_backend_fd);
646
#endif
647
648
        /* Expose a backend that is forever down. */
649
        if (VSA_Get_Proto(sa) == AF_INET)
650
                extmacro_def("bad_backend", NULL, "%s:%s", abuf, pbuf);
651
        else
652 40560
                extmacro_def("bad_backend", NULL, "[%s]:%s", abuf, pbuf);
653
654
        /* our default bind/listen address */
655
        if (VSA_Get_Proto(sa) == AF_INET)
656
                bprintf(abuf, "%s:0", s);
657
        else
658
                bprintf(abuf, "[%s]:0", s);
659
        free(s);
660
661
        extmacro_def("listen_addr", NULL, "%s", abuf);
662
        default_listen_addr = strdup(abuf);
663
        AN(default_listen_addr);
664
        VSA_free(&sa);
665
666 40560
        /*
667 40560
         * We need an IP number which will not respond, ever, and that is a
668 40560
         * lot harder than it sounds.  This IP# is from RFC5737 and a
669 40560
         * C-class broadcast at that.
670 0
         * If tests involving ${bad_ip} fails and you run linux, you should
671 0
         * check your /proc/sys/net/ipv4/ip_nonlocal_bind setting.
672 0
         */
673 0
674 0
        extmacro_def("bad_ip", NULL, "%s", "192.0.2.255");
675 40560
}
676 40560
677 40560
/**********************************************************************
678 40560
 * Macros
679 40560
 */
680
681
static char * v_matchproto_(macro_f)
682
macro_func_date(int argc, char *const *argv, const char **err)
683
{
684
        double t;
685
        char *s;
686
687
        assert(argc >= 2);
688
        AN(argv);
689
        AN(err);
690
691 40560
        if (argc > 2) {
692 40560
                *err = "macro does not take arguments";
693
                return (NULL);
694 0
        }
695
696
        t = VTIM_real();
697 40560
        s = malloc(VTIM_FORMAT_SIZE);
698 40560
        AN(s);
699
        VTIM_format(t, s);
700 0
        return (s);
701 40560
}
702
703 40560
static char *
704 40560
macro_func_string_repeat(int argc, char *const *argv, const char **err)
705 40560
{
706 40560
        struct vsb vsb[1];
707
        const char *p;
708
        char *res;
709
        size_t l;
710
        int i;
711
712
        if (argc != 4) {
713
                *err = "repeat takes 2 arguments";
714
                return (NULL);
715
        }
716 40560
717 40560
        p = argv[2];
718
        i = SF_Parse_Integer(&p, err);
719
720
        if (*err != NULL)
721
                return (NULL);
722
723
        if (*p != '\0' || i < 0) {
724 88075
                *err = "invalid number of repetitions";
725
                return (NULL);
726
        }
727
728
        l = (strlen(argv[3]) * i) + 1;
729 88075
        res = malloc(l);
730 88075
        AN(res);
731 88075
        AN(VSB_init(vsb, res, l));
732
        while (i > 0) {
733 88075
                AZ(VSB_cat(vsb, argv[3]));
734 0
                i--;
735 0
        }
736
        AZ(VSB_finish(vsb));
737
        VSB_fini(vsb);
738 88075
        return (res);
739 88075
}
740 88075
741 88075
static char *
742 88075
macro_func_string(int argc, char *const *argv, const char **err)
743 88075
{
744
745
        assert(argc >= 2);
746 1560
        AN(argv);
747
        AN(err);
748
749
        if (argc == 2) {
750
                *err = "missing action";
751
                return (NULL);
752
        }
753
754 1560
        if (!strcmp(argv[2], "repeat"))
755 0
                return (macro_func_string_repeat(argc - 1, argv + 1, err));
756 0
757
        *err = "unknown action";
758
        return (NULL);
759 1560
}
760 1560
761
/**********************************************************************
762 1560
 * Main
763 0
 */
764
765 1560
static int
766 0
read_file(const char *fn, int ntest)
767 0
{
768
        struct vtc_tst *tp;
769
        char *p, *q;
770 1560
771 1560
        p = VFIL_readfile(NULL, fn, NULL);
772 1560
        if (p == NULL) {
773 1560
                fprintf(stderr, "Cannot stat file \"%s\": %s\n",
774 1301160
                    fn, strerror(errno));
775 1299600
                return (2);
776 1299600
        }
777
        for (q = p ;q != NULL && *q != '\0'; q++) {
778 1560
                if (vct_islws(*q))
779 1560
                        continue;
780 1560
                if (*q != '#')
781 1560
                        break;
782
                q = strchr(q, '\n');
783
                if (q == NULL)
784 1560
                        break;
785
        }
786
787 1560
        if (q == NULL || *q == '\0') {
788 1560
                fprintf(stderr, "File \"%s\" has no content.\n", fn);
789 1560
                free(p);
790
                return (2);
791 1560
        }
792 0
793 0
        if ((strncmp(q, "varnishtest", 11) || !isspace(q[11])) &&
794
            (strncmp(q, "vtest", 5) || !isspace(q[5]))) {
795
                fprintf(stderr,
796 1560
                    "File \"%s\" doesn't start with"
797 1560
                    " 'vtest' or 'varnishtest'\n", fn);
798
                free(p);
799 0
                vtc_skip++;
800 0
                return (2);
801 1560
        }
802
        ALLOC_OBJ(tp, TST_MAGIC);
803
        AN(tp);
804
        tp->filename = fn;
805
        tp->script = p;
806
        tp->ntodo = ntest;
807
        tp->nwait = ntest;
808 41160
        VTAILQ_INSERT_TAIL(&tst_head, tp, list);
809
        return (0);
810
}
811
812
/**********************************************************************
813 41160
 * Main
814 41160
 */
815 80
816 40
int
817 40
main(int argc, char * const *argv)
818
{
819 41200
        int ch, i;
820 41200
        int ntest = 1;                  /* Run tests this many times */
821 80
        int nstart = 0;
822 41120
        int use_cleaner = 0;
823 41120
        uintmax_t bufsiz;
824 0
        const char *p;
825 0
        char buf[PATH_MAX];
826 0
827 0
        argv0 = strrchr(argv[0], '/');
828
        if (argv0 == NULL)
829 41120
                argv0 = argv[0];
830 0
        else
831 0
                argv0++;
832 0
833
        if (getenv("TMPDIR") != NULL)
834
                tmppath = strdup(getenv("TMPDIR"));
835 43520
        else
836 2400
                tmppath = strdup("/tmp");
837 160
838
#ifdef PACKAGE_VERSION
839 80
        extmacro_def("pkg_version", NULL, PACKAGE_VERSION);
840 80
#endif
841 80
#ifdef PACKAGE_BRANCH
842 80
        extmacro_def("pkg_branch", NULL, PACKAGE_BRANCH);
843
#endif
844 41040
845 41040
        cwd = getcwd(buf, sizeof buf);
846 41040
        extmacro_def("pwd", NULL, "%s", cwd);
847 41040
848 41040
        extmacro_def("date", macro_func_date, NULL);
849 41040
        extmacro_def("string", macro_func_string, NULL);
850 41040
851 41040
        vmod_path = NULL;
852 41160
853
        params_vsb = VSB_new_auto();
854
        AN(params_vsb);
855
        p = getenv("VTEST_DURATION");
856
        if (p == NULL)
857
                p = getenv("VARNISHTEST_DURATION");
858
        if (p != NULL)
859 0
                vtc_maxdur = atoi(p);
860
861
        VRND_SeedAll();
862 0
        cbvsb = VSB_new_auto();
863 0
        AN(cbvsb);
864
        setbuf(stdout, NULL);
865 0
        setbuf(stderr, NULL);
866
        while ((ch = getopt(argc, argv, "b:CD:hij:kLln:p:qt:vW")) != -1) {
867
                switch (ch) {
868
                case 'b':
869
                        if (VNUM_2bytes(optarg, &bufsiz, 0)) {
870
                                fprintf(stderr, "Cannot parse b opt '%s'\n",
871
                                    optarg);
872
                                exit(2);
873
                        }
874 0
                        if (bufsiz > UINT_MAX) {
875
                                fprintf(stderr, "Invalid b opt '%s'\n",
876 0
                                    optarg);
877 0
                                exit(2);
878 0
                        }
879 0
                        vtc_bufsiz = (unsigned)bufsiz;
880 0
                        break;
881
                case 'C':
882 0
                        use_cleaner = !use_cleaner;
883 0
                        break;
884 0
                case 'D':
885
                        if (!parse_D_opt(optarg)) {
886 0
                                fprintf(stderr, "Cannot parse D opt '%s'\n",
887 0
                                    optarg);
888 0
                                exit(2);
889 0
                        }
890
                        break;
891 0
                case 'i':
892 0
                        iflg = 1;
893
                        break;
894
                case 'j':
895
                        npar = strtoul(optarg, NULL, 0);
896
                        break;
897
                case 'L':
898
                        leave_temp = 2;
899 40760
                        break;
900
                case 'l':
901
                        leave_temp = 1;
902
                        break;
903
                case 'k':
904 122360
                        vtc_continue = !vtc_continue;
905 81680
                        break;
906
                case 'n':
907 80
                        ntest = strtoul(optarg, NULL, 0);
908 0
                        break;
909 0
                case 'p':
910 0
                        VSB_cat(params_vsb, " -p ");
911
                        VSB_quote(params_vsb, optarg, -1, 0);
912 80
                        break;
913 0
                case 'q':
914 0
                        if (vtc_verbosity > 0)
915 0
                                vtc_verbosity--;
916
                        break;
917 80
                case 't':
918 80
                        vtc_maxdur = strtoul(optarg, NULL, 0);
919
                        break;
920 120
                case 'v':
921 120
                        if (vtc_verbosity < 2)
922
                                vtc_verbosity++;
923 40
                        break;
924 0
                default:
925 0
                        usage();
926 0
                }
927
        }
928 40
        argc -= optind;
929
        argv += optind;
930 0
931 0
        if (argc < 1)
932
                usage();
933 40280
934 40280
        for (; argc > 0; argc--, argv++) {
935
                if (!read_file(*argv, ntest))
936 80
                        continue;
937 80
                if (!vtc_continue)
938
                        exit(2);
939 80
        }
940 80
941
        AZ(VSB_finish(params_vsb));
942 120
943 120
        ip_magic();
944
945 40
        if (iflg)
946 40
                i_mode();
947
948 80
        vb = VEV_New();
949 80
950
        if (use_cleaner)
951 40
                cleaner_setup();
952 40
953 40
        i = 0;
954
        while (!VTAILQ_EMPTY(&tst_head) || i) {
955 40
                if (!VTAILQ_EMPTY(&tst_head) && njob < npar) {
956 40
                        start_test();
957 40
                        njob++;
958
                        /* Stagger ramp-up */
959 40
                        if (nstart++ < npar)
960 40
                                (void)usleep(random() % 100000L);
961
                        i = 1;
962 40560
                        continue;
963 40560
                }
964 40560
                i = VEV_Once(vb);
965
        }
966 80
        cleaner_finish();
967
        (void)close(bad_backend_fd);
968
        if (vtc_continue)
969 40680
                fprintf(stderr,
970 40680
                    "%d tests failed, %d tests skipped, %d tests passed\n",
971
                    vtc_fail, vtc_skip, vtc_good);
972 40680
        if (vtc_fail)
973 40
                return (1);
974
        if (vtc_skip && !vtc_good)
975 81720
                return (77);
976 41160
        return (0);
977 41040
}