vinyl-cache/bin/vinyltest/vtest2/src/vtc_subr.c
0
/*-
1
 * Copyright (c) 2008-2017 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 <math.h>
33
#include <stdio.h>
34
#include <stdlib.h>
35
#include <string.h>
36
#include <stdint.h>
37
#include <unistd.h>
38
#include <sys/resource.h>
39
40
#include "vtc.h"
41
42
#include "vct.h"
43
#include "vnum.h"
44
#include "vre.h"
45
46
#include "vapi/vsig.h"
47
48
struct vsb *
49 1805
vtc_hex_to_bin(struct vtclog *vl, const char *arg)
50
{
51
        struct vsb *vsb;
52 1805
        unsigned sh = 4;
53 1805
        unsigned c, b = 0;
54
55 1805
        vsb = VSB_new_auto();
56 1805
        AN(vsb);
57 65475
        for (; *arg != '\0'; arg++) {
58 63670
                if (vct_issp(*arg) || *arg == '\n')
59 20720
                        continue;
60 42950
                c = (uint8_t)*arg;
61 42950
                if (c >= '0' && c <= '9')
62 35895
                        b |= (c - 48U) << sh;
63 7055
                else if (c >= 'A' && c <= 'F')
64 160
                        b |= (c - 55U) << sh;
65 6895
                else if (c >= 'a' && c <= 'f')
66 6895
                        b |= (c - 87U) << sh;
67
                else
68 0
                        vtc_fatal(vl,"Illegal hex string");
69 42950
                sh = 4 - sh;
70 42950
                if (sh == 4) {
71 21475
                        VSB_putc(vsb, b);
72 21475
                        b = 0;
73 21475
                }
74 42950
        }
75 1805
        if (sh != 4)
76 0
                VSB_putc(vsb, b);
77 1805
        AZ(VSB_finish(vsb));
78 1805
        return (vsb);
79
}
80
81
void
82 40466
vtc_expect(struct vtclog *vl,
83
    const char *olhs, const char *lhs,
84
    const char *cmp,
85
    const char *orhs, const char *rhs)
86
{
87
        vre_t *vre;
88
        struct vsb vsb[1];
89
        int error, erroroffset;
90 40466
        int i, j, retval = -1;
91
        double fl, fr;
92
        char errbuf[VRE_ERROR_LEN];
93
94 40466
        j = lhs == NULL || rhs == NULL;
95 40466
        if (lhs == NULL)
96 1365
                lhs = "<undef>";
97 40466
        if (rhs == NULL)
98 5
                rhs = "<undef>";
99
100 40466
        if (!strcmp(cmp, "~") || !strcmp(cmp, "!~")) {
101 350
                vre = VRE_compile(rhs, 0, &error, &erroroffset, 1);
102 350
                if (vre == NULL) {
103 0
                        AN(VSB_init(vsb, errbuf, sizeof errbuf));
104 0
                        AZ(VRE_error(vsb, error));
105 0
                        AZ(VSB_finish(vsb));
106 0
                        VSB_fini(vsb);
107 0
                        vtc_fatal(vl, "REGEXP error: %s (@%d) (%s)",
108 0
                            errbuf, erroroffset, rhs);
109
                }
110 350
                i = VRE_match(vre, lhs, 0, 0, NULL);
111 350
                retval = (i >= 0 && *cmp == '~') || (i < 0 && *cmp == '!');
112 350
                VRE_free(&vre);
113 40466
        } else if (!strcmp(cmp, "==")) {
114 39321
                retval = strcmp(lhs, rhs) == 0;
115 40116
        } else if (!strcmp(cmp, "!=")) {
116 220
                retval = strcmp(lhs, rhs) != 0;
117 795
        } else if (!strcmp(cmp, "-lt")) {
118 10
                retval = strtoul(lhs, NULL, 0) < strtoul(rhs, NULL, 0);
119 575
        } else if (!strcmp(cmp, "-le")) {
120 10
                retval = strtoul(lhs, NULL, 0) <= strtoul(rhs, NULL, 0);
121 565
        } else if (!strcmp(cmp, "-eq")) {
122 45
                retval = strtoul(lhs, NULL, 0) == strtoul(rhs, NULL, 0);
123 555
        } else if (!strcmp(cmp, "-ne")) {
124 0
                retval = strtoul(lhs, NULL, 0) != strtoul(rhs, NULL, 0);
125 510
        } else if (!strcmp(cmp, "-ge")) {
126 10
                retval = strtoul(lhs, NULL, 0) >= strtoul(rhs, NULL, 0);
127 510
        } else if (!strcmp(cmp, "-gt")) {
128 20
                retval = strtoul(lhs, NULL, 0) > strtoul(rhs, NULL, 0);
129 500
        } else if (j) {
130
                // fail inequality comparisons if either side is undef'ed
131 0
                retval = 0;
132 0
        } else {
133 480
                fl = VNUM(lhs);
134 480
                fr = VNUM(rhs);
135 480
                if (!strcmp(cmp, "<"))
136 50
                        retval = isless(fl, fr);
137 430
                else if (!strcmp(cmp, ">"))
138 245
                        retval = isgreater(fl, fr);
139 185
                else if (!strcmp(cmp, "<="))
140 100
                        retval = islessequal(fl, fr);
141 85
                else if (!strcmp(cmp, ">="))
142 85
                        retval = isgreaterequal(fl, fr);
143
        }
144
145 40466
        if (retval == -1)
146 0
                vtc_fatal(vl,
147
                    "EXPECT %s (%s) %s %s (%s) test not implemented",
148 0
                    olhs, lhs, cmp, orhs, rhs);
149 40466
        else if (retval == 0)
150 0
                vtc_fatal(vl, "EXPECT %s (%s) %s \"%s\" failed",
151 0
                    olhs, lhs, cmp, rhs);
152
        else
153 80932
                vtc_log(vl, 4, "EXPECT %s (%s) %s \"%s\" match",
154 40466
                    olhs, lhs, cmp, rhs);
155 40466
}
156
157
/**********************************************************************
158
 * Wait for a subprocess.
159
 *
160
 * if expect_signal > 0, the process must die on that signal.
161
 * if expect_signal < 0, dying on that signal is allowed, but not required.
162
 * if allow_core > 0, a coredump is allowed, but not required.
163
 * otherwise, the process must die on exit(expect_status)
164
 */
165
166
void
167 5390
vtc_wait4(struct vtclog *vl, long pid,
168
    int expect_status, int expect_signal, int allow_core)
169
{
170
        int status, r;
171
        struct rusage ru;
172
173 5390
        r = wait4(pid, &status, 0, &ru);
174 5390
        if (r < 0)
175 0
                vtc_fatal(vl, "wait4 failed on pid %ld: %s",
176 0
                    pid, strerror(errno));
177 5390
        assert(r == pid);
178 10780
        vtc_log(vl, 2, "WAIT4 pid=%ld status=0x%04x (user %.6f sys %.6f)",
179 5390
            pid, status,
180 5390
            ru.ru_utime.tv_sec + 1e-6 * ru.ru_utime.tv_usec,
181 5390
            ru.ru_stime.tv_sec + 1e-6 * ru.ru_stime.tv_usec
182
        );
183
184 5390
        if (WIFEXITED(status) && expect_signal <= 0 &&
185 5315
            WEXITSTATUS(status) == expect_status)
186 5315
                return;
187
188 75
        if (expect_signal < 0)
189 75
                expect_signal = -expect_signal;
190
191 75
        if (WIFSIGNALED(status) && WCOREDUMP(status) <= allow_core &&
192 75
            WTERMSIG(status) == expect_signal)
193 75
                return;
194 0
        vtc_log(vl, 1, "Expected exit: 0x%x signal: %d core: %d",
195 0
            expect_status, expect_signal, allow_core);
196 0
        vtc_fatal(vl, "Bad exit status: 0x%04x exit 0x%x signal %d core %d",
197 0
            status,
198 0
            WEXITSTATUS(status),
199 0
            WIFSIGNALED(status) ? WTERMSIG(status) : 0,
200 0
            WCOREDUMP(status));
201 5390
}
202
203
void *
204 5030
vtc_record(struct vtclog *vl, int fd, struct vsb *vsb)
205
{
206
        char buf[BUFSIZ];
207
        int i;
208
209 60256
        while (1) {
210 60256
                errno = 0;
211 60256
                i = read(fd, buf, sizeof buf - 1);
212 60256
                if (i > 0) {
213 55226
                        if (vsb != NULL)
214 10
                                VSB_bcat(vsb, buf, i);
215 55226
                        buf[i] = '\0';
216 55226
                        vtc_dump(vl, 3, "debug", buf, -2);
217 60256
                } else if (i == 0 && errno == 0) {
218 5030
                        vtc_log(vl, 4, "STDOUT EOF");
219 5030
                        break;
220
                } else {
221 0
                        vtc_log(vl, 4,
222
                            "STDOUT read failed with %d - %s.",
223 0
                            errno, strerror(errno));
224 0
                        break;
225
                }
226
        }
227 5030
        return (NULL);
228
}
229