varnish-cache/bin/varnishtest/vtc.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
31
#include <sys/wait.h>
32
33
#include <ctype.h>
34
#include <errno.h>
35
#include <grp.h>
36
#include <math.h>
37
#include <pwd.h>
38
#include <stdarg.h>
39
#include <stdio.h>
40
#include <stdlib.h>
41
#include <string.h>
42
#include <unistd.h>
43
44
#include "vtc.h"
45
46
#include "vav.h"
47
#include "vnum.h"
48
#include "vre.h"
49
#include "vtim.h"
50
51
#ifdef HAVE_SYS_PERSONALITY_H
52
#  include <sys/personality.h>
53
#endif
54
55
#define         MAX_TOKENS              200
56
57
volatile sig_atomic_t   vtc_error;      /* Error encountered */
58
int                     vtc_stop;       /* Stops current test without error */
59
pthread_t               vtc_thread;
60
static struct vtclog    *vltop;
61
static int              ign_unknown_macro = 0;
62
63
/**********************************************************************
64
 * Macro facility
65
 */
66
67
struct macro {
68
        unsigned                magic;
69
#define MACRO_MAGIC             0x803423e3
70
        VTAILQ_ENTRY(macro)     list;
71
        char                    *name;
72
        char                    *val;
73
};
74
75
static VTAILQ_HEAD(,macro) macro_list = VTAILQ_HEAD_INITIALIZER(macro_list);
76
77
/**********************************************************************/
78
79
static struct macro *
80 9326
macro_def_int(const char *name, const char *fmt, va_list ap)
81
{
82
        struct macro *m;
83
        char buf[256];
84
85 71628
        VTAILQ_FOREACH(m, &macro_list, list)
86 62527
                if (!strcmp(name, m->name))
87 225
                        break;
88 9326
        if (m == NULL) {
89 9101
                ALLOC_OBJ(m, MACRO_MAGIC);
90 9101
                AN(m);
91 9101
                REPLACE(m->name, name);
92 9101
                AN(m->name);
93 9101
                VTAILQ_INSERT_TAIL(&macro_list, m, list);
94
        }
95 9326
        AN(m);
96 9326
        vbprintf(buf, fmt, ap);
97 9326
        REPLACE(m->val, buf);
98 9326
        AN(m->val);
99 9326
        return (m);
100
}
101
102
103
/**********************************************************************
104
 * This is for defining macros before we fork the child process which
105
 * runs the test-case.
106
 */
107
108
void
109 3289
extmacro_def(const char *name, const char *fmt, ...)
110
{
111
        va_list ap;
112
113 3289
        va_start(ap, fmt);
114 3289
        (void)macro_def_int(name, fmt, ap);
115 3289
        va_end(ap);
116 3289
}
117
118
/**********************************************************************
119
 * Below this point is run inside the testing child-process.
120
 */
121
122
static pthread_mutex_t          macro_mtx;
123
124
static void
125 678
init_macro(void)
126
{
127
        struct macro *m;
128
129
        /* Dump the extmacros for completeness */
130 4063
        VTAILQ_FOREACH(m, &macro_list, list)
131 3385
                vtc_log(vltop, 4, "extmacro def %s=%s", m->name, m->val);
132
133 678
        AZ(pthread_mutex_init(&macro_mtx, NULL));
134 678
}
135
136
void
137 6037
macro_def(struct vtclog *vl, const char *instance, const char *name,
138
    const char *fmt, ...)
139
{
140
        char buf1[256];
141
        struct macro *m;
142
        va_list ap;
143
144 6037
        AN(fmt);
145
146 6037
        if (instance != NULL) {
147 5359
                bprintf(buf1, "%s_%s", instance, name);
148 5359
                name = buf1;
149
        }
150
151 6037
        AZ(pthread_mutex_lock(&macro_mtx));
152 6037
        va_start(ap, fmt);
153 6037
        m = macro_def_int(name, fmt, ap);
154 6037
        va_end(ap);
155 6037
        vtc_log(vl, 4, "macro def %s=%s", name, m->val);
156 6037
        AZ(pthread_mutex_unlock(&macro_mtx));
157 6037
}
158
159
void
160 2146
macro_undef(struct vtclog *vl, const char *instance, const char *name)
161
{
162
        char buf1[256];
163
        struct macro *m;
164
165 2146
        if (instance != NULL) {
166 2146
                bprintf(buf1, "%s_%s", instance, name);
167 2146
                name = buf1;
168
        }
169
170 2146
        AZ(pthread_mutex_lock(&macro_mtx));
171 15501
        VTAILQ_FOREACH(m, &macro_list, list)
172 15483
                if (!strcmp(name, m->name))
173 2128
                        break;
174 2146
        if (m != NULL) {
175 2128
                vtc_log(vl, 4, "macro undef %s", name);
176 2128
                VTAILQ_REMOVE(&macro_list, m, list);
177 2128
                free(m->name);
178 2128
                free(m->val);
179 2128
                free(m);
180
        }
181 2146
        AZ(pthread_mutex_unlock(&macro_mtx));
182 2146
}
183
184
static char *
185 2921
macro_get(const char *b, const char *e)
186
{
187
        struct macro *m;
188
        int l;
189 2921
        char *retval = NULL;
190
191 2921
        l = e - b;
192
193 2921
        if (l == 4 && !memcmp(b, "date", l)) {
194 3
                double t = VTIM_real();
195 3
                retval = malloc(64);
196 3
                AN(retval);
197 3
                VTIM_format(t, retval);
198 3
                return (retval);
199
        }
200
201 2918
        AZ(pthread_mutex_lock(&macro_mtx));
202 23557
        VTAILQ_FOREACH(m, &macro_list, list) {
203 23545
                CHECK_OBJ_NOTNULL(m, MACRO_MAGIC);
204 23545
                if (!strncmp(b, m->name, l) && m->name[l] == '\0')
205 2906
                        break;
206
        }
207 2918
        if (m != NULL)
208 2906
                retval = strdup(m->val);
209 2918
        AZ(pthread_mutex_unlock(&macro_mtx));
210 2918
        return (retval);
211
}
212
213
struct vsb *
214 2857
macro_expand(struct vtclog *vl, const char *text)
215
{
216
        struct vsb *vsb;
217
        const char *p, *q;
218
        char *m;
219
220 2857
        vsb = VSB_new_auto();
221 2857
        AN(vsb);
222 8635
        while (*text != '\0') {
223 4673
                p = strstr(text, "${");
224 4673
                if (p == NULL) {
225 1752
                        VSB_cat(vsb, text);
226 1752
                        break;
227
                }
228 2921
                VSB_bcat(vsb, text, p - text);
229 2921
                q = strchr(p, '}');
230 2921
                if (q == NULL) {
231 0
                        VSB_cat(vsb, text);
232 0
                        break;
233
                }
234 2921
                assert(p[0] == '$');
235 2921
                assert(p[1] == '{');
236 2921
                assert(q[0] == '}');
237 2921
                p += 2;
238 2921
                m = macro_get(p, q);
239 2921
                if (m == NULL) {
240 12
                        if (!ign_unknown_macro) {
241 0
                                VSB_destroy(&vsb);
242 0
                                vtc_fatal(vl, "Macro ${%.*s} not found",
243 0
                                          (int)(q - p), p);
244
                                NEEDLESS(return (NULL));
245
                        }
246 12
                        VSB_printf(vsb, "${%.*s}", (int)(q - p), p);
247
                }
248
                else {
249 2909
                        VSB_printf(vsb, "%s", m);
250 2909
                        free(m);
251
                }
252 2921
                text = q + 1;
253
        }
254 2857
        AZ(VSB_finish(vsb));
255 2857
        return (vsb);
256
}
257
258
/**********************************************************************
259
 * Parse a string
260
 *
261
 * We make a copy of the string and deliberately leak it, so that all
262
 * the cmd functions we call don't have to strdup(3) all over the place.
263
 *
264
 * Static checkers like Coverity may bitch about this, but we don't care.
265
 */
266
267
void
268 3630
parse_string(const char *spec, const struct cmds *cmd, void *priv,
269
    struct vtclog *vl)
270
{
271
        char *token_s[MAX_TOKENS], *token_e[MAX_TOKENS];
272
        struct vsb *token_exp[MAX_TOKENS];
273
        char *e, *p, *q, *f, *buf;
274
        int nest_brace;
275
        int tn;
276
        const struct cmds *cp;
277
278 3630
        AN(spec);
279 3630
        buf = strdup(spec);
280 3630
        AN(buf);
281 3630
        e = strchr(buf, '\0');
282 3630
        AN(e);
283 48784
        for (p = buf; p < e; p++) {
284 45187
                if (vtc_error || vtc_stop)
285
                        break;
286
                /* Start of line */
287 45178
                if (isspace(*p))
288 24238
                        continue;
289 20938
                if (*p == '\n')
290 0
                        continue;
291
292 20938
                if (*p == '#') {
293 884
                        for (; *p != '\0' && *p != '\n'; p++)
294
                                ;
295 884
                        if (*p == '\0')
296 0
                                break;
297 884
                        continue;
298
                }
299
300 20054
                q = strchr(p, '\n');
301 20054
                if (q == NULL)
302 199
                        q = strchr(p, '\0');
303 20054
                if (q - p > 60)
304 961
                        vtc_log(vl, 2, "=== %.60s...", p);
305
                else
306 19093
                        vtc_log(vl, 2, "=== %.*s", (int)(q - p), p);
307
308
                /* First content on line, collect tokens */
309 20050
                tn = 0;
310 20050
                f = p;
311 153285
                while (p < e) {
312 133039
                        assert(tn < MAX_TOKENS);
313 133040
                        assert(p < e);
314 133040
                        if (*p == '\n') { /* End on NL */
315 19855
                                break;
316
                        }
317 113185
                        if (isspace(*p)) { /* Inter-token whitespace */
318 47808
                                p++;
319 47808
                                continue;
320
                        }
321 65381
                        if (*p == '\\' && p[1] == '\n') { /* line-cont */
322 670
                                p += 2;
323 670
                                continue;
324
                        }
325 64711
                        if (*p == '"') { /* quotes */
326 6516
                                token_s[tn] = ++p;
327 6516
                                q = p;
328 161312
                                for (; *p != '\0'; p++) {
329 161312
                                        assert(p < e);
330 161309
                                        if (*p == '"')
331 6514
                                                break;
332 154795
                                        if (*p == '\\') {
333 872
                                                p += VAV_BackSlash(p, q) - 1;
334 873
                                                q++;
335
                                        } else {
336 153923
                                                if (*p == '\n')
337 0
                                                        vtc_fatal(vl,
338
                                "Unterminated quoted string in line: %*.*s",
339 0
                                (int)(p - f), (int)(p - f), f);
340 153923
                                                assert(*p != '\n');
341 153923
                                                *q++ = *p;
342
                                        }
343
                                }
344 6514
                                token_e[tn++] = q;
345 6514
                                p++;
346 58195
                        } else if (*p == '{') { /* Braces */
347 4497
                                nest_brace = 0;
348 4497
                                token_s[tn] = p + 1;
349 697655
                                for (; p < e; p++) {
350 697655
                                        if (*p == '{')
351 7739
                                                nest_brace++;
352 689916
                                        else if (*p == '}') {
353 7739
                                                if (--nest_brace == 0)
354 4497
                                                        break;
355
                                        }
356
                                }
357 4497
                                assert(*p == '}');
358 4497
                                token_e[tn++] = p++;
359
                        } else { /* other tokens */
360 53698
                                token_s[tn] = p;
361 352544
                                for (; p < e && !isspace(*p); p++)
362 298846
                                        continue;
363 53696
                                token_e[tn++] = p;
364
                        }
365
                }
366
367 20051
                assert(p <= e);
368 20051
                assert(tn < MAX_TOKENS);
369 20051
                token_s[tn] = NULL;
370 84758
                for (tn = 0; token_s[tn] != NULL; tn++) {
371 64704
                        token_exp[tn] = NULL;
372 64704
                        AN(token_e[tn]);        /*lint !e771 */
373 64707
                        *token_e[tn] = '\0';    /*lint !e771 */
374 64707
                        if (NULL != strstr(token_s[tn], "${")) {
375 407
                                token_exp[tn] = macro_expand(vl, token_s[tn]);
376 407
                                if (vtc_error)
377 3606
                                        return;
378 407
                                token_s[tn] = VSB_data(token_exp[tn]);
379 407
                                token_e[tn] = strchr(token_s[tn], '\0');
380
                        }
381
                }
382
383 332325
                for (cp = cmd; cp->name != NULL; cp++)
384 332333
                        if (!strcmp(token_s[0], cp->name))
385 20062
                                break;
386
387 20054
                if (cp->name == NULL)
388 0
                        vtc_fatal(vl, "Unknown command: \"%s\"", token_s[0]);
389
390 20054
                assert(cp->cmd != NULL);
391 20054
                cp->cmd(token_s, priv, cmd, vl);
392
        }
393
}
394
395
/**********************************************************************
396
 * Reset commands (between tests)
397
 */
398
399
static void
400 678
reset_cmds(const struct cmds *cmd)
401
{
402
403 8814
        for (; cmd->name != NULL; cmd++)
404 8136
                cmd->cmd(NULL, NULL, NULL, NULL);
405 678
}
406
407
/* SECTION: varnishtest varnishtest
408
 *
409
 * This should be the first command in your vtc as it will identify the test
410
 * case with a short yet descriptive sentence. It takes exactly one argument, a
411
 * string, eg::
412
 *
413
 *         varnishtest "Check that varnishtest is actually a valid command"
414
 *
415
 * It will also print that string in the log.
416
 */
417
418
static void
419 1356
cmd_varnishtest(CMD_ARGS)
420
{
421
422
        (void)priv;
423
        (void)cmd;
424
        (void)vl;
425
426 1356
        if (av == NULL)
427 2034
                return;
428 678
        AZ(strcmp(av[0], "varnishtest"));
429
430 678
        vtc_log(vl, 1, "TEST %s", av[1]);
431 678
        AZ(av[2]);
432
}
433
434
/* SECTION: shell shell
435
 *
436
 * Pass the string given as argument to a shell. If you have multiple
437
 * commands to run, you can use curly barces to describe a multi-lines
438
 * script, eg::
439
 *
440
 *         shell {
441
 *                 echo begin
442
 *                 cat /etc/fstab
443
 *                 echo end
444
 *         }
445
 *
446
 * By default a zero exit code is expected, otherwise the vtc will fail.
447
 *
448
 * Notice that the commandstring is prefixed with "exec 2>&1;" to join
449
 * stderr and stdout back to the varnishtest process.
450
 *
451
 * Optional arguments:
452
 *
453
 * \-err
454
 *      Expect non-zero exit code.
455
 *
456
 * \-exit N
457
 *      Expect exit code N instead of zero.
458
 *
459
 * \-expect STRING
460
 *      Expect string to be found in stdout+err.
461
 *
462
 * \-match REGEXP
463
 *      Expect regexp to match the stdout+err output.
464
 */
465
/* SECTION: client-server.spec.shell shell
466
 *
467
 * Same as for the top-level shell.
468
 */
469
470
static void
471 269
cmd_shell_engine(struct vtclog *vl, int ok, const char *cmd,
472
    const char *expect, const char *re)
473
{
474
        struct vsb *vsb;
475
        FILE *fp;
476 269
        vre_t *vre = NULL;
477
        const char *errptr;
478
        int r, c;
479
        int err;
480
481 269
        AN(vl);
482 269
        AN(cmd);
483 269
        vsb = VSB_new_auto();
484 269
        AN(vsb);
485 269
        if (re != NULL) {
486 29
                vre = VRE_compile(re, 0, &errptr, &err);
487 29
                if (vre == NULL)
488 0
                        vtc_fatal(vl, "shell_match invalid regexp (\"%s\")",
489
                            re);
490
        }
491 269
        VSB_printf(vsb, "exec 2>&1 ; %s", cmd);
492 269
        AZ(VSB_finish(vsb));
493 269
        vtc_dump(vl, 4, "shell_cmd", VSB_data(vsb), -1);
494 269
        fp = popen(VSB_data(vsb), "r");
495 269
        if (fp == NULL)
496 0
                vtc_fatal(vl, "popen fails: %s", strerror(errno));
497 269
        VSB_clear(vsb);
498
        do {
499 181287
                c = getc(fp);
500 181287
                if (c != EOF)
501 181018
                        VSB_putc(vsb, c);
502 181287
        } while (c != EOF);
503 269
        r = pclose(fp);
504 269
        AZ(VSB_finish(vsb));
505 269
        vtc_dump(vl, 4, "shell_out", VSB_data(vsb), VSB_len(vsb));
506 269
        vtc_log(vl, 4, "shell_status = 0x%04x", WEXITSTATUS(r));
507 269
        if (WIFSIGNALED(r))
508 0
                vtc_log(vl, 4, "shell_signal = %d", WTERMSIG(r));
509
510 269
        if (ok < 0 && !WEXITSTATUS(r) && !WIFSIGNALED(r))
511 0
                vtc_fatal(vl, "shell did not fail as expected");
512 269
        else if (ok >= 0 && WEXITSTATUS(r) != ok)
513 2
                vtc_fatal(vl, "shell_exit not as expected: "
514
                    "got 0x%04x wanted 0x%04x", WEXITSTATUS(r), ok);
515
516 267
        if (expect != NULL) {
517 151
                if (strstr(VSB_data(vsb), expect) == NULL)
518 0
                        vtc_fatal(vl,
519
                            "shell_expect not found: (\"%s\")", expect);
520
                else
521 151
                        vtc_log(vl, 4, "shell_expect found");
522 116
        } else if (vre != NULL) {
523 29
                if (VRE_exec(vre, VSB_data(vsb), VSB_len(vsb), 0, 0,
524
                    NULL, 0, NULL) < 1)
525 0
                        vtc_fatal(vl,
526
                            "shell_match failed: (\"%s\")", re);
527
                else
528 29
                        vtc_log(vl, 4, "shell_match succeeded");
529 29
                VRE_free(&vre);
530
        }
531 267
        VSB_destroy(&vsb);
532 267
}
533
534
535
void
536 947
cmd_shell(CMD_ARGS)
537
{
538 947
        const char *expect = NULL;
539 947
        const char *re = NULL;
540
        int n;
541 947
        int ok = 0;
542
543
        (void)priv;
544
        (void)cmd;
545
546 947
        if (av == NULL)
547 1623
                return;
548 593
        for (n = 1; av[n] != NULL; n++) {
549 593
                if (!strcmp(av[n], "-err")) {
550 129
                        ok = -1;
551 464
                } else if (!strcmp(av[n], "-exit")) {
552 15
                        n += 1;
553 15
                        ok = atoi(av[n]);
554 449
                } else if (!strcmp(av[n], "-expect")) {
555 151
                        if (re != NULL)
556 0
                                vtc_fatal(vl,
557
                                    "Cannot use -expect with -match");
558 151
                        n += 1;
559 151
                        expect = av[n];
560 298
                } else if (!strcmp(av[n], "-match")) {
561 29
                        if (expect != NULL)
562 0
                                vtc_fatal(vl,
563
                                    "Cannot use -match with -expect");
564 29
                        n += 1;
565 29
                        re = av[n];
566
                } else {
567 269
                        break;
568
                }
569
        }
570 269
        AN(av[n]);
571 269
        cmd_shell_engine(vl, ok, av[n], expect, re);
572
}
573
574
/* SECTION: err_shell err_shell
575
 *
576
 * This is very similar to the the ``shell`` command, except it takes a first
577
 * string as argument before the command::
578
 *
579
 *         err_shell "foo" "echo foo"
580
 *
581
 * err_shell expect the shell command to fail AND stdout to match the string,
582
 * failing the test case otherwise.
583
 */
584
585
static void
586 678
cmd_err_shell(CMD_ARGS)
587
{
588
        (void)priv;
589
        (void)cmd;
590
591 678
        if (av == NULL)
592 1356
                return;
593 0
        AN(av[1]);
594 0
        AN(av[2]);
595 0
        AZ(av[3]);
596 0
        vtc_log(vl, 1,
597
            "NOTICE: err_shell is deprecated, use 'shell -err -expect'");
598 0
        cmd_shell_engine(vl, -1, av[2], av[1], NULL);
599
}
600
601
/* SECTION: setenv setenv
602
 *
603
 * Set or change an environment variable::
604
 *
605
 *         setenv FOO "bar baz"
606
 *
607
 * The above will set the environment variable $FOO to the value
608
 * provided. There is also an ``-ifunset`` argument which will only
609
 * set the value if the the environment variable does not already
610
 * exist::
611
 *
612
 *        setenv -ifunset FOO quux
613
 */
614
static void
615 681
cmd_setenv(CMD_ARGS)
616
{
617
        int r;
618
        int force;
619
620
        (void)priv;
621
        (void)cmd;
622
623 681
        if (av == NULL)
624 1359
                return;
625 3
        AN(av[1]);
626 3
        AN(av[2]);
627
628 3
        force = 1;
629 3
        if (strcmp("-ifunset", av[1]) == 0) {
630 1
                force = 0;
631 1
                av++;
632 1
                AN(av[2]);
633
        }
634 3
        if (av[3] != NULL)
635 0
                vtc_fatal(vl, "CMD setenv: Unexpected argument '%s'", av[3]);
636 3
        r = setenv(av[1], av[2], force);
637 3
        if (r != 0)
638 0
                vtc_log(vl, 0, "CMD setenv %s=\"%s\" failed: %s",
639 0
                    av[1], av[2], strerror(errno));
640
}
641
642
/* SECTION: delay delay
643
 *
644
 * Sleep for the number of seconds specified in the argument. The number
645
 * can include a fractional part, e.g. 1.5.
646
 */
647
/* SECTION: stream.spec.delay delay
648
 *
649
 * Same as for the top-level delay.
650
 */
651
void
652 1055
cmd_delay(CMD_ARGS)
653
{
654
        double f;
655
656
        (void)priv;
657
        (void)cmd;
658 1055
        if (av == NULL)
659 1731
                return;
660 377
        AN(av[1]);
661 377
        AZ(av[2]);
662 377
        f = VNUM(av[1]);
663 377
        if (isnan(f))
664 0
                vtc_fatal(vl, "Syntax error in number (%s)", av[1]);
665 377
        vtc_log(vl, 3, "delaying %g second(s)", f);
666 377
        VTIM_sleep(f);
667
}
668
669
/* SECTION: feature feature
670
 *
671
 * Test that the required feature(s) for a test are available, and skip
672
 * the test otherwise; or change the interpretation of the test, as
673
 * documented below. feature takes any number of arguments from this list:
674
 *
675
 * SO_RCVTIMEO_WORKS
676
 *        The SO_RCVTIMEO socket option is working
677
 * 64bit
678
 *        The environment is 64 bits
679
 * !OSX
680
 *        The environment is not OSX
681
 * dns
682
 *        DNS lookups are working
683
 * topbuild
684
 *        varnishtest has been started with '-i'
685
 * root
686
 *        varnishtest has been invoked by the root user
687
 * user_varnish
688
 *        The varnish user is present
689
 * user_vcache
690
 *        The vcache user is present
691
 * group_varnish
692
 *        The varnish group is present
693
 * cmd <command-line>
694
 *        A command line that should execute with a zero exit status
695
 * ignore_unknown_macro
696
 *        Do not fail the test if a string of the form ${...} is not
697
 *        recognized as a macro.
698
 *
699
 * Be careful with the last feature, because it may cause a test with a
700
 * misspelled macro to fail silently. You should only need it if you must
701
 * run a test with strings of the form "${...}".
702
 */
703
704
static void
705 714
cmd_feature(CMD_ARGS)
706
{
707
        int r;
708
        int good;
709
710
        (void)priv;
711
        (void)cmd;
712
713 714
        if (av == NULL)
714 678
                return;
715
716
#define FEATURE(nm, tst)                                \
717
        do {                                            \
718
                if (!strcmp(*av, nm)) {                 \
719
                        if (tst) {                      \
720
                                good = 1;               \
721
                        } else {                        \
722
                                vtc_stop = 2;           \
723
                        }                               \
724
                }                                       \
725
        } while (0)
726
727 128
        for (av++; *av != NULL; av++) {
728 36
                good = 0;
729 36
                if (!strcmp(*av, "SO_RCVTIMEO_WORKS")) {
730
#ifdef SO_RCVTIMEO_WORKS
731 5
                        good = 1;
732
#else
733
                        vtc_stop = 2;
734
#endif
735
                }
736
737 36
                if (!strcmp(*av, "!OSX")) {
738
#if !defined(__APPLE__) || !defined(__MACH__)
739 1
                        good = 1;
740
#else
741
                        vtc_stop = 2;
742
#endif
743
                }
744 36
                FEATURE("pcre_jit", VRE_has_jit);
745 36
                FEATURE("64bit", sizeof(void*) == 8);
746 36
                FEATURE("dns", feature_dns);
747 36
                FEATURE("topbuild", iflg);
748 36
                FEATURE("root", !geteuid());
749 36
                FEATURE("user_varnish", getpwnam("varnish") != NULL);
750 36
                FEATURE("user_vcache", getpwnam("vcache") != NULL);
751 36
                FEATURE("group_varnish", getgrnam("varnish") != NULL);
752
753 36
                if (!strcmp(*av, "disable_aslr")) {
754 1
                        good = 1;
755
#ifdef HAVE_SYS_PERSONALITY_H
756
                        r = personality(0xffffffff);
757
                        r = personality(r | ADDR_NO_RANDOMIZE);
758
                        if (r < 0) {
759
                                good = 0;
760
                                vtc_stop = 2;
761
                        }
762
#endif
763 35
                } else if (!strcmp(*av, "cmd")) {
764 7
                        av++;
765 7
                        if (*av == NULL)
766 0
                                vtc_fatal(vl, "Missing the command-line");
767 7
                        r = system(*av);
768 7
                        if (WEXITSTATUS(r) == 0)
769 2
                                good = 1;
770
                        else
771 5
                                vtc_stop = 2;
772 28
                } else if (!strcmp(*av, "ignore_unknown_macro")) {
773 1
                        ign_unknown_macro = 1;
774 1
                        good = 1;
775
                }
776 36
                if (good)
777 28
                        continue;
778
779 8
                if (!vtc_stop)
780 0
                        vtc_fatal(vl, "FAIL test, unknown feature: %s", *av);
781
                else
782 8
                        vtc_log(vl, 1,
783
                            "SKIPPING test, lacking feature: %s", *av);
784 8
                return;
785
        }
786
}
787
788
/**********************************************************************
789
 * Execute a file
790
 */
791
792
static const struct cmds cmds[] = {
793
#define CMD(n) { #n, cmd_##n },
794
        CMD(server)
795
        CMD(client)
796
        CMD(varnish)
797
        CMD(delay)
798
        CMD(varnishtest)
799
        CMD(shell)
800
        CMD(err_shell)
801
        CMD(barrier)
802
        CMD(feature)
803
        CMD(logexpect)
804
        CMD(process)
805
        CMD(setenv)
806
#undef CMD
807
        { NULL, NULL }
808
};
809
810
static const char *tfn;
811
812
int
813 678
fail_out(void)
814
{
815
        unsigned old_err;
816
        static int once = 0;
817
818 678
        if (once++) {
819 0
                vtc_log(vltop, 1, "failure during reset");
820 0
                return(vtc_error);
821
        }
822 678
        old_err = vtc_error;
823 678
        if (!vtc_stop)
824 670
                vtc_stop = 1;
825 678
        vtc_log(vltop, 1, "RESETTING after %s", tfn);
826 678
        reset_cmds(cmds);
827 678
        vtc_error |= old_err;
828
829 678
        if (vtc_error)
830 2
                vtc_log(vltop, 1, "TEST %s FAILED", tfn);
831
        else
832 676
                vtc_log(vltop, 1, "TEST %s completed", tfn);
833
834 678
        if (vtc_stop > 1)
835 8
                return (1);
836 670
        return (vtc_error);
837
}
838
839
int
840 678
exec_file(const char *fn, const char *script, const char *tmpdir,
841
    char *logbuf, unsigned loglen)
842
{
843
        FILE *f;
844
845 678
        (void)signal(SIGPIPE, SIG_IGN);
846
847 678
        tfn = fn;
848 678
        vtc_loginit(logbuf, loglen);
849 678
        vltop = vtc_logopen("top");
850 678
        AN(vltop);
851
852 678
        init_macro();
853 678
        init_server();
854
855
        /* Move into our tmpdir */
856 678
        AZ(chdir(tmpdir));
857 678
        macro_def(vltop, NULL, "tmpdir", "%s", tmpdir);
858
859
        /* Drop file to tell what was going on here */
860 678
        f = fopen("INFO", "w");
861 678
        AN(f);
862 678
        fprintf(f, "Test case: %s\n", fn);
863 678
        AZ(fclose(f));
864
865 678
        vtc_stop = 0;
866 678
        vtc_log(vltop, 1, "TEST %s starting", fn);
867
868 678
        vtc_thread = pthread_self();
869 678
        parse_string(script, cmds, NULL, vltop);
870 676
        return(fail_out());
871
}