varnish-cache/bin/varnishtest/vtc.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/wait.h>
33
34
#include <ctype.h>
35
#include <stdarg.h>
36
#include <stdio.h>
37
#include <stdlib.h>
38
#include <string.h>
39
#include <unistd.h>
40
41
#include "vtc.h"
42
#include "vtc_log.h"
43
44
#include "vav.h"
45
#include "vrnd.h"
46
47
#define         MAX_TOKENS              200
48
49
volatile sig_atomic_t   vtc_error;      /* Error encountered */
50
int                     vtc_stop;       /* Stops current test without error */
51
pthread_t               vtc_thread;
52
int                     ign_unknown_macro = 0;
53
static struct vtclog    *vltop;
54
55
static pthread_mutex_t  vtc_vrnd_mtx;
56
57
static void
58 165120
vtc_vrnd_lock(void)
59
{
60 165120
        PTOK(pthread_mutex_lock(&vtc_vrnd_mtx));
61 165120
}
62
63
static void
64 165120
vtc_vrnd_unlock(void)
65
{
66 165120
        PTOK(pthread_mutex_unlock(&vtc_vrnd_mtx));
67 165120
}
68
69
static const char *tfn;
70
71
/**********************************************************************
72
 * Macro facility
73
 */
74
75
struct macro {
76
        unsigned                magic;
77
#define MACRO_MAGIC             0x803423e3
78
        VTAILQ_ENTRY(macro)     list;
79
        char                    *name;
80
        char                    *val;
81
        macro_f                 *func;
82
};
83
84
static VTAILQ_HEAD(,macro) macro_list = VTAILQ_HEAD_INITIALIZER(macro_list);
85
86
static const struct cmds global_cmds[] = {
87
#define CMD_GLOBAL(n) { #n, cmd_##n },
88
#include "cmds.h"
89
        { NULL, NULL }
90
};
91
92
static const struct cmds top_cmds[] = {
93
#define CMD_TOP(n) { #n, cmd_##n },
94
#include "cmds.h"
95
        { NULL, NULL }
96
};
97
98
/**********************************************************************/
99
100
static struct macro *
101 1012360
macro_def_int(const char *name, macro_f *func, const char *fmt, va_list ap)
102
{
103
        struct macro *m;
104
        char buf[2048];
105
106 13556240
        VTAILQ_FOREACH(m, &macro_list, list)
107 12564880
                if (!strcmp(name, m->name))
108 21000
                        break;
109 1012360
        if (m == NULL) {
110 991360
                ALLOC_OBJ(m, MACRO_MAGIC);
111 991360
                AN(m);
112 991360
                REPLACE(m->name, name);
113 991360
                AN(m->name);
114 991360
                VTAILQ_INSERT_TAIL(&macro_list, m, list);
115 991360
        }
116 1012360
        AN(m);
117 1012360
        if (func != NULL) {
118 79840
                AZ(fmt);
119 79840
                m->func = func;
120 79840
        } else {
121 932520
                AN(fmt);
122 932520
                vbprintf(buf, fmt, ap);
123 932520
                REPLACE(m->val, buf);
124 932520
                AN(m->val);
125
        }
126 1012360
        return (m);
127
}
128
129
130
/**********************************************************************
131
 * This is for defining macros before we fork the child process which
132
 * runs the test-case.
133
 */
134
135
void
136 436400
extmacro_def(const char *name, macro_f *func, const char *fmt, ...)
137
{
138
        va_list ap;
139
140 436400
        va_start(ap, fmt);
141 436400
        (void)macro_def_int(name, func, fmt, ap);
142 436400
        va_end(ap);
143 436400
}
144
145
/**********************************************************************
146
 * Below this point is run inside the testing child-process.
147
 */
148
149
static pthread_mutex_t          macro_mtx;
150
151
static void
152 40800
init_macro(void)
153
{
154
        struct macro *m;
155
156
        /* Dump the extmacros for completeness */
157 488240
        VTAILQ_FOREACH(m, &macro_list, list) {
158 447440
                if (m->val != NULL)
159 731680
                        vtc_log(vltop, 4,
160 365840
                            "extmacro def %s=%s", m->name, m->val);
161
                else
162 81600
                        vtc_log(vltop, 4, "extmacro def %s(...)", m->name);
163 447440
        }
164
165 40800
        PTOK(pthread_mutex_init(&macro_mtx, NULL));
166 40800
}
167
168
void
169 575960
macro_def(struct vtclog *vl, const char *instance, const char *name,
170
    const char *fmt, ...)
171
{
172
        char buf1[256];
173
        struct macro *m;
174
        va_list ap;
175
176 575960
        AN(fmt);
177
178 575960
        if (instance != NULL) {
179 453560
                bprintf(buf1, "%s_%s", instance, name);
180 453560
                name = buf1;
181 453560
        }
182
183 575960
        PTOK(pthread_mutex_lock(&macro_mtx));
184 575960
        va_start(ap, fmt);
185 575960
        m = macro_def_int(name, NULL, fmt, ap);
186 575960
        va_end(ap);
187 575960
        vtc_log(vl, 4, "macro def %s=%s", name, m->val);
188 575960
        PTOK(pthread_mutex_unlock(&macro_mtx));
189 575960
}
190
191
void
192 143202
macro_undef(struct vtclog *vl, const char *instance, const char *name)
193
{
194
        char buf1[256];
195
        struct macro *m;
196
197 143202
        if (instance != NULL) {
198 143197
                bprintf(buf1, "%s_%s", instance, name);
199 143197
                name = buf1;
200 143197
        }
201
202 143202
        PTOK(pthread_mutex_lock(&macro_mtx));
203 2322718
        VTAILQ_FOREACH(m, &macro_list, list)
204 2314876
                if (!strcmp(name, m->name))
205 135360
                        break;
206 143202
        if (m != NULL) {
207 135360
                if (!vtc_stop)
208 7200
                        vtc_log(vl, 4, "macro undef %s", name);
209 135360
                CHECK_OBJ(m, MACRO_MAGIC);
210 135360
                VTAILQ_REMOVE(&macro_list, m, list);
211 135360
                free(m->name);
212 135360
                free(m->val);
213 135360
                FREE_OBJ(m);
214 135360
        }
215 143202
        PTOK(pthread_mutex_unlock(&macro_mtx));
216 143202
}
217
218
unsigned
219 75600
macro_isdef(const char *instance, const char *name)
220
{
221
        char buf1[256];
222
        struct macro *m;
223
224 75600
        if (instance != NULL) {
225 0
                bprintf(buf1, "%s_%s", instance, name);
226 0
                name = buf1;
227 0
        }
228
229 75600
        PTOK(pthread_mutex_lock(&macro_mtx));
230 1386000
        VTAILQ_FOREACH(m, &macro_list, list)
231 1310400
                if (!strcmp(name, m->name))
232 0
                        break;
233 75600
        PTOK(pthread_mutex_unlock(&macro_mtx));
234
235 75600
        return (m != NULL);
236
}
237
238
void
239 477310
macro_cat(struct vtclog *vl, struct vsb *vsb, const char *b, const char *e)
240
{
241
        struct macro *m;
242 477310
        char **argv, *retval = NULL;
243 477310
        const char *err = NULL;
244
        int argc;
245
246 477310
        AN(b);
247 477310
        if (e == NULL)
248 252594
                e = strchr(b, '\0');
249 477310
        AN(e);
250
251 477310
        argv = VAV_ParseTxt(b, e, &argc, ARGV_COMMA);
252 477310
        AN(argv);
253
254 477310
        if (*argv != NULL)
255 0
                vtc_fatal(vl, "Macro ${%.*s} parsing failed: %s",
256 0
                    (int)(e - b), b, *argv);
257
258 477310
        assert(argc >= 2);
259
260 477310
        PTOK(pthread_mutex_lock(&macro_mtx));
261 4467272
        VTAILQ_FOREACH(m, &macro_list, list) {
262 4465273
                CHECK_OBJ_NOTNULL(m, MACRO_MAGIC);
263 4465273
                if (!strcmp(argv[1], m->name))
264 475311
                        break;
265 3989962
        }
266 477310
        if (m != NULL) {
267 475311
                if (m->func != NULL) {
268 88511
                        AZ(m->val);
269 88511
                        retval = m->func(argc, argv, &err);
270 88511
                        if (err == NULL)
271 88511
                                AN(retval);
272 88511
                } else {
273 386800
                        AN(m->val);
274 386800
                        if (argc == 2)
275 386800
                                REPLACE(retval, m->val);
276
                        else
277 0
                                err = "macro does not take arguments";
278
                }
279 475311
        }
280 477310
        PTOK(pthread_mutex_unlock(&macro_mtx));
281
282 477310
        VAV_Free(argv);
283
284 477310
        if (err != NULL)
285 0
                vtc_fatal(vl, "Macro ${%.*s} failed: %s",
286 0
                    (int)(e - b), b, err);
287
288 477310
        if (retval == NULL) {
289 2000
                if (!ign_unknown_macro)
290 0
                        vtc_fatal(vl, "Macro ${%.*s} not found",
291 0
                            (int)(e - b), b);
292 2000
                VSB_printf(vsb, "${%.*s}", (int)(e - b), b);
293 2000
                return;
294
        }
295
296 475310
        VSB_cat(vsb, retval);
297 475310
        free(retval);
298 477310
}
299
300
struct vsb *
301 57155
macro_expandf(struct vtclog *vl, const char *fmt, ...)
302
{
303
        va_list ap;
304
        struct vsb *vsb1, *vsb2;
305
306 57155
        vsb1 = VSB_new_auto();
307 57155
        AN(vsb1);
308 57155
        va_start(ap, fmt);
309 57155
        VSB_vprintf(vsb1, fmt, ap);
310 57155
        va_end(ap);
311 57155
        AZ(VSB_finish(vsb1));
312 57155
        vsb2 = macro_expand(vl, VSB_data(vsb1));
313 57155
        VSB_destroy(&vsb1);
314 57155
        return (vsb2);
315
}
316
317
struct vsb *
318 213400
macro_expand(struct vtclog *vl, const char *text)
319
{
320
        struct vsb *vsb;
321
        const char *p, *q;
322
323 213400
        vsb = VSB_new_auto();
324 213400
        AN(vsb);
325 438080
        while (*text != '\0') {
326 362160
                p = strstr(text, "${");
327 362160
                if (p == NULL) {
328 137480
                        VSB_cat(vsb, text);
329 137480
                        break;
330
                }
331 224680
                VSB_bcat(vsb, text, p - text);
332 224680
                q = strchr(p, '}');
333 224680
                if (q == NULL) {
334 0
                        VSB_cat(vsb, text);
335 0
                        break;
336
                }
337 224680
                assert(p[0] == '$');
338 224680
                assert(p[1] == '{');
339 224680
                assert(q[0] == '}');
340 224680
                p += 2;
341 224680
                macro_cat(vl, vsb, p, q);
342 224680
                text = q + 1;
343
        }
344 213400
        AZ(VSB_finish(vsb));
345 213400
        return (vsb);
346
}
347
348
/**********************************************************************
349
 * Parse a string
350
 *
351
 * We make a copy of the string and deliberately leak it, so that all
352
 * the cmd functions we call don't have to strdup(3) all over the place.
353
 *
354
 * Static checkers like Coverity may bitch about this, but we don't care.
355
 */
356
357
358
void
359 318051
parse_string(struct vtclog *vl, void *priv, const char *spec)
360
{
361
        char *token_s[MAX_TOKENS], *token_e[MAX_TOKENS];
362
        struct vsb *token_exp;
363
        char *e, *p, *q, *f, *buf;
364
        int nest_brace;
365
        int tn;
366
        unsigned n, m;
367
        const struct cmds *cp;
368
369 318051
        AN(spec);
370 318051
        buf = strdup(spec);
371 318051
        AN(buf);
372 318051
        e = strchr(buf, '\0');
373 318051
        AN(e);
374 4169524
        for (p = buf; p < e; p++) {
375 3852676
                if (vtc_error || vtc_stop)
376 1213
                        break;
377
                /* Start of line */
378 3851463
                if (isspace(*p))
379 2255321
                        continue;
380 1596142
                if (*p == '\n')
381 0
                        continue;
382
383 1596142
                if (*p == '#') {
384 3648124
                        for (; *p != '\0' && *p != '\n'; p++)
385
                                ;
386 88720
                        if (*p == '\0')
387 0
                                break;
388 88720
                        continue;
389
                }
390
391 1507422
                q = strchr(p, '\n');
392 1507422
                if (q == NULL)
393 15759
                        q = strchr(p, '\0');
394 1507422
                if (q - p > 60)
395 117106
                        vtc_log(vl, 2, "=== %.60s...", p);
396
                else
397 1390316
                        vtc_log(vl, 2, "=== %.*s", (int)(q - p), p);
398
399
                /* First content on line, collect tokens */
400 1507422
                memset(token_s, 0, sizeof token_s);
401 1507422
                memset(token_e, 0, sizeof token_e);
402 1507422
                tn = 0;
403 1507422
                f = p;
404 10155764
                while (p < e) {
405 10140362
                        assert(tn < MAX_TOKENS);
406 10140362
                        assert(p < e);
407 10140362
                        if (*p == '\n') { /* End on NL */
408 1492020
                                break;
409
                        }
410 8648342
                        if (isspace(*p)) { /* Inter-token whitespace */
411 3670503
                                p++;
412 3670503
                                continue;
413
                        }
414 4977839
                        if (*p == '\\' && p[1] == '\n') { /* line-cont */
415 39280
                                p += 2;
416 39280
                                continue;
417
                        }
418 4938559
                        if (*p == '"') { /* quotes */
419 475578
                                token_s[tn] = ++p;
420 475578
                                q = p;
421 11461587
                                for (; *p != '\0'; p++) {
422 11460947
                                        assert(p < e);
423 11460947
                                        if (*p == '"')
424 474938
                                                break;
425 10986009
                                        if (*p == '\\') {
426 111936
                                                p += VAV_BackSlash(p, q) - 1;
427 111936
                                                q++;
428 111936
                                        } else {
429 10874073
                                                if (*p == '\n')
430 0
                                                        vtc_fatal(vl,
431
                                "Unterminated quoted string in line: %*.*s",
432 0
                                (int)(p - f), (int)(p - f), f);
433 10874073
                                                assert(*p != '\n');
434 10874073
                                                *q++ = *p;
435
                                        }
436 10986009
                                }
437 475578
                                token_e[tn++] = q;
438 475578
                                p++;
439 4938559
                        } else if (*p == '{') { /* Braces */
440 307605
                                nest_brace = 0;
441 307605
                                token_s[tn] = p + 1;
442 49813904
                                for (; p < e; p++) {
443 49813904
                                        if (*p == '{')
444 563485
                                                nest_brace++;
445 49250419
                                        else if (*p == '}') {
446 563485
                                                if (--nest_brace == 0)
447 307605
                                                        break;
448 255880
                                        }
449 49506299
                                }
450 307605
                                assert(*p == '}');
451 307605
                                token_e[tn++] = p++;
452 307605
                        } else { /* other tokens */
453 4155376
                                token_s[tn] = p;
454 191002785
                                for (; p < e && !isspace(*p); p++)
455 186847409
                                        continue;
456 4155376
                                token_e[tn++] = p;
457
                        }
458
                }
459
460 1507422
                assert(p <= e);
461 1507422
                assert(tn < MAX_TOKENS);
462 1507422
                token_s[tn] = NULL;
463 6446120
                for (tn = 0; token_s[tn] != NULL; tn++) {
464 4938698
                        AN(token_e[tn]);        /*lint !e771 */
465 4938698
                        *token_e[tn] = '\0';    /*lint !e771 */
466 4938698
                        if (NULL != strstr(token_s[tn], "${")) {
467 43000
                                token_exp = macro_expand(vl, token_s[tn]);
468 43000
                                if (vtc_error)
469 0
                                        return;
470 43000
                                token_s[tn] = VSB_data(token_exp);
471 43000
                                token_e[tn] = strchr(token_s[tn], '\0');
472 43000
                        }
473 4938698
                }
474
475
476
/* SECTION: loop loop
477
 *
478
 * loop NUMBER STRING
479
 *         Process STRING as a specification, NUMBER times.
480
 *
481
 * This works inside all specification strings
482
 */
483
484 1507422
                if (!strcmp(token_s[0], "loop")) {
485 1737
                        n = strtoul(token_s[1], NULL, 0);
486 72168
                        for (m = 0; m < n; m++) {
487 70431
                                vtc_log(vl, 4, "Loop #%u", m);
488 70431
                                parse_string(vl, priv, token_s[2]);
489 70431
                        }
490 1737
                        continue;
491
                }
492
493 1505685
                AN(vl->cmds);
494 26551872
                for (cp = vl->cmds; cp->name != NULL; cp++)
495 26479026
                        if (!strcmp(token_s[0], cp->name))
496 1432839
                                break;
497
498 1505685
                if (cp->name == NULL) {
499 135569
                        for (cp = global_cmds; cp->name != NULL; cp++)
500 135571
                                if (!strcmp(token_s[0], cp->name))
501 72902
                                        break;
502 72910
                }
503
504 1505695
                if (cp->name == NULL)
505 0
                        vtc_fatal(vl, "Unknown command: \"%s\"", token_s[0]);
506
507 1505695
                assert(cp->cmd != NULL);
508 1505695
                cp->cmd(token_s, priv, vl);
509 1505695
        }
510 317401
}
511
512
/**********************************************************************
513
 * Reset commands (between tests)
514
 */
515
516
static void
517 81600
reset_cmds(const struct cmds *cmd)
518
{
519
520 816000
        for (; cmd->name != NULL; cmd++)
521 734400
                cmd->cmd(NULL, NULL, NULL);
522 81600
}
523
524
/**********************************************************************
525
 * Execute a file
526
 */
527
528
int
529 40800
fail_out(void)
530
{
531
        unsigned old_err;
532
        static int once = 0;
533
534 40800
        if (once++) {
535 0
                vtc_log(vltop, 1, "failure during reset");
536 0
                return (vtc_error);
537
        }
538 40800
        old_err = vtc_error;
539 40800
        if (!vtc_stop)
540 40200
                vtc_stop = 1;
541 40800
        vtc_log(vltop, 1, "RESETTING after %s", tfn);
542 40800
        reset_cmds(global_cmds);
543 40800
        reset_cmds(top_cmds);
544 40800
        vtc_error |= old_err;
545
546 40800
        if (vtc_error)
547 80
                vtc_log(vltop, 1, "TEST %s FAILED", tfn);
548
        else
549 40720
                vtc_log(vltop, 1, "TEST %s completed", tfn);
550
551 40800
        if (vtc_stop > 1)
552 600
                return (1);
553 40200
        return (vtc_error);
554 40800
}
555
556
int
557 40800
exec_file(const char *fn, const char *script, const char *tmpdir,
558
    char *logbuf, unsigned loglen)
559
{
560
        FILE *f;
561
        struct vsb *vsb;
562
        const char *p;
563
564 40800
        AN(tmpdir);
565
566 40800
        (void)signal(SIGPIPE, SIG_IGN);
567
568 40800
        PTOK(pthread_mutex_init(&vtc_vrnd_mtx, NULL));
569 40800
        VRND_Lock = vtc_vrnd_lock;
570 40800
        VRND_Unlock = vtc_vrnd_unlock;
571 40800
        VRND_SeedAll();
572
573 40800
        tfn = fn;
574 40800
        vtc_loginit(logbuf, loglen);
575 40800
        vltop = vtc_logopen("top");
576 40800
        AN(vltop);
577 40800
        vtc_log_set_cmd(vltop, top_cmds);
578
579 40800
        vtc_log(vltop, 1, "TEST %s starting", fn);
580
581 40800
        init_macro();
582 40800
        init_server();
583 40800
        init_syslog();
584 40800
        init_tunnel();
585
586 40800
        vsb = VSB_new_auto();
587 40800
        AN(vsb);
588 40800
        if (*fn != '/')
589 40400
                macro_cat(vltop, vsb, "pwd", NULL);
590 40800
        p = strrchr(fn, '/');
591 40800
        if (p != NULL) {
592 40480
                VSB_putc(vsb, '/');
593 40480
                VSB_bcat(vsb, fn, p - fn);
594 40480
        }
595 40800
        if (VSB_len(vsb) == 0)
596 0
                VSB_putc(vsb, '/');
597 40800
        AZ(VSB_finish(vsb));
598 40800
        macro_def(vltop, NULL, "testdir", "%s", VSB_data(vsb));
599 40800
        VSB_destroy(&vsb);
600
601
        /* Move into our tmpdir */
602 40800
        AZ(chdir(tmpdir));
603 40800
        macro_def(vltop, NULL, "tmpdir", "%s", tmpdir);
604 40800
        p = strrchr(tmpdir, '/');
605 40800
        AN(p);
606 40800
        p++;
607 40800
        AN(*p);
608 40800
        macro_def(vltop, NULL, "vtcid", "%s", p);
609
610
        /* Drop file to tell what was going on here */
611 40800
        f = fopen("INFO", "w");
612 40800
        AN(f);
613 40800
        fprintf(f, "Test case: %s\n", fn);
614 40800
        AZ(fclose(f));
615
616 40800
        vtc_stop = 0;
617
618 40800
        vtc_thread = pthread_self();
619 40800
        parse_string(vltop, NULL, script);
620 40800
        return (fail_out());
621
}