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 570
vtc_hex_to_bin(struct vtclog *vl, const char *arg)
50
{
51
        struct vsb *vsb;
52 570
        unsigned sh = 4;
53 570
        unsigned c, b = 0;
54
55 570
        vsb = VSB_new_auto();
56 570
        AN(vsb);
57 17970
        for (; *arg != '\0'; arg++) {
58 17400
                if (vct_issp(*arg) || *arg == '\n')
59 5568
                        continue;
60 11832
                c = (uint8_t)*arg;
61 11832
                if (c >= '0' && c <= '9')
62 9806
                        b |= (c - 48U) << sh;
63 2026
                else if (c >= 'A' && c <= 'F')
64 64
                        b |= (c - 55U) << sh;
65 1962
                else if (c >= 'a' && c <= 'f')
66 1962
                        b |= (c - 87U) << sh;
67
                else
68 0
                        vtc_fatal(vl,"Illegal hex string");
69 11832
                sh = 4 - sh;
70 11832
                if (sh == 4) {
71 5916
                        VSB_putc(vsb, b);
72 5916
                        b = 0;
73
                }
74
        }
75 570
        if (sh != 4)
76 0
                VSB_putc(vsb, b);
77 570
        AZ(VSB_finish(vsb));
78 570
        return (vsb);
79
}
80
81
void
82 10894
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 10894
        int i, j, retval = -1;
91
        double fl, fr;
92
93 10894
        j = lhs == NULL || rhs == NULL;
94 10894
        if (lhs == NULL)
95 322
                lhs = "<undef>";
96 10894
        if (rhs == NULL)
97 2
                rhs = "<undef>";
98
99 10894
        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 10862
        } else if (!strcmp(cmp, "==")) {
108 10748
                retval = strcmp(lhs, rhs) == 0;
109 114
        } else if (!strcmp(cmp, "!=")) {
110 38
                retval = strcmp(lhs, rhs) != 0;
111 76
        } else if (j) {
112
                // fail inequality comparisons if either side is undef'ed
113 0
                retval = 0;
114
        } else {
115 76
                fl = VNUM(lhs);
116 76
                fr = VNUM(rhs);
117 76
                if (!strcmp(cmp, "<"))
118 14
                        retval = isless(fl, fr);
119 62
                else if (!strcmp(cmp, ">"))
120 16
                        retval = isgreater(fl, fr);
121 46
                else if (!strcmp(cmp, "<="))
122 22
                        retval = islessequal(fl, fr);
123 24
                else if (!strcmp(cmp, ">="))
124 24
                        retval = isgreaterequal(fl, fr);
125
        }
126
127 10894
        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 10894
        else if (retval == 0)
132 0
                vtc_fatal(vl, "EXPECT %s (%s) %s \"%s\" failed",
133
                    olhs, lhs, cmp, rhs);
134
        else
135 10894
                vtc_log(vl, 4, "EXPECT %s (%s) %s \"%s\" match",
136
                    olhs, lhs, cmp, rhs);
137 10894
}
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 1480
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 1480
        r = wait4(pid, &status, 0, &ru);
160 1480
        if (r < 0)
161 0
                vtc_fatal(vl, "wait4 failed on pid %ld: %s",
162 0
                    pid, strerror(errno));
163 1480
        assert(r == pid);
164 5920
        vtc_log(vl, 2, "WAIT4 pid=%ld status=0x%04x (user %.6f sys %.6f)",
165
            pid, status,
166 2960
            ru.ru_utime.tv_sec + 1e-6 * ru.ru_utime.tv_usec,
167 2960
            ru.ru_stime.tv_sec + 1e-6 * ru.ru_stime.tv_usec
168
        );
169
170 2944
        if (WIFEXITED(status) && expect_signal <= 0 &&
171 1464
            WEXITSTATUS(status) == expect_status)
172 1464
                return;
173
174 16
        if (expect_signal < 0)
175 16
                expect_signal = -expect_signal;
176
177 32
        if (WIFSIGNALED(status) && WCOREDUMP(status) <= allow_core &&
178 16
            WTERMSIG(status) == expect_signal)
179 16
                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 1428
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 1428
        (void)VTCP_nonblocking(fd);
197
        while (1) {
198 26254
                memset(fds, 0, sizeof fds);
199 13841
                fds->fd = fd;
200 13841
                fds->events = POLLIN;
201 13841
                i = poll(fds, 1, 10000);
202 13841
                if (i == 0)
203 90
                        continue;
204 13751
                if (fds->revents & POLLIN) {
205 13751
                        i = read(fd, buf, sizeof buf - 1);
206 13751
                        if (i > 0) {
207 12323
                                if (vsb != NULL)
208 6
                                        VSB_bcat(vsb, buf, i);
209 12323
                                buf[i] = '\0';
210 12323
                                vtc_dump(vl, 3, "debug", buf, -2);
211
                        }
212
                }
213 13751
                if (fds->revents & (POLLERR|POLLHUP)) {
214 1428
                        vtc_log(vl, 4, "STDOUT poll 0x%x", fds->revents);
215 1428
                        break;
216
                }
217
        }
218 1428
        return (NULL);
219
}
220