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