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 357651
vtc_vrnd_lock(void)
62
{
63 357651
        PTOK(pthread_mutex_lock(&vtc_vrnd_mtx));
64 357651
}
65
66
static void
67 357651
vtc_vrnd_unlock(void)
68
{
69 357651
        PTOK(pthread_mutex_unlock(&vtc_vrnd_mtx));
70 357651
}
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 443289
add_cmd(const char *name, cmd_f *cmd, unsigned flags)
89
{
90
        struct icmds *cp;
91
92 443289
        AN(name);
93 443289
        AN(cmd);
94 443289
        ALLOC_OBJ(cp, ICMDS_MAGIC);
95 443289
        AN(cp);
96 443289
        ALLOC_OBJ(cp->cmd, CMDS_MAGIC);
97 443289
        AN(cp->cmd);
98 443289
        cp->cmd->name = strdup(name);
99 443289
        AN(cp->cmd->name);
100 443289
        cp->cmd->cmd = cmd;
101 443289
        cp->cmd->flags = flags;
102 443289
        VTAILQ_INSERT_HEAD(&icmd_list, cp, list);
103 443289
}
104
105
struct cmds *
106 315058
find_cmd(const char *name)
107
{
108
        struct icmds *cp;
109
        char buf[BUFSIZ];
110
111 3186807
        VTAILQ_FOREACH(cp, &icmd_list, list) {
112 3186702
                CHECK_OBJ_NOTNULL(cp, ICMDS_MAGIC);
113 3186702
                CHECK_OBJ_NOTNULL(cp->cmd, CMDS_MAGIC);
114 3186702
                if (!strcmp(name, cp->cmd->name))
115 314953
                        return (cp->cmd);
116 2871749
        }
117
118 105
        bprintf(buf, "libvtest_ext_%s.so", name);
119 105
        void *dlp = dlopen(buf, RTLD_NOW);
120 105
        if (dlp == NULL) {
121 105
                vtc_log(vltop, 4, "Autoload %s failed: %s", buf, dlerror());
122 105
                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 315058
}
134
135
static void
136 23331
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 0
167
        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
                    name, strerror(errno));
172
                exit(2);
173 0
        }
174 0
        closefd(&fd);
175 0
176 0
        ALLOC_OBJ(ep, EXTENSION_MAGIC);
177 0
        AN(ep);
178 0
        ep->name = strdup(name);
179
        AN(ep->name);
180
        VTAILQ_INSERT_HEAD(&extension_list, ep, list);
181
}
182
183
static int
184
init_extensions(void)
185
{
186
        struct extension *ep;
187
188
        VTAILQ_FOREACH(ep, &extension_list, list) {
189
                CHECK_OBJ_NOTNULL(ep, EXTENSION_MAGIC);
190
                void *dlp = dlopen(ep->name, RTLD_NOW);
191
                if (dlp == NULL) {
192
                        vtc_log(vltop, 1, "Cannot dlopen '%s': %s\n",
193
                            ep->name, dlerror());
194
                        return (1);
195
                }
196
        }
197
        return (0);
198 682541
}
199
200
/**********************************************************************
201
 * Macro facility
202
 */
203 9576822
204 8995586
struct macro {
205 101305
        unsigned                magic;
206 682541
#define MACRO_MAGIC             0x803423e3
207 581236
        VTAILQ_ENTRY(macro)     list;
208 581236
        char                    *name;
209 581236
        char                    *val;
210 581236
        macro_f                 *func;
211 581236
};
212 581236
213 682541
static VTAILQ_HEAD(,macro) macro_list = VTAILQ_HEAD_INITIALIZER(macro_list);
214 682541
215 44814
/**********************************************************************/
216 44814
217 44814
static struct macro *
218 637727
macro_def_int(const char *name, macro_f *func, const char *fmt, va_list ap)
219 637727
{
220 637727
        struct macro *m;
221 637727
        char buf[2048];
222
223 682541
        VTAILQ_FOREACH(m, &macro_list, list)
224
                if (!strcmp(name, m->name))
225
                        break;
226
        if (m == NULL) {
227
                ALLOC_OBJ(m, MACRO_MAGIC);
228
                AN(m);
229
                REPLACE(m->name, name);
230
                AN(m->name);
231
                VTAILQ_INSERT_TAIL(&macro_list, m, list);
232
        }
233 244965
        AN(m);
234
        if (func != NULL) {
235
                AZ(fmt);
236
                m->func = func;
237 244965
        } else {
238 244965
                AN(fmt);
239 244965
                vbprintf(buf, fmt, ap);
240 244965
                REPLACE(m->val, buf);
241
                AN(m->val);
242
        }
243
        return (m);
244
}
245
246
247
/**********************************************************************
248
 * This is for defining macros before we fork the child process which
249 23331
 * runs the test-case.
250
 */
251
252
void
253
extmacro_def(const char *name, macro_f *func, const char *fmt, ...)
254 279174
{
255 255843
        va_list ap;
256 418362
257 209181
        va_start(ap, fmt);
258
        (void)macro_def_int(name, func, fmt, ap);
259 46662
        va_end(ap);
260 255843
}
261
262 23331
/**********************************************************************
263 23331
 * Below this point is run inside the testing child-process.
264
 */
265
266 437576
static pthread_mutex_t          macro_mtx;
267
268
static void
269
init_macro(void)
270
{
271
        struct macro *m;
272
273 437576
        /* Dump the extmacros for completeness */
274
        VTAILQ_FOREACH(m, &macro_list, list) {
275 437576
                if (m->val != NULL)
276 255043
                        vtc_log(vltop, 4,
277 255043
                            "extmacro def %s=%s", m->name, m->val);
278 255043
                else
279
                        vtc_log(vltop, 4, "extmacro def %s(...)", m->name);
280 437576
        }
281 437576
282 437576
        PTOK(pthread_mutex_init(&macro_mtx, NULL));
283 437576
}
284 437576
285 437576
void
286 437576
macro_def(struct vtclog *vl, const char *instance, const char *name,
287
    const char *fmt, ...)
288
{
289 82368
        char buf1[256];
290
        struct macro *m;
291
        va_list ap;
292
293
        AN(fmt);
294 82368
295 82368
        if (instance != NULL) {
296 82368
                bprintf(buf1, "%s_%s", instance, name);
297 82368
                name = buf1;
298
        }
299 82368
300 1422669
        PTOK(pthread_mutex_lock(&macro_mtx));
301 1416279
        va_start(ap, fmt);
302 75978
        m = macro_def_int(name, NULL, fmt, ap);
303 82368
        va_end(ap);
304 75978
        vtc_log(vl, 4, "macro def %s=%s", name, m->val);
305 4536
        PTOK(pthread_mutex_unlock(&macro_mtx));
306 75978
}
307 75978
308 75978
void
309 75978
macro_undef(struct vtclog *vl, const char *instance, const char *name)
310 75978
{
311 75978
        char buf1[256];
312 82368
        struct macro *m;
313 82368
314
        if (instance != NULL) {
315
                bprintf(buf1, "%s_%s", instance, name);
316 42544
                name = buf1;
317
        }
318
319
        PTOK(pthread_mutex_lock(&macro_mtx));
320
        VTAILQ_FOREACH(m, &macro_list, list)
321 42544
                if (!strcmp(name, m->name))
322 0
                        break;
323 0
        if (m != NULL) {
324 0
                if (!vtc_stop)
325
                        vtc_log(vl, 4, "macro undef %s", name);
326 42544
                CHECK_OBJ(m, MACRO_MAGIC);
327 824764
                VTAILQ_REMOVE(&macro_list, m, list);
328 782220
                free(m->name);
329 0
                free(m->val);
330 42544
                FREE_OBJ(m);
331
        }
332 42544
        PTOK(pthread_mutex_unlock(&macro_mtx));
333
}
334
335
unsigned
336 283106
macro_isdef(const char *instance, const char *name)
337
{
338
        char buf1[256];
339 283106
        struct macro *m;
340 283106
341
        if (instance != NULL) {
342
                bprintf(buf1, "%s_%s", instance, name);
343 283106
                name = buf1;
344 283106
        }
345 146116
346 283106
        PTOK(pthread_mutex_lock(&macro_mtx));
347
        VTAILQ_FOREACH(m, &macro_list, list)
348 283106
                if (!strcmp(name, m->name))
349 283106
                        break;
350
        PTOK(pthread_mutex_unlock(&macro_mtx));
351 283106
352 0
        return (m != NULL);
353 0
}
354
355 283106
void
356
macro_cat(struct vtclog *vl, struct vsb *vsb, const char *b, const char *e)
357 283106
{
358 2762077
        struct macro *m;
359 2760250
        char **argv, *retval = NULL;
360 2760250
        const char *err = NULL;
361 281279
        int argc;
362 2478971
363 283106
        AN(b);
364 281279
        if (e == NULL)
365 51184
                e = strchr(b, '\0');
366 51184
        AN(e);
367 51184
368 51184
        argv = VAV_ParseTxt(b, e, &argc, ARGV_COMMA);
369 51184
        AN(argv);
370 230095
371 230095
        if (*argv != NULL)
372 230095
                vtc_fatal(vl, "Macro ${%.*s} parsing failed: %s",
373
                    (int)(e - b), b, *argv);
374 0
375
        assert(argc >= 2);
376 281279
377 283106
        PTOK(pthread_mutex_lock(&macro_mtx));
378
        VTAILQ_FOREACH(m, &macro_list, list) {
379 283106
                CHECK_OBJ_NOTNULL(m, MACRO_MAGIC);
380
                if (!strcmp(argv[1], m->name))
381 283106
                        break;
382 0
        }
383 0
        if (m != NULL) {
384
                if (m->func != NULL) {
385 283106
                        AZ(m->val);
386 1827
                        retval = m->func(argc, argv, &err);
387 0
                        if (err == NULL)
388 0
                                AN(retval);
389 1827
                } else {
390 1827
                        AN(m->val);
391
                        if (argc == 2)
392
                                REPLACE(retval, m->val);
393 281279
                        else
394 281279
                                err = "macro does not take arguments";
395 283106
                }
396
        }
397
        PTOK(pthread_mutex_unlock(&macro_mtx));
398 33893
399
        VAV_Free(argv);
400
401
        if (err != NULL)
402
                vtc_fatal(vl, "Macro ${%.*s} failed: %s",
403 33893
                    (int)(e - b), b, err);
404 33893
405 33893
        if (retval == NULL) {
406 33893
                if (!ign_unknown_macro)
407 33893
                        vtc_fatal(vl, "Macro ${%.*s} not found",
408 33893
                            (int)(e - b), b);
409 33893
                VSB_printf(vsb, "${%.*s}", (int)(e - b), b);
410 33893
                return;
411 33893
        }
412
413
        VSB_cat(vsb, retval);
414
        free(retval);
415 212721
}
416
417
struct vsb *
418
macro_expandf(struct vtclog *vl, const char *fmt, ...)
419
{
420 212721
        va_list ap;
421 212721
        struct vsb *vsb1, *vsb2;
422 349702
423 304804
        vsb1 = VSB_new_auto();
424 304804
        AN(vsb1);
425 167823
        va_start(ap, fmt);
426 167823
        VSB_vprintf(vsb1, fmt, ap);
427
        va_end(ap);
428 136981
        AZ(VSB_finish(vsb1));
429 136981
        vsb2 = macro_expand(vl, VSB_data(vsb1));
430 136981
        VSB_destroy(&vsb1);
431 0
        return (vsb2);
432 0
}
433
434 136981
struct vsb *
435 136981
macro_expand(struct vtclog *vl, const char *text)
436 136981
{
437 136981
        struct vsb *vsb;
438 136981
        const char *p, *q;
439 136981
440
        vsb = VSB_new_auto();
441 212721
        AN(vsb);
442 212721
        while (*text != '\0') {
443
                p = strstr(text, "${");
444
                if (p == NULL) {
445
                        VSB_cat(vsb, text);
446
                        break;
447
                }
448
                VSB_bcat(vsb, text, p - text);
449
                q = strchr(p, '}');
450
                if (q == NULL) {
451
                        VSB_cat(vsb, text);
452
                        break;
453
                }
454
                assert(p[0] == '$');
455
                assert(p[1] == '{');
456 231925
                assert(q[0] == '}');
457
                p += 2;
458
                macro_cat(vl, vsb, p, q);
459
                text = q + 1;
460
        }
461
        AZ(VSB_finish(vsb));
462
        return (vsb);
463
}
464
465
/**********************************************************************
466 231925
 * Parse a string
467 231925
 *
468 231925
 * We make a copy of the string and deliberately leak it, so that all
469 231925
 * the cmd functions we call don't have to strdup(3) all over the place.
470 231925
 *
471 2782621
 * Static checkers like Coverity may bitch about this, but we don't care.
472 2551498
 */
473 1604
474 802
475 802
void
476
parse_string(struct vtclog *vl, void *priv, const char *spec)
477
{
478 2550696
        char *token_s[MAX_TOKENS], *token_e[MAX_TOKENS];
479 1540621
        struct vsb *token_exp;
480 1010075
        char *e, *p, *q, *f, *buf;
481 0
        int nest_brace;
482
        int tn;
483 1010075
        unsigned n, m;
484 2132760
        const struct cmds *cp;
485
486 51387
        AN(spec);
487 0
        buf = strdup(spec);
488 51387
        AN(buf);
489
        e = strchr(buf, '\0');
490
        AN(e);
491 958688
        for (p = buf; p < e; p++) {
492 958688
                if (vtc_error || vtc_stop) {
493 8358
                        vtc_log(vl, 1, "Aborting execution, test %s",
494 958688
                            vtc_error ? "failed" : "ended");
495 66844
                        break;
496
                }
497 891844
                /* Start of line */
498
                if (isspace(*p))
499
                        continue;
500 958688
                if (*p == '\n')
501 958688
                        continue;
502 958688
503 958688
                if (*p == '#') {
504 6357456
                        for (; *p != '\0' && *p != '\n'; p++)
505 6349266
                                ;
506 6349266
                        if (*p == '\0')
507 6349266
                                break;
508 950498
                        continue;
509
                }
510 5398768
511 2274722
                q = strchr(p, '\n');
512 2274722
                if (q == NULL)
513
                        q = strchr(p, '\0');
514 3124046
                if (q - p > 60)
515 22554
                        vtc_log(vl, 2, "=== %.60s...", p);
516 22554
                else
517
                        vtc_log(vl, 2, "=== %.*s", (int)(q - p), p);
518 3101492
519 299615
                /* First content on line, collect tokens */
520 299615
                memset(token_s, 0, sizeof token_s);
521 6785951
                memset(token_e, 0, sizeof token_e);
522 6785615
                tn = 0;
523 6785615
                f = p;
524 299279
                while (p < e) {
525 6486336
                        assert(tn < MAX_TOKENS);
526 123239
                        assert(p < e);
527 123239
                        if (*p == '\n') { /* End on NL */
528 123239
                                break;
529 6363097
                        }
530 0
                        if (isspace(*p)) { /* Inter-token whitespace */
531
                                p++;
532 0
                                continue;
533 6363097
                        }
534 6363097
                        if (*p == '\\' && p[1] == '\n') { /* line-cont */
535
                                p += 2;
536 6486336
                                continue;
537 299615
                        }
538 299615
                        if (*p == '"') { /* quotes */
539 3101492
                                token_s[tn] = ++p;
540 178504
                                q = p;
541 178504
                                for (; *p != '\0'; p++) {
542 28858365
                                        assert(p < e);
543 28858365
                                        if (*p == '"')
544 328253
                                                break;
545 28530112
                                        if (*p == '\\') {
546 328253
                                                p += VAV_BackSlash(p, q) - 1;
547 178504
                                                q++;
548 149749
                                        } else {
549 28679861
                                                if (*p == '\n')
550 178504
                                                        vtc_fatal(vl,
551 178504
                                "Unterminated quoted string in line: %*.*s",
552 178504
                                (int)(p - f), (int)(p - f), f);
553 2623373
                                                assert(*p != '\n');
554 102905049
                                                *q++ = *p;
555 100281676
                                        }
556 2623373
                                }
557
                                token_e[tn++] = q;
558
                                p++;
559
                        } else if (*p == '{') { /* Braces */
560 958688
                                nest_brace = 0;
561 958688
                                token_s[tn] = p + 1;
562 958688
                                for (; p < e; p++) {
563 4060240
                                        if (*p == '{')
564 3101552
                                                nest_brace++;
565 3101552
                                        else if (*p == '}') {
566 3101552
                                                if (--nest_brace == 0)
567 25389
                                                        break;
568 25389
                                        }
569 0
                                }
570 25389
                                assert(*p == '}');
571 25389
                                token_e[tn++] = p++;
572 25389
                        } else { /* other tokens */
573 3101552
                                token_s[tn] = p;
574
                                for (; p < e && !isspace(*p); p++)
575
                                        continue;
576
                                token_e[tn++] = p;
577
                        }
578
                }
579
580
                assert(p <= e);
581
                assert(tn < MAX_TOKENS);
582
                token_s[tn] = NULL;
583
                for (tn = 0; token_s[tn] != NULL; tn++) {
584
                        AN(token_e[tn]);        /*lint !e771 */
585
                        *token_e[tn] = '\0';    /*lint !e771 */
586
                        if (NULL != strstr(token_s[tn], "${")) {
587 958688
                                token_exp = macro_expand(vl, token_s[tn]);
588 1226
                                if (vtc_error)
589 89205
                                        return;
590 87979
                                token_s[tn] = VSB_data(token_exp);
591 87979
                                token_e[tn] = strchr(token_s[tn], '\0');
592 87979
                        }
593 87979
                }
594 87979
595 87979
596 1226
/* SECTION: loop loop
597 1226
 *
598
 * loop NUMBER STRING
599
 *         Process STRING as a specification, NUMBER times.
600 957462
 *
601 957462
 * This works inside all specification strings
602 15512624
 */
603 15491969
604 15491969
                if (!strcmp(token_s[0], "loop")) {
605 689279
                        n = strtoul(token_s[1], NULL, 0);
606 14802690
                        for (m = 0; m < n && !vtc_error && !vtc_stop; m++) {
607 709934
                                vtc_log(vl, 4, "Loop #%u", m);
608
                                parse_string(vl, priv, token_s[2]);
609 957462
                        }
610 268207
                        continue;
611 268207
                }
612 20660
613 0
                cp = NULL;
614 268207
                if (vl->cmds != NULL) {
615
                        for (cp = vl->cmds; cp->name != NULL; cp++) {
616 957462
                                CHECK_OBJ_NOTNULL(cp, CMDS_MAGIC);
617 0
                                if (!strcmp(token_s[0], cp->name))
618
                                        break;
619 957462
                        }
620 957462
                }
621 957462
622 957462
                if (cp == NULL || cp->name == NULL) {
623 231601
                        cp = find_cmd(token_s[0]);
624
                        if (cp != NULL && vl->cmds != NULL &&
625
                            !(cp->flags & CMDS_F_GLOBAL))
626
                                cp = NULL;
627
                }
628
629
                if (cp == NULL)
630 46662
                        vtc_fatal(vl, "Unknown command: \"%s\"", token_s[0]);
631
632
                AN(cp->name);
633
                AN(cp->cmd);
634 46662
                cp->cmd(token_s, priv, vl);
635 46662
        }
636 46662
}
637 46662
638 46662
/**********************************************************************
639
 * Reset commands (between tests)
640
 */
641 23331
642
static void
643
reset_cmd(const char *name)
644
{
645
        struct cmds *cp;
646 23331
647 23331
        cp = find_cmd(name);
648
        AN(cp);
649 466620
        cp->cmd(NULL, NULL, NULL);
650 443289
        cp->flags |= CMDS_F_SHUT;
651 443289
}
652 443289
653 46662
static void
654 46662
reset_cmds(void)
655 396627
{
656
        struct icmds *cp;
657 443289
658 23331
        // Cleanup is easier if the sockets are closed first.
659
        reset_cmd("client");
660
        reset_cmd("server");
661
662
        VTAILQ_FOREACH(cp, &icmd_list, list) {
663
                CHECK_OBJ_NOTNULL(cp, ICMDS_MAGIC);
664
                CHECK_OBJ_NOTNULL(cp->cmd, CMDS_MAGIC);
665 23331
                if (cp->cmd->flags & CMDS_F_SHUT) {
666
                        cp->cmd->flags &= ~CMDS_F_SHUT;
667
                } else {
668
                        cp->cmd->cmd(NULL, NULL, NULL);
669
                }
670 23331
        }
671 0
}
672 0
673
/**********************************************************************
674 23331
 * Execute a file
675 23331
 */
676 22826
677 23331
int
678 23331
fail_out(void)
679 23331
{
680
        unsigned old_err;
681 23331
        static int once = 0;
682 63
683
        if (once++) {
684 23268
                vtc_log(vltop, 1, "failure during reset");
685
                return (vtc_error);
686 23331
        }
687 505
        old_err = vtc_error;
688 22826
        if (!vtc_stop)
689 23331
                vtc_stop = 1;
690
        vtc_log(vltop, 1, "RESETTING after %s", tfn);
691
        reset_cmds();
692 23331
        vtc_error |= old_err;
693
694
        if (vtc_error)
695
                vtc_log(vltop, 1, "TEST %s FAILED", tfn);
696
        else
697
                vtc_log(vltop, 1, "TEST %s completed", tfn);
698
699 23331
        if (vtc_stop > 1)
700
                return (1);
701 23331
        return (vtc_error);
702
}
703 23331
704
int
705 23331
exec_file(const char *fn, const char *script, const char *tmpdir,
706 23331
    char *logbuf, unsigned loglen)
707 23331
{
708 23331
        FILE *f;
709
        struct vsb *vsb;
710 23331
        const char *p;
711 23331
712 23331
        AN(tmpdir);
713 23331
714
        (void)signal(SIGPIPE, SIG_IGN);
715 23331
716
        VSUB_closefrom(STDERR_FILENO + 1);
717 23331
718 23331
        PTOK(pthread_mutex_init(&vtc_vrnd_mtx, NULL));
719 23331
        VRND_Lock = vtc_vrnd_lock;
720 23331
        VRND_Unlock = vtc_vrnd_unlock;
721 23331
        VRND_SeedAll();
722
723 23331
        tfn = fn;
724 23331
        vtc_loginit(logbuf, loglen);
725 23331
        vltop = vtc_logopen("top");
726 23100
        AN(vltop);
727 23331
728 23331
        vtc_log(vltop, 1, "TEST %s starting", fn);
729 23142
730 23142
        init_cmd_list();
731 23142
        if (init_extensions()) {
732 23331
                vtc_error = 2;
733 0
                return (fail_out());
734 23331
        }
735 23331
        init_macro();
736 23331
        init_server();
737
        init_syslog();
738
        init_tunnel();
739 23331
740 23331
        vsb = VSB_new_auto();
741 23331
        AN(vsb);
742 23331
        if (*fn != '/')
743 23331
                macro_cat(vltop, vsb, "pwd", NULL);
744 23331
        p = strrchr(fn, '/');
745 23331
        if (p != NULL) {
746
                VSB_putc(vsb, '/');
747
                VSB_bcat(vsb, fn, p - fn);
748 23331
        }
749 23331
        if (VSB_len(vsb) == 0)
750 23331
                VSB_putc(vsb, '/');
751 23331
        AZ(VSB_finish(vsb));
752
        macro_def(vltop, NULL, "testdir", "%s", VSB_data(vsb));
753 23331
        VSB_destroy(&vsb);
754
755 23331
        /* Move into our tmpdir */
756
        AZ(chdir(tmpdir));
757 23331
        macro_def(vltop, NULL, "tmpdir", "%s", tmpdir);
758 23331
        p = strrchr(tmpdir, '/');
759 23331
        AN(p);
760
        p++;
761
        AN(*p);
762
        macro_def(vltop, NULL, "vtcid", "%s", p);
763
764
        /* Drop file to tell what was going on here */
765
        f = fopen("INFO", "w");
766
        AN(f);
767
        fprintf(f, "Test case: %s\n", fn);
768
        AZ(fclose(f));
769
770
        vtc_stop = 0;
771
772
        vtc_thread = pthread_self();
773
        parse_string(vltop, NULL, script);
774
        return (fail_out());
775
}