varnish-cache/bin/varnishtest/vtc_subr.c
1
/*-
2
 * Copyright (c) 2008-2017 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/types.h>
32
#include <errno.h>
33
#include <math.h>
34
#include <poll.h>
35
#include <string.h>
36
#include <stdint.h>
37
#include <unistd.h>
38
#include <sys/wait.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
#include "vtcp.h"
47
48
struct vsb *
49 302
vtc_hex_to_bin(struct vtclog *vl, const char *arg)
50
{
51
        struct vsb *vsb;
52 302
        unsigned sh = 4;
53 302
        unsigned c, b = 0;
54
55 302
        vsb = VSB_new_auto();
56 302
        AN(vsb);
57 10161
        for (; *arg != '\0'; arg++) {
58 9859
                if (vct_issp(*arg) || *arg == '\n')
59 3241
                        continue;
60 6618
                c = (uint8_t)*arg;
61 6618
                if (c >= '0' && c <= '9')
62 5560
                        b |= (c - 48U) << sh;
63 1058
                else if (c >= 'A' && c <= 'F')
64 32
                        b |= (c - 55U) << sh;
65 1026
                else if (c >= 'a' && c <= 'f')
66 1026
                        b |= (c - 87U) << sh;
67
                else
68 0
                        vtc_fatal(vl,"Illegal hex string");
69 6618
                sh = 4 - sh;
70 6618
                if (sh == 4) {
71 3309
                        VSB_putc(vsb, b);
72 3309
                        b = 0;
73
                }
74
        }
75 302
        if (sh != 4)
76 0
                VSB_putc(vsb, b);
77 302
        AZ(VSB_finish(vsb));
78 302
        return (vsb);
79
}
80
81
void
82 5632
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
        const char *error;
89
        int erroroffset;
90 5632
        int i, j, retval = -1;
91
        double fl, fr;
92
93 5632
        j = lhs == NULL || rhs == NULL;
94 5632
        if (lhs == NULL)
95 167
                lhs = "<undef>";
96 5632
        if (rhs == NULL)
97 1
                rhs = "<undef>";
98
99 5632
        if (!strcmp(cmp, "~") || !strcmp(cmp, "!~")) {
100 32
                vre = VRE_compile(rhs, 0, &error, &erroroffset);
101 32
                if (vre == NULL)
102 0
                        vtc_fatal(vl, "REGEXP error: %s (@%d) (%s)",
103
                            error, erroroffset, rhs);
104 32
                i = VRE_exec(vre, lhs, strlen(lhs), 0, 0, NULL, 0, 0);
105 32
                retval = (i >= 0 && *cmp == '~') || (i < 0 && *cmp == '!');
106 32
                VRE_free(&vre);
107 5600
        } else if (!strcmp(cmp, "==")) {
108 5509
                retval = strcmp(lhs, rhs) == 0;
109 91
        } else if (!strcmp(cmp, "!=")) {
110 19
                retval = strcmp(lhs, rhs) != 0;
111 72
        } else if (j) {
112
                // fail inequality comparisons if either side is undef'ed
113 0
                retval = 0;
114
        } else {
115 72
                fl = VNUM(lhs);
116 72
                fr = VNUM(rhs);
117 72
                if (!strcmp(cmp, "<"))
118 7
                        retval = isless(fl, fr);
119 65
                else if (!strcmp(cmp, ">"))
120 8
                        retval = isgreater(fl, fr);
121 57
                else if (!strcmp(cmp, "<="))
122 28
                        retval = islessequal(fl, fr);
123 29
                else if (!strcmp(cmp, ">="))
124 29
                        retval = isgreaterequal(fl, fr);
125
        }
126
127 5632
        if (retval == -1)
128 0
                vtc_fatal(vl,
129
                    "EXPECT %s (%s) %s %s (%s) test not implemented",
130
                    olhs, lhs, cmp, orhs, rhs);
131 5632
        else if (retval == 0)
132 0
                vtc_fatal(vl, "EXPECT %s (%s) %s \"%s\" failed",
133
                    olhs, lhs, cmp, rhs);
134
        else
135 5632
                vtc_log(vl, 4, "EXPECT %s (%s) %s \"%s\" match",
136
                    olhs, lhs, cmp, rhs);
137 5632
}
138
139
/**********************************************************************
140
 * Wait for a subprocess.
141
 *
142
 * if expect_signal > 0, the process must die on that signal.
143
 * if expect_signal < 0, dying on that signal is allowed, but not required.
144
 * if allow_core > 0, a coredump is allowed, but not required.
145
 * otherwise, the process must die on exit(expect_status)
146
 */
147
148
#ifndef WCOREDUMP
149
#  define WCOREDUMP(s) (-1)
150
#endif
151
152
void
153 750
vtc_wait4(struct vtclog *vl, long pid,
154
    int expect_status, int expect_signal, int allow_core)
155
{
156
        int status, r;
157
        struct rusage ru;
158
159 750
        r = wait4(pid, &status, 0, &ru);
160 750
        if (r < 0)
161 0
                vtc_fatal(vl, "wait4 failed on pid %ld: %s",
162 0
                    pid, strerror(errno));
163 750
        assert(r == pid);
164 3000
        vtc_log(vl, 2, "WAIT4 pid=%ld status=0x%04x (user %.6f sys %.6f)",
165
            pid, status,
166 1500
            ru.ru_utime.tv_sec + 1e-6 * ru.ru_utime.tv_usec,
167 1500
            ru.ru_stime.tv_sec + 1e-6 * ru.ru_stime.tv_usec
168
        );
169
170 1489
        if (WIFEXITED(status) && expect_signal <= 0 &&
171 739
            WEXITSTATUS(status) == expect_status)
172 739
                return;
173
174 11
        if (expect_signal < 0)
175 11
                expect_signal = -expect_signal;
176
177 22
        if (WIFSIGNALED(status) && WCOREDUMP(status) <= allow_core &&
178 11
            WTERMSIG(status) == expect_signal)
179 11
                return;
180 0
        vtc_log(vl, 1, "Expected exit: 0x%x signal: %d core: %d",
181
            expect_status, expect_signal, allow_core);
182 0
        vtc_fatal(vl, "Bad exit status: 0x%04x exit 0x%x signal %d core %d",
183
            status,
184
            WEXITSTATUS(status),
185 0
            WIFSIGNALED(status) ? WTERMSIG(status) : 0,
186
            WCOREDUMP(status));
187
}
188
189
void *
190 718
vtc_record(struct vtclog *vl, int fd, struct vsb *vsb)
191
{
192
        char buf[65536];
193
        struct pollfd fds[1];
194
        int i;
195
196 718
        (void)VTCP_nonblocking(fd);
197
        while (1) {
198 13202
                memset(fds, 0, sizeof fds);
199 6960
                fds->fd = fd;
200 6960
                fds->events = POLLIN;
201 6960
                i = poll(fds, 1, 10000);
202 6960
                if (i == 0)
203 51
                        continue;
204 6909
                if (fds->revents & POLLIN) {
205 6909
                        i = read(fd, buf, sizeof buf - 1);
206 6909
                        if (i > 0) {
207 6191
                                if (vsb != NULL)
208 3
                                        VSB_bcat(vsb, buf, i);
209 6191
                                buf[i] = '\0';
210 6191
                                vtc_dump(vl, 3, "debug", buf, -2);
211
                        }
212
                }
213 6909
                if (fds->revents & (POLLERR|POLLHUP)) {
214 718
                        vtc_log(vl, 4, "STDOUT poll 0x%x", fds->revents);
215 718
                        break;
216
                }
217
        }
218 718
        return (NULL);
219
}
220