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