varnish-cache/bin/varnishtest/vtest2/src/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
vtc_vrnd_lock(void)
59
{
60
        PTOK(pthread_mutex_lock(&vtc_vrnd_mtx));
61 681240
}
62
63 681240
static void
64 681240
vtc_vrnd_unlock(void)
65
{
66
        PTOK(pthread_mutex_unlock(&vtc_vrnd_mtx));
67 681240
}
68
69 681240
static const char *tfn;
70 681240
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 745200
#include "cmds.h"
89
        { NULL, NULL }
90
};
91
92 745200
static const struct cmds top_cmds[] = {
93 745200
#define CMD_TOP(n) { #n, cmd_##n },
94 745200
#include "cmds.h"
95 745200
        { NULL, NULL }
96 745200
};
97 745200
98 745200
/**********************************************************************/
99 745200
100 745200
static struct macro *
101 745200
macro_def_int(const char *name, macro_f *func, const char *fmt, va_list ap)
102 745200
{
103 745200
        struct macro *m;
104
        char buf[2048];
105
106 537105
        VTAILQ_FOREACH(m, &macro_list, list)
107
                if (!strcmp(name, m->name))
108
                        break;
109
        if (m == NULL) {
110
                ALLOC_OBJ(m, MACRO_MAGIC);
111 4967402
                AN(m);
112 4967362
                REPLACE(m->name, name);
113 4967362
                AN(m->name);
114 4967362
                VTAILQ_INSERT_TAIL(&macro_list, m, list);
115 537065
        }
116 4430297
        AN(m);
117
        if (func != NULL) {
118 40
                AZ(fmt);
119 40
                m->func = func;
120 40
        } else {
121 40
                AN(fmt);
122 40
                vbprintf(buf, fmt, ap);
123
                REPLACE(m->val, buf);
124 0
                AN(m->val);
125
        }
126 0
        return (m);
127 0
}
128 0
129 0
130 0
/**********************************************************************
131 0
 * This is for defining macros before we fork the child process which
132 0
 * runs the test-case.
133 537105
 */
134
135
void
136 41400
extmacro_def(const char *name, macro_f *func, const char *fmt, ...)
137
{
138
        va_list ap;
139
140
        va_start(ap, fmt);
141
        (void)macro_def_int(name, func, fmt, ap);
142
        va_end(ap);
143
}
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
init_macro(void)
153
{
154
        struct macro *m;
155
156
        /* Dump the extmacros for completeness */
157
        VTAILQ_FOREACH(m, &macro_list, list) {
158
                if (m->val != NULL)
159
                        vtc_log(vltop, 4,
160
                            "extmacro def %s=%s", m->name, m->val);
161
                else
162 0
                        vtc_log(vltop, 4, "extmacro def %s(...)", m->name);
163
        }
164
165
        PTOK(pthread_mutex_init(&macro_mtx, NULL));
166
}
167 0
168 0
void
169 0
macro_def(struct vtclog *vl, const char *instance, const char *name,
170 0
    const char *fmt, ...)
171 0
{
172 0
        char buf1[256];
173
        struct macro *m;
174 0
        va_list ap;
175
176 0
        AN(fmt);
177 0
178 0
        if (instance != NULL) {
179 0
                bprintf(buf1, "%s_%s", instance, name);
180 0
                name = buf1;
181 0
        }
182
183
        PTOK(pthread_mutex_lock(&macro_mtx));
184 41400
        va_start(ap, fmt);
185
        m = macro_def_int(name, NULL, fmt, ap);
186
        va_end(ap);
187
        vtc_log(vl, 4, "macro def %s=%s", name, m->val);
188 41400
        PTOK(pthread_mutex_unlock(&macro_mtx));
189 0
}
190 0
191 0
void
192 0
macro_undef(struct vtclog *vl, const char *instance, const char *name)
193 0
{
194 0
        char buf1[256];
195
        struct macro *m;
196 0
197 41400
        if (instance != NULL) {
198 41400
                bprintf(buf1, "%s_%s", instance, name);
199
                name = buf1;
200
        }
201
202
        PTOK(pthread_mutex_lock(&macro_mtx));
203
        VTAILQ_FOREACH(m, &macro_list, list)
204
                if (!strcmp(name, m->name))
205
                        break;
206
        if (m != NULL) {
207
                if (!vtc_stop)
208
                        vtc_log(vl, 4, "macro undef %s", name);
209
                CHECK_OBJ(m, MACRO_MAGIC);
210
                VTAILQ_REMOVE(&macro_list, m, list);
211
                free(m->name);
212
                free(m->val);
213
                FREE_OBJ(m);
214
        }
215
        PTOK(pthread_mutex_unlock(&macro_mtx));
216
}
217
218 1033840
unsigned
219
macro_isdef(const char *instance, const char *name)
220
{
221
        char buf1[256];
222
        struct macro *m;
223 13839840
224 12828320
        if (instance != NULL) {
225 22320
                bprintf(buf1, "%s_%s", instance, name);
226 1033840
                name = buf1;
227 1011520
        }
228 1011520
229 1011520
        PTOK(pthread_mutex_lock(&macro_mtx));
230 1011520
        VTAILQ_FOREACH(m, &macro_list, list)
231 1011520
                if (!strcmp(name, m->name))
232 1011520
                        break;
233 1033840
        PTOK(pthread_mutex_unlock(&macro_mtx));
234 1033840
235 81520
        return (m != NULL);
236 81520
}
237 81520
238 952320
void
239 952320
macro_cat(struct vtclog *vl, struct vsb *vsb, const char *b, const char *e)
240 952320
{
241 952320
        struct macro *m;
242
        char **argv, *retval = NULL;
243 1033840
        const char *err = NULL;
244
        int argc;
245
246
        AN(b);
247
        if (e == NULL)
248
                e = strchr(b, '\0');
249
        AN(e);
250
251
        argv = VAV_ParseTxt(b, e, &argc, ARGV_COMMA);
252
        AN(argv);
253 446640
254
        if (*argv != NULL)
255
                vtc_fatal(vl, "Macro ${%.*s} parsing failed: %s",
256
                    (int)(e - b), b, *argv);
257 446640
258 446640
        assert(argc >= 2);
259 446640
260 446640
        PTOK(pthread_mutex_lock(&macro_mtx));
261
        VTAILQ_FOREACH(m, &macro_list, list) {
262
                CHECK_OBJ_NOTNULL(m, MACRO_MAGIC);
263
                if (!strcmp(argv[1], m->name))
264
                        break;
265
        }
266
        if (m != NULL) {
267
                if (m->func != NULL) {
268
                        AZ(m->val);
269 41400
                        retval = m->func(argc, argv, &err);
270
                        if (err == NULL)
271
                                AN(retval);
272
                } else {
273
                        AN(m->val);
274 495640
                        if (argc == 2)
275 454240
                                REPLACE(retval, m->val);
276 742880
                        else
277 371440
                                err = "macro does not take arguments";
278
                }
279 82800
        }
280 454240
        PTOK(pthread_mutex_unlock(&macro_mtx));
281
282 41400
        VAV_Free(argv);
283 41400
284
        if (err != NULL)
285
                vtc_fatal(vl, "Macro ${%.*s} failed: %s",
286 587200
                    (int)(e - b), b, err);
287
288
        if (retval == NULL) {
289
                if (!ign_unknown_macro)
290
                        vtc_fatal(vl, "Macro ${%.*s} not found",
291
                            (int)(e - b), b);
292
                VSB_printf(vsb, "${%.*s}", (int)(e - b), b);
293 587200
                return;
294
        }
295 587200
296 463000
        VSB_cat(vsb, retval);
297 463000
        free(retval);
298 463000
}
299
300 587200
struct vsb *
301 587200
macro_expandf(struct vtclog *vl, const char *fmt, ...)
302 587200
{
303 587200
        va_list ap;
304 587200
        struct vsb *vsb1, *vsb2;
305 587200
306 587200
        vsb1 = VSB_new_auto();
307
        AN(vsb1);
308
        va_start(ap, fmt);
309 143787
        VSB_vprintf(vsb1, fmt, ap);
310
        va_end(ap);
311
        AZ(VSB_finish(vsb1));
312
        vsb2 = macro_expand(vl, VSB_data(vsb1));
313
        VSB_destroy(&vsb1);
314 143787
        return (vsb2);
315 143787
}
316 143787
317 143787
struct vsb *
318
macro_expand(struct vtclog *vl, const char *text)
319 143787
{
320 2327956
        struct vsb *vsb;
321 2319649
        const char *p, *q;
322 135480
323 143787
        vsb = VSB_new_auto();
324 135480
        AN(vsb);
325 7840
        while (*text != '\0') {
326 135480
                p = strstr(text, "${");
327 135480
                if (p == NULL) {
328 135480
                        VSB_cat(vsb, text);
329 135480
                        break;
330 135480
                }
331 135480
                VSB_bcat(vsb, text, p - text);
332 143787
                q = strchr(p, '}');
333 143787
                if (q == NULL) {
334
                        VSB_cat(vsb, text);
335
                        break;
336 77520
                }
337
                assert(p[0] == '$');
338
                assert(p[1] == '{');
339
                assert(q[0] == '}');
340
                p += 2;
341 77520
                macro_cat(vl, vsb, p, q);
342 0
                text = q + 1;
343 0
        }
344 0
        AZ(VSB_finish(vsb));
345
        return (vsb);
346 77520
}
347 1422160
348 1344640
/**********************************************************************
349 0
 * Parse a string
350 77520
 *
351
 * We make a copy of the string and deliberately leak it, so that all
352 77520
 * 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 487715
357
358
void
359 487715
parse_string(struct vtclog *vl, void *priv, const char *spec)
360 487715
{
361
        char *token_s[MAX_TOKENS], *token_e[MAX_TOKENS];
362
        struct vsb *token_exp;
363 487715
        char *e, *p, *q, *f, *buf;
364 487715
        int nest_brace;
365 258662
        int tn;
366 487715
        unsigned n, m;
367
        const struct cmds *cp;
368 487715
369 487715
        AN(spec);
370
        buf = strdup(spec);
371 487715
        AN(buf);
372 0
        e = strchr(buf, '\0');
373 0
        AN(e);
374
        for (p = buf; p < e; p++) {
375 487715
                if (vtc_error || vtc_stop) {
376
                        vtc_log(vl, 1, "Aborting execution, test %s",
377 487715
                            vtc_error ? "failed" : "ended");
378 4577006
                        break;
379 4574446
                }
380 4574446
                /* Start of line */
381 485155
                if (isspace(*p))
382 4089291
                        continue;
383 487715
                if (*p == '\n')
384 485155
                        continue;
385 89635
386 89635
                if (*p == '#') {
387 89635
                        for (; *p != '\0' && *p != '\n'; p++)
388 89635
                                ;
389 89635
                        if (*p == '\0')
390 395520
                                break;
391 395520
                        continue;
392 395520
                }
393
394 0
                q = strchr(p, '\n');
395
                if (q == NULL)
396 485155
                        q = strchr(p, '\0');
397 487715
                if (q - p > 60)
398
                        vtc_log(vl, 2, "=== %.60s...", p);
399 487715
                else
400
                        vtc_log(vl, 2, "=== %.*s", (int)(q - p), p);
401 487715
402 0
                /* First content on line, collect tokens */
403 0
                memset(token_s, 0, sizeof token_s);
404
                memset(token_e, 0, sizeof token_e);
405 487715
                tn = 0;
406 2560
                f = p;
407 0
                while (p < e) {
408 0
                        assert(tn < MAX_TOKENS);
409 2560
                        assert(p < e);
410 2560
                        if (*p == '\n') { /* End on NL */
411
                                break;
412
                        }
413 485155
                        if (isspace(*p)) { /* Inter-token whitespace */
414 485155
                                p++;
415 487715
                                continue;
416
                        }
417
                        if (*p == '\\' && p[1] == '\n') { /* line-cont */
418 57920
                                p += 2;
419
                                continue;
420
                        }
421
                        if (*p == '"') { /* quotes */
422
                                token_s[tn] = ++p;
423 57920
                                q = p;
424 57920
                                for (; *p != '\0'; p++) {
425 57920
                                        assert(p < e);
426 57920
                                        if (*p == '"')
427 57920
                                                break;
428 57920
                                        if (*p == '\\') {
429 57920
                                                p += VAV_BackSlash(p, q) - 1;
430 57920
                                                q++;
431 57920
                                        } else {
432
                                                if (*p == '\n')
433
                                                        vtc_fatal(vl,
434
                                "Unterminated quoted string in line: %*.*s",
435 216000
                                (int)(p - f), (int)(p - f), f);
436
                                                assert(*p != '\n');
437
                                                *q++ = *p;
438
                                        }
439
                                }
440 216000
                                token_e[tn++] = q;
441 216000
                                p++;
442 445038
                        } else if (*p == '{') { /* Braces */
443 367158
                                nest_brace = 0;
444 367158
                                token_s[tn] = p + 1;
445 138120
                                for (; p < e; p++) {
446 138120
                                        if (*p == '{')
447
                                                nest_brace++;
448 229038
                                        else if (*p == '}') {
449 229038
                                                if (--nest_brace == 0)
450 229038
                                                        break;
451 0
                                        }
452 0
                                }
453
                                assert(*p == '}');
454 229038
                                token_e[tn++] = p++;
455 229038
                        } else { /* other tokens */
456 229038
                                token_s[tn] = p;
457 229038
                                for (; p < e && !isspace(*p); p++)
458 229038
                                        continue;
459 229038
                                token_e[tn++] = p;
460
                        }
461 216000
                }
462 216000
463
                assert(p <= e);
464
                assert(tn < MAX_TOKENS);
465
                token_s[tn] = NULL;
466
                for (tn = 0; token_s[tn] != NULL; tn++) {
467
                        AN(token_e[tn]);        /*lint !e771 */
468
                        *token_e[tn] = '\0';    /*lint !e771 */
469
                        if (NULL != strstr(token_s[tn], "${")) {
470
                                token_exp = macro_expand(vl, token_s[tn]);
471
                                if (vtc_error)
472
                                        return;
473
                                token_s[tn] = VSB_data(token_exp);
474
                                token_e[tn] = strchr(token_s[tn], '\0');
475
                        }
476 323209
                }
477
478
479
/* SECTION: loop loop
480
 *
481
 * loop NUMBER STRING
482
 *         Process STRING as a specification, NUMBER times.
483
 *
484
 * This works inside all specification strings
485
 */
486 323209
487 323209
                if (!strcmp(token_s[0], "loop")) {
488 323209
                        n = strtoul(token_s[1], NULL, 0);
489 323209
                        for (m = 0; m < n && !vtc_error && !vtc_stop; m++) {
490 323209
                                vtc_log(vl, 4, "Loop #%u", m);
491 4220579
                                parse_string(vl, priv, token_s[2]);
492 3898611
                        }
493 2458
                        continue;
494 1229
                }
495 1229
496
                AN(vl->cmds);
497
                for (cp = vl->cmds; cp->name != NULL; cp++)
498 3897382
                        if (!strcmp(token_s[0], cp->name))
499 2280200
                                break;
500 1617182
501 0
                if (cp->name == NULL) {
502
                        for (cp = global_cmds; cp->name != NULL; cp++)
503 1617182
                                if (!strcmp(token_s[0], cp->name))
504 3709692
                                        break;
505
                }
506 90040
507 0
                if (cp->name == NULL)
508 90040
                        vtc_fatal(vl, "Unknown command: \"%s\"", token_s[0]);
509
510
                assert(cp->cmd != NULL);
511 1527132
                cp->cmd(token_s, priv, vl);
512 1527132
        }
513 15798
}
514 1527132
515 116064
/**********************************************************************
516
 * Reset commands (between tests)
517 1411068
 */
518
519
static void
520 1527132
reset_cmds(const struct cmds *cmd)
521 1527132
{
522 1527132
523 1527132
        for (; cmd->name != NULL; cmd++)
524 10248452
                cmd->cmd(NULL, NULL, NULL);
525 10232961
}
526 10232961
527 10232961
/**********************************************************************
528 1511641
 * Execute a file
529
 */
530 8721320
531 3698727
int
532 3698727
fail_out(void)
533
{
534 5022593
        unsigned old_err;
535 39880
        static int once = 0;
536 39880
537
        if (once++) {
538 4982713
                vtc_log(vltop, 1, "failure during reset");
539 478121
                return (vtc_error);
540 478121
        }
541 11525953
        old_err = vtc_error;
542 11525633
        if (!vtc_stop)
543 11525633
                vtc_stop = 1;
544 477801
        vtc_log(vltop, 1, "RESETTING after %s", tfn);
545 11047832
        reset_cmds(global_cmds);
546 111232
        reset_cmds(top_cmds);
547 111232
        vtc_error |= old_err;
548 111232
549 10936600
        if (vtc_error)
550 0
                vtc_log(vltop, 1, "TEST %s FAILED", tfn);
551
        else
552 0
                vtc_log(vltop, 1, "TEST %s completed", tfn);
553 10936600
554 10936600
        if (vtc_stop > 1)
555
                return (1);
556 11047832
        return (vtc_error);
557 478121
}
558 478121
559 4982713
int
560 312923
exec_file(const char *fn, const char *script, const char *tmpdir,
561 312923
    char *logbuf, unsigned loglen)
562 50793290
{
563 50793290
        FILE *f;
564 577562
        struct vsb *vsb;
565 50215728
        const char *p;
566 577563
567 312923
        AN(tmpdir);
568 264640
569 50480367
        (void)signal(SIGPIPE, SIG_IGN);
570 312923
571 312923
        PTOK(pthread_mutex_init(&vtc_vrnd_mtx, NULL));
572 312923
        VRND_Lock = vtc_vrnd_lock;
573 4191669
        VRND_Unlock = vtc_vrnd_unlock;
574 191259134
        VRND_SeedAll();
575 187067465
576 4191669
        tfn = fn;
577
        vtc_loginit(logbuf, loglen);
578
        vltop = vtc_logopen("top");
579
        AN(vltop);
580 1527132
        vtc_log_set_cmd(vltop, top_cmds);
581 1527132
582 1527132
        vtc_log(vltop, 1, "TEST %s starting", fn);
583 6510035
584 4982903
        init_macro();
585 4982903
        init_server();
586 4982903
        init_syslog();
587 42440
        init_tunnel();
588 42440
589 0
        vsb = VSB_new_auto();
590 42440
        AN(vsb);
591 42440
        if (*fn != '/')
592 42440
                macro_cat(vltop, vsb, "pwd", NULL);
593 4982903
        p = strrchr(fn, '/');
594
        if (p != NULL) {
595
                VSB_putc(vsb, '/');
596
                VSB_bcat(vsb, fn, p - fn);
597
        }
598
        if (VSB_len(vsb) == 0)
599
                VSB_putc(vsb, '/');
600
        AZ(VSB_finish(vsb));
601
        macro_def(vltop, NULL, "testdir", "%s", VSB_data(vsb));
602
        VSB_destroy(&vsb);
603
604 1527132
        /* Move into our tmpdir */
605 1774
        AZ(chdir(tmpdir));
606 72386
        macro_def(vltop, NULL, "tmpdir", "%s", tmpdir);
607 70612
        p = strrchr(tmpdir, '/');
608 70612
        AN(p);
609 70612
        p++;
610 1774
        AN(*p);
611
        macro_def(vltop, NULL, "vtcid", "%s", p);
612
613 1525358
        /* Drop file to tell what was going on here */
614 1525358
        f = fopen("INFO", "w");
615 23518901
        AN(f);
616 23484965
        fprintf(f, "Test case: %s\n", fn);
617 23484965
        AZ(fclose(f));
618 1071175
619 22413790
        vtc_stop = 0;
620 1105111
621
        vtc_thread = pthread_self();
622 1525358
        parse_string(vltop, NULL, script);
623 454185
        return (fail_out());
624 454185
}