vinyl-cache/bin/vinyltest/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 <dlfcn.h>
36
#include <fcntl.h>
37
#include <stdarg.h>
38
#include <stdio.h>
39
#include <stdlib.h>
40
#include <string.h>
41
#include <unistd.h>
42
43
#include "vtc.h"
44
#include "vtc_log.h"
45
46
#include "vav.h"
47
#include "vsub.h"
48
#include "vrnd.h"
49
50
#define         MAX_TOKENS              200
51
52
volatile sig_atomic_t   vtc_error;      /* Error encountered */
53
int                     vtc_stop;       /* Stops current test without error */
54
pthread_t               vtc_thread;
55
int                     ign_unknown_macro = 0;
56
static struct vtclog    *vltop;
57
58
static pthread_mutex_t  vtc_vrnd_mtx;
59
60
static void
61 85155
vtc_vrnd_lock(void)
62
{
63 85155
        PTOK(pthread_mutex_lock(&vtc_vrnd_mtx));
64 85155
}
65
66
static void
67 85155
vtc_vrnd_unlock(void)
68
{
69 85155
        PTOK(pthread_mutex_unlock(&vtc_vrnd_mtx));
70 85155
}
71
72
static const char *tfn;
73
74
/**********************************************************************
75
 * Commands
76
 */
77
78
struct icmds {
79
        unsigned                magic;
80
#define ICMDS_MAGIC             0xa743d463
81
        struct cmds             *cmd;
82
        VTAILQ_ENTRY(icmds)     list;
83
};
84
85
static VTAILQ_HEAD(,icmds) icmd_list = VTAILQ_HEAD_INITIALIZER(icmd_list);
86
87
void
88 98190
add_cmd(const char *name, cmd_f *cmd, unsigned flags)
89
{
90
        struct icmds *cp;
91
92 98190
        AN(name);
93 98190
        AN(cmd);
94 98190
        ALLOC_OBJ(cp, ICMDS_MAGIC);
95 98190
        AN(cp);
96 98190
        ALLOC_OBJ(cp->cmd, CMDS_MAGIC);
97 98190
        AN(cp->cmd);
98 98190
        cp->cmd->name = strdup(name);
99 98190
        AN(cp->cmd->name);
100 98190
        cp->cmd->cmd = cmd;
101 98190
        cp->cmd->flags = flags;
102 98190
        VTAILQ_INSERT_HEAD(&icmd_list, cp, list);
103 98190
}
104
105
struct cmds *
106 72418
find_cmd(const char *name)
107
{
108
        struct icmds *cp;
109
        char buf[BUFSIZ];
110
111 661864
        VTAILQ_FOREACH(cp, &icmd_list, list) {
112 661839
                CHECK_OBJ_NOTNULL(cp, ICMDS_MAGIC);
113 661839
                CHECK_OBJ_NOTNULL(cp->cmd, CMDS_MAGIC);
114 661839
                if (!strcmp(name, cp->cmd->name))
115 72393
                        return (cp->cmd);
116 589446
        }
117
118 25
        bprintf(buf, "libvtest_ext_%s.so", name);
119 25
        void *dlp = dlopen(buf, RTLD_NOW);
120 25
        if (dlp == NULL) {
121 25
                vtc_log(vltop, 4, "Autoload %s failed: %s", buf, dlerror());
122 25
                return (NULL);
123
        }
124 0
        vtc_log(vltop, 4, "Autoloaded %s", buf);
125
126 0
        VTAILQ_FOREACH(cp, &icmd_list, list) {
127 0
                CHECK_OBJ_NOTNULL(cp, ICMDS_MAGIC);
128 0
                CHECK_OBJ_NOTNULL(cp->cmd, CMDS_MAGIC);
129 0
                if (!strcmp(name, cp->cmd->name))
130 0
                        return (cp->cmd);
131 0
        }
132 0
        return (NULL);
133 72418
}
134
135
static void
136 5455
init_cmd_list(void)
137
{
138
#define CMD_GLOBAL(n) add_cmd(#n, cmd_##n, CMDS_F_GLOBAL);
139
#define CMD_TOP(n) add_cmd(#n, cmd_##n, CMDS_F_NONE);
140
#include "cmds.h"
141
}
142
143
/**********************************************************************
144
 * Extensions
145
 *
146
 * We need to open the extension while doing argument processing
147
 * in order for relative paths to work.  This complicates the
148
 * VSUB_closefrom() a little bit.
149
 */
150
151
struct extension {
152
       unsigned                 magic;
153
#define EXTENSION_MAGIC         0x69e788db
154
       VTAILQ_ENTRY(extension)  list;
155
       const char               *name;
156
};
157
158
static VTAILQ_HEAD(,extension) extension_list =
159
    VTAILQ_HEAD_INITIALIZER(extension_list);
160
161
void
162 0
add_extension(const char *name)
163
{
164
        int fd;
165
        struct extension *ep;
166
167 0
        AN(name);
168 0
        fd = open(name, O_RDONLY);
169 0
        if (fd < 0) {
170 0
                fprintf(stderr, "Cannot open extension file '%s': %s\n",
171 0
                    name, strerror(errno));
172 0
                exit(2);
173
        }
174 0
        closefd(&fd);
175
176 0
        ALLOC_OBJ(ep, EXTENSION_MAGIC);
177 0
        AN(ep);
178 0
        ep->name = strdup(name);
179 0
        AN(ep->name);
180 0
        VTAILQ_INSERT_HEAD(&extension_list, ep, list);
181 0
}
182
183
static int
184 5455
init_extensions(void)
185
{
186
        struct extension *ep;
187
188 5455
        VTAILQ_FOREACH(ep, &extension_list, list) {
189 0
                CHECK_OBJ_NOTNULL(ep, EXTENSION_MAGIC);
190 0
                void *dlp = dlopen(ep->name, RTLD_NOW);
191 0
                if (dlp == NULL) {
192 0
                        vtc_log(vltop, 1, "Cannot dlopen '%s': %s\n",
193 0
                            ep->name, dlerror());
194 0
                        return (1);
195
                }
196 0
        }
197 5455
        return (0);
198 5455
}
199
200
/**********************************************************************
201
 * Macro facility
202
 */
203
204
struct macro {
205
        unsigned                magic;
206
#define MACRO_MAGIC             0x803423e3
207
        VTAILQ_ENTRY(macro)     list;
208
        char                    *name;
209
        char                    *val;
210
        macro_f                 *func;
211
};
212
213
static VTAILQ_HEAD(,macro) macro_list = VTAILQ_HEAD_INITIALIZER(macro_list);
214
215
/**********************************************************************/
216
217
static struct macro *
218 133610
macro_def_int(const char *name, macro_f *func, const char *fmt, va_list ap)
219
{
220
        struct macro *m;
221
        char buf[2048];
222
223 1792115
        VTAILQ_FOREACH(m, &macro_list, list)
224 1661415
                if (!strcmp(name, m->name))
225 2910
                        break;
226 133610
        if (m == NULL) {
227 130700
                ALLOC_OBJ(m, MACRO_MAGIC);
228 130700
                AN(m);
229 130700
                REPLACE(m->name, name);
230 130700
                AN(m->name);
231 130700
                VTAILQ_INSERT_TAIL(&macro_list, m, list);
232 130700
        }
233 133610
        AN(m);
234 133610
        if (func != NULL) {
235 10480
                AZ(fmt);
236 10480
                m->func = func;
237 10480
        } else {
238 123130
                AN(fmt);
239 123130
                vbprintf(buf, fmt, ap);
240 123130
                REPLACE(m->val, buf);
241 123130
                AN(m->val);
242
        }
243 133610
        return (m);
244
}
245
246
247
/**********************************************************************
248
 * This is for defining macros before we fork the child process which
249
 * runs the test-case.
250
 */
251
252
void
253 57280
extmacro_def(const char *name, macro_f *func, const char *fmt, ...)
254
{
255
        va_list ap;
256
257 57280
        va_start(ap, fmt);
258 57280
        (void)macro_def_int(name, func, fmt, ap);
259 57280
        va_end(ap);
260 57280
}
261
262
/**********************************************************************
263
 * Below this point is run inside the testing child-process.
264
 */
265
266
static pthread_mutex_t          macro_mtx;
267
268
static void
269 5455
init_macro(void)
270
{
271
        struct macro *m;
272
273
        /* Dump the extmacros for completeness */
274 65270
        VTAILQ_FOREACH(m, &macro_list, list) {
275 59815
                if (m->val != NULL)
276 97810
                        vtc_log(vltop, 4,
277 48905
                            "extmacro def %s=%s", m->name, m->val);
278
                else
279 10910
                        vtc_log(vltop, 4, "extmacro def %s(...)", m->name);
280 59815
        }
281
282 5455
        PTOK(pthread_mutex_init(&macro_mtx, NULL));
283 5455
}
284
285
void
286 76330
macro_def(struct vtclog *vl, const char *instance, const char *name,
287
    const char *fmt, ...)
288
{
289
        char buf1[256];
290
        struct macro *m;
291
        va_list ap;
292
293 76330
        AN(fmt);
294
295 76330
        if (instance != NULL) {
296 59965
                bprintf(buf1, "%s_%s", instance, name);
297 59965
                name = buf1;
298 59965
        }
299
300 76330
        PTOK(pthread_mutex_lock(&macro_mtx));
301 76330
        va_start(ap, fmt);
302 76330
        m = macro_def_int(name, NULL, fmt, ap);
303 76330
        va_end(ap);
304 76330
        vtc_log(vl, 4, "macro def %s=%s", name, m->val);
305 76330
        PTOK(pthread_mutex_unlock(&macro_mtx));
306 76330
}
307
308
void
309 19605
macro_undef(struct vtclog *vl, const char *instance, const char *name)
310
{
311
        char buf1[256];
312
        struct macro *m;
313
314 19605
        if (instance != NULL) {
315 19604
                bprintf(buf1, "%s_%s", instance, name);
316 19604
                name = buf1;
317 19604
        }
318
319 19605
        PTOK(pthread_mutex_lock(&macro_mtx));
320 320462
        VTAILQ_FOREACH(m, &macro_list, list)
321 318932
                if (!strcmp(name, m->name))
322 18075
                        break;
323 19605
        if (m != NULL) {
324 18075
                if (!vtc_stop)
325 1080
                        vtc_log(vl, 4, "macro undef %s", name);
326 18075
                CHECK_OBJ(m, MACRO_MAGIC);
327 18075
                VTAILQ_REMOVE(&macro_list, m, list);
328 18075
                free(m->name);
329 18075
                free(m->val);
330 18075
                FREE_OBJ(m);
331 18075
        }
332 19605
        PTOK(pthread_mutex_unlock(&macro_mtx));
333 19605
}
334
335
unsigned
336 9940
macro_isdef(const char *instance, const char *name)
337
{
338
        char buf1[256];
339
        struct macro *m;
340
341 9940
        if (instance != NULL) {
342 0
                bprintf(buf1, "%s_%s", instance, name);
343 0
                name = buf1;
344 0
        }
345
346 9940
        PTOK(pthread_mutex_lock(&macro_mtx));
347 182740
        VTAILQ_FOREACH(m, &macro_list, list)
348 172800
                if (!strcmp(name, m->name))
349 0
                        break;
350 9940
        PTOK(pthread_mutex_unlock(&macro_mtx));
351
352 9940
        return (m != NULL);
353
}
354
355
void
356 63891
macro_cat(struct vtclog *vl, struct vsb *vsb, const char *b, const char *e)
357
{
358
        struct macro *m;
359 63891
        char **argv, *retval = NULL;
360 63891
        const char *err = NULL;
361
        int argc;
362
363 63891
        AN(b);
364 63891
        if (e == NULL)
365 33671
                e = strchr(b, '\0');
366 63891
        AN(e);
367
368 63891
        argv = VAV_ParseTxt(b, e, &argc, ARGV_COMMA);
369 63891
        AN(argv);
370
371 63891
        if (*argv != NULL)
372 0
                vtc_fatal(vl, "Macro ${%.*s} parsing failed: %s",
373 0
                    (int)(e - b), b, *argv);
374
375 63891
        assert(argc >= 2);
376
377 63891
        PTOK(pthread_mutex_lock(&macro_mtx));
378 603126
        VTAILQ_FOREACH(m, &macro_list, list) {
379 602691
                CHECK_OBJ_NOTNULL(m, MACRO_MAGIC);
380 602691
                if (!strcmp(argv[1], m->name))
381 63456
                        break;
382 539235
        }
383 63891
        if (m != NULL) {
384 63456
                if (m->func != NULL) {
385 11786
                        AZ(m->val);
386 11786
                        retval = m->func(argc, argv, &err);
387 11786
                        if (err == NULL)
388 11786
                                AN(retval);
389 11786
                } else {
390 51670
                        AN(m->val);
391 51670
                        if (argc == 2)
392 51670
                                REPLACE(retval, m->val);
393
                        else
394 0
                                err = "macro does not take arguments";
395
                }
396 63456
        }
397 63891
        PTOK(pthread_mutex_unlock(&macro_mtx));
398
399 63891
        VAV_Free(argv);
400
401 63891
        if (err != NULL)
402 0
                vtc_fatal(vl, "Macro ${%.*s} failed: %s",
403 0
                    (int)(e - b), b, err);
404
405 63891
        if (retval == NULL) {
406 435
                if (!ign_unknown_macro)
407 0
                        vtc_fatal(vl, "Macro ${%.*s} not found",
408 0
                            (int)(e - b), b);
409 435
                VSB_printf(vsb, "${%.*s}", (int)(e - b), b);
410 435
                return;
411
        }
412
413 63456
        VSB_cat(vsb, retval);
414 63456
        free(retval);
415 63891
}
416
417
struct vsb *
418 7655
macro_expandf(struct vtclog *vl, const char *fmt, ...)
419
{
420
        va_list ap;
421
        struct vsb *vsb1, *vsb2;
422
423 7655
        vsb1 = VSB_new_auto();
424 7655
        AN(vsb1);
425 7655
        va_start(ap, fmt);
426 7655
        VSB_vprintf(vsb1, fmt, ap);
427 7655
        va_end(ap);
428 7655
        AZ(VSB_finish(vsb1));
429 7655
        vsb2 = macro_expand(vl, VSB_data(vsb1));
430 7655
        VSB_destroy(&vsb1);
431 7655
        return (vsb2);
432
}
433
434
struct vsb *
435 28630
macro_expand(struct vtclog *vl, const char *text)
436
{
437
        struct vsb *vsb;
438
        const char *p, *q;
439
440 28630
        vsb = VSB_new_auto();
441 28630
        AN(vsb);
442 58850
        while (*text != '\0') {
443 48465
                p = strstr(text, "${");
444 48465
                if (p == NULL) {
445 18245
                        VSB_cat(vsb, text);
446 18245
                        break;
447
                }
448 30220
                VSB_bcat(vsb, text, p - text);
449 30220
                q = strchr(p, '}');
450 30220
                if (q == NULL) {
451 0
                        VSB_cat(vsb, text);
452 0
                        break;
453
                }
454 30220
                assert(p[0] == '$');
455 30220
                assert(p[1] == '{');
456 30220
                assert(q[0] == '}');
457 30220
                p += 2;
458 30220
                macro_cat(vl, vsb, p, q);
459 30220
                text = q + 1;
460
        }
461 28630
        AZ(VSB_finish(vsb));
462 28630
        return (vsb);
463
}
464
465
/**********************************************************************
466
 * Parse a string
467
 *
468
 * We make a copy of the string and deliberately leak it, so that all
469
 * the cmd functions we call don't have to strdup(3) all over the place.
470
 *
471
 * Static checkers like Coverity may bitch about this, but we don't care.
472
 */
473
474
475
void
476 51981
parse_string(struct vtclog *vl, void *priv, const char *spec)
477
{
478
        char *token_s[MAX_TOKENS], *token_e[MAX_TOKENS];
479
        struct vsb *token_exp;
480
        char *e, *p, *q, *f, *buf;
481
        int nest_brace;
482
        int tn;
483
        unsigned n, m;
484
        const struct cmds *cp;
485
486 51981
        AN(spec);
487 51981
        buf = strdup(spec);
488 51981
        AN(buf);
489 51981
        e = strchr(buf, '\0');
490 51981
        AN(e);
491 611596
        for (p = buf; p < e; p++) {
492 559798
                if (vtc_error || vtc_stop) {
493 362
                        vtc_log(vl, 1, "Aborting execution, test %s",
494 181
                            vtc_error ? "failed" : "ended");
495 181
                        break;
496
                }
497
                /* Start of line */
498 559617
                if (isspace(*p))
499 336470
                        continue;
500 223147
                if (*p == '\n')
501 0
                        continue;
502
503 223147
                if (*p == '#') {
504 488533
                        for (; *p != '\0' && *p != '\n'; p++)
505
                                ;
506 11855
                        if (*p == '\0')
507 0
                                break;
508 11855
                        continue;
509
                }
510
511 211292
                q = strchr(p, '\n');
512 211292
                if (q == NULL)
513 1990
                        q = strchr(p, '\0');
514 211292
                if (q - p > 60)
515 14336
                        vtc_log(vl, 2, "=== %.60s...", p);
516
                else
517 196956
                        vtc_log(vl, 2, "=== %.*s", (int)(q - p), p);
518
519
                /* First content on line, collect tokens */
520 211292
                memset(token_s, 0, sizeof token_s);
521 211292
                memset(token_e, 0, sizeof token_e);
522 211292
                tn = 0;
523 211292
                f = p;
524 1395113
                while (p < e) {
525 1393163
                        assert(tn < MAX_TOKENS);
526 1393163
                        assert(p < e);
527 1393163
                        if (*p == '\n') { /* End on NL */
528 209342
                                break;
529
                        }
530 1183821
                        if (isspace(*p)) { /* Inter-token whitespace */
531 499128
                                p++;
532 499128
                                continue;
533
                        }
534 684693
                        if (*p == '\\' && p[1] == '\n') { /* line-cont */
535 5135
                                p += 2;
536 5135
                                continue;
537
                        }
538 679558
                        if (*p == '"') { /* quotes */
539 63197
                                token_s[tn] = ++p;
540 63197
                                q = p;
541 1494671
                                for (; *p != '\0'; p++) {
542 1494591
                                        assert(p < e);
543 1494591
                                        if (*p == '"')
544 63117
                                                break;
545 1431474
                                        if (*p == '\\') {
546 14850
                                                p += VAV_BackSlash(p, q) - 1;
547 14850
                                                q++;
548 14850
                                        } else {
549 1416624
                                                if (*p == '\n')
550 0
                                                        vtc_fatal(vl,
551
                                "Unterminated quoted string in line: %*.*s",
552 0
                                (int)(p - f), (int)(p - f), f);
553 1416624
                                                assert(*p != '\n');
554 1416624
                                                *q++ = *p;
555
                                        }
556 1431474
                                }
557 63197
                                token_e[tn++] = q;
558 63197
                                p++;
559 679558
                        } else if (*p == '{') { /* Braces */
560 40532
                                nest_brace = 0;
561 40532
                                token_s[tn] = p + 1;
562 6699846
                                for (; p < e; p++) {
563 6699846
                                        if (*p == '{')
564 74387
                                                nest_brace++;
565 6625459
                                        else if (*p == '}') {
566 74387
                                                if (--nest_brace == 0)
567 40532
                                                        break;
568 33855
                                        }
569 6659314
                                }
570 40532
                                assert(*p == '}');
571 40532
                                token_e[tn++] = p++;
572 40532
                        } else { /* other tokens */
573 575829
                                token_s[tn] = p;
574 24185934
                                for (; p < e && !isspace(*p); p++)
575 23610105
                                        continue;
576 575829
                                token_e[tn++] = p;
577
                        }
578
                }
579
580 211292
                assert(p <= e);
581 211292
                assert(tn < MAX_TOKENS);
582 211292
                token_s[tn] = NULL;
583 890868
                for (tn = 0; token_s[tn] != NULL; tn++) {
584 679576
                        AN(token_e[tn]);        /*lint !e771 */
585 679576
                        *token_e[tn] = '\0';    /*lint !e771 */
586 679576
                        if (NULL != strstr(token_s[tn], "${")) {
587 5785
                                token_exp = macro_expand(vl, token_s[tn]);
588 5785
                                if (vtc_error)
589 0
                                        return;
590 5785
                                token_s[tn] = VSB_data(token_exp);
591 5785
                                token_e[tn] = strchr(token_s[tn], '\0');
592 5785
                        }
593 679576
                }
594
595
596
/* SECTION: loop loop
597
 *
598
 * loop NUMBER STRING
599
 *         Process STRING as a specification, NUMBER times.
600
 *
601
 * This works inside all specification strings
602
 */
603
604 211292
                if (!strcmp(token_s[0], "loop")) {
605 232
                        n = strtoul(token_s[1], NULL, 0);
606 19313
                        for (m = 0; m < n && !vtc_error && !vtc_stop; m++) {
607 19081
                                vtc_log(vl, 4, "Loop #%u", m);
608 19081
                                parse_string(vl, priv, token_s[2]);
609 19081
                        }
610 232
                        continue;
611
                }
612
613 211060
                cp = NULL;
614 211060
                if (vl->cmds != NULL) {
615 3228621
                        for (cp = vl->cmds; cp->name != NULL; cp++) {
616 3224103
                                CHECK_OBJ_NOTNULL(cp, CMDS_MAGIC);
617 3224103
                                if (!strcmp(token_s[0], cp->name))
618 149598
                                        break;
619 3074505
                        }
620 154116
                }
621
622 211060
                if (cp == NULL || cp->name == NULL) {
623 61464
                        cp = find_cmd(token_s[0]);
624 61464
                        if (cp != NULL && vl->cmds != NULL &&
625 4517
                            !(cp->flags & CMDS_F_GLOBAL))
626 0
                                cp = NULL;
627 61464
                }
628
629 211058
                if (cp == NULL)
630 0
                        vtc_fatal(vl, "Unknown command: \"%s\"", token_s[0]);
631
632 211058
                AN(cp->name);
633 211058
                AN(cp->cmd);
634 211058
                cp->cmd(token_s, priv, vl);
635 211058
        }
636 51907
}
637
638
/**********************************************************************
639
 * Reset commands (between tests)
640
 */
641
642
static void
643 10910
reset_cmd(const char *name)
644
{
645
        struct cmds *cp;
646
647 10910
        cp = find_cmd(name);
648 10910
        AN(cp);
649 10910
        cp->cmd(NULL, NULL, NULL);
650 10910
        cp->flags |= CMDS_F_SHUT;
651 10910
}
652
653
static void
654 5455
reset_cmds(void)
655
{
656
        struct icmds *cp;
657
658
        // Cleanup is easier if the sockets are closed first.
659 5455
        reset_cmd("client");
660 5455
        reset_cmd("server");
661
662 103645
        VTAILQ_FOREACH(cp, &icmd_list, list) {
663 98190
                CHECK_OBJ_NOTNULL(cp, ICMDS_MAGIC);
664 98190
                CHECK_OBJ_NOTNULL(cp->cmd, CMDS_MAGIC);
665 98190
                if (cp->cmd->flags & CMDS_F_SHUT) {
666 10910
                        cp->cmd->flags &= ~CMDS_F_SHUT;
667 10910
                } else {
668 87280
                        cp->cmd->cmd(NULL, NULL, NULL);
669
                }
670 98190
        }
671 5455
}
672
673
/**********************************************************************
674
 * Execute a file
675
 */
676
677
int
678 5455
fail_out(void)
679
{
680
        unsigned old_err;
681
        static int once = 0;
682
683 5455
        if (once++) {
684 0
                vtc_log(vltop, 1, "failure during reset");
685 0
                return (vtc_error);
686
        }
687 5455
        old_err = vtc_error;
688 5455
        if (!vtc_stop)
689 5340
                vtc_stop = 1;
690 5455
        vtc_log(vltop, 1, "RESETTING after %s", tfn);
691 5455
        reset_cmds();
692 5455
        vtc_error |= old_err;
693
694 5455
        if (vtc_error)
695 15
                vtc_log(vltop, 1, "TEST %s FAILED", tfn);
696
        else
697 5440
                vtc_log(vltop, 1, "TEST %s completed", tfn);
698
699 5455
        if (vtc_stop > 1)
700 115
                return (1);
701 5340
        return (vtc_error);
702 5455
}
703
704
int
705 5455
exec_file(const char *fn, const char *script, const char *tmpdir,
706
    char *logbuf, unsigned loglen)
707
{
708
        FILE *f;
709
        struct vsb *vsb;
710
        const char *p;
711
712 5455
        AN(tmpdir);
713
714 5455
        (void)signal(SIGPIPE, SIG_IGN);
715
716 5455
        VSUB_closefrom(STDERR_FILENO + 1);
717
718 5455
        PTOK(pthread_mutex_init(&vtc_vrnd_mtx, NULL));
719 5455
        VRND_Lock = vtc_vrnd_lock;
720 5455
        VRND_Unlock = vtc_vrnd_unlock;
721 5455
        VRND_SeedAll();
722
723 5455
        tfn = fn;
724 5455
        vtc_loginit(logbuf, loglen);
725 5455
        vltop = vtc_logopen("top");
726 5455
        AN(vltop);
727
728 5455
        vtc_log(vltop, 1, "TEST %s starting", fn);
729
730 5455
        init_cmd_list();
731 5455
        if (init_extensions()) {
732 0
                vtc_error = 2;
733 0
                return (fail_out());
734
        }
735 5455
        init_macro();
736 5455
        init_server();
737 5455
        init_syslog();
738 5455
        init_tunnel();
739
740 5455
        vsb = VSB_new_auto();
741 5455
        AN(vsb);
742 5455
        if (*fn != '/')
743 5400
                macro_cat(vltop, vsb, "pwd", NULL);
744 5455
        p = strrchr(fn, '/');
745 5455
        if (p != NULL) {
746 5410
                VSB_putc(vsb, '/');
747 5410
                VSB_bcat(vsb, fn, p - fn);
748 5410
        }
749 5455
        if (VSB_len(vsb) == 0)
750 0
                VSB_putc(vsb, '/');
751 5455
        AZ(VSB_finish(vsb));
752 5455
        macro_def(vltop, NULL, "testdir", "%s", VSB_data(vsb));
753 5455
        VSB_destroy(&vsb);
754
755
        /* Move into our tmpdir */
756 5455
        AZ(chdir(tmpdir));
757 5455
        macro_def(vltop, NULL, "tmpdir", "%s", tmpdir);
758 5455
        p = strrchr(tmpdir, '/');
759 5455
        AN(p);
760 5455
        p++;
761 5455
        AN(*p);
762 5455
        macro_def(vltop, NULL, "vtcid", "%s", p);
763
764
        /* Drop file to tell what was going on here */
765 5455
        f = fopen("INFO", "w");
766 5455
        AN(f);
767 5455
        fprintf(f, "Test case: %s\n", fn);
768 5455
        AZ(fclose(f));
769
770 5455
        vtc_stop = 0;
771
772 5455
        vtc_thread = pthread_self();
773 5455
        parse_string(vltop, NULL, script);
774 5455
        return (fail_out());
775 5455
}