varnish-cache/bin/varnishtest/vtc_main.c
1
/*-
2
 * Copyright (c) 2008-2011 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * are met:
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 * 2. Redistributions in binary form must reproduce the above copyright
13
 *    notice, this list of conditions and the following disclaimer in the
14
 *    documentation and/or other materials provided with the distribution.
15
 *
16
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
20
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
 * SUCH DAMAGE.
27
 */
28
29
#include "config.h"
30 6136
31 6136
#include <sys/mman.h>
32 6136
#include <sys/stat.h>
33 6136
#include <sys/wait.h>
34 6136
35 6136
#include <ctype.h>
36 6136
#include <poll.h>
37 6136
#include <stdio.h>
38 3068
#include <stdlib.h>
39
#include <string.h>
40
#include <unistd.h>
41
#include <sys/socket.h>
42
43
#include "vtc.h"
44
45
#include "vev.h"
46
#include "vfil.h"
47
#include "vnum.h"
48
#include "vrnd.h"
49
#include "vss.h"
50
#include "vsub.h"
51
#include "vtcp.h"
52
#include "vtim.h"
53
#include "vct.h"
54
55
static const char *argv0;
56
57
struct buf {
58
        unsigned                magic;
59
#define BUF_MAGIC               0x39d1258a
60
        VTAILQ_ENTRY(buf)       list;
61
        char                    *buf;
62
        struct vsb              *diag;
63
        size_t                  bufsiz;
64
};
65
66
static VTAILQ_HEAD(, buf) free_bufs = VTAILQ_HEAD_INITIALIZER(free_bufs);
67
68
struct vtc_tst {
69
        unsigned                magic;
70
#define TST_MAGIC               0x618d8b88
71
        VTAILQ_ENTRY(vtc_tst)   list;
72
        const char              *filename;
73
        char                    *script;
74
        unsigned                ntodo;
75
};
76
77
struct vtc_job {
78
        unsigned                magic;
79
#define JOB_MAGIC               0x1b5fc419
80
        struct vtc_tst          *tst;
81
        pid_t                   child;
82
        struct vev              *ev;
83
        struct vev              *evt;
84
        struct buf              *bp;
85
        char                    *tmpdir;
86
        double                  t0;
87
        int                     killed;
88
};
89
90
91
int iflg = 0;
92
unsigned vtc_maxdur = 60;
93
static unsigned vtc_bufsiz = 1024 * 1024;
94
95
static VTAILQ_HEAD(, vtc_tst) tst_head = VTAILQ_HEAD_INITIALIZER(tst_head);
96
static struct vev_root *vb;
97
static int njob = 0;
98
static int npar = 1;                    /* Number of parallel tests */
99
static int vtc_continue;                /* Continue on error */
100
static int vtc_verbosity = 1;           /* Verbosity Level */
101
static int vtc_good;
102
static int vtc_fail;
103
static int vtc_skip;
104
static char *tmppath;
105
static char *cwd = NULL;
106
char *vmod_path = NULL;
107
struct vsb *params_vsb = NULL;
108
int leave_temp;
109
int vtc_witness = 0;
110
static struct vsb *cbvsb;
111
static int bad_backend_fd;
112
113
static int cleaner_fd = -1;
114
static pid_t cleaner_pid;
115
116
static struct buf *
117 3184
get_buf(void)
118
{
119
        struct buf *bp;
120
121 3184
        bp = VTAILQ_FIRST(&free_bufs);
122 3184
        CHECK_OBJ_ORNULL(bp, BUF_MAGIC);
123 3184
        if (bp != NULL) {
124 88
                VTAILQ_REMOVE(&free_bufs, bp, list);
125 88
                VSB_clear(bp->diag);
126 88
        } else {
127 3096
                ALLOC_OBJ(bp, BUF_MAGIC);
128 3096
                AN(bp);
129 3096
                bp->bufsiz = vtc_bufsiz;
130 3096
                bp->buf = mmap(NULL, bp->bufsiz, PROT_READ|PROT_WRITE,
131
                    MAP_ANON | MAP_SHARED, -1, 0);
132 3096
                assert(bp->buf != MAP_FAILED);
133 3096
                bp->diag = VSB_new_auto();
134 3096
                AN(bp->diag);
135
        }
136 3184
        memset(bp->buf, 0, bp->bufsiz);
137 3184
        return (bp);
138
}
139
140
static void
141 3184
rel_buf(struct buf **bp)
142
{
143 3184
        CHECK_OBJ_NOTNULL(*bp, BUF_MAGIC);
144
145 3184
        VTAILQ_INSERT_HEAD(&free_bufs, (*bp), list);
146 3184
        *bp = NULL;
147 3184
}
148
149
/**********************************************************************
150
 * Parse a -D option argument into a name/val pair, and insert
151
 * into extmacro list
152
 */
153
154
static int
155 8
parse_D_opt(char *arg)
156
{
157
        char *p, *q;
158
159 8
        p = arg;
160 8
        q = strchr(p, '=');
161 8
        if (!q)
162 0
                return (0);
163 8
        *q++ = '\0';
164 8
        extmacro_def(p, "%s", q);
165
166 8
        return (1);
167 8
}
168
169
/**********************************************************************
170
 * Print usage
171
 */
172
173
static void
174 16
usage(void)
175
{
176 16
        fprintf(stderr, "usage: %s [options] file ...\n", argv0);
177
#define FMT "    %-28s # %s\n"
178 16
        fprintf(stderr, FMT, "-b size",
179
            "Set internal buffer size (default: 1M)");
180 16
        fprintf(stderr, FMT, "-C", "Use cleaner subprocess");
181 16
        fprintf(stderr, FMT, "-D name=val", "Define macro");
182 16
        fprintf(stderr, FMT, "-i", "Find varnish binaries in build tree");
183 16
        fprintf(stderr, FMT, "-j jobs", "Run this many tests in parallel");
184 16
        fprintf(stderr, FMT, "-k", "Continue on test failure");
185 16
        fprintf(stderr, FMT, "-L", "Always leave temporary vtc.*");
186 16
        fprintf(stderr, FMT, "-l", "Leave temporary vtc.* if test fails");
187 16
        fprintf(stderr, FMT, "-n iterations", "Run tests this many times");
188 16
        fprintf(stderr, FMT, "-p name=val", "Pass a varnishd parameter");
189 16
        fprintf(stderr, FMT, "-q", "Quiet mode: report only failures");
190 16
        fprintf(stderr, FMT, "-t duration", "Time tests out after this long");
191 16
        fprintf(stderr, FMT, "-v", "Verbose mode: always report test log");
192 16
        fprintf(stderr, FMT, "-W", "Enable the witness facility for locking");
193 16
        exit(1);
194 0
}
195
196
/**********************************************************************
197
 * When running many tests, cleaning the tmpdir with "rm -rf" becomes
198
 * chore which limits our performance.
199
 * When the number of tests are above 100, we spawn a child-process
200
 * to do that for us.
201
 */
202
203
static void
204 3184
cleaner_do(const char *dirname)
205
{
206
        char buf[BUFSIZ];
207
208 3184
        AZ(memcmp(dirname, tmppath, strlen(tmppath)));
209 3184
        if (cleaner_pid > 0) {
210 92
                bprintf(buf, "%s\n", dirname);
211 92
                assert(write(cleaner_fd, buf, strlen(buf)) == strlen(buf));
212 92
                return;
213
        }
214 3092
        bprintf(buf, "exec /bin/rm -rf %s\n", dirname);
215 3092
        AZ(system(buf));
216 3184
}
217
218
static void
219 4
cleaner_setup(void)
220
{
221
        int p[2], st;
222
        char buf[BUFSIZ];
223
        char *q;
224
        pid_t pp;
225
226 4
        AZ(pipe(p));
227 4
        assert(p[0] > STDERR_FILENO);
228 4
        assert(p[1] > STDERR_FILENO);
229 4
        cleaner_pid = fork();
230 8
        assert(cleaner_pid >= 0);
231 8
        if (cleaner_pid == 0) {
232 4
                closefd(&p[1]);
233 4
                (void)nice(1);          /* Not important */
234 4
                setbuf(stdin, NULL);
235 4
                AZ(dup2(p[0], STDIN_FILENO));
236 96
                while (fgets(buf, sizeof buf, stdin)) {
237 92
                        AZ(memcmp(buf, tmppath, strlen(tmppath)));
238 92
                        q = buf + strlen(buf);
239 92
                        assert(q > buf);
240 92
                        assert(q[-1] == '\n');
241 92
                        q[-1] = '\0';
242
243
                        /* Dont expend a shell on running /bin/rm */
244 92
                        pp = fork();
245 184
                        assert(pp >= 0);
246 184
                        if (pp == 0)
247 92
                                exit(execl(
248 92
                                    "/bin/rm", "rm", "-rf", buf, (char*)0));
249 92
                        assert(waitpid(pp, &st, 0) == pp);
250 92
                        AZ(st);
251
                }
252 4
                exit(0);
253
        }
254 4
        closefd(&p[0]);
255 4
        cleaner_fd = p[1];
256 4
}
257
258
static void
259 3184
cleaner_neuter(void)
260
{
261 3184
        if (cleaner_pid > 0)
262 92
                closefd(&cleaner_fd);
263 3184
}
264
265
static void
266 3096
cleaner_finish(void)
267
{
268
        int st;
269
270 3096
        if (cleaner_pid > 0) {
271 4
                closefd(&cleaner_fd);
272 4
                assert(waitpid(cleaner_pid, &st, 0) == cleaner_pid);
273 4
                AZ(st);
274 4
        }
275 3096
}
276
277
/**********************************************************************
278
 * CallBack
279
 */
280
281
static int
282 3184
tst_cb(const struct vev *ve, int what)
283
{
284
        struct vtc_job *jp;
285
        char buf[BUFSIZ];
286
        int ecode;
287
        int i, stx;
288
        pid_t px;
289
        double t;
290
        FILE *f;
291
        char *p;
292
293 3184
        CAST_OBJ_NOTNULL(jp, ve->priv, JOB_MAGIC);
294
295
        // printf("CB %p %s %d\n", ve, jp->tst->filename, what);
296 3184
        if (what == 0) {
297 0
                jp->killed = 1;
298 0
                AZ(kill(-jp->child, SIGKILL)); /* XXX: Timeout */
299 0
        } else {
300 3184
                assert(what & (VEV__RD | VEV__HUP));
301
        }
302
303 3184
        *buf = '\0';
304 3184
        i = read(ve->fd, buf, sizeof buf);
305 3184
        if (i > 0)
306 0
                VSB_bcat(jp->bp->diag, buf, i);
307 3184
        if (i == 0) {
308
309 3184
                njob--;
310 3184
                px = wait4(jp->child, &stx, 0, NULL);
311 3184
                assert(px == jp->child);
312 3184
                t = VTIM_mono() - jp->t0;
313 3184
                AZ(close(ve->fd));
314
315 3184
                ecode = WTERMSIG(stx);
316 3184
                if (ecode == 0)
317 3184
                        ecode = WEXITSTATUS(stx);
318
319 3184
                AZ(VSB_finish(jp->bp->diag));
320
321 3184
                VSB_clear(cbvsb);
322 3184
                VSB_cat(cbvsb, jp->bp->buf);
323 3184
                p = strchr(jp->bp->buf, '\0');
324 3184
                if (p > jp->bp->buf && p[-1] != '\n')
325 0
                        VSB_putc(cbvsb, '\n');
326 6368
                VSB_quote_pfx(cbvsb, "*    diag  0.0 ",
327 3184
                    VSB_data(jp->bp->diag), -1, VSB_QUOTE_NONL);
328 3184
                AZ(VSB_finish(cbvsb));
329 3184
                rel_buf(&jp->bp);
330
331 3184
                if ((ecode > 1 && vtc_verbosity) || vtc_verbosity > 1)
332 3084
                        printf("%s", VSB_data(cbvsb));
333
334 3184
                if (!ecode)
335 3140
                        vtc_good++;
336 44
                else if (ecode == 1)
337 36
                        vtc_skip++;
338
                else
339 8
                        vtc_fail++;
340
341 3184
                if (leave_temp == 0 || (leave_temp == 1 && ecode <= 1)) {
342 3184
                        cleaner_do(jp->tmpdir);
343 3184
                } else {
344 0
                        bprintf(buf, "%s/LOG", jp->tmpdir);
345 0
                        f = fopen(buf, "w");
346 0
                        AN(f);
347 0
                        (void)fprintf(f, "%s\n", VSB_data(cbvsb));
348 0
                        AZ(fclose(f));
349
                }
350 3184
                free(jp->tmpdir);
351
352 3184
                if (jp->killed)
353 0
                        printf("#    top  TEST %s TIMED OUT (kill -9)\n",
354 0
                            jp->tst->filename);
355 3184
                if (ecode > 1) {
356 8
                        printf("#    top  TEST %s FAILED (%.3f)",
357 8
                            jp->tst->filename, t);
358 8
                        if (WIFSIGNALED(stx))
359 0
                                printf(" signal=%d\n", WTERMSIG(stx));
360 8
                        else if (WIFEXITED(stx))
361 8
                                printf(" exit=%d\n", WEXITSTATUS(stx));
362 8
                        if (!vtc_continue) {
363
                                /* XXX kill -9 other jobs ? */
364 8
                                exit(2);
365
                        }
366 3176
                } else if (vtc_verbosity) {
367 3168
                        printf("#    top  TEST %s %s (%.3f)\n",
368 3168
                            jp->tst->filename,
369 3168
                            ecode ? "skipped" : "passed", t);
370 3168
                }
371 3176
                if (jp->evt != NULL) {
372 3176
                        VEV_Stop(vb, jp->evt);
373 3176
                        free(jp->evt);
374 3176
                }
375 3176
                FREE_OBJ(jp);
376 3176
                return (1);
377
        }
378 0
        return (0);
379 3176
}
380
381
/**********************************************************************
382
 * Start Test
383
 */
384
385
static void
386 3184
start_test(void)
387
{
388
        struct vtc_tst *tp;
389
        int p[2], retval;
390
        struct vtc_job *jp;
391
        char tmpdir[PATH_MAX];
392
393 3184
        ALLOC_OBJ(jp, JOB_MAGIC);
394 3184
        AN(jp);
395
396 3184
        jp->bp = get_buf();
397
398 3184
        bprintf(tmpdir, "%s/vtc.%d.%08x", tmppath, (int)getpid(),
399
                (unsigned)random());
400 3184
        AZ(mkdir(tmpdir, 0711));
401
402 3184
        tp = VTAILQ_FIRST(&tst_head);
403 3184
        CHECK_OBJ_NOTNULL(tp, TST_MAGIC);
404 3184
        AN(tp->ntodo);
405 3184
        tp->ntodo--;
406 3184
        VTAILQ_REMOVE(&tst_head, tp, list);
407 3184
        if (tp->ntodo > 0)
408 0
                VTAILQ_INSERT_TAIL(&tst_head, tp, list);
409
410 3184
        jp->tst = tp;
411 3184
        jp->tmpdir = strdup(tmpdir);
412 3184
        AN(jp->tmpdir);
413
414 3184
        AZ(pipe(p));
415 3184
        assert(p[0] > STDERR_FILENO);
416 3184
        assert(p[1] > STDERR_FILENO);
417 3184
        jp->t0 = VTIM_mono();
418 3184
        jp->child = fork();
419 6368
        assert(jp->child >= 0);
420 6368
        if (jp->child == 0) {
421 3184
                cleaner_neuter();       // Too dangerous to have around
422 3184
                AZ(setpgid(getpid(), 0));
423 3184
                VFIL_null_fd(STDIN_FILENO);
424 3184
                assert(dup2(p[1], STDOUT_FILENO) == STDOUT_FILENO);
425 3184
                assert(dup2(p[1], STDERR_FILENO) == STDERR_FILENO);
426 3184
                VSUB_closefrom(STDERR_FILENO + 1);
427 6368
                retval = exec_file(jp->tst->filename, jp->tst->script,
428 3184
                    jp->tmpdir, jp->bp->buf, jp->bp->bufsiz);
429 3184
                exit(retval);
430
        }
431 3184
        closefd(&p[1]);
432
433 3184
        jp->ev = VEV_Alloc();
434 3184
        AN(jp->ev);
435 3184
        jp->ev->fd_flags = VEV__RD | VEV__HUP | VEV__ERR;
436 3184
        jp->ev->fd = p[0];
437 3184
        jp->ev->priv = jp;
438 3184
        jp->ev->callback = tst_cb;
439 3184
        AZ(VEV_Start(vb, jp->ev));
440
441 3184
        jp->evt = VEV_Alloc();
442 3184
        AN(jp->evt);
443 3184
        jp->evt->fd = -1;
444 3184
        jp->evt->timeout = vtc_maxdur;
445 3184
        jp->evt->priv = jp;
446 3184
        jp->evt->callback = tst_cb;
447 3184
        AZ(VEV_Start(vb, jp->evt));
448 3184
}
449
450
/**********************************************************************
451
 * i-mode = "we're inside a src-tree"
452
 *
453
 * Find the abs path to top of source dir from Makefile, if that
454
 * fails, fall back on "../../"
455
 *
456
 * Set path to all programs build directories
457
 *
458
 */
459
460
static void
461 3068
i_mode(void)
462
{
463
        const char *sep;
464
        struct vsb *vsb;
465
        char *p, *q;
466
        char *topbuild;
467
468
        /*
469
         * This code has a rather intimate knowledge of auto* generated
470
         * makefiles.
471
         */
472
473 3068
        vsb = VSB_new_auto();
474 3068
        AN(vsb);
475
476 3068
        q = p = VFIL_readfile(NULL, "Makefile", NULL);
477 3068
        if (p == NULL) {
478 0
                fprintf(stderr, "No Makefile to search for -i flag.\n");
479 0
                VSB_printf(vsb, "%s/../..", cwd);
480 0
                AZ(VSB_finish(vsb));
481 0
                topbuild = strdup(VSB_data(vsb));
482 0
                VSB_clear(vsb);
483 0
        } else {
484 3068
                p = strstr(p, "\nabs_top_builddir");
485 3068
                if (p == NULL) {
486 0
                        fprintf(stderr,
487
                            "could not find 'abs_top_builddir' in Makefile\n");
488 0
                        exit(2);
489
                }
490 3068
                topbuild =  strchr(p + 1, '\n');
491 3068
                if (topbuild == NULL) {
492 0
                        fprintf(stderr,
493
                            "No NL after 'abs_top_builddir' in Makefile\n");
494 0
                        exit(2);
495
                }
496 3068
                *topbuild = '\0';
497 3068
                topbuild = strchr(p, '/');
498 3068
                if (topbuild == NULL) {
499 0
                        fprintf(stderr,
500
                            "No '/' after 'abs_top_builddir' in Makefile\n");
501 0
                        exit(2);
502
                }
503 3068
                topbuild = strdup(topbuild);
504 3068
                free(q);
505
506
        }
507 3068
        AN(topbuild);
508 3068
        extmacro_def("topbuild", "%s", topbuild);
509
        /*
510
         * Build $PATH which can find all programs in the build tree
511
         */
512 3068
        VSB_printf(vsb, "PATH=");
513 3068
        sep = "";
514
#define VTC_PROG(l)                                                     \
515
        do {                                                            \
516
                VSB_printf(vsb, "%s%s/bin/" #l, sep, topbuild);         \
517
                sep = ":";                                              \
518
        } while (0);
519
#include "programs.h"
520
521 3068
        VSB_printf(vsb, ":%s", getenv("PATH"));
522 3068
        AZ(VSB_finish(vsb));
523
524 3068
        AZ(putenv(strdup(VSB_data(vsb))));
525
526
        /*
527
         * Build vmod_path which can find all VMODs in the build tree
528
         */
529 3068
        VSB_clear(vsb);
530 3068
        sep = "";
531
#define VTC_VMOD(l)                                                     \
532
        do {                                                            \
533
                VSB_printf(vsb, "%s%s/lib/libvmod_" #l "/.libs",        \
534
                    sep, topbuild);                                     \
535
                sep = ":";                                              \
536
        } while (0);
537
#include "vmods.h"
538
#undef VTC_VMOD
539 3068
        AZ(VSB_finish(vsb));
540 3068
        vmod_path = strdup(VSB_data(vsb));
541 3068
        AN(vmod_path);
542 3068
        free(topbuild);
543 3068
        VSB_destroy(&vsb);
544
545
        /*
546
         * strict jemalloc checking
547
         */
548 3068
        AZ(putenv(strdup("MALLOC_CONF=abort:true,junk:true")));
549 3068
}
550
551
/**********************************************************************
552
 * Figure out what IP related magic
553
 */
554
555
static void
556 3104
ip_magic(void)
557
{
558
        struct suckaddr *sa;
559
        char abuf[VTCP_ADDRBUFSIZE];
560
        char pbuf[VTCP_PORTBUFSIZE];
561
562
        /*
563
         * In FreeBSD jails localhost/127.0.0.1 becomes the jails IP#
564
         * XXX: IPv6-only hosts would have similar issue, but it is not
565
         * XXX: obvious how to cope.  Ideally "127.0.0.1" would be
566
         * XXX: "localhost", but that doesn't work out of the box.
567
         * XXX: Things like "prefer_ipv6" parameter complicates things.
568
         */
569 3104
        sa = VSS_ResolveOne(NULL, "127.0.0.1", "0", 0, SOCK_STREAM, 0);
570 3104
        AN(sa);
571 3104
        bad_backend_fd = VTCP_bind(sa, NULL);
572 3104
        assert(bad_backend_fd >= 0);
573 3104
        VTCP_myname(bad_backend_fd, abuf, sizeof abuf, pbuf, sizeof(pbuf));
574 3104
        extmacro_def("localhost", "%s", abuf);
575
576
#if defined (__APPLE__)
577
        /*
578
         * In MacOS a bound socket that is not listening will timeout
579
         * instead of refusing the connection so close it and hope
580
         * for the best.
581
         */
582
        VTCP_close(&bad_backend_fd);
583
#endif
584
585
        /* Expose a backend that is forever down. */
586 3104
        extmacro_def("bad_backend", "%s %s", abuf, pbuf);
587
588
        /*
589
         * We need an IP number which will not repond, ever, and that is a
590
         * lot harder than it sounds.  This IP# is from RFC5737 and a
591
         * C-class broadcast at that.
592
         * If tests involving ${bad_ip} fails and you run linux, you should
593
         * check your /proc/sys/net/ipv4/ip_nonlocal_bind setting.
594
         */
595
596 3104
        extmacro_def("bad_ip", "%s", "192.0.2.255");
597 3104
}
598
599
/**********************************************************************
600
 * Main
601
 */
602
603
static int
604 3200
read_file(const char *fn, int ntest)
605
{
606
        struct vtc_tst *tp;
607
        char *p, *q;
608
609 3200
        p = VFIL_readfile(NULL, fn, NULL);
610 3200
        if (p == NULL) {
611 0
                fprintf(stderr, "Cannot stat file \"%s\": %s\n",
612 0
                    fn, strerror(errno));
613 0
                return (2);
614
        }
615 3200
        for (q = p ;q != NULL && *q != '\0'; q++) {
616 3200
                if (vct_islws(*q))
617 0
                        continue;
618 3200
                if (*q != '#')
619 3200
                        break;
620 0
                q = strchr(q, '\n');
621 0
                if (q == NULL)
622 0
                        break;
623 0
        }
624
625 3200
        if (q == NULL || *q == '\0') {
626 0
                fprintf(stderr, "File \"%s\" has no content.\n", fn);
627 0
                free(p);
628 0
                return (2);
629
        }
630
631 3208
        if ((strncmp(q, "varnishtest", 11) || !isspace(q[11])) &&
632 24
            (strncmp(q, "vtest", 5) || !isspace(q[5]))) {
633 32
                fprintf(stderr,
634
                    "File \"%s\" doesn't start with"
635 16
                    " 'vtest' or 'varnishtest'\n", fn);
636 16
                free(p);
637 16
                vtc_skip++;
638 16
                return (2);
639
        }
640 3184
        ALLOC_OBJ(tp, TST_MAGIC);
641 3184
        AN(tp);
642 3184
        tp->filename = fn;
643 3184
        tp->script = p;
644 3184
        tp->ntodo = ntest;
645 3184
        VTAILQ_INSERT_TAIL(&tst_head, tp, list);
646 3184
        return (0);
647 3200
}
648
649
/**********************************************************************
650
 * Main
651
 */
652
653
int
654 3128
main(int argc, char * const *argv)
655
{
656
        int ch, i;
657 3128
        int ntest = 1;                  /* Run tests this many times */
658 3128
        int nstart = 0;
659 3128
        int use_cleaner = 0;
660
        uintmax_t bufsiz;
661
        const char *p;
662
663 3128
        argv0 = strrchr(argv[0], '/');
664 3128
        if (argv0 == NULL)
665 0
                argv0 = argv[0];
666
        else
667 3128
                argv0++;
668
669 3128
        if (getenv("TMPDIR") != NULL)
670 3120
                tmppath = strdup(getenv("TMPDIR"));
671
        else
672 8
                tmppath = strdup("/tmp");
673
674 3128
        cwd = getcwd(NULL, PATH_MAX);
675 3128
        extmacro_def("pwd", "%s", cwd);
676
677 3128
        vmod_path = NULL;
678
679 3128
        params_vsb = VSB_new_auto();
680 3128
        AN(params_vsb);
681 3128
        p = getenv("VTEST_DURATION");
682 3128
        if (p == NULL)
683 3128
                p = getenv("VARNISHTEST_DURATION");
684 3128
        if (p != NULL)
685 0
                vtc_maxdur = atoi(p);
686
687 3128
        VRND_SeedAll();
688 3128
        cbvsb = VSB_new_auto();
689 3128
        AN(cbvsb);
690 3128
        setbuf(stdout, NULL);
691 3128
        setbuf(stderr, NULL);
692 9324
        while ((ch = getopt(argc, argv, "b:CD:hij:kLln:p:qt:vW")) != -1) {
693 6212
                switch (ch) {
694
                case 'b':
695 0
                        if (VNUM_2bytes(optarg, &bufsiz, 0)) {
696 0
                                fprintf(stderr, "Cannot parse b opt '%s'\n",
697 0
                                    optarg);
698 0
                                exit(2);
699
                        }
700 0
                        if (bufsiz > UINT_MAX) {
701 0
                                fprintf(stderr, "Invalid b opt '%s'\n",
702 0
                                    optarg);
703 0
                                exit(2);
704
                        }
705 0
                        vtc_bufsiz = (unsigned)bufsiz;
706 0
                        break;
707
                case 'C':
708 4
                        use_cleaner = !use_cleaner;
709 4
                        break;
710
                case 'D':
711 8
                        if (!parse_D_opt(optarg)) {
712 0
                                fprintf(stderr, "Cannot parse D opt '%s'\n",
713 0
                                    optarg);
714 0
                                exit(2);
715
                        }
716 8
                        break;
717
                case 'i':
718 3068
                        iflg = 1;
719 3068
                        break;
720
                case 'j':
721 0
                        npar = strtoul(optarg, NULL, 0);
722 0
                        break;
723
                case 'L':
724 0
                        leave_temp = 2;
725 0
                        break;
726
                case 'l':
727 0
                        leave_temp = 1;
728 0
                        break;
729
                case 'k':
730 8
                        vtc_continue = !vtc_continue;
731 8
                        break;
732
                case 'n':
733 0
                        ntest = strtoul(optarg, NULL, 0);
734 0
                        break;
735
                case 'p':
736 4
                        VSB_printf(params_vsb, " -p ");
737 4
                        VSB_quote(params_vsb, optarg, -1, 0);
738 4
                        break;
739
                case 'q':
740 8
                        if (vtc_verbosity > 0)
741 8
                                vtc_verbosity--;
742 8
                        break;
743
                case 't':
744 4
                        vtc_maxdur = strtoul(optarg, NULL, 0);
745 4
                        break;
746
                case 'v':
747 3092
                        if (vtc_verbosity < 2)
748 3092
                                vtc_verbosity++;
749 3092
                        break;
750
                case 'W':
751 0
                        vtc_witness++;
752 0
                        break;
753
                default:
754 16
                        usage();
755 16
                }
756
        }
757 3112
        argc -= optind;
758 3112
        argv += optind;
759
760 3112
        if (argc < 1)
761 0
                usage();
762
763 6304
        for (; argc > 0; argc--, argv++) {
764 3200
                if (!read_file(*argv, ntest))
765 3184
                        continue;
766 16
                if (!vtc_continue)
767 8
                        exit(2);
768 8
        }
769
770 3104
        AZ(VSB_finish(params_vsb));
771
772 3104
        ip_magic();
773
774 3104
        if (iflg)
775 3068
                i_mode();
776
777 3104
        vb = VEV_New();
778
779 3104
        if (use_cleaner)
780 4
                cleaner_setup();
781
782 3104
        i = 0;
783 12560
        while (!VTAILQ_EMPTY(&tst_head) || i) {
784 9456
                if (!VTAILQ_EMPTY(&tst_head) && njob < npar) {
785 3184
                        start_test();
786 3184
                        njob++;
787
                        /* Stagger ramp-up */
788 3184
                        if (nstart++ < npar)
789 3096
                                (void)usleep(random() % 100000L);
790 3184
                        i = 1;
791 3184
                        continue;
792
                }
793 6272
                i = VEV_Once(vb);
794
        }
795 3096
        cleaner_finish();
796 3096
        (void)close(bad_backend_fd);
797 3096
        if (vtc_continue)
798 16
                fprintf(stderr,
799
                    "%d tests failed, %d tests skipped, %d tests passed\n",
800 8
                    vtc_fail, vtc_skip, vtc_good);
801 3096
        if (vtc_fail)
802 0
                return (1);
803 3096
        if (vtc_skip && !vtc_good)
804 44
                return (77);
805 3052
        return (0);
806 3096
}